]> 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 d6583d6c12fcbbfe1331fdfc02d592d88a931dea..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
@@ -67,12 +64,12 @@ heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
                 krb5_data *password, const char *tuning UNUSED, char *message,
                 size_t length)
 {
-    krb5_pwqual_moddata data;
+    krb5_pwqual_moddata data = NULL;
     char *pastring;
     char *name = NULL;
     krb5_error_code code;
-    const char *error;
 
+    /* Convert the password to a C string. */
     pastring = malloc(password->length + 1);
     if (pastring == NULL) {
         snprintf(message, length, "cannot allocate memory: %s",
@@ -81,46 +78,49 @@ heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
     }
     memcpy(pastring, password->data, password->length);
     pastring[password->length] = '\0';
-    code = pwcheck_init(ctx, NULL, &data);
+
+    /* Initialize strength checking. */
+    code = strength_init(ctx, NULL, &data);
     if (code != 0) {
-        error = krb5_get_error_message(ctx, code);
-        snprintf(message, length, "cannot initialize strength checking: %s",
-                 error);
-        krb5_free_error_message(ctx, error);
-        free(pastring);
-        return 1;
+        convert_error(ctx, code, NULL, message, length);
+        goto done;
     }
+
+    /* Convert the principal to a string. */
     code = krb5_unparse_name(ctx, principal, &name);
     if (code != 0) {
-        error = krb5_get_error_message(ctx, code);
-        snprintf(message, length, "cannot unparse principal name: %s", error);
-        krb5_free_error_message(ctx, error);
-        free(pastring);
-        pwcheck_close(ctx, data);
-        return 1;
-    }
-    code = pwcheck_check(ctx, data, pastring, name);
-    if (code != 0) {
-        error = krb5_get_error_message(ctx, code);
-        snprintf(message, length, "%s", error);
-        krb5_free_error_message(ctx, error);
+        convert_error(ctx, code, "cannot unparse principal", message, length);
+        goto done;
     }
-    krb5_free_unparsed_name(ctx, name);
+
+    /* 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(ctx, data);
+    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 */