]> eyrie.org Git - kerberos/krb5-strength.git/commitdiff
Merge branch 'debian' into squeeze
authorRuss Allbery <eagle@eyrie.org>
Mon, 16 Dec 2013 23:56:24 +0000 (15:56 -0800)
committerRuss Allbery <eagle@eyrie.org>
Mon, 16 Dec 2013 23:56:24 +0000 (15:56 -0800)
Conflicts:
debian/changelog
debian/control

102 files changed:
.gitignore
LICENSE
Makefile.am
Makefile.in
NEWS
README
TODO
config.h.in
configure
configure.ac
cracklib/HISTORY
cracklib/fascist.c
cracklib/packer.c
cracklib/packer.h
cracklib/packlib.c
cracklib/rules.c
cracklib/stringlib.c
debian/changelog
debian/control
debian/copyright
m4/cracklib.m4
m4/krb5-config.m4
m4/krb5.m4
m4/lib-depends.m4
m4/lib-helper.m4
m4/lib-pathname.m4
m4/snprintf.m4
m4/tinycdb.m4
m4/vamacros.m4
plugin/cdb.c
plugin/classes.c [new file with mode: 0644]
plugin/config.c
plugin/cracklib.c
plugin/error.c
plugin/general.c
plugin/heimdal.c
plugin/internal.h
plugin/principal.c
plugin/vector.c [new file with mode: 0644]
portable/asprintf.c
portable/dummy.c
portable/kadmin.h
portable/krb5-extra.c
portable/krb5.h
portable/macros.h
portable/snprintf.c
portable/stdbool.h
portable/strndup.c [new file with mode: 0644]
portable/system.h
tests/HOWTO
tests/TESTS
tests/data/make-krb5-conf
tests/data/passwords/classes.c [new file with mode: 0644]
tests/data/passwords/classes.json [new file with mode: 0644]
tests/data/passwords/letter.c [moved from tests/data/passwords/class.c with 97% similarity]
tests/data/passwords/letter.json [moved from tests/data/passwords/class.json with 100% similarity]
tests/data/passwords/make-c-data
tests/data/passwords/tests.h
tests/data/perlcriticrc
tests/data/valgrind.supp [new file with mode: 0644]
tests/docs/pod-spelling-t
tests/docs/pod-t
tests/perl/critic-t
tests/perl/minimum-version-t
tests/perl/strict-t
tests/plugin/heimdal-t.c
tests/plugin/mit-t.c
tests/portable/asprintf-t.c
tests/portable/snprintf-t.c
tests/portable/strndup-t.c [new file with mode: 0644]
tests/portable/strndup.c [new file with mode: 0644]
tests/runtests.c
tests/tap/basic.c
tests/tap/basic.h
tests/tap/kerberos.c
tests/tap/kerberos.h
tests/tap/libtap.sh
tests/tap/macros.h
tests/tap/perl/Test/RRA.pm
tests/tap/perl/Test/RRA/Automake.pm
tests/tap/perl/Test/RRA/Config.pm
tests/tap/process.c
tests/tap/process.h
tests/tap/string.c
tests/tap/string.h
tests/tools/cdbmake-wordlist-t
tests/tools/heimdal-strength-t
tests/util/messages-krb5-t.c
tests/util/messages-t.c
tests/util/xmalloc-t
tests/util/xmalloc.c
tools/cdbmake-wordlist
tools/cdbmake-wordlist.1
tools/heimdal-strength.1
tools/heimdal-strength.c
tools/heimdal-strength.pod
util/macros.h
util/messages-krb5.c
util/messages-krb5.h
util/messages.c
util/xmalloc.c
util/xmalloc.h

index 02ec31664edcbcd7104987c6b2f462088e070853..9d75f42ea1cc9e0f81adc522aed5d879c91f52ee 100644 (file)
@@ -25,6 +25,7 @@
 /tests/plugin/mit-t
 /tests/portable/asprintf-t
 /tests/portable/snprintf-t
+/tests/portable/strndup-t
 /tests/runtests
 /tests/tap/libtap.a
 /tests/util/messages-krb5-t
diff --git a/LICENSE b/LICENSE
index 59827b4d424eaf4e38d455eccac2f3d094c0340b..58dccb1b0b388af18776771d0055e3f147051910 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -10,11 +10,9 @@ Copyright: 2006-2007, 2009-2013
 License: Expat
 
 Files: *
-Copyright: 2000-2002, 2004-2012 Russ Allbery <rra@stanford.edu>
+Copyright: 2000-2002, 2004-2013 Russ Allbery <eagle@eyrie.org>
   2001-2002, 2004-2013
     The Board of Trustees of the Leland Stanford Junior University
-  2006-2007, 2009, 2012-2013
-    The Board of Trustees of the Leland Stanford Junior Unversity
   2010 the Massachusetts Institute of Technology
 License: Expat
 
@@ -99,7 +97,8 @@ License: FSF-unlimited, and GPL-2+ with Libtool exception or Expat
 
 Files: portable/asprintf.c portable/dummy.c portable/kadmin.h
  portable/krb5-extra.c portable/krb5.h portable/macros.h portable/stdbool.h
- portable/system.h tests/portable/asprintf-t.c util/macros.h
+ portable/strndup.c portable/system.h tests/portable/asprintf-t.c
+ tests/portable/strndup-t.c util/macros.h
 Copyright: no copyright notice, see License
 License: rra-public-domain
  The authors hereby relinquish any claim to any copyright that they may
@@ -112,7 +111,7 @@ License: rra-public-domain
 
 Files: portable/snprintf.c tests/portable/snprintf-t.c
 Copyright: 1995 Patrick Powell
-  2000-2006 Russ Allbery <rra@stanford.edu>
+  2000-2006 Russ Allbery <eagle@eyrie.org>
   2001 Hrvoje Niksic
   2009-2010 The Board of Trustees of the Leland Stanford Junior University
 License: Powell-snprintf
@@ -121,7 +120,7 @@ License: Powell-snprintf
  on all source code distributions
 
 Files: tests/HOWTO tools/heimdal-strength.1 tools/heimdal-strength.pod
-Copyright: 2010 Russ Allbery <rra@stanford.edu>
+Copyright: 2010 Russ Allbery <eagle@eyrie.org>
   2010, 2013 The Board of Trustees of the Leland Stanford Junior University
 License: all-permissive
  Copying and distribution of this file, with or without modification, are
index bdfae8925c1e9bbac6dd27e621288a67f897784c..c1f2e12b702ac5d9c990f5945c87c3ecbbc949b3 100644 (file)
@@ -1,6 +1,6 @@
 # Automake makefile for krb5-strength.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2007, 2009, 2010, 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -11,10 +11,10 @@ EXTRA_DIST = .gitignore LICENSE autogen cracklib/HISTORY cracklib/LICENCE  \
        cracklib/README cracklib/genrules.pl cracklib/mkdict tests/HOWTO   \
        tests/TESTS tests/data/krb5.conf tests/data/make-krb5-conf         \
        tests/data/passwords tests/data/perl.conf tests/data/perlcriticrc  \
-       tests/data/perltidyrc tests/data/wordlist tests/data/wordlist.cdb  \
-       tests/docs/pod-spelling-t tests/docs/pod-t tests/perl/critic-t     \
-       tests/perl/minimum-version-t tests/perl/strict-t                   \
-       tests/tap/libtap.sh tests/tap/perl/Test/RRA.pm                     \
+       tests/data/perltidyrc tests/data/valgrind.supp tests/data/wordlist \
+       tests/data/wordlist.cdb tests/docs/pod-spelling-t tests/docs/pod-t \
+       tests/perl/critic-t tests/perl/minimum-version-t                   \
+       tests/perl/strict-t tests/tap/libtap.sh tests/tap/perl/Test/RRA.pm \
        tests/tap/perl/Test/RRA/Config.pm                                  \
        tests/tap/perl/Test/RRA/Automake.pm tests/tools/cdbmake-wordlist-t \
        tests/tools/heimdal-strength-t tests/util/xmalloc-t                \
@@ -55,9 +55,9 @@ moduledir = $(libdir)/krb5/plugins/pwqual
 
 # Rules for building the password strength plugin.
 module_LTLIBRARIES = plugin/strength.la
-plugin_strength_la_SOURCES = plugin/cdb.c plugin/config.c plugin/cracklib.c \
-       plugin/error.c plugin/general.c plugin/heimdal.c plugin/internal.h  \
-       plugin/mit.c plugin/principal.c
+plugin_strength_la_SOURCES = plugin/cdb.c plugin/classes.c plugin/config.c \
+       plugin/cracklib.c plugin/error.c plugin/general.c plugin/heimdal.c \
+       plugin/internal.h plugin/mit.c plugin/principal.c plugin/vector.c
 plugin_strength_la_LDFLAGS = -module -avoid-version
 if EMBEDDED_CRACKLIB
     plugin_strength_la_LIBADD = cracklib/libcracklib.la
@@ -69,9 +69,10 @@ plugin_strength_la_LIBADD += portable/libportable.la $(KRB5_LIBS) $(CDB_LIBS)
 # The Heimdal external check program.
 bin_PROGRAMS = tools/heimdal-strength
 tools_heimdal_strength_CFLAGS = $(AM_CFLAGS)
-tools_heimdal_strength_SOURCES = plugin/cdb.c plugin/config.c              \
-       plugin/cracklib.c plugin/error.c plugin/general.c plugin/internal.h \
-       plugin/principal.c tools/heimdal-strength.c
+tools_heimdal_strength_SOURCES = plugin/cdb.c plugin/classes.c           \
+       plugin/config.c plugin/cracklib.c plugin/error.c plugin/general.c \
+       plugin/internal.h plugin/principal.c plugin/vector.c              \
+       tools/heimdal-strength.c
 if EMBEDDED_CRACKLIB
     tools_heimdal_strength_LDADD = cracklib/libcracklib.la
 else
@@ -120,9 +121,10 @@ warnings:
        $(MAKE) V=0 CFLAGS='$(WARNINGS)' $(check_PROGRAMS)
 
 # The bits below are for the test suite, not for the main package.
-check_PROGRAMS = tests/runtests tests/plugin/heimdal-t tests/plugin/mit-t   \
-       tests/portable/asprintf-t tests/portable/snprintf-t                 \
-       tests/util/messages-krb5-t tests/util/messages-t tests/util/xmalloc
+check_PROGRAMS = tests/runtests tests/plugin/heimdal-t tests/plugin/mit-t \
+       tests/portable/asprintf-t tests/portable/snprintf-t               \
+       tests/portable/strndup-t tests/util/messages-krb5-t               \
+       tests/util/messages-t tests/util/xmalloc
 if EMBEDDED_CRACKLIB
     check_PROGRAMS += cracklib/packer
 endif
@@ -148,6 +150,9 @@ tests_portable_asprintf_t_LDADD = tests/tap/libtap.a portable/libportable.la
 tests_portable_snprintf_t_SOURCES = tests/portable/snprintf-t.c \
        tests/portable/snprintf.c
 tests_portable_snprintf_t_LDADD = tests/tap/libtap.a portable/libportable.la
+tests_portable_strndup_t_SOURCES = tests/portable/strndup-t.c \
+       tests/portable/strndup.c
+tests_portable_strndup_t_LDADD = tests/tap/libtap.a portable/libportable.la
 tests_util_messages_t_LDADD = tests/tap/libtap.a util/libutil.a \
        portable/libportable.la
 tests_util_messages_krb5_t_LDADD = tests/tap/libtap.a util/libutil.a \
@@ -170,3 +175,18 @@ endif
 
 check-local: $(check_PROGRAMS) tests/data/dictionary.pwd
        cd tests && ./runtests -l $(abs_top_srcdir)/tests/TESTS
+
+# Used by maintainers to run the main test suite under valgrind.  Suppress
+# the xmalloc and pod-spelling tests because the former won't work properly
+# under valgrind (due to increased memory usage) and the latter is pointless
+# to run under valgrind.  Don't try to trace the test for cdbmake-wordlist,
+# since it's pure Perl.
+check-valgrind: $(check_PROGRAMS) tests/data/dictionary.pwd
+       rm -rf $(abs_top_builddir)/tmp-valgrind
+       mkdir $(abs_top_builddir)/tmp-valgrind
+       env RRA_MAINTAINER_TESTS= valgrind --leak-check=full    \
+           --show-reachable=yes --trace-children=yes           \
+           --log-file=$(abs_top_builddir)/tmp-valgrind/log.%p  \
+           --suppressions=tests/data/valgrind.supp             \
+           --trace-children-skip="/bin/sh,*/cat,*/diff,*/expr,*/grep,*/mkdir,*/rm,*/rmdir,*/sed,*/sleep,*/true,*/wc,*/docs/*-t,*/perl/*-t,*/data/make-krb5-conf,*/tools/cdbmake-wordlist-t" \
+           tests/runtests -l '$(abs_top_srcdir)/tests/TESTS'
index cd6b037aa0d633dc431f71478bd526d39ef0633a..715cae7a49b2502f07492896e39fecea683fb35a 100644 (file)
@@ -16,7 +16,7 @@
 
 # Automake makefile for krb5-strength.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2007, 2009, 2010, 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -95,6 +95,7 @@ check_PROGRAMS = tests/runtests$(EXEEXT) \
        tests/plugin/heimdal-t$(EXEEXT) tests/plugin/mit-t$(EXEEXT) \
        tests/portable/asprintf-t$(EXEEXT) \
        tests/portable/snprintf-t$(EXEEXT) \
+       tests/portable/strndup-t$(EXEEXT) \
        tests/util/messages-krb5-t$(EXEEXT) \
        tests/util/messages-t$(EXEEXT) tests/util/xmalloc$(EXEEXT) \
        $(am__EXEEXT_1)
@@ -102,9 +103,10 @@ check_PROGRAMS = tests/runtests$(EXEEXT) \
 subdir = .
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
        $(top_srcdir)/configure $(am__configure_deps) \
-       $(srcdir)/config.h.in $(top_srcdir)/portable/asprintf.c \
-       $(top_srcdir)/portable/krb5-extra.c \
-       $(top_srcdir)/portable/snprintf.c $(dist_bin_SCRIPTS) \
+       $(srcdir)/config.h.in $(top_srcdir)/portable/snprintf.c \
+       $(top_srcdir)/portable/asprintf.c \
+       $(top_srcdir)/portable/strndup.c \
+       $(top_srcdir)/portable/krb5-extra.c $(dist_bin_SCRIPTS) \
        $(top_srcdir)/build-aux/depcomp $(dist_man_MANS) NEWS README \
        TODO build-aux/ar-lib build-aux/compile build-aux/config.guess \
        build-aux/config.sub build-aux/depcomp build-aux/install-sh \
@@ -206,9 +208,10 @@ am__DEPENDENCIES_1 =
 @EMBEDDED_CRACKLIB_TRUE@       portable/libportable.la \
 @EMBEDDED_CRACKLIB_TRUE@       $(am__DEPENDENCIES_1) \
 @EMBEDDED_CRACKLIB_TRUE@       $(am__DEPENDENCIES_1)
-am_plugin_strength_la_OBJECTS = plugin/cdb.lo plugin/config.lo \
-       plugin/cracklib.lo plugin/error.lo plugin/general.lo \
-       plugin/heimdal.lo plugin/mit.lo plugin/principal.lo
+am_plugin_strength_la_OBJECTS = plugin/cdb.lo plugin/classes.lo \
+       plugin/config.lo plugin/cracklib.lo plugin/error.lo \
+       plugin/general.lo plugin/heimdal.lo plugin/mit.lo \
+       plugin/principal.lo plugin/vector.lo
 plugin_strength_la_OBJECTS = $(am_plugin_strength_la_OBJECTS)
 plugin_strength_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
        $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
@@ -250,6 +253,13 @@ tests_portable_snprintf_t_OBJECTS =  \
        $(am_tests_portable_snprintf_t_OBJECTS)
 tests_portable_snprintf_t_DEPENDENCIES = tests/tap/libtap.a \
        portable/libportable.la
+am_tests_portable_strndup_t_OBJECTS =  \
+       tests/portable/strndup-t.$(OBJEXT) \
+       tests/portable/strndup.$(OBJEXT)
+tests_portable_strndup_t_OBJECTS =  \
+       $(am_tests_portable_strndup_t_OBJECTS)
+tests_portable_strndup_t_DEPENDENCIES = tests/tap/libtap.a \
+       portable/libportable.la
 tests_runtests_SOURCES = tests/runtests.c
 tests_runtests_OBJECTS = tests/tests_runtests-runtests.$(OBJEXT)
 tests_runtests_LDADD = $(LDADD)
@@ -268,11 +278,13 @@ tests_util_xmalloc_DEPENDENCIES = util/libutil.a \
        portable/libportable.la
 am_tools_heimdal_strength_OBJECTS =  \
        plugin/tools_heimdal_strength-cdb.$(OBJEXT) \
+       plugin/tools_heimdal_strength-classes.$(OBJEXT) \
        plugin/tools_heimdal_strength-config.$(OBJEXT) \
        plugin/tools_heimdal_strength-cracklib.$(OBJEXT) \
        plugin/tools_heimdal_strength-error.$(OBJEXT) \
        plugin/tools_heimdal_strength-general.$(OBJEXT) \
        plugin/tools_heimdal_strength-principal.$(OBJEXT) \
+       plugin/tools_heimdal_strength-vector.$(OBJEXT) \
        tools/tools_heimdal_strength-heimdal-strength.$(OBJEXT)
 tools_heimdal_strength_OBJECTS = $(am_tools_heimdal_strength_OBJECTS)
 @EMBEDDED_CRACKLIB_FALSE@tools_heimdal_strength_DEPENDENCIES =  \
@@ -330,7 +342,8 @@ SOURCES = $(tests_tap_libtap_a_SOURCES) $(util_libutil_a_SOURCES) \
        $(portable_libportable_la_SOURCES) $(cracklib_packer_SOURCES) \
        tests/plugin/heimdal-t.c tests/plugin/mit-t.c \
        $(tests_portable_asprintf_t_SOURCES) \
-       $(tests_portable_snprintf_t_SOURCES) tests/runtests.c \
+       $(tests_portable_snprintf_t_SOURCES) \
+       $(tests_portable_strndup_t_SOURCES) tests/runtests.c \
        tests/util/messages-krb5-t.c tests/util/messages-t.c \
        tests/util/xmalloc.c $(tools_heimdal_strength_SOURCES)
 DIST_SOURCES = $(tests_tap_libtap_a_SOURCES) $(util_libutil_a_SOURCES) \
@@ -339,7 +352,8 @@ DIST_SOURCES = $(tests_tap_libtap_a_SOURCES) $(util_libutil_a_SOURCES) \
        $(portable_libportable_la_SOURCES) $(cracklib_packer_SOURCES) \
        tests/plugin/heimdal-t.c tests/plugin/mit-t.c \
        $(tests_portable_asprintf_t_SOURCES) \
-       $(tests_portable_snprintf_t_SOURCES) tests/runtests.c \
+       $(tests_portable_snprintf_t_SOURCES) \
+       $(tests_portable_strndup_t_SOURCES) tests/runtests.c \
        tests/util/messages-krb5-t.c tests/util/messages-t.c \
        tests/util/xmalloc.c $(tools_heimdal_strength_SOURCES)
 am__can_run_installinfo = \
@@ -520,10 +534,10 @@ EXTRA_DIST = .gitignore LICENSE autogen cracklib/HISTORY cracklib/LICENCE  \
        cracklib/README cracklib/genrules.pl cracklib/mkdict tests/HOWTO   \
        tests/TESTS tests/data/krb5.conf tests/data/make-krb5-conf         \
        tests/data/passwords tests/data/perl.conf tests/data/perlcriticrc  \
-       tests/data/perltidyrc tests/data/wordlist tests/data/wordlist.cdb  \
-       tests/docs/pod-spelling-t tests/docs/pod-t tests/perl/critic-t     \
-       tests/perl/minimum-version-t tests/perl/strict-t                   \
-       tests/tap/libtap.sh tests/tap/perl/Test/RRA.pm                     \
+       tests/data/perltidyrc tests/data/valgrind.supp tests/data/wordlist \
+       tests/data/wordlist.cdb tests/docs/pod-spelling-t tests/docs/pod-t \
+       tests/perl/critic-t tests/perl/minimum-version-t                   \
+       tests/perl/strict-t tests/tap/libtap.sh tests/tap/perl/Test/RRA.pm \
        tests/tap/perl/Test/RRA/Config.pm                                  \
        tests/tap/perl/Test/RRA/Automake.pm tests/tools/cdbmake-wordlist-t \
        tests/tools/heimdal-strength-t tests/util/xmalloc-t                \
@@ -565,9 +579,9 @@ moduledir = $(libdir)/krb5/plugins/pwqual
 
 # Rules for building the password strength plugin.
 module_LTLIBRARIES = plugin/strength.la
-plugin_strength_la_SOURCES = plugin/cdb.c plugin/config.c plugin/cracklib.c \
-       plugin/error.c plugin/general.c plugin/heimdal.c plugin/internal.h  \
-       plugin/mit.c plugin/principal.c
+plugin_strength_la_SOURCES = plugin/cdb.c plugin/classes.c plugin/config.c \
+       plugin/cracklib.c plugin/error.c plugin/general.c plugin/heimdal.c \
+       plugin/internal.h plugin/mit.c plugin/principal.c plugin/vector.c
 
 plugin_strength_la_LDFLAGS = -module -avoid-version
 @EMBEDDED_CRACKLIB_FALSE@plugin_strength_la_LIBADD = $(CRACKLIB_LIBS) \
@@ -578,9 +592,10 @@ plugin_strength_la_LDFLAGS = -module -avoid-version
 @EMBEDDED_CRACKLIB_TRUE@       portable/libportable.la $(KRB5_LIBS) \
 @EMBEDDED_CRACKLIB_TRUE@       $(CDB_LIBS)
 tools_heimdal_strength_CFLAGS = $(AM_CFLAGS)
-tools_heimdal_strength_SOURCES = plugin/cdb.c plugin/config.c              \
-       plugin/cracklib.c plugin/error.c plugin/general.c plugin/internal.h \
-       plugin/principal.c tools/heimdal-strength.c
+tools_heimdal_strength_SOURCES = plugin/cdb.c plugin/classes.c           \
+       plugin/config.c plugin/cracklib.c plugin/error.c plugin/general.c \
+       plugin/internal.h plugin/principal.c plugin/vector.c              \
+       tools/heimdal-strength.c
 
 @EMBEDDED_CRACKLIB_FALSE@tools_heimdal_strength_LDADD =  \
 @EMBEDDED_CRACKLIB_FALSE@      $(CRACKLIB_LIBS) util/libutil.a \
@@ -656,6 +671,10 @@ tests_portable_snprintf_t_SOURCES = tests/portable/snprintf-t.c \
        tests/portable/snprintf.c
 
 tests_portable_snprintf_t_LDADD = tests/tap/libtap.a portable/libportable.la
+tests_portable_strndup_t_SOURCES = tests/portable/strndup-t.c \
+       tests/portable/strndup.c
+
+tests_portable_strndup_t_LDADD = tests/tap/libtap.a portable/libportable.la
 tests_util_messages_t_LDADD = tests/tap/libtap.a util/libutil.a \
        portable/libportable.la
 
@@ -829,6 +848,8 @@ plugin/$(DEPDIR)/$(am__dirstamp):
        @$(MKDIR_P) plugin/$(DEPDIR)
        @: > plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/cdb.lo: plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
+plugin/classes.lo: plugin/$(am__dirstamp) \
+       plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/config.lo: plugin/$(am__dirstamp) \
        plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/cracklib.lo: plugin/$(am__dirstamp) \
@@ -842,6 +863,8 @@ plugin/heimdal.lo: plugin/$(am__dirstamp) \
 plugin/mit.lo: plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/principal.lo: plugin/$(am__dirstamp) \
        plugin/$(DEPDIR)/$(am__dirstamp)
+plugin/vector.lo: plugin/$(am__dirstamp) \
+       plugin/$(DEPDIR)/$(am__dirstamp)
 
 plugin/strength.la: $(plugin_strength_la_OBJECTS) $(plugin_strength_la_DEPENDENCIES) $(EXTRA_plugin_strength_la_DEPENDENCIES) plugin/$(am__dirstamp)
        $(AM_V_CCLD)$(plugin_strength_la_LINK) -rpath $(moduledir) $(plugin_strength_la_OBJECTS) $(plugin_strength_la_LIBADD) $(LIBS)
@@ -962,6 +985,14 @@ tests/portable/snprintf.$(OBJEXT): tests/portable/$(am__dirstamp) \
 tests/portable/snprintf-t$(EXEEXT): $(tests_portable_snprintf_t_OBJECTS) $(tests_portable_snprintf_t_DEPENDENCIES) $(EXTRA_tests_portable_snprintf_t_DEPENDENCIES) tests/portable/$(am__dirstamp)
        @rm -f tests/portable/snprintf-t$(EXEEXT)
        $(AM_V_CCLD)$(LINK) $(tests_portable_snprintf_t_OBJECTS) $(tests_portable_snprintf_t_LDADD) $(LIBS)
+tests/portable/strndup-t.$(OBJEXT): tests/portable/$(am__dirstamp) \
+       tests/portable/$(DEPDIR)/$(am__dirstamp)
+tests/portable/strndup.$(OBJEXT): tests/portable/$(am__dirstamp) \
+       tests/portable/$(DEPDIR)/$(am__dirstamp)
+
+tests/portable/strndup-t$(EXEEXT): $(tests_portable_strndup_t_OBJECTS) $(tests_portable_strndup_t_DEPENDENCIES) $(EXTRA_tests_portable_strndup_t_DEPENDENCIES) tests/portable/$(am__dirstamp)
+       @rm -f tests/portable/strndup-t$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(tests_portable_strndup_t_OBJECTS) $(tests_portable_strndup_t_LDADD) $(LIBS)
 tests/$(am__dirstamp):
        @$(MKDIR_P) tests
        @: > tests/$(am__dirstamp)
