2 * Heimdal shared module API.
4 * This is the glue required for a Heimdal password quality check via a
5 * dynamically loaded module. Heimdal's shared module API doesn't have
6 * separate initialization and shutdown functions, so provide a self-contained
7 * function that looks up the dictionary path from krb5.conf and does all the
8 * work. This means that it does memory allocations on every call, which
9 * isn't ideal, but it's probably not that slow.
11 * Of course, the external Heimdal strength checking program can be used
14 * Written by Russ Allbery <eagle@eyrie.org>
15 * Copyright 2009, 2013
16 * The Board of Trustees of the Leland Stanford Junior University
18 * See LICENSE for licensing terms.
22 #include <portable/krb5.h>
23 #include <portable/system.h>
26 #ifdef HAVE_KADM5_KADM5_PWCHECK_H
27 # include <kadm5/kadm5-pwcheck.h>
30 #include <plugin/internal.h>
31 #include <util/macros.h>
33 /* Skip this entire file if not building with Heimdal. */
34 #ifdef HAVE_KRB5_REALM
38 * Write a Kerberos error string to a message buffer, with an optional
42 convert_error(krb5_context ctx, krb5_error_code code, const char *prefix,
43 char *message, size_t length)
47 error = krb5_get_error_message(ctx, code);
49 snprintf(message, length, "%s", error);
51 snprintf(message, length, "%s: %s", prefix, error);
52 krb5_free_error_message(ctx, error);
57 * This is the single check function that we provide. It does the glue
58 * required to initialize our checks, convert the Heimdal arguments to the
59 * strings we expect, and return the result.
62 heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
63 krb5_data *password, const char *tuning UNUSED,
64 char *message, size_t length)
66 krb5_pwqual_moddata data = NULL;
67 char *pastring = NULL;
71 /* Convert the password to a C string. */
72 pastring = malloc(password->length + 1);
73 if (pastring == NULL) {
74 snprintf(message, length, "cannot allocate memory: %s",
78 memcpy(pastring, password->data, password->length);
79 pastring[password->length] = '\0';
81 /* Initialize strength checking. */
82 code = strength_init(ctx, NULL, &data);
84 convert_error(ctx, code, NULL, message, length);
88 /* Convert the principal to a string. */
89 code = krb5_unparse_name(ctx, principal, &name);
91 convert_error(ctx, code, "cannot unparse principal", message, length);
95 /* Do the password strength check. */
96 code = strength_check(ctx, data, name, pastring);
98 convert_error(ctx, code, NULL, message, length);
103 krb5_free_unparsed_name(ctx, name);
105 strength_close(ctx, data);
106 return (code == 0) ? 0 : 1;
109 /* The public symbol that Heimdal looks for. */
110 static struct kadm5_pw_policy_check_func functions[] = {
111 { "krb5-strength", heimdal_pwcheck },
114 struct kadm5_pw_policy_verifier kadm5_password_verifier = {
116 KADM5_PASSWD_VERSION_V1,
121 #endif /* HAVE_KRB5_REALM */