diff options
Diffstat (limited to 'src/useradd.c')
-rw-r--r-- | src/useradd.c | 207 |
1 files changed, 118 insertions, 89 deletions
diff --git a/src/useradd.c b/src/useradd.c index 127177e2..456b9de5 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -1,33 +1,10 @@ /* - * Copyright (c) 1991 - 1994, Julianne Frances Haugh - * Copyright (c) 1996 - 2000, Marek Michałkiewicz - * Copyright (c) 2000 - 2006, Tomasz Kłoczko - * Copyright (c) 2007 - 2012, Nicolas François - * All rights reserved. + * SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh + * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz + * SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko + * SPDX-FileCopyrightText: 2007 - 2012, Nicolas François * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the copyright holders or contributors may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include <config.h> @@ -41,6 +18,7 @@ #include <getopt.h> #include <grp.h> #include <lastlog.h> +#include <libgen.h> #include <pwd.h> #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM @@ -78,6 +56,7 @@ #ifdef WITH_TCB #include "tcbfuncs.h" #endif +#include "shadowlog.h" #ifndef SKEL_DIR #define SKEL_DIR "/etc/skel" @@ -96,7 +75,6 @@ * Global variables */ const char *Prog; -FILE *shadow_logfd = NULL; /* * These defaults are used if there is no defaults file. @@ -107,6 +85,7 @@ static const char *def_home = "/home"; static const char *def_shell = "/bin/bash"; static const char *def_template = SKEL_DIR; static const char *def_create_mail_spool = "yes"; +static const char *def_log_init = "yes"; static long def_inactive = -1; static const char *def_expire = ""; @@ -142,9 +121,7 @@ static bool is_sub_gid = false; static bool sub_uid_locked = false; static bool sub_gid_locked = false; static uid_t sub_uid_start; /* New subordinate uid range */ -static unsigned long sub_uid_count; static gid_t sub_gid_start; /* New subordinate gid range */ -static unsigned long sub_gid_count; #endif /* ENABLE_SUBIDS */ static bool pw_locked = false; static bool gr_locked = false; @@ -209,6 +186,7 @@ static bool home_added = false; #define DEXPIRE "EXPIRE=" #define DSKEL "SKEL=" #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL=" +#define DLOG_INIT "LOG_INIT=" /* local function prototypes */ static void fail_exit (int); @@ -234,7 +212,7 @@ static void open_shadow (void); static void faillog_reset (uid_t); static void lastlog_reset (uid_t); static void tallylog_reset (const char *); -static void usr_update (void); +static void usr_update (unsigned long subuid_count, unsigned long subgid_count); static void create_home (void); static void create_mail (void); static void check_uid_range(int rflg, uid_t user_id); @@ -362,7 +340,7 @@ static void get_defaults (void) char buf[1024]; char *cp; - if(prefix[0]) { + if (prefix[0]) { size_t len; int wlen; @@ -415,7 +393,6 @@ static void get_defaults (void) } else { def_group = grp->gr_gid; def_gname = xstrdup (grp->gr_name); - gr_free(grp); } } @@ -463,8 +440,8 @@ static void get_defaults (void) if ('\0' == *cp) { cp = SKEL_DIR; /* XXX warning: const */ } - - if(prefix[0]) { + + if (prefix[0]) { size_t len; int wlen; char* _def_template; /* avoid const warning */ @@ -490,10 +467,20 @@ static void get_defaults (void) def_create_mail_spool = xstrdup (cp); } + + /* + * By default do we add the user to the lastlog and faillog databases ? + */ + else if (MATCH (buf, DLOG_INIT)) { + if (*cp == '\0') { + cp = def_log_init; /* XXX warning: const */ + } + def_log_init = xstrdup (cp); + } } (void) fclose (fp); getdef_err: - if(prefix[0]) { + if (prefix[0]) { free(default_file); } } @@ -513,6 +500,7 @@ static void show_defaults (void) printf ("SHELL=%s\n", def_shell); printf ("SKEL=%s\n", def_template); printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); + printf ("LOG_INIT=%s\n", def_log_init); } /* @@ -528,6 +516,7 @@ static int set_defaults (void) FILE *ofp; char buf[1024]; char *new_file = NULL; + char *new_file_dup = NULL; char *default_file = USER_DEFAULTS_FILE; char *cp; int ofd; @@ -539,6 +528,7 @@ static int set_defaults (void) bool out_shell = false; bool out_skel = false; bool out_create_mail_spool = false; + bool out_log_init = false; size_t len; int ret = -1; @@ -554,7 +544,7 @@ static int set_defaults (void) wlen = snprintf(new_file, len, "%s%s%s", prefix, prefix[0]?"/":"", NEW_USER_FILE); assert (wlen <= (int) len -1); - if(prefix[0]) { + if (prefix[0]) { len = strlen(prefix) + strlen(USER_DEFAULTS_FILE) + 2; default_file = malloc(len); if (default_file == NULL) { @@ -567,6 +557,24 @@ static int set_defaults (void) assert (wlen == (int) len -1); } + new_file_dup = strdup(new_file); + if (new_file_dup == NULL) { + fprintf (stderr, + _("%s: cannot create directory for defaults file\n"), + Prog); + goto setdef_err; + } + + ret = mkdir(dirname(new_file_dup), 0755); + if (-1 == ret && EEXIST != errno) { + fprintf (stderr, + _("%s: cannot create directory for defaults file\n"), + Prog); + free(new_file_dup); + goto setdef_err; + } + free(new_file_dup); + /* * Create a temporary file to copy the new output to. */ @@ -638,6 +646,12 @@ static int set_defaults (void) DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool); out_create_mail_spool = true; + } else if (!out_log_init + && MATCH (buf, DLOG_INIT)) { + fprintf (ofp, + DLOG_INIT "%s\n", + def_log_init); + out_log_init = true; } else fprintf (ofp, "%s\n", buf); } @@ -664,7 +678,8 @@ static int set_defaults (void) if (!out_create_mail_spool) fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool); - + if (!out_log_init) + fprintf (ofp, DLOG_INIT "%s\n", def_log_init); /* * Flush and close the file. Check for errors to make certain * the new file is intact. @@ -710,14 +725,14 @@ static int set_defaults (void) #endif SYSLOG ((LOG_INFO, "useradd defaults: GROUP=%u, HOME=%s, SHELL=%s, INACTIVE=%ld, " - "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s", + "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s, LOG_INIT=%s", (unsigned int) def_group, def_home, def_shell, def_inactive, def_expire, def_template, - def_create_mail_spool)); + def_create_mail_spool, def_log_init)); ret = 0; setdef_err: free(new_file); - if(prefix[0]) { + if (prefix[0]) { free(default_file); } @@ -1044,7 +1059,7 @@ static void grp_update (void) fail_exit (E_GRP_UPDATE); /* XXX */ } - /* + /* * Add the username to the list of group members and * update the group entry to reflect the change. */ @@ -1119,7 +1134,7 @@ static void grp_update (void) fail_exit (E_GRP_UPDATE); /* XXX */ } - /* + /* * Add the username to the list of group members and * update the group entry to reflect the change. */ @@ -1529,7 +1544,7 @@ static void process_flags (int argc, char **argv) user_home = uh; } - if(prefix[0]) { + if (prefix[0]) { size_t len = strlen(prefix) + strlen(user_home) + 2; int wlen; char* _prefix_user_home; /* to avoid const warning */ @@ -1557,6 +1572,14 @@ static void process_flags (int argc, char **argv) create_mail_spool = def_create_mail_spool; + if (!lflg) { + /* If we are missing the flag lflg aka -l, check the defaults + * file to see if we need to disable it as a default*/ + if (strcmp (def_log_init, "no") == 0) { + lflg = true; + } + } + if (!rflg) { /* for system accounts defaults are ignored and we * do not create a home dir */ @@ -2084,7 +2107,7 @@ static void tallylog_reset (const char *user_name) * usr_update() creates the password file entries for this user * and will update the group entries if required. */ -static void usr_update (void) +static void usr_update (unsigned long subuid_count, unsigned long subgid_count) { struct passwd pwent; struct spwd spent; @@ -2147,14 +2170,14 @@ static void usr_update (void) } #ifdef ENABLE_SUBIDS if (is_sub_uid && - (sub_uid_add(user_name, sub_uid_start, sub_uid_count) == 0)) { + (sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) { fprintf (stderr, _("%s: failed to prepare the new %s entry\n"), Prog, sub_uid_dbname ()); fail_exit (E_SUB_UID_UPDATE); } if (is_sub_gid && - (sub_gid_add(user_name, sub_gid_start, sub_gid_count) == 0)) { + (sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) { fprintf (stderr, _("%s: failed to prepare the new %s entry\n"), Prog, sub_uid_dbname ()); @@ -2322,11 +2345,16 @@ static void create_mail (void) mode_t mode; spool = getdef_str ("MAIL_DIR"); +#ifdef MAIL_SPOOL_DIR + if ((NULL == spool) && (getdef_str ("MAIL_FILE") == NULL)) { + spool = MAIL_SPOOL_DIR; + } +#endif /* MAIL_SPOOL_DIR */ if (NULL == spool) { - spool = "/var/mail"; + return; } file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 2); - if(prefix[0]) + if (prefix[0]) sprintf (file, "%s/%s/%s", prefix, spool, user_name); else sprintf (file, "%s/%s", spool, user_name); @@ -2380,18 +2408,18 @@ static void check_uid_range(int rflg, uid_t user_id) { uid_t uid_min ; uid_t uid_max ; - if(rflg){ + if (rflg) { uid_min = (uid_t)getdef_ulong("SYS_UID_MIN",101UL); uid_max = (uid_t)getdef_ulong("SYS_UID_MAX",getdef_ulong("UID_MIN",1000UL)-1); - if(uid_min <= uid_max){ - if(user_id < uid_min || user_id >uid_max) + if (uid_min <= uid_max) { + if (user_id < uid_min || user_id >uid_max) fprintf(stderr, _("%s warning: %s's uid %d outside of the SYS_UID_MIN %d and SYS_UID_MAX %d range.\n"), Prog, user_name, user_id, uid_min, uid_max); } }else{ uid_min = (uid_t)getdef_ulong("UID_MIN", 1000UL); uid_max = (uid_t)getdef_ulong("UID_MAX", 6000UL); - if(uid_min <= uid_max){ - if(user_id < uid_min || user_id >uid_max) + if (uid_min <= uid_max) { + if (user_id < uid_min || user_id >uid_max) fprintf(stderr, _("%s warning: %s's uid %d outside of the UID_MIN %d and UID_MAX %d range.\n"), Prog, user_name, user_id, uid_min, uid_max); } } @@ -2412,15 +2440,16 @@ int main (int argc, char **argv) #ifdef ENABLE_SUBIDS uid_t uid_min; uid_t uid_max; - unsigned long subuid_count; - unsigned long subgid_count; #endif + unsigned long subuid_count = 0; + unsigned long subgid_count = 0; /* * Get my name so that I can use it to report errors. */ Prog = Basename (argv[0]); - shadow_logfd = stderr; + log_set_progname(Prog); + log_set_logfd(stderr); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); @@ -2473,14 +2502,14 @@ int main (int argc, char **argv) { struct passwd *pampw; pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */ - if (pampw == NULL) { + if (pampw == NULL && getuid ()) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); fail_exit (1); } - retval = pam_start ("useradd", pampw->pw_name, &conv, &pamh); + retval = pam_start ("useradd", pampw?pampw->pw_name:"root", &conv, &pamh); } if (PAM_SUCCESS == retval) { @@ -2589,7 +2618,7 @@ int main (int argc, char **argv) } } - if(uflg) + if (uflg) check_uid_range(rflg,user_id); #ifdef WITH_TCB if (getdef_bool ("USE_TCB")) { @@ -2616,16 +2645,16 @@ int main (int argc, char **argv) } #ifdef ENABLE_SUBIDS - if (is_sub_uid && sub_uid_count != 0) { - if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) < 0) { + if (is_sub_uid && subuid_count != 0) { + if (find_new_sub_uids(&sub_uid_start, &subuid_count) < 0) { fprintf (stderr, _("%s: can't create subordinate user IDs\n"), Prog); fail_exit(E_SUB_UID_UPDATE); } } - if (is_sub_gid && sub_gid_count != 0) { - if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) < 0) { + if (is_sub_gid && subgid_count != 0) { + if (find_new_sub_gids(&sub_gid_start, &subgid_count) < 0) { fprintf (stderr, _("%s: can't create subordinate group IDs\n"), Prog); @@ -2634,29 +2663,14 @@ int main (int argc, char **argv) } #endif /* ENABLE_SUBIDS */ - usr_update (); - - if (mflg) { - create_home (); - if (home_added) { - copy_tree (def_template, prefix_user_home, false, false, - (uid_t)-1, user_id, (gid_t)-1, user_gid); - } else { - fprintf (stderr, - _("%s: warning: the home directory %s already exists.\n" - "%s: Not copying any file from skel directory into it.\n"), - Prog, user_home, Prog); - } - - } - - /* Do not create mail directory for system accounts */ - if (!rflg) { - create_mail (); - } + usr_update (subuid_count, subgid_count); close_files (); + nscd_flush_cache ("passwd"); + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); + /* * tallylog_reset needs to be able to lookup * a valid existing user name, @@ -2682,15 +2696,30 @@ int main (int argc, char **argv) } #endif /* WITH_SELINUX */ + if (mflg) { + create_home (); + if (home_added) { + copy_tree (def_template, prefix_user_home, false, true, + (uid_t)-1, user_id, (gid_t)-1, user_gid); + } else { + fprintf (stderr, + _("%s: warning: the home directory %s already exists.\n" + "%s: Not copying any file from skel directory into it.\n"), + Prog, user_home, Prog); + } + + } + + /* Do not create mail directory for system accounts */ + if (!rflg) { + create_mail (); + } + if (run_parts ("/etc/shadow-maint/useradd-post.d", (char*)user_name, "useradd")) { exit(1); } - nscd_flush_cache ("passwd"); - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); - return E_SUCCESS; } |