diff options
Diffstat (limited to 'src/parabola_hackers/nslcd_backend')
-rw-r--r-- | src/parabola_hackers/nslcd_backend/db_pam.go | 68 | ||||
-rw-r--r-- | src/parabola_hackers/nslcd_backend/hackers.go | 13 |
2 files changed, 77 insertions, 4 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 +} diff --git a/src/parabola_hackers/nslcd_backend/hackers.go b/src/parabola_hackers/nslcd_backend/hackers.go index f7d56e3..bb03862 100644 --- a/src/parabola_hackers/nslcd_backend/hackers.go +++ b/src/parabola_hackers/nslcd_backend/hackers.go @@ -82,14 +82,19 @@ func (o *Hackers) Reload() error { return err } + passwords, err := parabola_hackers.LoadAllPasswords() + if err != nil { + return err + } + o.groups = make(map[string]map[string]bool) for uid, user := range o.users { user.Passwd.GID = usersGid - var _err error - user.Passwd.PwHash, _err = parabola_hackers.LoadUserPassword(user.Passwd.HomeDir + "/.password") - if _err != nil { - logger.Debug("hackers.git: Ignoring password: %v", _err) + hash, hasHash := passwords[user.Passwd.Name] + if !hasHash { + hash = "!" } + user.Passwd.PwHash = hash o.users[uid] = user for _, groupname := range user.Groups { o.add_user_to_group(user.Passwd.Name, groupname) |