summaryrefslogtreecommitdiff
path: root/src/useradd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/useradd.c')
-rw-r--r--src/useradd.c207
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;
}