summaryrefslogtreecommitdiff
path: root/go/src/nshd/nshd_files/users.go.in
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2017-02-03 02:44:33 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2017-02-03 03:19:23 -0500
commit374311b891c587bbeb554057e04b55f69073d1af (patch)
tree9903718c323bfe42bba8e3a6a48d5629029b286e /go/src/nshd/nshd_files/users.go.in
parent56689b495618d3e8326b0a6c79f15aaf2b029d9c (diff)
Less magic in the build system; don't hide the go workspace.
Diffstat (limited to 'go/src/nshd/nshd_files/users.go.in')
-rw-r--r--go/src/nshd/nshd_files/users.go.in143
1 files changed, 143 insertions, 0 deletions
diff --git a/go/src/nshd/nshd_files/users.go.in b/go/src/nshd/nshd_files/users.go.in
new file mode 100644
index 0000000..51703fd
--- /dev/null
+++ b/go/src/nshd/nshd_files/users.go.in
@@ -0,0 +1,143 @@
+// Copyright 2015-2016 Luke Shumaker <lukeshu@sbcglobal.net>.
+//
+// This is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This software is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this manual; if not, see
+// <http://www.gnu.org/licenses/>.
+
+package nshd_files
+
+import (
+ "fmt"
+ "os/exec"
+
+ "nshd/util"
+
+ yaml "gopkg.in/yaml.v2"
+ p "git.lukeshu.com/go/libnslcd/nslcd_proto"
+ "git.lukeshu.com/go/libsystemd/sd_daemon"
+)
+
+/* Note that the 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 */
+
+type User struct {
+ Passwd p.Passwd
+ Groups []string
+}
+
+func LoadAllUsers() (users map[int32]User, err error) {
+ contents, err := exec.Command("@bindir@/meta-cat").Output()
+ if err != nil {
+ return
+ }
+
+ var _data interface{}
+ err = yaml.Unmarshal(contents, &_data)
+ if err != nil {
+ return
+ }
+
+ data, isMap := _data.(map[interface{}]interface{})
+ errs := []string{}
+ if !isMap {
+ errs = append(errs, "root node is not a map")
+ } else {
+ users = make(map[int32]User, len(data))
+ for _uid, _user := range data {
+ uid, isInt := _uid.(int)
+ if !isInt {
+ errs = append(errs, fmt.Sprintf("UID is not an int: %T ( %#v )", _uid, _uid))
+ continue
+ }
+ user, _err := parseUser(_user)
+ if _err != nil {
+ errs = append(errs, fmt.Sprintf("Could not parse data for UID %d: %v", uid, _err))
+ continue
+ }
+ user.Passwd.UID = int32(uid)
+ sd_daemon.Log.Debug(fmt.Sprintf("hackers.git: -> User %d(%s) parsed", user.Passwd.UID, user.Passwd.Name))
+ users[user.Passwd.UID] = user
+ }
+ }
+ if len(errs) > 0 {
+ users = nil
+ err = &yaml.TypeError{Errors: errs}
+ }
+ return
+}
+
+func parseUser(_data interface{}) (ret User, err error) {
+ data, isMap := _data.(map[interface{}]interface{})
+ errs := []string{}
+ if !isMap {
+ errs = append(errs, "root node is not a map")
+ } else {
+ if iface, isSet := data["username"]; !isSet {
+ errs = append(errs, "\"username\" is not set")
+ } else if str, isTyp := iface.(string); !isTyp {
+ errs = append(errs, "\"username\" is not a string")
+ } else {
+ ret.Passwd.Name = str
+ ret.Passwd.HomeDir = "/home/" + str
+ }
+
+ if iface, isSet := data["fullname"]; !isSet {
+ errs = append(errs, "\"fullname\" is not set")
+ } else if str, isTyp := iface.(string); !isTyp {
+ errs = append(errs, "\"fullname\" is not a string")
+ } else {
+ ret.Passwd.GECOS = str
+ }
+
+ if iface, isSet := data["shell"]; !isSet {
+ errs = append(errs, "\"shell\" is not set")
+ } else if str, isTyp := iface.(string); !isTyp {
+ errs = append(errs, "\"shell\" is not a string")
+ } else {
+ ret.Passwd.Shell = str
+ }
+
+ if iface, isSet := data["groups"]; !isSet {
+ ret.Groups = make([]string, 0)
+ } else if ary, isTyp := iface.([]interface{}); !isTyp {
+ errs = append(errs, "\"groups\" is not an array")
+ } else {
+ groups := make(map[string]bool, len(ary))
+ e := false
+ for _, iface := range ary {
+ if str, isTyp := iface.(string); !isTyp {
+ errs = append(errs, "\"group\" item is not an array")
+ e = true
+ break
+ } else {
+ groups[str] = true
+ }
+ }
+ if !e {
+ ret.Groups = util.Set2list(groups)
+ }
+ }
+ }
+ if len(errs) > 0 {
+ err = &yaml.TypeError{Errors: errs}
+ }
+
+ ret.Passwd.PwHash = string("x") // look in shadow for the password hash
+ ret.Passwd.GID = -1
+
+ return
+}