]> eyrie.org Git - kerberos/krb5-strength.git/blob - plugin/cracklib.c
New upstream version 3.1
[kerberos/krb5-strength.git] / plugin / cracklib.c
1 /*
2  * Test a password for weaknesses using CrackLib.
3  *
4  * Contained here is the interface from the krb5-strength plugin to the
5  * CrackLib library, including initialization and checking of a password
6  * against a CrackLib dictionary.
7  *
8  * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
9  *     on behalf of Stanford University
10  * Extensive modifications by Russ Allbery <eagle@eyrie.org>
11  * Copyright 2006, 2007, 2009, 2012, 2013
12  *     The Board of Trustees of the Leland Stanford Junior University
13  *
14  * See LICENSE for licensing terms.
15  */
16
17 #include <config.h>
18 #include <portable/system.h>
19
20 #include <plugin/internal.h>
21
22 /* When using the embedded CrackLib, we need to provide our own prototype. */
23 #ifdef HAVE_CRACK_H
24 # include <crack.h>
25 #else
26 extern const char *FascistCheck(const char *password, const char *dict);
27 #endif
28
29
30 /*
31  * Initialize the CrackLib dictionary.  Ensure that the dictionary file exists
32  * and is readable and store the path in the module context.  Returns 0 on
33  * success, non-zero on failure.
34  *
35  * The dictionary file should not include the trailing .pwd extension.
36  * Currently, we don't cope with a NULL dictionary path.
37  */
38 krb5_error_code
39 strength_init_cracklib(krb5_context ctx, krb5_pwqual_moddata data,
40                        const char *dictionary)
41 {
42     char *file;
43     krb5_error_code code;
44
45     /*
46      * Get the dictionary from krb5.conf, and only use the dictionary provided
47      * if krb5.conf configuration is not present.  The dictionary passed to
48      * the initialization function is normally set by dict_path in the MIT
49      * Kerberos configuration, and this allows that setting to be used for
50      * other password strength modules while using a different dictionary for
51      * krb5-strength.
52      */
53     strength_config_string(ctx, "password_dictionary", &data->dictionary);
54     if (data->dictionary == NULL && dictionary != NULL) {
55         data->dictionary = strdup(dictionary);
56         if (data->dictionary == NULL)
57             return strength_error_system(ctx, "cannot allocate memory");
58     }
59
60     /* All done if we don't have a dictionary. */
61     if (data->dictionary == NULL)
62         return 0;
63
64     /* Sanity-check the dictionary path. */
65     if (asprintf(&file, "%s.pwd", data->dictionary) < 0)
66         return strength_error_system(ctx, "cannot allocate memory");
67     if (access(file, R_OK) != 0) {
68         code = strength_error_system(ctx, "cannot read dictionary %s", file);
69         free(file);
70         return code;
71     }
72     free(file);
73     return 0;
74 }
75
76
77 /*
78  * Check a password against CrackLib.  Returns 0 on success, non-zero on
79  * failure or if the password is rejected.
80  */
81 krb5_error_code
82 strength_check_cracklib(krb5_context ctx, krb5_pwqual_moddata data,
83                         const char *password)
84 {
85     const char *result;
86
87     /* Nothing to do if we don't have a dictionary. */
88     if (data->dictionary == NULL)
89         return 0;
90
91     /* Nothing to do if the password is longer than the maximum length. */
92     if (data->cracklib_maxlen > 0)
93         if (strlen(password) > (size_t) data->cracklib_maxlen)
94             return 0;
95
96     /* Check the password against CrackLib and return the results. */
97     result = FascistCheck(password, data->dictionary);
98     if (result != NULL)
99         return strength_error_generic(ctx, "%s", result);
100     else
101         return 0;
102 }