* NEWS, src/chpasswd.c: Added support for changing the passwords

with PAM.
	* src/chpasswd.c: Split the usage string in smaller parts to
	allows enabling single parts.
	* src/chpasswd.c: Do not set a global lock on the password files.
	This is done by PAM each time a password is updated.
This commit is contained in:
nekral-guest 2009-04-28 21:45:38 +00:00
parent 72fa8afa07
commit d7d0b06a41
3 changed files with 118 additions and 40 deletions

View File

@ -1,3 +1,12 @@
2009-04-28 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, src/chpasswd.c: Added support for changing the passwords
with PAM.
* src/chpasswd.c: Split the usage string in smaller parts to
allows enabling single parts.
* src/chpasswd.c: Do not set a global lock on the password files.
This is done by PAM each time a password is updated.
2009-04-28 Nicolas François <nicolas.francois@centraliens.net> 2009-04-28 Nicolas François <nicolas.francois@centraliens.net>
* lib/defines.h: Include <utmpx.h> and <utmp.h> to define * lib/defines.h: Include <utmpx.h> and <utmp.h> to define

5
NEWS
View File

@ -13,6 +13,11 @@ shadow-4.1.3.1 -> shadow-4.1.3.2 UNRELEASED
user to update his authentication token if needed. user to update his authentication token if needed.
- lastlog - lastlog
* Fix regression causing empty reports. * Fix regression causing empty reports.
- chpasswd
* Change the passwords using PAM. This permits to define the password
policy in a central place. The -c/--crypt-method, -e/--encrypted,
-m/--md5, -s/--sha-rounds are no more supported on PAM enabled
systems.
*** translation *** translation
- Updated Korean translation - Updated Korean translation

View File

