diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 16:18:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 16:18:37 +0000 |
commit | b6b00dd55e035bfbe311a527b567962ffa77ee43 (patch) | |
tree | cafc4d13785448e5a78bd40a51697ee07f07ac12 /src/newusers.c | |
parent | Adding debian version 1:4.13+dfsg1-5. (diff) | |
download | shadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.tar.xz shadow-b6b00dd55e035bfbe311a527b567962ffa77ee43.zip |
Merging upstream version 1:4.15.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/newusers.c')
-rw-r--r-- | src/newusers.c | 192 |
1 files changed, 97 insertions, 95 deletions
diff --git a/src/newusers.c b/src/newusers.c index deeb361..0705b57 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -29,6 +29,9 @@ #include <ctype.h> #include <errno.h> #include <string.h> + +#include "alloc.h" +#include "atoi/str2i.h" #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM #include "pam_defs.h" @@ -48,17 +51,19 @@ #endif /* ENABLE_SUBIDS */ #include "chkname.h" #include "shadowlog.h" +#include "string/sprintf.h" + /* * Global variables */ -const char *Prog; +static const char Prog[] = "newusers"; static bool rflg = false; /* create a system account */ #ifndef USE_PAM static /*@null@*//*@observer@*/char *crypt_method = NULL; #define cflg (NULL != crypt_method) -#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) static bool sflg = false; #endif #ifdef USE_SHA_CRYPT @@ -88,8 +93,8 @@ static bool sub_gid_locked = false; #endif /* ENABLE_SUBIDS */ /* local function prototypes */ -static void usage (int status); -static void fail_exit (int); +NORETURN static void usage (int status); +NORETURN static void fail_exit (int); static int add_group (const char *, const char *, gid_t *, gid_t); static int get_user_id (const char *, uid_t *); static int add_user (const char *, uid_t, gid_t); @@ -235,7 +240,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid) * new group, or an existing group. */ - if (get_gid (gid, &grent.gr_gid) == 0) { + if (get_gid(gid, &grent.gr_gid) == -1) { fprintf (stderr, _("%s: invalid group ID '%s'\n"), Prog, gid); @@ -245,11 +250,11 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid) /* Look in both the system database (getgrgid) and in the * internal database (gr_locate_gid), which may contain * uncommitted changes */ - if ( (getgrgid ((gid_t) grent.gr_gid) != NULL) - || (gr_locate_gid ((gid_t) grent.gr_gid) != NULL)) { + if ( (getgrgid (grent.gr_gid) != NULL) + || (gr_locate_gid (grent.gr_gid) != NULL)) { /* The user will use this ID for her * primary group */ - *ngid = (gid_t) grent.gr_gid; + *ngid = grent.gr_gid; return 0; } @@ -339,7 +344,7 @@ static int get_user_id (const char *uid, uid_t *nuid) { * caller provided, or the next available UID. */ if (isdigit (uid[0])) { - if ((get_uid (uid, nuid) == 0) || (*nuid == (uid_t)-1)) { + if ((get_uid(uid, nuid) == -1) || (*nuid == (uid_t)-1)) { fprintf (stderr, _("%s: invalid user ID '%s'\n"), Prog, uid); @@ -350,22 +355,20 @@ static int get_user_id (const char *uid, uid_t *nuid) { const struct passwd *pwd; /* local, no need for xgetpwnam */ pwd = getpwnam (uid); - if (NULL == pwd) { + if (pwd == NULL) pwd = pw_locate (uid); - } - if (NULL != pwd) { - *nuid = pwd->pw_uid; - } else { + if (pwd == NULL) { fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, uid); return -1; } + + *nuid = pwd->pw_uid; } else { - if (find_new_uid (rflg, nuid, NULL) < 0) { + if (find_new_uid (rflg, nuid, NULL) < 0) return -1; - } } } @@ -527,7 +530,7 @@ static int add_passwd (struct passwd *pwd, const char *password) } spent.sp_pwdp = cp; } - spent.sp_lstchg = (long) gettime () / SCALE; + spent.sp_lstchg = gettime () / DAY; if (0 == spent.sp_lstchg) { /* Better disable aging than requiring a password * change */ @@ -584,7 +587,7 @@ static int add_passwd (struct passwd *pwd, const char *password) */ spent.sp_pwdp = "!"; #endif - spent.sp_lstchg = (long) gettime () / SCALE; + spent.sp_lstchg = gettime () / DAY; if (0 == spent.sp_lstchg) { /* Better disable aging than requiring a password change */ spent.sp_lstchg = -1; @@ -662,21 +665,28 @@ static void process_flags (int argc, char **argv) case 's': sflg = true; bad_s = 0; + + if (!crypt_method){ + fprintf(stderr, + _("%s: Provide '--crypt-method' before number of rounds\n"), + Prog); + usage (EXIT_FAILURE); + } #if defined(USE_SHA_CRYPT) if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) - && (0 == getlong(optarg, &sha_rounds)))) { + && (-1 == str2sl(&sha_rounds, optarg)))) { bad_s = 1; } #endif /* USE_SHA_CRYPT */ #if defined(USE_BCRYPT) if (( (0 == strcmp (crypt_method, "BCRYPT")) - && (0 == getlong(optarg, &bcrypt_rounds)))) { + && (-1 == str2sl(&bcrypt_rounds, optarg)))) { bad_s = 1; } #endif /* USE_BCRYPT */ #if defined(USE_YESCRYPT) if (( (0 == strcmp (crypt_method, "YESCRYPT")) - && (0 == getlong(optarg, &yescrypt_cost)))) { + && (-1 == str2sl(&yescrypt_cost, optarg)))) { bad_s = 1; } #endif /* USE_YESCRYPT */ @@ -702,8 +712,9 @@ static void process_flags (int argc, char **argv) if (argv[optind] != NULL) { if (freopen (argv[optind], "r", stdin) == NULL) { - char buf[BUFSIZ]; - snprintf (buf, sizeof buf, "%s: %s", Prog, argv[1]); + char buf[BUFSIZ]; + + SNPRINTF(buf, "%s: %s", Prog, argv[1]); perror (buf); fail_exit (EXIT_FAILURE); } @@ -1039,7 +1050,6 @@ int main (int argc, char **argv) char *cp; const struct passwd *pw; struct passwd newpw; - int errors = 0; int line = 0; uid_t uid; gid_t gid; @@ -1050,7 +1060,6 @@ int main (int argc, char **argv) unsigned int nusers = 0; #endif /* USE_PAM */ - Prog = Basename (argv[0]); log_set_progname(Prog); log_set_logfd(stderr); @@ -1088,19 +1097,16 @@ int main (int argc, char **argv) * over 100 is allocated. The pw_gid field will be updated with that * value. */ - while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { + while (fgets (buf, sizeof buf, stdin) != NULL) { line++; cp = strrchr (buf, '\n'); - if (NULL != cp) { + if (cp == NULL && feof (stdin) == 0) { + fprintf (stderr, _("%s: line %d: line too long\n"), + Prog, line); + fail_exit (EXIT_FAILURE); + } + if (cp != NULL) { *cp = '\0'; - } else { - if (feof (stdin) == 0) { - fprintf (stderr, - _("%s: line %d: line too long\n"), - Prog, line); - errors++; - continue; - } } /* @@ -1111,39 +1117,35 @@ int main (int argc, char **argv) for (cp = buf, nfields = 0; nfields < 7; nfields++) { fields[nfields] = cp; cp = strchr (cp, ':'); - if (NULL != cp) { - *cp = '\0'; - cp++; - } else { + if (cp == NULL) break; - } + + *cp = '\0'; + cp++; } if (nfields != 6) { fprintf (stderr, _("%s: line %d: invalid line\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } /* - * First check if we have to create or update an user + * First check if we have to create or update a user */ pw = pw_locate (fields[0]); /* local, no need for xgetpwnam */ - if ( (NULL == pw) - && (getpwnam (fields[0]) != NULL)) { - fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]); - errors++; - continue; + if (NULL == pw && getpwnam(fields[0]) != NULL) { + fprintf (stderr, + _("%s: cannot update the entry of user %s (not in the passwd database)\n"), + Prog, fields[0]); + fail_exit (EXIT_FAILURE); } - if ( (NULL == pw) - && (get_user_id (fields[2], &uid) != 0)) { + if (NULL == pw && get_user_id(fields[2], &uid) != 0) { fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } /* @@ -1163,8 +1165,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: line %d: can't create group\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } /* @@ -1179,8 +1180,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } /* @@ -1192,17 +1192,22 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: line %d: user '%s' does not exist in %s\n"), Prog, line, fields[0], pw_dbname ()); - errors++; - continue; + fail_exit (EXIT_FAILURE); } newpw = *pw; #ifdef USE_PAM /* keep the list of user/password for later update by PAM */ nusers++; - lines = realloc (lines, sizeof (lines[0]) * nusers); - usernames = realloc (usernames, sizeof (usernames[0]) * nusers); - passwords = realloc (passwords, sizeof (passwords[0]) * nusers); + lines = REALLOCF(lines, nusers, int); + usernames = REALLOCF(usernames, nusers, char *); + passwords = REALLOCF(passwords, nusers, char *); + if (lines == NULL || usernames == NULL || passwords == NULL) { + fprintf (stderr, + _("%s: line %d: %s\n"), + Prog, line, strerror(errno)); + fail_exit (EXIT_FAILURE); + } lines[nusers-1] = line; usernames[nusers-1] = strdup (fields[0]); passwords[nusers-1] = strdup (fields[1]); @@ -1211,8 +1216,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: line %d: can't update password\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } if ('\0' != fields[4][0]) { newpw.pw_gecos = fields[4]; @@ -1235,21 +1239,24 @@ int main (int argc, char **argv) fprintf(stderr, _("%s: line %d: homedir must be an absolute path\n"), Prog, line); - errors++; - continue; - }; + fail_exit (EXIT_FAILURE); + } if (mkdir (newpw.pw_dir, mode) != 0) { fprintf (stderr, _("%s: line %d: mkdir %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); - } else if (chown (newpw.pw_dir, - newpw.pw_uid, - newpw.pw_gid) != 0) { + if (errno != EEXIST) { + fail_exit (EXIT_FAILURE); + } + } + if (chown(newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0) + { fprintf (stderr, _("%s: line %d: chown %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); + fail_exit (EXIT_FAILURE); } } @@ -1260,8 +1267,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: line %d: can't update entry\n"), Prog, line); - errors++; - continue; + fail_exit (EXIT_FAILURE); } #ifdef ENABLE_SUBIDS @@ -1271,17 +1277,19 @@ int main (int argc, char **argv) if (is_sub_uid && want_subuids() && !local_sub_uid_assigned(fields[0])) { uid_t sub_uid_start = 0; unsigned long sub_uid_count = 0; - if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) == 0) { - if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) { - fprintf (stderr, - _("%s: failed to prepare new %s entry\n"), - Prog, sub_uid_dbname ()); - } - } else { + if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) != 0) + { fprintf (stderr, _("%s: can't find subordinate user range\n"), Prog); - errors++; + fail_exit (EXIT_FAILURE); + } + if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) + { + fprintf (stderr, + _("%s: failed to prepare new %s entry\n"), + Prog, sub_uid_dbname ()); + fail_exit (EXIT_FAILURE); } } @@ -1291,17 +1299,17 @@ int main (int argc, char **argv) if (is_sub_gid && want_subgids() && !local_sub_gid_assigned(fields[0])) { gid_t sub_gid_start = 0; unsigned long sub_gid_count = 0; - if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) == 0) { - if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { - fprintf (stderr, - _("%s: failed to prepare new %s entry\n"), - Prog, sub_uid_dbname ()); - } - } else { + if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) != 0) { fprintf (stderr, _("%s: can't find subordinate group range\n"), Prog); - errors++; + fail_exit (EXIT_FAILURE); + } + if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { + fprintf (stderr, + _("%s: failed to prepare new %s entry\n"), + Prog, sub_uid_dbname ()); + fail_exit (EXIT_FAILURE); } } #endif /* ENABLE_SUBIDS */ @@ -1314,12 +1322,6 @@ int main (int argc, char **argv) * changes to be written out all at once, and then unlocked * afterwards. */ - if (0 != errors) { - fprintf (stderr, - _("%s: error detected, changes ignored\n"), Prog); - fail_exit (EXIT_FAILURE); - } - close_files (); nscd_flush_cache ("passwd"); @@ -1334,11 +1336,11 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, lines[i], usernames[i]); - errors++; + exit (EXIT_FAILURE); } } #endif /* USE_PAM */ - return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE); + exit (EXIT_SUCCESS); } |