From a6086577a4f47e521b8b889efe5749b9036c0f3d Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Thu, 19 Jul 2007 06:15:11 +0000 Subject: [PATCH] The check of the password against the principal checked against the fully-qualified principal, which is not the usual problem. Additionally check that the password doesn't match the principal with the realm removed or the reverse of that (case-insensitive). --- NEWS | 7 +++++++ plugin/api.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 74d39d6..2dc2e3c 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ User-Visible krb5-strength Changes +krb5-strength 0.5 (2007-07-18) + + The check of the password against the principal checked against the + fully-qualified principal, which is not the usual problem. + Additionally check that the password doesn't match the principal with + the realm removed or the reverse of that (case-insensitive). + krb5-strength 0.4 (2007-03-28) The patches directory was omitted from the distribution. Really diff --git a/plugin/api.c b/plugin/api.c index 52f5100..247782f 100644 --- a/plugin/api.c +++ b/plugin/api.c @@ -68,14 +68,59 @@ int pwcheck_check(void *context, const char *password, const char *principal, char *errstr, int errstrlen) { + char *user, *p; + size_t i, j; + char c; const char *result; struct context *ctx = context; + /* + * We get the principal (in krb5_unparse_name format) from kadmind and we + * want to be sure that the password doesn't match the username or the + * username reversed. We therefore have to copy the string so that we can + * manipulate it a bit. + */ if (strcasecmp(password, principal) == 0) { - snprintf(errstr, errstrlen, "Password same as username"); + snprintf(errstr, errstrlen, "Password based on username"); errstr[errstrlen - 1] = '\0'; return 1; } + user = strdup(principal); + if (user == NULL) { + snprintf(errstr, errstrlen, "Cannot allocate memory"); + errstr[errstrlen - 1] = '\0'; + return 1; + } + for (p = user; p[0] != '\0'; p++) { + if (p[0] == '\\' && p[1] != '\0') { + p++; + continue; + } + if (p[0] == '@') { + p[0] = '\0'; + break; + } + } + if (strlen(password) == strlen(user)) { + if (strcasecmp(password, user) == 0) { + free(user); + snprintf(errstr, errstrlen, "Password based on username"); + errstr[errstrlen - 1] = '\0'; + return 1; + } + for (i = 0, j = strlen(user) - 1; i < j; i++, j--) { + c = user[i]; + user[i] = user[j]; + user[j] = c; + } + if (strcasecmp(password, user) == 0) { + free(user); + snprintf(errstr, errstrlen, "Password based on username"); + errstr[errstrlen - 1] = '\0'; + return 1; + } + } + free(user); result = FascistCheck(password, ctx->dictionary); if (result != NULL) { strncpy(errstr, result, errstrlen); -- 2.39.2