summaryrefslogtreecommitdiff
path: root/modules/pam_cracklib
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 16:26:05 -0800
committerSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 17:26:38 -0800
commit9c52e721044e7501c3d4567b36d222dc7326224a (patch)
tree9011790770130c60a712a6f125ad50d60e07cc74 /modules/pam_cracklib
parent9727ff2a3fa0e94a42b34a579027bacf4146d571 (diff)
parent186ff16e8d12ff15d518000c17f115ccab5275a4 (diff)
New upstream version 1.0.1
Diffstat (limited to 'modules/pam_cracklib')
-rw-r--r--modules/pam_cracklib/Makefile.am38
-rw-r--r--modules/pam_cracklib/Makefile.in672
-rw-r--r--modules/pam_cracklib/README220
-rw-r--r--modules/pam_cracklib/README.xml41
-rw-r--r--modules/pam_cracklib/pam_cracklib.8309
-rw-r--r--modules/pam_cracklib/pam_cracklib.8.xml513
-rw-r--r--modules/pam_cracklib/pam_cracklib.c842
-rwxr-xr-xmodules/pam_cracklib/tst-pam_cracklib2
8 files changed, 2637 insertions, 0 deletions
diff --git a/modules/pam_cracklib/Makefile.am b/modules/pam_cracklib/Makefile.am
new file mode 100644
index 00000000..619ffc93
--- /dev/null
+++ b/modules/pam_cracklib/Makefile.am
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
+#
+
+CLEANFILES = *~
+
+EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_cracklib
+
+man_MANS = pam_cracklib.8
+
+XMLS = README.xml pam_cracklib.8.xml
+
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+if HAVE_LIBCRACK
+securelib_LTLIBRARIES = pam_cracklib.la
+
+TESTS = tst-pam_cracklib
+endif
+
+pam_cracklib_la_LIBADD = -L$(top_builddir)/libpam -lpam \
+ @LIBCRACK@ @LIBCRYPT@
+
+if ENABLE_REGENERATE_MAN
+
+noinst_DATA = README
+
+README: pam_cracklib.8.xml
+
+-include $(top_srcdir)/Make.xml.rules
+endif
diff --git a/modules/pam_cracklib/Makefile.in b/modules/pam_cracklib/Makefile.in
new file mode 100644
index 00000000..01daaf8e
--- /dev/null
+++ b/modules/pam_cracklib/Makefile.in
@@ -0,0 +1,672 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
+#
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map
+subdir = modules/pam_cracklib
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/jh_path_xml_catalog.m4 \
+ $(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libprelude.m4 \
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man8dir)"
+securelibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(securelib_LTLIBRARIES)
+pam_cracklib_la_DEPENDENCIES =
+pam_cracklib_la_SOURCES = pam_cracklib.c
+pam_cracklib_la_OBJECTS = pam_cracklib.lo
+@HAVE_LIBCRACK_TRUE@am_pam_cracklib_la_rpath = -rpath $(securelibdir)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = pam_cracklib.c
+DIST_SOURCES = pam_cracklib.c
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+DATA = $(noinst_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BROWSER = @BROWSER@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FO2PDF = @FO2PDF@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+HAVE_KEY_MANAGEMENT = @HAVE_KEY_MANAGEMENT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBAUDIT = @LIBAUDIT@
+LIBCRACK = @LIBCRACK@
+LIBCRYPT = @LIBCRYPT@
+LIBDB = @LIBDB@
+LIBDL = @LIBDL@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBNSL = @LIBNSL@
+LIBOBJS = @LIBOBJS@
+LIBPRELUDE_CFLAGS = @LIBPRELUDE_CFLAGS@
+LIBPRELUDE_CONFIG = @LIBPRELUDE_CONFIG@
+LIBPRELUDE_CONFIG_PREFIX = @LIBPRELUDE_CONFIG_PREFIX@
+LIBPRELUDE_LDFLAGS = @LIBPRELUDE_LDFLAGS@
+LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@
+LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@
+LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@
+LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PAM_READ_BOTH_CONFS = @PAM_READ_BOTH_CONFS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SCONFIGDIR = @SCONFIGDIR@
+SECUREDIR = @SECUREDIR@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WITH_DEBUG = @WITH_DEBUG@
+WITH_PAMLOCKING = @WITH_PAMLOCKING@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XMLCATALOG = @XMLCATALOG@
+XMLLINT = @XMLLINT@
+XML_CATALOG_FILE = @XML_CATALOG_FILE@
+XSLTPROC = @XSLTPROC@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libc_cv_fpie = @libc_cv_fpie@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pam_cv_ld_as_needed = @pam_cv_ld_as_needed@
+pam_xauth_path = @pam_xauth_path@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *~
+EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_cracklib
+man_MANS = pam_cracklib.8
+XMLS = README.xml pam_cracklib.8.xml
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+AM_LDFLAGS = -no-undefined -avoid-version -module $(am__append_1)
+@HAVE_LIBCRACK_TRUE@securelib_LTLIBRARIES = pam_cracklib.la
+@HAVE_LIBCRACK_TRUE@TESTS = tst-pam_cracklib
+pam_cracklib_la_LIBADD = -L$(top_builddir)/libpam -lpam \
+ @LIBCRACK@ @LIBCRYPT@
+
+@ENABLE_REGENERATE_MAN_TRUE@noinst_DATA = README
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/pam_cracklib/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu modules/pam_cracklib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-securelibLTLIBRARIES: $(securelib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(securelibdir)" || $(MKDIR_P) "$(DESTDIR)$(securelibdir)"
+ @list='$(securelib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(securelibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(securelibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(securelibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(securelibdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-securelibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(securelib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(securelibdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(securelibdir)/$$p"; \
+ done
+
+clean-securelibLTLIBRARIES:
+ -test -z "$(securelib_LTLIBRARIES)" || rm -f $(securelib_LTLIBRARIES)
+ @list='$(securelib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+pam_cracklib.la: $(pam_cracklib_la_OBJECTS) $(pam_cracklib_la_DEPENDENCIES)
+ $(LINK) $(am_pam_cracklib_la_rpath) $(pam_cracklib_la_OBJECTS) $(pam_cracklib_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_cracklib.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man8: $(man8_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 8*) ;; \
+ *) ext='8' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+ done
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 8*) ;; \
+ *) ext='8' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(MANS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-securelibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man install-securelibLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-securelibLTLIBRARIES
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-libtool clean-securelibLTLIBRARIES ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man8 install-pdf \
+ install-pdf-am install-ps install-ps-am \
+ install-securelibLTLIBRARIES install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-man uninstall-man8 \
+ uninstall-securelibLTLIBRARIES
+
+
+@ENABLE_REGENERATE_MAN_TRUE@README: pam_cracklib.8.xml
+
+@ENABLE_REGENERATE_MAN_TRUE@-include $(top_srcdir)/Make.xml.rules
+# 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/modules/pam_cracklib/README b/modules/pam_cracklib/README
new file mode 100644
index 00000000..25ec00b4
--- /dev/null
+++ b/modules/pam_cracklib/README
@@ -0,0 +1,220 @@
+pam_cracklib — PAM module to check the password against dictionary words
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+DESCRIPTION
+
+This module can be plugged into the password stack of a given application to
+provide some plug-in strength-checking for passwords.
+
+The action of this module is to prompt the user for a password and check its
+strength against a system dictionary and a set of rules for identifying poor
+choices.
+
+The first action is to prompt for a single password, check its strength and
+then, if it is considered strong, prompt for the password a second time (to
+verify that it was typed correctly on the first occasion). All being well, the
+password is passed on to subsequent modules to be installed as the new
+authentication token.
+
+The strength checks works in the following manner: at first the Cracklib
+routine is called to check if the password is part of a dictionary; if this is
+not the case an additional set of strength checks is done. These checks are:
+
+Palindrome
+
+ Is the new password a palindrome of the old one?
+
+Case Change Only
+
+ Is the new password the the old one with only a change of case?
+
+Similar
+
+ Is the new password too much like the old one? This is primarily controlled
+ by one argument, difok which is a number of characters that if different
+ between the old and new are enough to accept the new password, this
+ defaults to 10 or 1/2 the size of the new password whichever is smaller.
+
+ To avoid the lockup associated with trying to change a long and complicated
+ password, difignore is available. This argument can be used to specify the
+ minimum length a new password needs to be before the difok value is
+ ignored. The default value for difignore is 23.
+
+Simple
+
+ Is the new password too small? This is controlled by 5 arguments minlen,
+ dcredit, ucredit, lcredit, and ocredit. See the section on the arguments
+ for the details of how these work and there defaults.
+
+Rotated
+
+ Is the new password a rotated version of the old password?
+
+Already used
+
+ Was the password used in the past? Previously used passwords are to be
+ found in /etc/security/opasswd.
+
+This module with no arguments will work well for standard unix password
+encryption. With md5 encryption, passwords can be longer than 8 characters and
+the default settings for this module can make it hard for the user to choose a
+satisfactory new password. Notably, the requirement that the new password
+contain no more than 1/2 of the characters in the old password becomes a
+non-trivial constraint. For example, an old password of the form "the quick
+brown fox jumped over the lazy dogs" would be difficult to change... In
+addition, the default action is to allow passwords as small as 5 characters in
+length. For a md5 systems it can be a good idea to increase the required
+minimum size of a password. One can then allow more credit for different kinds
+of characters but accept that the new password may share most of these
+characters with the old password.
+
+OPTIONS
+
+debug
+
+ This option makes the module write information to syslog(3) indicating the
+ behavior of the module (this option does not write password information to
+ the log file).
+
+type=XXX
+
+ The default action is for the module to use the following prompts when
+ requesting passwords: "New UNIX password: " and "Retype UNIX password: ".
+ The default word UNIX can be replaced with this option.
+
+retry=N
+
+ Prompt user at most N times before returning with error. The default is 1
+
+difok=N
+
+ This argument will change the default of 5 for the number of characters in
+ the new password that must not be present in the old password. In addition,
+ if 1/2 of the characters in the new password are different then the new
+ password will be accepted anyway.
+
+difignore=N
+
+ How many characters should the password have before difok will be ignored.
+ The default is 23.
+
+minlen=N
+
+ The minimum acceptable size for the new password (plus one if credits are
+ not disabled which is the default). In addition to the number of characters
+ in the new password, credit (of +1 in length) is given for each different
+ kind of character (other, upper, lower and digit). The default for this
+ parameter is 9 which is good for a old style UNIX password all of the same
+ type of character but may be too low to exploit the added security of a md5
+ system. Note that there is a pair of length limits in Cracklib itself, a
+ "way too short" limit of 4 which is hard coded in and a defined limit (6)
+ that will be checked without reference to minlen. If you want to allow
+ passwords as short as 5 characters you should not use this module.
+
+dcredit=N
+
+ (N >= 0) This is the maximum credit for having digits in the new password.
+ If you have less than or N digits, each digit will count +1 towards meeting
+ the current minlen value. The default for dcredit is 1 which is the
+ recommended value for minlen less than 10.
+
+ (N < 0) This is the minimum number of digits that must be met for a new
+ password.
+
+ucredit=N
+
+ (N >= 0) This is the maximum credit for having upper case letters in the
+ new password. If you have less than or N upper case letters each letter
+ will count +1 towards meeting the current minlen value. The default for
+ ucredit is 1 which is the recommended value for minlen less than 10.
+
+ (N > 0) This is the minimum number of upper case letters that must be met
+ for a new password.
+
+lcredit=N
+
+ (N >= 0) This is the maximum credit for having lower case letters in the
+ new password. If you have less than or N lower case letters, each letter
+ will count +1 towards meeting the current minlen value. The default for
+ lcredit is 1 which is the recommended value for minlen less than 10.
+
+ (N < 0) This is the minimum number of lower case letters that must be met
+ for a new password.
+
+ocredit=N
+
+ (N >= 0) This is the maximum credit for having other characters in the new
+ password. If you have less than or N other characters, each character will
+ count +1 towards meeting the current minlen value. The default for ocredit
+ is 1 which is the recommended value for minlen less than 10.
+
+ (N < 0) This is the minimum number of other characters that must be met for
+ a new password.
+
+minclass=N
+
+ The minimum number of required classes of characters for the new password.
+ The default number is zero. The four classes are digits, upper and lower
+ letters and other characters. The difference to the credit check is that a
+ specific class if of characters is not required. Instead N out of four of
+ the classes are required.
+
+use_authtok
+
+ This argument is used to force the module to not prompt the user for a new
+ password but use the one provided by the previously stacked password
+ module.
+
+dictpath=/path/to/dict
+
+ Path to the cracklib dictionaries.
+
+EXAMPLES
+
+For an example of the use of this module, we show how it may be stacked with
+the password component of pam_unix(8)
+
+#
+# These lines stack two password type modules. In this example the
+# user is given 3 opportunities to enter a strong password. The
+# "use_authtok" argument ensures that the pam_unix module does not
+# prompt for a password, but instead uses the one provided by
+# pam_cracklib.
+#
+passwd password required pam_cracklib.so retry=3
+passwd password required pam_unix.so use_authtok
+
+
+Another example (in the /etc/pam.d/passwd format) is for the case that you want
+to use md5 password encryption:
+
+#%PAM-1.0
+#
+# These lines allow a md5 systems to support passwords of at least 14
+# bytes with extra credit of 2 for digits and 2 for others the new
+# password must have at least three bytes that are not present in the
+# old password
+#
+password required pam_cracklib.so \
+ difok=3 minlen=15 dcredit= 2 ocredit=2
+password required pam_unix.so use_authtok nullok md5
+
+
+And here is another example in case you don't want to use credits:
+
+#%PAM-1.0
+#
+# These lines require the user to select a password with a minimum
+# length of 8 and with at least 1 digit number, 1 upper case letter,
+# and 1 other character
+#
+password required pam_cracklib.so \
+ dcredit=-1 ucredit=-1 ocredit=-1 lcredit=0 minlen=8
+password required pam_unix.so use_authtok nullok md5
+
+
+AUTHOR
+
+pam_cracklib was written by Cristian Gafton <gafton@redhat.com>
+
diff --git a/modules/pam_cracklib/README.xml b/modules/pam_cracklib/README.xml
new file mode 100644
index 00000000..c4a7b54c
--- /dev/null
+++ b/modules/pam_cracklib/README.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.docbook.org/xml/4.3/docbookx.dtd"
+[
+<!--
+<!ENTITY pamaccess SYSTEM "pam_cracklib.8.xml">
+-->
+]>
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_cracklib.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_cracklib-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_cracklib.8.xml" xpointer='xpointer(//refsect1[@id = "pam_cracklib-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_cracklib.8.xml" xpointer='xpointer(//refsect1[@id = "pam_cracklib-options"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_cracklib.8.xml" xpointer='xpointer(//refsect1[@id = "pam_cracklib-examples"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_cracklib.8.xml" xpointer='xpointer(//refsect1[@id = "pam_cracklib-author"]/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_cracklib/pam_cracklib.8 b/modules/pam_cracklib/pam_cracklib.8
new file mode 100644
index 00000000..b772f747
--- /dev/null
+++ b/modules/pam_cracklib/pam_cracklib.8
@@ -0,0 +1,309 @@
+.\" Title: pam_cracklib
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/>
+.\" Date: 04/16/2008
+.\" Manual: Linux-PAM Manual
+.\" Source: Linux-PAM Manual
+.\"
+.TH "PAM_CRACKLIB" "8" "04/16/2008" "Linux-PAM Manual" "Linux\-PAM Manual"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+pam_cracklib - PAM module to check the password against dictionary words
+.SH "SYNOPSIS"
+.HP 16
+\fBpam_cracklib\.so\fR [\fI\.\.\.\fR]
+.SH "DESCRIPTION"
+.PP
+This module can be plugged into the
+\fIpassword\fR
+stack of a given application to provide some plug\-in strength\-checking for passwords\.
+.PP
+The action of this module is to prompt the user for a password and check its strength against a system dictionary and a set of rules for identifying poor choices\.
+.PP
+The first action is to prompt for a single password, check its strength and then, if it is considered strong, prompt for the password a second time (to verify that it was typed correctly on the first occasion)\. All being well, the password is passed on to subsequent modules to be installed as the new authentication token\.
+.PP
+The strength checks works in the following manner: at first the
+\fBCracklib\fR
+routine is called to check if the password is part of a dictionary; if this is not the case an additional set of strength checks is done\. These checks are:
+.PP
+Palindrome
+.RS 4
+Is the new password a palindrome of the old one?
+.RE
+.PP
+Case Change Only
+.RS 4
+Is the new password the the old one with only a change of case?
+.RE
+.PP
+Similar
+.RS 4
+Is the new password too much like the old one? This is primarily controlled by one argument,
+\fBdifok\fR
+which is a number of characters that if different between the old and new are enough to accept the new password, this defaults to 10 or 1/2 the size of the new password whichever is smaller\.
+.sp
+To avoid the lockup associated with trying to change a long and complicated password,
+\fBdifignore\fR
+is available\. This argument can be used to specify the minimum length a new password needs to be before the
+\fBdifok\fR
+value is ignored\. The default value for
+\fBdifignore\fR
+is 23\.
+.RE
+.PP
+Simple
+.RS 4
+Is the new password too small? This is controlled by 5 arguments
+\fBminlen\fR,
+\fBdcredit\fR,
+\fBucredit\fR,
+\fBlcredit\fR, and
+\fBocredit\fR\. See the section on the arguments for the details of how these work and there defaults\.
+.RE
+.PP
+Rotated
+.RS 4
+Is the new password a rotated version of the old password?
+.RE
+.PP
+Already used
+.RS 4
+Was the password used in the past? Previously used passwords are to be found in
+\fI/etc/security/opasswd\fR\.
+.RE
+.PP
+This module with no arguments will work well for standard unix password encryption\. With md5 encryption, passwords can be longer than 8 characters and the default settings for this module can make it hard for the user to choose a satisfactory new password\. Notably, the requirement that the new password contain no more than 1/2 of the characters in the old password becomes a non\-trivial constraint\. For example, an old password of the form "the quick brown fox jumped over the lazy dogs" would be difficult to change\.\.\. In addition, the default action is to allow passwords as small as 5 characters in length\. For a md5 systems it can be a good idea to increase the required minimum size of a password\. One can then allow more credit for different kinds of characters but accept that the new password may share most of these characters with the old password\.
+.SH "OPTIONS"
+.PP
+.PP
+\fBdebug\fR
+.RS 4
+This option makes the module write information to
+\fBsyslog\fR(3)
+indicating the behavior of the module (this option does not write password information to the log file)\.
+.RE
+.PP
+\fBtype=\fR\fB\fIXXX\fR\fR
+.RS 4
+The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: "\. The default word
+\fIUNIX\fR
+can be replaced with this option\.
+.RE
+.PP
+\fBretry=\fR\fB\fIN\fR\fR
+.RS 4
+Prompt user at most
+\fIN\fR
+times before returning with error\. The default is
+\fI1\fR
+.RE
+.PP
+\fBdifok=\fR\fB\fIN\fR\fR
+.RS 4
+This argument will change the default of
+\fI5\fR
+for the number of characters in the new password that must not be present in the old password\. In addition, if 1/2 of the characters in the new password are different then the new password will be accepted anyway\.
+.RE
+.PP
+\fBdifignore=\fR\fB\fIN\fR\fR
+.RS 4
+How many characters should the password have before difok will be ignored\. The default is
+\fI23\fR\.
+.RE
+.PP
+\fBminlen=\fR\fB\fIN\fR\fR
+.RS 4
+The minimum acceptable size for the new password (plus one if credits are not disabled which is the default)\. In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (\fIother\fR,
+\fIupper\fR,
+\fIlower\fR
+and
+\fIdigit\fR)\. The default for this parameter is
+\fI9\fR
+which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system\. Note that there is a pair of length limits in
+\fICracklib\fR
+itself, a "way too short" limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to
+\fBminlen\fR\. If you want to allow passwords as short as 5 characters you should not use this module\.
+.RE
+.PP
+\fBdcredit=\fR\fB\fIN\fR\fR
+.RS 4
+(N >= 0) This is the maximum credit for having digits in the new password\. If you have less than or
+\fIN\fR
+digits, each digit will count +1 towards meeting the current
+\fBminlen\fR
+value\. The default for
+\fBdcredit\fR
+is 1 which is the recommended value for
+\fBminlen\fR
+less than 10\.
+.sp
+(N < 0) This is the minimum number of digits that must be met for a new password\.
+.RE
+.PP
+\fBucredit=\fR\fB\fIN\fR\fR
+.RS 4
+(N >= 0) This is the maximum credit for having upper case letters in the new password\. If you have less than or
+\fIN\fR
+upper case letters each letter will count +1 towards meeting the current
+\fBminlen\fR
+value\. The default for
+\fBucredit\fR
+is
+\fI1\fR
+which is the recommended value for
+\fBminlen\fR
+less than 10\.
+.sp
+(N > 0) This is the minimum number of upper case letters that must be met for a new password\.
+.RE
+.PP
+\fBlcredit=\fR\fB\fIN\fR\fR
+.RS 4
+(N >= 0) This is the maximum credit for having lower case letters in the new password\. If you have less than or
+\fIN\fR
+lower case letters, each letter will count +1 towards meeting the current
+\fBminlen\fR
+value\. The default for
+\fBlcredit\fR
+is 1 which is the recommended value for
+\fBminlen\fR
+less than 10\.
+.sp
+(N < 0) This is the minimum number of lower case letters that must be met for a new password\.
+.RE
+.PP
+\fBocredit=\fR\fB\fIN\fR\fR
+.RS 4
+(N >= 0) This is the maximum credit for having other characters in the new password\. If you have less than or
+\fIN\fR
+other characters, each character will count +1 towards meeting the current
+\fBminlen\fR
+value\. The default for
+\fBocredit\fR
+is 1 which is the recommended value for
+\fBminlen\fR
+less than 10\.
+.sp
+(N < 0) This is the minimum number of other characters that must be met for a new password\.
+.RE
+.PP
+\fBminclass=\fR\fB\fIN\fR\fR
+.RS 4
+The minimum number of required classes of characters for the new password\. The default number is zero\. The four classes are digits, upper and lower letters and other characters\. The difference to the
+\fBcredit\fR
+check is that a specific class if of characters is not required\. Instead
+\fIN\fR
+out of four of the classes are required\.
+.RE
+.PP
+\fBuse_authtok\fR
+.RS 4
+This argument is used to
+\fIforce\fR
+the module to not prompt the user for a new password but use the one provided by the previously stacked
+\fIpassword\fR
+module\.
+.RE
+.PP
+\fBdictpath=\fR\fB\fI/path/to/dict\fR\fR
+.RS 4
+Path to the cracklib dictionaries\.
+.RE
+.SH "MODULE SERVICES PROVIDED"
+.PP
+Only he
+\fBpassword\fR
+service is supported\.
+.SH "RETURN VALUES"
+.PP
+.PP
+PAM_SUCCESS
+.RS 4
+The new password passes all checks\.
+.RE
+.PP
+PAM_AUTHTOK_ERR
+.RS 4
+No new password was entered, the username could not be determined or the new password fails the strength checks\.
+.RE
+.PP
+PAM_AUTHTOK_RECOVERY_ERR
+.RS 4
+The old password was not supplied by a previous stacked module or got not requested from the user\. The first error can happen if
+\fBuse_authtok\fR
+is specified\.
+.RE
+.PP
+PAM_SERVICE_ERR
+.RS 4
+A internal error occured\.
+.RE
+.SH "EXAMPLES"
+.PP
+For an example of the use of this module, we show how it may be stacked with the password component of
+\fBpam_unix\fR(8)
+.sp
+.RS 4
+.nf
+#
+# These lines stack two password type modules\. In this example the
+# user is given 3 opportunities to enter a strong password\. The
+# "use_authtok" argument ensures that the pam_unix module does not
+# prompt for a password, but instead uses the one provided by
+# pam_cracklib\.
+#
+passwd password required pam_cracklib\.so retry=3
+passwd password required pam_unix\.so use_authtok
+
+.fi
+.RE
+.PP
+Another example (in the
+\fI/etc/pam\.d/passwd\fR
+format) is for the case that you want to use md5 password encryption:
+.sp
+.RS 4
+.nf
+#%PAM\-1\.0
+#
+# These lines allow a md5 systems to support passwords of at least 14
+# bytes with extra credit of 2 for digits and 2 for others the new
+# password must have at least three bytes that are not present in the
+# old password
+#
+password required pam_cracklib\.so \e
+ difok=3 minlen=15 dcredit= 2 ocredit=2
+password required pam_unix\.so use_authtok nullok md5
+
+.fi
+.RE
+.PP
+And here is another example in case you don\'t want to use credits:
+.sp
+.RS 4
+.nf
+#%PAM\-1\.0
+#
+# These lines require the user to select a password with a minimum
+# length of 8 and with at least 1 digit number, 1 upper case letter,
+# and 1 other character
+#
+password required pam_cracklib\.so \e
+ dcredit=\-1 ucredit=\-1 ocredit=\-1 lcredit=0 minlen=8
+password required pam_unix\.so use_authtok nullok md5
+
+.fi
+.RE
+.sp
+.SH "SEE ALSO"
+.PP
+
+\fBpam.conf\fR(5),
+\fBpam.d\fR(8),
+\fBpam\fR(8)
+.SH "AUTHOR"
+.PP
+pam_cracklib was written by Cristian Gafton <gafton@redhat\.com>
diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml
new file mode 100644
index 00000000..589e7b44
--- /dev/null
+++ b/modules/pam_cracklib/pam_cracklib.8.xml
@@ -0,0 +1,513 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="pam_cracklib">
+
+ <refmeta>
+ <refentrytitle>pam_cracklib</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="pam_cracklib-name">
+ <refname>pam_cracklib</refname>
+ <refpurpose>PAM module to check the password against dictionary words</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pam_cracklib-cmdsynopsis">
+ <command>pam_cracklib.so</command>
+ <arg choice="opt">
+ <replaceable>...</replaceable>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="pam_cracklib-description">
+
+ <title>DESCRIPTION</title>
+
+ <para>
+ This module can be plugged into the <emphasis>password</emphasis> stack of
+ a given application to provide some plug-in strength-checking for passwords.
+ </para>
+
+ <para>
+ The action of this module is to prompt the user for a password and
+ check its strength against a system dictionary and a set of rules for
+ identifying poor choices.
+ </para>
+
+ <para>
+ The first action is to prompt for a single password, check its
+ strength and then, if it is considered strong, prompt for the password
+ a second time (to verify that it was typed correctly on the first
+ occasion). All being well, the password is passed on to subsequent
+ modules to be installed as the new authentication token.
+ </para>
+
+ <para>
+ The strength checks works in the following manner: at first the
+ <function>Cracklib</function> routine is called to check if the password
+ is part of a dictionary; if this is not the case an additional set of
+ strength checks is done. These checks are:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Palindrome</term>
+ <listitem>
+ <para>
+ Is the new password a palindrome of the old one?
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case Change Only</term>
+ <listitem>
+ <para>
+ Is the new password the the old one with only a change of case?
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Similar</term>
+ <listitem>
+ <para>
+ Is the new password too much like the old one?
+ This is primarily controlled by one argument,
+ <option>difok</option> which is a number of characters
+ that if different between the old and new are enough to accept
+ the new password, this defaults to 10 or 1/2 the size of the
+ new password whichever is smaller.
+ </para>
+ <para>
+ To avoid the lockup associated with trying to change a long and
+ complicated password, <option>difignore</option> is available.
+ This argument can be used to specify the minimum length a new
+ password needs to be before the <option>difok</option> value is
+ ignored. The default value for <option>difignore</option> is 23.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Simple</term>
+ <listitem>
+ <para>
+ Is the new password too small?
+ This is controlled by 5 arguments <option>minlen</option>,
+ <option>dcredit</option>, <option>ucredit</option>,
+ <option>lcredit</option>, and <option>ocredit</option>. See the section
+ on the arguments for the details of how these work and there defaults.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Rotated</term>
+ <listitem>
+ <para>
+ Is the new password a rotated version of the old password?
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Already used</term>
+ <listitem>
+ <para>
+ Was the password used in the past? Previously used passwords
+ are to be found in <filename>/etc/security/opasswd</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ This module with no arguments will work well for standard unix
+ password encryption. With md5 encryption, passwords can be longer
+ than 8 characters and the default settings for this module can make it
+ hard for the user to choose a satisfactory new password. Notably, the
+ requirement that the new password contain no more than 1/2 of the
+ characters in the old password becomes a non-trivial constraint. For
+ example, an old password of the form "the quick brown fox jumped over
+ the lazy dogs" would be difficult to change... In addition, the
+ default action is to allow passwords as small as 5 characters in
+ length. For a md5 systems it can be a good idea to increase the
+ required minimum size of a password. One can then allow more credit
+ for different kinds of characters but accept that the new password may
+ share most of these characters with the old password.
+ </para>
+
+ </refsect1>
+
+ <refsect1 id="pam_cracklib-options">
+
+ <title>OPTIONS</title>
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>debug</option>
+ </term>
+ <listitem>
+ <para>
+ This option makes the module write information to
+ <citerefentry>
+ <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ indicating the behavior of the module (this option does
+ not write password information to the log file).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>type=<replaceable>XXX</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ The default action is for the module to use the
+ following prompts when requesting passwords:
+ "New UNIX password: " and "Retype UNIX password: ".
+ The default word <emphasis>UNIX</emphasis> can
+ be replaced with this option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>retry=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ Prompt user at most <replaceable>N</replaceable> times
+ before returning with error. The default is
+ <emphasis>1</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>difok=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ This argument will change the default of
+ <emphasis>5</emphasis> for the number of characters in
+ the new password that must not be present in the old
+ password. In addition, if 1/2 of the characters in the
+ new password are different then the new password will
+ be accepted anyway.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>difignore=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ How many characters should the password have before
+ difok will be ignored. The default is
+ <emphasis>23</emphasis>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>minlen=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ The minimum acceptable size for the new password (plus
+ one if credits are not disabled which is the default).
+ In addition to the number of characters in the new password,
+ credit (of +1 in length) is given for each different kind
+ of character (<emphasis>other</emphasis>,
+ <emphasis>upper</emphasis>, <emphasis>lower</emphasis> and
+ <emphasis>digit</emphasis>). The default for this parameter
+ is <emphasis>9</emphasis> which is good for a old style UNIX
+ password all of the same type of character but may be too low
+ to exploit the added security of a md5 system. Note that
+ there is a pair of length limits in
+ <emphasis>Cracklib</emphasis> itself, a "way too short" limit
+ of 4 which is hard coded in and a defined limit (6) that will
+ be checked without reference to <option>minlen</option>.
+ If you want to allow passwords as short as 5 characters you
+ should not use this module.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>dcredit=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ (N &gt;= 0) This is the maximum credit for having digits in
+ the new password. If you have less than or
+ <replaceable>N</replaceable>
+ digits, each digit will count +1 towards meeting the current
+ <option>minlen</option> value. The default for
+ <option>dcredit</option> is 1 which is the recommended
+ value for <option>minlen</option> less than 10.
+ </para>
+ <para>
+ (N &lt; 0) This is the minimum number of digits that must
+ be met for a new password.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>ucredit=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ (N &gt;= 0) This is the maximum credit for having upper
+ case letters in the new password. If you have less than
+ or <replaceable>N</replaceable> upper case letters each
+ letter will count +1 towards meeting the current
+ <option>minlen</option> value. The default for
+ <option>ucredit</option> is <emphasis>1</emphasis> which
+ is the recommended value for <option>minlen</option> less
+ than 10.
+ </para>
+ <para>
+ (N &gt; 0) This is the minimum number of upper
+ case letters that must be met for a new password.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>lcredit=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ (N &gt;= 0) This is the maximum credit for having
+ lower case letters in the new password. If you have
+ less than or <replaceable>N</replaceable> lower case
+ letters, each letter will count +1 towards meeting the
+ current <option>minlen</option> value. The default for
+ <option>lcredit</option> is 1 which is the recommended
+ value for <option>minlen</option> less than 10.
+ </para>
+ <para>
+ (N &lt; 0) This is the minimum number of lower
+ case letters that must be met for a new password.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>ocredit=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ (N &gt;= 0) This is the maximum credit for having other
+ characters in the new password. If you have less than or
+ <replaceable>N</replaceable> other characters, each
+ character will count +1 towards meeting the current
+ <option>minlen</option> value. The default for
+ <option>ocredit</option> is 1 which is the recommended
+ value for <option>minlen</option> less than 10.
+ </para>
+ <para>
+ (N &lt; 0) This is the minimum number of other
+ characters that must be met for a new password.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>minclass=<replaceable>N</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ The minimum number of required classes of characters for
+ the new password. The default number is zero. The four
+ classes are digits, upper and lower letters and other
+ characters.
+ The difference to the <option>credit</option> check is
+ that a specific class if of characters is not required.
+ Instead <replaceable>N</replaceable> out of four of the
+ classes are required.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>use_authtok</option>
+ </term>
+ <listitem>
+ <para>
+ This argument is used to <emphasis>force</emphasis> the
+ module to not prompt the user for a new password but use
+ the one provided by the previously stacked
+ <emphasis>password</emphasis> module.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>dictpath=<replaceable>/path/to/dict</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ Path to the cracklib dictionaries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_cracklib-services">
+ <title>MODULE SERVICES PROVIDED</title>
+ <para>
+ Only he <option>password</option> service is supported.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_cracklib-return_values'>
+ <title>RETURN VALUES</title>
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ The new password passes all checks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_AUTHTOK_ERR</term>
+ <listitem>
+ <para>
+ No new password was entered,
+ the username could not be determined or the new
+ password fails the strength checks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_AUTHTOK_RECOVERY_ERR</term>
+ <listitem>
+ <para>
+ The old password was not supplied by a previous stacked
+ module or got not requested from the user.
+ The first error can happen if <option>use_authtok</option>
+ is specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SERVICE_ERR</term>
+ <listitem>
+ <para>
+ A internal error occured.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_cracklib-examples'>
+ <title>EXAMPLES</title>
+ <para>
+ For an example of the use of this module, we show how it may be
+ stacked with the password component of
+ <citerefentry>
+ <refentrytitle>pam_unix</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ <programlisting>
+#
+# These lines stack two password type modules. In this example the
+# user is given 3 opportunities to enter a strong password. The
+# "use_authtok" argument ensures that the pam_unix module does not
+# prompt for a password, but instead uses the one provided by
+# pam_cracklib.
+#
+passwd password required pam_cracklib.so retry=3
+passwd password required pam_unix.so use_authtok
+ </programlisting>
+ </para>
+
+ <para>
+ Another example (in the <filename>/etc/pam.d/passwd</filename> format)
+ is for the case that you want to use md5 password encryption:
+ <programlisting>
+#%PAM-1.0
+#
+# These lines allow a md5 systems to support passwords of at least 14
+# bytes with extra credit of 2 for digits and 2 for others the new
+# password must have at least three bytes that are not present in the
+# old password
+#
+password required pam_cracklib.so \
+ difok=3 minlen=15 dcredit= 2 ocredit=2
+password required pam_unix.so use_authtok nullok md5
+ </programlisting>
+ </para>
+
+ <para>
+ And here is another example in case you don't want to use credits:
+ <programlisting>
+#%PAM-1.0
+#
+# These lines require the user to select a password with a minimum
+# length of 8 and with at least 1 digit number, 1 upper case letter,
+# and 1 other character
+#
+password required pam_cracklib.so \
+ dcredit=-1 ucredit=-1 ocredit=-1 lcredit=0 minlen=8
+password required pam_unix.so use_authtok nullok md5
+ </programlisting>
+ </para>
+
+ </refsect1>
+
+ <refsect1 id='pam_cracklib-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_cracklib-author'>
+ <title>AUTHOR</title>
+ <para>
+ pam_cracklib was written by Cristian Gafton &lt;gafton@redhat.com&gt;
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c
new file mode 100644
index 00000000..0c39f89d
--- /dev/null
+++ b/modules/pam_cracklib/pam_cracklib.c
@@ -0,0 +1,842 @@
+/*
+ * pam_cracklib module
+ */
+
+/*
+ * 0.9. switch to using a distance algorithm in similar()
+ * 0.86. added support for setting minimum numbers of digits, uppers,
+ * lowers, and others
+ * 0.85. added six new options to use this with long passwords.
+ * 0.8. tidied output and improved D(()) usage for debugging.
+ * 0.7. added support for more obscure checks for new passwd.
+ * 0.6. root can reset user passwd to any values (it's only warned)
+ * 0.5. supports retries - 'retry=N' argument
+ * 0.4. added argument 'type=XXX' for 'New XXX password' prompt
+ * 0.3. Added argument 'debug'
+ * 0.2. new password is feeded to cracklib for verify after typed once
+ * 0.1. First release
+ */
+
+/*
+ * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
+ * Long password support by Philip W. Dalrymple <pwd@mdtsoft.com> 1997/07/18
+ * See the end of the file for Copyright Information
+ *
+ * Modification for long password systems (>8 chars). The original
+ * module had problems when used in a md5 password system in that it
+ * allowed too short passwords but required that at least half of the
+ * bytes in the new password did not appear in the old one. this
+ * action is still the default and the changes should not break any
+ * current user. This modification adds 6 new options, one to set the
+ * number of bytes in the new password that are not in the old one,
+ * the other five to control the length checking, these are all
+ * documented (or will be before anyone else sees this code) in the PAM
+ * S.A.G. in the section on the cracklib module.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_CRYPT_H
+# include <crypt.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <limits.h>
+
+#ifdef HAVE_CRACK_H
+#include <crack.h>
+#else
+extern char *FascistCheck(char *pw, const char *dictpath);
+#endif
+
+#ifndef CRACKLIB_DICTS
+#define CRACKLIB_DICTS NULL
+#endif
+
+/* For Translators: "%s%s" could be replaced with "<service> " or "". */
+#define PROMPT1 _("New %s%spassword: ")
+/* For Translators: "%s%s" could be replaced with "<service> " or "". */
+#define PROMPT2 _("Retype new %s%spassword: ")
+#define MISTYPED_PASS _("Sorry, passwords do not match.")
+
+#ifdef MIN
+#undef MIN
+#endif
+#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
+
+/*
+ * here, we make a definition for the externally accessible function
+ * in this file (this definition is required for static a module
+ * but strongly encouraged generally) it is used to instruct the
+ * modules include file to define the function prototypes.
+ */
+
+#define PAM_SM_PASSWORD
+
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+#include <security/pam_ext.h>
+
+/* argument parsing */
+#define PAM_DEBUG_ARG 0x0001
+
+struct cracklib_options {
+ int retry_times;
+ int diff_ok;
+ int diff_ignore;
+ int min_length;
+ int dig_credit;
+ int up_credit;
+ int low_credit;
+ int oth_credit;
+ int min_class;
+ int use_authtok;
+ char prompt_type[BUFSIZ];
+ const char *cracklib_dictpath;
+};
+
+#define CO_RETRY_TIMES 1
+#define CO_DIFF_OK 5
+#define CO_DIFF_IGNORE 23
+#define CO_MIN_LENGTH 9
+# define CO_MIN_LENGTH_BASE 5
+#define CO_DIG_CREDIT 1
+#define CO_UP_CREDIT 1
+#define CO_LOW_CREDIT 1
+#define CO_OTH_CREDIT 1
+#define CO_USE_AUTHTOK 0
+
+static int
+_pam_parse (pam_handle_t *pamh, struct cracklib_options *opt,
+ int argc, const char **argv)
+{
+ int ctrl=0;
+
+ /* step through arguments */
+ for (ctrl=0; argc-- > 0; ++argv) {
+ char *ep = NULL;
+
+ /* generic options */
+
+ if (!strcmp(*argv,"debug"))
+ ctrl |= PAM_DEBUG_ARG;
+ else if (!strncmp(*argv,"type=",5))
+ strncpy(opt->prompt_type, *argv+5, sizeof(opt->prompt_type) - 1);
+ else if (!strncmp(*argv,"retry=",6)) {
+ opt->retry_times = strtol(*argv+6,&ep,10);
+ if (!ep || (opt->retry_times < 1))
+ opt->retry_times = CO_RETRY_TIMES;
+ } else if (!strncmp(*argv,"difok=",6)) {
+ opt->diff_ok = strtol(*argv+6,&ep,10);
+ if (!ep || (opt->diff_ok < 0))
+ opt->diff_ok = CO_DIFF_OK;
+ } else if (!strncmp(*argv,"difignore=",10)) {
+ opt->diff_ignore = strtol(*argv+10,&ep,10);
+ if (!ep || (opt->diff_ignore < 0))
+ opt->diff_ignore = CO_DIFF_IGNORE;
+ } else if (!strncmp(*argv,"minlen=",7)) {
+ opt->min_length = strtol(*argv+7,&ep,10);
+ if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE))
+ opt->min_length = CO_MIN_LENGTH_BASE;
+ } else if (!strncmp(*argv,"dcredit=",8)) {
+ opt->dig_credit = strtol(*argv+8,&ep,10);
+ if (!ep)
+ opt->dig_credit = 0;
+ } else if (!strncmp(*argv,"ucredit=",8)) {
+ opt->up_credit = strtol(*argv+8,&ep,10);
+ if (!ep)
+ opt->up_credit = 0;
+ } else if (!strncmp(*argv,"lcredit=",8)) {
+ opt->low_credit = strtol(*argv+8,&ep,10);
+ if (!ep)
+ opt->low_credit = 0;
+ } else if (!strncmp(*argv,"ocredit=",8)) {
+ opt->oth_credit = strtol(*argv+8,&ep,10);
+ if (!ep)
+ opt->oth_credit = 0;
+ } else if (!strncmp(*argv,"minclass=",9)) {
+ opt->min_class = strtol(*argv+9,&ep,10);
+ if (!ep)
+ opt->min_class = 0;
+ if (opt->min_class > 4)
+ opt->min_class = 4 ;
+ } else if (!strncmp(*argv,"use_authtok",11)) {
+ opt->use_authtok = 1;
+ } else if (!strncmp(*argv,"dictpath=",9)) {
+ opt->cracklib_dictpath = *argv+9;
+ if (!*(opt->cracklib_dictpath)) {
+ opt->cracklib_dictpath = CRACKLIB_DICTS;
+ }
+ } else {
+ pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv);
+ }
+ }
+ opt->prompt_type[sizeof(opt->prompt_type) - 1] = '\0';
+
+ return ctrl;
+}
+
+/* Helper functions */
+
+/* use this to free strings. ESPECIALLY password strings */
+static char *_pam_delete(register char *xx)
+{
+ _pam_overwrite(xx);
+ free(xx);
+ return NULL;
+}
+
+/*
+ * can't be a palindrome - like `R A D A R' or `M A D A M'
+ */
+static int palindrome(const char *new)
+{
+ int i, j;
+
+ i = strlen (new);
+
+ for (j = 0;j < i;j++)
+ if (new[i - j - 1] != new[j])
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Calculate how different two strings are in terms of the number of
+ * character removals, additions, and changes needed to go from one to
+ * the other
+ */
+
+static int distdifferent(const char *old, const char *new,
+ size_t i, size_t j)
+{
+ char c, d;
+
+ if ((i == 0) || (strlen(old) < i)) {
+ c = 0;
+ } else {
+ c = old[i - 1];
+ }
+ if ((j == 0) || (strlen(new) < j)) {
+ d = 0;
+ } else {
+ d = new[j - 1];
+ }
+ return (c != d);
+}
+
+static int distcalculate(int **distances, const char *old, const char *new,
+ size_t i, size_t j)
+{
+ int tmp = 0;
+
+ if (distances[i][j] != -1) {
+ return distances[i][j];
+ }
+
+ tmp = distcalculate(distances, old, new, i - 1, j - 1);
+ tmp = MIN(tmp, distcalculate(distances, old, new, i, j - 1));
+ tmp = MIN(tmp, distcalculate(distances, old, new, i - 1, j));
+ tmp += distdifferent(old, new, i, j);
+
+ distances[i][j] = tmp;
+
+ return tmp;
+}
+
+static int distance(const char *old, const char *new)
+{
+ int **distances = NULL;
+ size_t m, n, i, j, r;
+
+ m = strlen(old);
+ n = strlen(new);
+ distances = malloc(sizeof(int*) * (m + 1));
+
+ for (i = 0; i <= m; i++) {
+ distances[i] = malloc(sizeof(int) * (n + 1));
+ for(j = 0; j <= n; j++) {
+ distances[i][j] = -1;
+ }
+ }
+ for (i = 0; i <= m; i++) {
+ distances[i][0] = i;
+ }
+ for (j = 0; j <= n; j++) {
+ distances[0][j] = j;
+ }
+ distances[0][0] = 0;
+
+ r = distcalculate(distances, old, new, m, n);
+
+ for (i = 0; i <= m; i++) {
+ memset(distances[i], 0, sizeof(int) * (n + 1));
+ free(distances[i]);
+ }
+ free(distances);
+
+ return r;
+}
+
+static int similar(struct cracklib_options *opt,
+ const char *old, const char *new)
+{
+ if (distance(old, new) >= opt->diff_ok) {
+ return 0;
+ }
+
+ if (strlen(new) >= (strlen(old) * 2)) {
+ return 0;
+ }
+
+ /* passwords are too similar */
+ return 1;
+}
+
+/*
+ * enough classes of charecters
+ */
+
+static int minclass (struct cracklib_options *opt,
+ const char *new)
+{
+ int digits = 0;
+ int uppers = 0;
+ int lowers = 0;
+ int others = 0;
+ int total_class;
+ int i;
+ int retval;
+
+ D(( "called" ));
+ for (i = 0; new[i]; i++)
+ {
+ if (isdigit (new[i]))
+ digits = 1;
+ else if (isupper (new[i]))
+ uppers = 1;
+ else if (islower (new[i]))
+ lowers = 1;
+ else
+ others = 1;
+ }
+
+ total_class = digits + uppers + lowers + others;
+
+ D (("total class: %d\tmin_class: %d", total_class, opt->min_class));
+
+ if (total_class >= opt->min_class)
+ retval = 0;
+ else
+ retval = 1;
+
+ return retval;
+}
+
+
+/*
+ * a nice mix of characters.
+ */
+static int simple(struct cracklib_options *opt, const char *new)
+{
+ int digits = 0;
+ int uppers = 0;
+ int lowers = 0;
+ int others = 0;
+ int size;
+ int i;
+
+ for (i = 0;new[i];i++) {
+ if (isdigit (new[i]))
+ digits++;
+ else if (isupper (new[i]))
+ uppers++;
+ else if (islower (new[i]))
+ lowers++;
+ else
+ others++;
+ }
+
+ /*
+ * The scam was this - a password of only one character type
+ * must be 8 letters long. Two types, 7, and so on.
+ * This is now changed, the base size and the credits or defaults
+ * see the docs on the module for info on these parameters, the
+ * defaults cause the effect to be the same as before the change
+ */
+
+ if ((opt->dig_credit >= 0) && (digits > opt->dig_credit))
+ digits = opt->dig_credit;
+
+ if ((opt->up_credit >= 0) && (uppers > opt->up_credit))
+ uppers = opt->up_credit;
+
+ if ((opt->low_credit >= 0) && (lowers > opt->low_credit))
+ lowers = opt->low_credit;
+
+ if ((opt->oth_credit >= 0) && (others > opt->oth_credit))
+ others = opt->oth_credit;
+
+ size = opt->min_length;
+
+ if (opt->dig_credit >= 0)
+ size -= digits;
+ else if (digits < opt->dig_credit * -1)
+ return 1;
+
+ if (opt->up_credit >= 0)
+ size -= uppers;
+ else if (uppers < opt->up_credit * -1)
+ return 1;
+
+ if (opt->low_credit >= 0)
+ size -= lowers;
+ else if (lowers < opt->low_credit * -1)
+ return 1;
+
+ if (opt->oth_credit >= 0)
+ size -= others;
+ else if (others < opt->oth_credit * -1)
+ return 1;
+
+ if (size <= i)
+ return 0;
+
+ return 1;
+}
+
+static char * str_lower(char *string)
+{
+ char *cp;
+
+ for (cp = string; *cp; cp++)
+ *cp = tolower(*cp);
+ return string;
+}
+
+static const char *password_check(struct cracklib_options *opt,
+ const char *old, const char *new)
+{
+ const char *msg = NULL;
+ char *oldmono = NULL, *newmono, *wrapped = NULL;
+
+ if (old && strcmp(new, old) == 0) {
+ msg = _("is the same as the old one");
+ return msg;
+ }
+
+ newmono = str_lower(x_strdup(new));
+ if (old) {
+ oldmono = str_lower(x_strdup(old));
+ wrapped = malloc(strlen(oldmono) * 2 + 1);
+ strcpy (wrapped, oldmono);
+ strcat (wrapped, oldmono);
+ }
+
+ if (palindrome(newmono))
+ msg = _("is a palindrome");
+
+ if (!msg && oldmono && strcmp(oldmono, newmono) == 0)
+ msg = _("case changes only");
+
+ if (!msg && oldmono && similar(opt, oldmono, newmono))
+ msg = _("is too similar to the old one");
+
+ if (!msg && simple(opt, new))
+ msg = _("is too simple");
+
+ if (!msg && wrapped && strstr(wrapped, newmono))
+ msg = _("is rotated");
+
+ if (!msg && minclass (opt, new))
+ msg = _("not enough character classes");
+
+ memset(newmono, 0, strlen(newmono));
+ free(newmono);
+ if (old) {
+ memset(oldmono, 0, strlen(oldmono));
+ memset(wrapped, 0, strlen(wrapped));
+ free(oldmono);
+ free(wrapped);
+ }
+
+ return msg;
+}
+
+
+#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
+
+static const char * check_old_password(const char *forwho, const char *newpass)
+{
+ static char buf[16384];
+ char *s_luser, *s_uid, *s_npas, *s_pas;
+ const char *msg = NULL;
+ FILE *opwfile;
+
+ opwfile = fopen(OLD_PASSWORDS_FILE, "r");
+ if (opwfile == NULL)
+ return NULL;
+
+ while (fgets(buf, 16380, opwfile)) {
+ if (!strncmp(buf, forwho, strlen(forwho))) {
+ char *sptr;
+ buf[strlen(buf)-1] = '\0';
+ s_luser = strtok_r(buf, ":,", &sptr);
+ s_uid = strtok_r(NULL, ":,", &sptr);
+ s_npas = strtok_r(NULL, ":,", &sptr);
+ s_pas = strtok_r(NULL, ":,", &sptr);
+ while (s_pas != NULL) {
+ if (!strcmp(crypt(newpass, s_pas), s_pas)) {
+ msg = _("has been already used");
+ break;
+ }
+ s_pas = strtok_r(NULL, ":,", &sptr);
+ }
+ break;
+ }
+ }
+ fclose(opwfile);
+
+ return msg;
+}
+
+
+static int _pam_unix_approve_pass(pam_handle_t *pamh,
+ unsigned int ctrl,
+ struct cracklib_options *opt,
+ const char *pass_old,
+ const char *pass_new)
+{
+ const char *msg = NULL;
+ const void *user;
+ int retval;
+
+ if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh, LOG_DEBUG, "bad authentication token");
+ pam_error(pamh, "%s", pass_new == NULL ?
+ _("No password supplied"):_("Password unchanged"));
+ return PAM_AUTHTOK_ERR;
+ }
+
+ /*
+ * if one wanted to hardwire authentication token strength
+ * checking this would be the place
+ */
+ msg = password_check(opt, pass_old, pass_new);
+ if (!msg) {
+ retval = pam_get_item(pamh, PAM_USER, &user);
+ if (retval != PAM_SUCCESS || user == NULL) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_ERR,"Can not get username");
+ return PAM_AUTHTOK_ERR;
+ }
+ msg = check_old_password(user, pass_new);
+ }
+
+ if (msg) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh, LOG_NOTICE,
+ "new passwd fails strength check: %s", msg);
+ pam_error(pamh, _("BAD PASSWORD: %s"), msg);
+ return PAM_AUTHTOK_ERR;
+ };
+ return PAM_SUCCESS;
+
+}
+
+/* The Main Thing (by Cristian Gafton, CEO at this module :-)
+ * (stolen from http://home.netscape.com)
+ */
+PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
+ int argc, const char **argv)
+{
+ unsigned int ctrl;
+ struct cracklib_options options;
+
+ D(("called."));
+
+ memset(&options, 0, sizeof(options));
+ options.retry_times = CO_RETRY_TIMES;
+ options.diff_ok = CO_DIFF_OK;
+ options.diff_ignore = CO_DIFF_IGNORE;
+ options.min_length = CO_MIN_LENGTH;
+ options.dig_credit = CO_DIG_CREDIT;
+ options.up_credit = CO_UP_CREDIT;
+ options.low_credit = CO_LOW_CREDIT;
+ options.oth_credit = CO_OTH_CREDIT;
+ options.use_authtok = CO_USE_AUTHTOK;
+ memset(options.prompt_type, 0, BUFSIZ);
+ strcpy(options.prompt_type,"UNIX");
+ options.cracklib_dictpath = CRACKLIB_DICTS;
+
+ ctrl = _pam_parse(pamh, &options, argc, argv);
+
+ if (flags & PAM_PRELIM_CHECK) {
+ /* Check for passwd dictionary */
+ /* We cannot do that, since the original path is compiled
+ into the cracklib library and we don't know it. */
+ return PAM_SUCCESS;
+ } else if (flags & PAM_UPDATE_AUTHTOK) {
+ int retval;
+ char *token1, *token2, *resp;
+ const void *oldtoken;
+
+ D(("do update"));
+ retval = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldtoken);
+ if (retval != PAM_SUCCESS) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_ERR,"Can not get old passwd");
+ oldtoken=NULL;
+ retval = PAM_SUCCESS;
+ }
+
+ do {
+ /*
+ * make sure nothing inappropriate gets returned
+ */
+ token1 = token2 = NULL;
+
+ if (!options.retry_times) {
+ D(("returning %s because maxtries reached",
+ pam_strerror(pamh, retval)));
+ return retval;
+ }
+
+ /* Planned modus operandi:
+ * Get a passwd.
+ * Verify it against cracklib.
+ * If okay get it a second time.
+ * Check to be the same with the first one.
+ * set PAM_AUTHTOK and return
+ */
+
+ if (options.use_authtok == 1) {
+ const void *item = NULL;
+
+ retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
+ if (retval != PAM_SUCCESS) {
+ /* very strange. */
+ pam_syslog(pamh, LOG_ALERT,
+ "pam_get_item returned error to pam_cracklib");
+ } else if (item != NULL) { /* we have a password! */
+ token1 = x_strdup(item);
+ item = NULL;
+ } else {
+ retval = PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */
+ }
+
+ } else {
+ /* Prepare to ask the user for the first time */
+ resp = NULL;
+ retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
+ PROMPT1, options.prompt_type,
+ options.prompt_type[0]?" ":"");
+
+ if (retval == PAM_SUCCESS) { /* a good conversation */
+ token1 = resp;
+ if (token1 == NULL) {
+ pam_syslog(pamh, LOG_NOTICE,
+ "could not recover authentication token 1");
+ retval = PAM_AUTHTOK_RECOVERY_ERR;
+ }
+ } else {
+ retval = (retval == PAM_SUCCESS) ?
+ PAM_AUTHTOK_RECOVERY_ERR:retval ;
+ }
+ }
+
+ if (retval != PAM_SUCCESS) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_DEBUG,"unable to obtain a password");
+ continue;
+ }
+
+ D(("testing password, retval = %s", pam_strerror(pamh, retval)));
+ /* now test this passwd against cracklib */
+ {
+ const char *crack_msg;
+
+ D(("against cracklib"));
+ if ((crack_msg = FascistCheck(token1,options.cracklib_dictpath))) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_DEBUG,"bad password: %s",crack_msg);
+ pam_error(pamh, _("BAD PASSWORD: %s"), crack_msg);
+ if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
+ retval = PAM_AUTHTOK_ERR;
+ else
+ retval = PAM_SUCCESS;
+ } else {
+ /* check it for strength too... */
+ D(("for strength"));
+ retval = _pam_unix_approve_pass (pamh, ctrl, &options,
+ oldtoken, token1);
+ if (retval != PAM_SUCCESS) {
+ if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
+ retval = PAM_AUTHTOK_ERR;
+ else
+ retval = PAM_SUCCESS;
+ }
+ }
+ }
+
+ D(("after testing: retval = %s", pam_strerror(pamh, retval)));
+ /* if cracklib/strength check said it is a bad passwd... */
+ if ((retval != PAM_SUCCESS) && (retval != PAM_IGNORE)) {
+ int temp_unused;
+
+ temp_unused = pam_set_item(pamh, PAM_AUTHTOK, NULL);
+ token1 = _pam_delete(token1);
+ continue;
+ }
+
+ /* Now we have a good passwd. Ask for it once again */
+
+ if (options.use_authtok == 0) {
+ resp = NULL;
+ retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
+ PROMPT2, options.prompt_type,
+ options.prompt_type[0]?" ":"");
+ if (retval == PAM_SUCCESS) { /* a good conversation */
+ token2 = resp;
+ if (token2 == NULL) {
+ pam_syslog(pamh,LOG_NOTICE,
+ "could not recover authentication token 2");
+ retval = PAM_AUTHTOK_RECOVERY_ERR;
+ }
+ }
+
+ /* No else, the a retval == PAM_SUCCESS path can change retval
+ to a failure code. */
+ if (retval != PAM_SUCCESS) {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_DEBUG,"unable to obtain retyped password");
+ continue;
+ }
+
+ /* Hopefully now token1 and token2 the same password ... */
+ if (strcmp(token1,token2) != 0) {
+ /* tell the user */
+ pam_error(pamh, "%s", MISTYPED_PASS);
+ token1 = _pam_delete(token1);
+ token2 = _pam_delete(token2);
+ pam_set_item(pamh, PAM_AUTHTOK, NULL);
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh,LOG_NOTICE,"Password mistyped");
+ retval = PAM_AUTHTOK_RECOVERY_ERR;
+ continue;
+ }
+
+ /* Yes, the password was typed correct twice
+ * we store this password as an item
+ */
+
+ {
+ const void *item = NULL;
+
+ retval = pam_set_item(pamh, PAM_AUTHTOK, token1);
+
+ /* clean up */
+ token1 = _pam_delete(token1);
+ token2 = _pam_delete(token2);
+
+ if ( (retval != PAM_SUCCESS) ||
+ ((retval = pam_get_item(pamh, PAM_AUTHTOK, &item)
+ ) != PAM_SUCCESS) ) {
+ pam_syslog(pamh, LOG_CRIT, "error manipulating password");
+ continue;
+ }
+ item = NULL; /* break link to password */
+ return PAM_SUCCESS;
+ }
+ }
+
+ } while (options.retry_times--);
+
+ } else {
+ if (ctrl & PAM_DEBUG_ARG)
+ pam_syslog(pamh, LOG_NOTICE, "UNKNOWN flags setting %02X",flags);
+ return PAM_SERVICE_ERR;
+ }
+
+ /* Not reached */
+ return PAM_SERVICE_ERR;
+}
+
+
+
+#ifdef PAM_STATIC
+/* static module data */
+struct pam_module _pam_cracklib_modstruct = {
+ "pam_cracklib",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ pam_sm_chauthtok
+};
+#endif
+
+/*
+ * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996.
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The following copyright was appended for the long password support
+ * added with the libpam 0.58 release:
+ *
+ * Modificaton Copyright (c) Philip W. Dalrymple III <pwd@mdtsoft.com>
+ * 1997. All rights reserved
+ *
+ * THE MODIFICATION THAT PROVIDES SUPPORT FOR LONG PASSWORD TYPE CHECKING TO
+ * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/modules/pam_cracklib/tst-pam_cracklib b/modules/pam_cracklib/tst-pam_cracklib
new file mode 100755
index 00000000..46a7060d
--- /dev/null
+++ b/modules/pam_cracklib/tst-pam_cracklib
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_cracklib.so