diff options
Diffstat (limited to 'src/nshd/hackers_git/hackers_parse.go')
-rw-r--r-- | src/nshd/hackers_git/hackers_parse.go | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/nshd/hackers_git/hackers_parse.go b/src/nshd/hackers_git/hackers_parse.go new file mode 100644 index 0000000..d5370eb --- /dev/null +++ b/src/nshd/hackers_git/hackers_parse.go @@ -0,0 +1,157 @@ +// Copyright 2015 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. +// +// The GNU General Public License's references to "object code" and +// "executables" are to be interpreted to also include the output of +// any document formatting or typesetting system, including +// intermediate and printed output. +// +// 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 hackers_git + +import ( + "fmt" + yaml "gopkg.in/yaml.v2" + "io/ioutil" + "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger" + "os" + "path" + "strconv" + "strings" +) + +func filename2uid(filename string) int32 { + basename := path.Base(filename) + parts := strings.SplitN(basename, ".", 2) + if len(parts) != 2 || parts[1] != "yml" { + return -1 + } + uid, err := strconv.ParseInt(parts[0], 10, 32) + if err != nil { + return -1 + } + return int32(uid) +} + +var usersGid = name2gid("users") + +func parse_user_yaml(filename string) (ret user, err error) { + ret.passwd.UID = filename2uid(filename) + + if ret.passwd.UID < 0 { + err = fmt.Errorf("Invalid user filename: %q", filename) + return + } + file, err := os.Open(filename) + if err != nil { + return + } + contents, err := ioutil.ReadAll(file) + 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 { + 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 = "!" + ret.passwd.GID = usersGid + + return +} + +func parse_user_password(filename string) (hash string) { + hash = "!" + file, err := os.Open(filename) + if err != nil { + logger.Debug("hackers.git: %v", err) + return + } + contents, err := ioutil.ReadAll(file) + if err != nil { + logger.Debug("hackers.git: Error while reading: %q: %v", filename, err) + return + } + lines := strings.Split(string(contents), "\n") + switch len(lines) { + case 1: + hash = lines[0] + case 2: + if lines[1] == "" { + hash = lines[0] + } else { + logger.Debug("hackers.git: Invalid password format in file: %q", filename) + } + default: + logger.Debug("hackers.git: Invalid password format in file: %q", filename) + } + return +} |