hush/loginutils/adduser.c
Denis Vlasenko 73c571a5ff *: move get_sock_lsa and xwrite_str to libbb, use where appropriate
function                                             old     new   delta
get_sock_lsa                                           -      72     +72
buffer_fill_and_print                                179     196     +17
parse_expr                                           824     832      +8
read_base64                                          343     348      +5
nameval                                              202     206      +4
fbset_main                                          1694    1698      +4
expand                                              1849    1853      +4
udhcp_send_kernel_packet                             249     252      +3
udhcp_get_option                                     223     222      -1
chat_main                                           1246    1245      -1
pack_gzip                                           1661    1659      -2
doset                                                299     297      -2
bb__parsespent                                       119     117      -2
test_main                                            260     257      -3
qgravechar                                           109     106      -3
tcpudpsvd_main                                      1834    1830      -4
sysctl_display_all                                   589     580      -9
xopen_xwrite_close                                    44      33     -11
prs                                                   30      18     -12
find_main                                            418     406     -12
full_write2_str                                       25      12     -13
adduser_main                                         667     654     -13
evaltreenr                                           817     802     -15
evaltree                                             817     802     -15
tftpd_main                                           526     493     -33
ftpd_main                                           2050    1990     -60
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 7/18 up/down: 117/-211)         Total: -94 bytes
2009-03-09 00:12:37 +00:00

181 lines
4.9 KiB
C

/* vi: set sw=4 ts=4: */
/*
* adduser - add users to /etc/passwd and /etc/shadow
*
* Copyright (C) 1999 by Lineo, inc. and John Beppu
* Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
#include "libbb.h"
#define OPT_DONT_SET_PASS (1 << 4)
#define OPT_SYSTEM_ACCOUNT (1 << 5)
#define OPT_DONT_MAKE_HOME (1 << 6)
/* remix */
/* recoded such that the uid may be passed in *p */
static void passwd_study(struct passwd *p)
{
int max;
if (getpwnam(p->pw_name))
bb_error_msg_and_die("login '%s' is in use", p->pw_name);
if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
p->pw_uid = 0;
max = 999;
} else {
p->pw_uid = 1000;
max = 64999;
}
/* check for a free uid (and maybe gid) */
while (getpwuid(p->pw_uid) || (p->pw_gid == (gid_t)-1 && getgrgid(p->pw_uid))) {
p->pw_uid++;
if (p->pw_uid > max)
bb_error_msg_and_die("no free uids left");
}
if (p->pw_gid == (gid_t)-1) {
p->pw_gid = p->pw_uid; /* new gid = uid */
if (getgrnam(p->pw_name))
bb_error_msg_and_die("group name '%s' is in use", p->pw_name);
}
}
static void addgroup_wrapper(struct passwd *p)
{
char *cmd;
cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name);
system(cmd);
free(cmd);
}
static void passwd_wrapper(const char *login) NORETURN;
static void passwd_wrapper(const char *login)
{
static const char prog[] ALIGN1 = "passwd";
BB_EXECLP(prog, prog, login, NULL);
bb_error_msg_and_die("cannot execute %s, you must set password manually", prog);
}
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
static const char adduser_longopts[] ALIGN1 =
"home\0" Required_argument "h"
"gecos\0" Required_argument "g"
"shell\0" Required_argument "s"
"ingroup\0" Required_argument "G"
"disabled-password\0" No_argument "D"
"empty-password\0" No_argument "D"
"system\0" No_argument "S"
"no-create-home\0" No_argument "H"
;
#endif
/*
* adduser will take a login_name as its first parameter.
* home, shell, gecos:
* can be customized via command-line parameters.
*/
int adduser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int adduser_main(int argc UNUSED_PARAM, char **argv)
{
struct passwd pw;
const char *usegroup = NULL;
FILE *file;
int fd;
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
applet_long_options = adduser_longopts;
#endif
/* got root? */
if (geteuid()) {
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
}
pw.pw_gecos = (char *)"Linux User,,,";
pw.pw_shell = (char *)DEFAULT_SHELL;
pw.pw_dir = NULL;
/* exactly one non-option arg */
opt_complementary = "=1";
getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
argv += optind;
/* fill in the passwd struct */
pw.pw_name = argv[0];
die_if_bad_username(pw.pw_name);
if (!pw.pw_dir) {
/* create string for $HOME if not specified already */
pw.pw_dir = xasprintf("/home/%s", argv[0]);
}
pw.pw_passwd = (char *)"x";
pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */
/* make sure everything is kosher and setup uid && maybe gid */
passwd_study(&pw);
/* add to passwd */
file = xfopen(bb_path_passwd_file, "a");
//fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
if (putpwent(&pw, file) != 0) {
bb_perror_nomsg_and_die();
}
/* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
* We will exec passwd, files must be flushed & closed before that! */
fclose(file);
#if ENABLE_FEATURE_SHADOWPASSWDS
/* add to shadow if necessary */
/* fopen(..., "a"); would create shadow file, which is wrong.
* If shadow file doesn't exist, admin probably does not want it */
fd = open_or_warn(bb_path_shadow_file, O_WRONLY | O_APPEND);
if (fd >= 0) {
char *s = xasprintf("%s:!:%u:0:99999:7:::\n",
pw.pw_name, /* username */
(unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
/*0,*/ /* sp->sp_min */
/*99999,*/ /* sp->sp_max */
/*7*/ /* sp->sp_warn */
);
xwrite_str(fd, s);
close(fd);
}
#endif
/* add to group */
/* addgroup should be responsible for dealing w/ gshadow */
/* if using a pre-existing group, don't create one */
if (!usegroup)
addgroup_wrapper(&pw);
/* Clear the umask for this process so it doesn't
* screw up the permissions on the mkdir and chown. */
umask(0);
if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
/* Set the owner and group so it is owned by the new user,
then fix up the permissions to 2755. Can't do it before
since chown will clear the setgid bit */
if (mkdir(pw.pw_dir, 0755)
|| chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
|| chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
) {
bb_simple_perror_msg(pw.pw_dir);
}
}
if (!(option_mask32 & OPT_DONT_SET_PASS)) {
/* interactively set passwd */
passwd_wrapper(pw.pw_name);
}
return 0;
}