diff options
author | Rob Landley <rob@landley.net> | 2006-04-04 19:19:53 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2006-04-04 19:19:53 +0000 |
commit | 9a2dd51237c065982b918f7e15d9248aa10d89d4 (patch) | |
tree | cb2aa1bf6f3ac94c8517994924da1a1a3a607429 /loginutils/adduser.c | |
parent | ab8736064b0220c0b7dd3d4226c3f40976a31c53 (diff) | |
download | busybox-w32-9a2dd51237c065982b918f7e15d9248aa10d89d4.tar.gz busybox-w32-9a2dd51237c065982b918f7e15d9248aa10d89d4.tar.bz2 busybox-w32-9a2dd51237c065982b918f7e15d9248aa10d89d4.zip |
Rewrite/shrink by tito.
Diffstat (limited to 'loginutils/adduser.c')
-rw-r--r-- | loginutils/adduser.c | 235 |
1 files changed, 68 insertions, 167 deletions
diff --git a/loginutils/adduser.c b/loginutils/adduser.c index 716f83069..a0d4872ec 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c | |||
@@ -8,43 +8,19 @@ | |||
8 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 8 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #ifndef _GNU_SOURCE | ||
12 | #define _GNU_SOURCE | ||
13 | #endif | ||
14 | #include <errno.h> | ||
15 | #include <fcntl.h> | ||
16 | #include <stdarg.h> | ||
17 | #include <stdio.h> | 11 | #include <stdio.h> |
18 | #include <stdlib.h> | 12 | #include <sys/types.h> |
19 | #include <string.h> | 13 | #include <string.h> |
20 | #include <time.h> | ||
21 | #include <unistd.h> | 14 | #include <unistd.h> |
15 | #include <time.h> | ||
22 | #include <getopt.h> | 16 | #include <getopt.h> |
23 | #include <sys/param.h> | ||
24 | #include <sys/stat.h> | 17 | #include <sys/stat.h> |
25 | #include <sys/types.h> | ||
26 | #include "busybox.h" | ||
27 | 18 | ||
19 | #include "busybox.h" | ||
28 | 20 | ||
21 | #define DONT_SET_PASS (1 << 4) | ||
22 | #define DONT_MAKE_HOME (1 << 6) | ||
29 | 23 | ||
30 | /* structs __________________________ */ | ||
31 | |||
32 | typedef struct { | ||
33 | uid_t u; | ||
34 | gid_t g; | ||
35 | } Id; | ||
36 | |||
37 | /* data _____________________________ */ | ||
38 | |||
39 | /* defaults : should this be in an external file? */ | ||
40 | static const char default_passwd[] = "x"; | ||
41 | static const char default_gecos[] = "Linux User,,,"; | ||
42 | static const char default_home_prefix[] = "/home"; | ||
43 | |||
44 | #ifdef CONFIG_FEATURE_SHADOWPASSWDS | ||
45 | /* shadow in use? */ | ||
46 | static int shadow_enabled = 0; | ||
47 | #endif | ||
48 | 24 | ||
49 | /* remix */ | 25 | /* remix */ |
50 | /* EDR recoded such that the uid may be passed in *p */ | 26 | /* EDR recoded such that the uid may be passed in *p */ |
@@ -56,9 +32,7 @@ static int passwd_study(const char *filename, struct passwd *p) | |||
56 | const int min = 500; | 32 | const int min = 500; |
57 | const int max = 65000; | 33 | const int max = 65000; |
58 | 34 | ||
59 | passwd = bb_wfopen(filename, "r"); | 35 | passwd = bb_xfopen(filename, "r"); |
60 | if (!passwd) | ||
61 | return 4; | ||
62 | 36 | ||
63 | /* EDR if uid is out of bounds, set to min */ | 37 | /* EDR if uid is out of bounds, set to min */ |
64 | if ((p->pw_uid > max) || (p->pw_uid < min)) | 38 | if ((p->pw_uid > max) || (p->pw_uid < min)) |
@@ -100,11 +74,11 @@ static int passwd_study(const char *filename, struct passwd *p) | |||
100 | return 0; | 74 | return 0; |
101 | } | 75 | } |
102 | 76 | ||
103 | static void addgroup_wrapper(const char *login, gid_t gid) | 77 | static void addgroup_wrapper(struct passwd *p) |
104 | { | 78 | { |
105 | char *cmd; | 79 | char *cmd; |
106 | 80 | ||
107 | cmd = bb_xasprintf("addgroup -g %d \"%s\"", gid, login); | 81 | cmd = bb_xasprintf("addgroup -g %d \"%s\"", p->pw_gid, p->pw_name); |
108 | system(cmd); | 82 | system(cmd); |
109 | free(cmd); | 83 | free(cmd); |
110 | } | 84 | } |
@@ -119,92 +93,63 @@ static void passwd_wrapper(const char *login) | |||
119 | } | 93 | } |
120 | 94 | ||
121 | /* putpwent(3) remix */ | 95 | /* putpwent(3) remix */ |
122 | static int adduser(const char *filename, struct passwd *p, int makehome, int setpass) | 96 | static int adduser(struct passwd *p, unsigned long flags) |
123 | { | 97 | { |
124 | FILE *passwd; | 98 | FILE *file; |
125 | int r; | ||
126 | #ifdef CONFIG_FEATURE_SHADOWPASSWDS | ||
127 | FILE *shadow; | ||
128 | struct spwd *sp; | ||
129 | #endif | ||
130 | int new_group = 1; | ||
131 | |||
132 | /* if using a pre-existing group, don't create one */ | ||
133 | if (p->pw_gid != 0) | ||
134 | new_group = 0; | ||
135 | 99 | ||
136 | /* make sure everything is kosher and setup uid && gid */ | 100 | /* make sure everything is kosher and setup uid && gid */ |
137 | passwd = bb_wfopen(filename, "a"); | 101 | file = bb_xfopen(bb_path_passwd_file, "a"); |
138 | if (passwd == NULL) { | 102 | fseek(file, 0, SEEK_END); |
139 | return 1; | 103 | |
140 | } | 104 | switch (passwd_study(bb_path_passwd_file, p)) { |
141 | fseek(passwd, 0, SEEK_END); | 105 | case 1: |
142 | 106 | bb_error_msg_and_die("%s: login already in use", p->pw_name); | |
143 | /* if (passwd_study(filename, p) == 0) { */ | 107 | case 2: |
144 | r = passwd_study(filename, p); | 108 | bb_error_msg_and_die("illegal uid or no uids left"); |
145 | if (r) { | 109 | case 3: |
146 | if (r == 1) | 110 | bb_error_msg_and_die("%s: group name already in use", p->pw_name); |
147 | bb_error_msg("%s: login already in use", p->pw_name); | 111 | } |
148 | else if (r == 2) | ||
149 | bb_error_msg("illegal uid or no uids left"); | ||
150 | else if (r == 3) | ||
151 | bb_error_msg("group name %s already in use", p->pw_name); | ||
152 | else | ||
153 | bb_error_msg("generic error."); | ||
154 | return 1; | ||
155 | } | ||
156 | 112 | ||
157 | /* add to passwd */ | 113 | /* add to passwd */ |
158 | if (putpwent(p, passwd) == -1) { | 114 | if (putpwent(p, file) == -1) { |
159 | return 1; | 115 | bb_perror_nomsg_and_die(); |
160 | } | 116 | } |
161 | fclose(passwd); | 117 | fclose(file); |
162 | 118 | ||
163 | #ifdef CONFIG_FEATURE_SHADOWPASSWDS | 119 | #if ENABLE_FEATURE_SHADOWPASSWDS |
164 | /* add to shadow if necessary */ | 120 | /* add to shadow if necessary */ |
165 | if (shadow_enabled) { | 121 | file = bb_xfopen(bb_path_shadow_file, "a"); |
166 | shadow = bb_wfopen(bb_path_shadow_file, "a"); | 122 | fseek(file, 0, SEEK_END); |
167 | if (shadow == NULL) { | 123 | fprintf(file, "%s:!:%ld:%d:%d:%d:::\n", |
168 | return 1; | 124 | p->pw_name, /* username */ |
169 | } | 125 | time(NULL) / 86400, /* sp->sp_lstchg */ |
170 | fseek(shadow, 0, SEEK_END); | 126 | 0, /* sp->sp_min */ |
171 | sp = pwd_to_spwd(p); | 127 | 99999, /* sp->sp_max */ |
172 | sp->sp_max = 99999; /* debianish */ | 128 | 7); /* sp->sp_warn */ |
173 | sp->sp_warn = 7; | 129 | fclose(file); |
174 | fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n", | ||
175 | sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max, | ||
176 | sp->sp_warn); | ||
177 | fclose(shadow); | ||
178 | } | ||
179 | #endif | 130 | #endif |
180 | 131 | ||
181 | if (new_group) { | 132 | /* add to group */ |
182 | /* add to group */ | 133 | /* addgroup should be responsible for dealing w/ gshadow */ |
183 | /* addgroup should be responsible for dealing w/ gshadow */ | 134 | /* if using a pre-existing group, don't create one */ |
184 | addgroup_wrapper(p->pw_name, p->pw_gid); | 135 | if (p->pw_gid == 0) { |
136 | addgroup_wrapper(p); | ||
185 | } | 137 | } |
186 | |||
187 | /* Clear the umask for this process so it doesn't | 138 | /* Clear the umask for this process so it doesn't |
188 | * * screw up the permissions on the mkdir and chown. */ | 139 | * * screw up the permissions on the mkdir and chown. */ |
189 | umask(0); | 140 | umask(0); |
190 | 141 | if (!(flags & DONT_MAKE_HOME)) { | |
191 | if (makehome) { | 142 | /* Set the owner and group so it is owned by the new user, |
192 | /* mkdir */ | 143 | then fix up the permissions to 2755. Can't do it before |
193 | if (mkdir(p->pw_dir, 0755)) { | 144 | since chown will clear the setgid bit */ |
194 | bb_perror_msg("%s", p->pw_dir); | 145 | if (mkdir(p->pw_dir, 0755) |
195 | } | 146 | || chown(p->pw_dir, p->pw_uid, p->pw_gid) |
196 | /* Set the owner and group so it is owned by the new user. */ | 147 | || chmod(p->pw_dir, 02755)) { |
197 | if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) { | 148 | bb_perror_msg("%s", p->pw_dir); |
198 | bb_perror_msg("%s", p->pw_dir); | 149 | } |
199 | } | 150 | } |
200 | /* Now fix up the permissions to 2755. Can't do it before now | 151 | |
201 | * since chown will clear the setgid bit */ | 152 | if (!(flags & DONT_SET_PASS)) { |
202 | if (chmod(p->pw_dir, 02755)) { | ||
203 | bb_perror_msg("%s", p->pw_dir); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | if (setpass) { | ||
208 | /* interactively set passwd */ | 153 | /* interactively set passwd */ |
209 | passwd_wrapper(p->pw_name); | 154 | passwd_wrapper(p->pw_name); |
210 | } | 155 | } |
@@ -212,22 +157,6 @@ static int adduser(const char *filename, struct passwd *p, int makehome, int set | |||
212 | return 0; | 157 | return 0; |
213 | } | 158 | } |
214 | 159 | ||
215 | |||
216 | /* return current uid (root is always uid == 0, right?) */ | ||
217 | #ifndef CONFIG_ADDGROUP | ||
218 | static inline void if_i_am_not_root(void) | ||
219 | #else | ||
220 | void if_i_am_not_root(void) | ||
221 | #endif | ||
222 | { | ||
223 | if (geteuid()) { | ||
224 | bb_error_msg_and_die( "Only root may add a user or group to the system."); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | #define SETPASS (1 << 4) | ||
229 | #define MAKEHOME (1 << 6) | ||
230 | |||
231 | /* | 160 | /* |
232 | * adduser will take a login_name as its first parameter. | 161 | * adduser will take a login_name as its first parameter. |
233 | * | 162 | * |
@@ -240,62 +169,34 @@ void if_i_am_not_root(void) | |||
240 | int adduser_main(int argc, char **argv) | 169 | int adduser_main(int argc, char **argv) |
241 | { | 170 | { |
242 | struct passwd pw; | 171 | struct passwd pw; |
243 | const char *login; | ||
244 | const char *gecos = default_gecos; | ||
245 | const char *home = NULL; | ||
246 | const char *shell = DEFAULT_SHELL; | ||
247 | const char *usegroup = NULL; | 172 | const char *usegroup = NULL; |
248 | int flags; | 173 | unsigned long flags; |
249 | int setpass = 1; | ||
250 | int makehome = 1; | ||
251 | 174 | ||
252 | /* init */ | 175 | pw.pw_gecos = "Linux User,,,"; |
253 | if (argc < 2) { | 176 | pw.pw_shell = (char *)DEFAULT_SHELL; |
254 | bb_show_usage(); | 177 | pw.pw_dir = NULL; |
255 | } | ||
256 | /* get args */ | ||
257 | flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &home, &gecos, &shell, &usegroup); | ||
258 | 178 | ||
259 | if (flags & SETPASS) { | 179 | /* check for min, max and missing args and exit on error */ |
260 | setpass = 0; | 180 | bb_opt_complementally = "-1:?1:?"; |
261 | } | 181 | flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup); |
262 | if (flags & MAKEHOME) { | ||
263 | makehome = 0; | ||
264 | } | ||
265 | 182 | ||
266 | /* got root? */ | 183 | /* got root? */ |
267 | if_i_am_not_root(); | 184 | if(geteuid()) { |
268 | 185 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | |
269 | /* get login */ | 186 | } |
270 | if (optind >= argc) { | ||
271 | bb_error_msg_and_die( "no user specified"); | ||
272 | } | ||
273 | login = argv[optind]; | ||
274 | 187 | ||
275 | /* create string for $HOME if not specified already */ | 188 | /* create string for $HOME if not specified already */ |
276 | if (!home) { | 189 | if (!pw.pw_dir) { |
277 | home = concat_path_file(default_home_prefix, login); | 190 | snprintf(bb_common_bufsiz1, BUFSIZ, "/home/%s", argv[optind]); |
191 | pw.pw_dir = &bb_common_bufsiz1[0]; | ||
278 | } | 192 | } |
279 | #ifdef CONFIG_FEATURE_SHADOWPASSWDS | ||
280 | /* is /etc/shadow in use? */ | ||
281 | shadow_enabled = (0 == access(bb_path_shadow_file, F_OK)); | ||
282 | #endif | ||
283 | 193 | ||
284 | /* create a passwd struct */ | 194 | /* create a passwd struct */ |
285 | pw.pw_name = (char *)login; | 195 | pw.pw_name = argv[optind]; |
286 | pw.pw_passwd = (char *)default_passwd; | 196 | pw.pw_passwd = "x"; |
287 | pw.pw_uid = 0; | 197 | pw.pw_uid = 0; |
288 | pw.pw_gid = 0; | 198 | pw.pw_gid = (usegroup) ? bb_xgetgrnam(usegroup) : 0; /* exits on failure */ |
289 | pw.pw_gecos = (char *)gecos; | ||
290 | pw.pw_dir = (char *)home; | ||
291 | pw.pw_shell = (char *)shell; | ||
292 | |||
293 | if (usegroup) { | ||
294 | /* Add user to a group that already exists */ | ||
295 | pw.pw_gid = bb_xgetgrnam(usegroup); | ||
296 | /* exits on error */ | ||
297 | } | ||
298 | 199 | ||
299 | /* grand finale */ | 200 | /* grand finale */ |
300 | return adduser(bb_path_passwd_file, &pw, makehome, setpass); | 201 | return adduser(&pw, flags); |
301 | } | 202 | } |