aboutsummaryrefslogtreecommitdiff
path: root/loginutils/adduser.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-22 21:35:52 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-22 21:35:52 +0000
commitc2931aa2df2ddc6a627f3c40eb1cf5c221067092 (patch)
tree8b4b92c8c5bea933f7ea68302328bd17c0610b4a /loginutils/adduser.c
parentc8d7109f6036fab6b5993c24fc6514ba0c6a7d3d (diff)
downloadbusybox-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.c82
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 */
18static void passwd_study(struct passwd *p) 24static 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 }