changeset 2638433e50ad in /srv/hg/libpwquality
details:
http://hg.fedorahosted.org/hg/srv/hg/libpwquality?cmd=changeset;node=2638...
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;