changeset 11e238259d43 in /srv/hg/libpwquality
details:
http://hg.fedorahosted.org/hg/srv/hg/libpwquality?cmd=changeset;node=11e2...
summary: Add a check against username.
diffstat:
src/check.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/error.c | 2 ++
src/generate.c | 2 +-
src/pam_pwquality.c | 10 +++++++++-
src/pwquality.h | 5 ++++-
src/pwscore.c | 11 ++++++++---
6 files changed, 77 insertions(+), 9 deletions(-)
diffs (233 lines):
diff -r 56e5589380fe -r 11e238259d43 src/check.c
--- a/src/check.c Mon Oct 03 16:26:48 2011 +0200
+++ b/src/check.c Tue Nov 01 14:12:22 2011 +0100
@@ -296,6 +296,43 @@
return 0;
}
+static int usercheck(pwquality_settings_t *pwq, const char *new,
+ char *user)
+{
+ char *f, *b;
+ int dist;
+
+ if (strstr(new, user) != NULL)
+ return 1;
+
+ dist = distance(new, user);
+ if (dist >= 0 && dist < PWQ_DEFAULT_DIFF_OK)
+ return 1;
+
+ /* now reverse the username, we can do that in place
+ as it is strdup-ed */
+ f = user;
+ b = user + strlen(user) - 1;
+ while (f < b) {
+ char c;
+
+ c = *f;
+ *f = *b;
+ *b = c;
+ --b;
+ ++f;
+ }
+
+ if (strstr(new, user) != NULL)
+ return 1;
+
+ dist = distance(new, user);
+ if (dist >= 0 && dist < PWQ_DEFAULT_DIFF_OK)
+ return 1;
+
+ return 0;
+}
+
static char *
str_lower(char *string)
{
@@ -319,15 +356,23 @@
static int
password_check(pwquality_settings_t *pwq,
- const char *new, const char *old, void **auxerror)
+ const char *new, const char *old, const char *user,
+ void **auxerror)
{
int rv = 0;
char *oldmono = NULL, *newmono, *wrapped = NULL;
+ char *usermono = NULL;
newmono = str_lower(x_strdup(new));
if (!newmono)
rv = PWQ_ERROR_MEM_ALLOC;
+ if (!rv && user) {
+ usermono = str_lower(x_strdup(user));
+ if (!usermono)
+ rv = PWQ_ERROR_MEM_ALLOC;
+ }
+
if (!rv && old) {
oldmono = str_lower(x_strdup(old));
if (oldmono)
@@ -365,11 +410,16 @@
if (!rv && consecutive(pwq, new, auxerror))
rv = PWQ_ERROR_MAX_CONSECUTIVE;
+ if (!rv && usermono && usercheck(pwq, newmono, usermono))
+ rv = PWQ_ERROR_USER_CHECK;
+
if (newmono) {
memset(newmono, 0, strlen(newmono));
free(newmono);
}
+ free(usermono);
+
if (oldmono) {
memset(oldmono, 0, strlen(oldmono));
free(oldmono);
@@ -443,7 +493,7 @@
* the old password is optional */
int
pwquality_check(pwquality_settings_t *pwq, const char *password,
- const char *oldpassword, void **auxerror)
+ const char *oldpassword, const char *user, void **auxerror)
{
const char *msg;
int score;
@@ -466,7 +516,7 @@
return PWQ_ERROR_CRACKLIB_CHECK;
}
- score = password_check(pwq, password, oldpassword, auxerror);
+ score = password_check(pwq, password, oldpassword, user, auxerror);
if (score == 0) {
score = password_score(pwq, password);
}
diff -r 56e5589380fe -r 11e238259d43 src/error.c
--- a/src/error.c Mon Oct 03 16:26:48 2011 +0200
+++ b/src/error.c Tue Nov 01 14:12:22 2011 +0100
@@ -41,6 +41,8 @@
return _("The password differs with case changes only");
case PWQ_ERROR_TOO_SIMILAR:
return _("The password is too similar to the old one");
+ case PWQ_ERROR_USER_CHECK:
+ return _("The password contains the user name in some form");
case PWQ_ERROR_MIN_DIGITS:
if (auxerror) {
snprintf(buf, len, _("The password contains less than %ld
digits"), (long)auxerror);
diff -r 56e5589380fe -r 11e238259d43 src/generate.c
--- a/src/generate.c Mon Oct 03 16:26:48 2011 +0200
+++ b/src/generate.c Tue Nov 01 14:12:22 2011 +0100
@@ -157,7 +157,7 @@
*ptr = consonants1[idx];
++ptr;
}
- } while (pwquality_check(pwq, tmp, NULL, NULL) < 0 &&
+ } while (pwquality_check(pwq, tmp, NULL, NULL, NULL) < 0 &&
++try < PWQ_NUM_GENERATION_TRIES);
/* clean up */
diff -r 56e5589380fe -r 11e238259d43 src/pam_pwquality.c
--- a/src/pam_pwquality.c Mon Oct 03 16:26:48 2011 +0200
+++ b/src/pam_pwquality.c Tue Nov 01 14:12:22 2011 +0100
@@ -123,8 +123,16 @@
} else if (flags & PAM_UPDATE_AUTHTOK) {
int retval;
const void *oldtoken;
+ const char *user;
int tries;
+ retval = pam_get_user(pamh, &user, NULL);
+ if (retval != PAM_SUCCESS || user == NULL) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh, LOG_ERR, "Can not get
username");
+ return PAM_AUTHTOK_ERR;
+ }
+
retval = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldtoken);
if (retval != PAM_SUCCESS) {
if (ctrl & PAM_DEBUG_ARG)
@@ -157,7 +165,7 @@
}
/* now test this passwd against libpwquality */
- retval = pwquality_check(options.pwq, newtoken, oldtoken,
&auxerror);
+ retval = pwquality_check(options.pwq, newtoken, oldtoken, user,
&auxerror);
if (retval < 0) {
const char *msg;
diff -r 56e5589380fe -r 11e238259d43 src/pwquality.h
--- a/src/pwquality.h Mon Oct 03 16:26:48 2011 +0200
+++ b/src/pwquality.h Tue Nov 01 14:12:22 2011 +0100
@@ -51,6 +51,7 @@
#define PWQ_ERROR_CRACKLIB_CHECK -22
#define PWQ_ERROR_RNG -23
#define PWQ_ERROR_GENERATION_FAILED -24
+#define PWQ_ERROR_USER_CHECK -25
typedef struct pwquality_settings pwquality_settings_t;
@@ -102,6 +103,8 @@
* and possibly also auxiliary error information that must be
* passed into pwquality_strerror() function.
* The old password is optional and can be NULL.
+ * The user is used for checking the password against user name
+ * and potentially other passwd information and can be NULL.
* The auxerror can be NULL - in that case the auxiliary error information
* is not returned.
* Not passing the *auxerror into pwquality_strerror() can lead to memory leaks.
@@ -109,7 +112,7 @@
* the score for the same passwords will be lower. */
int
pwquality_check(pwquality_settings_t *pwq, const char *password,
- const char *oldpassword, void **auxerror);
+ const char *oldpassword, const char *user, void **auxerror);
/* Translate the error code and auxiliary message into a localized
* text message.
diff -r 56e5589380fe -r 11e238259d43 src/pwscore.c
--- a/src/pwscore.c Mon Oct 03 16:26:48 2011 +0200
+++ b/src/pwscore.c Tue Nov 01 14:12:22 2011 +0100
@@ -18,7 +18,7 @@
int
usage(const char *progname) {
- fprintf(stderr, _("Usage: %s\n"), progname);
+ fprintf(stderr, _("Usage: %s [user]\n"), progname);
fprintf(stderr, _(" The command reads the password to be scored from
the standard input.\n"));
}
@@ -31,16 +31,21 @@
void *auxerror;
char buf[1024];
size_t len;
+ char *user = NULL;
setlocale(LC_ALL, "");
bindtextdomain("libpwquality", "/usr/share/locale");
textdomain("libpwquality");
- if (argc != 1) {
+ if (argc > 2) {
usage(basename(argv[0]));
exit(3);
}
+ if (argc == 2) {
+ user = argv[1];
+ }
+
if (fgets(buf, sizeof(buf), stdin) == NULL || (len = strlen(buf)) == 0) {
fprintf(stderr, _("Error: %s\n"), _("Could not obtain the
password to be scored"));
exit(4);
@@ -59,7 +64,7 @@
exit(3);
}
- rv = pwquality_check(pwq, buf, NULL, &auxerror);
+ rv = pwquality_check(pwq, buf, NULL, user, &auxerror);
if (rv < 0) {
fprintf(stderr, _("Password quality check failed:\n %s\n"),