diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2017-02-03 02:44:33 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2017-02-03 03:19:23 -0500 |
commit | 374311b891c587bbeb554057e04b55f69073d1af (patch) | |
tree | 9903718c323bfe42bba8e3a6a48d5629029b286e /go/src/nshd/nshd_files/users.go.in | |
parent | 56689b495618d3e8326b0a6c79f15aaf2b029d9c (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.in | 143 |
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 +} |