diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2020-10-29 08:00:00 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2020-10-29 08:00:00 +0000 |
commit | d702ff714c309069111899fd07c09e31c414c166 (patch) | |
tree | 0e4b5cf2449b8237ec9468faf2bba34c2e865076 /modules/pam_cracklib/pam_cracklib.c | |
parent | a0d402a38d0f043861879b287ac6069cb8a7d4b9 (diff) | |
download | pam-d702ff714c309069111899fd07c09e31c414c166.tar.gz pam-d702ff714c309069111899fd07c09e31c414c166.tar.bz2 pam-d702ff714c309069111899fd07c09e31c414c166.zip |
Remove deprecated pam_cracklib module
* ci/install-dependencies.sh: Remove libcrack2-dev.
* ci/run-build-and-tests.sh (DISTCHECK_CONFIGURE_FLAGS): Remove
--enable-cracklib=check.
* conf/pam.conf: Remove references to pam_cracklib.so.
* configure.ac: Remove --enable-cracklib option.
(AC_SUBST): Remove LIBCRACK.
(AM_CONDITIONAL): Remove COND_BUILD_PAM_CRACKLIB.
(AC_CONFIG_FILES): Remove modules/pam_cracklib/Makefile.
* doc/sag/pam_cracklib.xml: Remove.
* doc/sag/Linux-PAM_SAG.xml: Do not include pam_cracklib.xml.
* modules/Makefile.am (MAYBE_PAM_CRACKLIB): Remove.
(SUBDIRS): Remove MAYBE_PAM_CRACKLIB.
* modules/pam_cracklib/Makefile.am: Remove.
* modules/pam_cracklib/README.xml: Likewise.
* modules/pam_cracklib/pam_cracklib.8.xml: Likewise.
* modules/pam_cracklib/pam_cracklib.c: Likewise.
* modules/pam_cracklib/tst-pam_cracklib: Likewise.
* xtests/tst-pam_cracklib1.c: Likewise.
* xtests/tst-pam_cracklib1.pamd: Likewise.
* xtests/tst-pam_cracklib2.c: Likewise.
* xtests/tst-pam_cracklib2.pamd: Likewise.
* modules/pam_pwhistory/pam_pwhistory.8.xml: Replace pam_cracklib
in examples with pam_passwdqc.
* modules/pam_unix/pam_unix.8.xml: Likewise.
* po/POTFILES.in: Remove ./modules/pam_cracklib/pam_cracklib.c.
* xtests/.gitignore: Remove tst-pam_cracklib1 and tst-pam_cracklib2.
* xtests/Makefile.am (EXTRA_DIST): Remove tst-pam_cracklib1.pamd
and tst-pam_cracklib2.pamd.
(XTESTS): Remove tst-pam_cracklib1 and tst-pam_cracklib2.
* NEWS: Document this change.
Diffstat (limited to 'modules/pam_cracklib/pam_cracklib.c')
-rw-r--r-- | modules/pam_cracklib/pam_cracklib.c | 899 |
1 files changed, 0 insertions, 899 deletions
diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c deleted file mode 100644 index 01291305..00000000 --- a/modules/pam_cracklib/pam_cracklib.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * pam_cracklib module - * - * 0.9. switch to using a distance algorithm in similar() - * 0.86. added support for setting minimum numbers of digits, uppers, - * lowers, and others - * 0.85. added six new options to use this with long passwords. - * 0.8. tidied output and improved D(()) usage for debugging. - * 0.7. added support for more obscure checks for new passwd. - * 0.6. root can reset user passwd to any values (it's only warned) - * 0.5. supports retries - 'retry=N' argument - * 0.4. added argument 'type=XXX' for 'New XXX password' prompt - * 0.3. Added argument 'debug' - * 0.2. new password is fed to cracklib for verify after typed once - * 0.1. First release - * - * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10 - * Long password support by Philip W. Dalrymple <pwd@mdtsoft.com> 1997/07/18 - * See the end of the file for Copyright Information - * - * Modification for long password systems (>8 chars). The original - * module had problems when used in a md5 password system in that it - * allowed too short passwords but required that at least half of the - * bytes in the new password did not appear in the old one. this - * action is still the default and the changes should not break any - * current user. This modification adds 6 new options, one to set the - * number of bytes in the new password that are not in the old one, - * the other five to control the length checking, these are all - * documented (or will be before anyone else sees this code) in the PAM - * S.A.G. in the section on the cracklib module. - */ - -#include "config.h" - -#include <stdio.h> -#ifdef HAVE_LIBXCRYPT -# include <xcrypt.h> -#elif defined(HAVE_CRYPT_H) -# include <crypt.h> -#endif -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <ctype.h> -#include <limits.h> -#include <pwd.h> -#include <security/pam_modutil.h> - -#ifdef HAVE_CRACK_H -#include <crack.h> -#else -extern char *FascistCheck(char *pw, const char *dictpath); -#endif - -#ifndef CRACKLIB_DICTS -#define CRACKLIB_DICTS NULL -#endif - -#ifdef MIN -#undef MIN -#endif -#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) - -#include <security/pam_modules.h> -#include <security/_pam_macros.h> -#include <security/pam_ext.h> -#include "pam_inline.h" - -/* argument parsing */ -#define PAM_DEBUG_ARG 0x0001 - -struct cracklib_options { - int retry_times; - int diff_ok; - int min_length; - int dig_credit; - int up_credit; - int low_credit; - int oth_credit; - int min_class; - int max_repeat; - int max_sequence; - int max_class_repeat; - int reject_user; - int gecos_check; - int enforce_for_root; - const char *cracklib_dictpath; -}; - -#define CO_RETRY_TIMES 1 -#define CO_DIFF_OK 5 -#define CO_MIN_LENGTH 9 -# define CO_MIN_LENGTH_BASE 5 -#define CO_DIG_CREDIT 1 -#define CO_UP_CREDIT 1 -#define CO_LOW_CREDIT 1 -#define CO_OTH_CREDIT 1 -#define CO_MIN_WORD_LENGTH 4 - -static int -_pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, - int argc, const char **argv) -{ - int ctrl=0; - - /* step through arguments */ - for (ctrl=0; argc-- > 0; ++argv) { - const char *str; - char *ep = NULL; - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= PAM_DEBUG_ARG; - else if ((str = pam_str_skip_prefix(*argv, "type=")) != NULL) - pam_set_item (pamh, PAM_AUTHTOK_TYPE, str); - else if ((str = pam_str_skip_prefix(*argv, "retry=")) != NULL) { - opt->retry_times = strtol(str, &ep, 10); - if (!ep || (opt->retry_times < 1)) - opt->retry_times = CO_RETRY_TIMES; - } else if ((str = pam_str_skip_prefix(*argv, "difok=")) != NULL) { - opt->diff_ok = strtol(str, &ep, 10); - if (!ep || (opt->diff_ok < 0)) - opt->diff_ok = CO_DIFF_OK; - } else if (pam_str_skip_prefix(*argv, "difignore=") != NULL) { - /* just ignore */ - } else if ((str = pam_str_skip_prefix(*argv, "minlen=")) != NULL) { - opt->min_length = strtol(str, &ep, 10); - if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE)) - opt->min_length = CO_MIN_LENGTH_BASE; - } else if ((str = pam_str_skip_prefix(*argv, "dcredit=")) != NULL) { - opt->dig_credit = strtol(str, &ep, 10); - if (!ep) - opt->dig_credit = 0; - } else if ((str = pam_str_skip_prefix(*argv, "ucredit=")) != NULL) { - opt->up_credit = strtol(str, &ep, 10); - if (!ep) - opt->up_credit = 0; - } else if ((str = pam_str_skip_prefix(*argv, "lcredit=")) != NULL) { - opt->low_credit = strtol(str, &ep, 10); - if (!ep) - opt->low_credit = 0; - } else if ((str = pam_str_skip_prefix(*argv, "ocredit=")) != NULL) { - opt->oth_credit = strtol(str, &ep, 10); - if (!ep) - opt->oth_credit = 0; - } else if ((str = pam_str_skip_prefix(*argv, "minclass=")) != NULL) { - opt->min_class = strtol(str, &ep, 10); - if (!ep) - opt->min_class = 0; - if (opt->min_class > 4) - opt->min_class = 4; - } else if ((str = pam_str_skip_prefix(*argv, "maxrepeat=")) != NULL) { - opt->max_repeat = strtol(str, &ep, 10); - if (!ep) - opt->max_repeat = 0; - } else if ((str = pam_str_skip_prefix(*argv, "maxsequence=")) != NULL) { - opt->max_sequence = strtol(str, &ep, 10); - if (!ep) - opt->max_sequence = 0; - } else if ((str = pam_str_skip_prefix(*argv, "maxclassrepeat=")) != NULL) { - opt->max_class_repeat = strtol(str, &ep, 10); - if (!ep) - opt->max_class_repeat = 0; - } else if (!strcmp(*argv, "reject_username")) { - opt->reject_user = 1; - } else if (!strcmp(*argv, "gecoscheck")) { - opt->gecos_check = 1; - } else if (!strcmp(*argv, "enforce_for_root")) { - opt->enforce_for_root = 1; - } else if (pam_str_skip_prefix(*argv, "authtok_type=") != NULL) { - /* for pam_get_authtok, ignore */; - } else if (!strcmp(*argv, "use_authtok")) { - /* for pam_get_authtok, ignore */; - } else if (!strcmp(*argv, "use_first_pass")) { - /* for pam_get_authtok, ignore */; - } else if (!strcmp(*argv, "try_first_pass")) { - /* for pam_get_authtok, ignore */; - } else if ((str = pam_str_skip_prefix(*argv, "dictpath=")) != NULL) { - opt->cracklib_dictpath = str; - if (!*(opt->cracklib_dictpath)) { - opt->cracklib_dictpath = CRACKLIB_DICTS; - } - } else { - pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv); - } - } - - return ctrl; -} - -/* Helper functions */ - -/* - * can't be a palindrome - like `R A D A R' or `M A D A M' - */ -static int palindrome(const char *new) -{ - int i, j; - - i = strlen (new); - - for (j = 0;j < i;j++) - if (new[i - j - 1] != new[j]) - return 0; - - return 1; -} - -/* - * Calculate how different two strings are in terms of the number of - * character removals, additions, and changes needed to go from one to - * the other - */ - -static int distdifferent(const char *old, const char *new, - size_t i, size_t j) -{ - char c, d; - - if ((i == 0) || (strlen(old) < i)) { - c = 0; - } else { - c = old[i - 1]; - } - if ((j == 0) || (strlen(new) < j)) { - d = 0; - } else { - d = new[j - 1]; - } - return (c != d); -} - -static int distcalculate(int **distances, const char *old, const char *new, - size_t i, size_t j) -{ - int tmp = 0; - - if (distances[i][j] != -1) { - return distances[i][j]; - } - - tmp = distcalculate(distances, old, new, i - 1, j - 1); - tmp = MIN(tmp, distcalculate(distances, old, new, i, j - 1)); - tmp = MIN(tmp, distcalculate(distances, old, new, i - 1, j)); - tmp += distdifferent(old, new, i, j); - - distances[i][j] = tmp; - - return tmp; -} - -static int distance(const char *old, const char *new) -{ - int **distances = NULL; - size_t m, n, i, j, r; - - m = strlen(old); - n = strlen(new); - distances = malloc(sizeof(int*) * (m + 1)); - - for (i = 0; i <= m; i++) { - distances[i] = malloc(sizeof(int) * (n + 1)); - for(j = 0; j <= n; j++) { - distances[i][j] = -1; - } - } - for (i = 0; i <= m; i++) { - distances[i][0] = i; - } - for (j = 0; j <= n; j++) { - distances[0][j] = j; - } - distances[0][0] = 0; - - r = distcalculate(distances, old, new, m, n); - - for (i = 0; i <= m; i++) { - memset(distances[i], 0, sizeof(int) * (n + 1)); - free(distances[i]); - } - free(distances); - - return r; -} - -static int similar(struct cracklib_options *opt, - const char *old, const char *new) -{ - if (distance(old, new) >= opt->diff_ok) { - return 0; - } - - if (strlen(new) >= (strlen(old) * 2)) { - return 0; - } - - /* passwords are too similar */ - return 1; -} - -/* - * enough classes of characters - */ - -static int minclass (struct cracklib_options *opt, - const char *new) -{ - int digits = 0; - int uppers = 0; - int lowers = 0; - int others = 0; - int total_class; - int i; - int retval; - - D(( "called" )); - for (i = 0; new[i]; i++) - { - if (isdigit (new[i])) - digits = 1; - else if (isupper (new[i])) - uppers = 1; - else if (islower (new[i])) - lowers = 1; - else - others = 1; - } - - total_class = digits + uppers + lowers + others; - - D (("total class: %d\tmin_class: %d", total_class, opt->min_class)); - - if (total_class >= opt->min_class) - retval = 0; - else - retval = 1; - - return retval; -} - - -/* - * a nice mix of characters. - */ -static int simple(struct cracklib_options *opt, const char *new) -{ - int digits = 0; - int uppers = 0; - int lowers = 0; - int others = 0; - int size; - int i; - enum { NONE, DIGIT, UCASE, LCASE, OTHER } prevclass = NONE; - int sameclass = 0; - - for (i = 0;new[i];i++) { - if (isdigit (new[i])) { - digits++; - if (prevclass != DIGIT) { - prevclass = DIGIT; - sameclass = 1; - } else - sameclass++; - } - else if (isupper (new[i])) { - uppers++; - if (prevclass != UCASE) { - prevclass = UCASE; - sameclass = 1; - } else - sameclass++; - } - else if (islower (new[i])) { - lowers++; - if (prevclass != LCASE) { - prevclass = LCASE; - sameclass = 1; - } else - sameclass++; - } - else { - others++; - if (prevclass != OTHER) { - prevclass = OTHER; - sameclass = 1; - } else - sameclass++; - } - if (opt->max_class_repeat > 0 && sameclass > opt->max_class_repeat) { - return 1; - } - } - - /* - * The scam was this - a password of only one character type - * must be 8 letters long. Two types, 7, and so on. - * This is now changed, the base size and the credits or defaults - * see the docs on the module for info on these parameters, the - * defaults cause the effect to be the same as before the change - */ - - if ((opt->dig_credit >= 0) && (digits > opt->dig_credit)) - digits = opt->dig_credit; - - if ((opt->up_credit >= 0) && (uppers > opt->up_credit)) - uppers = opt->up_credit; - - if ((opt->low_credit >= 0) && (lowers > opt->low_credit)) - lowers = opt->low_credit; - - if ((opt->oth_credit >= 0) && (others > opt->oth_credit)) - others = opt->oth_credit; - - size = opt->min_length; - - if (opt->dig_credit >= 0) - size -= digits; - else if (digits < opt->dig_credit * -1) - return 1; - - if (opt->up_credit >= 0) - size -= uppers; - else if (uppers < opt->up_credit * -1) - return 1; - - if (opt->low_credit >= 0) - size -= lowers; - else if (lowers < opt->low_credit * -1) - return 1; - - if (opt->oth_credit >= 0) - size -= others; - else if (others < opt->oth_credit * -1) - return 1; - - if (size <= i) - return 0; - - return 1; -} - -static int consecutive(struct cracklib_options *opt, const char *new) -{ - char c; - int i; - int same; - - if (opt->max_repeat == 0) - return 0; - - for (i = 0; new[i]; i++) { - if (i > 0 && new[i] == c) { - ++same; - if (same > opt->max_repeat) - return 1; - } else { - c = new[i]; - same = 1; - } - } - return 0; -} - -static int sequence(struct cracklib_options *opt, const char *new) -{ - char c; - int i; - int sequp = 1; - int seqdown = 1; - - if (opt->max_sequence == 0) - return 0; - - if (new[0] == '\0') - return 0; - - for (i = 1; new[i]; i++) { - c = new[i-1]; - if (new[i] == c+1) { - ++sequp; - if (sequp > opt->max_sequence) - return 1; - seqdown = 1; - } else if (new[i] == c-1) { - ++seqdown; - if (seqdown > opt->max_sequence) - return 1; - sequp = 1; - } else { - sequp = 1; - seqdown = 1; - } - } - return 0; -} - -static int wordcheck(const char *new, char *word) -{ - char *f, *b; - - if (strstr(new, word) != NULL) - return 1; - - /* now reverse the word, we can do that in place - as it is strdup-ed */ - f = word; - b = word+strlen(word)-1; - while (f < b) { - char c; - - c = *f; - *f = *b; - *b = c; - --b; - ++f; - } - - if (strstr(new, word) != NULL) - return 1; - return 0; -} - -static int usercheck(struct cracklib_options *opt, const char *new, - char *user) -{ - if (!opt->reject_user) - return 0; - - return wordcheck(new, user); -} - -static char * str_lower(char *string) -{ - char *cp; - - if (!string) - return NULL; - - for (cp = string; *cp; cp++) - *cp = tolower(*cp); - return string; -} - -static int gecoscheck(pam_handle_t *pamh, struct cracklib_options *opt, const char *new, - const char *user) -{ - struct passwd *pwd; - char *list; - char *p; - char *next; - - if (!opt->gecos_check) - return 0; - - if ((pwd = pam_modutil_getpwnam(pamh, user)) == NULL) { - return 0; - } - - list = strdup(pwd->pw_gecos); - - if (list == NULL || *list == '\0') { - free(list); - return 0; - } - - for (p = list;;p = next + 1) { - next = strchr(p, ' '); - if (next) - *next = '\0'; - - if (strlen(p) >= CO_MIN_WORD_LENGTH) { - str_lower(p); - if (wordcheck(new, p)) { - free(list); - return 1; - } - } - - if (!next) - break; - } - - free(list); - return 0; -} - -static const char *password_check(pam_handle_t *pamh, struct cracklib_options *opt, - const char *old, const char *new, - const char *user) -{ - const char *msg = NULL; - char *oldmono = NULL, *newmono, *wrapped = NULL; - char *usermono = NULL; - - if (old && strcmp(new, old) == 0) { - msg = _("is the same as the old one"); - return msg; - } - - newmono = str_lower(strdup(new)); - if (!newmono) - msg = _("memory allocation error"); - - usermono = str_lower(strdup(user)); - if (!usermono) - msg = _("memory allocation error"); - - if (!msg && old) { - oldmono = str_lower(strdup(old)); - if (oldmono) - wrapped = malloc(strlen(oldmono) * 2 + 1); - if (wrapped) { - strcpy (wrapped, oldmono); - strcat (wrapped, oldmono); - } else { - msg = _("memory allocation error"); - } - } - - if (!msg && palindrome(newmono)) - msg = _("is a palindrome"); - - if (!msg && oldmono && strcmp(oldmono, newmono) == 0) - msg = _("case changes only"); - - if (!msg && oldmono && similar(opt, oldmono, newmono)) - msg = _("is too similar to the old one"); - - if (!msg && simple(opt, new)) - msg = _("is too simple"); - - if (!msg && wrapped && strstr(wrapped, newmono)) - msg = _("is rotated"); - - if (!msg && minclass (opt, new)) - msg = _("not enough character classes"); - - if (!msg && consecutive(opt, new)) - msg = _("contains too many same characters consecutively"); - - if (!msg && sequence(opt, new)) - msg = _("contains too long of a monotonic character sequence"); - - if (!msg && (usercheck(opt, newmono, usermono) || gecoscheck(pamh, opt, newmono, user))) - msg = _("contains the user name in some form"); - - free(usermono); - if (newmono) { - memset(newmono, 0, strlen(newmono)); - free(newmono); - } - if (oldmono) { - memset(oldmono, 0, strlen(oldmono)); - free(oldmono); - } - if (wrapped) { - memset(wrapped, 0, strlen(wrapped)); - free(wrapped); - } - - return msg; -} - - -static int _pam_unix_approve_pass(pam_handle_t *pamh, - unsigned int ctrl, - struct cracklib_options *opt, - const char *pass_old, - const char *pass_new) -{ - const char *msg = NULL; - const char *user; - int retval; - - if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh, LOG_DEBUG, "bad authentication token"); - pam_error(pamh, "%s", pass_new == NULL ? - _("No password has been supplied.") : - _("The password has not been changed.")); - return PAM_AUTHTOK_ERR; - } - - retval = pam_get_user(pamh, &user, NULL); - if (retval != PAM_SUCCESS) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s", - pam_strerror(pamh, retval)); - return PAM_AUTHTOK_ERR; - } - /* - * if one wanted to hardwire authentication token strength - * checking this would be the place - */ - msg = password_check(pamh, opt, pass_old, pass_new, user); - - if (msg) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh, LOG_NOTICE, - "new passwd fails strength check: %s", msg); - pam_error(pamh, _("BAD PASSWORD: %s"), msg); - return PAM_AUTHTOK_ERR; - }; - return PAM_SUCCESS; - -} - -/* The Main Thing (by Cristian Gafton, CEO at this module :-) - * (stolen from http://home.netscape.com) - */ -int -pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) -{ - unsigned int ctrl; - struct cracklib_options options; - - D(("called.")); - - memset(&options, 0, sizeof(options)); - options.retry_times = CO_RETRY_TIMES; - options.diff_ok = CO_DIFF_OK; - options.min_length = CO_MIN_LENGTH; - options.dig_credit = CO_DIG_CREDIT; - options.up_credit = CO_UP_CREDIT; - options.low_credit = CO_LOW_CREDIT; - options.oth_credit = CO_OTH_CREDIT; - options.cracklib_dictpath = CRACKLIB_DICTS; - - ctrl = _pam_parse(pamh, &options, argc, argv); - - if (flags & PAM_PRELIM_CHECK) { - /* Check for passwd dictionary */ - /* We cannot do that, since the original path is compiled - into the cracklib library and we don't know it. */ - return PAM_SUCCESS; - } else if (flags & PAM_UPDATE_AUTHTOK) { - int retval; - const void *oldtoken; - int tries; - - D(("do update")); - - - retval = pam_get_item (pamh, PAM_OLDAUTHTOK, &oldtoken); - if (retval != PAM_SUCCESS) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_ERR,"Can not get old passwd"); - oldtoken = NULL; - } - - tries = 0; - while (tries < options.retry_times) { - const char *crack_msg; - const char *newtoken = NULL; - - - tries++; - - /* Planned modus operandi: - * Get a passwd. - * Verify it against cracklib. - * If okay get it a second time. - * Check to be the same with the first one. - * set PAM_AUTHTOK and return - */ - - retval = pam_get_authtok_noverify (pamh, &newtoken, NULL); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_ERR, "pam_get_authtok_noverify returned error: %s", - pam_strerror (pamh, retval)); - continue; - } else if (newtoken == NULL) { /* user aborted password change, quit */ - return PAM_AUTHTOK_ERR; - } - - D(("testing password")); - /* now test this passwd against cracklib */ - - D(("against cracklib")); - if ((crack_msg = FascistCheck (newtoken, options.cracklib_dictpath))) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_DEBUG,"bad password: %s",crack_msg); - pam_error (pamh, _("BAD PASSWORD: %s"), crack_msg); - if (getuid() || options.enforce_for_root || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - { - pam_set_item (pamh, PAM_AUTHTOK, NULL); - retval = PAM_AUTHTOK_ERR; - continue; - } - } - - /* check it for strength too... */ - D(("for strength")); - retval = _pam_unix_approve_pass (pamh, ctrl, &options, - oldtoken, newtoken); - if (retval != PAM_SUCCESS) { - if (getuid() || options.enforce_for_root || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - { - pam_set_item(pamh, PAM_AUTHTOK, NULL); - retval = PAM_AUTHTOK_ERR; - continue; - } - } - - retval = pam_get_authtok_verify (pamh, &newtoken, NULL); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_ERR, "pam_get_authtok_verify returned error: %s", - pam_strerror (pamh, retval)); - pam_set_item(pamh, PAM_AUTHTOK, NULL); - continue; - } else if (newtoken == NULL) { /* user aborted password change, quit */ - return PAM_AUTHTOK_ERR; - } - - return PAM_SUCCESS; - } - - D(("returning because maxtries reached")); - - pam_set_item (pamh, PAM_AUTHTOK, NULL); - - /* if we have only one try, we can use the real reason, - else say that there were too many tries. */ - if (options.retry_times > 1) - return PAM_MAXTRIES; - else - return retval; - - } else { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh, LOG_NOTICE, "UNKNOWN flags setting %02X",flags); - return PAM_SERVICE_ERR; - } - - /* Not reached */ - return PAM_SERVICE_ERR; -} - - - -/* - * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996. - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The following copyright was appended for the long password support - * added with the libpam 0.58 release: - * - * Modificaton Copyright (c) Philip W. Dalrymple III <pwd@mdtsoft.com> - * 1997. All rights reserved - * - * THE MODIFICATION THAT PROVIDES SUPPORT FOR LONG PASSWORD TYPE CHECKING TO - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ |