diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-22 21:35:52 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-22 21:35:52 +0000 |
commit | c2931aa2df2ddc6a627f3c40eb1cf5c221067092 (patch) | |
tree | 8b4b92c8c5bea933f7ea68302328bd17c0610b4a /loginutils/adduser.c | |
parent | c8d7109f6036fab6b5993c24fc6514ba0c6a7d3d (diff) | |
download | busybox-w32-c2931aa2df2ddc6a627f3c40eb1cf5c221067092.tar.gz busybox-w32-c2931aa2df2ddc6a627f3c40eb1cf5c221067092.tar.bz2 busybox-w32-c2931aa2df2ddc6a627f3c40eb1cf5c221067092.zip |
adduser/addgroup: support specifying uid/gid, add system
account creation mode. By Tito.
function old new delta
adduser_main 650 726 +76
addgroup_main 341 402 +61
addgroup_longopts - 16 +16
adduser_longopts 97 103 +6
packed_usage 26161 26163 +2
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/0 up/down: 161/0) Total: 161 bytes
Diffstat (limited to 'loginutils/adduser.c')
-rw-r--r-- | loginutils/adduser.c | 82 |
1 files changed, 60 insertions, 22 deletions
diff --git a/loginutils/adduser.c b/loginutils/adduser.c index df4fad694..a399d9e4c 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c | |||
@@ -9,38 +9,55 @@ | |||
9 | */ | 9 | */ |
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | 11 | ||
12 | /* #define OPT_HOME (1 << 0) */ /* unused */ | ||
13 | /* #define OPT_GECOS (1 << 1) */ /* unused */ | ||
14 | #define OPT_SHELL (1 << 2) | ||
15 | #define OPT_GID (1 << 3) | ||
12 | #define OPT_DONT_SET_PASS (1 << 4) | 16 | #define OPT_DONT_SET_PASS (1 << 4) |
13 | #define OPT_SYSTEM_ACCOUNT (1 << 5) | 17 | #define OPT_SYSTEM_ACCOUNT (1 << 5) |
14 | #define OPT_DONT_MAKE_HOME (1 << 6) | 18 | #define OPT_DONT_MAKE_HOME (1 << 6) |
19 | #define OPT_UID (1 << 7) | ||
15 | 20 | ||
21 | /* We assume UID_T_MAX == INT_MAX */ | ||
16 | /* remix */ | 22 | /* remix */ |
17 | /* recoded such that the uid may be passed in *p */ | 23 | /* recoded such that the uid may be passed in *p */ |
18 | static void passwd_study(struct passwd *p) | 24 | static void passwd_study(struct passwd *p) |
19 | { | 25 | { |
20 | int max; | 26 | int max = UINT_MAX; |
21 | 27 | ||
22 | if (getpwnam(p->pw_name)) | 28 | if (getpwnam(p->pw_name)) { |
23 | bb_error_msg_and_die("login '%s' is in use", p->pw_name); | 29 | bb_error_msg_and_die("%s '%s' in use", "user", p->pw_name); |
24 | 30 | /* this format string is reused in adduser and addgroup */ | |
25 | if (option_mask32 & OPT_SYSTEM_ACCOUNT) { | ||
26 | p->pw_uid = 0; | ||
27 | max = 999; | ||
28 | } else { | ||
29 | p->pw_uid = 1000; | ||
30 | max = 64999; | ||
31 | } | 31 | } |
32 | 32 | ||
33 | if (!(option_mask32 & OPT_UID)) { | ||
34 | if (option_mask32 & OPT_SYSTEM_ACCOUNT) { | ||
35 | p->pw_uid = 100; /* FIRST_SYSTEM_UID */ | ||
36 | max = 999; /* LAST_SYSTEM_UID */ | ||
37 | } else { | ||
38 | p->pw_uid = 1000; /* FIRST_UID */ | ||
39 | max = 64999; /* LAST_UID */ | ||
40 | } | ||
41 | } | ||
33 | /* check for a free uid (and maybe gid) */ | 42 | /* check for a free uid (and maybe gid) */ |
34 | while (getpwuid(p->pw_uid) || (p->pw_gid == (gid_t)-1 && getgrgid(p->pw_uid))) { | 43 | while (getpwuid(p->pw_uid) || (p->pw_gid == (gid_t)-1 && getgrgid(p->pw_uid))) { |
44 | if (option_mask32 & OPT_UID) { | ||
45 | /* -u N, cannot pick uid other than N: error */ | ||
46 | bb_error_msg_and_die("%s '%s' in use", "uid", itoa(p->pw_uid)); | ||
47 | /* this format string is reused in adduser and addgroup */ | ||
48 | } | ||
49 | if (p->pw_uid == max) { | ||
50 | bb_error_msg_and_die("no %cids left", 'u'); | ||
51 | } | ||
35 | p->pw_uid++; | 52 | p->pw_uid++; |
36 | if (p->pw_uid > max) | ||
37 | bb_error_msg_and_die("no free uids left"); | ||
38 | } | 53 | } |
39 | 54 | ||
40 | if (p->pw_gid == (gid_t)-1) { | 55 | if (p->pw_gid == (gid_t)-1) { |
41 | p->pw_gid = p->pw_uid; /* new gid = uid */ | 56 | p->pw_gid = p->pw_uid; /* new gid = uid */ |
42 | if (getgrnam(p->pw_name)) | 57 | if (getgrnam(p->pw_name)) { |
43 | bb_error_msg_and_die("group name '%s' is in use", p->pw_name); | 58 | bb_error_msg_and_die("%s '%s' in use", "group", p->pw_name); |
59 | /* this format string is reused in adduser and addgroup */ | ||
60 | } | ||
44 | } | 61 | } |
45 | } | 62 | } |
46 | 63 | ||
@@ -73,6 +90,7 @@ static const char adduser_longopts[] ALIGN1 = | |||
73 | "empty-password\0" No_argument "D" | 90 | "empty-password\0" No_argument "D" |
74 | "system\0" No_argument "S" | 91 | "system\0" No_argument "S" |
75 | "no-create-home\0" No_argument "H" | 92 | "no-create-home\0" No_argument "H" |
93 | "uid\0" Required_argument "u" | ||
76 | ; | 94 | ; |
77 | #endif | 95 | #endif |
78 | 96 | ||
@@ -87,6 +105,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
87 | struct passwd pw; | 105 | struct passwd pw; |
88 | const char *usegroup = NULL; | 106 | const char *usegroup = NULL; |
89 | char *p; | 107 | char *p; |
108 | unsigned opts; | ||
90 | 109 | ||
91 | #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS | 110 | #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS |
92 | applet_long_options = adduser_longopts; | 111 | applet_long_options = adduser_longopts; |
@@ -102,8 +121,17 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
102 | pw.pw_dir = NULL; | 121 | pw.pw_dir = NULL; |
103 | 122 | ||
104 | /* exactly one non-option arg */ | 123 | /* exactly one non-option arg */ |
105 | opt_complementary = "=1"; | 124 | /* disable interactive passwd for system accounts */ |
106 | getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup); | 125 | opt_complementary = "=1:SD:u+"; |
126 | if (sizeof(pw.pw_uid) == sizeof(int)) { | ||
127 | opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); | ||
128 | } else { | ||
129 | unsigned uid; | ||
130 | opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &uid); | ||
131 | if (opts & OPT_UID) { | ||
132 | pw.pw_uid = uid; | ||
133 | } | ||
134 | } | ||
107 | argv += optind; | 135 | argv += optind; |
108 | 136 | ||
109 | /* fill in the passwd struct */ | 137 | /* fill in the passwd struct */ |
@@ -114,12 +142,22 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
114 | pw.pw_dir = xasprintf("/home/%s", argv[0]); | 142 | pw.pw_dir = xasprintf("/home/%s", argv[0]); |
115 | } | 143 | } |
116 | pw.pw_passwd = (char *)"x"; | 144 | pw.pw_passwd = (char *)"x"; |
145 | if (opts & OPT_SYSTEM_ACCOUNT) { | ||
146 | if (!usegroup) { | ||
147 | usegroup = "nogroup"; | ||
148 | } | ||
149 | if (!(opts & OPT_SHELL)) { | ||
150 | pw.pw_shell = (char *) "/bin/false"; | ||
151 | } | ||
152 | } | ||
117 | pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */ | 153 | pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */ |
118 | 154 | ||
119 | /* make sure everything is kosher and setup uid && maybe gid */ | 155 | /* make sure everything is kosher and setup uid && maybe gid */ |
120 | passwd_study(&pw); | 156 | passwd_study(&pw); |
121 | 157 | ||
122 | p = xasprintf("x:%u:%u:%s:%s:%s", pw.pw_uid, pw.pw_gid, pw.pw_gecos, pw.pw_dir, pw.pw_shell); | 158 | p = xasprintf("x:%u:%u:%s:%s:%s", |
159 | (unsigned) pw.pw_uid, (unsigned) pw.pw_gid, | ||
160 | pw.pw_gecos, pw.pw_dir, pw.pw_shell); | ||
123 | if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) { | 161 | if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) { |
124 | return EXIT_FAILURE; | 162 | return EXIT_FAILURE; |
125 | } | 163 | } |
@@ -143,10 +181,10 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
143 | /* clear the umask for this process so it doesn't | 181 | /* clear the umask for this process so it doesn't |
144 | * screw up the permissions on the mkdir and chown. */ | 182 | * screw up the permissions on the mkdir and chown. */ |
145 | umask(0); | 183 | umask(0); |
146 | if (!(option_mask32 & OPT_DONT_MAKE_HOME)) { | 184 | if (!(opts & OPT_DONT_MAKE_HOME)) { |
147 | /* Set the owner and group so it is owned by the new user, | 185 | /* set the owner and group so it is owned by the new user, |
148 | then fix up the permissions to 2755. Can't do it before | 186 | * then fix up the permissions to 2755. Can't do it before |
149 | since chown will clear the setgid bit */ | 187 | * since chown will clear the setgid bit */ |
150 | if (mkdir(pw.pw_dir, 0755) | 188 | if (mkdir(pw.pw_dir, 0755) |
151 | || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid) | 189 | || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid) |
152 | || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */ | 190 | || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */ |
@@ -155,7 +193,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
155 | } | 193 | } |
156 | } | 194 | } |
157 | 195 | ||
158 | if (!(option_mask32 & OPT_DONT_SET_PASS)) { | 196 | if (!(opts & OPT_DONT_SET_PASS)) { |
159 | /* interactively set passwd */ | 197 | /* interactively set passwd */ |
160 | passwd_wrapper(pw.pw_name); | 198 | passwd_wrapper(pw.pw_name); |
161 | } | 199 | } |