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 <rra@stanford.edu>
15 * Copyright 2009, 2013
16 * The Board of Trustees of the Leland Stanford Junior Unversity
18 * See LICENSE for licensing terms.
22 #include <portable/system.h>
27 #include <plugin/api.h>
29 /* Skip this entire file if not building with Heimdal. */
30 #ifdef HAVE_KRB5_REALM
32 /* Used for unused parameters to silence gcc warnings. */
33 # define UNUSED __attribute__((__unused__))
35 /* kadm5/kadm5-pwcheck.h isn't always installed by Heimdal. */
36 # ifdef HAVE_KADM5_KADM5_PWCHECK_H
37 # include <kadm5/kadm5-pwcheck.h>
39 # define KADM5_PASSWD_VERSION_V1 1
42 (*kadm5_passwd_quality_check_func)(krb5_context context,
43 krb5_principal principal,
49 struct kadm5_pw_policy_check_func {
51 kadm5_passwd_quality_check_func func;
54 struct kadm5_pw_policy_verifier {
58 const struct kadm5_pw_policy_check_func *funcs;
60 # endif /* !HAVE_KADM5_PWCHECK_H */
63 * This is the single check function that we provide. It does the glue
64 * required to initialize our checks, convert the Heimdal arguments to the
65 * strings we expect, and return the result.
68 heimdal_pwcheck(krb5_context context, krb5_principal principal,
69 krb5_data *password, const char *tuning UNUSED, char *message,
75 char *dictionary = NULL;
76 krb5_error_code status;
79 krb5_appdefault_string(context, "krb5-strength", principal->realm,
80 "password_dictionary", "", &dictionary);
81 if (dictionary == NULL || dictionary[0] == '\0') {
82 strlcpy(message, "password_dictionary not configured in krb5.conf",
86 status = krb5_unparse_name(context, principal, &name);
88 strlcpy(message, "Cannot unparse principal name", length);
91 pastring = malloc(password->length + 1);
92 if (pastring == NULL) {
93 snprintf(message, length, "Cannot allocate memory: %s",
97 memcpy(pastring, password->data, password->length);
98 pastring[password->length] = '\0';
99 if (pwcheck_init(&data, dictionary) != 0) {
100 snprintf(message, length, "Cannot initialize strength checking"
101 " with dictionary %s: %s", dictionary, strerror(errno));
105 result = pwcheck_check(data, pastring, name, message, length);
106 krb5_free_unparsed_name(ctx, name);
112 /* The public symbol that Heimdal looks for. */
113 static struct kadm5_pw_policy_check_func functions[] = {
114 { "krb5-strength", heimdal_pwcheck },
117 struct kadm5_pw_policy_verifier kadm5_password_verifier = {
119 KADM5_PASSWD_VERSION_V1,
124 #endif /* HAVE_KRB5_REALM */