]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs: 115055
authorAndrew G. Morgan <morgan@kernel.org>
Sat, 25 Nov 2000 03:27:39 +0000 (03:27 +0000)
committerAndrew G. Morgan <morgan@kernel.org>
Sat, 25 Nov 2000 03:27:39 +0000 (03:27 +0000)
Purpose of commit: bugfix

Commit summary:
---------------
fixed the bogus logic in 'similiar' (renamed it to similar) and
documented the new override argument: difignore.

CHANGELOG
doc/modules/pam_cracklib.sgml
modules/pam_cracklib/README
modules/pam_cracklib/pam_cracklib.c

index b59524c2cc5d6f89614802a77809bc485abf7400..f90cb3e6d5a6b246ae7aa4af05d8e64c1f370d4d 100644 (file)
--- 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
index f5b2359ab027a98da1a67024241223868af5d293..031a440ed1fbf20548625c159a7b5e5038bc6745 100644 (file)
@@ -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
index e4b02731b523241f8e91a87c0a7b6ed708d74857..69662f7385b3df597f8cd687fc62817c2983ff56 100644 (file)
@@ -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>
 
index d3d74947e1ffde1640aab07281c12a0e60b4153b..c79d4e76d8a55bfb792f39c2a6a9dfa1cc069b12 100644 (file)
@@ -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);