summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nshd/hackers_git/check_password.go29
-rw-r--r--src/nshd/hackers_git/db_group.go3
-rw-r--r--src/nshd/hackers_git/db_pam.go70
-rw-r--r--src/nshd/hackers_git/db_passwd.go78
-rw-r--r--src/nshd/hackers_git/db_shadow.go82
-rw-r--r--src/nshd/hackers_git/hackers.go9
6 files changed, 241 insertions, 30 deletions
diff --git a/src/nshd/hackers_git/check_password.go b/src/nshd/hackers_git/check_password.go
new file mode 100644
index 0000000..c112641
--- /dev/null
+++ b/src/nshd/hackers_git/check_password.go
@@ -0,0 +1,29 @@
+package hackers_git
+
+import "unsafe"
+
+/*
+#cgo LDFLAGS: -lcrypt
+#define _GNU_SOURCE // for crypt_r(3) in crypt.h
+#include <stdlib.h> // for free(3)
+#include <crypt.h> // for crypt_r(3)
+#include <string.h> // for strcmp(3) and memset(3)
+int check_password(const char *password, const char *hash)
+{
+ int ret;
+ struct crypt_data data;
+ data.initialized = 0;
+ ret = (strcmp(crypt_r(password, hash, &data), hash) == 0);
+ memset(&data, 0, sizeof(data));
+ return ret;
+}
+*/
+import "C"
+
+func check_password(password string, hash string) bool {
+ cpassword := C.CString(password)
+ defer C.free(unsafe.Pointer(cpassword))
+ chash := C.CString(hash)
+ defer C.free(unsafe.Pointer(chash))
+ return C.check_password(cpassword, chash) != 0
+}
diff --git a/src/nshd/hackers_git/db_group.go b/src/nshd/hackers_git/db_group.go
index 5277094..b72dcfe 100644
--- a/src/nshd/hackers_git/db_group.go
+++ b/src/nshd/hackers_git/db_group.go
@@ -1,5 +1,5 @@
package hackers_git
-
+/*
import p "nslcd_proto"
func (o *Hackers) Group_ByName(cred p.Ucred, req p.Request_Group_ByName) p.Group_Enumerator {
@@ -26,3 +26,4 @@ func (o *Hackers) Group_All(cred p.Ucred, req p.Request_Group_All) p.Group_Enume
// TODO
return nil
}
+*/
diff --git a/src/nshd/hackers_git/db_pam.go b/src/nshd/hackers_git/db_pam.go
index a133e88..7c20a56 100644
--- a/src/nshd/hackers_git/db_pam.go
+++ b/src/nshd/hackers_git/db_pam.go
@@ -1,28 +1,72 @@
package hackers_git
-import p "nslcd_proto"
+import (
+ "crypto/rand"
+ "math/big"
+ p "nslcd_proto"
+ "nslcd_proto/util"
+)
func (o *Hackers) PAM_Authentication(cred p.Ucred, req p.Request_PAM_Authentication) p.PAM_Authentication_Enumerator {
o.lock.RLock()
defer o.lock.RUnlock()
- // TODO
- return nil
+
+ uid := o.name2uid(req.UserName)
+ if uid < 0 {
+ return util.PAM_Authentication_Ø{}
+ }
+
+ user := o.users[uid]
+ ret := p.PAM_Authentication{
+ AuthenticationResult: p.NSLCD_PAM_AUTH_ERR,
+ UserName: "",
+ AuthorizationResult: p.NSLCD_PAM_AUTH_ERR,
+ AuthorizationError: "",
+ }
+ if check_password(req.Password, user.passwd.PwHash) {
+ ret.AuthenticationResult = p.NSLCD_PAM_SUCCESS
+ ret.AuthorizationResult = ret.AuthenticationResult
+ ret.UserName = user.passwd.Name
+ }
+
+ return util.New_PAM_Authentication_List([]p.PAM_Authentication{ret})
}
+
func (o *Hackers) PAM_Authorization(cred p.Ucred, req p.Request_PAM_Authorization) p.PAM_Authorization_Enumerator {
o.lock.RLock()
defer o.lock.RUnlock()
- // TODO
- return nil
+
+ uid := o.name2uid(req.UserName)
+ if uid < 0 {
+ return util.PAM_Authorization_Ø{}
+ }
+ ret := p.PAM_Authorization{
+ Result: p.NSLCD_PAM_SUCCESS,
+ Error: "",
+ }
+
+ return util.New_PAM_Authorization_List([]p.PAM_Authorization{ret})
}
+
+const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890"
+var alphabet_len = big.NewInt(int64(len(alphabet)))
+
func (o *Hackers) PAM_SessionOpen(cred p.Ucred, req p.Request_PAM_SessionOpen) p.PAM_SessionOpen_Enumerator {
- o.lock.RLock()
- defer o.lock.RUnlock()
- // TODO
- return nil
+ var sessionid [24]byte
+
+ for i := 0; i < len(sessionid); i++ {
+ bigint, err := rand.Int(rand.Reader, alphabet_len)
+ if err != nil {
+ return util.PAM_SessionOpen_Ø{}
+ }
+ sessionid[i] = alphabet[bigint.Int64()]
+ }
+
+ ret := p.PAM_SessionOpen{SessionID: string(sessionid[:])}
+
+ return util.New_PAM_SessionOpen_List([]p.PAM_SessionOpen{ret})
}
+
func (o *Hackers) PAM_SessionClose(cred p.Ucred, req p.Request_PAM_SessionClose) p.PAM_SessionClose_Enumerator {
- o.lock.RLock()
- defer o.lock.RUnlock()
- // TODO
- return nil
+ return util.PAM_SessionClose_Ø{}
}
diff --git a/src/nshd/hackers_git/db_passwd.go b/src/nshd/hackers_git/db_passwd.go
index f0a0257..e8a6838 100644
--- a/src/nshd/hackers_git/db_passwd.go
+++ b/src/nshd/hackers_git/db_passwd.go
@@ -1,22 +1,82 @@
package hackers_git
-import p "nslcd_proto"
+import (
+ p "nslcd_proto"
+ "nslcd_proto/util"
+)
+
+/* Note that the output password hash value should be one of:
+ <empty> - no password set, allow login without password
+ ! - used to prevent logins
+ x - "valid" encrypted password that does not match any valid password
+ often used to indicate that the password is defined elsewhere
+ other - encrypted password, in crypt(3) format */
func (o *Hackers) Passwd_ByName(cred p.Ucred, req p.Request_Passwd_ByName) p.Passwd_Enumerator {
o.lock.RLock()
defer o.lock.RUnlock()
- // TODO
- return nil
+
+ uid := o.name2uid(string(req))
+ if uid < 0 {
+ return util.Passwd_Ø{}
+ }
+ passwd := o.users[uid].passwd
+ passwd.PwHash = "x" // only put actual hashes in the Shadow DB
+
+ return util.New_Passwd_List([]p.Passwd{passwd})
}
+
func (o *Hackers) Passwd_ByUID(cred p.Ucred, req p.Request_Passwd_ByUID) p.Passwd_Enumerator {
o.lock.RLock()
defer o.lock.RUnlock()
- // TODO
- return nil
+
+ user, found := o.users[int32(req)]
+ if !found {
+ return util.Passwd_Ø{}
+ }
+ passwd := user.passwd
+ passwd.PwHash = "x" // only put actual hashes in the Shadow DB
+
+ return util.New_Passwd_List([]p.Passwd{passwd})
}
-func (o *Hackers) Passwd_All(cred p.Ucred, req p.Request_Passwd_All) p.Passwd_Enumerator {
+
+type allPasswdEnumerator struct {
+ uids []int32
+ backend *Hackers
+ done bool
+}
+
+func (e *allPasswdEnumerator) GetNext() (*p.Passwd, error) {
+ if len(e.uids) > 0 {
+ passwd := e.backend.users[e.uids[0]].passwd
+ passwd.PwHash = "x" // only put actual hashes in the Shadow DB
+ e.uids = e.uids[1:]
+ return &passwd, nil
+ }
+ if len(e.uids) == 0 && !e.done {
+ e.done = true
+ e.backend.lock.RUnlock()
+ }
+ return nil, nil
+}
+
+func (e *allPasswdEnumerator) GenericGetNext() (interface{}, error) {
+ return e.GetNext()
+}
+
+func (o *Hackers) newAllPasswdEnumerator() *allPasswdEnumerator {
o.lock.RLock()
- defer o.lock.RUnlock()
- // TODO
- return nil
+ e := allPasswdEnumerator{
+ uids: make([]int32, len(o.users)),
+ backend: o,
+ done: false,
+ }
+ for uid, _ := range o.users {
+ e.uids = append(e.uids, uid)
+ }
+ return &e
+}
+
+func (o *Hackers) Passwd_All(cred p.Ucred, req p.Request_Passwd_All) p.Passwd_Enumerator {
+ return o.newAllPasswdEnumerator()
}
diff --git a/src/nshd/hackers_git/db_shadow.go b/src/nshd/hackers_git/db_shadow.go
index 199d89e..08384d9 100644
--- a/src/nshd/hackers_git/db_shadow.go
+++ b/src/nshd/hackers_git/db_shadow.go
@@ -1,16 +1,84 @@
package hackers_git
-import p "nslcd_proto"
+import (
+ p "nslcd_proto"
+ "nslcd_proto/util"
+)
func (o *Hackers) Shadow_ByName(cred p.Ucred, req p.Request_Shadow_ByName) p.Shadow_Enumerator {
o.lock.RLock()
defer o.lock.RUnlock()
- // TODO
- return nil
+
+ if cred.Uid != 0 {
+ return util.Shadow_Ø{}
+ }
+ uid := o.name2uid(string(req))
+ passwd := o.users[uid].passwd
+ shadow := p.Shadow{
+ Name: passwd.Name,
+ PwHash: passwd.PwHash,
+ LastChangeDate: -1,
+ MinDays: -1,
+ MaxDays: -1,
+ WarnDays: -1,
+ InactDays: -1,
+ ExpireDate: -1,
+ Flag: -1,
+ }
+
+ return util.New_Shadow_List([]p.Shadow{shadow})
}
-func (o *Hackers) Shadow_All(cred p.Ucred, req p.Request_Shadow_All) p.Shadow_Enumerator {
+
+type allShadowEnumerator struct {
+ uids []int32
+ backend *Hackers
+ done bool
+}
+
+func (e *allShadowEnumerator) GetNext() (*p.Shadow, error) {
+ if len(e.uids) > 0 {
+ passwd := e.backend.users[e.uids[0]].passwd
+ shadow := p.Shadow{
+ Name: passwd.Name,
+ PwHash: passwd.PwHash,
+ LastChangeDate: -1,
+ MinDays: -1,
+ MaxDays: -1,
+ WarnDays: -1,
+ InactDays: -1,
+ ExpireDate: -1,
+ Flag: -1,
+ }
+ e.uids = e.uids[1:]
+ return &shadow, nil
+ }
+ if len(e.uids) == 0 && !e.done {
+ e.done = true
+ e.backend.lock.RUnlock()
+ }
+ return nil, nil
+}
+
+func (e *allShadowEnumerator) GenericGetNext() (interface{}, error) {
+ return e.GetNext()
+}
+
+func (o *Hackers) newAllShadowEnumerator() *allShadowEnumerator {
o.lock.RLock()
- defer o.lock.RUnlock()
- // TODO
- return nil
+ e := allShadowEnumerator{
+ uids: make([]int32, len(o.users)),
+ backend: o,
+ done: false,
+ }
+ for uid, _ := range o.users {
+ e.uids = append(e.uids, uid)
+ }
+ return &e
+}
+
+func (o *Hackers) Shadow_All(cred p.Ucred, req p.Request_Shadow_All) p.Shadow_Enumerator {
+ if cred.Uid != 0 {
+ return util.Shadow_Ø{}
+ }
+ return o.newAllShadowEnumerator()
}
diff --git a/src/nshd/hackers_git/hackers.go b/src/nshd/hackers_git/hackers.go
index 5876613..4a1021a 100644
--- a/src/nshd/hackers_git/hackers.go
+++ b/src/nshd/hackers_git/hackers.go
@@ -51,3 +51,12 @@ func (o *Hackers) Reload() error {
return o.reload()
}
+
+func (o *Hackers) name2uid(name string) int32 {
+ for uid, data := range o.users {
+ if data.passwd.Name == name {
+ return uid
+ }
+ }
+ return -1
+}