summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG3
-rw-r--r--doc/modules/pam_cracklib.sgml13
-rw-r--r--modules/pam_cracklib/README18
-rw-r--r--modules/pam_cracklib/pam_cracklib.c79
4 files changed, 79 insertions, 34 deletions
diff --git a/CHANGELOG b/CHANGELOG
index b59524c2..f90cb3e6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -35,6 +35,9 @@ Where you should replace XXXXX with a bug-id.
0.73: please submit patches for this section with actual code/doc
patches!
+* replaced bogus logic in the pam_cracklib module for determining if
+ the replacement is too similar to the old password (Bug 115055 -
+ agmorgan)
* added accessconf=<filename> feature to pam_access - request from
Aldrin Martoq and Meelis Roos (Bugs 111927,117240 - agmorgan)
* fix for pam_limit module not dealing with all limits Adam J. Richter
diff --git a/doc/modules/pam_cracklib.sgml b/doc/modules/pam_cracklib.sgml
index f5b2359a..031a440e 100644
--- a/doc/modules/pam_cracklib.sgml
+++ b/doc/modules/pam_cracklib.sgml
@@ -70,12 +70,19 @@ Is the new password the the old one with only a change of case?
<item> <bf/Similar/ -
-Is the new password too much like the old one? This is controlled
-by one argument, <tt/difok/ which is a number of characters that if
-different between the old and new are enough to accept the new
+Is the new password too much like the old one? This is primarily
+controlled by one argument, <tt/difok/ which is a number of characters
+that if different between the old and new are enough to accept the new
password, this defaults to 10 or 1/2 the size of the new password
whichever is smaller.
+To avoid the lockup associated with trying to change a long and
+complicated password, <tt/difignore/ is available. This argument can
+be used to specify the minimum length a new password needs to be
+before the <tt/difok/ value is ignored. The default value for
+<tt/difignore/ is 23.
+
+
<item> <bf/Simple/ -
Is the new password too small? This is controlled by 5 arguments
diff --git a/modules/pam_cracklib/README b/modules/pam_cracklib/README
index e4b02731..69662f73 100644
--- a/modules/pam_cracklib/README
+++ b/modules/pam_cracklib/README
@@ -13,9 +13,25 @@ RECOGNIZED ARGUMENTS:
retry=N Prompt user at most N times before returning with
error. Default N=1.
+ difok=N How many characters can be the same in the new
+ password relative to the old
+ difignore=N How many characters long should the password be
+ before we ignore difok.
+
+ minlen=N The minimum simplicity count for a good password.
+
+ dcredit=N
+ ucredit=N
+ lcredit=N
+ ocredit=N Weight, digits, upper, lower, other characters with
+ count N. Use these values to compute the
+ 'unsimplicity' of the password.
+
+ use_authtok Get the proposed password from PAM_AUTHTOK
+
MODULE SERVICES PROVIDED:
passwd chauthtok
AUTHOR:
- Cristian Gafton <gafton@sorosis.ro>
+ Cristian Gafton <gafton@redhat.com>
diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c
index d3d74947..c79d4e76 100644
--- a/modules/pam_cracklib/pam_cracklib.c
+++ b/modules/pam_cracklib/pam_cracklib.c
@@ -87,11 +87,10 @@ static void _pam_log(int err, const char *format, ...)
/* argument parsing */
#define PAM_DEBUG_ARG 0x0001
-/* module data - AGM: */
-
struct cracklib_options {
int retry_times;
int diff_ok;
+ int diff_ignore;
int min_length;
int dig_credit;
int up_credit;
@@ -101,6 +100,17 @@ struct cracklib_options {
char prompt_type[BUFSIZ];
};
+#define CO_RETRY_TIMES 1
+#define CO_DIFF_OK 10
+#define CO_DIFF_IGNORE 23
+#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_USE_AUTHTOK 0
+
static int _pam_parse(struct cracklib_options *opt, int argc, const char **argv)
{
int ctrl=0;
@@ -118,15 +128,19 @@ static int _pam_parse(struct cracklib_options *opt, int argc, const char **argv)
else if (!strncmp(*argv,"retry=",6)) {
opt->retry_times = strtol(*argv+6,&ep,10);
if (!ep || (opt->retry_times < 1))
- opt->retry_times = 1;
+ opt->retry_times = CO_RETRY_TIMES;
} else if (!strncmp(*argv,"difok=",6)) {
opt->diff_ok = strtol(*argv+6,&ep,10);
if (!ep || (opt->diff_ok < 0))
- opt->diff_ok = 10;
+ opt->diff_ok = CO_DIFF_OK;
+ } else if (!strncmp(*argv,"difignore=",10)) {
+ opt->diff_ignore = strtol(*argv+10,&ep,10);
+ if (!ep || (opt->diff_ignore < 0))
+ opt->diff_ignore = CO_DIFF_IGNORE;
} else if (!strncmp(*argv,"minlen=",7)) {
opt->min_length = strtol(*argv+7,&ep,10);
- if (!ep || (opt->min_length < 5))
- opt->min_length = 5;
+ if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE))
+ opt->min_length = CO_MIN_LENGTH_BASE;
} else if (!strncmp(*argv,"dcredit=",8)) {
opt->dig_credit = strtol(*argv+8,&ep,10);
if (!ep || (opt->dig_credit < 0))
@@ -224,26 +238,30 @@ static int palindrome(const char *old, const char *new)
}
/*
- * more than half of the characters are different ones.
- * or at least diff_ok are different
- * NOTE that the defaults are NOT the same as befor this
- * change. as long as there are at least 10 different bytes
- * in a new password it will now pass even if the password
- * is longer than 20 bytes (MD5)
+ * This is a reasonably severe check for a different selection of characters
+ * in the old and new passwords.
*/
-static int similiar(struct cracklib_options *opt, const char *old, const char *new)
+static int similar(struct cracklib_options *opt,
+ const char *old, const char *new)
{
- int i, j;
+ int i, j;
- for (i = j = 0;new[i] && old[i];i++)
- if (strchr (new, old[i]))
- j++;
+ for (i = j = 0; old[i]; i++) {
+ if (strchr (new, old[i])) {
+ j++;
+ }
+ }
- if (j >= opt->diff_ok || i >= j * 2)
- return 0;
+ if (((i-j) >= opt->diff_ok)
+ || (strlen(new) >= (j * 2))
+ || (strlen(new) >= opt->diff_ignore)) {
+ /* passwords are not very similar */
+ return 0;
+ }
- return 1;
+ /* passwords are too similar */
+ return 1;
}
/*
@@ -332,8 +350,8 @@ static const char * password_check(struct cracklib_options *opt, const char *old
if (!msg && strcmp(oldmono, newmono) == 0)
msg = "case changes only";
- if (!msg && similiar(opt, oldmono, newmono))
- msg = "is too similiar to the old one";
+ if (!msg && similar(opt, oldmono, newmono))
+ msg = "is too similar to the old one";
if (!msg && simple(opt, old, new))
msg = "is too simple";
@@ -447,14 +465,15 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
unsigned int ctrl;
struct cracklib_options options;
- options.retry_times = 1;
- options.diff_ok = 10;
- options.min_length = 9;
- options.dig_credit = 1;
- options.up_credit = 1;
- options.low_credit = 1;
- options.oth_credit = 1;
- options.use_authtok = 0;
+ options.retry_times = CO_RETRY_TIMES;
+ options.diff_ok = CO_DIFF_OK;
+ options.diff_ignore = CO_DIFF_IGNORE;
+ 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.use_authtok = CO_USE_AUTHTOK;
memset(options.prompt_type, 0, BUFSIZ);
ctrl = _pam_parse(&options, argc, argv);