File pam-pam_cracklib-add-usersubstr.patch of Package pam

Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.c
===================================================================
--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.c
+++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.c
@@ -106,6 +106,7 @@ struct cracklib_options {
 	int reject_user;
         int gecos_check;
         int enforce_for_root;
+	int user_substr;
         const char *cracklib_dictpath;
 };
 
@@ -118,6 +119,15 @@ struct cracklib_options {
 #define CO_LOW_CREDIT   1
 #define CO_OTH_CREDIT   1
 #define CO_MIN_WORD_LENGTH 4
+#define CO_MIN_WORD_LENGTH      4
+
+static inline const char *
+pam_str_skip_prefix(const char *str, const char *prefix)
+{
+    size_t prefix_len = strlen(prefix);
+
+    return strncmp(str, prefix, prefix_len) ? NULL : str + prefix_len;
+}
 
 static int
 _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt,
@@ -127,6 +137,7 @@ _pam_parse (pam_handle_t *pamh, struct c
 
      /* step through arguments */
      for (ctrl=0; argc-- > 0; ++argv) {
+	 const char *str;
 	 char *ep = NULL;
 
 	 /* generic options */
@@ -202,6 +213,10 @@ _pam_parse (pam_handle_t *pamh, struct c
 	     if (!*(opt->cracklib_dictpath)) {
 		 opt->cracklib_dictpath = CRACKLIB_DICTS;
 	     }
+	 } else if ((str = pam_str_skip_prefix(*argv, "usersubstr=")) != NULL) {
+	     opt->user_substr = strtol(str, &ep, 10);
+	     if (ep == str)
+	         opt->user_substr = 0;
 	 } else {
 	     pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv);
 	 }
@@ -542,13 +557,54 @@ static int wordcheck(const char *new, ch
     return 0;
 }
 
+/*
+ * RETURNS: True if the password is unacceptable, else false
+ */
+static int usersubstr(int len, const char *new, char *user)
+{
+    int i, userlen;
+    int bad = 0;	// Assume it's OK unless proven otherwise
+    char *subuser = calloc(len+1, sizeof(char));
+
+    if (subuser == NULL) {
+	return 1;
+    }
+
+    userlen = strlen(user);
+
+    if (len >= CO_MIN_WORD_LENGTH &&
+	    userlen > len) {
+	for(i = 0; !bad && (i <= userlen - len); i++) {
+	    strncpy(subuser, user+i, len+1);
+	    subuser[len] = '\0';
+	    bad = wordcheck(new, subuser);
+	}
+    } else {
+	// if we already tested substrings, there's no need to test
+	// the whole username; all substrings would've been found :)
+	if (!bad)
+	    bad = wordcheck(new, user);
+    }
+
+    free(subuser);
+
+    return bad;
+}
+
+/*
+ * RETURNS: True if the password is unacceptable, else false
+ */
 static int usercheck(struct cracklib_options *opt, const char *new,
 		     char *user)
 {
-    if (!opt->reject_user)
-        return 0;
+    int bad = 0;
+
+    if (opt->reject_user)
+        bad = wordcheck(new, user);
+    if (!bad && opt->user_substr != 0)
+       bad = usersubstr(opt->user_substr, new, user);
 
-    return wordcheck(new, user);
+    return bad;
 }
 
 static char * str_lower(char *string)
Index: Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt
===================================================================
--- Linux-PAM-1.3.0.orig/doc/sag/Linux-PAM_SAG.txt
+++ Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt
@@ -990,6 +990,14 @@ reject_username
     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.
 
+usersubstr=N
+
+    Reject passwords which contain any substring of N or more consecutive
+    characters of the user's name straight or in reverse order.
+    N must be at least 4 for this to be applicable.
+    Also, usernames shorter than N are not checked.
+    If such a substring is found, the password is rejected.
+
 gecoscheck
 
     Check whether the words from the GECOS field (usualy full name of the user)
Index: Linux-PAM-1.3.0/doc/sag/html/sag-pam_cracklib.html
===================================================================
--- Linux-PAM-1.3.0.orig/doc/sag/html/sag-pam_cracklib.html
+++ Linux-PAM-1.3.0/doc/sag/html/sag-pam_cracklib.html
@@ -197,6 +197,15 @@
               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.
+	    </p></dd><dt><span class="term">
+	    <code class="option">usersubstr=<em class="replaceable"><code>N</code></em></code>
+	  </span></dt><dd><p>
+	      Reject passwords which contain any substring of N or more
+	      consecutive characters of the user's name straight or in
+	      reverse order.
+	      N must be at least 4 for this to be applicable.
+	      Also, usernames shorter than N are not checked.
+	      If such a substring is found, the password is rejected.
             </p></dd><dt><span class="term">
             <code class="option">gecoscheck</code>
           </span></dt><dd><p>
Index: Linux-PAM-1.3.0/modules/pam_cracklib/README
===================================================================
--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/README
+++ Linux-PAM-1.3.0/modules/pam_cracklib/README
@@ -179,6 +179,14 @@ reject_username
     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.
 
+usersubstr=N
+
+    Reject passwords which contain any substring of N or more consecutive
+    characters of the user's name straight or in reverse order.
+    N must be at least 4 for this to be applicable.
+    Also, usernames shorter than N are not checked.
+    If such a substring is found, the password is rejected.
+
 gecoscheck
 
     Check whether the words from the GECOS field (usualy full name of the user)
Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8
===================================================================
--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.8
+++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8
@@ -232,6 +232,15 @@ Reject passwords which contain more than
 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\&.
 .RE
 .PP
+\fBusersubstr=\fR\fB\fIN\fR\fR
+.RS 4
+Reject passwords which contain any substring of N or more consecutive characters of the user\*(Aqs name straight or in
+reverse order\&.
+N must be at least 4 for this to be applicable\&.
+Also, usernames shorter than N are not checked\&.
+If such a substring is found, the password is rejected\&.
+.RE
+.PP
 \fBgecoscheck\fR
 .RS 4
 Check whether the words from the GECOS field (usualy full name of the user) longer than 3 characters in straight or reversed form are contained in the new password\&. If any such word is found the new password is rejected\&.
Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8.xml
===================================================================
--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.8.xml
+++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8.xml
@@ -396,6 +396,21 @@
           </listitem>
         </varlistentry>
 
+	<varlistentry>
+	  <term>
+	    <option>usersubstr=<replaceable>N</replaceable></option>
+	  </term>
+	  <listitem>
+	    <para>
+	      Reject passwords which contain any substring of N or more
+	      consecutive characters of the user's name straight or in
+	      reverse order. N must be at least 4 for this to be applicable.
+	      Also, usernames shorter than N are not checked.
+	      If such a substring is found, the password is rejected.
+	    </para>
+          </listitem>
+	</varlistentry>
+
         <varlistentry>
           <term>
             <option>gecoscheck</option>
openSUSE Build Service is sponsored by