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