1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
/* useradd.c - add a new user
*
* Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com>
* Copyright 2013 Kyungwan Han <asura321@gmail.com>
*
* See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/useradd.html
USE_USERADD(NEWTOY(useradd, "<1>2u#<0G:s:g:h:SDH", TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
USE_USERADD(OLDTOY(adduser, useradd, TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
config USERADD
bool "useradd"
default n
help
usage: useradd [-SDH] [-h DIR] [-s SHELL] [-G GRP] [-g NAME] [-u UID] USER [GROUP]
Create new user, or add USER to GROUP
-D Don't assign a password
-g NAME Real name
-G GRP Add user to existing group
-h DIR Home directory
-H Don't create home directory
-s SHELL Login shell
-S Create a system user
-u UID User id
*/
#define FOR_useradd
#include "toys.h"
GLOBALS(
char *dir;
char *gecos;
char *shell;
char *u_grp;
long uid;
long gid;
)
void useradd_main(void)
{
char *s = *toys.optargs, *entry;
struct passwd pwd;
// Act like groupadd?
if (toys.optc == 2) {
if (toys.optflags) {
toys.exithelp = 1;
error_exit("options with USER GROUP");
}
xexec((char *[]){"groupadd", toys.optargs[0], toys.optargs[1], 0});
}
// Sanity check user to add
if (s[strcspn(s, ":/\n")] || strlen(s) > LOGIN_NAME_MAX)
error_exit("bad username");
// race condition: two adds at same time?
if (getpwnam(s)) error_exit("'%s' in use", s);
// Add a new group to the system, if UID is given then that is validated
// to be free, else a free UID is choosen by self.
// SYSTEM IDs are considered in the range 100 ... 999
// add_user(), add a new entry in /etc/passwd, /etc/shadow files
pwd.pw_name = s;
pwd.pw_passwd = "x";
pwd.pw_gecos = TT.gecos ? TT.gecos : "Linux User,";
pwd.pw_dir = TT.dir ? TT.dir : xmprintf("/home/%s", *toys.optargs);
if (!TT.shell) {
TT.shell = getenv("SHELL");
if (!TT.shell) {
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_shell && *pw->pw_shell) TT.shell = xstrdup(pw->pw_shell);
else TT.shell = "/bin/sh";
}
}
pwd.pw_shell = TT.shell;
if (toys.optflags & FLAG_u) {
if (TT.uid > INT_MAX) error_exit("bad uid");
if (getpwuid(TT.uid)) error_exit("uid '%ld' in use", TT.uid);
} else {
if (toys.optflags & FLAG_S) TT.uid = CFG_TOYBOX_UID_SYS;
else TT.uid = CFG_TOYBOX_UID_USR;
//find unused uid
while (getpwuid(TT.uid)) TT.uid++;
}
pwd.pw_uid = TT.uid;
if (toys.optflags & FLAG_G) TT.gid = xgetgrnam(TT.u_grp)->gr_gid;
else {
// Set the GID for the user, if not specified
if (toys.optflags & FLAG_S) TT.gid = CFG_TOYBOX_UID_SYS;
else TT.gid = CFG_TOYBOX_UID_USR;
if (getgrnam(pwd.pw_name)) error_exit("group '%s' in use", pwd.pw_name);
//find unused gid
while (getgrgid(TT.gid)) TT.gid++;
}
pwd.pw_gid = TT.gid;
// Create a new group for user
if (!(toys.optflags & FLAG_G)) {
char *s = xmprintf("-g%ld", pwd.pw_gid);
if (xrun((char *[]){"groupadd", *toys.optargs, s, 0}))
error_msg("addgroup -g%ld fail", pwd.pw_gid);
free(s);
}
/*add user to system
* 1. add an entry to /etc/passwd and /etcshadow file
* 2. Copy /etc/skel dir contents to use home dir
* 3. update the user passwd by running 'passwd' utility
*/
// 1. add an entry to /etc/passwd and /etc/shadow file
entry = xmprintf("%s:%s:%ld:%ld:%s:%s:%s", pwd.pw_name, pwd.pw_passwd,
pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir, pwd.pw_shell);
if (update_password("/etc/passwd", pwd.pw_name, entry)) error_exit("updating passwd file failed");
free(entry);
if (toys.optflags & FLAG_S)
entry = xmprintf("%s:!!:%u::::::", pwd.pw_name,
(unsigned)(time(NULL))/(24*60*60)); //passwd is not set initially
else entry = xmprintf("%s:!!:%u:%ld:%ld:%ld:::", pwd.pw_name,
(unsigned)(time(NULL))/(24*60*60), 0, 99999, 7); //passwd is not set initially
update_password("/etc/shadow", pwd.pw_name, entry);
free(entry);
// create home dir & copy skel dir to home
if (!(toys.optflags & (FLAG_S|FLAG_H))) {
char *skel = "/etc/skel", *p = pwd.pw_dir;
// Copy and change ownership
if (access(p, F_OK)) {
if (!access(skel, R_OK))
toys.exitval = xrun((char *[]){"cp", "-R", skel, p, 0});
else toys.exitval = xrun((char *[]){"mkdir", "-p", p, 0});
if (!toys.exitval)
toys.exitval |= xrun((char *[]){"chown", "-R",
xmprintf("%u:%u", TT.uid, TT.gid), p, 0});
wfchmodat(AT_FDCWD, p, 0700);
} else fprintf(stderr, "'%s' exists, not copying '%s'", p, skel);
}
//3. update the user passwd by running 'passwd' utility
if (!(toys.optflags & FLAG_D))
if (xrun((char *[]){"passwd", pwd.pw_name, 0})) error_exit("passwd");
if (toys.optflags & FLAG_G) {
/*add user to the existing group, invoke addgroup command */
if (xrun((char *[]){"groupadd", *toys.optargs, TT.u_grp, 0}))
error_exit("groupadd");
}
}
|