1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/*
* Test a password for weaknesses using CrackLib.
*
* Contained here is the interface from the krb5-strength plugin to the
* CrackLib library, including initialization and checking of a password
* against a CrackLib dictionary.
*
* Developed by Daria Phoebe Brashear and Ken Hornstein of Sine Nomine
* Associates, on behalf of Stanford University Extensive modifications by Russ
* Allbery <eagle@eyrie.org> Copyright 2017 Russ Allbery <eagle@eyrie.org>
* Copyright 2006-2007, 2009, 2012-2013
* The Board of Trustees of the Leland Stanford Junior University
*
* SPDX-License-Identifier: MIT
*/
#include <config.h>
#include <portable/kadmin.h>
#include <portable/system.h>
#include <plugin/internal.h>
#include <util/macros.h>
/* When using the embedded CrackLib, we need to provide our own prototype. */
#ifdef HAVE_CRACKLIB
# ifdef HAVE_CRACK_H
# include <crack.h>
# else
extern const char *FascistCheck(const char *password, const char *dict);
# endif
#endif
/*
* Stub for strength_init_cracklib if not built with CrackLib support.
*/
#ifndef HAVE_CRACKLIB
krb5_error_code
strength_init_cracklib(krb5_context ctx, krb5_pwqual_moddata data UNUSED,
const char *dictionary UNUSED)
{
char *path = NULL;
/* Get CDB dictionary path from krb5.conf. */
strength_config_string(ctx, "password_dictionary", &path);
/* If it was set, report an error, since we don't have CrackLib support. */
if (path == NULL)
return 0;
free(path);
krb5_set_error_message(ctx, KADM5_BAD_SERVER_PARAMS,
"CrackLib dictionary requested but not built with"
" CrackLib support");
return KADM5_BAD_SERVER_PARAMS;
}
#endif
/* Skip the rest of this file if CrackLib is not available. */
#ifdef HAVE_CRACKLIB
/*
* Initialize the CrackLib dictionary. Ensure that the dictionary file exists
* and is readable and store the path in the module context. Returns 0 on
* success, non-zero on failure.
*
* The dictionary file should not include the trailing .pwd extension.
* Currently, we don't cope with a NULL dictionary path.
*/
krb5_error_code
strength_init_cracklib(krb5_context ctx, krb5_pwqual_moddata data,
const char *dictionary)
{
char *file;
krb5_error_code code;
/*
* Get the dictionary from krb5.conf, and only use the dictionary provided
* if krb5.conf configuration is not present. The dictionary passed to
* the initialization function is normally set by dict_path in the MIT
* Kerberos configuration, and this allows that setting to be used for
* other password strength modules while using a different dictionary for
* krb5-strength.
*/
strength_config_string(ctx, "password_dictionary", &data->dictionary);
if (data->dictionary == NULL && dictionary != NULL) {
data->dictionary = strdup(dictionary);
if (data->dictionary == NULL)
return strength_error_system(ctx, "cannot allocate memory");
}
/* All done if we don't have a dictionary. */
if (data->dictionary == NULL)
return 0;
/* Sanity-check the dictionary path. */
if (asprintf(&file, "%s.pwd", data->dictionary) < 0)
return strength_error_system(ctx, "cannot allocate memory");
if (access(file, R_OK) != 0) {
code = strength_error_system(ctx, "cannot read dictionary %s", file);
free(file);
return code;
}
free(file);
return 0;
}
/*
* Check a password against CrackLib. Returns 0 on success, non-zero on
* failure or if the password is rejected.
*/
krb5_error_code
strength_check_cracklib(krb5_context ctx, krb5_pwqual_moddata data,
const char *password)
{
const char *result;
/* Nothing to do if we don't have a dictionary. */
if (data->dictionary == NULL)
return 0;
/* Nothing to do if the password is longer than the maximum length. */
if (data->cracklib_maxlen > 0)
if (strlen(password) > (size_t) data->cracklib_maxlen)
return 0;
/* Check the password against CrackLib and return the results. */
result = FascistCheck(password, data->dictionary);
if (result != NULL)
return strength_error_generic(ctx, "%s", result);
else
return 0;
}
#endif /* HAVE_CRACKLIB */
|