Beispiel #1
0
func lookupPasswd(uid int, username string, lookupByName bool) (*user.User, error) {
	f, err := os.Open(UserDatabase)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	exist := false
	p := &PasswdRecord{}
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		fields := strings.SplitN(scanner.Text(), ":", 7)
		if strings.HasPrefix(fields[0], "#") {
			continue
		}
		if len(fields) < 7 {
			return nil, InvalidUserDatabaseError
		}
		p = &PasswdRecord{fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6]}
		if lookupByName {
			if username == p.Name {
				exist = true
				break
			}
		} else {
			if strconv.Itoa(uid) == p.Uid {
				exist = true
				break
			}
		}
	}
	if !exist {
		if lookupByName {
			return nil, user.UnknownUserError(username)
		} else {
			return nil, user.UnknownUserIdError(uid)
		}
	}

	u := &user.User{
		Username: p.Name,
		Uid:      p.Uid,
		Gid:      p.Gid,
		Name:     p.Gecos,
		HomeDir:  p.Directory,
	}
	// The gecos field isn't quite standardized.  Some docs
	// say: "It is expected to be a comma separated list of
	// personal data where the first item is the full name of the
	// user."
	if i := strings.Index(u.Name, ","); i >= 0 {
		u.Name = u.Name[:i]
	}
	return u, nil
}
Beispiel #2
0
func Lookup(username string, users []*User) (*User, error) {
	if users == nil {
		var err error
		users, err = AllUsers()
		if err != nil {
			return nil, err
		}
	}
	for _, user := range users {
		if user.Username == username {
			return user, nil
		}
	}
	return nil, osuser.UnknownUserError(username)
}
Beispiel #3
0
// EtcPasswdLookup looks up a user by username. If the user cannot be
// found, the returned error is of type user.UnknownUserError.  This
// differs from os/user.Lookup by parsing /etc/password directly, so
// it doesn't need cgo support.
func EtcPasswdLookup(username string) (*user.User, error) {
	usernamePrefix := []byte(username)
	usernamePrefix = append(usernamePrefix, ':')
	etcPasswd, err := ioutil.ReadFile("/etc/passwd")
	if err != nil {
		return nil, err
	}

	passwdReader := bufio.NewReader(bytes.NewReader(etcPasswd))
	for {
		l, isPrefix, err := passwdReader.ReadLine()
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		if isPrefix {
			return nil, fmt.Errorf("passwd: line too long: '%s'", l)
		}
		if !bytes.HasPrefix(l, usernamePrefix) {
			continue
		}
		fields := strings.Split(string(l), ":")
		if len(fields) != 7 {
			log.Printf("/etc/passwd: wrong num fields (%d): %s\n",
				len(fields), string(l))
			continue
		}

		// The pw_gecos field isn't standardized.  Some docs
		// say: "It is expected to be a comma separated list
		// of personal data where the first item is the full
		// name of the user."
		fullName := strings.SplitN(fields[fieldGecos], ",", 2)[0]

		return &user.User{
			Uid:      fields[fieldUid],
			Gid:      fields[fieldGid],
			Username: fields[fieldUsername],
			Name:     fullName,
			HomeDir:  fields[fieldHomeDir],
		}, nil
	}

	return nil, user.UnknownUserError(username)
}
Beispiel #4
0
func lookupDscl(uid int, username string, lookupByName bool) (*user.User, error) {
	dscl := exec.Command("/usr/bin/dscl", ".", "-list", "users", "uid")

	dsclbuf, err := dscl.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err = dscl.Start(); err != nil {
		return nil, err
	}

	name := ""
	id := ""

	exist := false
	scanner := bufio.NewScanner(dsclbuf)
	for scanner.Scan() {
		scannerWord := bufio.NewScanner(bytes.NewReader(scanner.Bytes()))
		scannerWord.Split(bufio.ScanWords)
		scannerWord.Scan()
		name = scannerWord.Text()
		scannerWord.Scan()
		id = scannerWord.Text()

		if lookupByName {
			if username != name && "_"+username != name {
				continue
			}
		} else {
			if strconv.Itoa(uid) != id {
				continue
			}
		}

		dscl = exec.Command("/usr/bin/dscl", "-plist", ".", "-read", "users/"+name)
		dsclbuf, err = dscl.StdoutPipe()
		if err != nil {
			return nil, err
		}
		if err = dscl.Start(); err != nil {
			return nil, err
		}

		var uplist userplist
		buf, err := ioutil.ReadAll(dsclbuf)
		if err != nil {
			return nil, err
		}
		_, err = plist.Unmarshal(buf, &uplist)
		if err != nil {
			return nil, err
		}
		exist = true

		if name[0] == '_' {
			name = name[1:]
		}

		u := &user.User{
			Username: name,
			Uid:      id,
			Gid:      uplist.Gid[0],
			Name:     uplist.Name[0],
			HomeDir:  uplist.HomeDir[0],
		}
		return u, nil
	}
	if !exist {
		if lookupByName {
			return nil, user.UnknownUserError(username)
		} else {
			return nil, user.UnknownUserIdError(uid)
		}
	}
	return nil, InvalidUserDatabaseError
}