# Rules for building the password strength plugin.
module_LTLIBRARIES = plugin/passwd_strength.la
-plugin_passwd_strength_la_SOURCES = plugin/api.c plugin/heimdal.c plugin/mit.c
+plugin_passwd_strength_la_SOURCES = plugin/api.c plugin/heimdal.c \
+ plugin/mit.c
plugin_passwd_strength_la_LDFLAGS = -module -avoid-version
if EMBEDDED_CRACKLIB
plugin_passwd_strength_la_LIBADD = cracklib/libcracklib.la
krb5-strength 2.0 (unreleased)
+ Add support for the MIT Kerberos password quality plugin interface,
+ available in MIT Kerberos 1.9 and later, contributed by Greg Hudson
+ and MIT. Drop the patch for MIT Kerberos 1.4 (and hence support for
+ versions of MIT Kerberos prior to 1.9).
+
CrackLib checks for passwords where a character is a simple increment
or decrement of the previous character. In previous versions, the
embedded version of CrackLib allowed at most four such occurrences in
krb5-strength 1.1
- (kadmind password strength checking plugin)
+ (Kerberos password strength checking plugin)
Maintained by Russ Allbery <rra@stanford.edu>
- Copyright 2006, 2007, 2009, 2010, 2012 The Board of Trustees of the
- Leland Stanford Junior University. Portions copyright 1993 Alec
+ Copyright 2006, 2007, 2009, 2010, 2012, 2013 The Board of Trustees of
+ the Leland Stanford Junior University. Portions copyright 1993 Alec
Muffett. Developed by Derrick Brashear and Ken Hornstein of Sine Nomine
Associates, on behalf of Stanford University.
in a Kerberos KDC. It is roughly equivalent to checking password
strength via CrackLib, except that it embeds a copy of Alec Muffett's
CrackLib that has been modified to perform slightly more strenuous
- tests. It is usable as-is with Heimdal. With MIT Kerberos, it requires
- an included patch to libkadm5srv to support a dynamically loaded
- password check module.
+ tests. It supports both Heimdal and MIT Kerberos (1.9 or later).
DESCRIPTION
transform rules does not catch passwords that can be guessed using the
same dictionary with other tools, such as Jack the Ripper.
- The MIT Kerberos kadmind supports password strength checking against a
- dictionary out of the box. Unfortunately, that support loads the entire
- dictionary into memory, requires uncompressed dictionaries, and doesn't
- apply any transformations to the password before checking it against the
- dictionary. CrackLib provides more sophisticated strength checking and
- an optimized, compressed on-disk database format.
-
- This toolkit therefore provides the ability to check password quality
- against the standard version of CrackLib, or against a modified version
- of CrackLib that only passes passwords that resist attacks from both
- Crack and Jack the Ripper using the same rule sets. For Heimdal, it
- includes both a program usable as an external password quality check and
- a plugin that implements the dynamic module API. For MIT Kerberos, it
- includes two pieces:
-
- * A patch to MIT Kerberos to add a plugin system for password strength
- checking. This patch adds initialization and shutdown hooks plus a
- hook that's run prior to each password change. The code in kadmind
- is independent of what the plugin might do.
-
- * A libkadm5srv or Heimdal kpasswdd plugin that provides a wrapper
- around CrackLib.
+ This plugin provides the ability to check password quality against the
+ standard version of CrackLib, or against a modified version of CrackLib
+ that only passes passwords that resist attacks from both Crack and Jack
+ the Ripper using the same rule sets. For Heimdal, it includes both a
+ program usable as an external password quality check and a plugin that
+ implements the dynamic module API. For MIT Kerberos (1.9 or later), it
+ includes a plugin for the password quality (pwqual) plugin API.
krb5-strength can be built with either the system CrackLib or with the
modified version of CrackLib included in this package. Note, however,
also minor changes to fix portability issues and remove some code that
doesn't make sense in the kadmind context.
- My eventual hope is to submit to CrackLib 2.x modifications that allow
- the rule set to be configured at runtime, at which point this package
- can likely wither away in favor of much simpler plugins that link to the
- standard CrackLib library.
+ Ideally, the changes to CrackLib should be added to the standard
+ CrackLib distribution by adding an additional interface to configure its
+ behavior, at which point this package can likely wither away in favor of
+ much simpler plugins that link to the standard CrackLib library.
REQUIREMENTS
- For Heimdal, this package is usable without any special considerations.
- You may use either the external password quality check tool, installed
- as heimdal-strength, or the plugin as you choose. It has been tested
- with Heimdal 1.2.1 and later.
+ For Heimdal, you may use either the external password quality check
+ tool, installed as heimdal-strength, or the plugin as you choose. It
+ has been tested with Heimdal 1.2.1 and later, but has not recently been
+ tested with versions prior to 1.5.
- To use this plugin with MIT Kerberos, you will need to apply the patch
- in the patches directory to MIT Kerberos and rebuild. Due to how
- kadmind is constructed, the changes are actually in the libkadm5srv
- library, not in the kadmind binary, so you'll need to install the
- modified libraries.
+ For MIT Kerberos, version 1.9 or higher is required for the password
+ quality plugin interface. MIT Kerberos does not support an external
+ password quality check tool directly, so you will need to install the
+ plugin.
You can optionally build against the system CrackLib library. Any
version should be supported, but note that some versions, particularly
older versions close to the original code, do things like printing
diagnostics to stderr, calling exit, and otherwise not being
- well-behaved for use inside plugins or libraries.
+ well-behaved for use inside plugins or libraries. If using a system
+ CrackLib library, use version 2.8.22 or later to avoid these problems.
For this module to be effective for either Heimdal or MIT Kerberos, you
will also need to construct a dictionary. The mkdict and packer
For a word list to use as source for the dictionary, you can use
/usr/share/dict/words if it's available on your system, but it would be
- better to find a more comprehensive word list (or even better, find
- every word list you can locate on the Internet and combine them). Since
- word lists are bulky, often covered by murky copyrights, and easily
- locatable on the Internet with a modicum of searching, none are included
- in this toolkit.
+ better to find a more comprehensive word list. Since word lists are
+ bulky, often covered by murky copyrights, and easily locatable on the
+ Internet with a modicum of searching, none are included in this toolkit.
To bootstrap from a Git checkout, or If you change the Automake files
and need to regenerate Makefile.in, you will need Automake 1.11 or
/usr/local/bin/heimdal-strength. You can change these paths with the
--prefix, --libdir, and --bindir options to configure.
- For MIT Kerberos, you also have to apply the patch provided in the
- patches directory to the MIT Kerberos source and install the new
- libkadm5srv library. See patches/README for more information about the
- patch. If you're using a different version of MIT Kerberos, you may
- need to adjust the patch accordingly.
-
To build with the system version of CrackLib, pass --with-cracklib to
configure. You can optionally add a directory, giving the root
directory where CrackLib was installed, or separately set the include
You can also individually set the paths to the include directory and the
library directory with --with-krb5-include and --with-krb5-lib. You may
need to do this if Autoconf can't figure out whether to use lib, lib32,
- or lib64 on your platform. Note that these settings aren't used if a
- krb5-config script is found, so you may need to disable the krb5-config
- script as described below.
+ or lib64 on your platform.
To specify a particular krb5-config script to use, either set the
PATH_KRB5_CONFIG environment variable or pass it to configure like:
krb5-config script on your path, set PATH_KRB5_CONFIG to a nonexistent
path:
- ./configure KRB5_CONFIG=/nonexistent
+ ./configure PATH_KRB5_CONFIG=/nonexistent
+
+ krb5-config is not used and library probing is always done if either
+ --with-krb5-include or --with-krb5-lib are given.
You can pass the --enable-reduced-depends flag to configure to try to
minimize the shared library dependencies encoded in the binaries. This
policies = krb5-strength
policy_libraries = /usr/local/lib/kadmind/passwd_strength.so
- in either krb5.conf or kdc.conf. Note that some versions of Heimdal
- have a bug in the support for loading modules when policy_libraries is
- set. If you get an error like:
+ in either krb5.conf or kdc.conf. Note that some older versions of
+ Heimdal have a bug in the support for loading modules when
+ policy_libraries is set. If you get an error like:
didn't find `kadm5_password_verifier' symbol in `(null)'
MIT Kerberos
- In the [realms] section of your kdc.conf, under the appropriate realm or
- realms, specify the path to the dictionary:
+ To add this module to the list of password quality checks, add a section
+ to krb5.conf (or to a separate kdc.conf if you use that) like:
+
+ [plugins]
+ pwqual = {
+ module = strength:/usr/local/lib/kadmind/passwd_strength.so
+ }
+
+ to register the plugin.
+
+ There are two ways to tell where the dictionary is. One option is to
+ use krb5.conf (and in this case you must use krb5.conf, even if you use
+ a separate kdc.conf file). For this approach, add the following to the
+ [appdefaults] section:
+
+ krb5-strength = {
+ password_dictionary = /path/to/cracklib/dictionary
+ }
+
+ The second option is to use the normal dict_path setting. In the
+ [realms] section of your krb5.conf kdc.conf, under the appropriate realm
+ or realms, specify the path to the dictionary:
dict_file = /path/to/cracklib/dictionary
The provided path should be the full path to the dictionary files,
- omitting the trailing *.hwm, *.pwd, or *.pwi extension. Then, specify
- the path to the plugin by adding:
-
- pwcheck_plugin = /usr/local/lib/kadmind/passwd_strength.so
-
- to the same section of the kdc.conf, giving the correct full path to the
- plugin. Restart kadmind and password strength checking should be
- enabled.
-
- Be aware that, for MIT Kerberos, password strength checking is only
- applied to principals with a policy set. If you want to check all user
- passwords, assign all user principals a password policy. (Similarly,
- you can avoid checking the strength of passwords for particular
- principals by clearing their policy.) Also be aware that enabling this
- plugin will disable the normal kadmind dictionary check. There
- currently is no way to have them both enabled at the same time.
-
- Finally, note that the default rules of this plugin will reject the
- temporary password used by addprinc -randkey or ktadd -randkey when
- initializing a principal. When generating service principals using that
- flag, you will need to pass in the -clearpolicy flag as well to avoid
- rejecting the initial temporary password. You can then add a policy
- later with modprinc if desired.
+ omitting the trailing *.hwm, *.pwd, or *.pwi extension. However, be
+ aware that, if you use this approach, you will probably want to disable
+ the built-in standard dict pwqual plugin by adding the line:
+
+ disable = dict
+
+ to the pwqual block of the [plugins] section as shown above. Otherwise,
+ it will also try to load a dictionary at the same path to do simple
+ dictionary matching.
RRA_LIB_CRACKLIB
RRA_LIB_KRB5
RRA_LIB_KRB5_SWITCH
-AC_CHECK_HEADERS([kadm5/kadm5-pwcheck.h krb5/pwcheck_plugin.h], [], [],
+AC_CHECK_HEADERS([kadm5/kadm5-pwcheck.h krb5/pwqual_plugin.h], [], [],
[RRA_INCLUDES_KRB5])
AC_CHECK_TYPES([krb5_realm], [], [], [RRA_INCLUDES_KRB5])
RRA_LIB_KRB5_RESTORE
+++ /dev/null
-The patches in this directory apply to MIT Kerberos and add to kadmind a
-plugin API for checking the acceptability of a password before any
-password (key) change and rejecting the change if the new password is
-unsuitable.
-
-Currently, there is only one patch available:
-
- mit-krb5-1.4.4 Built against MIT Kerberos 1.4.4
-
-This patch should also apply (with some fuzz) to MIT Kerberos 1.6.
-
-More patches against other source trees may be provided in the future.
-Please let me know if there is a specific version you wish to see a patch
-for (and even better, let me know if you have a tested patch for a
-different version).
-
-This patch adds to kadmind a configuration option which should be set in
-the local realm section of kdc.conf. That configuration option is in the
-form:
-
- pwcheck_plugin = /usr/local/lib/kadmind/passwd_strength.so
-
-It passes the value of the existing dict_file configuration option, if
-any, into the initialization function. If this plugin configuration
-option is present, the normal password dictionary check in kadmind is
-suppressed.
-
-
-Any plugin used with this patch must implement the following three
-interfaces:
-
-int pwcheck_init(void **context, const char *dictionary)
-
- Initialize the plugin. A pointer to any data structure that the
- plugin needs to initialize can be stored in context. dictionary will
- be the value of the dict_path configuration option, if set, and NULL
- otherwise. Returns 0 on success and non-zero on failure.
-
-int pwcheck_check(void *context, const char *password,
- const char *principal, char *errstr, int errstrlen)
-
- Called immediately before any password change, at the same point that
- the existing kadmind dictionary check would be called. context is the
- pointer set by pwcheck_init(), if any. password is the new password
- and principal is the principal whose password is being changed, in
- case the module wants to apply checks based on the username. errstr
- is a buffer into which failure messages can be stored and errstrlen is
- the length of that buffer.
-
- This function should return 0 for success and non-zero for failure.
- On failure, some appropriate error message should be written into the
- errstr buffer (being careful to nul-terminate and not exceed errstrlen
- bytes including the terminating nul). The return code and the error
- message will be logged by kadmind but not passed back to the client.
-
- If this call fails (returns a non-zero status), the password change is
- aborted and is not changed in the local KDC database.
-
-void pwcheck_close(void *context)
-
- Called on kadmind shutdown. This function is responsible for freeing
- any resources used by the plugin, if any. context is the pointer set
- by pwcheck_init.
+++ /dev/null
-Patch built against MIT Kerberos 1.4.4. Note that this patch was
-generated with some other Stanford-local patches applied and therefore may
-not apply entirely cleanly. I will hopefully have a chance to regenerate
-a clean patch against a virgin source tarball for a later release.
-
-This patch may apply to earlier or later versions but may not and will
-require verification.
-
-Note that this patch unconditionally adds -ldl to the link line and will
-require modification on platforms that use some other library for dlopen
-and related calls.
-
-
-Index: krb5-local/src/lib/kadm5/admin.h
-===================================================================
---- krb5-local.orig/src/lib/kadm5/admin.h 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/admin.h 2006-06-06 16:29:45.000000000 -0700
-@@ -227,6 +227,7 @@ typedef struct _kadm5_config_params {
- char * admin_keytab;
- char * acl_file;
- char * dict_file;
-+ char * pwcheck_plugin;
-
- int mkey_from_kbd;
- char * stash_file;
-Index: krb5-local/src/lib/kadm5/alt_prof.c
-===================================================================
---- krb5-local.orig/src/lib/kadm5/alt_prof.c 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/alt_prof.c 2006-06-06 16:29:45.000000000 -0700
-@@ -514,7 +514,15 @@ krb5_error_code kadm5_get_config_params(
- params.mask |= KADM5_CONFIG_DICT_FILE;
- params.dict_file = svalue;
- }
--
-+
-+ /* Right now, always get the value for the pwcheck plugin */
-+ hierarchy[2] = "pwcheck_plugin";
-+ if (aprofile && !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
-+ params.pwcheck_plugin = svalue;
-+ } else {
-+ params.pwcheck_plugin = NULL;
-+ }
-+
- /* Get the value for the kadmind port */
- if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) {
- hierarchy[2] = "kadmind_port";
-Index: krb5-local/src/lib/kadm5/server_internal.h
-===================================================================
---- krb5-local.orig/src/lib/kadm5/server_internal.h 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/server_internal.h 2006-06-06 16:29:45.000000000 -0700
-@@ -59,7 +59,7 @@ krb5_error_code kdb_iter_entry(kadm5
- void *data);
-
- int init_dict(kadm5_config_params *);
--int find_word(const char *word);
-+int find_word(const char *word, const char *princ);
- void destroy_dict(void);
-
- /* XXX this ought to be in libkrb5.a, but isn't */
-Index: krb5-local/src/lib/kadm5/srv/server_dict.c
-===================================================================
---- krb5-local.orig/src/lib/kadm5/srv/server_dict.c 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/srv/server_dict.c 2006-06-06 16:29:45.000000000 -0700
-@@ -24,11 +24,17 @@ static char *rcsid = "$Header$";
- #include "adm_proto.h"
- #include <syslog.h>
- #include "server_internal.h"
-+#include <dlfcn.h>
-
- static char **word_list = NULL; /* list of word pointers */
- static char *word_block = NULL; /* actual word data */
- static unsigned int word_count = 0; /* number of words */
--
-+static void *plugin_handle = NULL; /* Library plugin handle */
-+static int (*d_pwcheck_init)(void **, const char *);
-+static int (*d_pwcheck_check)(void *, const char *, const char *,
-+ char *, int);
-+static void (*d_pwcheck_close)(void *);
-+static void *d_pwcheck_context;
-
- /*
- * Function: word_compare
-@@ -86,6 +92,44 @@ int init_dict(kadm5_config_params *param
- *t;
- struct stat sb;
-
-+ if (plugin_handle != NULL)
-+ return KADM5_OK;
-+ if (params->pwcheck_plugin) {
-+ plugin_handle = dlopen(params->pwcheck_plugin, RTLD_NOW);
-+
-+ if (! plugin_handle) {
-+ krb5_klog_syslog(LOG_ERR, "WARNING: Unable to load plugin "
-+ "\"%s\": %s, continuing without password checking",
-+ params->pwcheck_plugin, dlerror());
-+ return KADM5_OK;
-+ }
-+ d_pwcheck_init = dlsym(plugin_handle, "pwcheck_init");
-+ d_pwcheck_check = dlsym(plugin_handle, "pwcheck_check");
-+ d_pwcheck_close = dlsym(plugin_handle, "pwcheck_close");
-+
-+ if (d_pwcheck_init == NULL || d_pwcheck_check == NULL ||
-+ d_pwcheck_close == NULL) {
-+ krb5_klog_syslog(LOG_ERR, "WARNING: Needed symbols missing in "
-+ "pwcheck plugin, continuing without password "
-+ "checking.");
-+ dlclose(plugin_handle);
-+ plugin_handle = NULL;
-+ return KADM5_OK;
-+ }
-+
-+ if ((*d_pwcheck_init)(&d_pwcheck_context, params->dict_file)) {
-+ krb5_klog_syslog(LOG_ERR, "WARNING: Plugin initialization failed, "
-+ "continuing without password checking.");
-+ dlclose(plugin_handle);
-+ plugin_handle = NULL;
-+ return KADM5_OK;
-+ }
-+
-+ krb5_klog_syslog(LOG_INFO, "Password checking plugin \"%s\" "
-+ "initialized.", params->pwcheck_plugin);
-+ return KADM5_OK;
-+ }
-+
- if(word_list != NULL && word_block != NULL)
- return KADM5_OK;
- if (! (params->mask & KADM5_CONFIG_DICT_FILE)) {
-@@ -154,10 +198,26 @@ int init_dict(kadm5_config_params *param
- */
-
- int
--find_word(const char *word)
-+find_word(const char *word, const char *princ)
- {
- char **value;
-
-+ if (plugin_handle) {
-+ char ret_message[256];
-+ int ret_value;
-+
-+ ret_value = (*d_pwcheck_check)(d_pwcheck_context, word, princ,
-+ ret_message, sizeof(ret_message));
-+
-+ if (ret_value) {
-+ krb5_klog_syslog(LOG_INFO, "pwcheck plugin rejected new change: "
-+ "%s", ret_message);
-+ return KADM5_OK;
-+ } else {
-+ return WORD_NOT_FOUND;
-+ }
-+ }
-+
- if(word_list == NULL || word_block == NULL)
- return WORD_NOT_FOUND;
- if ((value = (char **) bsearch(&word, word_list, word_count, sizeof(char *),
-@@ -189,6 +249,9 @@ find_word(const char *word)
- void
- destroy_dict(void)
- {
-+ if (plugin_handle)
-+ (*d_pwcheck_close)(d_pwcheck_context);
-+
- if(word_list) {
- free(word_list);
- word_list = NULL;
-Index: krb5-local/src/lib/kadm5/srv/server_misc.c
-===================================================================
---- krb5-local.orig/src/lib/kadm5/srv/server_misc.c 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/srv/server_misc.c 2006-06-06 16:29:45.000000000 -0700
-@@ -129,6 +129,7 @@ passwd_check(kadm5_server_handle_t handl
- npunct = 0,
- nspec = 0;
- char c, *s, *cp;
-+ krb5_error_code ret;
- #ifdef HESIOD
- extern struct passwd *hes_getpwnam();
- struct passwd *ent;
-@@ -159,9 +160,14 @@ passwd_check(kadm5_server_handle_t handl
- }
- if ((nupper + nlower + ndigit + npunct + nspec) < pol->pw_min_classes)
- return KADM5_PASS_Q_CLASS;
-- if((find_word(password) == KADM5_OK))
-+ ret = krb5_unparse_name(handle->context, principal, &cp);
-+ if (ret)
-+ return ret;
-+ ret = find_word(password, cp);
-+ krb5_free_unparsed_name(handle->context, cp);
-+ if(ret == KADM5_OK) {
- return KADM5_PASS_Q_DICT;
-- else {
-+ } else {
- int i, n = krb5_princ_size(handle->context, principal);
- cp = krb5_princ_realm(handle->context, principal)->data;
- if (strcasecmp(cp, password) == 0)
-Index: krb5-local/src/lib/kadm5/Makefile.in
-===================================================================
---- krb5-local.orig/src/lib/kadm5/Makefile.in 2006-06-06 16:22:39.000000000 -0700
-+++ krb5-local/src/lib/kadm5/Makefile.in 2006-06-06 16:29:45.000000000 -0700
-@@ -53,6 +53,8 @@ STLIBOBJS = \
- str_conv.o \
- logger.o
-
-+SHLIB_EXPLIBS=-ldl
-+
- HDRDIR=$(BUILDTOP)/include/kadm5
- HDRS = $(HDRDIR)/adb.h \
- $(HDRDIR)/admin.h \
-Index: krb5-local/src/config/pre.in
-===================================================================
---- krb5-local.orig/src/config/pre.in 2006-06-06 16:31:20.000000000 -0700
-+++ krb5-local/src/config/pre.in 2006-06-06 16:31:33.000000000 -0700
-@@ -393,7 +393,7 @@ GSS_LIBS = $(GSS_KRB5_LIB)
- GSSRPC_LIBS = -lgssrpc $(GSS_LIBS)
- KADM_COMM_LIBS = $(GSSRPC_LIBS)
- # need fixing if ever used on Mac OS X!
--KADMSRV_LIBS = -lkadm5srv $(HESIOD_LIBS) $(KDB5_LIBS) $(KADM_COMM_LIBS)
-+KADMSRV_LIBS = -lkadm5srv $(HESIOD_LIBS) $(KDB5_LIBS) $(KADM_COMM_LIBS) -ldl
- KADMCLNT_LIBS = -lkadm5clnt $(KADM_COMM_LIBS)
-
- # need fixing if ever used on Mac OS X!
/*
- * MIT Kerberos shared module API.
+ * Kerberos shared module API for MIT krb5 1.9 or later.
*
- * This is the glue required for a Heimdal password quality check via a
- * dynamically loaded module. Retrieves the dictionary path from krb5.conf.
- * This may change in later versions via a mechanism to pass profile
- * information from kadmind to the plugin.
+ * This is the glue required for a password quality check via a dynamically
+ * loaded module using the MIT krb5 pwqual interface.
*
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2010
- * The Board of Trustees of the Leland Stanford Junior Unversity
+ * Written by Greg Hudson <ghudson@mit.edu>
+ * Copyright 2010 the Massachusetts Institute of Technology
+ * Copyright 2013
+ * The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
#include <errno.h>
#include <krb5.h>
+#ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
+# include <krb5/pwqual_plugin.h>
+#endif
#include <plugin/api.h>
-/* Skip this entire file if building with Heimdal. */
-#ifndef HAVE_KRB5_REALM
+/* Skip this entire file if building with Heimdal or pre-1.9 MIT. */
+#ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
/* Used for unused parameters to silence gcc warnings. */
-#define UNUSED __attribute__((__unused__))
-
-/* Allow for a build without the plugin header. */
-# ifdef HAVE_KRB5_PWCHECK_PLUGIN_H
-# include <krb5/pwcheck_plugin.h>
-# else
-typedef struct krb5plugin_kadmin_pwcheck_ftable_v0 {
- int minor_version;
- krb5_error_code (*init)(krb5_context, void **);
- void (*fini)(krb5_context, void *);
- int (*check)(krb5_context, void *, krb5_const_principal,
- const krb5_data *password);
-} krb5plugin_kadmin_pwcheck_ftable_v0;
-# endif /* !HAVE_KRB5_PWCHECK_PLUGIN_H */
-
+# define UNUSED __attribute__((__unused__))
/*
* Initialize the library. We can't just call pwcheck_init, since currently
* dictionary is, and then call pwcheck_init.
*/
static krb5_error_code
-init(krb5_context context, void **data)
+init(krb5_context context, const char *dict_file, krb5_pwqual_moddata *data)
{
- char *dictionary = NULL;
+ void *d;
- krb5_appdefault_string(context, "krb5-strength", NULL,
- "password_dictionary", "", &dictionary);
- if (dictionary == NULL || dictionary[0] == '\0') {
- krb5_set_error_message(context, KRB5_PLUGIN_OP_NOTSUPP,
- "password_dictionary not configured in"
- " krb5.conf");
- return KRB5_PLUGIN_OP_NOTSUPP;
- }
- if (pwcheck_init(data, dictionary) != 0) {
+ if (pwcheck_init(&d, dict_file) != 0) {
krb5_set_error_message(context, errno, "Cannot initialize strength"
- " checking with dictionary %s: %s", dictionary,
+ " checking with dictionary %s: %s", dict_file,
strerror(errno));
return errno;
}
+ *data = d;
return 0;
}
-
/*
- * Check the password. We need to transform the krb5_data struct and the
- * principal passed us by kadmind into nul-terminated strings for our check.
+ * Check the password. We need to transform the principal passed us by kadmind
+ * into a string for our check.
*/
static krb5_error_code
-check(krb5_context context, void *data, krb5_const_principal princ,
- const krb5_data *password)
+check(krb5_context context, krb5_pwqual_moddata data, const char *password,
+ const char *policy_name UNUSED, krb5_principal princ,
+ const char **languages UNUSED)
{
- char *pastring;
char *name = NULL;
krb5_error_code status;
char message[BUFSIZ];
status = krb5_unparse_name(context, princ, &name);
if (status != 0)
return status;
- pastring = malloc(password->length + 1);
- if (pastring == NULL) {
- status = errno;
- krb5_set_error_message(context, status, "%s", strerror(status));
- krb5_free_unparsed_name(context, name);
- return status;
- }
- memcpy(pastring, password->data, password->length);
- pastring[password->length] = '\0';
- status = pwcheck_check(data, pastring, name, message, sizeof(message));
+ status = pwcheck_check(data, password, name, message, sizeof(message));
if (status != 0)
krb5_set_error_message(context, status, "%s", message);
- free(pastring);
krb5_free_unparsed_name(context, name);
return status;
}
-
/*
* Shut down the library.
*/
static void
-fini(krb5_context context UNUSED, void *data)
+fini(krb5_context context UNUSED, krb5_pwqual_moddata data)
{
pwcheck_close(data);
}
-
/* The public symbol that MIT Kerberos looks for. */
-krb5plugin_kadmin_pwcheck_ftable_v0 kadmin_pwcheck_0 = {
- 0, init, fini, check
-};
+krb5_error_code
+pwqual_strength_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable);
+
+krb5_error_code
+pwqual_strength_initvt(krb5_context context UNUSED, int maj_ver,
+ int min_ver UNUSED, krb5_plugin_vtable vtable)
+{
+ krb5_pwqual_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (krb5_pwqual_vtable)vtable;
+ vt->name = "krb5-strength";
+ vt->open = init;
+ vt->check = check;
+ vt->close = fini;
+ return 0;
+}
-#endif /* !HAVE_KRB5_REALM */
+#endif /* HAVE_KRB5_PWQUAL_PLUGIN_H */
# Test suite wrapper for the MIT Kerberos shared module API.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009, 2010
+# Copyright 2009, 2010, 2013
# The Board of Trustees of the Leland Stanford Junior University
#
# See LICENSE for licensing terms.
password="$3"
w_status="$4"
w_stderr="$5"
- stderr=`"$BUILD/mit/plugin" "$princ" "$password" 2>&1`
+ dict="${BUILD}/data/dictionary"
+ stderr=`"$BUILD/mit/plugin" "$princ" "$password" "$dict" 2>&1`
status="$?"
echo "# status: $status"
echo "# stderr: $stderr"
fi
# Okay, we should be good to run the test suite.
-plan 28
-
-# We don't have a password_dictionary setting, so we should fail with an
-# initialization error.
-ok_password "no dictionary configured" 'test@EXAMPLE.ORG' 'password' 1 \
- 'password_dictionary not configured in krb5.conf'
-
-# Now add the password dictionary configuration.
-cat <<EOF >> ./krb5.conf
-
-[appdefaults]
- krb5-strength = {
- password_dictionary = $BUILD/data/dictionary
- }
-
-EOF
+plan `expr 13 \* 2`
# Check the basic functionality.
ok_password "good password" 'test@EXAMPLE.ORG' 'known good password' 0 ''
#include <dlfcn.h>
#include <errno.h>
#include <krb5.h>
+#ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
+# include <krb5/pwqual_plugin.h>
+#endif
-/* Allow for a build without the plugin header. */
-# ifdef HAVE_KRB5_PWCHECK_PLUGIN_H
-# include <krb5/pwcheck_plugin.h>
-# else
-typedef struct krb5plugin_kadmin_pwcheck_ftable_v0 {
- int minor_version;
- krb5_error_code (*init)(krb5_context, void **);
- void (*fini)(krb5_context, void *);
- int (*check)(krb5_context, void *, krb5_const_principal,
- const krb5_data *password);
-} krb5plugin_kadmin_pwcheck_ftable_v0;
-# endif /* !HAVE_KRB5_PWCHECK_PLUGIN_H */
+#include <tests/tap/macros.h>
+#ifndef HAVE_KRB5_PWQUAL_PLUGIN_H
+/*
+ * If we're not building with MIT Kerberos, we can't run this test. Exit with
+ * a special status to communicate this to the test wrapper.
+ */
+int
+main(int argc UNUSED, char *argv[] UNUSED)
+{
+ exit(42);
+}
+
+#else
+
+/* The public symbol that we load and call to get the vtable. */
+typedef krb5_error_code pwqual_strength_initvt(krb5_context, int, int,
+ krb5_plugin_vtable);
/*
* Expects a principal and a password to check on the command line. Loads the
size_t length;
krb5_context ctx;
krb5_principal princ;
- krb5_data password;
krb5_error_code status;
- void *handle, *data;
- struct krb5plugin_kadmin_pwcheck_ftable_v0 *verifier;
-
- /*
- * If we're not building with MIT Kerberos, we can't run this test. Exit
- * with a special status to communicate this to the test wrapper.
- */
-#ifdef HAVE_KRB5_REALM
- exit(42);
-#endif
+ void *handle;
+ krb5_pwqual_moddata data;
+ krb5_pwqual_vtable verifier = NULL;
+ krb5_error_code (*init)(krb5_context, int, int, krb5_plugin_vtable);
/* Build the path of the plugin. */
- if (argc != 3) {
+ if (argc != 4) {
fprintf(stderr, "Wrong number of arguments\n");
exit(1);
}
fprintf(stderr, "Cannot parse principal name\n");
exit(1);
}
- password.length = strlen(argv[2]);
- password.data = argv[2];
/* Load the module and find the correct symbol. */
handle = dlopen(path, RTLD_NOW);
fprintf(stderr, "Cannot dlopen %s: %s\n", path, dlerror());
exit(1);
}
- verifier = dlsym(handle, "kadmin_pwcheck_0");
+ init = dlsym(handle, "pwqual_strength_initvt");
+ if (init == NULL) {
+ fprintf(stderr, "Cannot get pwqual_strength_initvt symbol: %s\n",
+ dlerror());
+ exit(1);
+ }
+
+ /* Call that function to get the vtable. */
+ verifier = malloc(sizeof(*verifier));
if (verifier == NULL) {
- fprintf(stderr, "Cannot get kadmin_pwcheck_0 symbol: %s\n", dlerror());
+ fprintf(stderr, "Cannot allocate memory: %s\n", strerror(errno));
exit(1);
}
- if (verifier->minor_version != 0
- || verifier->init == NULL
- || verifier->check == NULL
- || verifier->fini == NULL) {
+ status = init(ctx, 1, 1, (krb5_plugin_vtable) verifier);
+ if (status != 0) {
+ fprintf(stderr, "Cannot obtain module vtable\n");
+ exit(1);
+ }
+ if (strcmp(verifier->name, "krb5-strength") != 0) {
fprintf(stderr, "Invalid metadata in plugin\n");
exit(1);
}
- status = verifier->init(ctx, &data);
+
+ /* Open the verifier, run the check function, and close it. */
+ status = verifier->open(ctx, argv[3], &data);
if (status != 0) {
fprintf(stderr, "%s\n", krb5_get_error_message(ctx, status));
exit(1);
}
- status = verifier->check(ctx, data, princ, &password);
+ status = verifier->check(ctx, data, argv[2], NULL, princ, NULL);
if (status != 0)
fprintf(stderr, "%s\n", krb5_get_error_message(ctx, status));
- verifier->fini(ctx, data);
+ verifier->close(ctx, data);
exit(status);
}
+
+#endif /* HAVE_KRB5_PWQUAL_PLUGIN_H */