walters / rpms / pam

Forked from rpms/pam 5 years ago
Clone
Blob Blame History Raw
diff -up Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.8.xml.pwquality Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.8.xml
--- Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.8.xml.pwquality	2007-11-06 15:58:54.000000000 +0100
+++ Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.8.xml	2008-09-23 15:06:40.000000000 +0200
@@ -59,7 +59,7 @@
         <term>Palindrome</term>
         <listitem>
           <para>
-            Is the new password a palindrome of the old one?
+            Is the new password a palindrome?
           </para>
         </listitem>
       </varlistentry>
@@ -120,6 +120,23 @@
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>Same consecutive characters</term>
+        <listitem>
+          <para>
+            Optional check for same consecutive characters.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>Contains user name</term>
+        <listitem>
+          <para>
+            Optional check whether the password contains the user's name
+            in some form.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
     <para>
       This module with no arguments will work well for standard unix
@@ -281,7 +298,7 @@
               than 10.
             </para>
             <para>
-              (N &gt; 0) This is the minimum number of upper
+              (N &lt; 0) This is the minimum number of upper
               case letters that must be met for a new password.
             </para>
           </listitem>
@@ -349,6 +366,50 @@
 
         <varlistentry>
           <term>
+            <option>minclass=<replaceable>N</replaceable></option>
+          </term>
+          <listitem>
+            <para>
+              The minimum number of required classes of characters for
+              the new password. The default number is zero. The four
+              classes are digits, upper and lower letters and other
+              characters.
+              The difference to the <option>credit</option> check is
+              that a specific class if of characters is not required.
+              Instead <replaceable>N</replaceable> out of four of the
+              classes are required.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>maxrepeat=<replaceable>N</replaceable></option>
+          </term>
+          <listitem>
+            <para>
+              Reject passwords which contain more than N same consecutive
+              characters. The default is 0 which means that this check
+              is disabled.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
+            <option>reject_username</option>
+          </term>
+          <listitem>
+            <para>
+              Check whether the name of the user in straight or reversed
+              form is contained in the new password. If it is found the
+              new password is rejected.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>
             <option>use_authtok</option>
           </term>
           <listitem>
@@ -495,7 +556,7 @@ password  required pam_unix.so use_autht
 	<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>,
       <citerefentry>
-	<refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum>
+	<refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>,
       <citerefentry>
 	<refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
diff -up Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.c.pwquality Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.c
--- Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.c.pwquality	2008-09-23 15:06:40.000000000 +0200
+++ Linux-PAM-1.0.2/modules/pam_cracklib/pam_cracklib.c	2008-09-23 15:10:14.000000000 +0200
@@ -99,6 +99,8 @@ struct cracklib_options {
         int min_class;
 	int use_authtok;
 	int try_first_pass;
+	int max_repeat;
+	int reject_user;
 	char prompt_type[BUFSIZ];
         const char *cracklib_dictpath;
 };
@@ -166,8 +168,14 @@ _pam_parse (pam_handle_t *pamh, struct c
              opt->min_class = strtol(*argv+9,&ep,10);
              if (!ep)
                  opt->min_class = 0;
-                 if (opt->min_class > 4)
-                     opt->min_class = 4 ;
+             if (opt->min_class > 4)
+                 opt->min_class = 4;
+         } else if (!strncmp(*argv,"maxrepeat=",10)) {
+             opt->max_repeat = strtol(*argv+10,&ep,10);
+             if (!ep)
+                 opt->max_repeat = 0;
+	 } else if (!strncmp(*argv,"reject_username",15)) {
+		 opt->reject_user = 1;
 	 } else if (!strncmp(*argv,"use_authtok",11)) {
 		 opt->use_authtok = 1;
 	 } else if (!strncmp(*argv,"use_first_pass",14)) {
@@ -418,6 +426,58 @@ static int simple(struct cracklib_option
     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 usercheck(struct cracklib_options *opt, const char *new,
+		     char *user)
+{
+    char *f, *b;
+
+    if (!opt->reject_user)
+	return 0;
+
+    if (strstr(new, user) != NULL)
+	return 1;
+
+    /* now reverse the username, we can do that in place
+       as it is strdup-ed */
+    f = user;
+    b = user+strlen(user)-1;    
+    while (f < b) {
+	char c;
+
+	c = *f;
+	*f = *b;
+	*b = c;
+	--b;
+	++f;
+    }
+
+    if (strstr(new, user) != NULL)
+	return 1;
+    return 0;
+}
+
 static char * str_lower(char *string)
 {
 	char *cp;
@@ -428,10 +488,12 @@ static char * str_lower(char *string)
 }
 
 static const char *password_check(struct cracklib_options *opt,
-				  const char *old, const char *new)
+				  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");
@@ -439,6 +501,7 @@ static const char *password_check(struct
 	}
 
 	newmono = str_lower(x_strdup(new));
+	usermono = str_lower(x_strdup(user));
 	if (old) {
 	  oldmono = str_lower(x_strdup(old));
 	  wrapped = malloc(strlen(oldmono) * 2 + 1);
@@ -464,8 +527,15 @@ static const char *password_check(struct
 	if (!msg && minclass (opt, new))
 	        msg = _("not enough character classes");
 
+	if (!msg && consecutive(opt, new))
+	        msg = _("contains too many same characters consecutively");
+
+	if (!msg && usercheck(opt, newmono, usermono))
+	        msg = _("contains the user name in some form");
+
 	memset(newmono, 0, strlen(newmono));
 	free(newmono);
+	free(usermono);
 	if (old) {
 	  memset(oldmono, 0, strlen(oldmono));
 	  memset(wrapped, 0, strlen(wrapped));
@@ -532,18 +602,18 @@ static int _pam_unix_approve_pass(pam_ha
         return PAM_AUTHTOK_ERR;
     }
 
+    retval = pam_get_item(pamh, PAM_USER, &user);
+    if (retval != PAM_SUCCESS || user == NULL) {
+	if (ctrl & PAM_DEBUG_ARG)
+		pam_syslog(pamh,LOG_ERR,"Can not get username");
+	return PAM_AUTHTOK_ERR;
+    }
     /*
      * if one wanted to hardwire authentication token strength
      * checking this would be the place
      */
-    msg = password_check(opt, pass_old, pass_new);
+    msg = password_check(opt, pass_old, pass_new, user);
     if (!msg) {
-	retval = pam_get_item(pamh, PAM_USER, &user);
-	if (retval != PAM_SUCCESS || user == NULL) {
-	    if (ctrl & PAM_DEBUG_ARG)
-		pam_syslog(pamh,LOG_ERR,"Can not get username");
-	    return PAM_AUTHTOK_ERR;
-	}
 	msg = check_old_password(user, pass_new);
     }