diff options
author | Tomas Mraz <tmraz@redhat.com> | 2011-12-07 16:53:47 +0100 |
---|---|---|
committer | Tomas Mraz <tmraz@redhat.com> | 2011-12-07 16:53:47 +0100 |
commit | 965d6e2410e6f9fb4415c7d2be4603d0912f7ad5 (patch) | |
tree | c752e5e664df02fcff1b9d7316fbca95c89ceed0 /src | |
parent | e5f3076c599bdeb4a6ec31a718876614039a0339 (diff) | |
download | libpwquality-965d6e2410e6f9fb4415c7d2be4603d0912f7ad5.tar.gz |
Check for arbitrary list of forbidden words.
Diffstat (limited to 'src')
-rw-r--r-- | src/check.c | 74 | ||||
-rw-r--r-- | src/error.c | 2 | ||||
-rw-r--r-- | src/pwqprivate.h | 1 | ||||
-rw-r--r-- | src/pwquality.h | 7 | ||||
-rw-r--r-- | src/settings.c | 8 |
5 files changed, 67 insertions, 25 deletions
diff --git a/src/check.c b/src/check.c index ca815b0..372d352 100644 --- a/src/check.c +++ b/src/check.c @@ -382,30 +382,21 @@ str_lower(char *string) } static int -gecoscheck(pwquality_settings_t *pwq, const char *new, - const char *user) +wordlistcheck(pwquality_settings_t *pwq, const char *new, + const char *wordlist) { - struct passwd pwd; - struct passwd *result; - char *buf; - size_t bufsize; + char *list; char *p; char *next; - bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (bufsize == -1 || bufsize > PWQ_MAX_PASSWD_BUF_LEN) - bufsize = PWQ_MAX_PASSWD_BUF_LEN; - buf = malloc(bufsize); - if (buf == NULL) - return PWQ_ERROR_MEM_ALLOC; - - if (getpwnam_r(user, &pwd, buf, bufsize, &result) != 0 || - result == NULL) { - free(buf); + if (wordlist == NULL) return 0; - } - for (p = result->pw_gecos;;p = next + 1) { + if ((list = strdup(wordlist)) == NULL) { + return PWQ_ERROR_MEM_ALLOC; + } + + for (p = list;;p = next + 1) { next = strchr(p, ' '); if (next) *next = '\0'; @@ -413,8 +404,8 @@ gecoscheck(pwquality_settings_t *pwq, const char *new, if (strlen(p) >= PWQ_MIN_WORD_LENGTH) { str_lower(p); if (usercheck(pwq, new, p)) { - free(buf); - return PWQ_ERROR_GECOS_CHECK; + free(list); + return PWQ_ERROR_BAD_WORDS; } } @@ -422,9 +413,41 @@ gecoscheck(pwquality_settings_t *pwq, const char *new, break; } + free(list); return 0; } +static int +gecoscheck(pwquality_settings_t *pwq, const char *new, + const char *user) +{ + struct passwd pwd; + struct passwd *result; + char *buf; + size_t bufsize; + int rv; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1 || bufsize > PWQ_MAX_PASSWD_BUF_LEN) + bufsize = PWQ_MAX_PASSWD_BUF_LEN; + buf = malloc(bufsize); + if (buf == NULL) + return PWQ_ERROR_MEM_ALLOC; + + if (getpwnam_r(user, &pwd, buf, bufsize, &result) != 0 || + result == NULL) { + free(buf); + 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 * x_strdup(const char *string) { @@ -495,6 +518,9 @@ password_check(pwquality_settings_t *pwq, 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 @@ password_score(pwquality_settings_t *pwq, const char *password) 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 --git a/src/error.c b/src/error.c index cb4c89f..25e834b 100644 --- a/src/error.c +++ b/src/error.c @@ -45,6 +45,8 @@ pwquality_strerror(char *buf, size_t len, int rv, void *auxerror) 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 --git a/src/pwqprivate.h b/src/pwqprivate.h index 08b2d37..092a6f3 100644 --- a/src/pwqprivate.h +++ b/src/pwqprivate.h @@ -23,6 +23,7 @@ struct pwquality_settings { int max_repeat; int max_class_repeat; int gecos_check; + char *bad_words; char *dict_path; }; diff --git a/src/pwquality.h b/src/pwquality.h index 2ea40b1..e22b084 100644 --- a/src/pwquality.h +++ b/src/pwquality.h @@ -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 @@ pwquality_set_str_value(pwquality_settings_t *pwq, int setting, 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 --git a/src/settings.c b/src/settings.c index d2d3de9..a9976ed 100644 --- a/src/settings.c +++ b/src/settings.c @@ -58,6 +58,7 @@ static const struct setting_mapping s_map[] = { { "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 @@ pwquality_set_str_value(pwquality_settings_t *pwq, int setting, } 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 @@ int 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; |