2 * Prototypes for the kadmin password strength checking plugin.
4 * Developed by Daria Phoebe Brashear and Ken Hornstein of Sine Nomine
5 * Associates, on behalf of Stanford University
6 * Extensive modifications by Russ Allbery <eagle@eyrie.org>
7 * Copyright 2023 Russ Allbery <eagle@eyrie.org>
8 * Copyright 2006-2007, 2009, 2012-2014
9 * The Board of Trustees of the Leland Stanford Junior University
11 * SPDX-License-Identifier: MIT
14 #ifndef PLUGIN_INTERNAL_H
15 #define PLUGIN_INTERNAL_H 1
18 #include <portable/krb5.h>
19 #include <portable/macros.h>
29 #ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
30 # include <krb5/pwqual_plugin.h>
32 typedef struct krb5_pwqual_moddata_st *krb5_pwqual_moddata;
35 /* Error strings returned (and displayed to the user) for various failures. */
36 #define ERROR_ASCII "Password contains non-ASCII or control characters"
37 #define ERROR_CLASS_LOWER "Password must contain a lowercase letter"
38 #define ERROR_CLASS_UPPER "Password must contain an uppercase letter"
39 #define ERROR_CLASS_DIGIT "Password must contain a number"
40 #define ERROR_CLASS_SYMBOL \
41 "Password must contain a space or punctuation character"
42 #define ERROR_CLASS_MIN \
43 "Password must contain %lu types of characters (lowercase, uppercase," \
45 #define ERROR_DICT "Password found in list of common passwords"
46 #define ERROR_LETTER "Password is only letters and spaces"
47 #define ERROR_MINDIFF "Password does not contain enough unique characters"
48 #define ERROR_SHORT "Password is too short"
49 #define ERROR_USERNAME "Password based on username or principal"
52 * A character class rule, which consists of a minimum length to which the
53 * rule is applied, a maximum length to which the rule is applied, and a set
54 * of flags for which character classes are required. The symbol class
55 * includes everything that isn't in one of the other classes, including
65 unsigned long num_classes;
66 struct class_rule *next;
69 /* Used to store a list of strings, managed by the sync_vector_* functions. */
77 * MIT Kerberos uses this type as an abstract data type for any data that a
78 * password quality check needs to carry. Reuse it since then we get type
79 * checking for at least the MIT plugin.
81 struct krb5_pwqual_moddata_st {
82 long minimum_different; /* Minimum number of different characters */
83 long minimum_length; /* Minimum password length */
84 bool ascii; /* Whether to require printable ASCII */
85 bool nonletter; /* Whether to require a non-letter */
86 struct class_rule *rules; /* Linked list of character class rules */
87 char *dictionary; /* Base path to CrackLib dictionary */
88 long cracklib_maxlen; /* Longer passwords skip CrackLib checks */
89 bool have_cdb; /* Whether we have a CDB dictionary */
90 int cdb_fd; /* File descriptor of CDB dictionary */
92 struct cdb cdb; /* Open CDB dictionary data */
95 sqlite3 *sqlite; /* Open SQLite database handle */
96 sqlite3_stmt *prefix_query; /* Query using the password prefix */
97 sqlite3_stmt *suffix_query; /* Query using the reversed password suffix */
103 /* Default to a hidden visibility for all internal functions. */
104 #pragma GCC visibility push(hidden)
106 /* Initialize the plugin and set up configuration. */
107 krb5_error_code strength_init(krb5_context, const char *dictionary,
108 krb5_pwqual_moddata *);
111 * Check a password. Returns 0 if okay. On error, sets the Kerberos error
112 * message and returns a Kerberos status code.
114 krb5_error_code strength_check(krb5_context, krb5_pwqual_moddata,
115 const char *principal, const char *password);
117 /* Free the internal plugin state. */
118 void strength_close(krb5_context, krb5_pwqual_moddata);
121 * CDB handling. strength_init_cdb gets the dictionary configuration and sets
122 * up the CDB database, strength_check_cdb checks it, and strength_close_cdb
123 * handles freeing resources.
125 * If not built with CDB support, provide some stubs for check and close.
126 * init is always a real function, which reports an error if CDB is
127 * requested and not available.
129 krb5_error_code strength_init_cdb(krb5_context, krb5_pwqual_moddata);
131 krb5_error_code strength_check_cdb(krb5_context, krb5_pwqual_moddata,
132 const char *password);
133 void strength_close_cdb(krb5_context, krb5_pwqual_moddata);
135 # define strength_check_cdb(c, d, p) 0
136 # define strength_close_cdb(c, d) /* empty */
140 * CrackLib handling. strength_init_cracklib gets the dictionary
141 * configuration does some sanity checks on it, and strength_check_cracklib
142 * checks the password against CrackLib.
144 * If not built with CrackLib support, provide a stub for check. init is
145 * always a real function, which reports an error if CrackLib is requested and
148 krb5_error_code strength_init_cracklib(krb5_context, krb5_pwqual_moddata,
149 const char *dictionary);
151 krb5_error_code strength_check_cracklib(krb5_context, krb5_pwqual_moddata,
152 const char *password);
154 # define strength_check_cracklib(c, d, p) 0
158 * SQLite handling. strength_init_sqlite gets the database configuration and
159 * sets up the SQLite internal data, strength_check_sqlite checks a password,
160 * and strength_close_sqlite handles freeing resources.
162 * If not built with SQLite support, provide some stubs for check and close.
163 * init is always a real function, which reports an error if SQLite is
164 * requested and not available.
166 krb5_error_code strength_init_sqlite(krb5_context, krb5_pwqual_moddata);
168 krb5_error_code strength_check_sqlite(krb5_context, krb5_pwqual_moddata,
169 const char *password);
170 void strength_close_sqlite(krb5_context, krb5_pwqual_moddata);
172 # define strength_check_sqlite(c, d, p) 0
173 # define strength_close_sqlite(c, d) /* empty */
176 /* Check whether the password statisfies character class requirements. */
177 krb5_error_code strength_check_classes(krb5_context, krb5_pwqual_moddata,
178 const char *password);
180 /* Check whether the password is based on the principal in some way. */
181 krb5_error_code strength_check_principal(krb5_context, krb5_pwqual_moddata,
182 const char *principal,
183 const char *password);
186 * Manage vectors, which are counted lists of strings. The functions that
187 * return a boolean return false if memory allocation fails.
189 struct vector *strength_vector_new(void) __attribute__((__malloc__));
190 bool strength_vector_add(struct vector *, const char *string)
191 __attribute__((__nonnull__));
192 void strength_vector_free(struct vector *);
195 * vector_split_multi splits on a set of characters. If the vector argument
196 * is NULL, a new vector is allocated; otherwise, the provided one is reused.
197 * Returns NULL on memory allocation failure, after which the provided vector
198 * may have been modified to only have partial results.
200 * Empty strings will yield zero-length vectors. Adjacent delimiters are
201 * treated as a single delimiter by vector_split_multi. Any leading or
202 * trailing delimiters are ignored, so this function will never create
203 * zero-length strings (similar to the behavior of strtok).
205 struct vector *strength_vector_split_multi(const char *string,
206 const char *seps, struct vector *)
207 __attribute__((__nonnull__(1, 2)));
210 * Obtain configuration settings from krb5.conf. These are wrappers around
211 * the krb5_appdefault_* APIs that handle setting the section name, obtaining
212 * the local default realm and using it to find settings, and doing any
213 * necessary conversion.
215 void strength_config_boolean(krb5_context, const char *, bool *)
216 __attribute__((__nonnull__));
217 krb5_error_code strength_config_list(krb5_context, const char *,
219 __attribute__((__nonnull__));
220 void strength_config_number(krb5_context, const char *, long *)
221 __attribute__((__nonnull__));
222 void strength_config_string(krb5_context, const char *, char **)
223 __attribute__((__nonnull__));
225 /* Parse the more complex configuration of required character classes. */
226 krb5_error_code strength_config_classes(krb5_context, const char *,
227 struct class_rule **)
228 __attribute__((__nonnull__));
231 * Store a particular password quality error in the Kerberos context. The
232 * _system variant uses errno for the error code and appends the strerror
233 * results to the message. All versions return the error code set.
235 krb5_error_code strength_error_class(krb5_context, const char *format, ...)
236 __attribute__((__nonnull__, __format__(printf, 2, 3)));
237 krb5_error_code strength_error_config(krb5_context, const char *format, ...)
238 __attribute__((__nonnull__, __format__(printf, 2, 3)));
239 krb5_error_code strength_error_dict(krb5_context, const char *format, ...)
240 __attribute__((__nonnull__, __format__(printf, 2, 3)));
241 krb5_error_code strength_error_generic(krb5_context, const char *format, ...)
242 __attribute__((__nonnull__, __format__(printf, 2, 3)));
243 krb5_error_code strength_error_system(krb5_context, const char *format, ...)
244 __attribute__((__nonnull__, __format__(printf, 2, 3)));
245 krb5_error_code strength_error_tooshort(krb5_context, const char *format, ...)
246 __attribute__((__nonnull__, __format__(printf, 2, 3)));
248 /* Undo default visibility change. */
249 #pragma GCC visibility pop
253 #endif /* !PLUGIN_INTERNAL_H */