@@ -1000,6 +1031,8 @@ tests/util/xmalloc$(EXEEXT): $(tests_util_xmalloc_OBJECTS) $(tests_util_xmalloc_
        $(AM_V_CCLD)$(LINK) $(tests_util_xmalloc_OBJECTS) $(tests_util_xmalloc_LDADD) $(LIBS)
 plugin/tools_heimdal_strength-cdb.$(OBJEXT): plugin/$(am__dirstamp) \
        plugin/$(DEPDIR)/$(am__dirstamp)
+plugin/tools_heimdal_strength-classes.$(OBJEXT):  \
+       plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/tools_heimdal_strength-config.$(OBJEXT):  \
        plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/tools_heimdal_strength-cracklib.$(OBJEXT):  \
@@ -1010,6 +1043,8 @@ plugin/tools_heimdal_strength-general.$(OBJEXT):  \
        plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
 plugin/tools_heimdal_strength-principal.$(OBJEXT):  \
        plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
+plugin/tools_heimdal_strength-vector.$(OBJEXT):  \
+       plugin/$(am__dirstamp) plugin/$(DEPDIR)/$(am__dirstamp)
 tools/$(am__dirstamp):
        @$(MKDIR_P) tools
        @: > tools/$(am__dirstamp)
@@ -1083,6 +1118,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@cracklib/$(DEPDIR)/cracklib_libcracklib_la-stringlib.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@cracklib/$(DEPDIR)/packer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/cdb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/classes.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/cracklib.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/error.Plo@am__quote@
@@ -1091,15 +1127,19 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/mit.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/principal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-cdb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-classes.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-config.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-cracklib.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-error.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-general.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-principal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/tools_heimdal_strength-vector.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@plugin/$(DEPDIR)/vector.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@portable/$(DEPDIR)/asprintf.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@portable/$(DEPDIR)/dummy.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@portable/$(DEPDIR)/krb5-extra.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@portable/$(DEPDIR)/snprintf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@portable/$(DEPDIR)/strndup.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_runtests-runtests.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/plugin/$(DEPDIR)/tests_plugin_heimdal_t-heimdal-t.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/plugin/$(DEPDIR)/tests_plugin_mit_t-mit-t.Po@am__quote@
@@ -1107,6 +1147,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@tests/portable/$(DEPDIR)/asprintf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/portable/$(DEPDIR)/snprintf-t.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/portable/$(DEPDIR)/snprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/portable/$(DEPDIR)/strndup-t.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/portable/$(DEPDIR)/strndup.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/tap/$(DEPDIR)/tests_tap_libtap_a-basic.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/tap/$(DEPDIR)/tests_tap_libtap_a-kerberos.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/tap/$(DEPDIR)/tests_tap_libtap_a-process.Po@am__quote@
@@ -1283,6 +1325,20 @@ plugin/tools_heimdal_strength-cdb.obj: plugin/cdb.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-cdb.obj `if test -f 'plugin/cdb.c'; then $(CYGPATH_W) 'plugin/cdb.c'; else $(CYGPATH_W) '$(srcdir)/plugin/cdb.c'; fi`
 
+plugin/tools_heimdal_strength-classes.o: plugin/classes.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT plugin/tools_heimdal_strength-classes.o -MD -MP -MF plugin/$(DEPDIR)/tools_heimdal_strength-classes.Tpo -c -o plugin/tools_heimdal_strength-classes.o `test -f 'plugin/classes.c' || echo '$(srcdir)/'`plugin/classes.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) plugin/$(DEPDIR)/tools_heimdal_strength-classes.Tpo plugin/$(DEPDIR)/tools_heimdal_strength-classes.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin/classes.c' object='plugin/tools_heimdal_strength-classes.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-classes.o `test -f 'plugin/classes.c' || echo '$(srcdir)/'`plugin/classes.c
+
+plugin/tools_heimdal_strength-classes.obj: plugin/classes.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT plugin/tools_heimdal_strength-classes.obj -MD -MP -MF plugin/$(DEPDIR)/tools_heimdal_strength-classes.Tpo -c -o plugin/tools_heimdal_strength-classes.obj `if test -f 'plugin/classes.c'; then $(CYGPATH_W) 'plugin/classes.c'; else $(CYGPATH_W) '$(srcdir)/plugin/classes.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) plugin/$(DEPDIR)/tools_heimdal_strength-classes.Tpo plugin/$(DEPDIR)/tools_heimdal_strength-classes.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin/classes.c' object='plugin/tools_heimdal_strength-classes.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-classes.obj `if test -f 'plugin/classes.c'; then $(CYGPATH_W) 'plugin/classes.c'; else $(CYGPATH_W) '$(srcdir)/plugin/classes.c'; fi`
+
 plugin/tools_heimdal_strength-config.o: plugin/config.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT plugin/tools_heimdal_strength-config.o -MD -MP -MF plugin/$(DEPDIR)/tools_heimdal_strength-config.Tpo -c -o plugin/tools_heimdal_strength-config.o `test -f 'plugin/config.c' || echo '$(srcdir)/'`plugin/config.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) plugin/$(DEPDIR)/tools_heimdal_strength-config.Tpo plugin/$(DEPDIR)/tools_heimdal_strength-config.Po
@@ -1353,6 +1409,20 @@ plugin/tools_heimdal_strength-principal.obj: plugin/principal.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-principal.obj `if test -f 'plugin/principal.c'; then $(CYGPATH_W) 'plugin/principal.c'; else $(CYGPATH_W) '$(srcdir)/plugin/principal.c'; fi`
 
+plugin/tools_heimdal_strength-vector.o: plugin/vector.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT plugin/tools_heimdal_strength-vector.o -MD -MP -MF plugin/$(DEPDIR)/tools_heimdal_strength-vector.Tpo -c -o plugin/tools_heimdal_strength-vector.o `test -f 'plugin/vector.c' || echo '$(srcdir)/'`plugin/vector.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) plugin/$(DEPDIR)/tools_heimdal_strength-vector.Tpo plugin/$(DEPDIR)/tools_heimdal_strength-vector.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin/vector.c' object='plugin/tools_heimdal_strength-vector.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-vector.o `test -f 'plugin/vector.c' || echo '$(srcdir)/'`plugin/vector.c
+
+plugin/tools_heimdal_strength-vector.obj: plugin/vector.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT plugin/tools_heimdal_strength-vector.obj -MD -MP -MF plugin/$(DEPDIR)/tools_heimdal_strength-vector.Tpo -c -o plugin/tools_heimdal_strength-vector.obj `if test -f 'plugin/vector.c'; then $(CYGPATH_W) 'plugin/vector.c'; else $(CYGPATH_W) '$(srcdir)/plugin/vector.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) plugin/$(DEPDIR)/tools_heimdal_strength-vector.Tpo plugin/$(DEPDIR)/tools_heimdal_strength-vector.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin/vector.c' object='plugin/tools_heimdal_strength-vector.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -c -o plugin/tools_heimdal_strength-vector.obj `if test -f 'plugin/vector.c'; then $(CYGPATH_W) 'plugin/vector.c'; else $(CYGPATH_W) '$(srcdir)/plugin/vector.c'; fi`
+
 tools/tools_heimdal_strength-heimdal-strength.o: tools/heimdal-strength.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tools_heimdal_strength_CFLAGS) $(CFLAGS) -MT tools/tools_heimdal_strength-heimdal-strength.o -MD -MP -MF tools/$(DEPDIR)/tools_heimdal_strength-heimdal-strength.Tpo -c -o tools/tools_heimdal_strength-heimdal-strength.o `test -f 'tools/heimdal-strength.c' || echo '$(srcdir)/'`tools/heimdal-strength.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) tools/$(DEPDIR)/tools_heimdal_strength-heimdal-strength.Tpo tools/$(DEPDIR)/tools_heimdal_strength-heimdal-strength.Po
@@ -1840,6 +1910,21 @@ warnings:
 check-local: $(check_PROGRAMS) tests/data/dictionary.pwd
        cd tests && ./runtests -l $(abs_top_srcdir)/tests/TESTS
 
+# Used by maintainers to run the main test suite under valgrind.  Suppress
+# the xmalloc and pod-spelling tests because the former won't work properly
+# under valgrind (due to increased memory usage) and the latter is pointless
+# to run under valgrind.  Don't try to trace the test for cdbmake-wordlist,
+# since it's pure Perl.
+check-valgrind: $(check_PROGRAMS) tests/data/dictionary.pwd
+       rm -rf $(abs_top_builddir)/tmp-valgrind
+       mkdir $(abs_top_builddir)/tmp-valgrind
+       env RRA_MAINTAINER_TESTS= valgrind --leak-check=full    \
+           --show-reachable=yes --trace-children=yes           \
+           --log-file=$(abs_top_builddir)/tmp-valgrind/log.%p  \
+           --suppressions=tests/data/valgrind.supp             \
+           --trace-children-skip="/bin/sh,*/cat,*/diff,*/expr,*/grep,*/mkdir,*/rm,*/rmdir,*/sed,*/sleep,*/true,*/wc,*/docs/*-t,*/perl/*-t,*/data/make-krb5-conf,*/tools/cdbmake-wordlist-t" \
+           tests/runtests -l '$(abs_top_srcdir)/tests/TESTS'
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/NEWS b/NEWS
index d313c39f4f4c9c7e08fdbae6f824ab9dd113293a..4c3b208100d6241738d31232c161ad76c2a5c6b3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,31 @@
                     User-Visible krb5-strength Changes
 
+krb5-strength 2.2 (2013-12-16)
+
+    More complex character class requirements can be specified with the
+    configuration option require_classes.  This option lists the character
+    classes the password must contain.  These restrictions may be
+    qualified with password length ranges, allowing the requirements to
+    change with the length of the password.  See README for more details
+    and the option syntax.
+
+    cdbmake-wordlist now supports filtering out words based on maximum
+    length (-L) and arbitrary user-provided regular expressions (-x).  It
+    also supports running in filter mode to produce a new wordlist instead
+    of a CDB file (-o).
+
+    Close a file descriptor and memory leak in the included version of
+    CrackLib.  This problem was already fixed in CrackLib 2.9.0.
+
+    Update to rra-c-util 4.12:
+
+    * Properly check the return status of snprintf and friends.
+
+    Update to C TAP Harness 2.3:
+
+    * Suppress lazy plans and test summaries if the test failed with bail.
+    * Add warn_unused_result gcc attributes to relevant functions.
+
 krb5-strength 2.1 (2013-10-10)
 
     Fix the package build when CDB support is disabled or TinyCDB was not
diff --git a/README b/README
index 43a8f12e00d7ff3dcc2527caf0f2bdbbd985186f..a5cbc361591b7b5a432f8c6d5f05e9dc6ea68324 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-                            krb5-strength 2.1
+                            krb5-strength 2.2
                (Kerberos password strength checking plugin)
 
-              Maintained by Russ Allbery <rra@stanford.edu>
+               Maintained by Russ Allbery <eagle@eyrie.org>
 
   Copyright 2006, 2007, 2009, 2010, 2012, 2013 The Board of Trustees of
   the Leland Stanford Junior University.  Portions copyright 1993 Alec
@@ -18,7 +18,7 @@ BLURB
   tested with CrackLib, checked against a CDB database of known weak
   passwords, checked for length, checked for non-printable or non-ASCII
   characters that may be difficult to enter reproducibly, required to
-  contain a non-alphabetic character, or any combination of these tests.
+  contain particular character classes, or any combination of these tests.
   It supports both Heimdal and MIT Kerberos (1.9 or later).
 
 DESCRIPTION
@@ -27,15 +27,23 @@ DESCRIPTION
   checks and comes with an example that checks passwords against CrackLib.
   However, in testing at Stanford, we found that CrackLib with its default
   transform rules does not catch passwords that can be guessed using the
-  same dictionary with other tools, such as Jack the Ripper.
+  same dictionary with other tools, such as Jack the Ripper.  We then
+  discovered other issues with CrackLib with longer passwords, such as
+  some bad assumptions about how certain measures of complexity will
+  scale, and wanted to impose other limitations that it didn't support.
 
   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.
+  the Ripper using the same rule sets.  It also supports doing simpler
+  dictionary checks against a CDB database, which is fast with very large
+  dictionaries, and imposing other programmatic checks on passwords such
+  as character class requirements.
+
+  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,
@@ -79,9 +87,7 @@ REQUIREMENTS
 
   You can also optionally build against the TinyCDB library, which
   provides support for simpler and faster password checking against a CDB
-  dictionary file.  Building a CDB dictionary with cdbmake-wordlist
-  (included) requires Perl 5.006 or later and the CDB utility that comes
-  with TinyCDB.
+  dictionary file.
 
   For this module to be effective for either Heimdal or MIT Kerberos, you
   will also need to construct a dictionary.  The mkdict and packer
@@ -89,9 +95,11 @@ REQUIREMENTS
   in this toolkit but not installed by default.  You can run them out of
   the cracklib directory after building.  You can also use the utilities
   that come with the stock CrackLib package (often already packaged in a
-  Linux distribution); the database format is compatible.  For building a
-  CDB dictionary, use the provided cdbmake-wordlist program.  The CDB
-  utility must be on your PATH.
+  Linux distribution); the database format is compatible.
+
+  For building a CDB dictionary, use the provided cdbmake-wordlist
+  program.  The CDB utility must be on your PATH.  cdbmake-wordlist
+  requires Perl 5.006 or later.
 
   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
@@ -103,9 +111,9 @@ REQUIREMENTS
   following additional Perl modules will be used by the test suite if
   present:
 
-      File::Slurp
       IPC::Run
       JSON
+      Perl6::Slurp
       Test::MinimumVersion
       Test::Perl::Critic
       Test::Pod
@@ -123,7 +131,9 @@ REQUIREMENTS
   and need to regenerate Makefile.in, you will need Automake 1.11 or
   later.  For bootstrap or if you change configure.ac or any of the m4
   files it includes and need to regenerate configure or config.h.in, you
-  will need Autoconf 2.64 or later.
+  will need Autoconf 2.64 or later.  You will also need Perl 5.010 or
+  later and the JSON, Perl6::Slurp, and Readonly modules (from CPAN) to
+  bootstrap the test suite data from a Git checkout.
 
 COMPILING AND INSTALLING
 
@@ -228,7 +238,11 @@ CONFIGURATION
   dictionary.  The provided path should be the full path to the dictionary
   files, omitting the trailing *.hwm, *.pwd, and *.pwi extensions for the
   CrackLib dictionary.  You can use either or both settings.  If you use
-  both, CrackLib will be checked first, and then CDB.
+  both, CrackLib will be checked first, and then CDB.  When checking a CDB
+  database, the password, the password with the first character removed,
+  the last character removed, the first and last characters removed, the
+  first two characters removed, and the last two characters removed will
+  all be checked against the dictionary.
 
   Then, for the external password checking program, add a new section (or
   modify the existing [password_quality] section) to look like the
@@ -286,7 +300,11 @@ CONFIGURATION
   dictionary.  The provided path should be the full path to the dictionary
   files, omitting the trailing *.hwm, *.pwd, and *.pwi extensions for the
   CrackLib dictionary.  You can use either or both settings.  If you use
-  both, CrackLib will be checked first, and then CDB.
+  both, CrackLib will be checked first, and then CDB.  When checking a CDB
+  database, the password, the password with the first character removed,
+  the last character removed, the first and last characters removed, the
+  first two characters removed, and the last two characters removed will
+  all be checked against the 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
@@ -336,6 +354,46 @@ CONFIGURATION
       interoperability problems with computers with different default
       character sets or Unicode normalization forms.
 
+  require_classes
+
+      This option allows specification of more complex character class
+      requirements.  The value of this parameter should be one or more
+      whitespace-separated rule.  Each rule has the syntax:
+
+          [<min>-<max>:]<class>[,<class>...]
+
+      where <class> is one of "upper", "lower", "digit", or "symbol"
+      (without the quote marks).  The symbol class includes all characters
+      other than alphanumeric characters, including space.  The listed
+      classes must appear in the password.  Separate multiple required
+      classes with a comma (and no space).
+
+      The character class checks will be done in whatever locale the
+      plugin or password check program is run in, which will normally be
+      the POSIX C locale but may be different depending on local
+      configuration.
+
+      A simple example:
+
+          require_classes = upper,lower,digit
+
+      This requires all passwords contain at least one uppercase letter,
+      at least one lowercase letter, and at least one digit.
+
+      If present, <min> and <max> specify the minimum password length and
+      maximum password length to which this rule applies.  This allows one
+      to specify character class requirements that change with password
+      length.  So, for example:
+
+          require_classes = 8-19:upper,lower 8-15:digit 8-11:symbol
+
+      requires all passwords from 8 to 11 characters long contain all four
+      character classes, passwords from 12 to 15 characters long contain
+      upper and lower case and a digit, and passwords from 16 to 19
+      characters long contain both upper and lower case.  Passowrds longer
+      than 20 characters have no character class restrictions.  (This
+      example is probably used in conjunction with minimum_length = 8.)
+
   require_non_letter
 
       If set to a true boolean value, the password must contain at least
@@ -359,7 +417,7 @@ SUPPORT
   will always have the current version of this package, the current
   documentation, and pointers to any additional resources.
 
-  I welcome bug reports and patches for this package at rra@stanford.edu.
+  I welcome bug reports and patches for this package at eagle@eyrie.org.
   However, please be aware that I tend to be extremely busy and work
   projects often take priority.  I'll save your mail and get to it as soon
   as I can, but it may take me a couple of months.
diff --git a/TODO b/TODO
index 0d3b030682a5e81a0f76911c4553fc8a215df8f5..19e6b97cdaef19081d344e514b6193cea06b6c69 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,3 +14,6 @@
 
  * Use the realm of the principal changing its password to determine the
    krb5.conf configuration rather than always using the default realm.
+
+ * Refactor the tests for configuration errors in the heimdal-strength
+   test suite into JSON.
index 923628700fd985fd2b5ced133e38ef74a076e420..b2074bed0b10a90c0b58ed6e25fc405cc094bfd7 100644 (file)
@@ -49,7 +49,7 @@
 #undef HAVE_KADM5_KADM5_PWCHECK_H
 
 /* Define to enable Kerberos features. */
-#undef HAVE_KERBEROS
+#undef HAVE_KRB5
 
 /* Define to 1 if you have the `krb5_free_default_realm' function. */
 #undef HAVE_KRB5_FREE_DEFAULT_REALM
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
 /* Define to 1 if you have the <syslog.h> header file. */
 #undef HAVE_SYSLOG_H
 
index 919f4aba384f644750ecadc75d6418a8e6175caf..27606583983e4c275d315d5950b03da6527ffa5a 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for krb5-strength 2.1.
+# Generated by GNU Autoconf 2.69 for krb5-strength 2.2.
 #
-# Report bugs to <rra@stanford.edu>.
+# Report bugs to <eagle@eyrie.org>.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -274,7 +274,7 @@ fi
     $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
     $as_echo "$0: be upgraded to zsh 4.3.4 or later."
   else
-    $as_echo "$0: Please tell bug-autoconf@gnu.org and rra@stanford.edu
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and eagle@eyrie.org
 $0: about your system, including any error possibly output
 $0: before this message. Then install a modern shell, or
 $0: manually run the script under such a shell if you do
@@ -590,9 +590,9 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='krb5-strength'
 PACKAGE_TARNAME='krb5-strength'
-PACKAGE_VERSION='2.1'
-PACKAGE_STRING='krb5-strength 2.1'
-PACKAGE_BUGREPORT='rra@stanford.edu'
+PACKAGE_VERSION='2.2'
+PACKAGE_STRING='krb5-strength 2.2'
+PACKAGE_BUGREPORT='eagle@eyrie.org'
 PACKAGE_URL=''
 
 ac_config_libobj_dir=portable
