]> eyrie.org Git - kerberos/krb5-strength.git/blob - plugin/heimdal.c
Change my email address to eagle@eyrie.org
[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 <eagle@eyrie.org>
15  * Copyright 2009, 2013
16  *     The Board of Trustees of the Leland Stanford Junior University
17  *
18  * See LICENSE for licensing terms.
19  */
20
21 #include <config.h>
22 #include <portable/krb5.h>
23 #include <portable/system.h>
24
25 #include <errno.h>
26 #ifdef HAVE_KADM5_KADM5_PWCHECK_H
27 # include <kadm5/kadm5-pwcheck.h>
28 #endif
29
30 #include <plugin/internal.h>
31 #include <util/macros.h>
32
33 /* Skip this entire file if not building with Heimdal. */
34 #ifdef HAVE_KRB5_REALM
35
36
37 /*
38  * Write a Kerberos error string to a message buffer, with an optional
39  * prefix.
40  */
41 static void
42 convert_error(krb5_context ctx, krb5_error_code code, const char *prefix,
43               char *message, size_t length)
44 {
45     const char *error;
46
47     error = krb5_get_error_message(ctx, code);
48     if (prefix == NULL)
49         snprintf(message, length, "%s", error);
50     else
51         snprintf(message, length, "%s: %s", prefix, error);
52     krb5_free_error_message(ctx, error);
53 }
54
55
56 /*
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.
60  */
61 static int
62 heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
63                 krb5_data *password, const char *tuning UNUSED,
64                 char *message, size_t length)
65 {
66     krb5_pwqual_moddata data = NULL;
67     char *pastring = NULL;
68     char *name = NULL;
69     krb5_error_code code;
70
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",
75                  strerror(errno));
76         return 1;
77     }
78     memcpy(pastring, password->data, password->length);
79     pastring[password->length] = '\0';
80
81     /* Initialize strength checking. */
82     code = strength_init(ctx, NULL, &data);
83     if (code != 0) {
84         convert_error(ctx, code, NULL, message, length);
85         goto done;
86     }
87
88     /* Convert the principal to a string. */
89     code = krb5_unparse_name(ctx, principal, &name);
90     if (code != 0) {
91         convert_error(ctx, code, "cannot unparse principal", message, length);
92         goto done;
93     }
94
95     /* Do the password strength check. */
96     code = strength_check(ctx, data, name, pastring);
97     if (code != 0)
98         convert_error(ctx, code, NULL, message, length);
99
100 done:
101     free(pastring);
102     if (name != NULL)
103         krb5_free_unparsed_name(ctx, name);
104     if (data != NULL)
105         strength_close(ctx, data);
106     return (code == 0) ? 0 : 1;
107 }
108
109 /* The public symbol that Heimdal looks for. */
110 static struct kadm5_pw_policy_check_func functions[] = {
111     { "krb5-strength", heimdal_pwcheck },
112     { NULL, NULL }
113 };
114 struct kadm5_pw_policy_verifier kadm5_password_verifier = {
115     "krb5-strength",
116     KADM5_PASSWD_VERSION_V1,
117     "Russ Allbery",
118     functions
119 };
120
121 #endif /* HAVE_KRB5_REALM */