summaryrefslogtreecommitdiffstats
path: root/src/chpasswd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/chpasswd.c')
-rw-r--r--src/chpasswd.c51
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 */