/* * check_password - test a password to see if it can be changed * * check_password() sees if the invoker has permission to change the * password for the given user. */ static void check_password (const struct passwd *pw, const struct spwd *sp) { time_t now, last, ok; int exp_status; exp_status = isexpired (pw, sp); /* * If not expired and the "change only if expired" option (idea from * PAM) was specified, do nothing. --marekm */ if (kflg && (0 == exp_status)) { exit (E_SUCCESS); } /* * Root can change any password any time. */ if (amroot) { return; } (void) time (&now); /* * Expired accounts cannot be changed ever. Passwords which are * locked may not be changed. Passwords where min > max may not be * changed. Passwords which have been inactive too long cannot be * changed. */ if ( (sp->sp_pwdp[0] == '!') || (exp_status > 1) || ( (sp->sp_max >= 0) && (sp->sp_min > sp->sp_max))) { fprintf (stderr, _("The password for %s cannot be changed.\n"), sp->sp_namp); SYSLOG ((LOG_WARN, "password locked for '%s'", sp->sp_namp)); closelog (); exit (E_NOPERM); } /* * Passwords may only be changed after sp_min time is up. */ if (sp->sp_lstchg > 0) { last = sp->sp_lstchg * SCALE; ok = last + (sp->sp_min > 0 ? sp->sp_min * SCALE : 0); if (now < ok) { fprintf (stderr, _("The password for %s cannot be changed yet.\n"), pw->pw_name); SYSLOG ((LOG_WARN, "now < minimum age for '%s'", pw->pw_name)); closelog (); exit (E_NOPERM); } } }
/* * expiry - check and enforce password expiration policy * * expiry checks (-c) the current password expiration and forces (-f) * changes when required. It is callable as a normal user command. */ int main (int argc, char **argv) { struct passwd *pwd; struct spwd *spwd; Prog = Basename (argv[0]); sanitize_env (); /* * Start by disabling all of the keyboard signals. */ (void) signal (SIGHUP, catch_signals); (void) signal (SIGINT, catch_signals); (void) signal (SIGQUIT, catch_signals); #ifdef SIGTSTP (void) signal (SIGTSTP, catch_signals); #endif /* * expiry takes one of two arguments. The default action is to give * the usage message. */ (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); OPENLOG ("expiry"); process_flags (argc, argv); /* * Get user entries for /etc/passwd and /etc/shadow */ pwd = get_my_pwent (); if (NULL == pwd) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); exit (10); } spwd = getspnam (pwd->pw_name); /* !USE_PAM, No need for xgetspnam */ /* * If checking accounts, use agecheck() function. */ if (cflg) { /* * Print out number of days until expiration. */ agecheck (spwd); /* * Exit with status indicating state of account. */ exit (isexpired (pwd, spwd)); } /* * Otherwise, force a password change with the expire() function. * It will force the change or give a message indicating what to * do. * It won't return unless the account is unexpired. */ (void) expire (pwd, spwd); return E_SUCCESS; }