changeset 2638433e50ad in /srv/hg/libpwquality details: http://hg.fedorahosted.org/hg/srv/hg/libpwquality?cmd=changeset;node=2638433... summary: Check for arbitrary list of forbidden words.
diffstat:
doc/man/pam_pwquality.8 | 7 +++ doc/man/pwquality.conf.5 | 8 ++++ src/check.c | 74 +++++++++++++++++++++++++------------ src/error.c | 2 + src/pwqprivate.h | 1 + src/pwquality.h | 7 +++- src/settings.c | 8 ++++ 7 files changed, 82 insertions(+), 25 deletions(-)
diffs (244 lines):
diff -r 314db03fc507 -r 2638433e50ad doc/man/pam_pwquality.8 --- a/doc/man/pam_pwquality.8 Wed Dec 07 16:06:05 2011 +0100 +++ b/doc/man/pam_pwquality.8 Wed Dec 07 16:53:47 2011 +0100 @@ -233,6 +233,13 @@ The default is 0 which means that this check is disabled&. .RE .PP +\fBbadwords=\fR\fB\fI<list of words>\fR\fR +.RS 4 +The words more than 3 characters long from this space separated list are +individually searched for and forbidden in the new password&. +By default the list is empty which means that this check is disabled&. +.RE +.PP \fBuse_authtok\fR .RS 4 This argument is used to diff -r 314db03fc507 -r 2638433e50ad doc/man/pwquality.conf.5 --- a/doc/man/pwquality.conf.5 Wed Dec 07 16:06:05 2011 +0100 +++ b/doc/man/pwquality.conf.5 Wed Dec 07 16:53:47 2011 +0100 @@ -93,6 +93,14 @@ The check is disabled if the value is 0. (default 0) .RE .PP +\fBbadwords\fR +.RS 4 +Space separated list of words that must not be contained in the password. These +are additional words to the cracklib dictionary check. This setting can be +also used by applications to emulate the gecos check for user accounts that are +not created yet. +.RE +.PP \fBdictpath\fR .RS 4 Path to the cracklib dictionaries. Default is to use the cracklib default. diff -r 314db03fc507 -r 2638433e50ad src/check.c --- a/src/check.c Wed Dec 07 16:06:05 2011 +0100 +++ b/src/check.c Wed Dec 07 16:53:47 2011 +0100 @@ -382,6 +382,42 @@ }
static int +wordlistcheck(pwquality_settings_t *pwq, const char *new, + const char *wordlist) +{ + char *list; + char *p; + char *next; + + if (wordlist == NULL) + return 0; + + if ((list = strdup(wordlist)) == NULL) { + return PWQ_ERROR_MEM_ALLOC; + } + + for (p = list;;p = next + 1) { + next = strchr(p, ' '); + if (next) + *next = '\0'; + + if (strlen(p) >= PWQ_MIN_WORD_LENGTH) { + str_lower(p); + if (usercheck(pwq, new, p)) { + free(list); + return PWQ_ERROR_BAD_WORDS; + } + } + + if (!next) + break; + } + + free(list); + return 0; +} + +static int gecoscheck(pwquality_settings_t *pwq, const char *new, const char *user) { @@ -389,8 +425,7 @@ struct passwd *result; char *buf; size_t bufsize; - char *p; - char *next; + int rv;
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize == -1 || bufsize > PWQ_MAX_PASSWD_BUF_LEN) @@ -403,26 +438,14 @@ result == NULL) { free(buf); return 0; - } - - for (p = result->pw_gecos;;p = next + 1) { - next = strchr(p, ' '); - if (next) - *next = '\0'; - - if (strlen(p) >= PWQ_MIN_WORD_LENGTH) { - str_lower(p); - if (usercheck(pwq, new, p)) { - free(buf); - return PWQ_ERROR_GECOS_CHECK; - } - } - - if (!next) - break; }
- return 0; + rv = wordlistcheck(pwq, new, result->pw_gecos); + if (rv == PWQ_ERROR_BAD_WORDS) + rv = PWQ_ERROR_GECOS_CHECK; + + free(buf); + return rv; }
static char * @@ -495,6 +518,9 @@ if (!rv && user && pwq->gecos_check) rv = gecoscheck(pwq, newmono, user);
+ if (!rv) + rv = wordlistcheck(pwq, newmono, pwq->bad_words); + if (newmono) { memset(newmono, 0, strlen(newmono)); free(newmono); @@ -554,19 +580,19 @@
memset(buf, 0, len); free(buf); - + score += numclass(pwq, password) * 2;
score = (score * 100)/(3 * pwq->min_length + + PWQ_NUM_CLASSES * 2); - + score -= 50; - + if (score > 100) score = 100; if (score < 0) score = 0; - + return score; }
diff -r 314db03fc507 -r 2638433e50ad src/error.c --- a/src/error.c Wed Dec 07 16:06:05 2011 +0100 +++ b/src/error.c Wed Dec 07 16:53:47 2011 +0100 @@ -45,6 +45,8 @@ return _("The password contains the user name in some form"); case PWQ_ERROR_GECOS_CHECK: return _("The password contains words from the real name of the user in some form"); + case PWQ_ERROR_BAD_WORDS: + return _("The password contains forbidden words in some form"); case PWQ_ERROR_MIN_DIGITS: if (auxerror) { snprintf(buf, len, _("The password contains less than %ld digits"), (long)auxerror); diff -r 314db03fc507 -r 2638433e50ad src/pwqprivate.h --- a/src/pwqprivate.h Wed Dec 07 16:06:05 2011 +0100 +++ b/src/pwqprivate.h Wed Dec 07 16:53:47 2011 +0100 @@ -23,6 +23,7 @@ int max_repeat; int max_class_repeat; int gecos_check; + char *bad_words; char *dict_path; };
diff -r 314db03fc507 -r 2638433e50ad src/pwquality.h --- a/src/pwquality.h Wed Dec 07 16:06:05 2011 +0100 +++ b/src/pwquality.h Wed Dec 07 16:53:47 2011 +0100 @@ -21,6 +21,7 @@ #define PWQ_SETTING_DICT_PATH 10 #define PWQ_SETTING_MAX_CLASS_REPEAT 11 #define PWQ_SETTING_GECOS_CHECK 12 +#define PWQ_SETTING_BAD_WORDS 13
#define PWQ_MAX_ENTROPY_BITS 256 #define PWQ_MIN_ENTROPY_BITS 56 @@ -55,6 +56,7 @@ #define PWQ_ERROR_USER_CHECK -25 #define PWQ_ERROR_GECOS_CHECK -26 #define PWQ_ERROR_MAX_CLASS_REPEAT -27 +#define PWQ_ERROR_BAD_WORDS -28
typedef struct pwquality_settings pwquality_settings_t;
@@ -91,7 +93,10 @@ int pwquality_get_int_value(pwquality_settings_t *pwq, int setting, int *value);
-/* Get value of a string setting. */ +/* Get value of a string setting. + * The caller must copy the string before another calls that can + * manipulate the pwq settings object. + */ int pwquality_get_str_value(pwquality_settings_t *pwq, int setting, const char **value);
diff -r 314db03fc507 -r 2638433e50ad src/settings.c --- a/src/settings.c Wed Dec 07 16:06:05 2011 +0100 +++ b/src/settings.c Wed Dec 07 16:53:47 2011 +0100 @@ -58,6 +58,7 @@ { "maxrepeat", PWQ_SETTING_MAX_REPEAT, PWQ_TYPE_INT}, { "maxclassrepeat", PWQ_SETTING_MAX_CLASS_REPEAT, PWQ_TYPE_INT}, { "gecoscheck", PWQ_SETTING_GECOS_CHECK, PWQ_TYPE_INT}, + { "badwords", PWQ_SETTING_BAD_WORDS, PWQ_TYPE_STR}, { "dictpath", PWQ_SETTING_DICT_PATH, PWQ_TYPE_STR} };
@@ -270,6 +271,10 @@ }
switch(setting) { + case PWQ_SETTING_BAD_WORDS: + free(pwq->bad_words); + pwq->bad_words = dup; + break; case PWQ_SETTING_DICT_PATH: free(pwq->dict_path); pwq->dict_path = dup; @@ -328,6 +333,9 @@ pwquality_get_str_value(pwquality_settings_t *pwq, int setting, const char **value) { switch(setting) { + case PWQ_SETTING_BAD_WORDS: + *value = pwq->bad_words; + break; case PWQ_SETTING_DICT_PATH: *value = pwq->dict_path; break;
libpwquality-commits@lists.fedorahosted.org