+2010-03-25 Nicolas François <nicolas.francois@centraliens.net>
+
+ * NEWS, src/chpasswd.c, man/chpasswd.8.xml, man/login.defs.5.xml:
+ PAM enabled versions: restore the -e option to allow restoring
+ passwords without knowing those passwords. Restore together the -m
+ and -c options.
+
2010-03-23 Nicolas François <nicolas.francois@centraliens.net>
* src/su.c, src/vipw.c, src/newgrp.c: When the child is
* initial support for tcb (http://openwall.com/tcb/) for useradd,
userdel, usermod, chage, pwck, vipw.
+-chpasswd
+ * PAM enabled versions: restore the -e option to allow restoring
+ passwords without knowing those passwords. Restore together the -m
+ and -c options. (These options were removed in shadow-4.1.4 on PAM
+ enabled versions)
- faillog
* The -l, -m, -r, -t options only act on the existing users, unless -a is
specified.
<emphasis remap='I'>user_name</emphasis>:<emphasis
remap='I'>password</emphasis>
</para>
- <refsect2 condition="no_pam">
<para>
- By default the supplied password must be in clear-text, and is
+ By default the passwords must be supplied in clear-text, and are
encrypted by <command>chpasswd</command>.
Also the password age will be updated, if present.
</para>
- <para>
+ <para condition="no_pam">
The default encryption algorithm can be defined for the system with
- the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>,
- and can be overwiten with the <option>-e</option>,
- <option>-m</option>, or <option>-c</option> options.
+ the <option>ENCRYPT_METHOD</option> or
+ <option>MD5_CRYPT_ENAB</option> variables of
+ <filename>/etc/login.defs</filename>, and can be overwitten with the
+ <option>-e</option>, <option>-m</option>, or <option>-c</option>
+ options.
+ </para>
+ <para condition="pam">
+ By default, passwords are encrypted by PAM, but (even if not
+ recommended) you can select a different encryption method with the
+ <option>-e</option>, <option>-m</option>, or <option>-c</option>
+ options.
+ </para>
+ <para>
+ <phrase condition="pam">Except when PAM is used to encrypt the
+ passwords,</phrase> <command>chpasswd</command> first updates all the
+ passwords in memory, and then commits all the changes to disk if no
+ errors occured for any user.
+ </para>
+ <para condition="pam">
+ When PAM is used to encrypt the passwords (and update the passwords in
+ the system database) then if a password cannot be updated
+ <command>chpasswd</command> continues updating the passwords of the
+ next users, and will return an error code on exit.
</para>
- <para>
- <command>chpasswd</command> first update the password in memory,
- and then commit all the changes to disk if no errors occured for
- any users.
- </para>
- </refsect2>
- <refsect2 condition="pam">
- <para>
- The supplied passwords must be in clear-text.
- </para>
- <para>
- PAM is used to update the password in the system database
- according to the PAM chpasswd configuration.
- </para>
- <para>
- When <command>chpasswd</command> fails to update a password, it
- continues updating the passwords of the next users, and will
- return an error code on exit.
- </para>
- </refsect2>
<para>
This command is intended to be used in a large system environment
where many accounts are created at a single time.
The options which apply to the <command>chpasswd</command> command
are:
</para>
- <variablelist remap='IP' condition="no_pam">
+ <variablelist remap='IP'>
<varlistentry>
- <term><option>-c</option>, <option>--crypt-method</option></term>
+ <term>
+ <option>-c</option>, <option>--crypt-method</option>
+ <replaceable>METHOD</replaceable>
+ </term>
<listitem>
<para>Use the specified method to encrypt the passwords.</para>
<para condition="no_sha_crypt">
The available methods are DES, MD5, NONE, and SHA256 or SHA512
if your libc support these methods.
</para>
+ <para condition="pam">
+ By default, PAM is used to encrypt the passwords.
+ </para>
+ <para condition="no_pam">
+ By default (if none of the <option>-c</option>,
+ <option>-m</option>, or <option>-e</option> options are
+ specified), the encryption method is defined by the
+ <option>ENCRYPT_METHOD</option> or
+ <option>MD5_CRYPT_ENAB</option> variables of
+ <filename>/etc/login.defs</filename>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
</listitem>
</varlistentry>
</variablelist>
- <variablelist remap='IP' condition="no_pam">
+ <variablelist remap='IP'>
<varlistentry>
<term><option>-m</option>, <option>--md5</option></term>
<listitem>
</listitem>
</varlistentry>
<varlistentry condition="sha_crypt">
- <term><option>-s</option>, <option>--sha-rounds</option></term>
+ <term>
+ <option>-s</option>, <option>--sha-rounds</option>
+ <replaceable>ROUNDS</replaceable>
+ </term>
<listitem>
<para>
Use the specified number of rounds to encrypt the passwords.
</para>
<para>
By default, the number of rounds is defined by the
- SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS variables in
+ <option>SHA_CRYPT_MIN_ROUNDS</option> and
+ <option>SHA_CRYPT_MAX_ROUNDS</option> variables in
<filename>/etc/login.defs</filename>.
</para>
</listitem>
Remember to set permissions or umask to prevent readability of
unencrypted files by other users.
</para>
- <para condition="no_pam">
- You should make sure the passwords and the encryption method respect
- the system's password policy.
- </para>
</refsect1>
- <refsect1 id='configuration' condition="no_pam">
+ <refsect1 id='configuration'>
<title>CONFIGURATION</title>
<para>
The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this
tool:
</para>
- <variablelist>
+ <variablelist condition="no_pam">
&ENCRYPT_METHOD;
&MD5_CRYPT_ENAB;
+ </variablelist>
+ <variablelist>
&SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS-->
</variablelist>
</refsect1>
<refsect1 id='files'>
<title>FILES</title>
<variablelist>
- <varlistentry condition="no_pam">
+ <varlistentry>
<term><filename>/etc/passwd</filename></term>
<listitem>
<para>User account information.</para>
</listitem>
</varlistentry>
- <varlistentry condition="no_pam">
+ <varlistentry>
<term><filename>/etc/shadow</filename></term>
<listitem>
<para>Secure user account information.</para>
</listitem>
</varlistentry>
- <varlistentry condition="no_pam">
+ <varlistentry>
<term><filename>/etc/login.defs</filename></term>
<listitem>
<para>Shadow password suite configuration.</para>
<citerefentry>
<refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
- <phrase condition="no_pam">
+ <phrase>
<citerefentry>
<refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
</para>
</listitem>
</varlistentry>
- <varlistentry condition="no_pam">
+ <varlistentry>
<term>chpasswd</term>
<listitem>
<para>
- ENCRYPT_METHOD MD5_CRYPT_ENAB
+ <phrase condition="no_pam">ENCRYPT_METHOD
+ MD5_CRYPT_ENAB </phrase>
<phrase condition="sha_crypt">SHA_CRYPT_MAX_ROUNDS
SHA_CRYPT_MIN_ROUNDS</phrase>
</para>
* Global variables
*/
char *Prog;
-#ifndef USE_PAM
static bool cflg = false;
static bool eflg = false;
static bool md5flg = false;
static bool is_shadow_pwd;
static bool pw_locked = false;
static bool spw_locked = false;
-#endif /* !USE_PAM */
/* local function prototypes */
static void fail_exit (int code);
static void process_flags (int argc, char **argv);
static void check_flags (void);
static void check_perms (void);
-#ifndef USE_PAM
static void open_files (void);
static void close_files (void);
-#endif /* !USE_PAM */
/*
* fail_exit - exit with a failure code after unlocking the files
*/
static void fail_exit (int code)
{
-#ifndef USE_PAM
if (pw_locked) {
if (pw_unlock () == 0) {
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
/* continue */
}
}
-#endif /* !USE_PAM */
exit (code);
}
"\n"
"Options:\n"),
Prog);
-#ifndef USE_PAM
(void) fprintf (usageout,
- _(" -c, --crypt-method the crypt method (one of %s)\n"),
+ _(" -c, --crypt-method <METHOD> the crypt method (one of %s)\n"),
#ifndef USE_SHA_CRYPT
"NONE DES MD5"
#else /* USE_SHA_CRYPT */
#endif /* USE_SHA_CRYPT */
);
(void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout);
-#endif /* !USE_PAM */
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
-#ifndef USE_PAM
(void) fputs (_(" -m, --md5 encrypt the clear text password using\n"
" the MD5 algorithm\n"),
usageout);
" crypt algorithms\n"),
usageout);
#endif /* USE_SHA_CRYPT */
-#endif /* !USE_PAM */
(void) fputs ("\n", usageout);
exit (status);
int option_index = 0;
int c;
static struct option long_options[] = {
-#ifndef USE_PAM
{"crypt-method", required_argument, NULL, 'c'},
{"encrypted", no_argument, NULL, 'e'},
{"md5", no_argument, NULL, 'm'},
#ifdef USE_SHA_CRYPT
{"sha-rounds", required_argument, NULL, 's'},
#endif /* USE_SHA_CRYPT */
-#endif /* !USE_PAM */
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv,
-#ifndef USE_PAM
-# ifdef USE_SHA_CRYPT
+#ifdef USE_SHA_CRYPT
"c:ehms:",
-# else /* !USE_SHA_CRYPT */
+#else /* !USE_SHA_CRYPT */
"c:ehm",
-# endif /* !USE_SHA_CRYPT */
-#else
- "h",
-#endif /* !USE_PAM */
+#endif /* !USE_SHA_CRYPT */
long_options, &option_index)) != -1) {
switch (c) {
case 'h':
usage (E_SUCCESS);
break;
-#ifndef USE_PAM
case 'c':
cflg = true;
crypt_method = optarg;
}
break;
#endif /* USE_SHA_CRYPT */
-#endif /* !USE_PAM */
default:
usage (E_USAGE);
break;
*/
static void check_flags (void)
{
-#ifndef USE_PAM
#ifdef USE_SHA_CRYPT
if (sflg && !cflg) {
fprintf (stderr,
#ifdef USE_SHA_CRYPT
&& (0 != strcmp (crypt_method, "SHA256"))
&& (0 != strcmp (crypt_method, "SHA512"))
-#endif
+#endif /* USE_SHA_CRYPT */
) {
fprintf (stderr,
_("%s: unsupported crypt method: %s\n"),
usage (E_USAGE);
}
}
-#endif /* USE_PAM */
}
/*
{
#ifdef USE_PAM
#ifdef ACCT_TOOLS_SETUID
+ /* If chpasswd uses PAM and is SUID, check the permissions,
+ * otherwise, the permissions are enforced by the access to the
+ * passwd and shadow files.
+ */
pam_handle_t *pamh = NULL;
int retval;
struct passwd *pampw;
#endif /* USE_PAM */
}
-#ifndef USE_PAM
/*
* open_files - lock and open the password databases
*/
}
pw_locked = false;
}
-#endif
int main (int argc, char **argv)
{
char *newpwd;
char *cp;
-#ifndef USE_PAM
- const struct spwd *sp;
- struct spwd newsp;
-
- const struct passwd *pw;
- struct passwd newpw;
-#endif /* !USE_PAM */
+#ifdef USE_PAM
+ bool use_pam = true;
+#endif /* USE_PAM */
int errors = 0;
int line = 0;
process_flags (argc, argv);
+#ifdef USE_PAM
+ if (md5flg || eflg || cflg) {
+ use_pam = false;
+ }
+#endif /* USE_PAM */
+
OPENLOG ("chpasswd");
check_perms ();
-#ifndef USE_PAM
- is_shadow_pwd = spw_file_present ();
+#ifdef USE_PAM
+ if (!use_pam)
+#endif /* USE_PAM */
+ {
+ is_shadow_pwd = spw_file_present ();
- open_files ();
-#endif
+ open_files ();
+ }
/*
* Read each line, separating the user name from the password. The
newpwd = cp;
#ifdef USE_PAM
+ if (use_pam){
if (do_pam_passwd_non_interractive ("chpasswd", name, newpwd) != 0) {
fprintf (stderr,
_("%s: (line %d, user %s) password not changed\n"),
Prog, line, name);
errors++;
}
-#else /* !USE_PAM */
+ } else
+#endif /* USE_PAM */
+ {
+ const struct spwd *sp;
+ struct spwd newsp;
+ const struct passwd *pw;
+ struct passwd newpw;
+
if ( !eflg
&& ( (NULL == crypt_method)
|| (0 != strcmp (crypt_method, "NONE")))) {
continue;
}
}
-#endif /* !USE_PAM */
+ }
}
/*
* password database.
*/
if (0 != errors) {
-#ifndef USE_PAM
- fprintf (stderr,
- _("%s: error detected, changes ignored\n"), Prog);
-#endif
+#ifdef USE_PAM
+ if (!use_pam)
+#endif /* USE_PAM */
+ {
+ fprintf (stderr,
+ _("%s: error detected, changes ignored\n"),
+ Prog);
+ }
fail_exit (1);
}
-#ifndef USE_PAM
+#ifdef USE_PAM
+ if (!use_pam)
+#endif /* USE_PAM */
+ {
/* Save the changes */
- close_files ();
-#endif
+ close_files ();
+ }
nscd_flush_cache ("passwd");