]> eyrie.org Git - kerberos/krb5-strength.git/commitdiff
Add support for new MIT plugin interface, drop old patch
authorRuss Allbery <rra@stanford.edu>
Thu, 19 Sep 2013 03:55:02 +0000 (20:55 -0700)
committerRuss Allbery <rra@stanford.edu>
Thu, 19 Sep 2013 06:13:35 +0000 (23:13 -0700)
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).

Makefile.am
NEWS
README
configure.ac
patches/README [deleted file]
patches/mit-krb5-1.4.4 [deleted file]
plugin/mit.c
tests/mit/plugin-t
tests/mit/plugin.c

index 4112956a519616d5ae367ff82ea66f088d87a50c..d2c71dac3f6bcd958ee3e82e07b5b8bbb8a5b387 100644 (file)
@@ -43,7 +43,8 @@ endif
 
 # 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
diff --git a/NEWS b/NEWS
index 77381323e51ce251694f6b8be770a315d0577c3f..a8fc32ad67042c3f36b7d215d48959365bac161b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@
 
 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
diff --git a/README b/README
index 81ea778ab10e515158dbd071d178aa06316e93b9..faa3fab6a97a232dbfc8872d0781d951f35f9d31 100644 (file)
--- a/README
+++ b/README
@@ -1,10 +1,10 @@
                             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.
 
@@ -18,9 +18,7 @@ BLURB
   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
 
@@ -30,28 +28,13 @@ 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,
@@ -69,29 +52,29 @@ DESCRIPTION
   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
@@ -103,11 +86,9 @@ REQUIREMENTS
 
   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
@@ -133,12 +114,6 @@ COMPILING AND INSTALLING
   /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
@@ -158,9 +133,7 @@ COMPILING AND INSTALLING
   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:
@@ -171,7 +144,10 @@ COMPILING AND INSTALLING
   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
@@ -230,9 +206,9 @@ CONFIGURATION
           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)'
 
@@ -242,32 +218,38 @@ CONFIGURATION
 
  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.
index 268086ad08c38165d07f0e5f6fa8bbce27634d64..74e14e2964c9e8bbd36994f96ceb9ae4602dc8d7 100644 (file)
@@ -27,7 +27,7 @@ AC_PROG_LIBTOOL
 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
diff --git a/patches/README b/patches/README
deleted file mode 100644 (file)
index ec284ef..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-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.
diff --git a/patches/mit-krb5-1.4.4 b/patches/mit-krb5-1.4.4
deleted file mode 100644 (file)
index dd918ad..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-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!
index 5dec76feb0747859615ae0d7f4f70e2c34d6914a..6abd3958fbcb4e984daccd5eb6a19af8b3726ba2 100644 (file)
@@ -1,14 +1,13 @@
 /*
- * 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
@@ -47,37 +35,29 @@ typedef struct krb5plugin_kadmin_pwcheck_ftable_v0 {
  * 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];
@@ -85,37 +65,41 @@ check(krb5_context context, void *data, krb5_const_principal princ,
     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 */
index 4ccd8503d74a6e2babfdce3cf64379033ff8bdf4..ccb9d03a49fbd3de68e949178bb5a87b46f455b3 100755 (executable)
@@ -3,7 +3,7 @@
 # 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.
@@ -20,7 +20,8 @@ ok_password () {
     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"
@@ -53,22 +54,7 @@ if [ $? = 42 ] ; then
 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 ''
index ea7585e3f000119b848d6400c1645e7d02ed41ef..182ff3a6ce58225f10ac61880e98372480f8a113 100644 (file)
 #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
@@ -49,21 +57,14 @@ main(int argc, char *argv[])
     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);
     }
@@ -92,8 +93,6 @@ main(int argc, char *argv[])
         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);
@@ -101,26 +100,40 @@ main(int argc, char *argv[])
         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 */