summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Mraz <tmraz@redhat.com>2011-12-07 16:53:47 +0100
committerTomas Mraz <tmraz@redhat.com>2011-12-07 16:53:47 +0100
commit965d6e2410e6f9fb4415c7d2be4603d0912f7ad5 (patch)
treec752e5e664df02fcff1b9d7316fbca95c89ceed0 /src
parente5f3076c599bdeb4a6ec31a718876614039a0339 (diff)
downloadlibpwquality-965d6e2410e6f9fb4415c7d2be4603d0912f7ad5.tar.gz
Check for arbitrary list of forbidden words.
Diffstat (limited to 'src')
-rw-r--r--src/check.c74
-rw-r--r--src/error.c2
-rw-r--r--src/pwqprivate.h1
-rw-r--r--src/pwquality.h7
-rw-r--r--src/settings.c8
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;