@@ -1341,7 +1341,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures krb5-strength 2.1 to adapt to many kinds of systems.
+\`configure' configures krb5-strength 2.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1411,7 +1411,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of krb5-strength 2.1:";;
+     short | recursive ) echo "Configuration of krb5-strength 2.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1472,7 +1472,7 @@ Some influential environment variables:
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
-Report bugs to <rra@stanford.edu>.
+Report bugs to <eagle@eyrie.org>.
 _ACEOF
 ac_status=$?
 fi
@@ -1535,7 +1535,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-krb5-strength configure 2.1
+krb5-strength configure 2.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1694,9 +1694,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
 $as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( $as_echo "## ------------------------------- ##
-## Report this to rra@stanford.edu ##
-## ------------------------------- ##"
+( $as_echo "## ------------------------------ ##
+## Report this to eagle@eyrie.org ##
+## ------------------------------ ##"
      ) | sed "s/^/$as_me: WARNING:     /" >&2
     ;;
 esac
@@ -2241,7 +2241,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by krb5-strength $as_me 2.1, which was
+It was created by krb5-strength $as_me 2.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3106,7 +3106,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='krb5-strength'
- VERSION='2.1'
+ VERSION='2.2'
 
 
 cat >>confdefs.h <<_ACEOF
 $as_echo "$ac_cv_lib_cdb_cdb_init" >&6; }
 if test "x$ac_cv_lib_cdb_cdb_init" = xyes; then :
   CDB_LIBS=-lcdb
-
-$as_echo "#define HAVE_CDB 1" >>confdefs.h
-
-     rra_use_CDB=true
 else
   if test x"true" = xtrue; then :
   as_fn_error $? "cannot find usable TinyCDB library" "$LINENO" 5
 $as_echo "$ac_cv_lib_cdb_cdb_init" >&6; }
 if test "x$ac_cv_lib_cdb_cdb_init" = xyes; then :
   CDB_LIBS=-lcdb
-
-$as_echo "#define HAVE_CDB 1" >>confdefs.h
-
-     rra_use_CDB=true
 else
   if test x"false" = xtrue; then :
   as_fn_error $? "cannot find usable TinyCDB library" "$LINENO" 5
@@ -12570,6 +12562,12 @@ done
  LDFLAGS="$rra_CDB_save_LDFLAGS"
  LIBS="$rra_CDB_save_LIBS"
 fi
+fi
+ if test x"$CDB_LIBS" != x; then :
+  rra_use_CDB=true
+
+$as_echo "#define HAVE_CDB 1" >>confdefs.h
+
 fi
 rra_system_cracklib=
  rra_cracklib_root=
@@ -12746,7 +12744,7 @@ fi
 rra_krb5_root=
  rra_krb5_libdir=
  rra_krb5_includedir=
- rra_use_kerberos=true
+ rra_use_KRB5=true
 
 
 
@@ -13046,7 +13044,11 @@ $as_echo "$ac_cv_lib_com_err_com_err" >&6; }
 if test "x$ac_cv_lib_com_err_com_err" = xyes; then :
   KRB5_LIBS="$KRB5_LIBS -lcom_err"
 else
+  if test x"true" = xtrue; then :
   as_fn_error $? "cannot find usable com_err library" "$LINENO" 5
+else
+  KRB5_LIBS=""
+fi
 fi
 
                   for ac_header in et/com_err.h
@@ -16184,7 +16186,7 @@ done
 fi
 fi
  rra_krb5_uses_com_err=false
- case $LIBS in #(
+ case $KRB5_LIBS in #(
   *-lcom_err*) :
     rra_krb5_uses_com_err=true ;; #(
   *) :
@@ -16199,7 +16201,7 @@ else
 fi
 
 
-$as_echo "#define HAVE_KERBEROS 1" >>confdefs.h
+$as_echo "#define HAVE_KRB5 1" >>confdefs.h
 
 rra_krb5_save_CPPFLAGS="$CPPFLAGS"
  rra_krb5_save_LDFLAGS="$LDFLAGS"
@@ -16265,9 +16267,9 @@ fi
 
 for ac_func in krb5_free_default_realm \
     krb5_free_string \
-    krb5_principal_get_realm \
     krb5_get_init_creds_opt_alloc \
     krb5_get_init_creds_opt_set_default_flags \
+    krb5_principal_get_realm \
     krb5_xfree
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -16860,6 +16862,19 @@ esac
 
 fi
 
+ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup"
+if test "x$ac_cv_func_strndup" = xyes; then :
+  $as_echo "#define HAVE_STRNDUP 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" strndup.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS strndup.$ac_objext"
+ ;;
+esac
+
+fi
+
 
 
 ac_config_files="$ac_config_files Makefile"
@@ -17408,7 +17423,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by krb5-strength $as_me 2.1, which was
+This file was extended by krb5-strength $as_me 2.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17468,13 +17483,13 @@ $config_headers
 Configuration commands:
 $config_commands
 
-Report bugs to <rra@stanford.edu>."
+Report bugs to <eagle@eyrie.org>."
 
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-krb5-strength config.status 2.1
+krb5-strength config.status 2.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index ee929d3fa022fd1baa5865256174b1860d9a432b..519cfe3d7eb0346f6847a19daf651f915e0fe7dd 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2006, 2007, 2009, 2010, 2012, 2013
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
@@ -8,7 +8,7 @@ dnl See LICENSE for licensing terms.
 
 dnl Basic Autoconf configuration.
 AC_PREREQ([2.64])
-AC_INIT([krb5-strength], [2.1], [rra@stanford.edu])
+AC_INIT([krb5-strength], [2.2], [eagle@eyrie.org])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_LIBOBJ_DIR([portable])
 AC_CONFIG_MACRO_DIR([m4])
@@ -24,7 +24,7 @@ AM_PROG_CC_C_O
 AC_PROG_INSTALL
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 AM_DISABLE_STATIC
-AC_PROG_LIBTOOL
+LT_INIT
 
 dnl External libraries.
 RRA_LIB_CDB_OPTIONAL
@@ -41,9 +41,9 @@ AC_CHECK_HEADERS([krb5/pwqual_plugin.h], [], [], [RRA_INCLUDES_KRB5])
 AC_CHECK_TYPES([krb5_realm], [], [], [RRA_INCLUDES_KRB5])
 AC_CHECK_FUNCS([krb5_free_default_realm \
     krb5_free_string \
-    krb5_principal_get_realm \
     krb5_get_init_creds_opt_alloc \
     krb5_get_init_creds_opt_set_default_flags \
+    krb5_principal_get_realm \
     krb5_xfree])
 AC_CHECK_FUNCS([krb5_get_init_creds_opt_free],
     [RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS])
@@ -71,7 +71,7 @@ AC_CHECK_TYPES([ssize_t], [], [],
     [#include <sys/types.h>])
 RRA_FUNC_SNPRINTF
 AC_CHECK_FUNCS([setrlimit])
-AC_REPLACE_FUNCS([asprintf])
+AC_REPLACE_FUNCS([asprintf strndup])
 
 dnl Write out the results.
 AC_CONFIG_FILES([Makefile])
index 35c72ae30fc52c66220a252cb36415c812917403..80c2196ae76b8e9ec630563a1e32c75772f9856c 100644 (file)
@@ -20,6 +20,7 @@ following modifications have been made:
  * Remove last block optimization in GetPW and start fresh each time.
  * Close the dictionary after each password lookup.
  * Set hidden visibility on all CrackLib symbols.
+ * Close the wfp file handle on PWClose if it's open.
 
 Below is the original changelog for CrackLib:
 
index e51a613b2926b6d7c23074cdc8939786b3b5e118..2d9310ca75d5b40a07d4bc7863dda44d6bd1e9f0 100644 (file)
@@ -9,23 +9,23 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2007-03-22  Russ Allbery <rra@stanford.edu>
+ * 2007-03-22  Russ Allbery <eagle@eyrie.org>
  *   - Add four-, five-, and six-character prefix and suffix rules.
  *   - Longer passwords must contain more different characters, up to 8.
  *   - Disable GECOS checking (useless for a server).
  *   - Replace exit(-1) with return when dictionary doesn't exist.
  *   - Additional system includes for other functions.
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Add ANSI C protototypes for all functions.
  *   - Tweaks for const cleanliness.
  *   - Add parentheses around assignment used for its truth value.
  *   - Change a variable to unsigned int to avoid gcc warnings.
  *   - Remove the unused FascistGecos function.
- * 2012-05-11  Russ Allbery <rra@stanford.edu>
+ * 2012-05-11  Russ Allbery <eagle@eyrie.org>
  *   - Change MINLENGTH to 8.
  *   - Use a separate buffer to hold the reversed password.
  *   - Also check whether a password is a duplicated dictionary word.
- * 2013-09-24  Russ Allbery <rra@stanford.edu>
+ * 2013-09-24  Russ Allbery <eagle@eyrie.org>
  *   - Replaced MAXSTEP with allowing one increment per four characters.
  *   - Changed error for very short passwords to match current CrackLib.
  *   - Close the dictionary after each password lookup.
index 11ee9376ddf8b468ee2395c2c8c1949e0b976984..e601b385c2a8ca2839c686eacac362837b7dae02 100644 (file)
@@ -9,9 +9,9 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Add ANSI C protototypes for all functions.
- * 2010-03-14  Russ Allbery <rra@stanford.edu>
+ * 2010-03-14  Russ Allbery <eagle@eyrie.org>
  *   - Use unsigned long instead of int32 to avoid printf warnings.
  */
 
index f27784717c2a620084ff71fb10aa0b1a7b73753e..b0f6703fdb875fba90777123c49a3ef39a1299e4 100644 (file)
@@ -9,13 +9,13 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2007-03-23  Russ Allbery <rra@stanford.edu>
+ * 2007-03-23  Russ Allbery <eagle@eyrie.org>
  *   - Add ANSI C prototypes and prototype additional functions.
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Prototype changes for const cleanliness.
- * 2010-03-14  Russ Allbery <rra@stanford.edu>
+ * 2010-03-14  Russ Allbery <eagle@eyrie.org>
  *   - Fix int8, int16, and int32 definitions.
- * 2013-10-01  Russ Allbery <rra@stanford.edu>
+ * 2013-10-01  Russ Allbery <eagle@eyrie.org>
  *   - Set hidden visibility on all symbols by default.
  */
 
index 70112f9a627b0ca7bcd79a867b7658e884a49d1b..74e75fd3f0a944780062e7ba57351c076349a587 100644 (file)
@@ -9,21 +9,23 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2007-03-23  Russ Allbery <rra@stanford.edu>
+ * 2007-03-23  Russ Allbery <eagle@eyrie.org>
  *   - Apply Debian patch to improve the search logic.
  *   - Don't crash if the dictionary is corrupt.
  *   - Additional system includes for other functions.
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Add ANSI C protototypes for all functions.
  *   - Tweaks for const cleanliness.
  *   - Add parentheses around assignment used for its truth value.
  *   - Make internal functions static.
  *   - Remove unused variables.
- * 2009-11-18  Russ Allbery <rra@stanford.edu>
+ * 2009-11-18  Russ Allbery <eagle@eyrie.org>
  *   - Fixed the data format output by packer to properly pad the end.
- * 2013-09-24  Russ Allbery <rra@stanford.edu>
+ * 2013-09-24  Russ Allbery <eagle@eyrie.org>
  *   - Add a missing ANSI C prototype.
  *   - Remove last block optimization in GetPW and start fresh each time.
+ * 2013-12-13  Russ Allbery <eagle@eyrie.org>
+ *   - Close the wfp file handle on PWClose if it's open.
  */
 
 #include <stdio.h>
@@ -97,6 +99,10 @@ PWOpen(const char *prefix, const char *mode)
            pdesc.header.pih_magic = 0;
            fclose(ifp);
            fclose(dfp);
+           if (wfp != NULL)
+           {
+               fclose(wfp);
+           }
            return ((PWDICT *) 0);
        }
 
@@ -107,6 +113,10 @@ PWOpen(const char *prefix, const char *mode)
            pdesc.header.pih_magic = 0;
            fclose(ifp);
            fclose(dfp);
+           if (wfp != NULL)
+           {
+               fclose(wfp);
+           }
            return ((PWDICT *) 0);
        }
 
@@ -117,6 +127,10 @@ PWOpen(const char *prefix, const char *mode)
            pdesc.header.pih_magic = 0;
            fclose(ifp);
            fclose(dfp);
+           if (wfp != NULL)
+           {
+               fclose(wfp);
+           }
            return ((PWDICT *) 0);
        }
 
@@ -177,6 +191,10 @@ PWClose(PWDICT *pwp)
 
     fclose(pwp->ifp);
     fclose(pwp->dfp);
+    if (pwp->wfp != NULL)
+    {
+       fclose(pwp->wfp);
+    }
 
     pwp->header.pih_magic = 0;
 
index b1829ed9fadaaec295c34cead4c28f30d12f97d6..c4ffc97db0422389cc989d8663677b62ae44e424 100644 (file)
@@ -9,13 +9,13 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2007-03-22  Russ Allbery <rra@stanford.edu>
+ * 2007-03-22  Russ Allbery <eagle@eyrie.org>
  *   - Cap deletion of leading or trailing characters at one more than half
  *     the length of the password string and no more than five characters.
  *     This goes with a change to fascist.c that adds rules to delete more
  *     leading and trailing characters for longer passwords.
  *   - Additional system includes for other functions.
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Simplify Debug() function for how it's actually called.
  *   - Add ANSI C protototypes for all functions.
  *   - Tweaks for const cleanliness.
index b4f135968f6818964a1e126440a52f3b2e771dc4..3a38164537dce1fe31e198c2cea465d219a7179e 100644 (file)
@@ -9,9 +9,9 @@
 /*
  * Modified as part of the krb5-strength project as follows:
  *
- * 2007-03-23  Russ Allbery <rra@stanford.edu>
+ * 2007-03-23  Russ Allbery <eagle@eyrie.org>
  *   - Additional system includes for other functions.
- * 2009-10-14  Russ Allbery <rra@stanford.edu>
+ * 2009-10-14  Russ Allbery <eagle@eyrie.org>
  *   - Add ANSI C protototypes for all functions.
  *   - Remove unused Clone function.
  */
index 69f31a02aa27639ff59b68512f20bd2a3df2fc2e..34b89a3e7a0e9a0e15edad6216b5a0224651dd7d 100644 (file)
@@ -1,10 +1,22 @@
-krb5-strength (2.1-1~sbp60+1) squeeze-backports; urgency=low
+krb5-strength (2.2-1~sbp60+1) squeeze-backports; urgency=low
 
   * Special Stanford-only local backport that builds the package against
     Heimdal instead of MIT Kerberos.  We only need the heimdal-strength
     program and the MIT API isn't supported until wheezy.
 
- -- Russ Allbery <rra@debian.org>  Tue, 05 Nov 2013 12:00:21 -0800
+ -- Russ Allbery <rra@debian.org>  Mon, 16 Dec 2013 15:56:00 -0800
+
+krb5-strength (2.2-1) unstable; urgency=low
+
+  * New upstream release.
+    - Support for more complex length-sensitive character class
+      restrictions using the new require_classes configuration setting.
+    - cdbmake-wordlist now supports filtering out words based on maximum
+      length and user-supplied regular expressions, and supports running
+      in filter mode to generate a new word list.
+  * Update to standards version 3.9.5 (no changes required).
+
+ -- Russ Allbery <rra@debian.org>  Mon, 16 Dec 2013 15:36:29 -0800
 
 krb5-strength (2.1-1) unstable; urgency=low
 
index f1aeb3ab0b9d196559110b1d73849657bd95ce2a..8fbdf13c30be05a9d5657f2ff82b8622730af970 100644 (file)
@@ -7,7 +7,7 @@ Build-Depends: debhelper (>= 9), cracklib-runtime, dh-autoreconf,
  libipc-run-perl, libjson-perl, libperl6-slurp-perl, libreadonly-perl,
  libtest-pod-perl, libtest-minimumversion-perl, libtest-strict-perl, perl,
  tinycdb
-Standards-Version: 3.9.4
+Standards-Version: 3.9.5
 Homepage: http://www.eyrie.org/~eagle/software/krb5-strength/
 Vcs-Git: git://git.eyrie.org/kerberos/krb5-strength.git -b debian
 Vcs-Browser: http://git.eyrie.org/?p=kerberos/krb5-strength.git
index 7a25d968e104d59c650968503e0737dccd36285b..7fd6710876621169e63a4ad996eedec2453e302a 100644 (file)
@@ -6,7 +6,7 @@ Copyright: 2006-2007, 2009-2013
 License: Expat
 
 Files: *
-Copyright: 2000-2002, 2004-2012 Russ Allbery <rra@stanford.edu>
+Copyright: 2000-2002, 2004-2013 Russ Allbery <eagle@eyrie.org>
   2001-2002, 2004-2013
     The Board of Trustees of the Leland Stanford Junior University
   2010 the Massachusetts Institute of Technology
@@ -95,7 +95,8 @@ License: FSF-unlimited, and GPL-2+ with Libtool exception or Expat
 
 Files: portable/asprintf.c portable/dummy.c portable/kadmin.h
  portable/krb5-extra.c portable/krb5.h portable/macros.h portable/stdbool.h
- portable/system.h tests/portable/asprintf-t.c util/macros.h
+ portable/strndup.c portable/system.h tests/portable/asprintf-t.c
+ tests/portable/strndup-t.c util/macros.h
 Copyright: no copyright notice, see License
 License: rra-public-domain
  The authors hereby relinquish any claim to any copyright that they may
@@ -108,7 +109,7 @@ License: rra-public-domain
 
 Files: portable/snprintf.c tests/portable/snprintf-t.c
 Copyright: 1995 Patrick Powell
-  2000-2006 Russ Allbery <rra@stanford.edu>
+  2000-2006 Russ Allbery <eagle@eyrie.org>
   2001 Hrvoje Niksic
   2009-2010 The Board of Trustees of the Leland Stanford Junior University
 License: Powell-snprintf
@@ -117,7 +118,7 @@ License: Powell-snprintf
  on all source code distributions
 
 Files: tests/HOWTO tools/heimdal-strength.1 tools/heimdal-strength.pod
-Copyright: 2010 Russ Allbery <rra@stanford.edu>
+Copyright: 2010 Russ Allbery <eagle@eyrie.org>
   2010, 2013 The Board of Trustees of the Leland Stanford Junior University
 License: all-permissive
  Copying and distribution of this file, with or without modification, are
index 4f9ac0598ae6f702a67e6a8fb4401922a22871ff..d19bd1533826d248d969a545ca8ea3566fbfa1ba 100644 (file)
@@ -17,7 +17,7 @@ dnl RRA_LIB_CRACKLIB_SWITCH.
 dnl
 dnl Depends on RRA_SET_LDFLAGS.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2010
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index d73085f9ca5f6d2872d38f99a692d69c1f391d6a..c69c4f337fdff2971a02ec5274d5245c239334a0 100644 (file)
@@ -10,7 +10,7 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2011, 2012
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index 964023a63fa0034551c2ee765e79455f03296f16..950524f4069f28c62c51ecaaae8e68966f93a7bb 100644 (file)
@@ -11,23 +11,27 @@ dnl KRB5_CPPFLAGS, KRB5_LDFLAGS, and KRB5_LIBS.  Also provides
 dnl RRA_LIB_KRB5_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the
 dnl Kerberos libraries, saving the current values first, and
 dnl RRA_LIB_KRB5_RESTORE to restore those settings to before the last
-dnl RRA_LIB_KRB5_SWITCH.  HAVE_KERBEROS will always be defined if RRA_LIB_KRB5
-dnl is used.
+dnl RRA_LIB_KRB5_SWITCH.  HAVE_KRB5 will always be defined if RRA_LIB_KRB5 is
+dnl used.
 dnl
 dnl If KRB5_CPPFLAGS, KRB5_LDFLAGS, or KRB5_LIBS are set before calling these
 dnl macros, their values will be added to whatever the macros discover.
 dnl
 dnl Provides the RRA_LIB_KRB5_OPTIONAL macro, which should be used if Kerberos
-dnl support is optional.  This macro will still always set the substitution
-dnl variables, but they'll be empty unless --with-krb5 is given.  Also,
-dnl HAVE_KERBEROS will be defined if --with-krb5 is given and
-dnl $rra_use_kerberos will be set to "true".
+dnl support is optional.  In this case, Kerberos libraries are mandatory if
+dnl --with-krb5 is given, and will not be probed for if --without-krb5 is
+dnl given.  Otherwise, they'll be probed for but will not be required.
+dnl Defines HAVE_KRB5 and sets rra_use_KRB5 to true if the libraries are
+dnl found.  The substitution variables will always be set, but they will be
+dnl empty unless Kerberos libraries are found and the user did not disable
+dnl Kerberos support.
 dnl
 dnl Sets the Automake conditional KRB5_USES_COM_ERR saying whether we use
 dnl com_err, since if we're also linking with AFS libraries, we may have to
 dnl change library ordering in that case.
 dnl
-dnl Depends on RRA_ENABLE_REDUCED_DEPENDS and RRA_SET_LDFLAGS.
+dnl Depends on RRA_KRB5_CONFIG, RRA_ENABLE_REDUCED_DEPENDS, and
+dnl RRA_SET_LDFLAGS.
 dnl
 dnl Also provides RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS, which checks
 dnl whether krb5_get_init_creds_opt_free takes one argument or two.  Defines
@@ -39,14 +43,17 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011
+dnl Written by Russ Allbery <eagle@eyrie.org>
+dnl Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
 dnl This file is free software; the authors give unlimited permission to copy
 dnl and/or distribute it, with or without modifications, as long as this
 dnl notice is preserved.
 
+dnl Ignore Automake conditionals if not using Automake.
+m4_define_default([AM_CONDITIONAL], [:])
+
 dnl Headers to include when probing for Kerberos library properties.
 AC_DEFUN([RRA_INCLUDES_KRB5], [[
 #if HAVE_KRB5_H
@@ -124,7 +131,9 @@ AC_DEFUN([_RRA_LIB_KRB5_REDUCED],
                      [RRA_INCLUDES_KRB5])],
                  [AC_CHECK_LIB([com_err], [com_err],
                      [KRB5_LIBS="$KRB5_LIBS -lcom_err"],
-                     [AC_MSG_ERROR([cannot find usable com_err library])])
+                     [AS_IF([test x"$1" = xtrue],
+                         [AC_MSG_ERROR([cannot find usable com_err library])],
+                         [KRB5_LIBS=""])])
                   AC_CHECK_HEADERS([et/com_err.h])])])])])
  RRA_LIB_KRB5_RESTORE])
 
@@ -242,15 +251,16 @@ AC_DEFUN([_RRA_LIB_KRB5_INTERNAL],
         [_RRA_LIB_KRB5_PATHS
          _RRA_LIB_KRB5_MANUAL([$1])])])
  rra_krb5_uses_com_err=false
- AS_CASE([$LIBS], [*-lcom_err*], [rra_krb5_uses_com_err=true])
- AM_CONDITIONAL([KRB5_USES_COM_ERR], [test x"$rra_krb5_uses_com_err" = xtrue])])
+ AS_CASE([$KRB5_LIBS], [*-lcom_err*], [rra_krb5_uses_com_err=true])
+ AM_CONDITIONAL([KRB5_USES_COM_ERR],
+    [test x"$rra_krb5_uses_com_err" = xtrue])])
 
 dnl The main macro for packages with mandatory Kerberos support.
 AC_DEFUN([RRA_LIB_KRB5],
 [rra_krb5_root=
  rra_krb5_libdir=
  rra_krb5_includedir=
- rra_use_kerberos=true
+ rra_use_KRB5=true
  AC_SUBST([KRB5_CPPFLAGS])
  AC_SUBST([KRB5_LDFLAGS])
  AC_SUBST([KRB5_LIBS])
@@ -271,14 +281,14 @@ AC_DEFUN([RRA_LIB_KRB5],
     [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
         [rra_krb5_libdir="$withval"])])
  _RRA_LIB_KRB5_INTERNAL([true])
- AC_DEFINE([HAVE_KERBEROS], 1, [Define to enable Kerberos features.])])
+ AC_DEFINE([HAVE_KRB5], 1, [Define to enable Kerberos features.])])
 
 dnl The main macro for packages with optional Kerberos support.
 AC_DEFUN([RRA_LIB_KRB5_OPTIONAL],
 [rra_krb5_root=
  rra_krb5_libdir=
  rra_krb5_includedir=
- rra_use_kerberos=
+ rra_use_KRB5=
  AC_SUBST([KRB5_CPPFLAGS])
  AC_SUBST([KRB5_LDFLAGS])
  AC_SUBST([KRB5_LIBS])
@@ -287,9 +297,9 @@ AC_DEFUN([RRA_LIB_KRB5_OPTIONAL],
     [AS_HELP_STRING([--with-krb5@<:@=DIR@:>@],
         [Location of Kerberos headers and libraries])],
     [AS_IF([test x"$withval" = xno],
-        [rra_use_kerberos=false],
+        [rra_use_KRB5=false],
         [AS_IF([test x"$withval" != xyes], [rra_krb5_root="$withval"])
-         rra_use_kerberos=true])])
+         rra_use_KRB5=true])])
  AC_ARG_WITH([krb5-include],
     [AS_HELP_STRING([--with-krb5-include=DIR],
         [Location of Kerberos headers])],
@@ -301,13 +311,14 @@ AC_DEFUN([RRA_LIB_KRB5_OPTIONAL],
     [AS_IF([test x"$withval" != xyes && test x"$withval" != xno],
         [rra_krb5_libdir="$withval"])])
 
- AS_IF([test x"$rra_use_kerberos" != xfalse],
-     [AS_IF([test x"$rra_use_kerberos" = xtrue],
+ AS_IF([test x"$rra_use_KRB5" != xfalse],
+     [AS_IF([test x"$rra_use_KRB5" = xtrue],
          [_RRA_LIB_KRB5_INTERNAL([true])],
          [_RRA_LIB_KRB5_INTERNAL([false])])],
      [AM_CONDITIONAL([KRB5_USES_COM_ERR], [false])])
  AS_IF([test x"$KRB5_LIBS" != x],
-    [AC_DEFINE([HAVE_KERBEROS], 1, [Define to enable Kerberos features.])])])
+    [rra_use_KRB5=true
+     AC_DEFINE([HAVE_KRB5], 1, [Define to enable Kerberos features.])])])
 
 dnl Source used by RRA_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS.
 AC_DEFUN([_RRA_FUNC_KRB5_OPT_FREE_ARGS_SOURCE], [RRA_INCLUDES_KRB5] [[
index b5185f3023571953f74085f297970ac840954e5e..22d38ee8164f8874502e908daee28f4f2a45fa1a 100644 (file)
@@ -12,7 +12,7 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2005, 2006, 2007
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index 32d4a751b2b56f4f8ab8de71667024319f293510..0b2e85ca99e650a27ba844563b751003e082566c 100644 (file)
@@ -6,12 +6,12 @@ dnl CPPFLAGS, LDFLAGS, and LIBS shell substitution variables.  Most of them
 dnl take as one of the arguments the prefix string to use for variables, which
 dnl is usually something like "KRB5" or "GSSAPI".
 dnl
-dnl Depends on RRA_ENABLE_REDUCED_DEPENDS and RRA_SET_LDFLAGS.
+dnl Depends on RRA_SET_LDFLAGS.
 dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2011, 2013
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index fd5a5a12e57dfa619287791eebbe69b75d30771d..828270f7671e34d1f52ea6ba3994c27f0d26347b 100644 (file)
@@ -15,7 +15,7 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2008, 2009
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index cd585efa3a92feea1e1b2ce349802755b5a632da..f134ab975b167126c0d4f3481eaa09aa1ed71b84 100644 (file)
@@ -12,7 +12,7 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2006, 2008, 2009
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index 1c9ef437e10a0d4411cf127a00774ed11f036bea..d7fd22f4143a86db5b5cebc1cc90569bc76f391f 100644 (file)
@@ -7,15 +7,17 @@ dnl
 dnl Provides the macros RRA_LIB_CDB and RRA_LIB_CDB_OPTIONAL and sets the
 dnl substitution variables CDB_CPPFLAGS, CDB_LDFLAGS, and CDB_LIBS.  Also
 dnl provides RRA_LIB_CDB_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include
-dnl the kadmin client libraries, saving the ecurrent values, and
-dnl RRA_LIB_CDB_RESTORE to restore those settings to before the last
-dnl RRA_LIB_CDB_SWITCH.  Defines HAVE_CDB and sets rra_use_CDB to true if the
-dnl library is found.
+dnl the TinyCDB libraries, saving the current values, and RRA_LIB_CDB_RESTORE
+dnl to restore those settings to before the last RRA_LIB_CDB_SWITCH.  Defines
+dnl HAVE_CDB and sets rra_use_CDB to true if the library is found.
 dnl
-dnl Depends on the lib-helper.m4 infrastructure.
+dnl Depends on the lib-helper.m4 framework.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
-dnl Copyright 2010, 2013
+dnl The canonical version of this file is maintained in the rra-c-util
+dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+dnl
+dnl Written by Russ Allbery <eagle@eyrie.org>
+dnl Copyright 2013
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
 dnl This file is free software; the authors give unlimited permission to copy
@@ -36,26 +38,28 @@ dnl says to fail if the libcdb library could not be found.
 AC_DEFUN([_RRA_LIB_CDB_INTERNAL],
 [RRA_LIB_HELPER_PATHS([CDB])
  RRA_LIB_CDB_SWITCH
- AC_CHECK_LIB([cdb], [cdb_init],
-    [CDB_LIBS=-lcdb
-     AC_DEFINE([HAVE_CDB], 1, [Define if libcdb is available.])
-     rra_use_CDB=true],
+ AC_CHECK_LIB([cdb], [cdb_init], [CDB_LIBS=-lcdb],
     [AS_IF([test x"$1" = xtrue],
         [AC_MSG_ERROR([cannot find usable TinyCDB library])])])
  AC_CHECK_HEADERS([cdb.h])
  RRA_LIB_CDB_RESTORE])
 
-dnl The main macro for packages with mandatory kadmin client support.
+dnl The main macro for packages with mandatory TinyCDB support.
 AC_DEFUN([RRA_LIB_CDB],
 [RRA_LIB_HELPER_VAR_INIT([CDB])
  RRA_LIB_HELPER_WITH([tinycdb], [TinyCDB], [CDB])
- _RRA_LIB_CDB_INTERNAL([true])])
+ _RRA_LIB_CDB_INTERNAL([true])
+ rra_use_CDB=true
+ AC_DEFINE([HAVE_CDB], 1, [Define if libcdb is available.])])
 
-dnl The main macro for packages with optional kadmin client support.
+dnl The main macro for packages with optional TinyCDB support.
 AC_DEFUN([RRA_LIB_CDB_OPTIONAL],
 [RRA_LIB_HELPER_VAR_INIT([CDB])
  RRA_LIB_HELPER_WITH_OPTIONAL([tinycdb], [TinyCDB], [CDB])
  AS_IF([test x"$rra_use_CDB" != xfalse],
     [AS_IF([test x"$rra_use_CDB" = xtrue],
         [_RRA_LIB_CDB_INTERNAL([true])],
-        [_RRA_LIB_CDB_INTERNAL([false])])])])
+        [_RRA_LIB_CDB_INTERNAL([false])])])
+ AS_IF([test x"$CDB_LIBS" != x],
+    [rra_use_CDB=true
+     AC_DEFINE([HAVE_CDB], 1, [Define if libcdb is available.])])])
index af98f6a6b870bcffe887367807090969dff2cf92..62fb82d521ad3c82f1d7bb12533ba81789986502 100644 (file)
@@ -16,7 +16,7 @@ dnl
 dnl The canonical version of this file is maintained in the rra-c-util
 dnl package, available at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 dnl
-dnl Written by Russ Allbery <rra@stanford.edu>
+dnl Written by Russ Allbery <eagle@eyrie.org>
 dnl Copyright 2006, 2008, 2009
 dnl     The Board of Trustees of the Leland Stanford Junior University
 dnl
index dc80d86f22a1ede207d3fdc23c0376e5b2d84a70..92e08eb13dfdd6e78d2b0d0d73ef1b58c670da1d 100644 (file)
@@ -8,7 +8,7 @@
  * or end, two characters removed from the start, two from the end, or one
  * character from both start and end.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
diff --git a/plugin/classes.c b/plugin/classes.c
new file mode 100644 (file)
index 0000000..6e79d14
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Password strength checks for character classes.
+ *
+ * Checks whether the password satisfies a set of character class rules.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2013
+ *     The Board of Trustees of the Leland Stanford Junior University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <ctype.h>
+
+#include <plugin/internal.h>
+
+/* Stores the characteristics of a particular password as boolean flags. */
+struct password_classes {
+    bool lower;
+    bool upper;
+    bool digit;
+    bool symbol;
+};
+
+/* Abbreviate the most common error reporting syntax. */
+#define MUST_HAVE(ctx, err) \
+    strength_error_class((ctx), "password must contain " err)
+
+
+/*
+ * Analyze a password and fill out a struct with flags indicating which
+ * character classes are present in the password.
+ */
+static void
+analyze_password(const char *password, struct password_classes *classes)
+{
+    const char *p;
+
+    memset(classes, 0, sizeof(struct password_classes));
+    for (p = password; *p != '\0'; p++) {
+        if (islower((unsigned char) *p))
+            classes->lower = true;
+        else if (isupper((unsigned char) *p))
+            classes->upper = true;
+        else if (isdigit((unsigned char) *p))
+            classes->digit = true;
+        else
+            classes->symbol = true;
+    }
+}
+
+
+/*
+ * Check whether a password satisfies a required character class rule, given
+ * the length of the password and the classes.  Returns 0 if it does and a
+ * Kerberos error code if it does not.
+ */
+static krb5_error_code
+check_rule(krb5_context ctx, struct class_rule *rule, size_t length,
+           struct password_classes *classes)
+{
+    if (length < rule->min || (rule->max > 0 && length > rule->max))
+        return 0;
+    if (rule->lower && !classes->lower)
+        return MUST_HAVE(ctx, "a lowercase letter");
+    if (rule->upper && !classes->upper)
+        return MUST_HAVE(ctx, "an uppercase letter");
+    if (rule->digit && !classes->digit)
+        return MUST_HAVE(ctx, "a number");
+    if (rule->symbol && !classes->symbol)
+        return MUST_HAVE(ctx, "a space or punctuation character");
+    return 0;
+}
+
+
+/*
+ * Check whether a password satisfies the configured character class
+ * restrictions.
+ */
+krb5_error_code
+strength_check_classes(krb5_context ctx, krb5_pwqual_moddata data,
+                       const char *password)
+{
+    struct password_classes classes;
+    size_t length;
+    struct class_rule *rule;
+    krb5_error_code code;
+
+    if (data->rules == NULL)
+        return 0;
+    analyze_password(password, &classes);
+    length = strlen(password);
+    for (rule = data->rules; rule != NULL; rule = rule->next) {
+        code = check_rule(ctx, rule, length, &classes);
+        if (code != 0)
+            return code;
+    }
+    return 0;
+}
index 9cbd3b44435e105c750afde1fc7e8572958f312c..6aaa21a40b31062cc2ce1d918d53c8ebf52d4ed7 100644 (file)
@@ -5,7 +5,7 @@
  * settings from krb5.conf.  This wraps the somewhat awkward
  * krb5_appdefaults_* functions.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
@@ -16,6 +16,7 @@
 #include <portable/krb5.h>
 #include <portable/system.h>
 
+#include <ctype.h>
 #include <errno.h>
 
 #include <plugin/internal.h>
@@ -105,6 +106,26 @@ free_default_realm(krb5_context ctx UNUSED, realm_type realm)
 #endif /* !HAVE_KRB5_REALM */
 
 
+/*
+ * Helper function to parse a number.  Takes the string to parse, the unsigned
+ * int in which to store the number, and the pointer to set to the first
+ * invalid character after the number.  Returns true if a number could be
+ * successfully parsed and false otherwise.
+ */
+static bool
+parse_number(const char *string, unsigned long *result, const char **end)
+{
+    unsigned long value;
+
+    errno = 0;
+    value = strtoul(string, (char **) end, 10);
+    if (errno != 0 || *end == string)
+        return false;
+    *result = value;
+    return true;
+}
+
+
 /*
  * Load a boolean option from Kerberos appdefaults.  Takes the Kerberos
  * context, the option, and the result location.
@@ -127,6 +148,171 @@ strength_config_boolean(krb5_context ctx, const char *opt, bool *result)
 }
 
 
+/*
+ * Parse a single class specification.  Currently, this assumes that the class
+ * specification is a comma-separated list of required classes, and those
+ * classes are required for any length of password.  This will be enhanced
+ * later.
+ */
+static krb5_error_code
+parse_class(krb5_context ctx, const char *spec, struct class_rule **rule)
+{
+    struct vector *classes = NULL;
+    size_t i;
+    krb5_error_code code;
+    const char *end;
+    bool okay;
+
+    /* Create the basic rule structure. */
+    *rule = calloc(1, sizeof(struct class_rule));
+    if (*rule == NULL)
+        return strength_error_system(ctx, "cannot allocate memory");
+
+    /*
+     * If the rule starts with a digit, it starts with a range of affected
+     * password lengths.  Parse that range.
+     */
+    if (isdigit((unsigned char) *spec)) {
+        okay = parse_number(spec, &(*rule)->min, &end);
+        if (okay)
+            okay = (*end == '-');
+        if (okay)
+            okay = parse_number(end + 1, &(*rule)->max, &end);
+        if (okay)
+            okay = (*end == ':');
+        if (okay)
+            spec = end + 1;
+        else {
+            code = strength_error_config(ctx, "bad character class requirement"
+                                         " in configuration: %s", spec);
+            goto fail;
+        }
+    }
+
+    /* Parse the required classes into a vector. */
+    classes = strength_vector_split_multi(spec, ",", NULL);
+    if (classes == NULL) {
+        code = strength_error_system(ctx, "cannot allocate memory");
+        goto fail;
+    }
+
+    /*
+     * Walk the list of required classes and set our flags, diagnosing an
+     * unknown character class.
+     */
+    for (i = 0; i < classes->count; i++) {
+        if (strcmp(classes->strings[i], "upper") == 0)
+            (*rule)->upper = true;
+        else if (strcmp(classes->strings[i], "lower") == 0)
+            (*rule)->lower = true;
+        else if (strcmp(classes->strings[i], "digit") == 0)
+            (*rule)->digit = true;
+        else if (strcmp(classes->strings[i], "symbol") == 0)
+            (*rule)->symbol = true;
+        else {
+            code = strength_error_config(ctx, "unknown character class %s",
+                                         classes->strings[i]);
+            goto fail;
+        }
+    }
+    strength_vector_free(classes);
+    return 0;
+
+fail:
+    strength_vector_free(classes);
+    free(*rule);
+    *rule = NULL;
+    return code;
+}
+
+
+/*
+ * Parse character class requirements from Kerberos appdefaults.  Takes the
+ * Kerberos context, the option, and the place to store the linked list of
+ * class requirements.
+ */
+krb5_error_code
+strength_config_classes(krb5_context ctx, const char *opt,
+                        struct class_rule **result)
+{
+    struct vector *config = NULL;
+    struct class_rule *rules, *last, *tmp;
+    krb5_error_code code;
+    size_t i;
+
+    /* Get the basic configuration as a list. */
+    code = strength_config_list(ctx, opt, &config);
+    if (code != 0)
+        return code;
+    if (config == NULL || config->count == 0) {
+        *result = NULL;
+        return 0;
+    }
+
+    /* Each word in the list will be a class rule. */
+    code = parse_class(ctx, config->strings[0], &rules);
+    if (code != 0 || rules == NULL)
+        goto fail;
+    last = rules;
+    for (i = 1; i < config->count; i++) {
+        code = parse_class(ctx, config->strings[i], &last->next);
+        if (code != 0 || last->next == NULL)
+            goto fail;
+        last = last->next;
+    }
+
+    /* Success.  Free the vector and return the results. */
+    strength_vector_free(config);
+    *result = rules;
+    return 0;
+
+fail:
+    last = rules;
+    while (last != NULL) {
+        tmp = last;
+        last = last->next;
+        free(tmp);
+    }
+    strength_vector_free(config);
+    return code;
+}
+
+
+/*
+ * Load a list option from Kerberos appdefaults.  Takes the Kerberos context,
+ * the option, and the result location.  The option is read as a string and
+ * the split on spaces and tabs into a list.
+ *
+ * This requires an annoying workaround because one cannot specify a default
+ * value of NULL with MIT Kerberos, since MIT Kerberos unconditionally calls
+ * strdup on the default value.  There's also no way to determine if memory
+ * allocation failed while parsing or while setting the default value.
+ */
+krb5_error_code
+strength_config_list(krb5_context ctx, const char *opt,
+                     struct vector **result)
+{
+    realm_type realm;
+    char *value = NULL;
+
+    /* Obtain the string from [appdefaults]. */
+    realm = default_realm(ctx);
+    krb5_appdefault_string(ctx, "krb5-strength", realm, opt, "", &value);
+    free_default_realm(ctx, realm);
+
+    /* If we got something back, store it in result. */
+    if (value != NULL) {
+        if (value[0] != '\0') {
+            *result = strength_vector_split_multi(value, " \t", *result);
+            if (*result == NULL)
+                return strength_error_system(ctx, "cannot allocate memory");
+        }
+        krb5_free_string(ctx, value);
+    }
+    return 0;
+}
+
+
 /*
  * Load a number option from Kerberos appdefaults.  Takes the Kerberos
  * context, the option, and the result location.  The native interface doesn't
index b7b9dd067dad98964d3c5fd05ebafc7427cce9a3..ed5d4aeb8fca21e210886a99a7273a9df73fc66a 100644 (file)
@@ -6,10 +6,10 @@
  * against a CrackLib dictionary.
  *
  * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
- *     on behalf of Stanford University.
- * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ *     on behalf of Stanford University
+ * Extensive modifications by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2009, 2012, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     The Board of Trustees of the Leland Stanford Junior University
  *
  * See LICENSE for licensing terms.
  */
index e6525ef40a94650dd1190508575c6df47301e7f1..9fc0422d14d2a95a1222526e6ead71bd03b775cc 100644 (file)
@@ -4,7 +4,7 @@
  * Provides helper functions for the rest of the plugin code to store an error
  * message in the Kerberos context.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
@@ -60,6 +60,7 @@ set_error(krb5_context ctx, krb5_error_code code, const char *format,
         return code;                                                    \
     }
 ERROR_FUNC(class,    KADM5_PASS_Q_CLASS)
+ERROR_FUNC(config,   KADM5_MISSING_KRB5_CONF_PARAMS)
 ERROR_FUNC(dict,     KADM5_PASS_Q_DICT)
 ERROR_FUNC(generic,  KADM5_PASS_Q_GENERIC)
 ERROR_FUNC(tooshort, KADM5_PASS_Q_TOOSHORT)
index 8a26acdcaeedc3c66c2b9e2fee0e31f06df85598..22690b1a78e17a711ea1cf4a646442a5c290a10a 100644 (file)
@@ -7,10 +7,10 @@
  * wrapped up in those interfaces.
  *
  * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
- *     on behalf of Stanford University.
- * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ *     on behalf of Stanford University
+ * Extensive modifications by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2009, 2012, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     The Board of Trustees of the Leland Stanford Junior University
  *
  * See LICENSE for licensing terms.
  */
@@ -50,10 +50,15 @@ strength_init(krb5_context ctx, const char *dictionary,
     /* Get minimum length information from krb5.conf. */
     strength_config_number(ctx, "minimum_length", &data->minimum_length);
 
-    /* Get character class restrictions from krb5.conf. */
+    /* Get simple character class restrictions from krb5.conf. */
     strength_config_boolean(ctx, "require_ascii_printable", &data->ascii);
     strength_config_boolean(ctx, "require_non_letter", &data->nonletter);
 
+    /* Get complex character class restrictions from krb5.conf. */
+    code = strength_config_classes(ctx, "require_classes", &data->rules);
+    if (code != 0)
+        goto fail;
+
     /*
      * Try to initialize CDB and CrackLib dictionaries.  Both functions handle
      * their own configuration parsing and will do nothing if the
@@ -139,6 +144,14 @@ strength_check(krb5_context ctx UNUSED, krb5_pwqual_moddata data,
     if (data->nonletter && only_alpha_space(password))
         return strength_error_class(ctx, ERROR_LETTER);
 
+    /*
+     * If desired, check that the password satisfies character class
+     * restrictions.
+     */
+    code = strength_check_classes(ctx, data, password);
+    if (code != 0)
+        return code;
+
     /* Check if the password is based on the principal in some way. */
     code = strength_check_principal(ctx, data, principal, password);
     if (code != 0)
@@ -164,9 +177,17 @@ strength_check(krb5_context ctx UNUSED, krb5_pwqual_moddata data,
 void
 strength_close(krb5_context ctx UNUSED, krb5_pwqual_moddata data)
 {
-    if (data != NULL) {
-        strength_close_cdb(ctx, data);
-        free(data->dictionary);
-        free(data);
+    struct class_rule *last, *tmp;
+
+    if (data == NULL)
+        return;
+    strength_close_cdb(ctx, data);
+    last = data->rules;
+    while (last != NULL) {
+        tmp = last;
+        last = last->next;
+        free(tmp);
     }
+    free(data->dictionary);
+    free(data);
 }
index 0acae9fdc037d4f05f19a525163826cb53d440d2..52c81975d808495cc663f5ea1fe114b6d55282b2 100644 (file)
@@ -11,9 +11,9 @@
  * Of course, the external Heimdal strength checking program can be used
  * instead.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     The Board of Trustees of the Leland Stanford Junior University
  *
  * See LICENSE for licensing terms.
  */
index 7872e80f8419c74d81a6c47656dd16911cc026ce..7eebf67ae42cf2f3c54498f6ea4c923b77c02b34 100644 (file)
@@ -2,10 +2,10 @@
  * Prototypes for the kadmin password strength checking plugin.
  *
  * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
- *     on behalf of Stanford University.
- * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ *     on behalf of Stanford University
+ * Extensive modifications by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2009, 2012, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     The Board of Trustees of the Leland Stanford Junior University
  *
  * See LICENSE for licensing terms.
  */
@@ -20,6 +20,7 @@
 #ifdef HAVE_CDB_H
 # include <cdb.h>
 #endif
+#include <stddef.h>
 
 #ifdef HAVE_KRB5_PWQUAL_PLUGIN_H
 # include <krb5/pwqual_plugin.h>
@@ -34,6 +35,30 @@ typedef struct krb5_pwqual_moddata_st *krb5_pwqual_moddata;
 #define ERROR_SHORT    "password is too short"
 #define ERROR_USERNAME "password based on username or principal"
 
+/*
+ * A character class rule, which consists of a minimum length to which the
+ * rule is applied, a maximum length to which the rule is applied, and a set
+ * of flags for which character classes are required.  The symbol class
+ * includes everything that isn't in one of the other classes, including
+ * space.
+ */
+struct class_rule {
+    unsigned long min;
+    unsigned long max;
+    bool lower;
+    bool upper;
+    bool digit;
+    bool symbol;
+    struct class_rule *next;
+};
+
+/* Used to store a list of strings, managed by the sync_vector_* functions. */
+struct vector {
+    size_t count;
+    size_t allocated;
+    char **strings;
+};
+
 /*
  * MIT Kerberos uses this type as an abstract data type for any data that a
  * password quality check needs to carry.  Reuse it since then we get type
@@ -43,6 +68,7 @@ struct krb5_pwqual_moddata_st {
     long minimum_length;        /* Minimum password length */
     bool ascii;                 /* Whether to require printable ASCII */
     bool nonletter;             /* Whether to require a non-letter */
+    struct class_rule *rules;   /* Linked list of character class rules */
     char *dictionary;           /* Base path to CrackLib dictionary */
     bool have_cdb;              /* Whether we have a CDB dictionary */
     int cdb_fd;                 /* File descriptor of CDB dictionary */
@@ -99,11 +125,40 @@ krb5_error_code strength_init_cracklib(krb5_context, krb5_pwqual_moddata,
 krb5_error_code strength_check_cracklib(krb5_context, krb5_pwqual_moddata,
                                         const char *password);
 
+/* Check whether the password statisfies character class requirements. */
+krb5_error_code strength_check_classes(krb5_context, krb5_pwqual_moddata,
+                                       const char *password);
+
 /* Check whether the password is based on the principal in some way. */
 krb5_error_code strength_check_principal(krb5_context, krb5_pwqual_moddata,
                                          const char *principal,
                                          const char *password);
 
+/*
+ * Manage vectors, which are counted lists of strings.  The functions that
+ * return a boolean return false if memory allocation fails.
+ */
+struct vector *strength_vector_new(void)
+    __attribute__((__malloc__));
+bool strength_vector_add(struct vector *, const char *string)
+    __attribute__((__nonnull__));
+void strength_vector_free(struct vector *);
+
+/*
+ * vector_split_multi splits on a set of characters.  If the vector argument
+ * is NULL, a new vector is allocated; otherwise, the provided one is reused.
+ * Returns NULL on memory allocation failure, after which the provided vector
+ * may have been modified to only have partial results.
+ *
+ * Empty strings will yield zero-length vectors.  Adjacent delimiters are
+ * treated as a single delimiter by vector_split_multi.  Any leading or
+ * trailing delimiters are ignored, so this function will never create
+ * zero-length strings (similar to the behavior of strtok).
+ */
+struct vector *strength_vector_split_multi(const char *string,
+                                           const char *seps, struct vector *)
+    __attribute__((__nonnull__(1, 2)));
+
 /*
  * Obtain configuration settings from krb5.conf.  These are wrappers around
  * the krb5_appdefault_* APIs that handle setting the section name, obtaining
@@ -112,11 +167,19 @@ krb5_error_code strength_check_principal(krb5_context, krb5_pwqual_moddata,
  */
 void strength_config_boolean(krb5_context, const char *, bool *)
     __attribute__((__nonnull__));
+krb5_error_code strength_config_list(krb5_context, const char *,
+                                     struct vector **)
+    __attribute__((__nonnull__));
 void strength_config_number(krb5_context, const char *, long *)
     __attribute__((__nonnull__));
 void strength_config_string(krb5_context, const char *, char **)
     __attribute__((__nonnull__));
 
+/* Parse the more complex configuration of required character classes. */
+krb5_error_code strength_config_classes(krb5_context, const char *,
+                                        struct class_rule **)
+    __attribute__((__nonnull__));
+
 /*
  * Store a particular password quality error in the Kerberos context.  The
  * _system variant uses errno for the error code and appends the strerror
@@ -124,6 +187,8 @@ void strength_config_string(krb5_context, const char *, char **)
  */
 krb5_error_code strength_error_class(krb5_context, const char *format, ...)
     __attribute__((__nonnull__, __format__(printf, 2, 3)));
+krb5_error_code strength_error_config(krb5_context, const char *format, ...)
+    __attribute__((__nonnull__, __format__(printf, 2, 3)));
 krb5_error_code strength_error_dict(krb5_context, const char *format, ...)
     __attribute__((__nonnull__, __format__(printf, 2, 3)));
 krb5_error_code strength_error_generic(krb5_context, const char *format, ...)
index 55b6d1344277f62e13363e0edfa5ba75f22c715b..5dfe55d82c23e3a78b6d0fefe57ca235b4b7287b 100644 (file)
@@ -6,10 +6,10 @@
  * components of the principal.
  *
  * Developed by Derrick Brashear and Ken Hornstein of Sine Nomine Associates,
- *     on behalf of Stanford University.
- * Extensive modifications by Russ Allbery <rra@stanford.edu>
+ *     on behalf of Stanford University
+ * Extensive modifications by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2009, 2012, 2013
- *     The Board of Trustees of the Leland Stanford Junior Unversity
+ *     The Board of Trustees of the Leland Stanford Junior University
  *
  * See LICENSE for licensing terms.
  */
diff --git a/plugin/vector.c b/plugin/vector.c
new file mode 100644 (file)
index 0000000..b7895be
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Vector handling (counted lists of char *'s).
+ *
+ * A vector is a table for handling a list of strings with less overhead than
+ * linked list.  The intention is for vectors, once allocated, to be reused;
+ * this saves on memory allocations once the array of char *'s reaches a
+ * stable size.
+ *
+ * This is based on the from rra-c-util util/vector.c library, but that
+ * library uses xmalloc routines to exit the program if memory allocation
+ * fails.  This is a modified version of the vector library that instead
+ * returns false on failure to allocate memory, allowing the caller to do
+ * appropriate recovery.
+ *
+ * Vectors require list of strings, not arbitrary binary data, and cannot
+ * handle data elements containing nul characters.
+ *
+ * Only the portions of the vector library needed by this module is
+ * implemented.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2013
+ *     The Board of Trustees of the Leland Stanford Junior University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <plugin/internal.h>
+
+
+/*
+ * Allocate a new, empty vector.  Returns NULL if memory allocation fails.
+ */
+struct vector *
+strength_vector_new(void)
+{
+    return calloc(1, sizeof(struct vector));
+}
+
+
+/*
+ * Resize a vector (using realloc to resize the table).  Return false if
+ * memory allocation fails.
+ */
+static bool
+strength_vector_resize(struct vector *vector, size_t size)
+{
+    size_t i;
+    char **strings;
+
+    /* If we're shrinking the vector, free the excess strings. */
+    if (vector->count > size) {
+        for (i = size; i < vector->count; i++)
+            free(vector->strings[i]);
+        vector->count = size;
+    }
+
+    /* If resizing to zero, free all storage.  Otherwise, realloc. */
+    if (size == 0) {
+        free(vector->strings);
+        vector->strings = NULL;
+    } else {
+        strings = realloc(vector->strings, size * sizeof(char *));
+        if (strings == NULL)
+            return false;
+        vector->strings = strings;
+    }
+    vector->allocated = size;
+    return true;
+}
+
+
+/*
+ * Add a new string to the vector, resizing the vector as necessary.  The
+ * vector is resized an element at a time; if a lot of resizes are expected,
+ * vector_resize should be called explicitly with a more suitable size.
+ * Return false if memory allocation fails.
+ */
+bool
+strength_vector_add(struct vector *vector, const char *string)
+{
+    size_t next = vector->count;
+
+    if (vector->count == vector->allocated)
+        if (!strength_vector_resize(vector, vector->allocated + 1))
+            return false;
+    vector->strings[next] = strdup(string);
+    if (vector->strings[next] == NULL)
+        return false;
+    vector->count++;
+    return true;
+}
+
+
+/*
+ * Empty a vector but keep the allocated memory for the pointer table.
+ */
+static void
+strength_vector_clear(struct vector *vector)
+{
+    size_t i;
+
+    for (i = 0; i < vector->count; i++)
+        if (vector->strings[i] != NULL)
+            free(vector->strings[i]);
+    vector->count = 0;
+}
+
+
+/*
+ * Free a vector completely.
+ */
+void
+strength_vector_free(struct vector *vector)
+{
+    if (vector == NULL)
+        return;
+    strength_vector_clear(vector);
+    free(vector->strings);
+    free(vector);
+}
+
+
+/*
+ * Given a vector that we may be reusing, clear it out.  If the first argument
+ * is NULL, allocate a new vector.  Used by vector_split*.  Returns NULL if
+ * memory allocation fails.
+ */
+static struct vector *
+strength_vector_reuse(struct vector *vector)
+{
+    if (vector == NULL)
+        return strength_vector_new();
+    else {
+        strength_vector_clear(vector);
+        return vector;
+    }
+}
+
+
+/*
+ * Given a string and a set of separators expressed as a string, count the
+ * number of strings that it will split into when splitting on those
+ * separators.
+ */
+static size_t
+split_multi_count(const char *string, const char *seps)
+{
+    const char *p;
+    size_t count;
+
+    /* If the string is empty, the count of components is zero. */
+    if (*string == '\0')
+        return 0;
+
+    /* Otherwise, walk the string looking for non-consecutive separators. */
+    for (count = 1, p = string + 1; *p != '\0'; p++)
+        if (strchr(seps, *p) != NULL && strchr(seps, p[-1]) == NULL)
+            count++;
+
+    /*
+     * If the string ends in separators, we've overestimated the number of
+     * strings by one.
+     */
+    if (strchr(seps, p[-1]) != NULL)
+        count--;
+    return count;
+}
+
+
+/*
+ * Given a string, split it at any of the provided separators to form a
+ * vector, copying each string segment.  If the third argument isn't NULL,
+ * reuse that vector; otherwise, allocate a new one.  Any number of
+ * consecutive separators are considered a single separator.  Returns NULL on
+ * memory allocation failure, after which the provided vector may only have
+ * partial results.
+ */
+struct vector *
+strength_vector_split_multi(const char *string, const char *seps,
+                        struct vector *vector)
+{
+    const char *p, *start;
+    size_t i, count;
+    bool created = false;
+
+    /* Set up the vector we'll use to store the results. */
+    if (vector == NULL)
+        created = true;
+    vector = strength_vector_reuse(vector);
+    if (vector == NULL)
+        return NULL;
+
+    /* Count how big a vector we need and resize accordingly. */
+    count = split_multi_count(string, seps);
+    if (count == 0)
+        return vector;
+    if (vector->allocated < count && !strength_vector_resize(vector, count))
+        goto fail;
+
+    /* Now, walk the string and build the components. */
+    vector->count = 0;
+    for (start = string, p = string, i = 0; *p != '\0'; p++)
+        if (strchr(seps, *p) != NULL) {
+            if (start != p) {
+                vector->strings[i] = strndup(start, (size_t) (p - start));
+                if (vector->strings[i] == NULL)
+                    goto fail;
+                i++;
+                vector->count++;
+            }
+            start = p + 1;
+        }
+
+    /* If there is anything left in the string, we have one more component. */
+    if (start != p) {
+        vector->strings[i] = strndup(start, (size_t) (p - start));
+        if (vector->strings[i] == NULL)
+            goto fail;
+        vector->count++;
+    }
+    return vector;
+
+fail:
+    if (created)
+        strength_vector_free(vector);
+    return NULL;
+}
index 0093070abbba0830bf620a4a76a0f1d271188237..eb2b713e55b3fd5f023f07c870aed588e813288f 100644 (file)
@@ -7,7 +7,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
@@ -21,6 +21,8 @@
 #include <config.h>
 #include <portable/system.h>
 
+#include <errno.h>
+
 /*
  * If we're running the test suite, rename the functions to avoid conflicts
  * with the system versions.
@@ -33,6 +35,7 @@ int test_asprintf(char **, const char *, ...)
 int test_vasprintf(char **, const char *, va_list);
 #endif
 
+
 int
 asprintf(char **strp, const char *fmt, ...)
 {
@@ -45,11 +48,12 @@ asprintf(char **strp, const char *fmt, ...)
     return status;
 }
 
+
 int
 vasprintf(char **strp, const char *fmt, va_list args)
 {
     va_list args_copy;
-    int status, needed;
+    int status, needed, oerrno;
 
     va_copy(args_copy, args);
     needed = vsnprintf(NULL, 0, fmt, args_copy);
@@ -65,8 +69,10 @@ vasprintf(char **strp, const char *fmt, va_list args)
     if (status >= 0)
         return status;
     else {
+        oerrno = errno;
         free(*strp);
         *strp = NULL;
+        errno = oerrno;
         return status;
     }
 }
index e054268efa2a5717752ba6e9ec56646f3d49afcb..890bc0cc3ea8332bd1184d1765992071730fff57 100644 (file)
@@ -8,7 +8,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index e5854de08b4efb4bc9bfd58ae3f79ddcafda4fdb..f4104814f2d96193e23e9796c8a04cd24ddc041f 100644 (file)
@@ -8,7 +8,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
 # define KADM5_PASS_Q_GENERIC KADM5_PASS_Q_DICT
 #endif
 
+/* Heimdal doesn't define KADM5_MISSING_KRB5_CONF_PARAMS. */
+#ifndef KADM5_MISSING_KRB5_CONF_PARAMS
+# define KADM5_MISSING_KRB5_CONF_PARAMS KADM5_MISSING_CONF_PARAMS
+#endif
+
 /*
  * Heimdal provides _ctx functions that take an existing context.  MIT always
  * requires the context be passed in.  Code should use the _ctx variant, and
index 849842cec9e185389c6fa4742e50e1444de3cdac..b1c8b8d1f5b0aa2d05b26a6ee306513145c0b45b 100644 (file)
@@ -9,7 +9,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index f63a6fb90784cc6f2ba800915fd7c733df5a38e8..19016ba8efe85aef0ca1a92a977e4267a0069330 100644 (file)
@@ -19,7 +19,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index b33d06427de3c498109bc2a45eee9a728a8b2f81..b5093f53bdd004843af5c0cb12523a32d9315596 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index d42e11fe2308c61d52cd2f517a1ab7ff6f8eae65..c35ad807671286144845be9cb9c4570bdbe86801 100644 (file)
@@ -2,8 +2,9 @@
  * Replacement for a missing snprintf or vsnprintf.
  *
  * The following implementation of snprintf was taken mostly verbatim from
- * <http://www.fiction.net/~blong/programs/>; it is the version of snprintf
- * used in Mutt.
+ * <http://www.fiction.net/blong/programs/>; it is the version of snprintf
+ * used in Mutt.  A possibly newer version is used in wget, found at
+ * <https://github.com/wertarbyte/wget/blob/master/src/snprintf.c>.
  *
  * Please do not reformat or otherwise change this file more than necessary so
  * that later merges with the original source are easy.  Bug fixes and
@@ -73,7 +74,7 @@
  *    fixed handling of %.0f
  *    added test for HAVE_LONG_DOUBLE
  *
- *  Russ Allbery <rra@stanford.edu> 2000-08-26
+ *  Russ Allbery <eagle@eyrie.org> 2000-08-26
  *    fixed return value to comply with C99
  *    fixed handling of snprintf(NULL, ...)
  *
index 045436f128b8d31b292313255e33b3e6b5fe469f..14d011b804272d84e046659a517c42b3502cb5d1 100644 (file)
@@ -8,7 +8,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
diff --git a/portable/strndup.c b/portable/strndup.c
new file mode 100644 (file)
index 0000000..e94d944
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Replacement for a missing strndup.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <errno.h>
+
+/*
+ * If we're running the test suite, rename the functions to avoid conflicts
+ * with the system versions.
+ */
+#if TESTING
+# undef strndup
+# define strndup test_strndup
+char *test_strndup(const char *, size_t);
+#endif
+
+char *
+strndup(const char *s, size_t n)
+{
+    const char *p;
+    size_t length;
+    char *copy;
+
+    if (s == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    /* Don't assume that the source string is nul-terminated. */
+    for (p = s; (size_t) (p - s) < n && *p != '\0'; p++)
+        ;
+    length = p - s;
+    copy = malloc(length + 1);
+    if (copy == NULL)
+        return NULL;
+    memcpy(copy, s, length);
+    copy[length] = '\0';
+    return copy;
+}
index 173d8e9a0accd4b2e25354f144d780453c252bea..5345da360c4a6f921bd7e15b624d119542d1dd2e 100644 (file)
@@ -22,7 +22,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
@@ -124,6 +124,9 @@ extern int snprintf(char *, size_t, const char *, ...)
 #if !HAVE_DECL_VSNPRINTF
 extern int vsnprintf(char *, size_t, const char *, va_list);
 #endif
+#if !HAVE_STRNDUP
+extern char *strndup(const char *, size_t);
+#endif
 
 /* Undo default visibility change. */
 #pragma GCC visibility pop
index 5d38748f7b1da4a54b5571ac97ca528bcbb131bb..b94985def87eeff3cf5140c58bbc58f1da19cd61 100644 (file)
@@ -240,7 +240,7 @@ License
     This file is part of the documentation of C TAP Harness, which can be
     found at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
 
-    Copyright 2010 Russ Allbery <rra@stanford.edu>
+    Copyright 2010 Russ Allbery <eagle@eyrie.org>
 
     Copying and distribution of this file, with or without modification,
     are permitted in any medium without royalty provided the copyright
index 344e69850c87d303fd641579e17b8b6f49fc05cc..b85e43d61576931dc3f83b8e19323567b8eff50b 100644 (file)
@@ -7,6 +7,7 @@ perl/minimum-version
 perl/strict
 portable/asprintf
 portable/snprintf
+portable/strndup
 tools/cdbmake-wordlist
 tools/heimdal-strength
 util/messages
index 42891b378bc9a3165e3a99a3b6189a732daa111d..abff6d11a1a0e2ccbdf67ef77eaab9a0874b11e1 100755 (executable)
@@ -1,10 +1,10 @@
 #!/bin/sh
 #
-# Generate a krb5.conf file with an [appdefault] password_dictionary setting
-# pointing to the password dictionary we generated for the build.  This script
-# is used by C tests to set up the environment.
+# Generate a krb5.conf file with an [appdefault] krb5-strength section that
+# contains all the key/value pairs given on the command line.  This script is
+# used by C tests to set up the environment.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2009, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
diff --git a/tests/data/passwords/classes.c b/tests/data/passwords/classes.c
new file mode 100644 (file)
index 0000000..4828512
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Automatically generated -- do not edit!
+ *
+ * This file was automatically generated from the original JSON source file
+ * for the use in C test programs.  To make changes, modify the original
+ * JSON source or (more rarely) the make-c-data script and run it again.
+ *
+ * Copyright 2013
+ *     The Board of Trustees of the Leland Stanford Junior University
+ *
+ * See LICENSE for licensing terms.
+ */
+
+#include <tests/data/passwords/tests.h>
+
+const struct password_test classes_tests[] = {
+    {
+
+        "no lowercase (11)",
+        "test@EXAMPLE.ORG",
+        "PASSWORD98!",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a lowercase letter",
+    },
+    {
+
+        "no uppercase (11)",
+        "test@EXAMPLE.ORG",
+        "password98!",
+        KADM5_PASS_Q_CLASS,
+        "password must contain an uppercase letter",
+    },
+    {
+
+        "no digit (11)",
+        "test@EXAMPLE.ORG",
+        "passwordXX!",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a number",
+    },
+    {
+
+        "no symbol (11)",
+        "test@EXAMPLE.ORG",
+        "passwordXX9",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a space or punctuation character",
+    },
+    {
+
+        "all classes (11)",
+        "test@EXAMPLE.ORG",
+        "passwordX9!",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes with space (11)",
+        "test@EXAMPLE.ORG",
+        "pass wordX9",
+        0,
+        NULL,
+    },
+    {
+
+        "no lowercase (15)",
+        "test@EXAMPLE.ORG",
+        "PASSWORD98!WORD",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a lowercase letter",
+    },
+    {
+
+        "no uppercase (15)",
+        "test@EXAMPLE.ORG",
+        "password98!word",
+        KADM5_PASS_Q_CLASS,
+        "password must contain an uppercase letter",
+    },
+    {
+
+        "no digit (15)",
+        "test@EXAMPLE.ORG",
+        "passwordXX!word",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a number",
+    },
+    {
+
+        "no symbol (12)",
+        "test@EXAMPLE.ORG",
+        "passwordXX9w",
+        0,
+        NULL,
+    },
+    {
+
+        "no symbol (15)",
+        "test@EXAMPLE.ORG",
+        "passwordXX9word",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes (15)",
+        "test@EXAMPLE.ORG",
+        "passwordX9!word",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes with space (15)",
+        "test@EXAMPLE.ORG",
+        "pass wordX9word",
+        0,
+        NULL,
+    },
+    {
+
+        "no lowercase (19)",
+        "test@EXAMPLE.ORG",
+        "PASSWORD98!WORDWORD",
+        KADM5_PASS_Q_CLASS,
+        "password must contain a lowercase letter",
+    },
+    {
+
+        "no uppercase (19)",
+        "test@EXAMPLE.ORG",
+        "password98!wordword",
+        KADM5_PASS_Q_CLASS,
+        "password must contain an uppercase letter",
+    },
+    {
+
+        "no digit (16)",
+        "test@EXAMPLE.ORG",
+        "passwordXX!wordw",
+        0,
+        NULL,
+    },
+    {
+
+        "no digit (19)",
+        "test@EXAMPLE.ORG",
+        "passwordXX!wordword",
+        0,
+        NULL,
+    },
+    {
+
+        "no symbol (19)",
+        "test@EXAMPLE.ORG",
+        "passwordXX9wordword",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes (19)",
+        "test@EXAMPLE.ORG",
+        "passwordX9!wordword",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes with space (19)",
+        "test@EXAMPLE.ORG",
+        "pass wordX9wordword",
+        0,
+        NULL,
+    },
+    {
+
+        "no lowercase (20)",
+        "test@EXAMPLE.ORG",
+        "PASSWORD98!WORDWORDW",
+        0,
+        NULL,
+    },
+    {
+
+        "no uppercase (20)",
+        "test@EXAMPLE.ORG",
+        "password98!wordwordw",
+        0,
+        NULL,
+    },
+    {
+
+        "no digit (20)",
+        "test@EXAMPLE.ORG",
+        "passwordXX!wordwordw",
+        0,
+        NULL,
+    },
+    {
+
+        "no symbol (20)",
+        "test@EXAMPLE.ORG",
+        "passwordXX9wordwordw",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes (20)",
+        "test@EXAMPLE.ORG",
+        "passwordX9!wordwordw",
+        0,
+        NULL,
+    },
+    {
+
+        "all classes with space (20)",
+        "test@EXAMPLE.ORG",
+        "pass wordX9wordwordw",
+        0,
+        NULL,
+    },
+};
diff --git a/tests/data/passwords/classes.json b/tests/data/passwords/classes.json
new file mode 100644 (file)
index 0000000..bb0da1a
--- /dev/null
@@ -0,0 +1,150 @@
+[
+    {
+        "name": "no lowercase (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "PASSWORD98!",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a lowercase letter"
+    },
+    {
+        "name": "no uppercase (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "password98!",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain an uppercase letter"
+    },
+    {
+        "name": "no digit (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX!",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a number"
+    },
+    {
+        "name": "no symbol (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX9",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a space or punctuation character"
+    },
+    {
+        "name": "all classes (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordX9!"
+    },
+    {
+        "name": "all classes with space (11)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "pass wordX9"
+    },
+    {
+        "name": "no lowercase (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "PASSWORD98!WORD",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a lowercase letter"
+    },
+    {
+        "name": "no uppercase (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "password98!word",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain an uppercase letter"
+    },
+    {
+        "name": "no digit (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX!word",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a number"
+    },
+    {
+        "name": "no symbol (12)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX9w"
+    },
+    {
+        "name": "no symbol (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX9word"
+    },
+    {
+        "name": "all classes (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordX9!word"
+    },
+    {
+        "name": "all classes with space (15)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "pass wordX9word"
+    },
+    {
+        "name": "no lowercase (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "PASSWORD98!WORDWORD",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain a lowercase letter"
+    },
+    {
+        "name": "no uppercase (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "password98!wordword",
+        "code": "KADM5_PASS_Q_CLASS",
+        "error": "password must contain an uppercase letter"
+    },
+    {
+        "name": "no digit (16)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX!wordw"
+    },
+    {
+        "name": "no digit (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX!wordword"
+    },
+    {
+        "name": "no symbol (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX9wordword"
+    },
+    {
+        "name": "all classes (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordX9!wordword"
+    },
+    {
+        "name": "all classes with space (19)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "pass wordX9wordword"
+    },
+    {
+        "name": "no lowercase (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "PASSWORD98!WORDWORDW"
+    },
+    {
+        "name": "no uppercase (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "password98!wordwordw"
+    },
+    {
+        "name": "no digit (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX!wordwordw"
+    },
+    {
+        "name": "no symbol (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordXX9wordwordw"
+    },
+    {
+        "name": "all classes (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "passwordX9!wordwordw"
+    },
+    {
+        "name": "all classes with space (20)",
+        "principal": "test@EXAMPLE.ORG",
+        "password": "pass wordX9wordwordw"
+    }
+]
similarity index 97%
rename from tests/data/passwords/class.c
rename to tests/data/passwords/letter.c
index b3259f940f647c268cb44df739f901f04265ae29..3233aa594779685bb0cdf21dba45154dac9370ba 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <tests/data/passwords/tests.h>
 
-const struct password_test class_tests[] = {
+const struct password_test letter_tests[] = {
     {
 
         "non-ASCII characters",
index 2d6f0e931f0261a6640c3d652c8615a9316a2d08..57d9e94b5d864ec2a2d42b52397dddc589b834f8 100755 (executable)
@@ -191,7 +191,7 @@ code field.
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 6de74a91eb092423a9589ec7f507f2a62b80b461..dd38bdee6b1e23c969f5fef943bfffd9b4c70f3d 100644 (file)
@@ -4,7 +4,7 @@
  * This header provides the struct definition for password test data written
  * out by make-c-data.  It's included by the test data files.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index 7032cb8a7883bef7aaf6302c2600da72d65a900b..b05bb38c0d068a70dfa93dfa8b0f649ce6371bd9 100644 (file)
@@ -9,7 +9,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2011, 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
diff --git a/tests/data/valgrind.supp b/tests/data/valgrind.supp
new file mode 100644 (file)
index 0000000..8bbc290
--- /dev/null
@@ -0,0 +1,119 @@
+# -*- conf -*-
+#
+# This is a valgrind suppression file for analysis of test suite results.
+#
+# Suppress a variety of apparent memory leaks in various Kerberos
+# implementations due to one-time instantiation of data, and a few other
+# artifacts of the test suite for rra-c-util portability and utility code
+# and related software.
+#
+# The canonical version of this file is maintained in the rra-c-util package,
+# which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+#
+# Written by Russ Allbery <eagle@eyrie.org>
+# Copyright 2011, 2012, 2013
+#     The Board of Trustees of the Leland Stanford Junior University
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+{
+   dlopen-dlerror
+   Memcheck:Leak
+   fun:calloc
+   fun:_dlerror_run
+}
+{
+   heimdal-krb5-init-context-once
+   Memcheck:Leak
+   fun:*alloc
+   ...
+   fun:init_context_once
+}
+{
+   heimdal-krb5-reg-plugins-once
+   Memcheck:Leak
+   fun:*alloc
+   ...
+   fun:krb5_plugin_register
+   fun:reg_def_plugins_once
+}
+{
+   heimdal-krb5-openssl-init
+   Memcheck:Leak
+   fun:*alloc
+   obj:*
+   fun:CRYPTO_*alloc
+}
+{
+   mit-gss-ccache
+   Memcheck:Leak
+   fun:*alloc
+   fun:krb5int_setspecific
+   fun:kg_set_ccache_name
+   fun:gss_krb5int_ccache_name
+}
+{
+   mit-gss-ccache-2
+   Memcheck:Leak
+   fun:*alloc
+   fun:strdup
+   fun:kg_set_ccache_name
+   fun:gss_krb5int_ccache_name
+}
+{
+   mit-krb5-pkinit-openssl-init
+   Memcheck:Leak
+   fun:*alloc
+   ...
+   fun:krb5_init_preauth_context
+}
+{
+   mit-krb5-pkinit-openssl-request
+   Memcheck:Leak
+   fun:*alloc
+   ...
+   fun:krb5_preauth_request_context_init
+}
+{
+   mit-krb5-plugin-dirs
+   Memcheck:Leak
+   fun:calloc
+   fun:krb5int_open_plugin_dirs
+}
+{
+   mit-krb5-plugin-dlerror
+   Memcheck:Leak
+   fun:calloc
+   fun:_dlerror_run
+   ...
+   fun:krb5int_open_plugin
+}
+{
+   mit-krb5-plugin-register
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   fun:register_module.isra.1
+}
+{
+   portable-setenv
+   Memcheck:Leak
+   fun:malloc
+   fun:test_setenv
+}
index e1a95cdfacbe6a7d2f2c3d9a95c21ff719a3bbfe..1a02af8efca52224fc3d294c092373b3f67c84ad 100755 (executable)
@@ -7,7 +7,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index 2743287bb65fe1b044a64fa3ccc8586fbc7c0257..69182713f88b4f9b2fb91de357b166c9bad4c389 100755 (executable)
@@ -6,7 +6,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index 89b872d100232bd39bfb7834247c4e620ffbefa7..d588d65c9fac761f2e029328dc3b6581f51f6448 100755 (executable)
@@ -9,7 +9,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index 266f208627bac0de0d58cee49b9f2fdca652352b..060d51e93a72884057c70bae31625b8dab692b4d 100755 (executable)
@@ -9,7 +9,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index a2f92cba888698cf8d6a256f6e7dc6d9f1677a8f..6bac75f71c51b375582f362eb8524d7856a0ee7c 100755 (executable)
@@ -11,7 +11,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index af3057ab7c79f734fcee35cde48cab85fa8eaacf..bd5c2596a644f08bb5f0384b7ed51ef4b17dd5f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Test for the Heimdal shared module API.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
  * named cdb_tests, cracklib_tests, and principal_tests.
  */
 #include <tests/data/passwords/cdb.c>
-#include <tests/data/passwords/class.c>
+#include <tests/data/passwords/classes.c>
 #include <tests/data/passwords/cracklib.c>
 #include <tests/data/passwords/length.c>
+#include <tests/data/passwords/letter.c>
 #include <tests/data/passwords/principal.c>
 
 
@@ -53,28 +54,28 @@ main(void)
 /*
  * Loads the Heimdal password change plugin and tests that its metadata is
  * correct.  Returns a pointer to the kadm5_pw_policy_verifier struct or bails
- * on failure to load the plugin.
+ * on failure to load the plugin.  Stores the handle in the last argument so
+ * that the caller can free the handle at the end of the test suite.
  */
 static struct kadm5_pw_policy_verifier *
-load_plugin(void)
+load_plugin(void **handle)
 {
     char *path;
-    void *handle;
     struct kadm5_pw_policy_verifier *verifier;
 
     /* Load the module. */
     path = test_file_path("../plugin/.libs/strength.so");
     if (path == NULL)
         bail("cannot find plugin");
-    handle = dlopen(path, RTLD_NOW);
-    if (handle == NULL)
-        sysbail("cannot dlopen %s: %s", path, dlerror());
+    *handle = dlopen(path, RTLD_NOW);
+    if (*handle == NULL)
+        bail("cannot dlopen %s: %s", path, dlerror());
     test_file_path_free(path);
 
     /* Find the dispatch table and do a basic sanity check. */
-    verifier = dlsym(handle, "kadm5_password_verifier");
+    verifier = dlsym(*handle, "kadm5_password_verifier");
     if (verifier == NULL)
-        sysbail("cannot get kadm5_password_verifier symbol: %s", dlerror());
+        bail("cannot get kadm5_password_verifier symbol: %s", dlerror());
     if (verifier->funcs == NULL || verifier->funcs[0].func == NULL)
         bail("no verifier functions in module");
 
@@ -140,6 +141,7 @@ main(void)
     char *setup_argv[10];
     size_t i, count;
     struct kadm5_pw_policy_verifier *verifier;
+    void *handle;
 
     /*
      * Calculate how many tests we have.  There are five tests for the module
@@ -148,8 +150,9 @@ main(void)
      */
     count = ARRAY_SIZE(cracklib_tests);
     count += ARRAY_SIZE(cdb_tests);
-    count += ARRAY_SIZE(class_tests);
+    count += ARRAY_SIZE(classes_tests);
     count += ARRAY_SIZE(length_tests);
+    count += ARRAY_SIZE(letter_tests);
     count += ARRAY_SIZE(principal_tests) * 2;
     plan(5 + count * 2);
 
@@ -161,7 +164,7 @@ main(void)
     putenv(krb5_config_empty);
 
     /* Load the plugin. */
-    verifier = load_plugin();
+    verifier = load_plugin(&handle);
 
     /* Set up our krb5.conf with the dictionary configuration. */
     setup_argv[0] = test_file_path("data/make-krb5-conf");
@@ -186,7 +189,7 @@ main(void)
     for (i = 0; i < ARRAY_SIZE(principal_tests); i++)
         is_password_test(verifier, &principal_tests[i]);
 
-    /* Add character class restrictions. */
+    /* Add simple character class restrictions. */
     setup_argv[5] = (char *) "require_ascii_printable";
     setup_argv[6] = (char *) "true";
     setup_argv[7] = (char *) "require_non_letter";
@@ -194,15 +197,25 @@ main(void)
     setup_argv[9] = NULL;
     run_setup((const char **) setup_argv);
 
-    /* Run the character class tests. */
-    for (i = 0; i < ARRAY_SIZE(class_tests); i++)
-        is_password_test(verifier, &class_tests[i]);
+    /* Run the simple character class tests. */
+    for (i = 0; i < ARRAY_SIZE(letter_tests); i++)
+        is_password_test(verifier, &letter_tests[i]);
+
+    /* Add complex character class restrictions and remove the dictionary. */
+    free(setup_argv[4]);
+    setup_argv[3] = (char *) "require_classes";
+    setup_argv[4] = (char *) "8-19:lower,upper 8-15:digit 8-11:symbol";
+    setup_argv[5] = NULL;
+    run_setup((const char **) setup_argv);
+
+    /* Run the simple character class tests. */
+    for (i = 0; i < ARRAY_SIZE(classes_tests); i++)
+        is_password_test(verifier, &classes_tests[i]);
 
     /*
-     * Add length restrictions and remove the dictionary.  This should only do
-     * length checks without any dictionary checks.
+     * Add length restrictions.  This should only do length checks without any
+     * dictionary checks.
      */
-    free(setup_argv[4]);
     setup_argv[3] = (char *) "minimum_length";
     setup_argv[4] = (char *) "12";
     setup_argv[5] = NULL;
@@ -245,6 +258,10 @@ main(void)
     free(path);
     test_tmpdir_free(tmpdir);
 
+    /* Close down the module. */
+    if (dlclose(handle) != 0)
+        bail("cannot close plugin: %s", dlerror());
+
     /* Keep valgrind clean by freeing environmental memory. */
     putenv((char *) "KRB5_CONFIG=");
     free(krb5_config);
index 71a1c9864bebfdb56f0e33e8739a60ab4e655634..f2c02dd82cdc78f65d2e62eb9ad054bfbcad66b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Test for the MIT Kerberos shared module API.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2010, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
  * named cdb_tests, cracklib_tests, and principal_tests.
  */
 #include <tests/data/passwords/cdb.c>
-#include <tests/data/passwords/class.c>
+#include <tests/data/passwords/classes.c>
 #include <tests/data/passwords/cracklib.c>
 #include <tests/data/passwords/length.c>
+#include <tests/data/passwords/letter.c>
 #include <tests/data/passwords/principal.c>
 
 
@@ -59,13 +60,13 @@ typedef krb5_error_code pwqual_strength_initvt(krb5_context, int, int,
 /*
  * Loads the Heimdal password change plugin and tests that its metadata is
  * correct.  Returns a pointer to the kadm5_pw_policy_verifier struct or bails
- * on failure to load the plugin.
+ * on failure to load the plugin.  Stores the handle from dlopen in its second
+ * argument for a later clean shutdown.
  */
 static krb5_pwqual_vtable
-load_plugin(krb5_context ctx)
+load_plugin(krb5_context ctx, void **handle)
 {
     char *path;
-    void *handle;
     krb5_error_code code;
     krb5_pwqual_vtable vtable = NULL;
     krb5_error_code (*init)(krb5_context, int, int, krb5_plugin_vtable);
@@ -74,13 +75,13 @@ load_plugin(krb5_context ctx)
     path = test_file_path("../plugin/.libs/strength.so");
     if (path == NULL)
         bail("cannot find plugin");
-    handle = dlopen(path, RTLD_NOW);
-    if (handle == NULL)
+    *handle = dlopen(path, RTLD_NOW);
+    if (*handle == NULL)
         bail("cannot dlopen %s: %s", path, dlerror());
     test_file_path_free(path);
 
     /* Find the entry point function. */
-    init = dlsym(handle, "pwqual_strength_initvt");
+    init = dlsym(*handle, "pwqual_strength_initvt");
     if (init == NULL)
         bail("cannot get pwqual_strength_initvt symbol: %s", dlerror());
 
@@ -154,10 +155,11 @@ main(void)
     krb5_pwqual_vtable vtable;
     krb5_pwqual_moddata data;
     krb5_error_code code;
+    void *handle;
 
     /*
      * Calculate how many tests we have.  There are two tests for the module
-     * metadata, five more tests for initializing the plugin, and two tests per
+     * metadata, six more tests for initializing the plugin, and two tests per
      * password test.
      *
      * We run all the CrackLib tests twice, once with an explicit dictionary
@@ -166,10 +168,11 @@ main(void)
      */
     count = 2 * ARRAY_SIZE(cracklib_tests);
     count += ARRAY_SIZE(cdb_tests);
-    count += ARRAY_SIZE(class_tests);
+    count += ARRAY_SIZE(classes_tests);
     count += ARRAY_SIZE(length_tests);
+    count += ARRAY_SIZE(letter_tests);
     count += 2 * ARRAY_SIZE(principal_tests);
-    plan(2 + 5 + count * 2);
+    plan(2 + 6 + count * 2);
 
     /* Start with the krb5.conf that contains no dictionary configuration. */
     path = test_file_path("data/krb5.conf");
@@ -184,7 +187,7 @@ main(void)
         bail_krb5(ctx, code, "cannot initialize Kerberos context");
 
     /* Load the plugin. */
-    vtable = load_plugin(ctx);
+    vtable = load_plugin(ctx, &handle);
 
     /* Initialize the plugin with a CrackLib dictionary. */
     build = getenv("BUILD");
@@ -239,7 +242,7 @@ main(void)
         is_password_test(ctx, vtable, data, &cracklib_tests[i]);
     vtable->close(ctx, data);
 
-    /* Add character class configuration to krb5.conf. */
+    /* Add simple character class configuration to krb5.conf. */
     setup_argv[5] = (char *) "require_ascii_printable";
     setup_argv[6] = (char *) "true";
     setup_argv[7] = (char *) "require_non_letter";
@@ -253,18 +256,42 @@ main(void)
     if (code != 0)
         bail_krb5(ctx, code, "cannot initialize Kerberos context");
 
-    /* Run all the character class tests. */
+    /* Run all the simple character class tests. */
+    code = vtable->open(ctx, NULL, &data);
+    is_int(0, code, "Plugin initialization (simple character class)");
+    if (code != 0)
+        bail("cannot continue after plugin initialization failure");
+    for (i = 0; i < ARRAY_SIZE(letter_tests); i++)
+        is_password_test(ctx, vtable, data, &letter_tests[i]);
+    vtable->close(ctx, data);
+
+    /*
+     * Add complex character class configuration to krb5.conf but drop
+     * the dictionary configuration.
+     */
+    setup_argv[3] = (char *) "require_classes";
+    setup_argv[4] = (char *) "8-19:lower,upper 8-15:digit 8-11:symbol";
+    setup_argv[5] = NULL;
+    run_setup((const char **) setup_argv);
+
+    /* Obtain a new Kerberos context with that krb5.conf file. */
+    krb5_free_context(ctx);
+    code = krb5_init_context(&ctx);
+    if (code != 0)
+        bail_krb5(ctx, code, "cannot initialize Kerberos context");
+
+    /* Run all the complex character class tests. */
     code = vtable->open(ctx, NULL, &data);
-    is_int(0, code, "Plugin initialization (character class)");
+    is_int(0, code, "Plugin initialization (complex character class)");
     if (code != 0)
         bail("cannot continue after plugin initialization failure");
-    for (i = 0; i < ARRAY_SIZE(class_tests); i++)
-        is_password_test(ctx, vtable, data, &class_tests[i]);
+    for (i = 0; i < ARRAY_SIZE(classes_tests); i++)
+        is_password_test(ctx, vtable, data, &classes_tests[i]);
     vtable->close(ctx, data);
 
     /*
-     * Add length restrictions and remove the dictionary.  This should only do
-     * length checks without any dictionary checks.
+     * Add length restrictions.  This should only do length checks without any
+     * dictionary checks.
      */
     setup_argv[3] = (char *) "minimum_length";
     setup_argv[4] = (char *) "12";
@@ -289,7 +316,7 @@ main(void)
 #ifdef HAVE_CDB
 
     /* If built with CDB, set up krb5.conf to use a CDB dictionary instead. */
-    free(dictionary);
+    test_file_path_free(dictionary);
     dictionary = test_file_path("data/wordlist.cdb");
     if (dictionary == NULL)
         bail("cannot find data/wordlist.cdb in the test suite");
@@ -331,6 +358,10 @@ main(void)
     free(path);
     test_tmpdir_free(tmpdir);
 
+    /* Close down the module. */
+    if (dlclose(handle) != 0)
+        bail("cannot close plugin: %s", dlerror());
+
     /* Keep valgrind clean by freeing all memory. */
     test_file_path_free(dictionary);
     krb5_free_context(ctx);
index 4513a8592cd34387e7f601f069cdcf0896ad9c31..c61c14aef1415c8b42892cb87568bc73080cc3dd 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index 927de96070c5e65769cf96cbbd64398f140e6b0b..270d2e1831743b5366c66cf318ca7a38b317dddd 100644 (file)
@@ -4,9 +4,9 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
- *     Russ Allbery <rra@stanford.edu>
+ *     Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2010
  *     The Board of Trustees of the Leland Stanford Junior University
  * Copyright 1995 Patrick Powell
diff --git a/tests/portable/strndup-t.c b/tests/portable/strndup-t.c
new file mode 100644 (file)
index 0000000..0f923b7
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * strndup test suite.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#include <config.h>
+#include <portable/system.h>
+
+#include <errno.h>
+
+#include <tests/tap/basic.h>
+
+char *test_strndup(const char *, size_t);
+
+
+int
+main(void)
+{
+    char buffer[3];
+    char *result = NULL;
+
+    plan(7);
+
+    result = test_strndup("foo", 8);
+    is_string("foo", result, "strndup longer than string");
+    free(result);
+    result = test_strndup("foo", 2);
+    is_string("fo", result, "strndup shorter than string");
+    free(result);
+    result = test_strndup("foo", 3);
+    is_string("foo", result, "strndup same size as string");
+    free(result);
+    result = test_strndup("foo", 0);
+    is_string("", result, "strndup of size 0");
+    free(result);
+    memcpy(buffer, "foo", 3);
+    result = test_strndup(buffer, 3);
+    is_string("foo", result, "strndup of non-nul-terminated string");
+    free(result);
+    errno = 0;
+    result = test_strndup(NULL, 0);
+    is_string(NULL, result, "strndup of NULL");
+    is_int(errno, EINVAL, "...and returns EINVAL");
+
+    return 0;
+}
diff --git a/tests/portable/strndup.c b/tests/portable/strndup.c
new file mode 100644 (file)
index 0000000..99c3bc1
--- /dev/null
@@ -0,0 +1,2 @@
+#define TESTING 1
+#include <portable/strndup.c>
index 5518c39b8204bb8b19899ca4bc19e824cc8fff89..2b7959bfc854d9751774b1d4d7c58966ea900904 100644 (file)
@@ -55,7 +55,7 @@
  * Harness <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
  *
  * Copyright 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010, 2011
- *     Russ Allbery <rra@stanford.edu>
+ *     Russ Allbery <eagle@eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -87,6 +87,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 /* AIX doesn't have WCOREDUMP. */
 #ifndef WCOREDUMP
-# define WCOREDUMP(status)      ((unsigned)(status) & 0x80)
+# define WCOREDUMP(status) ((unsigned)(status) & 0x80)
 #endif
 
 /*
@@ -173,14 +174,16 @@ struct testlist {
 };
 
 /*
- * Usage message.  Should be used as a printf format with two arguments: the
- * path to runtests, given twice.
+ * Usage message.  Should be used as a printf format with four arguments: the
+ * path to runtests, given three times, and the usage_description.  This is
+ * split into variables to satisfy the pedantic ISO C90 limit on strings.
  */
 static const char usage_message[] = "\
 Usage: %s [-b <build-dir>] [-s <source-dir>] <test> ...\n\
        %s [-b <build-dir>] [-s <source-dir>] -l <test-list>\n\
        %s -o [-b <build-dir>] [-s <source-dir>] <test>\n\
-\n\
+\n%s";
+static const char usage_extra[] = "\
 Options:\n\
     -b <build-dir>      Set the build directory to <build-dir>\n\
     -l <list>           Take the list of tests to run from <test-list>\n\
@@ -1310,7 +1313,7 @@ main(int argc, char *argv[])
             build = optarg;
             break;
         case 'h':
-            printf(usage_message, argv[0], argv[0], argv[0]);
+            printf(usage_message, argv[0], argv[0], argv[0], usage_extra);
             exit(0);
             break;
         case 'l':
@@ -1329,7 +1332,7 @@ main(int argc, char *argv[])
     argv += optind;
     argc -= optind;
     if ((list == NULL && argc < 1) || (list != NULL && argc > 0)) {
-        fprintf(stderr, usage_message, argv[0], argv[0], argv[0]);
+        fprintf(stderr, usage_message, argv[0], argv[0], argv[0], usage_extra);
         exit(1);
     }
 
index 35350c88d001da346458a9fd04190ac614e9ffd7..bb51606b639b08350820bad6936386437b713c01 100644 (file)
@@ -12,7 +12,7 @@
  * This file is part of C TAP Harness.  The current version plus supporting
  * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
  *
- * Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010, 2011, 2012, 2013 Russ Allbery <eagle@eyrie.org>
  * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
@@ -58,7 +58,7 @@
 
 /*
  * The test count.  Always contains the number that will be used for the next
- * test status.
+ * test status.  This is exported to callers of the library.
  */
 unsigned long testnum = 1;
 
@@ -66,53 +66,133 @@ unsigned long testnum = 1;
  * Status information stored so that we can give a test summary at the end of
  * the test case.  We store the planned final test and the count of failures.
  * We can get the highest test count from testnum.
- *
- * We also store the PID of the process that called plan() and only summarize
- * results when that process exits, so as to not misreport results in forked
- * processes.
- *
- * If _lazy is true, we're doing lazy planning and will print out the plan
- * based on the last test number at the end of testing.
  */
 static unsigned long _planned = 0;
 static unsigned long _failed  = 0;
+
+/*
+ * Store the PID of the process that called plan() and only summarize
+ * results when that process exits, so as to not misreport results in forked
+ * processes.
+ */
 static pid_t _process = 0;
+
+/*
+ * If true, we're doing lazy planning and will print out the plan based on the
+ * last test number at the end of testing.
+ */
 static int _lazy = 0;
 
+/*
+ * If true, the test was aborted by calling bail().  Currently, this is only
+ * used to ensure that we pass a false value to any cleanup functions even if
+ * all tests to that point have passed.
+ */
+static int _aborted = 0;
+
+/*
+ * Registered cleanup functions.  These are stored as a linked list and run in
+ * registered order by finish when the test program exits.  Each function is
+ * passed a boolean value indicating whether all tests were successful.
+ */
+struct cleanup_func {
+    test_cleanup_func func;
+    struct cleanup_func *next;
+};
+static struct cleanup_func *cleanup_funcs = NULL;
+
+/*
+ * Print a specified prefix and then the test description.  Handles turning
+ * the argument list into a va_args structure suitable for passing to
+ * print_desc, which has to be done in a macro.  Assumes that format is the
+ * argument immediately before the variadic arguments.
+ */
+#define PRINT_DESC(prefix, format)              \
+    do {                                        \
+        if (format != NULL) {                   \
+            va_list args;                       \
+            if (prefix != NULL)                 \
+                printf("%s", prefix);           \
+            va_start(args, format);             \
+            vprintf(format, args);              \
+            va_end(args);                       \
+        }                                       \
+    } while (0)
+
 
 /*
  * Our exit handler.  Called on completion of the test to report a summary of
  * results provided we're still in the original process.  This also handles
  * printing out the plan if we used plan_lazy(), although that's suppressed if
- * we never ran a test (due to an early bail, for example).
+ * we never ran a test (due to an early bail, for example), and running any
+ * registered cleanup functions.
  */
 static void
 finish(void)
 {
+    int success;
+    struct cleanup_func *current;
     unsigned long highest = testnum - 1;
 
-    if (_planned == 0 && !_lazy)
-        return;
-    fflush(stderr);
-    if (_process != 0 && getpid() == _process) {
-        if (_lazy && highest > 0) {
-            printf("1..%lu\n", highest);
-            _planned = highest;
+    /*
+     * Don't do anything except free the cleanup functions if we aren't the
+     * primary process (the process in which plan or plan_lazy was called).
+     */
+    if (_process != 0 && getpid() != _process) {
+        while (cleanup_funcs != NULL) {
+            current = cleanup_funcs;
+            cleanup_funcs = cleanup_funcs->next;
+            free(current);
         }
-        if (_planned > highest)
-            printf("# Looks like you planned %lu test%s but only ran %lu\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest);
-        else if (_planned < highest)
-            printf("# Looks like you planned %lu test%s but ran %lu extra\n",
-                   _planned, (_planned > 1 ? "s" : ""), highest - _planned);
-        else if (_failed > 0)
-            printf("# Looks like you failed %lu test%s of %lu\n", _failed,
-                   (_failed > 1 ? "s" : ""), _planned);
-        else if (_planned > 1)
-            printf("# All %lu tests successful or skipped\n", _planned);
-        else
-            printf("# %lu test successful or skipped\n", _planned);
+        return;
     }
+
+    /*
+     * Determine whether all tests were successful, which is needed before
+     * calling cleanup functions since we pass that fact to the functions.
+     */
+    if (_planned == 0 && _lazy)
+        _planned = highest;
+    success = (!_aborted && _planned == highest && _failed == 0);
+
+    /*
+     * If there are any registered cleanup functions, we run those first.  We
+     * always run them, even if we didn't run a test.
+     */
+    while (cleanup_funcs != NULL) {
+        cleanup_funcs->func(success);
+        current = cleanup_funcs;
+        cleanup_funcs = cleanup_funcs->next;
+        free(current);
+    }
+
+    /* Don't do anything further if we never planned a test. */
+    if (_planned == 0)
+        return;
+
+    /* If we're aborting due to bail, don't print summaries. */
+    if (_aborted)
+        return;
+
+    /* Print out the lazy plan if needed. */
+    fflush(stderr);
+    if (_lazy && _planned > 0)
+        printf("1..%lu\n", _planned);
+
+    /* Print out a summary of the results. */
+    if (_planned > highest)
+        diag("Looks like you planned %lu test%s but only ran %lu", _planned,
+             (_planned > 1 ? "s" : ""), highest);
+    else if (_planned < highest)
+        diag("Looks like you planned %lu test%s but ran %lu extra", _planned,
+             (_planned > 1 ? "s" : ""), highest - _planned);
+    else if (_failed > 0)
+        diag("Looks like you failed %lu test%s of %lu", _failed,
+             (_failed > 1 ? "s" : ""), _planned);
+    else if (_planned != 1)
+        diag("All %lu tests successful or skipped", _planned);
+    else
+        diag("%lu test successful or skipped", _planned);
 }
 
 
@@ -124,14 +204,16 @@ void
 plan(unsigned long count)
 {
     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
-        fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
-                strerror(errno));
+        sysdiag("cannot set stdout to line buffered");
     fflush(stderr);
     printf("1..%lu\n", count);
     testnum = 1;
     _planned = count;
     _process = getpid();
-    atexit(finish);
+    if (atexit(finish) != 0) {
+        sysdiag("cannot register exit handler");
+        diag("cleanups will not be run");
+    }
 }
 
 
@@ -143,12 +225,12 @@ void
 plan_lazy(void)
 {
     if (setvbuf(stdout, NULL, _IOLBF, BUFSIZ) != 0)
-        fprintf(stderr, "# cannot set stdout to line buffered: %s\n",
-                strerror(errno));
+        sysdiag("cannot set stdout to line buffered");
     testnum = 1;
     _process = getpid();
     _lazy = 1;
-    atexit(finish);
+    if (atexit(finish) != 0)
+        sysbail("cannot register exit handler to display plan");
 }
 
 
@@ -161,30 +243,12 @@ skip_all(const char *format, ...)
 {
     fflush(stderr);
     printf("1..0 # skip");
-    if (format != NULL) {
-        va_list args;
-
-        putchar(' ');
-        va_start(args, format);
-        vprintf(format, args);
-        va_end(args);
-    }
+    PRINT_DESC(" ", format);
     putchar('\n');
     exit(0);
 }
 
 
-/*
- * Print the test description.
- */
-static void
-print_desc(const char *format, va_list args)
-{
-    printf(" - ");
-    vprintf(format, args);
-}
-
-
 /*
  * Takes a boolean success value and assumes the test passes if that value
  * is true and fails if that value is false.
@@ -196,13 +260,7 @@ ok(int success, const char *format, ...)
     printf("%sok %lu", success ? "" : "not ", testnum++);
     if (!success)
         _failed++;
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
+    PRINT_DESC(" - ", format);
     putchar('\n');
 }
 
@@ -217,8 +275,10 @@ okv(int success, const char *format, va_list args)
     printf("%sok %lu", success ? "" : "not ", testnum++);
     if (!success)
         _failed++;
-    if (format != NULL)
-        print_desc(format, args);
+    if (format != NULL) {
+        printf(" - ");
+        vprintf(format, args);
+    }
     putchar('\n');
 }
 
@@ -231,14 +291,7 @@ skip(const char *reason, ...)
 {
     fflush(stderr);
     printf("ok %lu # skip", testnum++);
-    if (reason != NULL) {
-        va_list args;
-
-        va_start(args, reason);
-        putchar(' ');
-        vprintf(reason, args);
-        va_end(args);
-    }
+    PRINT_DESC(" ", reason);
     putchar('\n');
 }
 
@@ -256,13 +309,7 @@ ok_block(unsigned long count, int status, const char *format, ...)
         printf("%sok %lu", status ? "" : "not ", testnum++);
         if (!status)
             _failed++;
-        if (format != NULL) {
-            va_list args;
-
-            va_start(args, format);
-            print_desc(format, args);
-            va_end(args);
-        }
+        PRINT_DESC(" - ", format);
         putchar('\n');
     }
 }
@@ -279,14 +326,7 @@ skip_block(unsigned long count, const char *reason, ...)
     fflush(stderr);
     for (i = 0; i < count; i++) {
         printf("ok %lu # skip", testnum++);
-        if (reason != NULL) {
-            va_list args;
-
-            va_start(args, reason);
-            putchar(' ');
-            vprintf(reason, args);
-            va_end(args);
-        }
+        PRINT_DESC(" ", reason);
         putchar('\n');
     }
 }
@@ -303,17 +343,12 @@ is_int(long wanted, long seen, const char *format, ...)
     if (wanted == seen)
         printf("ok %lu", testnum++);
     else {
-        printf("# wanted: %ld\n#   seen: %ld\n", wanted, seen);
+        diag("wanted: %ld", wanted);
+        diag("  seen: %ld", seen);
         printf("not ok %lu", testnum++);
         _failed++;
     }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
+    PRINT_DESC(" - ", format);
     putchar('\n');
 }
 
@@ -333,17 +368,12 @@ is_string(const char *wanted, const char *seen, const char *format, ...)
     if (strcmp(wanted, seen) == 0)
         printf("ok %lu", testnum++);
     else {
-        printf("# wanted: %s\n#   seen: %s\n", wanted, seen);
+        diag("wanted: %s", wanted);
+        diag("  seen: %s", seen);
         printf("not ok %lu", testnum++);
         _failed++;
     }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
+    PRINT_DESC(" - ", format);
     putchar('\n');
 }
 
@@ -359,18 +389,12 @@ is_hex(unsigned long wanted, unsigned long seen, const char *format, ...)
     if (wanted == seen)
         printf("ok %lu", testnum++);
     else {
-        printf("# wanted: %lx\n#   seen: %lx\n", (unsigned long) wanted,
-               (unsigned long) seen);
+        diag("wanted: %lx", (unsigned long) wanted);
+        diag("  seen: %lx", (unsigned long) seen);
         printf("not ok %lu", testnum++);
         _failed++;
     }
-    if (format != NULL) {
-        va_list args;
-
-        va_start(args, format);
-        print_desc(format, args);
-        va_end(args);
-    }
+    PRINT_DESC(" - ", format);
     putchar('\n');
 }
 
@@ -383,6 +407,7 @@ bail(const char *format, ...)
 {
     va_list args;
 
+    _aborted = 1;
     fflush(stderr);
     fflush(stdout);
     printf("Bail out! ");
@@ -403,6 +428,7 @@ sysbail(const char *format, ...)
     va_list args;
     int oerrno = errno;
 
+    _aborted = 1;
     fflush(stderr);
     fflush(stdout);
     printf("Bail out! ");
@@ -627,3 +653,22 @@ test_tmpdir_free(char *path)
     if (path != NULL)
         free(path);
 }
+
+
+/*
+ * Register a cleanup function that is called when testing ends.  All such
+ * registered functions will be run by finish.
+ */
+void
+test_cleanup_register(test_cleanup_func func)
+{
+    struct cleanup_func *cleanup, **last;
+
+    cleanup = bmalloc(sizeof(struct cleanup_func));
+    cleanup->func = func;
+    cleanup->next = NULL;
+    last = &cleanup_funcs;
+    while (*last != NULL)
+        last = &(*last)->next;
+    *last = cleanup;
+}
index fa4adafe292e43b4fd5d27ee13d4a0544ae33f06..92d348a15a0c6af752e66d796b0cd57e331a44ad 100644 (file)
@@ -4,7 +4,7 @@
  * This file is part of C TAP Harness.  The current version plus supporting
  * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
  *
- * Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2009, 2010, 2011, 2012, 2013 Russ Allbery <eagle@eyrie.org>
  * Copyright 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2011, 2012
  *     The Board of Trustees of the Leland Stanford Junior University
  *
@@ -32,7 +32,7 @@
 
 #include <tests/tap/macros.h>
 #include <stdarg.h>             /* va_list */
-#include <sys/types.h>          /* size_t */
+#include <stddef.h>             /* size_t */
 
 /*
  * Used for iterating through arrays.  ARRAY_SIZE returns the number of
@@ -55,7 +55,7 @@ extern unsigned long testnum;
 void plan(unsigned long count);
 
 /*
- * Prepare for lazy planning, in which the plan will be  printed automatically
+ * Prepare for lazy planning, in which the plan will be printed automatically
  * at the end of the test program.
  */
 void plan_lazy(void);
@@ -103,22 +103,22 @@ void sysdiag(const char *format, ...)
 
 /* Allocate memory, reporting a fatal error with bail on failure. */
 void *bcalloc(size_t, size_t)
-    __attribute__((__alloc_size__(1, 2), __malloc__));
+    __attribute__((__alloc_size__(1, 2), __malloc__, __warn_unused_result__));
 void *bmalloc(size_t)
-    __attribute__((__alloc_size__(1), __malloc__));
+    __attribute__((__alloc_size__(1), __malloc__, __warn_unused_result__));
 void *brealloc(void *, size_t)
-    __attribute__((__alloc_size__(2), __malloc__));
+    __attribute__((__alloc_size__(2), __malloc__, __warn_unused_result__));
 char *bstrdup(const char *)
-    __attribute__((__malloc__, __nonnull__));
+    __attribute__((__malloc__, __nonnull__, __warn_unused_result__));
 char *bstrndup(const char *, size_t)
-    __attribute__((__malloc__, __nonnull__));
+    __attribute__((__malloc__, __nonnull__, __warn_unused_result__));
 
 /*
  * Find a test file under BUILD or SOURCE, returning the full path.  The
  * returned path should be freed with test_file_path_free().
  */
 char *test_file_path(const char *file)
-    __attribute__((__malloc__, __nonnull__));
+    __attribute__((__malloc__, __nonnull__, __warn_unused_result__));
 void test_file_path_free(char *path);
 
 /*
@@ -126,9 +126,20 @@ void test_file_path_free(char *path);
  * returned path should be freed with test_tmpdir_free.
  */
 char *test_tmpdir(void)
-    __attribute__((__malloc__));
+    __attribute__((__malloc__, __warn_unused_result__));
 void test_tmpdir_free(char *path);
 
+/*
+ * Register a cleanup function that is called when testing ends.  All such
+ * registered functions will be run during atexit handling (and are therefore
+ * subject to all the same constraints and caveats as atexit functions).  The
+ * function must return void and will be passed one argument, an int that will
+ * be true if the test completed successfully and false otherwise.
+ */
+typedef void (*test_cleanup_func)(int);
+void test_cleanup_register(test_cleanup_func)
+    __attribute__((__nonnull__));
+
 END_DECLS
 
 #endif /* TAP_BASIC_H */
index 474cf4fb0d8efda81adfba22d61ac31475a74872..58315ee2ca9c302d050134c0dbb99661163af761 100644 (file)
@@ -14,8 +14,8 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2006, 2007, 2009, 2010, 2011, 2012
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2006, 2007, 2009, 2010, 2011, 2012, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -38,7 +38,7 @@
  */
 
 #include <config.h>
-#ifdef HAVE_KERBEROS
+#ifdef HAVE_KRB5
 # include <portable/krb5.h>
 #endif
 #include <portable/system.h>
@@ -79,7 +79,7 @@ static char *tmpdir_conf = NULL;
  * Kerberos libraries available and one if we don't.  Uses keytab to obtain
  * credentials, and fills in the cache member of the provided config struct.
  */
-#ifdef HAVE_KERBEROS
+#ifdef HAVE_KRB5
 
 static void
 kerberos_kinit(void)
@@ -147,7 +147,7 @@ kerberos_kinit(void)
     free(krbtgt);
 }
 
-#else /* !HAVE_KERBEROS */
+#else /* !HAVE_KRB5 */
 
 static void
 kerberos_kinit(void)
@@ -197,7 +197,7 @@ kerberos_kinit(void)
         bail("cannot get Kerberos tickets");
 }
 
-#endif /* !HAVE_KERBEROS */
+#endif /* !HAVE_KRB5 */
 
 
 /*
@@ -401,7 +401,7 @@ kerberos_generate_conf(const char *realm)
  * The remaining functions in this file are only available if Kerberos
  * libraries are available.
  */
-#ifdef HAVE_KERBEROS
+#ifdef HAVE_KRB5
 
 
 /*
@@ -485,4 +485,4 @@ kerberos_keytab_principal(krb5_context ctx, const char *path)
     return princ;
 }
 
-#endif /* HAVE_KERBEROS */
+#endif /* HAVE_KRB5 */
index 8ce0da9f204558760b1a3e8356336241a38741ad..c34f891005e2e5775f2d9ed41ae14ae93d76ab68 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2009, 2011, 2012, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
@@ -33,7 +33,7 @@
 #include <config.h>
 #include <tests/tap/macros.h>
 
-#ifdef HAVE_KERBEROS
+#ifdef HAVE_KRB5
 # include <portable/krb5.h>
 #endif
 
@@ -100,7 +100,7 @@ void kerberos_generate_conf(const char *realm);
 void kerberos_cleanup_conf(void);
 
 /* Thes interfaces are only available with native Kerberos support. */
-#ifdef HAVE_KERBEROS
+#ifdef HAVE_KRB5
 
 /* Bail out with an error, appending the Kerberos error message. */
 void bail_krb5(krb5_context, krb5_error_code, const char *format, ...)
@@ -118,7 +118,7 @@ void diag_krb5(krb5_context, krb5_error_code, const char *format, ...)
 krb5_principal kerberos_keytab_principal(krb5_context, const char *path)
     __attribute__((__nonnull__));
 
-#endif /* HAVE_KERBEROS */
+#endif /* HAVE_KRB5 */
 
 END_DECLS
 
index 0ffab2d238c50d8cf06d1e96fac46171b890f363..9731032addeb85b2770248d7725ca07a0d6cdeeb 100644 (file)
@@ -9,8 +9,8 @@
 # writing test cases.  It is part of C TAP Harness, which can be found at
 # <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2009, 2010, 2011, 2012 Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
+# Copyright 2009, 2010, 2011, 2012 Russ Allbery <eagle@eyrie.org>
 # Copyright 2006, 2007, 2008, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index 33fee42d9d2fa8d0241b23dcc5d3bbb280039e15..04cc420ddc76b7b08cd89fc00693251d8b9362d5 100644 (file)
@@ -8,7 +8,7 @@
  * This file is part of C TAP Harness.  The current version plus supporting
  * documentation is at <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
  *
- * Copyright 2008, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2008, 2012, 2013 Russ Allbery <eagle@eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 # endif
 #endif
 
+/* Suppress __warn_unused_result__ if gcc is too old. */
+#if !defined(__attribute__) && !defined(__warn_unused_result__)
+# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+#  define __warn_unused_result__ /* empty */
+# endif
+#endif
+
 /*
  * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
  * settings that GCC does.  For them, suppress warnings about unknown
index c4560ddcdbbfc3c2a94530c30bb7d5834103c1c8..b252250e6a0623eb32a2bec5919ce8c36db0b761 100644 (file)
@@ -9,7 +9,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -56,7 +56,7 @@ BEGIN {
     # This version should match the corresponding rra-c-util release, but with
     # two digits for the minor version, including a leading zero if necessary,
     # so that it will sort properly.
-    $VERSION = '4.09';
+    $VERSION = '4.12';
 }
 
 # Skip this test unless maintainer tests are requested.  Takes a short
@@ -149,7 +149,7 @@ Test::RRA - Support functions for Perl tests
     skip_unless_maintainer('Coding style tests');
 
     # Load modules, skipping the test if they're not available.
-    use_prereq('File::Slurp');
+    use_prereq('Perl6::Slurp', 'slurp');
     use_prereq('Test::Script::Run', '0.04');
 
 =head1 DESCRIPTION
@@ -188,7 +188,7 @@ value of an array.
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 5a0f4e8a2df1753da20a204b7fcf69851324e490..b8ce0958b02c16e2a21968bf43b686221f5f0416 100644 (file)
@@ -13,7 +13,7 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -82,12 +82,12 @@ our (@EXPORT_OK, @ISA, $VERSION);
 # consistency is good).
 BEGIN {
     @ISA       = qw(Exporter);
-    @EXPORT_OK = qw(automake_setup perl_dirs test_file_path);
+    @EXPORT_OK = qw(automake_setup perl_dirs test_file_path test_tmpdir);
 
     # This version should match the corresponding rra-c-util release, but with
     # two digits for the minor version, including a leading zero if necessary,
     # so that it will sort properly.
-    $VERSION = '4.09';
+    $VERSION = '4.12';
 }
 
 # Perl directories to skip globally for perl_dirs.  We ignore the perl
@@ -95,6 +95,11 @@ BEGIN {
 # distribution and has its own standalone test suite.
 my @GLOBAL_SKIP = qw(.git perl);
 
+# The temporary directory created by test_tmpdir, if any.  If this is set,
+# attempt to remove the directory stored here on program exit (but ignore
+# failure to do so).
+my $TMPDIR;
+
 # Perform initial test setup for running a Perl test in an Automake package.
 # This verifies that BUILD and SOURCE are set and then changes directory to
 # the SOURCE directory by default.  Sets LD_LIBRARY_PATH if the $LIBRARY_PATH
@@ -238,12 +243,53 @@ sub test_file_path {
     return;
 }
 
+# Create a temporary directory for tests to use for transient files and return
+# the path to that directory.  The directory is automatically removed on
+# program exit.  The directory permissions use the current umask.  Calls
+# BAIL_OUT if the directory could not be created.
+#
+# Returns: Path to a writable temporary directory
+sub test_tmpdir {
+    my $path;
+
+    # If we already figured out what directory to use, reuse the same path.
+    # Otherwise, create a directory relative to BUILD if set.
+    if (defined($TMPDIR)) {
+        $path = $TMPDIR;
+    } else {
+        my $base = defined($ENV{BUILD}) ? $ENV{BUILD} : File::Spec->curdir;
+        $path = File::Spec->catdir($base, 'tmp');
+    }
+
+    # Create the directory if it doesn't exist.
+    if (!-d $path) {
+        if (!mkdir($path, 0777)) {
+            BAIL_OUT("cannot create directory $path: $!");
+        }
+    }
+
+    # Store the directory name for cleanup and return it.
+    $TMPDIR = $path;
+    return $path;
+}
+
+# On program exit, remove $TMPDIR if set and if possible.  Report errors with
+# diag but otherwise ignore them.
+END {
+    if (defined($TMPDIR) && -d $TMPDIR) {
+        local $! = undef;
+        if (!rmdir($TMPDIR)) {
+            diag("cannot remove temporary directory $TMPDIR: $!");
+        }
+    }
+}
+
 1;
 __END__
 
 =for stopwords
 Allbery Automake Automake-aware Automake-based rra-c-util ARGS
-subdirectories sublicense MERCHANTABILITY NONINFRINGEMENT
+subdirectories sublicense MERCHANTABILITY NONINFRINGEMENT umask
 
 =head1 NAME
 
@@ -320,11 +366,24 @@ checked for relative to the environment variable BUILD first, and then
 relative to SOURCE.  test_file_path() returns the full path to FILE or
 calls BAIL_OUT if FILE could not be found.
 
+=item test_tmpdir()
+
+Create a temporary directory for tests to use for transient files and
+return the path to that directory.  The directory is created relative to
+the BUILD environment variable, which must be set.  Permissions on the
+directory are set using the current umask.  test_tmpdir() returns the full
+path to the temporary directory or calls BAIL_OUT if it could not be
+created.
+
+The directory is automatically removed if possible on program exit.
+Failure to remove the directory on exit is reported with diag() and
+otherwise ignored.
+
 =back
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 21c2f20c0eac2d6d3fda4d775b386bb7960a897e..106cc6eed3e21361fe52389c8ed1929cba3a14d7 100644 (file)
@@ -36,7 +36,7 @@ BEGIN {
     # This version should match the corresponding rra-c-util release, but with
     # two digits for the minor version, including a leading zero if necessary,
     # so that it will sort properly.
-    $VERSION = '4.09';
+    $VERSION = '4.12';
 }
 
 # If BUILD or SOURCE are set in the environment, look for data/perl.conf under
@@ -131,7 +131,7 @@ directory names starting with F<tests/>.
 
 =item $LIBRARY_PATH
 
-Add this directory (or a .libs subdirectory) relative to the top of the
+Add this directory (or a F<.libs> subdirectory) relative to the top of the
 source tree to LD_LIBRARY_PATH when checking the syntax of Perl modules.
 This may be required to pick up libraries that are used by in-tree Perl
 modules so that Perl scripts can pass a syntax check.
@@ -170,7 +170,7 @@ into the local namespace to avoid long variable names.
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 8ed4cfd0b33de46f2a73a4361f389820a0f3b667..b8d6ff96dce2c5d9dbdf19be3a389c5b3a7ccdfb 100644 (file)
@@ -10,9 +10,9 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
- * Copyright 2009, 2010, 2011
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2002, 2004, 2005 Russ Allbery <eagle@eyrie.org>
+ * Copyright 2009, 2010, 2011, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -171,7 +171,10 @@ run_setup(const char *const argv[])
         p = strchr(output, '\n');
         if (p != NULL)
             *p = '\0';
-        bail("%s", output);
+        if (output[0] != '\0')
+            bail("%s", output);
+        else
+            bail("setup command failed with no output");
     }
     free(output);
 }
index df74b5feed5d1f110707c1e76758d619f7be2d0f..ed903451c00ede6be9b1c65f456b3b6d5df1a062 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2010
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index f5c965cb17989152deab74b69aa4a30588021e09..6ed7e68dc7c3f4b162de7e6dacf4c359c2df49a7 100644 (file)
@@ -7,7 +7,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2011, 2012 Russ Allbery <eagle@eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
index 2f699e4459fcfcfc77accc54c9317936aec007f3..cc51945da6f27d06c25a292d18a9fb4afd82b6c3 100644 (file)
@@ -7,7 +7,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2011, 2012 Russ Allbery <rra@stanford.edu>
+ * Copyright 2011, 2012 Russ Allbery <eagle@eyrie.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
index 2ff6612eeba877bbbcc622a98906556cfc015369..08d8d91eaddb62aa63f3826f13f48e016544ebfa 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # Test suite for the cdbmake-wordlist utility.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -17,7 +17,7 @@ if ! command -v cdb >/dev/null 2>&1 ; then
 fi
 
 # Output the test plan.
-plan 11
+plan 20
 
 # Create a temporary directory and wordlist and ensure it's writable.
 tmpdir=`test_tmpdir`
@@ -61,6 +61,32 @@ ok_program 'Database still contains password' 0 '1' \
 ok_program 'Database does not contain non-ASCII password' 100 '' \
     cdb -q "$tmpdir/wordlist.cdb" 'عربى'
 
+# Regenerate the database, filtering out long passwords.
+ok_program 'Database generation with no long passwords' 0 '' \
+    "$cdbmake" -L 10 "$tmpdir/wordlist"
+ok_program 'Database still contains bitterbane' 0 '1' \
+    cdb -q "$tmpdir/wordlist.cdb" bitterbane
+ok_program 'Database does not contain happenstance' 100 '' \
+    cdb -q "$tmpdir/wordlist.cdb" happenstance
+
+# Regenerate the database, filtering out words starting with b or ending in d.
+ok_program 'Database generation with no b passwords' 0 '' \
+    "$cdbmake" -x '\Ab' -x '.*d' "$tmpdir/wordlist"
+ok_program 'Database does not contain bitterbane' 100 '' \
+    cdb -q "$tmpdir/wordlist.cdb" bitterbane
+ok_program 'Database still contains happenstance' 0 '1' \
+    cdb -q "$tmpdir/wordlist.cdb" happenstance
+ok_program 'Database does not contain password' 100 '' \
+    cdb -q "$tmpdir/wordlist.cdb" password
+
+# Try filtering the wordlist into a new wordlist.
+ok_program 'Wordlist filtering' 0 '' \
+    "$cdbmake" -a -x '.*d' -l 8 -o "$tmpdir/wordlist.new" "$tmpdir/wordlist"
+( echo 'bitterbane'; echo 'happenstance' ) > "$tmpdir/wordlist.expected"
+ok_program 'Filtered wordlist is correct' 0 '' \
+    cmp "$tmpdir/wordlist.expected" "$tmpdir/wordlist.new"
+rm -f "$tmpdir/wordlist.expected" "$tmpdir/wordlist.new"
+
 # Clean up.
 rm -f "$tmpdir/wordlist.cdb"
 rm -f "$tmpdir/wordlist"
index 1c25c8359785132ccb72ee99bc3cc2d3067bd597..8a70bade35879f600fa050d37af75501fb8a03e1 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # Test suite for basic Heimdal external strength checking functionality.
 #
-# Written by Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
 # Copyright 2009, 2012, 2013
 #     The Board of Trustees of the Leland Stanford Junior University
 #
@@ -18,10 +18,10 @@ use File::Copy qw(copy);
 use Test::RRA qw(use_prereq);
 use Test::RRA::Automake qw(test_file_path);
 
-use_prereq('File::Slurp');
 use_prereq('IPC::Run', 'run');
 use_prereq('JSON');
-use_prereq('Test::More', '0.87_01');
+use_prereq('Perl6::Slurp', 'slurp');
+use_prereq('Test::More',   '0.87_01');
 
 # Run the newly-built heimdal-strength command and return the status, output,
 # and error output as a list.
@@ -43,8 +43,7 @@ sub run_heimdal_strength {
     my $program = test_file_path('../tools/heimdal-strength');
 
     # Run the password strength checker.
-    my $out;
-    my $err;
+    my ($out, $err);
     run([$program, $principal], \$in, \$out, \$err);
     my $status = ($? >> 8);
 
@@ -140,7 +139,7 @@ sub load_password_tests {
     my $path = test_file_path("data/passwords/$file");
 
     # Load the test file data into memory.
-    my $testdata = read_file($path);
+    my $testdata = slurp($path);
 
     # Decode the JSON into Perl objects and return them.
     my $json = JSON->new->utf8;
@@ -150,7 +149,7 @@ sub load_password_tests {
 # Load the password tests from JSON.  Accumulate a total count of tests for
 # the testing plan.
 my (%tests, $count);
-for my $type (qw(cdb class cracklib length principal)) {
+for my $type (qw(cdb classes cracklib length letter principal)) {
     my $tests = load_password_tests("$type.json");
     $tests{$type} = $tests;
     $count += scalar(@{$tests});
@@ -159,8 +158,9 @@ for my $type (qw(cdb class cracklib length principal)) {
 # We run the principal tests twice, once for CrackLib and once for CDB.
 $count += scalar(@{ $tests{principal} });
 
-# We can now calculate our plan based on three tests for each password test.
-plan(tests => $count * 3);
+# We can now calculate our plan based on three tests for each password test,
+# plus 21 additional tests for error handling.
+plan(tests => $count * 3 + 21);
 
 # Install the krb5.conf file with a configuration pointing to the test
 # CrackLib dictionary.
@@ -189,7 +189,7 @@ for my $test (@{ $tests{length} }) {
     check_password($test);
 }
 
-# Install the krb5.conf file for character class restrictions.
+# Install the krb5.conf file for simple character class restrictions.
 $krb5_conf = create_krb5_conf(
     {
         require_ascii_printable => 'true',
@@ -198,9 +198,20 @@ $krb5_conf = create_krb5_conf(
 );
 local $ENV{KRB5_CONFIG} = $krb5_conf;
 
-# Run the character class tests.
-note('Password character class checks');
-for my $test (@{ $tests{class} }) {
+# Run the simple character class tests.
+note('Simple password character class checks');
+for my $test (@{ $tests{letter} }) {
+    check_password($test);
+}
+
+# Install the krb5.conf file for complex character class restrictions.
+my $classes = '8-19:lower,upper 8-15:digit 8-11:symbol';
+$krb5_conf = create_krb5_conf({ require_classes => $classes });
+local $ENV{KRB5_CONFIG} = $krb5_conf;
+
+# Run the complex character class tests.
+note('Complex password character class checks');
+for my $test (@{ $tests{classes} }) {
     check_password($test);
 }
 
@@ -229,6 +240,29 @@ SKIP: {
     }
 }
 
+# Test error for an unknown character class.
+$krb5_conf = create_krb5_conf({ require_classes => 'bogus' });
+local $ENV{KRB5_CONFIG} = $krb5_conf;
+my $error_prefix = 'Cannot initialize strength checking';
+($status, $output, $err) = run_heimdal_strength('test', 'password');
+is($status, 1,   'Bad character class (status)');
+is($output, q{}, '...no output');
+is($err, "$error_prefix: unknown character class bogus\n", '...correct error');
+
+# Test a variety of configuration syntax errors in require_classes.
+my @bad_classes = qw(
+  8 8bogus 8:bogus 4-:bogus 4-bogus 4-8bogus
+);
+my $bad_message = 'bad character class requirement in configuration';
+for my $bad_class (@bad_classes) {
+    $krb5_conf = create_krb5_conf({ require_classes => $bad_class });
+    local $ENV{KRB5_CONFIG} = $krb5_conf;
+    ($status, $output, $err) = run_heimdal_strength('test', 'password');
+    is($status, 1,   "Bad class specification '$bad_class' (status)");
+    is($output, q{}, '...no output');
+    is($err, "$error_prefix: $bad_message: $bad_class\n", '...correct error');
+}
+
 # Clean up our temporary krb5.conf file on any exit.
 END {
     my $tmpdir = $ENV{BUILD} ? "$ENV{BUILD}/tmp" : 'tests/tmp';
index 35a4632484685b2c6a4ebd8fd543dbcdbc4d65b5..8015c4e62943f952667f0923f0d8525a99a9a873 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2010, 2011, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index 54f1cf1bb4806d8a2d9ba515980687b1177e1f9b..f60fa6a9698af051b0977903116bff426a407559 100644 (file)
@@ -4,8 +4,8 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2002, 2004, 2005 Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2002, 2004, 2005 Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2010, 2011, 2012
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index b6c6dfdb261e4836f32a2c3949733d52ae6ccb41..74e4bbd2462278f18922cfc0bfbb5582056af62c 100755 (executable)
@@ -5,8 +5,8 @@
 # The canonical version of this file is maintained in the rra-c-util package,
 # which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 #
-# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
+# Written by Russ Allbery <eagle@eyrie.org>
+# Copyright 2000, 2001, 2006 Russ Allbery <eagle@eyrie.org>
 # Copyright 2008, 2009, 2010, 2012
 #     The Board of Trustees of the Leland Stanford Junior University
 #
index 7e650e4ecbec7c4cc35da480455ba5b470c75a7c..a415614cdd6b52e3f18834c995518f82d1d2256c 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2000, 2001, 2006 Russ Allbery <rra@stanford.edu>
+ * Copyright 2000, 2001, 2006 Russ Allbery <eagle@eyrie.org>
  * Copyright 2008, 2012, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index bceb0ea3f3954ddfaa7e89938a939f9b96c114b6..74621a7ef7b1ad93cf005af286a4036a5203a2ec 100755 (executable)
@@ -34,6 +34,74 @@ sub print_fh {
     return;
 }
 
+# Filter the given input file and write it to a CDB data file, and then use
+# cdb to turn that into a database.
+#
+# $in_fh  - Input file handle for the source wordlist
+# $input  - Name of the input file, from which the CDB file name is derived
+# $filter - Reference to sub that returns true to keep a word, false otherwise
+#
+# Returns: undef
+#  Throws: Text exception on output failure or pre-existing temporary file
+sub write_cdb {
+    my ($in_fh, $input, $filter) = @_;
+
+    # Create a temporary file to write the CDB input into.
+    my $tmp = $input . '.data';
+    if (-f $tmp) {
+        die "$0: temporary output file $tmp already exists\n";
+    }
+    open(my $tmp_fh, '>', $tmp)
+      or die "$0: cannot create output file $tmp: $!\n";
+
+    # Walk through the input word list and write each word that passes the
+    # filter to the output file handle as CDB data.
+    while (defined(my $word = <$in_fh>)) {
+        chomp($word);
+        next if !$filter->($word);
+        my $length = length($word);
+        print_fh($tmp_fh, "+$length,1:$word->1\n");
+    }
+
+    # Add a trailing newline, required by the CDB data format, and close.
+    print_fh($tmp_fh, "\n");
+    close($tmp_fh) or die "$0: cannot write to temporary file $tmp: $!\n";
+
+    # Run cdb to turn the result into a CDB database.  Ignore duplicate keys.
+    system($CDB, '-c', '-u', "$input.cdb", $tmp) == 0
+      or die "$0: cdb -c failed\n";
+
+    # Remove the temporary file and return.
+    unlink($tmp) or die "$0: cannot remove temporary file $tmp: $!\n";
+    return;
+}
+
+# Filter the given input file and write the results to a new wordlist.
+#
+# $in_fh  - Input file handle for the source wordlist
+# $output - Output file name to which to write the resulting wordlist
+# $filter - Reference to sub that returns true to keep a word, false otherwise
+#
+# Returns: undef
+#  Throws: Text exception on output failure
+sub write_wordlist {
+    my ($in_fh, $output, $filter) = @_;
+    open(my $out_fh, '>', $output)
+      or die "$0: cannot create output file $output: $!\n";
+
+    # Walk through the input word list and write each word that passes the
+    # filter to the output file handle.
+    while (defined(my $word = <$in_fh>)) {
+        chomp($word);
+        next if !$filter->($word);
+        print_fh($out_fh, "$word\n");
+    }
+
+    # All done.
+    close($out_fh) or die "$0: cannot write to output file $output: $!\n";
+    return;
+}
+
 # Always flush output.
 STDOUT->autoflush;
 
@@ -42,12 +110,15 @@ my $fullpath = $0;
 local $0 = basename($0);
 
 # Parse the argument list.
-my ($ascii, $min_length, $manual);
+my ($ascii, @exclude, $max_length, $min_length, $manual, $output);
 Getopt::Long::config('bundling', 'no_ignore_case');
 GetOptions(
     'ascii|a'        => \$ascii,
+    'max-length|L=i' => \$max_length,
     'min-length|l=i' => \$min_length,
-    'manual|man|m'   => \$manual
+    'manual|man|m'   => \$manual,
+    'output|o=s'     => \$output,
+    'exclude|x=s'    => \@exclude,
 );
 if ($manual) {
     print_fh(\*STDOUT, "Feeding myself to perldoc, please wait...\n");
@@ -58,39 +129,40 @@ if (@ARGV != 1) {
 }
 my $input = $ARGV[0];
 
-# The output file goes in the same directory and is named the same as the
-# input but with .data appended.
-my $output = $input . '.data';
-if (-f $output) {
-    die "$0: temporary output file $output already exists\n";
-}
-
-# Process the input file into the output file, converting it to cdb input
-# format.
-open(my $in, '<', $input)
-  or die "$0: cannot open input file $input: $!\n";
-open(my $out, '>', $output)
-  or die "$0: cannot create output file $output: $!\n";
-while (defined(my $word = <$in>)) {
-    chomp($word);
+# Build a filter from our command-line parameters.  This is an anonymous sub
+# that returns true to keep a word and false otherwise.
+my $filter = sub {
+    my ($word) = @_;
     my $length = length($word);
-    next if (defined($min_length) && $length < $min_length);
+
+    # Check length.
+    return if (defined($min_length) && $length < $min_length);
+    return if (defined($max_length) && $length > $max_length);
+
+    # Check character classes.
     if ($ascii) {
-        next if $word =~ m{ [^[:ascii:]] }xms;
-        next if $word =~ m{ [[:cntrl:]] }xms;
+        return if $word =~ m{ [^[:ascii:]] }xms;
+        return if $word =~ m{ [[:cntrl:]] }xms;
     }
-    print_fh($out, "+$length,1:$word->1\n");
-}
-print_fh($out, "\n");
-close($in)  or die "$0: cannot read all of input file $input: $!\n";
-close($out) or die "$0: cannot write to output file $output: $!\n";
 
-# Run cdb to turn the result into a constant database.  Ignore duplicate keys.
-system($CDB, '-c', '-u', "$input.cdb", $output) == 0
-  or die "$0: cdb -c failed\n";
+    # Check regex exclusions.
+    for my $pattern (@exclude) {
+        return if $word =~ m{ $pattern }xms;
+    }
 
-# Remove the temporary file.
-unlink($output) or die "$0: cannot remove temporary file $output: $!\n";
+    # Word passes.  Return success.
+    return 1;
+};
+
+# Process the input file into either wordlist output or a CDB file.
+open(my $in_fh, '<', $input)
+  or die "$0: cannot open input file $input: $!\n";
+if (defined($output)) {
+    write_wordlist($in_fh, $output, $filter);
+} else {
+    write_cdb($in_fh, $input, $filter);
+}
+close($in_fh) or die "$0: cannot read all of input file $input: $!\n";
 
 # All done.
 exit(0);
@@ -98,7 +170,8 @@ __END__
 
 =for stopwords
 cdbmake-wordlist cdb whitespace wordlist lookups lookup sublicense
-MERCHANTABILITY NONINFRINGEMENT krb5-strength --ascii Allbery
+MERCHANTABILITY NONINFRINGEMENT krb5-strength --ascii Allbery regexes
+output-wordlist
 
 =head1 NAME
 
@@ -106,7 +179,8 @@ cdbmake-wordlist - Create a cdb database from a wordlist
 
 =head1 SYNOPSIS
 
-B<cdbmake-wordlist> [B<-am>] [B<-l> I<length>] I<wordlist>
+B<cdbmake-wordlist> [B<-am>] [B<-l> I<min-length>] [B<-L> I<max-length>]
+    [B<-o> I<output-wordlist>] [B<-x> I<exclude> ...] I<wordlist>
 
 =head1 DESCRIPTION
 
@@ -123,6 +197,10 @@ B<cdbmake-wordlist> takes one argument, the input wordlist file.  The
 output cdb database will have the same name as I<wordlist> but with
 C<.cdb> appended.  The input wordlist file does not have to be sorted.
 
+B<cdbmake-wordlist> can, instead of building a CDB file, filter a wordlist
+against the criteria given on the command line and generate a new
+wordlist.  See the B<-o> option for more details.
+
 =head1 OPTIONS
 
 =over 4
@@ -133,6 +211,17 @@ Filter all words that contain non-ASCII characters or control characters
 from the resulting cdb file, leaving only words that consist solely of
 ASCII non-control characters.
 
+=item B<-L> I<maximum>, B<--max-length>=I<maximum>
+
+Filter all words of length greater than I<maximum> from the resulting cdb
+database.  The length of each line (minus the separating newline) in the
+input wordlist will be checked against I<minimum> and will be filtered out
+of the resulting database if it is shorter.  Useful for generating
+password dictionaries from word lists that contain random noise that's
+highly unlikely to be used as a password.
+
+The default is to not filter out any words for maximum length.
+
 =item B<-l> I<minimum>, B<--min-length>=I<minimum>
 
 Filter all words of length less than I<minimum> from the resulting cdb
@@ -150,11 +239,29 @@ The default is not to filter out any words for minimum length.
 Print out this documentation (which is done simply by feeding the script to
 C<perldoc -t>).
 
+=item B<-o> I<wordlist>, B<--output>=I<wordlist>
+
+Rather than creating a CDB database, apply the filter rules given by the
+other command-line arguments and generate a new wordlist in the file name
+given by the I<wordlist> option.  This can be used to reduce the size of
+a raw wordlist file (such as one taken from Internet sources) by removing
+the words that will be filtered out of the CDB file anyway, thus reducing
+the size of the source required to regenerate the CDB database.
+
+If this option is given, no CDB database will be created.
+
+=item B<-x> I<exclude>, B<--exclude>=I<exclude>
+
+Filter all words matching the regular expression I<exclude> from the
+resulting cdb database.  This regular expression will be matched against
+each line of the source wordlist after the trailing newline is removed.
+This option may be given repeatedly to add multiple exclusion regexes.
+
 =back
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 50438ca191c5a587dcdc21b4f9a9373d6a73ac7f..eb77472057a0f7165c29a32f9e18cd9bfa4f7497 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "CDBMAKE-WORDLIST 1"
-.TH CDBMAKE-WORDLIST 1 "2013-10-10" "2.1" "krb5-strength"
+.TH CDBMAKE-WORDLIST 1 "2013-12-16" "2.2" "krb5-strength"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
 cdbmake\-wordlist \- Create a cdb database from a wordlist
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-\&\fBcdbmake-wordlist\fR [\fB\-am\fR] [\fB\-l\fR \fIlength\fR] \fIwordlist\fR
+\&\fBcdbmake-wordlist\fR [\fB\-am\fR] [\fB\-l\fR \fImin-length\fR] [\fB\-L\fR \fImax-length\fR]
+    [\fB\-o\fR \fIoutput-wordlist\fR] [\fB\-x\fR \fIexclude\fR ...] \fIwordlist\fR
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
 cdb is a format invented by Dan Bernstein for fast, constant databases.
@@ -157,6 +158,10 @@ checks.
 \&\fBcdbmake-wordlist\fR takes one argument, the input wordlist file.  The
 output cdb database will have the same name as \fIwordlist\fR but with
 \&\f(CW\*(C`.cdb\*(C'\fR appended.  The input wordlist file does not have to be sorted.
+.PP
+\&\fBcdbmake-wordlist\fR can, instead of building a \s-1CDB\s0 file, filter a wordlist
+against the criteria given on the command line and generate a new
+wordlist.  See the \fB\-o\fR option for more details.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-a\fR, \fB\-\-ascii\fR" 4
@@ -164,6 +169,16 @@ output cdb database will have the same name as \fIwordlist\fR but with
 Filter all words that contain non-ASCII characters or control characters
 from the resulting cdb file, leaving only words that consist solely of
 \&\s-1ASCII\s0 non-control characters.
+.IP "\fB\-L\fR \fImaximum\fR, \fB\-\-max\-length\fR=\fImaximum\fR" 4
+.IX Item "-L maximum, --max-length=maximum"
+Filter all words of length greater than \fImaximum\fR from the resulting cdb
+database.  The length of each line (minus the separating newline) in the
+input wordlist will be checked against \fIminimum\fR and will be filtered out
+of the resulting database if it is shorter.  Useful for generating
+password dictionaries from word lists that contain random noise that's
+highly unlikely to be used as a password.
+.Sp
+The default is to not filter out any words for maximum length.
 .IP "\fB\-l\fR \fIminimum\fR, \fB\-\-min\-length\fR=\fIminimum\fR" 4
 .IX Item "-l minimum, --min-length=minimum"
 Filter all words of length less than \fIminimum\fR from the resulting cdb
@@ -179,9 +194,25 @@ The default is not to filter out any words for minimum length.
 .IX Item "-m, --man, --manual"
 Print out this documentation (which is done simply by feeding the script to
 \&\f(CW\*(C`perldoc \-t\*(C'\fR).
+.IP "\fB\-o\fR \fIwordlist\fR, \fB\-\-output\fR=\fIwordlist\fR" 4
+.IX Item "-o wordlist, --output=wordlist"
+Rather than creating a \s-1CDB\s0 database, apply the filter rules given by the
+other command-line arguments and generate a new wordlist in the file name
+given by the \fIwordlist\fR option.  This can be used to reduce the size of
+a raw wordlist file (such as one taken from Internet sources) by removing
+the words that will be filtered out of the \s-1CDB\s0 file anyway, thus reducing
+the size of the source required to regenerate the \s-1CDB\s0 database.
+.Sp
+If this option is given, no \s-1CDB\s0 database will be created.
+.IP "\fB\-x\fR \fIexclude\fR, \fB\-\-exclude\fR=\fIexclude\fR" 4
+.IX Item "-x exclude, --exclude=exclude"
+Filter all words matching the regular expression \fIexclude\fR from the
+resulting cdb database.  This regular expression will be matched against
+each line of the source wordlist after the trailing newline is removed.
+This option may be given repeatedly to add multiple exclusion regexes.
 .SH "AUTHOR"
 .IX Header "AUTHOR"
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 .SH "COPYRIGHT AND LICENSE"
 .IX Header "COPYRIGHT AND LICENSE"
 Copyright 2013 The Board of Trustees of the Leland Stanford Junior
index 0baa595c9ae19437e35987c5f4fc0161f9dbf8d8..b7c80513cbfdd774d1a6c5a383df087ebf9f06af 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "HEIMDAL-STRENGTH 1"
-.TH HEIMDAL-STRENGTH 1 "2013-10-10" "2.1" "krb5-strength"
+.TH HEIMDAL-STRENGTH 1 "2013-12-16" "2.2" "krb5-strength"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -146,15 +146,17 @@ heimdal\-strength \- Heimdal password quality check embedding CrackLib
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
 \&\fBheimdal-strength\fR is an external password quality check program for
-Heimdal that verifies the strength of a password using an embedded copy of
-CrackLib, with some modifications to increase the aggressiveness of its
-rules.  It is normally run via \fIkpasswdd\fR\|(8) using the Heimdal password
-quality check interface rather than directly.
+Heimdal that verifies the strength of a password.  Passwords can be tested
+with CrackLib, checked against a \s-1CDB\s0 database of known weak passwords,
+checked for length, checked for non-printable or non-ASCII characters that
+may be difficult to enter reproducibly, required to contain particular
+character classes, or any combination of these tests.  It is normally run
+via \fIkpasswdd\fR\|(8) using the Heimdal password quality check interface rather
+than directly.
 .PP
-To use this program, the path to a CrackLib database must be configured in
-krb5.conf via the \f(CW\*(C`password_dictionary\*(C'\fR setting in \f(CW\*(C`[appdefaults]\*(C'\fR.  It
-uses the application name \f(CW\*(C`krb5\-strength\*(C'\fR when trying to find this
-setting.  A typical setting would be:
+To use this program, it must be configured in \fIkrb5.conf\fR via settings
+in \f(CW\*(C`[appdefaults]\*(C'\fR for the application name \f(CW\*(C`krb5\-strength\*(C'\fR.  A typical
+setting would be:
 .PP
 .Vb 3
 \&    krb5\-strength = {
@@ -162,6 +164,10 @@ setting.  A typical setting would be:
 \&    }
 .Ve
 .PP
+which says to check passwords with CrackLib using the given path as the
+base path of the CrackLib dictionary.  See \*(L"\s-1CONFIGURATION\*(R"\s0 below for
+details on the supported configuration options.
+.PP
 \&\fBheimdal-strength\fR then expects the Heimdal password quality check
 information on standard input, specifically:
 .PP
@@ -178,9 +184,101 @@ the password is rejected as being too weak, it will print the reason for
 rejecting the password on standard error and exit with a status of 0.  If
 some fatal error occurs, it will print that error to standard error and
 exit with a non-zero status.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+The following \fIkrb5.conf\fR configuration options are supported:
+.IP "minimum_length" 4
+.IX Item "minimum_length"
+If set to a numeric value, passwords with fewer than that number of
+characters will be rejected, independent of any length restrictions in
+CrackLib.  Note that this setting does not bypass the minimum length
+requirements in CrackLib itself.
+.IP "password_dictionary" 4
+.IX Item "password_dictionary"
+Specifies the base path to a CrackLib dictionary and enables password
+strength testing using CrackLib.  The provided path should be the full
+path to the dictionary files, omitting the trailing \fI*.hwm\fR, \fI*.pwd\fR,
+and \fI*.pwi\fR extensions for the CrackLib dictionary.
+.IP "password_dictionary_cdb" 4
+.IX Item "password_dictionary_cdb"
+Specifies the base path to a \s-1CDB\s0 dictionary and enables \s-1CDB\s0 password
+dictionary lookups.  The path must point to a CDB-format database whose
+keys are the known passwords or dictionary words.  The values are ignored.
+You can use the \fBcdbmake-wordlist\fR utility to generate the \s-1CDB\s0 database
+from a word list.
+.Sp
+The \s-1CDB\s0 dictionary lookups do not do the complex password mangling that
+CrackLib does.  Instead, the password itself will be checked against the
+dictionary, and then variations of the password formed by removing the
+first character, the last character, the first and last characters, the
+first two characters, and the last two characters.  If any of these
+strings are found in the \s-1CDB\s0 database, the password will be rejected;
+otherwise, it will be accepted, at least by this check.
+.Sp
+Both a CrackLib dictionary and a \s-1CDB\s0 dictionary may be configured at the
+same time, in which case CrackLib will be run first, followed by the \s-1CDB\s0
+checks.
+.IP "require_ascii_printable" 4
+.IX Item "require_ascii_printable"
+If set to a true boolean value, rejects any password that contains
+non-ASCII characters or \s-1ASCII\s0 control characters.  Spaces are allowed;
+tabs are not (at least assuming the \s-1POSIX C\s0 locale).  No canonicalization
+or character set is defined for Kerberos passwords in general, so you may
+want to reject non-ASCII characters to avoid interoperability problems
+with computers with different default character sets or Unicode
+normalization forms.
+.IP "require_classes" 4
+.IX Item "require_classes"
+This option allows specification of more complex character class
+requirements.  The value of this parameter should be one or more
+whitespace-separated rule.  Each rule has the syntax:
+.Sp
+.Vb 1
+\&    [<min>\-<max>:]<class>[,<class>...]
+.Ve
+.Sp
+where <class> is one of \f(CW\*(C`upper\*(C'\fR, \f(CW\*(C`lower\*(C'\fR, \f(CW\*(C`digit\*(C'\fR, or \f(CW\*(C`symbol\*(C'\fR.  The
+symbol class includes all characters other than alphanumeric characters,
+including space.  The listed classes must appear in the password.
+Separate multiple required classes with a comma (and no space).
+.Sp
+The character class checks will be done in whatever locale the plugin or
+password check program is run in, which will normally be the \s-1POSIX C\s0
+locale but may be different depending on local configuration.
+.Sp
+A simple example:
+.Sp
+.Vb 1
+\&    require_classes = upper,lower,digit
+.Ve
+.Sp
+This requires all passwords contain at least one uppercase letter, at
+least one lowercase letter, and at least one digit.
+.Sp
+If present, <min> and <max> specify the minimum password length and
+maximum password length to which this rule applies.  This allows one to
+specify character class requirements that change with password length.
+So, for example:
+.Sp
+.Vb 1
+\&    require_classes = 8\-19:upper,lower 8\-15:digit 8\-11:symbol
+.Ve
+.Sp
+requires all passwords from 8 to 11 characters long contain all four
+character classes, passwords from 12 to 15 characters long contain upper
+and lower case and a digit, and passwords from 16 to 19 characters long
+contain both upper and lower case.  Passwords longer than 20 characters
+have no character class restrictions.  (This example is probably used in
+conjunction with minimum_length = 8.)
+.IP "require_non_letter" 4
+.IX Item "require_non_letter"
+If set to a true boolean value, the password must contain at least one
+character that is not a letter (uppercase or lowercase) or a space.  This
+may be helpful in combination with passphrases; users may choose a stock
+English phrase, and this will force at least some additional complexity.
 .SH "SEE ALSO"
 .IX Header "SEE ALSO"
-\&\fIkadm5\-strength\fR\|(3), \fIkpasswdd\fR\|(8), \fIkrb5.conf\fR\|(5)
+\&\fIcdbmake\-wordlist\fR\|(1), \fIkadm5\-strength\fR\|(3), \fIkpasswdd\fR\|(8), \fIkrb5.conf\fR\|(5)
 .PP
 The \*(L"Password changing\*(R" section of the Heimdal info documentation
 describes the interface that this program implements and how to configure
@@ -191,7 +289,7 @@ The current version of this program is available from its web page at
 krb5\-strength package.
 .SH "AUTHOR"
 .IX Header "AUTHOR"
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 .SH "COPYRIGHT AND LICENSE"
 .IX Header "COPYRIGHT AND LICENSE"
 Copyright 2010, 2013 The Board of Trustees of the Leland Stanford Junior
index 51416c7cbbbdb87a8e83e288fe06ce6137efef69..775d3afd965b7108ef5c5e95b327be9fe38d84ec 100644 (file)
@@ -6,7 +6,7 @@
  * interface.  It uses a krb5.conf parameter to determine the location of its
  * dictionary.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2009, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index 7884e0edd2ed748e147b095f8fd56c4b3ec4de8d..9e26a09bcf547da345d12719c62fb7ee7ddc1b0b 100644 (file)
@@ -1,5 +1,6 @@
 =for stopwords
-heimdal-strength Heimdal CrackLib krb5.conf krb5-strength Allbery
+heimdal-strength Heimdal CrackLib krb5-strength Allbery CDB
+canonicalization cdbmake-wordlist reproducibly
 
 =head1 NAME
 
@@ -12,20 +13,26 @@ B<heimdal-strength> [I<principal>]
 =head1 DESCRIPTION
 
 B<heimdal-strength> is an external password quality check program for
-Heimdal that verifies the strength of a password using an embedded copy of
-CrackLib, with some modifications to increase the aggressiveness of its
-rules.  It is normally run via kpasswdd(8) using the Heimdal password
-quality check interface rather than directly.
-
-To use this program, the path to a CrackLib database must be configured in
-krb5.conf via the C<password_dictionary> setting in C<[appdefaults]>.  It
-uses the application name C<krb5-strength> when trying to find this
-setting.  A typical setting would be:
+Heimdal that verifies the strength of a password.  Passwords can be tested
+with CrackLib, checked against a CDB database of known weak passwords,
+checked for length, checked for non-printable or non-ASCII characters that
+may be difficult to enter reproducibly, required to contain particular
+character classes, or any combination of these tests.  It is normally run
+via kpasswdd(8) using the Heimdal password quality check interface rather
+than directly.
+
+To use this program, it must be configured in F<krb5.conf> via settings
+in C<[appdefaults]> for the application name C<krb5-strength>.  A typical
+setting would be:
 
     krb5-strength = {
         password_dictionary = /usr/local/lib/kadmind/dictionary
     }
 
+which says to check passwords with CrackLib using the given path as the
+base path of the CrackLib dictionary.  See L</CONFIGURATION> below for
+details on the supported configuration options.
+
 B<heimdal-strength> then expects the Heimdal password quality check
 information on standard input, specifically:
 
@@ -41,9 +48,106 @@ rejecting the password on standard error and exit with a status of 0.  If
 some fatal error occurs, it will print that error to standard error and
 exit with a non-zero status.
 
+=head1 CONFIGURATION
+
+The following F<krb5.conf> configuration options are supported:
+
+=over 4
+
+=item minimum_length
+
+If set to a numeric value, passwords with fewer than that number of
+characters will be rejected, independent of any length restrictions in
+CrackLib.  Note that this setting does not bypass the minimum length
+requirements in CrackLib itself.
+
+=item password_dictionary
+
+Specifies the base path to a CrackLib dictionary and enables password
+strength testing using CrackLib.  The provided path should be the full
+path to the dictionary files, omitting the trailing F<*.hwm>, F<*.pwd>,
+and F<*.pwi> extensions for the CrackLib dictionary.
+
+=item password_dictionary_cdb
+
+Specifies the base path to a CDB dictionary and enables CDB password
+dictionary lookups.  The path must point to a CDB-format database whose
+keys are the known passwords or dictionary words.  The values are ignored.
+You can use the B<cdbmake-wordlist> utility to generate the CDB database
+from a word list.
+
+The CDB dictionary lookups do not do the complex password mangling that
+CrackLib does.  Instead, the password itself will be checked against the
+dictionary, and then variations of the password formed by removing the
+first character, the last character, the first and last characters, the
+first two characters, and the last two characters.  If any of these
+strings are found in the CDB database, the password will be rejected;
+otherwise, it will be accepted, at least by this check.
+
+Both a CrackLib dictionary and a CDB dictionary may be configured at the
+same time, in which case CrackLib will be run first, followed by the CDB
+checks.
+
+=item require_ascii_printable
+
+If set to a true boolean value, rejects any password that contains
+non-ASCII characters or ASCII control characters.  Spaces are allowed;
+tabs are not (at least assuming the POSIX C locale).  No canonicalization
+or character set is defined for Kerberos passwords in general, so you may
+want to reject non-ASCII characters to avoid interoperability problems
+with computers with different default character sets or Unicode
+normalization forms.
+
+=item require_classes
+
+This option allows specification of more complex character class
+requirements.  The value of this parameter should be one or more
+whitespace-separated rule.  Each rule has the syntax:
+
+    [<min>-<max>:]<class>[,<class>...]
+
+where <class> is one of C<upper>, C<lower>, C<digit>, or C<symbol>.  The
+symbol class includes all characters other than alphanumeric characters,
+including space.  The listed classes must appear in the password.
+Separate multiple required classes with a comma (and no space).
+
+The character class checks will be done in whatever locale the plugin or
+password check program is run in, which will normally be the POSIX C
+locale but may be different depending on local configuration.
+
+A simple example:
+
+    require_classes = upper,lower,digit
+
+This requires all passwords contain at least one uppercase letter, at
+least one lowercase letter, and at least one digit.
+
+If present, <min> and <max> specify the minimum password length and
+maximum password length to which this rule applies.  This allows one to
+specify character class requirements that change with password length.
+So, for example:
+
+    require_classes = 8-19:upper,lower 8-15:digit 8-11:symbol
+
+requires all passwords from 8 to 11 characters long contain all four
+character classes, passwords from 12 to 15 characters long contain upper
+and lower case and a digit, and passwords from 16 to 19 characters long
+contain both upper and lower case.  Passwords longer than 20 characters
+have no character class restrictions.  (This example is probably used in
+conjunction with minimum_length = 8.)
+
+=item require_non_letter
+
+If set to a true boolean value, the password must contain at least one
+character that is not a letter (uppercase or lowercase) or a space.  This
+may be helpful in combination with passphrases; users may choose a stock
+English phrase, and this will force at least some additional complexity.
+
+=back
+
 =head1 SEE ALSO
 
-kadm5-strength(3), kpasswdd(8), krb5.conf(5)
+cdbmake-wordlist(1), kadm5-strength(3), kpasswdd(8), krb5.conf(5)
 
 The "Password changing" section of the Heimdal info documentation
 describes the interface that this program implements and how to configure
@@ -55,7 +159,7 @@ krb5-strength package.
 
 =head1 AUTHOR
 
-Russ Allbery <rra@stanford.edu>
+Russ Allbery <eagle@eyrie.org>
 
 =head1 COPYRIGHT AND LICENSE
 
index 54faee57b0d2161c9d7ea74353600f996fa0af3e..d071793a807580cf2ecf190cc2ba3f86a5f9bd53 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  *
  * The authors hereby relinquish any claim to any copyright that they may have
  * in this work, whether granted under contract or by operation of law or
index 82c1ffd06fd1e9a1ffe98da39e1011e495b0fc9c..961ea1d18fec80e2a9f922243b29b52b647b6b28 100644 (file)
@@ -8,7 +8,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2008, 2009, 2010, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index 0e157035588ca12aa66a6030366a6c898e19a95b..3fc08620bf89e2b5765d9ecf5af15e29c9effbf2 100644 (file)
@@ -4,7 +4,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
+ * Written by Russ Allbery <eagle@eyrie.org>
  * Copyright 2006, 2007, 2008, 2009, 2010, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  *
index 52fcfb744ded90644d3ca56f0e11507548293be8..769166fc4c01b4cd0cb33a13092ce129d0b205e4 100644 (file)
@@ -53,8 +53,8 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Written by Russ Allbery <rra@stanford.edu>
- * Copyright 2008, 2009, 2010
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2008, 2009, 2010, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  * Copyright (c) 2004, 2005, 2006
  *     by Internet Systems Consortium, Inc. ("ISC")
@@ -204,6 +204,7 @@ static void
 message_log_syslog(int pri, size_t len, const char *fmt, va_list args, int err)
 {
     char *buffer;
+    int status;
 
     buffer = malloc(len + 1);
     if (buffer == NULL) {
@@ -211,7 +212,12 @@ message_log_syslog(int pri, size_t len, const char *fmt, va_list args, int err)
                 (unsigned long) len + 1, __FILE__, __LINE__, strerror(errno));
         exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
     }
-    vsnprintf(buffer, len + 1, fmt, args);
+    status = vsnprintf(buffer, len + 1, fmt, args);
+    if (status < 0) {
+        warn("failed to format output with vsnprintf in syslog handler");
+        free(buffer);
+        return;
+    }
 #ifdef _WIN32
     {
         HANDLE eventlog;
index cffae803096a7f16b188305a40cd5bceca510ca0..5bfd5558589f2290a8c221a5747194a950dfac5c 100644 (file)
@@ -58,7 +58,7 @@
  * The canonical version of this file is maintained in the rra-c-util package,
  * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2012
+ * Copyright 2012, 2013
  *     The Board of Trustees of the Leland Stanford Junior University
  * Copyright (c) 2004, 2005, 2006
  *     by Internet Systems Consortium, Inc. ("ISC")
 void
 xmalloc_fail(const char *function, size_t size, const char *file, int line)
 {
-    sysdie("failed to %s %lu bytes at %s line %d", function,
-           (unsigned long) size, file, line);
+    if (size == 0)
+        sysdie("failed to format output with %s at %s line %d", function,
+               file, line);
+    else
+        sysdie("failed to %s %lu bytes at %s line %d", function,
+               (unsigned long) size, file, line);
 }
 
 /* Assign to this variable to choose a handler other than the default. */
@@ -206,7 +210,8 @@ x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
         va_copy(args_copy, args);
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
-        (*xmalloc_error_handler)("vasprintf", status + 1, file, line);
+        status = (status < 0) ? 0 : status + 1;
+        (*xmalloc_error_handler)("vasprintf", status, file, line);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
@@ -229,7 +234,8 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
         va_copy(args_copy, args);
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
-        (*xmalloc_error_handler)("asprintf", status + 1, file, line);
+        status = (status < 0) ? 0 : status + 1;
+        (*xmalloc_error_handler)("asprintf", status, file, line);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
@@ -250,7 +256,8 @@ x_asprintf(char **strp, const char *fmt, ...)
         va_copy(args_copy, args);
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
-        (*xmalloc_error_handler)("asprintf", status + 1, __FILE__, __LINE__);
+        status = (status < 0) ? 0 : status + 1;
+        (*xmalloc_error_handler)("asprintf", status, __FILE__, __LINE__);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
index 3f680adff4b5b69a63713b8ebf89d74bf57dfd14..ac4d79629c0d302376ab01768b58526f1102a9a5 100644 (file)
@@ -97,7 +97,11 @@ void x_asprintf(char **, const char *, ...)
     __attribute__((__nonnull__, __format__(printf, 2, 3)));
 #endif
 
-/* Failure handler takes the function, the size, the file, and the line. */
+/*
+ * Failure handler takes the function, the size, the file, and the line.  The
+ * size will be zero if the failure was due to some failure in snprintf
+ * instead of a memory allocation failure.
+ */
 typedef void (*xmalloc_handler_type)(const char *, size_t, const char *, int);
 
 /* The default error handler. */