summaryrefslogtreecommitdiff
path: root/src/parabola_hackers/users.go.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/parabola_hackers/users.go.in')
-rw-r--r--src/parabola_hackers/users.go.in141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/parabola_hackers/users.go.in b/src/parabola_hackers/users.go.in
new file mode 100644
index 0000000..aeda069
--- /dev/null
+++ b/src/parabola_hackers/users.go.in
@@ -0,0 +1,141 @@
+// 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 parabola_hackers
+
+import (
+ "fmt"
+ "os/exec"
+
+ yaml "gopkg.in/yaml.v2"
+ nslcd_proto "lukeshu.com/git/go/libnslcd.git/proto"
+ "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger"
+)
+
+/* 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 nslcd_proto.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)
+ logger.Debug("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 = Set2list(groups)
+ }
+ }
+ }
+ if len(errs) > 0 {
+ err = &yaml.TypeError{Errors: errs}
+ }
+
+ ret.Passwd.PwHash = "x" // look in shadow for the password hash
+ ret.Passwd.GID = -1
+
+ return
+}