* Of course, the external Heimdal strength checking program can be used
* instead.
*
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2009 Board of Trustees, Leland Stanford Jr. Unversity
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2009, 2013
+ * The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
#include <config.h>
+#include <portable/krb5.h>
#include <portable/system.h>
#include <errno.h>
-#include <krb5.h>
+#ifdef HAVE_KADM5_KADM5_PWCHECK_H
+# include <kadm5/kadm5-pwcheck.h>
+#endif
-#include <plugin/api.h>
+#include <plugin/internal.h>
+#include <util/macros.h>
/* Skip this entire file if not building with Heimdal. */
#ifdef HAVE_KRB5_REALM
-/* Used for unused parameters to silence gcc warnings. */
-#define UNUSED __attribute__((__unused__))
-
-/* kadm5-pwcheck.h isn't always installed by Heimdal. */
-# ifdef HAVE_KADM5_PWCHECK_H
-# include <kadm5-pwcheck.h>
-# else
-# define KADM5_PASSWD_VERSION_V1 1
-
-typedef int
-(*kadm5_passwd_quality_check_func)(krb5_context context,
- krb5_principal principal,
- krb5_data *password,
- const char *tuning,
- char *message,
- size_t length);
-
-struct kadm5_pw_policy_check_func {
- const char *name;
- kadm5_passwd_quality_check_func func;
-};
-struct kadm5_pw_policy_verifier {
- const char *name;
- int version;
- const char *vendor;
- const struct kadm5_pw_policy_check_func *funcs;
-};
-# endif /* !HAVE_KADM5_PWCHECK_H */
+/*
+ * Write a Kerberos error string to a message buffer, with an optional
+ * prefix.
+ */
+static void
+convert_error(krb5_context ctx, krb5_error_code code, const char *prefix,
+ char *message, size_t length)
+{
+ const char *error;
+
+ error = krb5_get_error_message(ctx, code);
+ if (prefix == NULL)
+ snprintf(message, length, "%s", error);
+ else
+ snprintf(message, length, "%s: %s", prefix, error);
+ krb5_free_error_message(ctx, error);
+}
+
/*
* This is the single check function that we provide. It does the glue
* strings we expect, and return the result.
*/
static int
-heimdal_pwcheck(krb5_context context, krb5_principal principal,
- krb5_data *password, const char *tuning UNUSED, char *message,
- size_t length)
+heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
+ krb5_data *password, const char *tuning UNUSED,
+ char *message, size_t length)
{
- void *data;
- char *pastring;
+ krb5_pwqual_moddata data = NULL;
+ char *pastring = NULL;
char *name = NULL;
- char *dictionary = NULL;
- krb5_error_code status;
- int result;
-
- krb5_appdefault_string(context, "krb5-strength", principal->realm,
- "password_dictionary", "", &dictionary);
- if (dictionary == NULL || dictionary[0] == '\0') {
- strlcpy(message, "password_dictionary not configured in krb5.conf",
- length);
- return 1;
- }
- status = krb5_unparse_name(context, principal, &name);
- if (status != 0) {
- strlcpy(message, "Cannot unparse principal name", length);
- return 1;
- }
+ krb5_error_code code;
+
+ /* Convert the password to a C string. */
pastring = malloc(password->length + 1);
if (pastring == NULL) {
- snprintf(message, length, "Cannot allocate memory: %s",
+ snprintf(message, length, "cannot allocate memory: %s",
strerror(errno));
return 1;
}
memcpy(pastring, password->data, password->length);
pastring[password->length] = '\0';
- if (pwcheck_init(&data, dictionary) != 0) {
- snprintf(message, length, "Cannot initialize strength checking"
- " with dictionary %s: %s", dictionary, strerror(errno));
- free(pastring);
- return 1;
+
+ /* Initialize strength checking. */
+ code = strength_init(ctx, NULL, &data);
+ if (code != 0) {
+ convert_error(ctx, code, NULL, message, length);
+ goto done;
}
- result = pwcheck_check(data, pastring, name, message, length);
+
+ /* Convert the principal to a string. */
+ code = krb5_unparse_name(ctx, principal, &name);
+ if (code != 0) {
+ convert_error(ctx, code, "cannot unparse principal", message, length);
+ goto done;
+ }
+
+ /* Do the password strength check. */
+ code = strength_check(ctx, data, name, pastring);
+ if (code != 0)
+ convert_error(ctx, code, NULL, message, length);
+
+done:
free(pastring);
- pwcheck_close(data);
- return result;
+ if (name != NULL)
+ krb5_free_unparsed_name(ctx, name);
+ if (data != NULL)
+ strength_close(ctx, data);
+ return (code == 0) ? 0 : 1;
}
/* The public symbol that Heimdal looks for. */