diff options
Diffstat (limited to 'src/parabola_hackers/nslcd_backend/db_pam.go')
-rw-r--r-- | src/parabola_hackers/nslcd_backend/db_pam.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/parabola_hackers/nslcd_backend/db_pam.go b/src/parabola_hackers/nslcd_backend/db_pam.go index 303a66c..3374170 100644 --- a/src/parabola_hackers/nslcd_backend/db_pam.go +++ b/src/parabola_hackers/nslcd_backend/db_pam.go @@ -17,17 +17,32 @@ package hackers_nslcd_backend import ( + "fmt" "parabola_hackers" s "syscall" "lukeshu.com/git/go/libgnulinux.git/crypt" p "lukeshu.com/git/go/libnslcd.git/proto" + "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger" ) func checkPassword(password string, hash string) bool { return crypt.Crypt(password, hash) == hash } +func hashPassword(newPassword string, oldHash string) string { + salt := oldHash + if salt == "!" { + str, err := parabola_hackers.RandomString(crypt.SaltAlphabet, 8) + if err != nil { + logger.Err("Could not generate a random string") + str = "" + } + salt = "$6$" + str + "$" + } + return crypt.Crypt(newPassword, salt) +} + func (o *Hackers) PAM_Authentication(cred s.Ucred, req p.Request_PAM_Authentication) <-chan p.PAM_Authentication { o.lock.RLock() ret := make(chan p.PAM_Authentication) @@ -97,3 +112,56 @@ func (o *Hackers) PAM_SessionClose(cred s.Ucred, req p.Request_PAM_SessionClose) go close(ret) return ret } + +func (o *Hackers) PAM_PwMod(cred s.Ucred, req p.Request_PAM_PwMod) <-chan p.PAM_PwMod { + ret := make(chan p.PAM_PwMod) + o.lock.Lock() + go func() { + defer close(ret) + defer o.lock.Unlock() + + uid := o.name2uid(req.UserName) + if uid < 0 { + return + } + user := o.users[uid] + + // Check the OldPassword + if req.AsRoot == 1 { + if !checkPassword(req.OldPassword, user.Passwd.PwHash) { + ret <- p.PAM_PwMod{ + Result: p.NSLCD_PAM_PERM_DENIED, + Error: fmt.Sprintf("password change failed: %s", "Old password did not match"), + } + return + } + } + + // Update the PwHash in memory + user.Passwd.PwHash = hashPassword(req.NewPassword, user.Passwd.PwHash) + if user.Passwd.PwHash == "" { + logger.Err("Password hashing failed") + return + } + + // Update the PwHash on disk + passwords := make(map[string]string, len(o.users)) + for _, ouser := range o.users { + passwords[ouser.Passwd.Name] = ouser.Passwd.PwHash + } + passwords[user.Passwd.Name] = user.Passwd.PwHash + err := parabola_hackers.SaveAllPasswords(passwords) + if err != nil { + logger.Err("Writing passwords to disk: %v", err) + return + } + + // Ok, we're done, commit the changes + o.users[uid] = user + ret <- p.PAM_PwMod{ + Result: p.NSLCD_PAM_SUCCESS, + Error: "", + } + }() + return ret +} |