@ -39,11 +39,9 @@
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM #ifdef USE_PAM
#include "pam_defs.h" #include "pam_defs.h"
#endif /* USE_PAM */ #endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
#include "defines.h" #include "defines.h"
#include "exitcodes.h" #include "exitcodes.h"
#include "nscd.h" #include "nscd.h"
@ -54,21 +52,23 @@
* Global variables * Global variables
*/ */
char *Prog; char *Prog;
#ifndef USE_PAM
static bool cflg = false; static bool cflg = false;
static bool eflg = false; static bool eflg = false;
static bool md5flg = false; static bool md5flg = false;
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
static bool sflg = false; static bool sflg = false;
#endif #endif /* USE_SHA_CRYPT */
static const char *crypt_method = NULL; static const char *crypt_method = NULL;
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
static long sha_rounds = 5000; static long sha_rounds = 5000;
#endif #endif /* USE_SHA_CRYPT */
static bool is_shadow_pwd; static bool is_shadow_pwd;
static bool pw_locked = false; static bool pw_locked = false;
static bool spw_locked = false; static bool spw_locked = false;
#endif /* !USE_PAM */
/* local function prototypes */ /* local function prototypes */
static void fail_exit (int code); static void fail_exit (int code);
@ -76,14 +76,17 @@ static void usage (void);
static void process_flags (int argc, char **argv); static void process_flags (int argc, char **argv);
static void check_flags (void); static void check_flags (void);
static void check_perms (void); static void check_perms (void);
#ifndef USE_PAM
static void open_files (void); static void open_files (void);
static void close_files (void); static void close_files (void);
#endif /* !USE_PAM */
/* /*
* fail_exit - exit with a failure code after unlocking the files * fail_exit - exit with a failure code after unlocking the files
*/ */
static void fail_exit (int code) static void fail_exit (int code)
{ {
#ifndef USE_PAM
if (pw_locked) { if (pw_locked) {
if (pw_unlock () == 0) { if (pw_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
@ -99,6 +102,7 @@ static void fail_exit (int code)
/* continue */ /* continue */
} }
} }
#endif /* !USE_PAM */
exit (code); exit (code);
} }
@ -108,25 +112,35 @@ static void fail_exit (int code)
*/ */
static void usage (void) static void usage (void)
{ {
fprintf (stderr, _("Usage: %s [options]\n" (void) fprintf (stderr,
"\n" _("Usage: %s [options]\n"
"Options:\n" "\n"
" -c, --crypt-method the crypt method (one of %s)\n" "Options:\n"),
" -e, --encrypted supplied passwords are encrypted\n" Prog);
" -h, --help display this help message and exit\n" #ifndef USE_PAM
" -m, --md5 encrypt the clear text password using\n" (void) fprintf (stderr,
" the MD5 algorithm\n" _(" -c, --crypt-method the crypt method (one of %s)\n"),
"%s"
"\n"),
Prog,
#ifndef USE_SHA_CRYPT #ifndef USE_SHA_CRYPT
"NONE DES MD5", "" "NONE DES MD5"
#else #else /* USE_SHA_CRYPT */
"NONE DES MD5 SHA256 SHA512", "NONE DES MD5 SHA256 SHA512"
_(" -s, --sha-rounds number of SHA rounds for the SHA*\n" #endif /* USE_SHA_CRYPT */
" crypt algorithms\n") );
#endif (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), stderr);
); #endif /* !USE_PAM */
(void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
#ifndef USE_PAM
(void) fputs (_(" -m, --md5 encrypt the clear text password using\n"
" the MD5 algorithm\n"),
stderr);
#ifdef USE_SHA_CRYPT
(void) fputs (_(" -s, --sha-rounds number of SHA rounds for the SHA*\n"
" crypt algorithms\n"),
stderr);
#endif /* USE_SHA_CRYPT */
#endif /* !USE_PAM */
(void) fputs ("\n", stderr);
exit (E_USAGE); exit (E_USAGE);
} }
@ -140,24 +154,34 @@ static void process_flags (int argc, char **argv)
int option_index = 0; int option_index = 0;
int c; int c;
static struct option long_options[] = { static struct option long_options[] = {
#ifndef USE_PAM
{"crypt-method", required_argument, NULL, 'c'}, {"crypt-method", required_argument, NULL, 'c'},
{"encrypted", no_argument, NULL, 'e'}, {"encrypted", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'}, {"md5", no_argument, NULL, 'm'},
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
{"sha-rounds", required_argument, NULL, 's'}, {"sha-rounds", required_argument, NULL, 's'},
#endif #endif /* USE_SHA_CRYPT */
#endif /* !USE_PAM */
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = getopt_long (argc, argv, while ((c = getopt_long (argc, argv,
#ifdef USE_SHA_CRYPT #ifndef USE_PAM
# ifdef USE_SHA_CRYPT
"c:ehms:", "c:ehms:",
#else # else /* !USE_SHA_CRYPT */
"c:ehm", "c:ehm",
#endif # endif /* !USE_SHA_CRYPT */
#else
"h",
#endif /* !USE_PAM */
long_options, &option_index)) != -1) { long_options, &option_index)) != -1) {
switch (c) { switch (c) {
case 'h':
usage ();
break;
#ifndef USE_PAM
case 'c': case 'c':
cflg = true; cflg = true;
crypt_method = optarg; crypt_method = optarg;
@ -165,9 +189,6 @@ static void process_flags (int argc, char **argv)
case 'e': case 'e':
eflg = true; eflg = true;
break; break;
case 'h':
usage ();
break;
case 'm': case 'm':
md5flg = true; md5flg = true;
break; break;
@ -181,10 +202,8 @@ static void process_flags (int argc, char **argv)
usage (); usage ();
} }
break; break;
#endif #endif /* USE_SHA_CRYPT */
case 0: #endif /* !USE_PAM */
/* long option */
break;
default: default:
usage (); usage ();
break; break;
@ -202,6 +221,7 @@ static void process_flags (int argc, char **argv)
*/ */
static void check_flags (void) static void check_flags (void)
{ {
#ifndef USE_PAM
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
if (sflg && !cflg) { if (sflg && !cflg) {
fprintf (stderr, fprintf (stderr,
@ -234,6 +254,7 @@ static void check_flags (void)
usage (); usage ();
} }
} }
#endif /* USE_PAM */
} }
/* /*
@ -248,8 +269,8 @@ static void check_flags (void)
*/ */
static void check_perms (void) static void check_perms (void)
{ {
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM #ifdef USE_PAM
#ifdef ACCT_TOOLS_SETUID
pam_handle_t *pamh = NULL; pam_handle_t *pamh = NULL;
int retval; int retval;
struct passwd *pampw; struct passwd *pampw;
@ -279,10 +300,11 @@ static void check_perms (void)
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog); fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
exit (1); exit (1);
} }
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */ #endif /* ACCT_TOOLS_SETUID */
#endif /* USE_PAM */
} }
#ifndef USE_PAM
/* /*
* open_files - lock and open the password databases * open_files - lock and open the password databases
*/ */
@ -358,6 +380,7 @@ static void close_files (void)
} }
pw_locked = false; pw_locked = false;
} }
#endif
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
@ -366,11 +389,14 @@ int main (int argc, char **argv)
char *newpwd; char *newpwd;
char *cp; char *cp;
#ifndef USE_PAM
const struct spwd *sp; const struct spwd *sp;
struct spwd newsp; struct spwd newsp;
const struct passwd *pw; const struct passwd *pw;
struct passwd newpw; struct passwd newpw;
#endif /* !USE_PAM */
int errors = 0; int errors = 0;
int line = 0; int line = 0;
@ -386,9 +412,11 @@ int main (int argc, char **argv)
check_perms (); check_perms ();
#ifndef USE_PAM
is_shadow_pwd = spw_file_present (); is_shadow_pwd = spw_file_present ();
open_files (); open_files ();
#endif
/* /*
* Read each line, separating the user name from the password. The * Read each line, separating the user name from the password. The
@ -404,7 +432,8 @@ int main (int argc, char **argv)
if (NULL != cp) { if (NULL != cp) {
*cp = '\0'; *cp = '\0';
} else { } else {
fprintf (stderr, _("%s: line %d: line too long\n"), fprintf (stderr,
_("%s: line %d: line too long\n"),
Prog, line); Prog, line);
errors++; errors++;
continue; continue;
@ -432,9 +461,41 @@ int main (int argc, char **argv)
continue; continue;
} }
newpwd = cp; newpwd = cp;
if (!eflg &&
(NULL == crypt_method || #ifdef USE_PAM
0 != strcmp(crypt_method, "NONE"))) { pam_handle_t *pamh = NULL;
int ret;
ret = pam_start ("chpasswd", name, &non_interactive_pam_conv, &pamh);
if (ret != PAM_SUCCESS) {
fprintf (stderr,
_("chpasswd: (user %s) pam_start failure %d\n"),
name, ret);
fprintf (stderr,
_("chpasswd: (user %s) password unchanged\n"),
name);
errors++;
continue;
}
non_interactive_password = newpwd;
ret = pam_chauthtok (pamh, 0);
if (ret != PAM_SUCCESS) {
fprintf (stderr, _("chpasswd: (user %s) pam_chauthtok() failed, error:\n"
" %s\n"),
name, pam_strerror (pamh, ret));
fprintf (stderr,
_("chpasswd: (user %s) password unchanged\n"),
name);
errors++;
continue;
}
(void) pam_end (pamh, PAM_SUCCESS);
#else /* !USE_PAM */
if ( !eflg
&& ((NULL == crypt_method)
(0 != strcmp (crypt_method, "NONE")))) {
void *arg = NULL; void *arg = NULL;
if (md5flg) { if (md5flg) {
crypt_method = "MD5"; crypt_method = "MD5";
@ -510,6 +571,7 @@ int main (int argc, char **argv)
continue; continue;
} }
} }
#endif /* !USE_PAM */
} }
/* /*
@ -525,7 +587,9 @@ int main (int argc, char **argv)
fail_exit (1); fail_exit (1);
} }
#ifndef USE_PAM
close_files (); close_files ();
#endif
nscd_flush_cache ("passwd"); nscd_flush_cache ("passwd");