2 * Password strength checks based on the principal.
4 * Performs various checks of the password against the principal for which the
5 * password is being changed, trying to detect and reject passwords based on
6 * components of the principal.
8 * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
9 * on behalf of Stanford University.
10 * Extensive modifications by Russ Allbery <rra@stanford.edu>
11 * Copyright 2006, 2007, 2009, 2012, 2013
12 * The Board of Trustees of the Leland Stanford Junior Unversity
14 * See LICENSE for licensing terms.
18 #include <portable/system.h>
22 #include <plugin/internal.h>
23 #include <util/macros.h>
27 * Check whether the password is based in some way on the principal. Returns
28 * 0 if it is not and some non-zero error code if it appears to be.
31 strength_check_principal(krb5_context ctx, krb5_pwqual_moddata data UNUSED,
32 const char *principal, const char *password)
40 * We get the principal (in krb5_unparse_name format) and we want to be
41 * sure that the password doesn't match the username, the username
42 * reversed, or the username with trailing digits. We therefore have to
43 * copy the string so that we can manipulate it a bit.
45 if (strcasecmp(password, principal) == 0)
46 return strength_error_generic(ctx, ERROR_USERNAME);
47 user = strdup(principal);
49 return strength_error_system(ctx, "cannot allocate memory");
51 /* Strip the realm off of the principal. */
52 for (p = user; p[0] != '\0'; p++) {
53 if (p[0] == '\\' && p[1] != '\0') {
64 * If the length of the password matches the length of the local portion
65 * of the principal, check for exact matches or reversed matches.
67 if (strlen(password) == strlen(user)) {
68 if (strcasecmp(password, user) == 0) {
70 return strength_error_generic(ctx, ERROR_USERNAME);
73 /* Check against the reversed username. */
74 for (i = 0, j = strlen(user) - 1; i < j; i++, j--) {
79 if (strcasecmp(password, user) == 0) {
81 return strength_error_generic(ctx, ERROR_USERNAME);
86 * If the length is greater, check whether the user just added trailing
87 * digits to the local portion of the principal to form the password.
89 if (strlen(password) > strlen(user))
90 if (strncasecmp(password, user, strlen(user)) == 0) {
91 q = password + strlen(user);
92 while (isdigit((unsigned char) *q))
96 return strength_error_generic(ctx, ERROR_USERNAME);
100 /* Password does not appear to be based on the principal. */