2020-11-19 12:13:17 +01:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2020-11-19 14:56:42 +01:00
|
|
|
@@ -185,6 +186,10 @@ _pam_parse (pam_handle_t *pamh, struct c
|
2020-11-19 12:13:17 +01:00
|
|
|
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);
|
|
|
|
}
|
2020-11-19 14:56:42 +01:00
|
|
|
@@ -525,13 +530,54 @@ static int wordcheck(const char *new, ch
|
2020-11-19 12:13:17 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * RETURNS: True if the password is unacceptable, else false
|
|
|
|
+ */
|
2020-11-19 14:56:42 +01:00
|
|
|
+static int usersubstr(int len, const char *new, char *user)
|
2020-11-19 12:13:17 +01:00
|
|
|
+{
|
|
|
|
+ int i, userlen;
|
2020-11-19 14:56:42 +01:00
|
|
|
+ int bad = 0; // Assume it's OK unless proven otherwise
|
2020-11-19 12:13:17 +01:00
|
|
|
+ char *subuser = calloc(len+1, sizeof(char));
|
|
|
|
+
|
|
|
|
+ if (subuser == NULL) {
|
2020-11-19 14:56:42 +01:00
|
|
|
+ return 1;
|
2020-11-19 12:13:17 +01:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ userlen = strlen(user);
|
|
|
|
+
|
|
|
|
+ if (len >= CO_MIN_WORD_LENGTH &&
|
2020-11-19 14:56:42 +01:00
|
|
|
+ userlen > len) {
|
|
|
|
+ for(i = 0; !bad && (i <= userlen - len); i++) {
|
|
|
|
+ strncpy(subuser, user+i, len+1);
|
|
|
|
+ subuser[len] = '\0';
|
|
|
|
+ bad = wordcheck(new, subuser);
|
|
|
|
+ }
|
2020-11-19 12:13:17 +01:00
|
|
|
+ } else {
|
2020-11-19 14:56:42 +01:00
|
|
|
+ // 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);
|
2020-11-19 12:13:17 +01:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ free(subuser);
|
|
|
|
+
|
|
|
|
+ return bad;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * RETURNS: True if the password is unacceptable, else false
|
|
|
|
+ */
|
2020-11-19 14:56:42 +01:00
|
|
|
static int usercheck(struct cracklib_options *opt, const char *new,
|
2020-11-19 12:13:17 +01:00
|
|
|
char *user)
|
|
|
|
{
|
|
|
|
- if (!opt->reject_user)
|
|
|
|
- return 0;
|
|
|
|
+ int bad = 0;
|
|
|
|
+
|
|
|
|
+ if (opt->reject_user)
|
2020-11-19 14:56:42 +01:00
|
|
|
+ bad = wordcheck(new, user);
|
2020-11-19 12:13:17 +01:00
|
|
|
+ if (!bad && opt->user_substr != 0)
|
2020-11-19 14:56:42 +01:00
|
|
|
+ bad = usersubstr(opt->user_substr, new, user);
|
2020-11-19 12:13:17 +01:00
|
|
|
|
|
|
|
- return wordcheck(new, user);
|
|
|
|
+ return bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char * str_lower(char *string)
|