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