diff options
author | Tomas Mraz <tmraz@redhat.com> | 2011-11-01 14:12:22 +0100 |
---|---|---|
committer | Tomas Mraz <tmraz@redhat.com> | 2011-11-01 14:12:22 +0100 |
commit | fc8869eb77d6e782f6d892862787b2a8b410aa91 (patch) | |
tree | 3d37f032ab171bdc6410739e9d4f49778916002f /src | |
parent | 7b9cf2921746d8f738f4aa1cedd8ce69bfccf120 (diff) | |
download | libpwquality-fc8869eb77d6e782f6d892862787b2a8b410aa91.tar.gz |
Add a check against username.
Diffstat (limited to 'src')
-rw-r--r-- | src/check.c | 56 | ||||
-rw-r--r-- | src/error.c | 2 | ||||
-rw-r--r-- | src/generate.c | 2 | ||||
-rw-r--r-- | src/pam_pwquality.c | 10 | ||||
-rw-r--r-- | src/pwquality.h | 5 | ||||
-rw-r--r-- | src/pwscore.c | 11 |
6 files changed, 77 insertions, 9 deletions
diff --git a/src/check.c b/src/check.c index 1b65409..2a42931 100644 --- a/src/check.c +++ b/src/check.c @@ -296,6 +296,43 @@ consecutive(pwquality_settings_t *pwq, const char *new, void **auxerror) 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 @@ x_strdup(const char *string) 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 @@ password_check(pwquality_settings_t *pwq, 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 @@ password_score(pwquality_settings_t *pwq, const char *password) * 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 @@ pwquality_check(pwquality_settings_t *pwq, const char *password, 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 --git a/src/error.c b/src/error.c index 790dbed..9a69741 100644 --- a/src/error.c +++ b/src/error.c @@ -41,6 +41,8 @@ pwquality_strerror(char *buf, size_t len, int rv, void *auxerror) 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 --git a/src/generate.c b/src/generate.c index 193e27b..50d3b52 100644 --- a/src/generate.c +++ b/src/generate.c @@ -157,7 +157,7 @@ pwquality_generate(pwquality_settings_t *pwq, int entropy_bits, char **password) *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 --git a/src/pam_pwquality.c b/src/pam_pwquality.c index 8c9e164..fb6a6e3 100644 --- a/src/pam_pwquality.c +++ b/src/pam_pwquality.c @@ -123,8 +123,16 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, } 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 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, } /* 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 --git a/src/pwquality.h b/src/pwquality.h index e6de079..f7fd8d5 100644 --- a/src/pwquality.h +++ b/src/pwquality.h @@ -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 @@ pwquality_generate(pwquality_settings_t *pwq, int entropy_bits, * 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 @@ pwquality_generate(pwquality_settings_t *pwq, int entropy_bits, * 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 --git a/src/pwscore.c b/src/pwscore.c index c9db396..0c99680 100644 --- a/src/pwscore.c +++ b/src/pwscore.c @@ -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 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) 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"), |