]> eyrie.org Git - kerberos/krb5-strength.git/blob - plugin/internal.h
Update default GCC warning flags
[kerberos/krb5-strength.git] / plugin / internal.h
1 /*
2  * Prototypes for the kadmin password strength checking plugin.
3  *
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
10  *
11  * SPDX-License-Identifier: MIT
12  */
13
14 #ifndef PLUGIN_INTERNAL_H
15 #define PLUGIN_INTERNAL_H 1
16
17 #include <config.h>
18 #include <portable/krb5.h>
19 #include <portable/macros.h>
20
21 #ifdef HAVE_CDB_H
22 #    include <cdb.h>
23 #endif
24 #ifdef HAVE_SQLITE3_H
25 #    include <sqlite3.h>
26 #endif
27 #include <stddef.h>
28
29 #ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
30 #    include <krb5/pwqual_plugin.h>
31 #else
32 typedef struct krb5_pwqual_moddata_st *krb5_pwqual_moddata;
33 #endif
34
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," \
44     " numbers, symbols)"
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"
50
51 /*
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
56  * space.
57  */
58 struct class_rule {
59     unsigned long min;
60     unsigned long max;
61     bool lower;
62     bool upper;
63     bool digit;
64     bool symbol;
65     unsigned long num_classes;
66     struct class_rule *next;
67 };
68
69 /* Used to store a list of strings, managed by the sync_vector_* functions. */
70 struct vector {
71     size_t count;
72     size_t allocated;
73     char **strings;
74 };
75
76 /*
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.
80  */
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 */
91 #ifdef HAVE_CDB_H
92     struct cdb cdb; /* Open CDB dictionary data */
93 #endif
94 #ifdef HAVE_SQLITE3_H
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 */
98 #endif
99 };
100
101 BEGIN_DECLS
102
103 /* Default to a hidden visibility for all internal functions. */
104 #pragma GCC visibility push(hidden)
105
106 /* Initialize the plugin and set up configuration. */
107 krb5_error_code strength_init(krb5_context, const char *dictionary,
108                               krb5_pwqual_moddata *);
109
110 /*
111  * Check a password.  Returns 0 if okay.  On error, sets the Kerberos error
112  * message and returns a Kerberos status code.
113  */
114 krb5_error_code strength_check(krb5_context, krb5_pwqual_moddata,
115                                const char *principal, const char *password);
116
117 /* Free the internal plugin state. */
118 void strength_close(krb5_context, krb5_pwqual_moddata);
119
120 /*
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.
124  *
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.
128  */
129 krb5_error_code strength_init_cdb(krb5_context, krb5_pwqual_moddata);
130 #ifdef HAVE_CDB
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);
134 #else
135 #    define strength_check_cdb(c, d, p) 0
136 #    define strength_close_cdb(c, d)    /* empty */
137 #endif
138
139 /*
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.
143  *
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
146  * not availble.
147  */
148 krb5_error_code strength_init_cracklib(krb5_context, krb5_pwqual_moddata,
149                                        const char *dictionary);
150 #ifdef HAVE_CRACKLIB
151 krb5_error_code strength_check_cracklib(krb5_context, krb5_pwqual_moddata,
152                                         const char *password);
153 #else
154 #    define strength_check_cracklib(c, d, p) 0
155 #endif
156
157 /*
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.
161  *
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.
165  */
166 krb5_error_code strength_init_sqlite(krb5_context, krb5_pwqual_moddata);
167 #ifdef HAVE_SQLITE3
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);
171 #else
172 #    define strength_check_sqlite(c, d, p) 0
173 #    define strength_close_sqlite(c, d)    /* empty */
174 #endif
175
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);
179
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);
184
185 /*
186  * Manage vectors, which are counted lists of strings.  The functions that
187  * return a boolean return false if memory allocation fails.
188  */
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 *);
193
194 /*
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.
199  *
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).
204  */
205 struct vector *strength_vector_split_multi(const char *string,
206                                            const char *seps, struct vector *)
207     __attribute__((__nonnull__(1, 2)));
208
209 /*
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.
214  */
215 void strength_config_boolean(krb5_context, const char *, bool *)
216     __attribute__((__nonnull__));
217 krb5_error_code strength_config_list(krb5_context, const char *,
218                                      struct vector **)
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__));
224
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__));
229
230 /*
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.
234  */
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)));
247
248 /* Undo default visibility change. */
249 #pragma GCC visibility pop
250
251 END_DECLS
252
253 #endif /* !PLUGIN_INTERNAL_H */