summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Mraz <tmraz@redhat.com>2011-11-01 14:12:22 +0100
committerTomas Mraz <tmraz@redhat.com>2011-11-01 14:12:22 +0100
commitfc8869eb77d6e782f6d892862787b2a8b410aa91 (patch)
tree3d37f032ab171bdc6410739e9d4f49778916002f /src
parent7b9cf2921746d8f738f4aa1cedd8ce69bfccf120 (diff)
downloadlibpwquality-fc8869eb77d6e782f6d892862787b2a8b410aa91.tar.gz
Add a check against username.
Diffstat (limited to 'src')
-rw-r--r--src/check.c56
-rw-r--r--src/error.c2
-rw-r--r--src/generate.c2
-rw-r--r--src/pam_pwquality.c10
-rw-r--r--src/pwquality.h5
-rw-r--r--src/pwscore.c11
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"),