2 * MIT Kerberos shared module API.
4 * This is the glue required for a Heimdal password quality check via a
5 * dynamically loaded module. Retrieves the dictionary path from krb5.conf.
6 * This may change in later versions via a mechanism to pass profile
7 * information from kadmind to the plugin.
9 * Written by Russ Allbery <rra@stanford.edu>
11 * The Board of Trustees of the Leland Stanford Junior Unversity
13 * See LICENSE for licensing terms.
17 #include <portable/system.h>
22 #include <plugin/api.h>
24 /* Skip this entire file if building with Heimdal. */
25 #ifndef HAVE_KRB5_REALM
27 /* Used for unused parameters to silence gcc warnings. */
28 #define UNUSED __attribute__((__unused__))
30 /* Allow for a build without the plugin header. */
31 # ifdef HAVE_KRB5_PWCHECK_PLUGIN_H
32 # include <krb5/pwcheck_plugin.h>
34 typedef struct krb5plugin_kadmin_pwcheck_ftable_v0 {
36 krb5_error_code (*init)(krb5_context, void **);
37 void (*fini)(krb5_context, void *);
38 int (*check)(krb5_context, void *, krb5_const_principal,
39 const krb5_data *password);
40 } krb5plugin_kadmin_pwcheck_ftable_v0;
41 # endif /* !HAVE_KRB5_PWCHECK_PLUGIN_H */
45 * Initialize the library. We can't just call pwcheck_init, since currently
46 * kadmind doesn't tell us the dictionary path. So first look up where the
47 * dictionary is, and then call pwcheck_init.
49 static krb5_error_code
50 init(krb5_context context, void **data)
52 char *dictionary = NULL;
54 krb5_appdefault_string(context, "krb5-strength", NULL,
55 "password_dictionary", "", &dictionary);
56 if (dictionary == NULL || dictionary[0] == '\0') {
57 krb5_set_error_message(context, KRB5_PLUGIN_OP_NOTSUPP,
58 "password_dictionary not configured in"
60 return KRB5_PLUGIN_OP_NOTSUPP;
62 if (pwcheck_init(data, dictionary) != 0) {
63 krb5_set_error_message(context, errno, "Cannot initialize strength"
64 " checking with dictionary %s: %s", dictionary,
73 * Check the password. We need to transform the krb5_data struct and the
74 * principal passed us by kadmind into nul-terminated strings for our check.
76 static krb5_error_code
77 check(krb5_context context, void *data, krb5_const_principal princ,
78 const krb5_data *password)
82 krb5_error_code status;
85 status = krb5_unparse_name(context, princ, &name);
88 pastring = malloc(password->length + 1);
89 if (pastring == NULL) {
91 krb5_set_error_message(context, status, "%s", strerror(status));
92 krb5_free_unparsed_name(context, name);
95 memcpy(pastring, password->data, password->length);
96 pastring[password->length] = '\0';
97 status = pwcheck_check(data, pastring, name, message, sizeof(message));
99 krb5_set_error_message(context, status, "%s", message);
101 krb5_free_unparsed_name(context, name);
107 * Shut down the library.
110 fini(krb5_context context UNUSED, void *data)
116 /* The public symbol that MIT Kerberos looks for. */
117 krb5plugin_kadmin_pwcheck_ftable_v0 kadmin_pwcheck_0 = {
121 #endif /* !HAVE_KRB5_REALM */