* character from both start and end.
*
* Written by Russ Allbery <eagle@eyrie.org>
- * Copyright 2013, 2014
+ * Copyright 2013
* The Board of Trustees of the Leland Stanford Junior University
*
- * See LICENSE for licensing terms.
+ * SPDX-License-Identifier: MIT
*/
#include <config.h>
#include <portable/system.h>
#ifdef HAVE_CDB_H
-# include <cdb.h>
+# include <cdb.h>
#endif
-#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
if (path == NULL)
return 0;
free(path);
- krb5_set_error_message(ctx, KADM5_BAD_SERVER_PARAMS, "CDB dictionary"
- " requested but not built with CDB support");
+ krb5_set_error_message(ctx, KADM5_BAD_SERVER_PARAMS,
+ "CDB dictionary requested but not built with CDB"
+ " support");
return KADM5_BAD_SERVER_PARAMS;
}
#endif
/* Skip the rest of this file if CDB is not available. */
#ifdef HAVE_CDB
-/*
- * Macros used to make password checks more readable. Assumes that the found
- * and fail labels are available for the abort cases of finding a password or
- * failing to look it up.
- */
-# define CHECK_PASSWORD(ctx, data, password) \
- do { \
- code = in_cdb_dictionary(ctx, data, password, &found); \
- if (code != 0) \
- goto fail; \
- if (found) \
- goto found; \
- } while (0)
-# define CHECK_PASSWORD_VARIANT(ctx, data, template, p) \
- do { \
- code = variant_in_cdb_dictionary(ctx, data, template, p, &found); \
- if (code != 0) \
- goto fail; \
- if (found) \
- goto found; \
- } while (0)
-
-
/*
* Look up a password in CDB and set the found parameter to true if it is
* found, false otherwise. Returns a Kerberos status code, which will be 0 on
int status;
*found = false;
- status = cdb_find(&data->cdb, password, strlen(password));
+ status = cdb_find(&data->cdb, password, (unsigned int) strlen(password));
if (status < 0)
return strength_error_system(ctx, "cannot query CDB database");
else {
}
-/*
- * Given a password template and a pointer to the character to change, check
- * all versions of that template with that character replaced by all possible
- * printable ASCII characters. The template will be modified in place to try
- * the various characters. Sets the found parameter to true if some variation
- * of the template is found, false otherwise. Returns a Kerberos status code.
- */
-static krb5_error_code
-variant_in_cdb_dictionary(krb5_context ctx, krb5_pwqual_moddata data,
- char *template, char *permute, bool *found)
-{
- int c;
- krb5_error_code code;
-
- *found = false;
- for (c = 0; c <= 127; c++)
- if (isprint(c)) {
- *permute = c;
- code = in_cdb_dictionary(ctx, data, template, found);
- if (code != 0 || found)
- return code;
- }
- return 0;
-}
-
-
/*
* Initialize the CDB dictionary. Opens the dictionary and sets up the
* TinyCDB state. Returns 0 on success, non-zero on failure (and sets the
}
+/*
+ * Macro used to make password checks more readable. Assumes that the found
+ * and fail labels are available for the abort cases of finding a password or
+ * failing to look it up.
+ */
+# define CHECK_PASSWORD(ctx, data, password) \
+ do { \
+ code = in_cdb_dictionary(ctx, data, password, &found); \
+ if (code != 0) \
+ goto fail; \
+ if (found) \
+ goto found; \
+ } while (0)
+
+
/*
* Given a password, try the various transformations that we want to apply and
* check for each of them in the dictionary. Returns a Kerberos status code,
{
krb5_error_code code;
bool found;
- size_t length, i;
- char *p;
char *variant = NULL;
/* If we have no dictionary, there is nothing to do. */
/* Check the basic password. */
CHECK_PASSWORD(ctx, data, password);
- /* Allocate memory for password variations. */
- length = strlen(password);
- variant = malloc(length + 2);
- if (variant == NULL)
- return strength_error_system(ctx, "cannot allocate memory");
-
- /* Check all one-character deletions. */
- for (i = 0; i < length; i++) {
- if (i > 0)
- memcpy(variant, password, i);
- if (i < length - 1)
- memcpy(variant + i, password + i + 1, length - i - 1);
- variant[length - 1] = '\0';
- CHECK_PASSWORD(ctx, data, variant);
- }
-
- /* Check all one-character permutations. */
- memcpy(variant, password, length + 1);
- for (p = variant; *p != '\0'; p++)
- CHECK_PASSWORD_VARIANT(ctx, data, variant, p);
-
- /* Check all one-character additions. */
- for (i = 0; i <= length; i++) {
- if (i > 0)
- memcpy(variant, password, i);
- if (i < length)
- memcpy(variant + i + 1, password + i, length - i);
- variant[length + 1] = '\0';
- CHECK_PASSWORD_VARIANT(ctx, data, variant, variant + i);
+ /* Check with one or two characters removed from the start. */
+ if (password[0] != '\0') {
+ CHECK_PASSWORD(ctx, data, password + 1);
+ if (password[1] != '\0')
+ CHECK_PASSWORD(ctx, data, password + 2);
}
/*
- * Check the password with first and last, two leading, or two trailing
- * characters removed.
+ * Strip a character from the end and then check both that password and
+ * the one with a character taken from the start as well.
*/
- if (length > 2) {
- memcpy(variant, password + 2, length - 1);
- CHECK_PASSWORD(ctx, data, variant);
- memcpy(variant, password + 1, length - 2);
- variant[length - 2] = '\0';
- CHECK_PASSWORD(ctx, data, variant);
- memcpy(variant, password, length - 2);
- variant[length - 2] = '\0';
+ if (strlen(password) > 0) {
+ variant = strdup(password);
+ if (variant == NULL)
+ return strength_error_system(ctx, "cannot allocate memory");
+ variant[strlen(variant) - 1] = '\0';
CHECK_PASSWORD(ctx, data, variant);
+ if (variant[0] != '\0')
+ CHECK_PASSWORD(ctx, data, variant + 1);
+
+ /* Check the password with two characters removed. */
+ if (strlen(password) > 1) {
+ variant[strlen(variant) - 1] = '\0';
+ CHECK_PASSWORD(ctx, data, variant);
+ }
}
/* Password not found. */