diff options
Diffstat (limited to 'src/chpasswd.c')
-rw-r--r-- | src/chpasswd.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/src/chpasswd.c b/src/chpasswd.c index 48d5178..79880f5 100644 --- a/src/chpasswd.c +++ b/src/chpasswd.c @@ -16,9 +16,11 @@ #include <pwd.h> #include <stdio.h> #include <stdlib.h> + #ifdef USE_PAM #include "pam_defs.h" #endif /* USE_PAM */ +#include "atoi/str2i.h" #include "defines.h" #include "nscd.h" #include "sssd.h" @@ -30,12 +32,13 @@ #include "exitcodes.h" #include "shadowlog.h" + #define IS_CRYPT_METHOD(str) ((crypt_method != NULL && strcmp(crypt_method, str) == 0) ? true : false) /* * Global variables */ -const char *Prog; +static const char Prog[] = "chpasswd"; static bool eflg = false; static bool md5flg = false; #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) @@ -54,13 +57,15 @@ static long bcrypt_rounds = 13; static long yescrypt_cost = 5; #endif +static const char *prefix = ""; + static bool is_shadow_pwd; static bool pw_locked = false; static bool spw_locked = false; /* local function prototypes */ -static void fail_exit (int code); -static /*@noreturn@*/void usage (int status); +NORETURN static void fail_exit (int code); +NORETURN static void usage (int status); static void process_flags (int argc, char **argv); static void check_flags (void); static void check_perms (void); @@ -94,7 +99,9 @@ static void fail_exit (int code) /* * usage - display usage message and exit */ -static /*@noreturn@*/void usage (int status) +NORETURN +static void +usage (int status) { FILE *usageout = (E_SUCCESS != status) ? stderr : stdout; (void) fprintf (usageout, @@ -121,6 +128,7 @@ static /*@noreturn@*/void usage (int status) " the MD5 algorithm\n"), usageout); (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); + (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout); #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" " or YESCRYPT crypt algorithms\n"), @@ -148,6 +156,7 @@ static void process_flags (int argc, char **argv) {"help", no_argument, NULL, 'h'}, {"md5", no_argument, NULL, 'm'}, {"root", required_argument, NULL, 'R'}, + {"prefix", required_argument, NULL, 'P'}, #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) {"sha-rounds", required_argument, NULL, 's'}, #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ @@ -156,9 +165,9 @@ static void process_flags (int argc, char **argv) while ((c = getopt_long (argc, argv, #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:ehmR:s:", + "c:ehmR:P:s:", #else - "c:ehmR:", + "c:ehmR:P:", #endif long_options, NULL)) != -1) { switch (c) { @@ -176,25 +185,27 @@ static void process_flags (int argc, char **argv) break; case 'R': /* no-op, handled in process_root_flag () */ break; + case 'P': /* no-op, handled in process_prefix_flag () */ + break; #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': sflg = true; bad_s = 0; #if defined(USE_SHA_CRYPT) if ((IS_CRYPT_METHOD("SHA256") || IS_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 (IS_CRYPT_METHOD("BCRYPT") - && (0 == getlong(optarg, &bcrypt_rounds))) { + && (-1 == str2sl(&bcrypt_rounds, optarg))) { bad_s = 1; } #endif /* USE_BCRYPT */ #if defined(USE_YESCRYPT) if (IS_CRYPT_METHOD("YESCRYPT") - && (0 == getlong(optarg, &yescrypt_cost))) { + && (-1 == str2sl(&yescrypt_cost, optarg))) { bad_s = 1; } #endif /* USE_YESCRYPT */ @@ -294,7 +305,7 @@ static void check_perms (void) exit (1); } - retval = pam_start ("chpasswd", pampw->pw_name, &conv, &pamh); + retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); if (PAM_SUCCESS == retval) { retval = pam_authenticate (pamh, 0); @@ -442,7 +453,6 @@ int main (int argc, char **argv) int errors = 0; int line = 0; - Prog = Basename (argv[0]); log_set_progname(Prog); log_set_logfd(stderr); @@ -450,18 +460,25 @@ int main (int argc, char **argv) (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); +#ifdef WITH_SELINUX + if (check_selinux_permit ("passwd") != 0) { + return (E_NOPERM); + } +#endif /* WITH_SELINUX */ + process_flags (argc, argv); salt = get_salt(); process_root_flag ("-R", argc, argv); + prefix = process_prefix_flag ("-P", argc, argv); #ifdef USE_PAM - if (md5flg || eflg || cflg) { + if (md5flg || eflg || cflg || prefix[0]) { use_pam = false; } #endif /* USE_PAM */ - OPENLOG ("chpasswd"); + OPENLOG (Prog); check_perms (); @@ -482,7 +499,7 @@ int main (int argc, char **argv) * last change date is set in the age only if aging information is * present. */ - while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { + while (fgets (buf, sizeof buf, stdin) != NULL) { line++; cp = strrchr (buf, '\n'); if (NULL != cp) { @@ -491,7 +508,7 @@ int main (int argc, char **argv) if (feof (stdin) == 0) { // Drop all remaining characters on this line. - while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { + while (fgets (buf, sizeof buf, stdin) != NULL) { cp = strchr (buf, '\n'); if (cp != NULL) { break; @@ -531,7 +548,7 @@ int main (int argc, char **argv) #ifdef USE_PAM if (use_pam) { - if (do_pam_passwd_non_interactive ("chpasswd", name, newpwd) != 0) { + if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, line, name); @@ -606,7 +623,7 @@ int main (int argc, char **argv) if (NULL != sp) { newsp = *sp; newsp.sp_pwdp = cp; - newsp.sp_lstchg = (long) gettime () / SCALE; + newsp.sp_lstchg = gettime () / DAY; if (0 == newsp.sp_lstchg) { /* Better disable aging than requiring a * password change */ |