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