94ef2ca6a9
OBS-URL: https://build.opensuse.org/request/show/849367 OBS-URL: https://build.opensuse.org/package/show/Linux-PAM/pam?expand=0&rev=226
100 lines
2.9 KiB
Diff
100 lines
2.9 KiB
Diff
Index: Linux-PAM-1.4.0/modules/pam_cracklib/pam_cracklib.c
|
|
===================================================================
|
|
--- Linux-PAM-1.4.0.orig/modules/pam_cracklib/pam_cracklib.c
|
|
+++ Linux-PAM-1.4.0/modules/pam_cracklib/pam_cracklib.c
|
|
@@ -88,6 +88,7 @@ struct cracklib_options {
|
|
int reject_user;
|
|
int gecos_check;
|
|
int enforce_for_root;
|
|
+ int user_substr;
|
|
const char *cracklib_dictpath;
|
|
};
|
|
|
|
@@ -100,6 +101,7 @@ 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 int
|
|
_pam_parse (pam_handle_t *pamh, struct cracklib_options *opt,
|
|
@@ -185,6 +187,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);
|
|
}
|
|
@@ -525,13 +531,54 @@ static int wordcheck(const char *new, ch
|
|
return 0;
|
|
}
|
|
|
|
-static int usercheck(struct cracklib_options *opt, const char *new,
|
|
+/*
|
|
+ * RETURNS: True if the password is unacceptable, else false
|
|
+ */
|
|
+static int usersubstr(pam_handle_t *pamh, 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(pam_handle_t *pamh, 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(pamh, opt->user_substr, new, user);
|
|
|
|
- return wordcheck(new, user);
|
|
+ return bad;
|
|
}
|
|
|
|
static char * str_lower(char *string)
|
|
@@ -646,7 +693,7 @@ static const char *password_check(pam_ha
|
|
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)))
|
|
+ if (!msg && (usercheck(pamh, opt, newmono, usermono) || gecoscheck(pamh, opt, newmono, user)))
|
|
msg = _("contains the user name in some form");
|
|
|
|
free(usermono);
|