Contents of /trunk/mkinitrd-magellan/busybox/loginutils/adduser.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 4776 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 4776 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * adduser - add users to /etc/passwd and /etc/shadow |
4 | * |
5 | * Copyright (C) 1999 by Lineo, inc. and John Beppu |
6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> |
7 | * |
8 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
9 | */ |
10 | |
11 | #include "busybox.h" |
12 | |
13 | #define DONT_SET_PASS (1 << 4) |
14 | #define DONT_MAKE_HOME (1 << 6) |
15 | |
16 | |
17 | /* remix */ |
18 | /* EDR recoded such that the uid may be passed in *p */ |
19 | static int passwd_study(const char *filename, struct passwd *p) |
20 | { |
21 | struct passwd *pw; |
22 | FILE *passwd; |
23 | |
24 | const int min = 500; |
25 | const int max = 65000; |
26 | |
27 | passwd = xfopen(filename, "r"); |
28 | |
29 | /* EDR if uid is out of bounds, set to min */ |
30 | if ((p->pw_uid > max) || (p->pw_uid < min)) |
31 | p->pw_uid = min; |
32 | |
33 | /* stuff to do: |
34 | * make sure login isn't taken; |
35 | * find free uid and gid; |
36 | */ |
37 | while ((pw = fgetpwent(passwd))) { |
38 | if (strcmp(pw->pw_name, p->pw_name) == 0) { |
39 | /* return 0; */ |
40 | return 1; |
41 | } |
42 | if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max) |
43 | && (pw->pw_uid >= min)) { |
44 | p->pw_uid = pw->pw_uid + 1; |
45 | } |
46 | } |
47 | |
48 | if (p->pw_gid == 0) { |
49 | /* EDR check for an already existing gid */ |
50 | while (getgrgid(p->pw_uid) != NULL) |
51 | p->pw_uid++; |
52 | |
53 | /* EDR also check for an existing group definition */ |
54 | if (getgrnam(p->pw_name) != NULL) |
55 | return 3; |
56 | |
57 | /* EDR create new gid always = uid */ |
58 | p->pw_gid = p->pw_uid; |
59 | } |
60 | |
61 | /* EDR bounds check */ |
62 | if ((p->pw_uid > max) || (p->pw_uid < min)) |
63 | return 2; |
64 | |
65 | /* return 1; */ |
66 | return 0; |
67 | } |
68 | |
69 | static void addgroup_wrapper(struct passwd *p) |
70 | { |
71 | char *cmd; |
72 | |
73 | cmd = xasprintf("addgroup -g %d \"%s\"", p->pw_gid, p->pw_name); |
74 | system(cmd); |
75 | free(cmd); |
76 | } |
77 | |
78 | static void passwd_wrapper(const char *login) ATTRIBUTE_NORETURN; |
79 | |
80 | static void passwd_wrapper(const char *login) |
81 | { |
82 | static const char prog[] = "passwd"; |
83 | execlp(prog, prog, login, NULL); |
84 | bb_error_msg_and_die("failed to execute '%s', you must set the password for '%s' manually", prog, login); |
85 | } |
86 | |
87 | /* putpwent(3) remix */ |
88 | static int adduser(struct passwd *p, unsigned long flags) |
89 | { |
90 | FILE *file; |
91 | int addgroup = !p->pw_gid; |
92 | |
93 | /* make sure everything is kosher and setup uid && gid */ |
94 | file = xfopen(bb_path_passwd_file, "a"); |
95 | fseek(file, 0, SEEK_END); |
96 | |
97 | switch (passwd_study(bb_path_passwd_file, p)) { |
98 | case 1: |
99 | bb_error_msg_and_die("%s: login already in use", p->pw_name); |
100 | case 2: |
101 | bb_error_msg_and_die("illegal uid or no uids left"); |
102 | case 3: |
103 | bb_error_msg_and_die("%s: group name already in use", p->pw_name); |
104 | } |
105 | |
106 | /* add to passwd */ |
107 | if (putpwent(p, file) == -1) { |
108 | bb_perror_nomsg_and_die(); |
109 | } |
110 | fclose(file); |
111 | |
112 | #if ENABLE_FEATURE_SHADOWPASSWDS |
113 | /* add to shadow if necessary */ |
114 | file = xfopen(bb_path_shadow_file, "a"); |
115 | fseek(file, 0, SEEK_END); |
116 | fprintf(file, "%s:!:%ld:%d:%d:%d:::\n", |
117 | p->pw_name, /* username */ |
118 | time(NULL) / 86400, /* sp->sp_lstchg */ |
119 | 0, /* sp->sp_min */ |
120 | 99999, /* sp->sp_max */ |
121 | 7); /* sp->sp_warn */ |
122 | fclose(file); |
123 | #endif |
124 | |
125 | /* add to group */ |
126 | /* addgroup should be responsible for dealing w/ gshadow */ |
127 | /* if using a pre-existing group, don't create one */ |
128 | if (addgroup) addgroup_wrapper(p); |
129 | |
130 | /* Clear the umask for this process so it doesn't |
131 | * * screw up the permissions on the mkdir and chown. */ |
132 | umask(0); |
133 | if (!(flags & DONT_MAKE_HOME)) { |
134 | /* Set the owner and group so it is owned by the new user, |
135 | then fix up the permissions to 2755. Can't do it before |
136 | since chown will clear the setgid bit */ |
137 | if (mkdir(p->pw_dir, 0755) |
138 | || chown(p->pw_dir, p->pw_uid, p->pw_gid) |
139 | || chmod(p->pw_dir, 02755)) { |
140 | bb_perror_msg("%s", p->pw_dir); |
141 | } |
142 | } |
143 | |
144 | if (!(flags & DONT_SET_PASS)) { |
145 | /* interactively set passwd */ |
146 | passwd_wrapper(p->pw_name); |
147 | } |
148 | |
149 | return 0; |
150 | } |
151 | |
152 | /* |
153 | * adduser will take a login_name as its first parameter. |
154 | * |
155 | * home |
156 | * shell |
157 | * gecos |
158 | * |
159 | * can be customized via command-line parameters. |
160 | */ |
161 | int adduser_main(int argc, char **argv) |
162 | { |
163 | struct passwd pw; |
164 | const char *usegroup = NULL; |
165 | unsigned long flags; |
166 | |
167 | /* got root? */ |
168 | if (geteuid()) { |
169 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
170 | } |
171 | |
172 | pw.pw_gecos = "Linux User,,,"; |
173 | pw.pw_shell = (char *)DEFAULT_SHELL; |
174 | pw.pw_dir = NULL; |
175 | |
176 | /* check for min, max and missing args and exit on error */ |
177 | opt_complementary = "-1:?1:?"; |
178 | flags = getopt32(argc, argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup); |
179 | |
180 | /* create string for $HOME if not specified already */ |
181 | if (!pw.pw_dir) { |
182 | snprintf(bb_common_bufsiz1, BUFSIZ, "/home/%s", argv[optind]); |
183 | pw.pw_dir = bb_common_bufsiz1; |
184 | } |
185 | |
186 | /* create a passwd struct */ |
187 | pw.pw_name = argv[optind]; |
188 | pw.pw_passwd = "x"; |
189 | pw.pw_uid = 0; |
190 | pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */ |
191 | |
192 | /* grand finale */ |
193 | return adduser(&pw, flags); |
194 | } |