...

Source file src/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go

Documentation: github.com/opencontainers/runc/libcontainer/user

     1  //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
     2  // +build darwin dragonfly freebsd linux netbsd openbsd solaris
     3  
     4  package user
     5  
     6  import (
     7  	"io"
     8  	"os"
     9  	"strconv"
    10  
    11  	"golang.org/x/sys/unix"
    12  )
    13  
    14  // Unix-specific path to the passwd and group formatted files.
    15  const (
    16  	unixPasswdPath = "/etc/passwd"
    17  	unixGroupPath  = "/etc/group"
    18  )
    19  
    20  // LookupUser looks up a user by their username in /etc/passwd. If the user
    21  // cannot be found (or there is no /etc/passwd file on the filesystem), then
    22  // LookupUser returns an error.
    23  func LookupUser(username string) (User, error) {
    24  	return lookupUserFunc(func(u User) bool {
    25  		return u.Name == username
    26  	})
    27  }
    28  
    29  // LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
    30  // be found (or there is no /etc/passwd file on the filesystem), then LookupId
    31  // returns an error.
    32  func LookupUid(uid int) (User, error) {
    33  	return lookupUserFunc(func(u User) bool {
    34  		return u.Uid == uid
    35  	})
    36  }
    37  
    38  func lookupUserFunc(filter func(u User) bool) (User, error) {
    39  	// Get operating system-specific passwd reader-closer.
    40  	passwd, err := GetPasswd()
    41  	if err != nil {
    42  		return User{}, err
    43  	}
    44  	defer passwd.Close()
    45  
    46  	// Get the users.
    47  	users, err := ParsePasswdFilter(passwd, filter)
    48  	if err != nil {
    49  		return User{}, err
    50  	}
    51  
    52  	// No user entries found.
    53  	if len(users) == 0 {
    54  		return User{}, ErrNoPasswdEntries
    55  	}
    56  
    57  	// Assume the first entry is the "correct" one.
    58  	return users[0], nil
    59  }
    60  
    61  // LookupGroup looks up a group by its name in /etc/group. If the group cannot
    62  // be found (or there is no /etc/group file on the filesystem), then LookupGroup
    63  // returns an error.
    64  func LookupGroup(groupname string) (Group, error) {
    65  	return lookupGroupFunc(func(g Group) bool {
    66  		return g.Name == groupname
    67  	})
    68  }
    69  
    70  // LookupGid looks up a group by its group id in /etc/group. If the group cannot
    71  // be found (or there is no /etc/group file on the filesystem), then LookupGid
    72  // returns an error.
    73  func LookupGid(gid int) (Group, error) {
    74  	return lookupGroupFunc(func(g Group) bool {
    75  		return g.Gid == gid
    76  	})
    77  }
    78  
    79  func lookupGroupFunc(filter func(g Group) bool) (Group, error) {
    80  	// Get operating system-specific group reader-closer.
    81  	group, err := GetGroup()
    82  	if err != nil {
    83  		return Group{}, err
    84  	}
    85  	defer group.Close()
    86  
    87  	// Get the users.
    88  	groups, err := ParseGroupFilter(group, filter)
    89  	if err != nil {
    90  		return Group{}, err
    91  	}
    92  
    93  	// No user entries found.
    94  	if len(groups) == 0 {
    95  		return Group{}, ErrNoGroupEntries
    96  	}
    97  
    98  	// Assume the first entry is the "correct" one.
    99  	return groups[0], nil
   100  }
   101  
   102  func GetPasswdPath() (string, error) {
   103  	return unixPasswdPath, nil
   104  }
   105  
   106  func GetPasswd() (io.ReadCloser, error) {
   107  	return os.Open(unixPasswdPath)
   108  }
   109  
   110  func GetGroupPath() (string, error) {
   111  	return unixGroupPath, nil
   112  }
   113  
   114  func GetGroup() (io.ReadCloser, error) {
   115  	return os.Open(unixGroupPath)
   116  }
   117  
   118  // CurrentUser looks up the current user by their user id in /etc/passwd. If the
   119  // user cannot be found (or there is no /etc/passwd file on the filesystem),
   120  // then CurrentUser returns an error.
   121  func CurrentUser() (User, error) {
   122  	return LookupUid(unix.Getuid())
   123  }
   124  
   125  // CurrentGroup looks up the current user's group by their primary group id's
   126  // entry in /etc/passwd. If the group cannot be found (or there is no
   127  // /etc/group file on the filesystem), then CurrentGroup returns an error.
   128  func CurrentGroup() (Group, error) {
   129  	return LookupGid(unix.Getgid())
   130  }
   131  
   132  func currentUserSubIDs(fileName string) ([]SubID, error) {
   133  	u, err := CurrentUser()
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	filter := func(entry SubID) bool {
   138  		return entry.Name == u.Name || entry.Name == strconv.Itoa(u.Uid)
   139  	}
   140  	return ParseSubIDFileFilter(fileName, filter)
   141  }
   142  
   143  func CurrentUserSubUIDs() ([]SubID, error) {
   144  	return currentUserSubIDs("/etc/subuid")
   145  }
   146  
   147  func CurrentUserSubGIDs() ([]SubID, error) {
   148  	return currentUserSubIDs("/etc/subgid")
   149  }
   150  
   151  func CurrentProcessUIDMap() ([]IDMap, error) {
   152  	return ParseIDMapFile("/proc/self/uid_map")
   153  }
   154  
   155  func CurrentProcessGIDMap() ([]IDMap, error) {
   156  	return ParseIDMapFile("/proc/self/gid_map")
   157  }
   158  

View as plain text