source: MondoRescue/branches/2.2.2/mindi-busybox/loginutils/adduser.c@ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 18 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

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