]> eyrie.org Git - kerberos/krb5-strength.git/blob - plugin/heimdal.c
Use the portability layer and close a memory leak
[kerberos/krb5-strength.git] / plugin / heimdal.c
1 /*
2  * Heimdal shared module API.
3  *
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.
10  *
11  * Of course, the external Heimdal strength checking program can be used
12  * instead.
13  *
14  * Written by Russ Allbery <rra@stanford.edu>
15  * Copyright 2009, 2013
16  *     The Board of Trustees of the Leland Stanford Junior Unversity
17  *
18  * See LICENSE for licensing terms.
19  */
20
21 #include <config.h>
22 #include <portable/system.h>
23
24 #include <errno.h>
25 #include <krb5.h>
26
27 #include <plugin/api.h>
28
29 /* Skip this entire file if not building with Heimdal. */
30 #ifdef HAVE_KRB5_REALM
31
32 /* Used for unused parameters to silence gcc warnings. */
33 # define UNUSED  __attribute__((__unused__))
34
35 /* kadm5/kadm5-pwcheck.h isn't always installed by Heimdal. */
36 # ifdef HAVE_KADM5_KADM5_PWCHECK_H
37 #  include <kadm5/kadm5-pwcheck.h>
38 # else
39 #  define KADM5_PASSWD_VERSION_V1 1
40
41 typedef int
42 (*kadm5_passwd_quality_check_func)(krb5_context context,
43                                    krb5_principal principal,
44                                    krb5_data *password,
45                                    const char *tuning,
46                                    char *message,
47                                    size_t length);
48
49 struct kadm5_pw_policy_check_func {
50     const char *name;
51     kadm5_passwd_quality_check_func func;
52 };
53
54 struct kadm5_pw_policy_verifier {
55     const char *name;
56     int version;
57     const char *vendor;
58     const struct kadm5_pw_policy_check_func *funcs;
59 };
60 # endif /* !HAVE_KADM5_PWCHECK_H */
61
62 /*
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.
66  */
67 static int
68 heimdal_pwcheck(krb5_context context, krb5_principal principal,
69                 krb5_data *password, const char *tuning UNUSED, char *message,
70                 size_t length)
71 {
72     void *data;
73     char *pastring;
74     char *name = NULL;
75     char *dictionary = NULL;
76     krb5_error_code status;
77     int result;
78
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",
83                 length);
84         return 1;
85     }
86     status = krb5_unparse_name(context, principal, &name);
87     if (status != 0) {
88         strlcpy(message, "Cannot unparse principal name", length);
89         return 1;
90     }
91     pastring = malloc(password->length + 1);
92     if (pastring == NULL) {
93         snprintf(message, length, "Cannot allocate memory: %s",
94                  strerror(errno));
95         return 1;
96     }
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));
102         free(pastring);
103         return 1;
104     }
105     result = pwcheck_check(data, pastring, name, message, length);
106     krb5_free_unparsed_name(ctx, name);
107     free(pastring);
108     pwcheck_close(data);
109     return result;
110 }
111
112 /* The public symbol that Heimdal looks for. */
113 static struct kadm5_pw_policy_check_func functions[] = {
114     { "krb5-strength", heimdal_pwcheck },
115     { NULL, NULL }
116 };
117 struct kadm5_pw_policy_verifier kadm5_password_verifier = {
118     "krb5-strength",
119     KADM5_PASSWD_VERSION_V1,
120     "Russ Allbery",
121     functions
122 };
123
124 #endif /* HAVE_KRB5_REALM */