src/passwd.c: implement reading password from pipe
New option --stdin/-t is available for root user. It is useful for automation/setup and it makes shadow utils passwd more versatile. Signed-off-by: Tomas Halman <tomas@halman.net>
This commit is contained in:
committed by
Serge Hallyn
parent
3fff9d7621
commit
49001ca846
@@ -358,6 +358,17 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>-s</option>, <option>--stdin</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This option is used to indicate that passwd should read the new password from standard
|
||||
input, which can be a pipe.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
+81
-47
@@ -68,7 +68,8 @@ static bool
|
||||
Sflg = false, /* -S - show password status */
|
||||
uflg = false, /* -u - unlock the user's password */
|
||||
wflg = false, /* -w - set warning days */
|
||||
xflg = false; /* -x - set maximum days */
|
||||
xflg = false, /* -x - set maximum days */
|
||||
sflg = false; /* -s - read passwd from stdin */
|
||||
|
||||
/*
|
||||
* set to 1 if there are any flags which require root privileges,
|
||||
@@ -158,6 +159,7 @@ usage (int status)
|
||||
(void) fputs (_(" -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout);
|
||||
(void) fputs (_(" -x, --maxdays MAX_DAYS set maximum number of days before password\n"
|
||||
" change to MAX_DAYS\n"), usageout);
|
||||
(void) fputs (_(" -s, --stdin read new token from stdin\n"), usageout);
|
||||
(void) fputs ("\n", usageout);
|
||||
exit (status);
|
||||
}
|
||||
@@ -252,7 +254,7 @@ static int new_password (const struct passwd *pw)
|
||||
pass_max_len = getdef_num ("PASS_MAX_LEN", 8);
|
||||
}
|
||||
}
|
||||
if (!qflg) {
|
||||
if (!qflg && !sflg) {
|
||||
if (pass_max_len == -1) {
|
||||
(void) printf (_(
|
||||
"Enter the new password (minimum of %d characters)\n"
|
||||
@@ -266,56 +268,69 @@ static int new_password (const struct passwd *pw)
|
||||
}
|
||||
}
|
||||
|
||||
warned = false;
|
||||
for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
|
||||
cp = agetpass (_("New password: "));
|
||||
if (NULL == cp) {
|
||||
MEMZERO(orig);
|
||||
MEMZERO(pass);
|
||||
return -1;
|
||||
}
|
||||
if (warned && (strcmp (pass, cp) != 0)) {
|
||||
warned = false;
|
||||
}
|
||||
STRTCPY(pass, cp);
|
||||
erase_pass (cp);
|
||||
|
||||
if (!amroot && !obscure(orig, pass, pw)) {
|
||||
(void) puts (_("Try again."));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sflg) {
|
||||
/*
|
||||
* If enabled, warn about weak passwords even if you are
|
||||
* root (enter this password again to use it anyway).
|
||||
* --marekm
|
||||
* root is setting the passphrase from stdin
|
||||
*/
|
||||
if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
|
||||
&& !obscure(orig, pass, pw)) {
|
||||
(void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
|
||||
warned = true;
|
||||
continue;
|
||||
}
|
||||
cp = agetpass (_("Re-enter new password: "));
|
||||
cp = agetpass_stdin ();
|
||||
if (NULL == cp) {
|
||||
MEMZERO(orig);
|
||||
return -1;
|
||||
}
|
||||
STRTCPY (pass, cp);
|
||||
erase_pass (cp);
|
||||
} else {
|
||||
warned = false;
|
||||
for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) {
|
||||
cp = agetpass (_("New password: "));
|
||||
if (NULL == cp) {
|
||||
MEMZERO(orig);
|
||||
MEMZERO(pass);
|
||||
return -1;
|
||||
}
|
||||
if (warned && (strcmp (pass, cp) != 0)) {
|
||||
warned = false;
|
||||
}
|
||||
STRTCPY(pass, cp);
|
||||
erase_pass (cp);
|
||||
|
||||
if (!amroot && !obscure(orig, pass, pw)) {
|
||||
(void) puts (_("Try again."));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If enabled, warn about weak passwords even if you are
|
||||
* root (enter this password again to use it anyway).
|
||||
* --marekm
|
||||
*/
|
||||
if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN")
|
||||
&& !obscure(orig, pass, pw)) {
|
||||
(void) puts (_("\nWarning: weak password (enter it again to use it anyway)."));
|
||||
warned = true;
|
||||
continue;
|
||||
}
|
||||
cp = agetpass (_("Re-enter new password: "));
|
||||
if (NULL == cp) {
|
||||
MEMZERO(orig);
|
||||
MEMZERO(pass);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp (cp, pass) != 0) {
|
||||
erase_pass (cp);
|
||||
(void) fputs (_("They don't match; try again.\n"), stderr);
|
||||
} else {
|
||||
erase_pass (cp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MEMZERO(orig);
|
||||
|
||||
if (i == 0) {
|
||||
MEMZERO(pass);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp (cp, pass) != 0) {
|
||||
erase_pass (cp);
|
||||
(void) fputs (_("They don't match; try again.\n"), stderr);
|
||||
} else {
|
||||
erase_pass (cp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MEMZERO(orig);
|
||||
|
||||
if (i == 0) {
|
||||
MEMZERO(pass);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt the password, then wipe the cleartext password.
|
||||
@@ -684,6 +699,7 @@ static void update_shadow (void)
|
||||
* -u unlock the password of the named account (*)
|
||||
* -w # set sp_warn to # days (*)
|
||||
* -x # set sp_max to # days (*)
|
||||
* -s read password from stdin (*)
|
||||
*
|
||||
* (*) requires root permission to execute.
|
||||
*
|
||||
@@ -751,10 +767,11 @@ int main (int argc, char **argv)
|
||||
{"unlock", no_argument, NULL, 'u'},
|
||||
{"warndays", required_argument, NULL, 'w'},
|
||||
{"maxdays", required_argument, NULL, 'x'},
|
||||
{"stdin", no_argument, NULL, 's'},
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:",
|
||||
while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:s",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
@@ -847,6 +864,15 @@ int main (int argc, char **argv)
|
||||
xflg = true;
|
||||
anyflag = true;
|
||||
break;
|
||||
case 's':
|
||||
if (!amroot) {
|
||||
(void) fprintf (stderr,
|
||||
_("%s: only root can use --stdin/-s option\n"),
|
||||
Prog);
|
||||
usage (E_BAD_ARG);
|
||||
}
|
||||
sflg = true;
|
||||
break;
|
||||
default:
|
||||
usage (E_BAD_ARG);
|
||||
}
|
||||
@@ -1038,7 +1064,16 @@ int main (int argc, char **argv)
|
||||
* Don't set the real UID for PAM...
|
||||
*/
|
||||
if (!anyflag && use_pam) {
|
||||
do_pam_passwd (name, qflg, kflg);
|
||||
if (sflg) {
|
||||
cp = agetpass_stdin ();
|
||||
if (cp == NULL) {
|
||||
exit (E_FAILURE);
|
||||
}
|
||||
do_pam_passwd_non_interactive ("passwd", name, cp);
|
||||
erase_pass (cp);
|
||||
} else {
|
||||
do_pam_passwd (name, qflg, kflg);
|
||||
}
|
||||
exit (E_SUCCESS);
|
||||
}
|
||||
#endif /* USE_PAM */
|
||||
@@ -1072,4 +1107,3 @@ int main (int argc, char **argv)
|
||||
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user