]> eyrie.org Git - kerberos/krb5-strength.git/commitdiff
Initial implementation of Heimdal plugin API
authorRuss Allbery <rra@stanford.edu>
Wed, 9 Dec 2009 07:50:25 +0000 (23:50 -0800)
committerRuss Allbery <rra@stanford.edu>
Wed, 9 Dec 2009 07:50:25 +0000 (23:50 -0800)
Support the Heimdal shared module API for embedded password strength
checking and build that interface only if building against Heimdal.

Makefile.am
configure.ac
plugin/heimdal.c [new file with mode: 0644]

index ec08402d2d0697f8cce320b13e299e65d29641bf..ac125265587a6df0b9f3afe44543af62320941e2 100644 (file)
@@ -26,7 +26,7 @@ cracklib_packer_LDADD = cracklib/libcracklib.la
 
 # Rules for building the password strength plugin.
 module_LTLIBRARIES = plugin/passwd_strength.la
-plugin_passwd_strength_la_SOURCES = plugin/api.c
+plugin_passwd_strength_la_SOURCES = plugin/api.c plugin/heimdal.c
 plugin_passwd_strength_la_LDFLAGS = -module -avoid-version
 plugin_passwd_strength_la_LIBADD = cracklib/libcracklib.la
 
index bb4f0213920e1b1ea8040c62c519f4219424218f..71bc73b1b235fbf427dd2594c05fc5621fe709be 100644 (file)
@@ -22,6 +22,11 @@ AC_PROG_LIBTOOL
 
 RRA_LIB_KRB5
 
+RRA_LIB_KRB5_SWITCH
+AC_CHECK_HEADERS([kadm5-pwcheck.h])
+AC_CHECK_TYPES([krb5_realm], , , [#include <krb5.h>])
+RRA_LIB_KRB5_RESTORE
+
 dnl Create the tests/data directory for builds outside the source directory.
 AC_CONFIG_COMMANDS([tests/data/.placeholder], [touch tests/data/.placeholder])
 
diff --git a/plugin/heimdal.c b/plugin/heimdal.c
new file mode 100644 (file)
index 0000000..9c9219e
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Heimdal shared module API.
+ *
+ * This is the glue required for a Heimdal password quality check via a
+ * dynamically loaded module.  Heimdal's shared module API doesn't have
+ * separate initialization and shutdown functions, so provide a self-contained
+ * function that looks up the dictionary path from krb5.conf and does all the
+ * work.  This means that it does memory allocations on every call, which
+ * isn't ideal, but it's probably not that slow.
+ *
+ * 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
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <plugin/api.h>
+
+/* Skip this entire file if not building with Heimdal. */
+#ifdef HAVE_KRB5_REALM
+
+/* 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 */
+
+/*
+ * This is the single check function that we provide.  It does the glue
+ * required to initialize our checks, convert the Heimdal arguments to the
+ * strings we expect, and return the result.
+ */
+static int
+heimdal_pwcheck(krb5_context context, krb5_principal principal,
+                krb5_data *password, const char *tuning, char *message,
+                size_t length)
+{
+    void *data;
+    char *pastring;
+    char *name = NULL;
+    char *dictionary = NULL;
+    krb5_error_code status;
+    int result;
+
+    krb5_get_default_realm(ctx, &realm);
+    krb5_appdefault_string(ctx, "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;
+    }
+    pastring = malloc(password->length + 1);
+    if (pastring == NULL) {
+        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: %s",
+                strerror(errno));
+        free(pastring);
+        return 1;
+    }
+    result = pwcheck_check(data, pastring, name, message, length);
+    free(pastring);
+    pwcheck_close(data);
+    return result;
+}
+
+/* The public symbol that Heimdal looks for. */
+static struct kadm5_pw_policy_check_func functions[] = {
+    { "krb5-strength", heimdal_pwcheck },
+    { NULL, NULL }
+};
+struct kadm5_pw_policy_verifier kadm5_password_verifier = {
+    "krb5-strength",
+    KADM5_PASSWD_VERSION_V1,
+    "Russ Allbery",
+    functions
+};
+
+#endif /* HAVE_KRB5_REALM */