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