]> eyrie.org Git - kerberos/krb5-strength.git/blobdiff - plugin/heimdal.c
Merge pull request #4 from dariaphoebe/main
[kerberos/krb5-strength.git] / plugin / heimdal.c
index 98507d42456af1c26903141222a60cd035dab04f..8ace00ab59e7288e559a4b6c2ddb6e942a306075 100644 (file)
  * Of course, the external Heimdal strength checking program can be used
  * instead.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2020, 2023 Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     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>
 
 #include <errno.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
 
-/* kadm5/kadm5-pwcheck.h isn't always installed by Heimdal. */
-# ifdef HAVE_KADM5_KADM5_PWCHECK_H
-#  include <kadm5/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
@@ -63,60 +60,67 @@ struct kadm5_pw_policy_verifier {
  * strings we expect, and return the result.
  */
 static int
-heimdal_pwcheck(krb5_context context, krb5_principal principal,
+heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
                 krb5_data *password, const char *tuning UNUSED, char *message,
                 size_t length)
 {
-    void *data;
+    krb5_pwqual_moddata data = NULL;
     char *pastring;
     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);
-    krb5_free_unparsed_name(ctx, name);
+
+    /* 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:
+    explicit_bzero(pastring, password->length);
     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. */
+/* clang-format off */
 static struct kadm5_pw_policy_check_func functions[] = {
-    { "krb5-strength", heimdal_pwcheck },
-    { NULL, NULL }
+    {"krb5-strength", heimdal_pwcheck},
+    {NULL, NULL}
 };
+extern struct kadm5_pw_policy_verifier kadm5_password_verifier;
 struct kadm5_pw_policy_verifier kadm5_password_verifier = {
     "krb5-strength",
     KADM5_PASSWD_VERSION_V1,
     "Russ Allbery",
     functions
 };
+/* clang-format on */
 
 #endif /* HAVE_KRB5_REALM */