summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2017-02-04 17:25:55 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2017-02-04 17:31:02 -0500
commitd6e5cd6b00f598500b59f7d204d5e4c9d1c39573 (patch)
treecc89ea4fa49d1048b086e9c39bf986dc56785eec
parent190b7b234cc69fdcf65aaaa0a763a73dfa58fe45 (diff)
nshd: db_pam: gut; only support pam_sm_chauthtok()
-rw-r--r--go/src/nshd/nslcd_backend/db_pam.go98
1 files changed, 38 insertions, 60 deletions
diff --git a/go/src/nshd/nslcd_backend/db_pam.go b/go/src/nshd/nslcd_backend/db_pam.go
index b704620..55a0641 100644
--- a/go/src/nshd/nslcd_backend/db_pam.go
+++ b/go/src/nshd/nslcd_backend/db_pam.go
@@ -1,4 +1,4 @@
-// Copyright 2015-2016 Luke Shumaker <git.lukeshu@sbcglobal>.
+// Copyright 2015-2017 Luke Shumaker <git.lukeshu@sbcglobal>.
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
@@ -20,11 +20,11 @@ import (
"fmt"
"os"
- "nshd/util"
"nshd/nshd_files"
+ "nshd/util"
- s "golang.org/x/sys/unix"
p "git.lukeshu.com/go/libnslcd/nslcd_proto"
+ s "golang.org/x/sys/unix"
"git.lukeshu.com/go/libgnulinux/crypt"
"git.lukeshu.com/go/libsystemd/sd_daemon"
@@ -42,6 +42,7 @@ func hashPassword(newPassword string, oldHash string) string {
sd_daemon.Log.Err("Could not generate a random string")
str = ""
}
+ // "$6$" is SHA-512; see crypt(3) for others
salt = "$6$" + str + "$"
}
return crypt.Crypt(newPassword, salt)
@@ -55,6 +56,21 @@ func dirExists(path string) bool {
return stat.IsDir()
}
+func (o *Hackers) canChangePassword(user nshd_files.User, oldpassword string) bool {
+ // special hack: if the old password is not
+ // set, but the home directory exists, let the
+ // user set their password
+ if user.Passwd.PwHash == "!" && dirExists(user.Passwd.HomeDir) {
+ return true
+ }
+
+ return checkPassword(oldpassword, user.Passwd.PwHash)
+}
+
+// We don't actually use this for authentication (we let pam_unix.so
+// call NSS getspnam(3), which will call our Shadow_ByName()), but
+// pam_ldap.so calls this as a pre-flight check for
+// pam_sm_chauthtok()/PAM_PwMod().
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)
@@ -63,6 +79,8 @@ func (o *Hackers) PAM_Authentication(cred s.Ucred, req p.Request_PAM_Authenticat
defer close(ret)
if len(req.UserName) == 0 && len(req.Password) == 0 && cred.Uid == 0 {
+ // Being called by root; root can do what root
+ // wants.
ret <- p.PAM_Authentication{
AuthenticationResult: p.NSLCD_PAM_SUCCESS,
UserName: "",
@@ -76,65 +94,31 @@ func (o *Hackers) PAM_Authentication(cred s.Ucred, req p.Request_PAM_Authenticat
if uid < 0 {
return
}
-
user := o.users[uid]
- obj := p.PAM_Authentication{
- AuthenticationResult: p.NSLCD_PAM_AUTH_ERR,
- UserName: "",
- AuthorizationResult: p.NSLCD_PAM_AUTH_ERR,
- AuthorizationError: "",
- }
- if checkPassword(req.Password, user.Passwd.PwHash) {
- obj.AuthenticationResult = p.NSLCD_PAM_SUCCESS
- obj.AuthorizationResult = obj.AuthenticationResult
- obj.UserName = user.Passwd.Name
- }
- ret <- obj
- }()
- return ret
-}
-
-func (o *Hackers) PAM_Authorization(cred s.Ucred, req p.Request_PAM_Authorization) <-chan p.PAM_Authorization {
- o.lock.RLock()
- ret := make(chan p.PAM_Authorization)
- go func() {
- defer o.lock.RUnlock()
- defer close(ret)
- uid := o.name2uid(req.UserName)
- if uid < 0 {
+ if o.canChangePassword(user, req.Password) {
+ // Success
+ ret <- p.PAM_Authentication{
+ AuthenticationResult: p.NSLCD_PAM_SUCCESS,
+ UserName: user.Passwd.Name,
+ AuthorizationResult: p.NSLCD_PAM_SUCCESS,
+ AuthorizationError: "",
+ }
return
- }
- ret <- p.PAM_Authorization{
- Result: p.NSLCD_PAM_SUCCESS,
- Error: "",
- }
- }()
- return ret
-}
-
-const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-func (o *Hackers) PAM_SessionOpen(cred s.Ucred, req p.Request_PAM_SessionOpen) <-chan p.PAM_SessionOpen {
- ret := make(chan p.PAM_SessionOpen)
- go func() {
- defer close(ret)
-
- sessionid, err := util.RandomString(alphabet, 24)
- if err != nil {
+ } else {
+ // Failure
+ ret <- p.PAM_Authentication{
+ AuthenticationResult: p.NSLCD_PAM_AUTH_ERR,
+ UserName: "",
+ AuthorizationResult: p.NSLCD_PAM_AUTH_ERR,
+ AuthorizationError: fmt.Sprintf("password change failed: %s", "Old password did not match"),
+ }
return
}
- ret <- p.PAM_SessionOpen{SessionID: sessionid}
}()
return ret
}
-func (o *Hackers) PAM_SessionClose(cred s.Ucred, req p.Request_PAM_SessionClose) <-chan p.PAM_SessionClose {
- ret := make(chan p.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()
@@ -152,13 +136,7 @@ func (o *Hackers) PAM_PwMod(cred s.Ucred, req p.Request_PAM_PwMod) <-chan p.PAM_
if req.AsRoot == 1 && cred.Uid == 0 {
goto update
}
- // special hack: if the old password is not
- // set, but the home directory exists, let the
- // user set their password
- if user.Passwd.PwHash == "!" && dirExists(user.Passwd.HomeDir) {
- goto update
- }
- if !checkPassword(req.OldPassword, user.Passwd.PwHash) {
+ if !o.canChangePassword(user, req.OldPassword) {
ret <- p.PAM_PwMod{
Result: p.NSLCD_PAM_PERM_DENIED,
Error: fmt.Sprintf("password change failed: %s", "Old password did not match"),