summaryrefslogtreecommitdiff
path: root/pkg/chrootuser
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/chrootuser')
-rw-r--r--pkg/chrootuser/user.go108
-rw-r--r--pkg/chrootuser/user_basic.go27
-rw-r--r--pkg/chrootuser/user_linux.go293
3 files changed, 0 insertions, 428 deletions
diff --git a/pkg/chrootuser/user.go b/pkg/chrootuser/user.go
deleted file mode 100644
index c83dcc230..000000000
--- a/pkg/chrootuser/user.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package chrootuser
-
-import (
- "os/user"
- "strconv"
- "strings"
-
- "github.com/pkg/errors"
-)
-
-var (
- // ErrNoSuchUser indicates that the user provided by the caller does not
- // exist in /etc/passws
- ErrNoSuchUser = errors.New("user does not exist in /etc/passwd")
-)
-
-// GetUser will return the uid, gid of the user specified in the userspec
-// it will use the /etc/passwd and /etc/group files inside of the rootdir
-// to return this information.
-// userspec format [user | user:group | uid | uid:gid | user:gid | uid:group ]
-func GetUser(rootdir, userspec string) (uint32, uint32, error) {
- var gid64 uint64
- var gerr error = user.UnknownGroupError("error looking up group")
-
- spec := strings.SplitN(userspec, ":", 2)
- userspec = spec[0]
- groupspec := ""
- if userspec == "" {
- return 0, 0, nil
- }
- if len(spec) > 1 {
- groupspec = spec[1]
- }
-
- uid64, uerr := strconv.ParseUint(userspec, 10, 32)
- if uerr == nil && groupspec == "" {
- // We parsed the user name as a number, and there's no group
- // component, so try to look up the primary GID of the user who
- // has this UID.
- var name string
- name, gid64, gerr = lookupGroupForUIDInContainer(rootdir, uid64)
- if gerr == nil {
- userspec = name
- } else {
- // Leave userspec alone, but swallow the error and just
- // use GID 0.
- gid64 = 0
- gerr = nil
- }
- }
- if uerr != nil {
- // The user ID couldn't be parsed as a number, so try to look
- // up the user's UID and primary GID.
- uid64, gid64, uerr = lookupUserInContainer(rootdir, userspec)
- gerr = uerr
- }
-
- if groupspec != "" {
- // We have a group name or number, so parse it.
- gid64, gerr = strconv.ParseUint(groupspec, 10, 32)
- if gerr != nil {
- // The group couldn't be parsed as a number, so look up
- // the group's GID.
- gid64, gerr = lookupGroupInContainer(rootdir, groupspec)
- }
- }
-
- if uerr == nil && gerr == nil {
- return uint32(uid64), uint32(gid64), nil
- }
-
- err := errors.Wrapf(uerr, "error determining run uid")
- if uerr == nil {
- err = errors.Wrapf(gerr, "error determining run gid")
- }
- return 0, 0, err
-}
-
-// GetGroup returns the gid by looking it up in the /etc/group file
-// groupspec format [ group | gid ]
-func GetGroup(rootdir, groupspec string) (uint32, error) {
- gid64, gerr := strconv.ParseUint(groupspec, 10, 32)
- if gerr != nil {
- // The group couldn't be parsed as a number, so look up
- // the group's GID.
- gid64, gerr = lookupGroupInContainer(rootdir, groupspec)
- }
- if gerr != nil {
- return 0, errors.Wrapf(gerr, "error looking up group for gid %q", groupspec)
- }
- return uint32(gid64), nil
-}
-
-// GetAdditionalGroupsForUser returns a list of gids that userid is associated with
-func GetAdditionalGroupsForUser(rootdir string, userid uint64) ([]uint32, error) {
- gids, err := lookupAdditionalGroupsForUIDInContainer(rootdir, userid)
- if err != nil {
- return nil, errors.Wrapf(err, "error looking up supplemental groups for uid %d", userid)
- }
- return gids, nil
-}
-
-// LookupUIDInContainer returns username and gid associated with a UID in a container
-// it will use the /etc/passwd files inside of the rootdir
-// to return this information.
-func LookupUIDInContainer(rootdir string, uid uint64) (user string, gid uint64, err error) {
- return lookupUIDInContainer(rootdir, uid)
-}
diff --git a/pkg/chrootuser/user_basic.go b/pkg/chrootuser/user_basic.go
deleted file mode 100644
index 79b0b24b5..000000000
--- a/pkg/chrootuser/user_basic.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// +build !linux
-
-package chrootuser
-
-import (
- "github.com/pkg/errors"
-)
-
-func lookupUserInContainer(rootdir, username string) (uint64, uint64, error) {
- return 0, 0, errors.New("user lookup not supported")
-}
-
-func lookupGroupInContainer(rootdir, groupname string) (uint64, error) {
- return 0, errors.New("group lookup not supported")
-}
-
-func lookupGroupForUIDInContainer(rootdir string, userid uint64) (string, uint64, error) {
- return "", 0, errors.New("primary group lookup by uid not supported")
-}
-
-func lookupAdditionalGroupsForUIDInContainer(rootdir string, userid uint64) (gid []uint32, err error) {
- return nil, errors.New("supplemental groups list lookup by uid not supported")
-}
-
-func lookupUIDInContainer(rootdir string, uid uint64) (string, uint64, error) {
- return "", 0, errors.New("UID lookup not supported")
-}
diff --git a/pkg/chrootuser/user_linux.go b/pkg/chrootuser/user_linux.go
deleted file mode 100644
index 583eca569..000000000
--- a/pkg/chrootuser/user_linux.go
+++ /dev/null
@@ -1,293 +0,0 @@
-// +build linux
-
-package chrootuser
-
-import (
- "bufio"
- "flag"
- "fmt"
- "io"
- "os"
- "os/exec"
- "os/user"
- "strconv"
- "strings"
- "sync"
-
- "github.com/containers/storage/pkg/reexec"
- "github.com/sirupsen/logrus"
- "golang.org/x/sys/unix"
-)
-
-const (
- openChrootedCommand = "chrootuser-open"
-)
-
-func init() {
- reexec.Register(openChrootedCommand, openChrootedFileMain)
-}
-
-func openChrootedFileMain() {
- status := 0
- flag.Parse()
- if len(flag.Args()) < 1 {
- os.Exit(1)
- }
- // Our first parameter is the directory to chroot into.
- if err := unix.Chdir(flag.Arg(0)); err != nil {
- fmt.Fprintf(os.Stderr, "chdir(): %v", err)
- os.Exit(1)
- }
- if err := unix.Chroot(flag.Arg(0)); err != nil {
- fmt.Fprintf(os.Stderr, "chroot(): %v", err)
- os.Exit(1)
- }
- // Anything else is a file we want to dump out.
- for _, filename := range flag.Args()[1:] {
- f, err := os.Open(filename)
- if err != nil {
- fmt.Fprintf(os.Stderr, "open(%q): %v", filename, err)
- status = 1
- continue
- }
- _, err = io.Copy(os.Stdout, f)
- if err != nil {
- fmt.Fprintf(os.Stderr, "read(%q): %v", filename, err)
- }
- f.Close()
- }
- os.Exit(status)
-}
-
-func openChrootedFile(rootdir, filename string) (*exec.Cmd, io.ReadCloser, error) {
- // The child process expects a chroot and one or more filenames that
- // will be consulted relative to the chroot directory and concatenated
- // to its stdout. Start it up.
- cmd := reexec.Command(openChrootedCommand, rootdir, filename)
- stdout, err := cmd.StdoutPipe()
- if err != nil {
- return nil, nil, err
- }
- err = cmd.Start()
- if err != nil {
- return nil, nil, err
- }
- // Hand back the child's stdout for reading, and the child to reap.
- return cmd, stdout, nil
-}
-
-var (
- lookupUser, lookupGroup sync.Mutex
-)
-
-type lookupPasswdEntry struct {
- name string
- uid uint64
- gid uint64
-}
-type lookupGroupEntry struct {
- name string
- gid uint64
- user string
-}
-
-func readWholeLine(rc *bufio.Reader) ([]byte, error) {
- line, isPrefix, err := rc.ReadLine()
- if err != nil {
- return nil, err
- }
- for isPrefix {
- // We didn't get a whole line. Keep reading chunks until we find an end of line, and discard them.
- for isPrefix {
- logrus.Debugf("discarding partial line %q", string(line))
- _, isPrefix, err = rc.ReadLine()
- if err != nil {
- return nil, err
- }
- }
- // That last read was the end of a line, so now we try to read the (beginning of?) the next line.
- line, isPrefix, err = rc.ReadLine()
- if err != nil {
- return nil, err
- }
- }
- return line, nil
-}
-
-func parseNextPasswd(rc *bufio.Reader) *lookupPasswdEntry {
- line, err := readWholeLine(rc)
- if err != nil {
- return nil
- }
- fields := strings.Split(string(line), ":")
- if len(fields) < 7 {
- return nil
- }
- uid, err := strconv.ParseUint(fields[2], 10, 32)
- if err != nil {
- return nil
- }
- gid, err := strconv.ParseUint(fields[3], 10, 32)
- if err != nil {
- return nil
- }
- return &lookupPasswdEntry{
- name: fields[0],
- uid: uid,
- gid: gid,
- }
-}
-
-func parseNextGroup(rc *bufio.Reader) *lookupGroupEntry {
- line, err := readWholeLine(rc)
- if err != nil {
- return nil
- }
- fields := strings.Split(string(line), ":")
- if len(fields) < 4 {
- return nil
- }
- gid, err := strconv.ParseUint(fields[2], 10, 32)
- if err != nil {
- return nil
- }
- return &lookupGroupEntry{
- name: fields[0],
- gid: gid,
- user: fields[3],
- }
-}
-
-func lookupUserInContainer(rootdir, username string) (uid uint64, gid uint64, err error) {
- cmd, f, err := openChrootedFile(rootdir, "/etc/passwd")
- if err != nil {
- return 0, 0, err
- }
- defer func() {
- _ = cmd.Wait()
- }()
- rc := bufio.NewReader(f)
- defer f.Close()
-
- lookupUser.Lock()
- defer lookupUser.Unlock()
-
- pwd := parseNextPasswd(rc)
- for pwd != nil {
- if pwd.name != username {
- pwd = parseNextPasswd(rc)
- continue
- }
- return pwd.uid, pwd.gid, nil
- }
-
- return 0, 0, user.UnknownUserError(fmt.Sprintf("error looking up user %q", username))
-}
-
-func lookupGroupForUIDInContainer(rootdir string, userid uint64) (username string, gid uint64, err error) {
- cmd, f, err := openChrootedFile(rootdir, "/etc/passwd")
- if err != nil {
- return "", 0, err
- }
- defer func() {
- _ = cmd.Wait()
- }()
- rc := bufio.NewReader(f)
- defer f.Close()
-
- lookupUser.Lock()
- defer lookupUser.Unlock()
-
- pwd := parseNextPasswd(rc)
- for pwd != nil {
- if pwd.uid != userid {
- pwd = parseNextPasswd(rc)
- continue
- }
- return pwd.name, pwd.gid, nil
- }
-
- return "", 0, ErrNoSuchUser
-}
-
-func lookupAdditionalGroupsForUIDInContainer(rootdir string, userid uint64) (gid []uint32, err error) {
- // Get the username associated with userid
- username, _, err := lookupGroupForUIDInContainer(rootdir, userid)
- if err != nil {
- return nil, err
- }
-
- cmd, f, err := openChrootedFile(rootdir, "/etc/group")
- if err != nil {
- return nil, err
- }
- defer func() {
- _ = cmd.Wait()
- }()
- rc := bufio.NewReader(f)
- defer f.Close()
-
- lookupGroup.Lock()
- defer lookupGroup.Unlock()
-
- grp := parseNextGroup(rc)
- for grp != nil {
- if strings.Contains(grp.user, username) {
- gid = append(gid, uint32(grp.gid))
- }
- grp = parseNextGroup(rc)
- }
- return gid, nil
-}
-
-func lookupGroupInContainer(rootdir, groupname string) (gid uint64, err error) {
- cmd, f, err := openChrootedFile(rootdir, "/etc/group")
- if err != nil {
- return 0, err
- }
- defer func() {
- _ = cmd.Wait()
- }()
- rc := bufio.NewReader(f)
- defer f.Close()
-
- lookupGroup.Lock()
- defer lookupGroup.Unlock()
-
- grp := parseNextGroup(rc)
- for grp != nil {
- if grp.name != groupname {
- grp = parseNextGroup(rc)
- continue
- }
- return grp.gid, nil
- }
-
- return 0, user.UnknownGroupError(fmt.Sprintf("error looking up group %q", groupname))
-}
-
-func lookupUIDInContainer(rootdir string, uid uint64) (string, uint64, error) {
- cmd, f, err := openChrootedFile(rootdir, "/etc/passwd")
- if err != nil {
- return "", 0, err
- }
- defer func() {
- _ = cmd.Wait()
- }()
- rc := bufio.NewReader(f)
- defer f.Close()
-
- lookupUser.Lock()
- defer lookupUser.Unlock()
-
- pwd := parseNextPasswd(rc)
- for pwd != nil {
- if pwd.uid != uid {
- pwd = parseNextPasswd(rc)
- continue
- }
- return pwd.name, pwd.gid, nil
- }
-
- return "", 0, user.UnknownUserError(fmt.Sprintf("error looking up uid %q", uid))
-}