diff options
Diffstat (limited to 'vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go')
-rw-r--r-- | vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go | 155 |
1 files changed, 0 insertions, 155 deletions
diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go deleted file mode 100644 index c1eedff..0000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go +++ /dev/null | |||
@@ -1,155 +0,0 @@ | |||
1 | package idtools | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "os/exec" | ||
6 | "path/filepath" | ||
7 | "strings" | ||
8 | "syscall" | ||
9 | ) | ||
10 | |||
11 | // add a user and/or group to Linux /etc/passwd, /etc/group using standard | ||
12 | // Linux distribution commands: | ||
13 | // adduser --uid <id> --shell /bin/login --no-create-home --disabled-login --ingroup <groupname> <username> | ||
14 | // useradd -M -u <id> -s /bin/nologin -N -g <groupname> <username> | ||
15 | // addgroup --gid <id> <groupname> | ||
16 | // groupadd -g <id> <groupname> | ||
17 | |||
18 | const baseUID int = 10000 | ||
19 | const baseGID int = 10000 | ||
20 | const idMAX int = 65534 | ||
21 | |||
22 | var ( | ||
23 | userCommand string | ||
24 | groupCommand string | ||
25 | |||
26 | cmdTemplates = map[string]string{ | ||
27 | "adduser": "--uid %d --shell /bin/false --no-create-home --disabled-login --ingroup %s %s", | ||
28 | "useradd": "-M -u %d -s /bin/false -N -g %s %s", | ||
29 | "addgroup": "--gid %d %s", | ||
30 | "groupadd": "-g %d %s", | ||
31 | } | ||
32 | ) | ||
33 | |||
34 | func init() { | ||
35 | // set up which commands are used for adding users/groups dependent on distro | ||
36 | if _, err := resolveBinary("adduser"); err == nil { | ||
37 | userCommand = "adduser" | ||
38 | } else if _, err := resolveBinary("useradd"); err == nil { | ||
39 | userCommand = "useradd" | ||
40 | } | ||
41 | if _, err := resolveBinary("addgroup"); err == nil { | ||
42 | groupCommand = "addgroup" | ||
43 | } else if _, err := resolveBinary("groupadd"); err == nil { | ||
44 | groupCommand = "groupadd" | ||
45 | } | ||
46 | } | ||
47 | |||
48 | func resolveBinary(binname string) (string, error) { | ||
49 | binaryPath, err := exec.LookPath(binname) | ||
50 | if err != nil { | ||
51 | return "", err | ||
52 | } | ||
53 | resolvedPath, err := filepath.EvalSymlinks(binaryPath) | ||
54 | if err != nil { | ||
55 | return "", err | ||
56 | } | ||
57 | //only return no error if the final resolved binary basename | ||
58 | //matches what was searched for | ||
59 | if filepath.Base(resolvedPath) == binname { | ||
60 | return resolvedPath, nil | ||
61 | } | ||
62 | return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath) | ||
63 | } | ||
64 | |||
65 | // AddNamespaceRangesUser takes a name and finds an unused uid, gid pair | ||
66 | // and calls the appropriate helper function to add the group and then | ||
67 | // the user to the group in /etc/group and /etc/passwd respectively. | ||
68 | // This new user's /etc/sub{uid,gid} ranges will be used for user namespace | ||
69 | // mapping ranges in containers. | ||
70 | func AddNamespaceRangesUser(name string) (int, int, error) { | ||
71 | // Find unused uid, gid pair | ||
72 | uid, err := findUnusedUID(baseUID) | ||
73 | if err != nil { | ||
74 | return -1, -1, fmt.Errorf("Unable to find unused UID: %v", err) | ||
75 | } | ||
76 | gid, err := findUnusedGID(baseGID) | ||
77 | if err != nil { | ||
78 | return -1, -1, fmt.Errorf("Unable to find unused GID: %v", err) | ||
79 | } | ||
80 | |||
81 | // First add the group that we will use | ||
82 | if err := addGroup(name, gid); err != nil { | ||
83 | return -1, -1, fmt.Errorf("Error adding group %q: %v", name, err) | ||
84 | } | ||
85 | // Add the user as a member of the group | ||
86 | if err := addUser(name, uid, name); err != nil { | ||
87 | return -1, -1, fmt.Errorf("Error adding user %q: %v", name, err) | ||
88 | } | ||
89 | return uid, gid, nil | ||
90 | } | ||
91 | |||
92 | func addUser(userName string, uid int, groupName string) error { | ||
93 | |||
94 | if userCommand == "" { | ||
95 | return fmt.Errorf("Cannot add user; no useradd/adduser binary found") | ||
96 | } | ||
97 | args := fmt.Sprintf(cmdTemplates[userCommand], uid, groupName, userName) | ||
98 | return execAddCmd(userCommand, args) | ||
99 | } | ||
100 | |||
101 | func addGroup(groupName string, gid int) error { | ||
102 | |||
103 | if groupCommand == "" { | ||
104 | return fmt.Errorf("Cannot add group; no groupadd/addgroup binary found") | ||
105 | } | ||
106 | args := fmt.Sprintf(cmdTemplates[groupCommand], gid, groupName) | ||
107 | // only error out if the error isn't that the group already exists | ||
108 | // if the group exists then our needs are already met | ||
109 | if err := execAddCmd(groupCommand, args); err != nil && !strings.Contains(err.Error(), "already exists") { | ||
110 | return err | ||
111 | } | ||
112 | return nil | ||
113 | } | ||
114 | |||
115 | func execAddCmd(cmd, args string) error { | ||
116 | execCmd := exec.Command(cmd, strings.Split(args, " ")...) | ||
117 | out, err := execCmd.CombinedOutput() | ||
118 | if err != nil { | ||
119 | return fmt.Errorf("Failed to add user/group with error: %v; output: %q", err, string(out)) | ||
120 | } | ||
121 | return nil | ||
122 | } | ||
123 | |||
124 | func findUnusedUID(startUID int) (int, error) { | ||
125 | return findUnused("passwd", startUID) | ||
126 | } | ||
127 | |||
128 | func findUnusedGID(startGID int) (int, error) { | ||
129 | return findUnused("group", startGID) | ||
130 | } | ||
131 | |||
132 | func findUnused(file string, id int) (int, error) { | ||
133 | for { | ||
134 | cmdStr := fmt.Sprintf("cat /etc/%s | cut -d: -f3 | grep '^%d$'", file, id) | ||
135 | cmd := exec.Command("sh", "-c", cmdStr) | ||
136 | if err := cmd.Run(); err != nil { | ||
137 | // if a non-zero return code occurs, then we know the ID was not found | ||
138 | // and is usable | ||
139 | if exiterr, ok := err.(*exec.ExitError); ok { | ||
140 | // The program has exited with an exit code != 0 | ||
141 | if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { | ||
142 | if status.ExitStatus() == 1 { | ||
143 | //no match, we can use this ID | ||
144 | return id, nil | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | return -1, fmt.Errorf("Error looking in /etc/%s for unused ID: %v", file, err) | ||
149 | } | ||
150 | id++ | ||
151 | if id > idMAX { | ||
152 | return -1, fmt.Errorf("Maximum id in %q reached with finding unused numeric ID", file) | ||
153 | } | ||
154 | } | ||
155 | } | ||