Lines 17-26
Link Here
|
17 |
/* #define OPT_GECOS (1 << 1) */ /* unused */ |
17 |
/* #define OPT_GECOS (1 << 1) */ /* unused */ |
18 |
#define OPT_SHELL (1 << 2) |
18 |
#define OPT_SHELL (1 << 2) |
19 |
#define OPT_GID (1 << 3) |
19 |
#define OPT_GID (1 << 3) |
20 |
#define OPT_DONT_SET_PASS (1 << 4) |
20 |
/* #define OPT_GROUPS (1 << 4) */ /* unused */ |
21 |
#define OPT_SYSTEM_ACCOUNT (1 << 5) |
21 |
#define OPT_SET_PASS (1 << 5) |
22 |
#define OPT_DONT_MAKE_HOME (1 << 6) |
22 |
#define OPT_SYSTEM_ACCOUNT (1 << 6) |
23 |
#define OPT_UID (1 << 7) |
23 |
#define OPT_MAKE_HOME (1 << 7) |
|
|
24 |
#define OPT_UID (1 << 8) |
24 |
|
25 |
|
25 |
/* We assume UID_T_MAX == INT_MAX */ |
26 |
/* We assume UID_T_MAX == INT_MAX */ |
26 |
/* remix */ |
27 |
/* remix */ |
Lines 69-75
Link Here
|
69 |
{ |
70 |
{ |
70 |
char *cmd; |
71 |
char *cmd; |
71 |
|
72 |
|
72 |
cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name); |
73 |
cmd = xasprintf("'%s' groupadd -g %u '%s'", bb_busybox_exec_path, (unsigned)p->pw_gid, p->pw_name); |
|
|
74 |
system(cmd); |
75 |
free(cmd); |
76 |
} |
77 |
|
78 |
static void addgroup_wrapper2(char * name, char * grp) |
79 |
{ |
80 |
char *cmd; |
81 |
|
82 |
cmd = xasprintf("'%s' groupadd '%s' '%s'", bb_busybox_exec_path, name, grp); |
73 |
system(cmd); |
83 |
system(cmd); |
74 |
free(cmd); |
84 |
free(cmd); |
75 |
} |
85 |
} |
Lines 86-99
Link Here
|
86 |
|
96 |
|
87 |
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS |
97 |
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS |
88 |
static const char adduser_longopts[] ALIGN1 = |
98 |
static const char adduser_longopts[] ALIGN1 = |
89 |
"home\0" Required_argument "h" |
99 |
"home-dir\0" Required_argument "d" |
90 |
"gecos\0" Required_argument "g" |
100 |
"comment\0" Required_argument "c" |
91 |
"shell\0" Required_argument "s" |
101 |
"shell\0" Required_argument "s" |
92 |
"ingroup\0" Required_argument "G" |
102 |
"gid\0" Required_argument "g" |
93 |
"disabled-password\0" No_argument "D" |
103 |
"groups\0" Required_argument "G" |
94 |
"empty-password\0" No_argument "D" |
104 |
"enable-password\0" No_argument "P" |
95 |
"system\0" No_argument "S" |
105 |
"system\0" No_argument "r" |
96 |
"no-create-home\0" No_argument "H" |
106 |
"create-home\0" No_argument "m" |
97 |
"uid\0" Required_argument "u" |
107 |
"uid\0" Required_argument "u" |
98 |
; |
108 |
; |
99 |
#endif |
109 |
#endif |
Lines 108-115
Link Here
|
108 |
{ |
118 |
{ |
109 |
struct passwd pw; |
119 |
struct passwd pw; |
110 |
const char *usegroup = NULL; |
120 |
const char *usegroup = NULL; |
|
|
121 |
const char *groups = NULL; |
111 |
char *p; |
122 |
char *p; |
112 |
unsigned opts; |
123 |
unsigned opts; |
|
|
124 |
char *groupsbuf = NULL; |
125 |
char **sup_grp = NULL; |
126 |
char *tmp_grp = NULL; |
127 |
int sup_num = 0; |
113 |
|
128 |
|
114 |
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS |
129 |
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS |
115 |
applet_long_options = adduser_longopts; |
130 |
applet_long_options = adduser_longopts; |
Lines 120-137
Link Here
|
120 |
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
135 |
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
121 |
} |
136 |
} |
122 |
|
137 |
|
123 |
pw.pw_gecos = (char *)"Linux User,,,"; |
138 |
pw.pw_gecos = NULL; |
124 |
pw.pw_shell = (char *)DEFAULT_SHELL; |
139 |
pw.pw_shell = (char *)DEFAULT_SHELL; |
125 |
pw.pw_dir = NULL; |
140 |
pw.pw_dir = NULL; |
126 |
|
141 |
|
127 |
/* exactly one non-option arg */ |
142 |
/* exactly one non-option arg */ |
128 |
/* disable interactive passwd for system accounts */ |
143 |
/* disable interactive passwd for system accounts */ |
129 |
opt_complementary = "=1:SD:u+"; |
144 |
opt_complementary = "=1:r-P:u+"; |
130 |
if (sizeof(pw.pw_uid) == sizeof(int)) { |
145 |
if (sizeof(pw.pw_uid) == sizeof(int)) { |
131 |
opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); |
146 |
opts = getopt32(argv, "d:c:s:g:G:Prmu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &groups, &pw.pw_uid); |
132 |
} else { |
147 |
} else { |
133 |
unsigned uid; |
148 |
unsigned uid; |
134 |
opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &uid); |
149 |
opts = getopt32(argv, "d:c:s:g:G:Prmu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &groups, &uid); |
135 |
if (opts & OPT_UID) { |
150 |
if (opts & OPT_UID) { |
136 |
pw.pw_uid = uid; |
151 |
pw.pw_uid = uid; |
137 |
} |
152 |
} |
Lines 141-159
Link Here
|
141 |
/* fill in the passwd struct */ |
155 |
/* fill in the passwd struct */ |
142 |
pw.pw_name = argv[0]; |
156 |
pw.pw_name = argv[0]; |
143 |
die_if_bad_username(pw.pw_name); |
157 |
die_if_bad_username(pw.pw_name); |
|
|
158 |
if (!pw.pw_gecos) { |
159 |
pw.pw_gecos = pw.pw_name; |
160 |
} |
144 |
if (!pw.pw_dir) { |
161 |
if (!pw.pw_dir) { |
145 |
/* create string for $HOME if not specified already */ |
162 |
/* create string for $HOME if not specified already */ |
146 |
pw.pw_dir = xasprintf("/home/%s", argv[0]); |
163 |
pw.pw_dir = xasprintf("/home/%s", argv[0]); |
147 |
} |
164 |
} |
148 |
pw.pw_passwd = (char *)"x"; |
165 |
pw.pw_passwd = (char *)"x"; |
149 |
if (opts & OPT_SYSTEM_ACCOUNT) { |
166 |
if (opts & OPT_SYSTEM_ACCOUNT) { |
150 |
if (!usegroup) { |
167 |
if (!usegroup && !groups) { |
151 |
usegroup = "nogroup"; |
168 |
usegroup = "nogroup"; |
152 |
} |
169 |
} |
153 |
if (!(opts & OPT_SHELL)) { |
170 |
if (!(opts & OPT_SHELL)) { |
154 |
pw.pw_shell = (char *) "/bin/false"; |
171 |
pw.pw_shell = (char *) "/bin/false"; |
155 |
} |
172 |
} |
156 |
} |
173 |
} |
|
|
174 |
|
175 |
if (groups) { |
176 |
groupsbuf = (char *) calloc(strlen(groups) + 1, sizeof(char)); |
177 |
strcpy(groupsbuf, groups); |
178 |
for (tmp_grp = groupsbuf; (tmp_grp = strchr(&tmp_grp[1], ',')) != NULL; sup_num++); |
179 |
if (sup_num || usegroup) { |
180 |
if (usegroup) |
181 |
sup_num++; |
182 |
sup_grp = (char **) malloc(sizeof(char *) * sup_num); |
183 |
sup_num = 0; |
184 |
strtok((char * restrict) groupsbuf, ","); |
185 |
if (usegroup) { |
186 |
sup_grp[sup_num] = (const char *) groupsbuf; |
187 |
sup_num++; |
188 |
} else { |
189 |
usegroup = (const char *) groupsbuf; |
190 |
} |
191 |
while ((tmp_grp = (char *) strtok(NULL, ",")) != NULL) { |
192 |
sup_grp[sup_num] = (const char *) calloc(strlen(tmp_grp) + 1, sizeof(char)); |
193 |
strcpy(sup_grp[sup_num], tmp_grp); |
194 |
sup_num++; |
195 |
} |
196 |
} else { |
197 |
usegroup = groups; |
198 |
groups = NULL; |
199 |
} |
200 |
} |
201 |
|
157 |
pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */ |
202 |
pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */ |
158 |
|
203 |
|
159 |
/* make sure everything is kosher and setup uid && maybe gid */ |
204 |
/* make sure everything is kosher and setup uid && maybe gid */ |
Lines 162-168
Link Here
|
162 |
p = xasprintf("x:%u:%u:%s:%s:%s", |
208 |
p = xasprintf("x:%u:%u:%s:%s:%s", |
163 |
(unsigned) pw.pw_uid, (unsigned) pw.pw_gid, |
209 |
(unsigned) pw.pw_uid, (unsigned) pw.pw_gid, |
164 |
pw.pw_gecos, pw.pw_dir, pw.pw_shell); |
210 |
pw.pw_gecos, pw.pw_dir, pw.pw_shell); |
165 |
if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) { |
211 |
if (update_passwd(cross_path(bb_path_passwd_file), pw.pw_name, p, NULL) < 0) { |
166 |
return EXIT_FAILURE; |
212 |
return EXIT_FAILURE; |
167 |
} |
213 |
} |
168 |
if (ENABLE_FEATURE_CLEAN_UP) |
214 |
if (ENABLE_FEATURE_CLEAN_UP) |
Lines 182-188
Link Here
|
182 |
/* fields: 2 3 4 5 6 78 */ |
228 |
/* fields: 2 3 4 5 6 78 */ |
183 |
p = xasprintf("!:%u:0:99999:7:::", (unsigned)(time(NULL)) / (24*60*60)); |
229 |
p = xasprintf("!:%u:0:99999:7:::", (unsigned)(time(NULL)) / (24*60*60)); |
184 |
/* ignore errors: if file is missing we suppose admin doesn't want it */ |
230 |
/* ignore errors: if file is missing we suppose admin doesn't want it */ |
185 |
update_passwd(bb_path_shadow_file, pw.pw_name, p, NULL); |
231 |
update_passwd(cross_path(bb_path_shadow_file), pw.pw_name, p, NULL); |
186 |
if (ENABLE_FEATURE_CLEAN_UP) |
232 |
if (ENABLE_FEATURE_CLEAN_UP) |
187 |
free(p); |
233 |
free(p); |
188 |
#endif |
234 |
#endif |
Lines 192-202
Link Here
|
192 |
/* if using a pre-existing group, don't create one */ |
238 |
/* if using a pre-existing group, don't create one */ |
193 |
if (!usegroup) |
239 |
if (!usegroup) |
194 |
addgroup_wrapper(&pw); |
240 |
addgroup_wrapper(&pw); |
|
|
241 |
|
242 |
if (groups) { |
243 |
do { |
244 |
sup_num--; |
245 |
addgroup_wrapper2(pw.pw_name, sup_grp[sup_num]); |
246 |
free(sup_grp[sup_num]); |
247 |
} while (sup_num > 0); |
248 |
free(sup_grp); |
249 |
} |
195 |
|
250 |
|
196 |
/* clear the umask for this process so it doesn't |
251 |
/* clear the umask for this process so it doesn't |
197 |
* screw up the permissions on the mkdir and chown. */ |
252 |
* screw up the permissions on the mkdir and chown. */ |
198 |
umask(0); |
253 |
umask(0); |
199 |
if (!(opts & OPT_DONT_MAKE_HOME)) { |
254 |
if (opts & OPT_MAKE_HOME) { |
200 |
/* set the owner and group so it is owned by the new user, |
255 |
/* set the owner and group so it is owned by the new user, |
201 |
* then fix up the permissions to 2755. Can't do it before |
256 |
* then fix up the permissions to 2755. Can't do it before |
202 |
* since chown will clear the setgid bit */ |
257 |
* since chown will clear the setgid bit */ |
Lines 208-214
Link Here
|
208 |
} |
263 |
} |
209 |
} |
264 |
} |
210 |
|
265 |
|
211 |
if (!(opts & OPT_DONT_SET_PASS)) { |
266 |
if (opts & OPT_SET_PASS) { |
212 |
/* interactively set passwd */ |
267 |
/* interactively set passwd */ |
213 |
passwd_wrapper(pw.pw_name); |
268 |
passwd_wrapper(pw.pw_name); |
214 |
} |
269 |
} |