diff --git a/Linux-PAM-1.4.0-docs.tar.xz b/Linux-PAM-1.4.0-docs.tar.xz deleted file mode 100644 index 273819e..0000000 --- a/Linux-PAM-1.4.0-docs.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:351764a0643052564a4b840320744c7e402112a2a57d2ac04511a6d22dc52e04 -size 477712 diff --git a/Linux-PAM-1.4.0.tar.xz b/Linux-PAM-1.4.0.tar.xz deleted file mode 100644 index fedf45f..0000000 --- a/Linux-PAM-1.4.0.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd6d928c51e64139be3bdb38692c68183a509b83d4f2c221024ccd4bcddfd034 -size 988908 diff --git a/Linux-PAM-1.5.0-docs.tar.xz b/Linux-PAM-1.5.0-docs.tar.xz new file mode 100644 index 0000000..f465fd7 --- /dev/null +++ b/Linux-PAM-1.5.0-docs.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75fefd2a601c76d5e289aa8c36234ec2ac398395f4a48caf5ef638c1131019a9 +size 441644 diff --git a/Linux-PAM-1.5.0.tar.xz b/Linux-PAM-1.5.0.tar.xz new file mode 100644 index 0000000..d5f6b23 --- /dev/null +++ b/Linux-PAM-1.5.0.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02d39854b508fae9dc713f7733bbcdadbe17b50de965aedddd65bcb6cc7852c8 +size 972228 diff --git a/pam-bsc1177858-dont-free-environment-string.patch b/pam-bsc1177858-dont-free-environment-string.patch new file mode 100644 index 0000000..9a9670b --- /dev/null +++ b/pam-bsc1177858-dont-free-environment-string.patch @@ -0,0 +1,26 @@ +Index: Linux-PAM-1.4.0/modules/pam_xauth/pam_xauth.c +=================================================================== +--- Linux-PAM-1.4.0.orig/modules/pam_xauth/pam_xauth.c ++++ Linux-PAM-1.4.0/modules/pam_xauth/pam_xauth.c +@@ -701,8 +701,9 @@ pam_sm_open_session (pam_handle_t *pamh, + pam_syslog(pamh, LOG_ERR, + "can't set environment variable '%s'", + xauthority); +- putenv (xauthority); /* The environment owns this string now. */ +- /* Don't free environment variables nor set them to NULL. */ ++ if (putenv (xauthority) == 0) /* The environment owns this string now. */ ++ xauthority = NULL; ++ /* Don't free environment variables. */ + + /* set $DISPLAY in pam handle to make su - work */ + { +@@ -765,7 +766,8 @@ cleanup: + unsetenv (XAUTHENV); + free(cookiefile); + free(cookie); +- free(xauthority); ++ if (xauthority != NULL) /* If it hasn't been successfully passed to putenv() ... */ ++ free(xauthority); + return retval; + } + diff --git a/pam-login_defs-check.sh b/pam-login_defs-check.sh index d1f9e38..b559d79 100644 --- a/pam-login_defs-check.sh +++ b/pam-login_defs-check.sh @@ -9,10 +9,10 @@ set -o errexit echo -n "Checking login.defs variables in pam... " >&2 grep -rh LOGIN_DEFS . | - sed -n 's/^.*search_key *("\([A-Z0-9_]*\)", *LOGIN_DEFS).*$/\1/p' | + sed -n 's/^.*search_key *([A-Za-z_]*, *[A-Z_]*LOGIN_DEFS, *"\([A-Z0-9_]*\)").*$/\1/p' | LC_ALL=C sort -u >pam-login_defs-vars.lst -if test $(sha1sum pam-login_defs-vars.lst | sed 's/ .*$//') != da39a3ee5e6b4b0d3255bfef95601890afd80709 ; then +if test $(sha1sum pam-login_defs-vars.lst | sed 's/ .*$//') != 3c6e0020c31609690b69ef391654df930b74151d ; then echo "does not match!" >&2 echo "Checksum is: $(sha1sum pam-login_defs-vars.lst | sed 's/ .*$//')" >&2 diff --git a/pam-pam_cracklib-add-usersubstr.patch b/pam-pam_cracklib-add-usersubstr.patch new file mode 100644 index 0000000..8478271 --- /dev/null +++ b/pam-pam_cracklib-add-usersubstr.patch @@ -0,0 +1,81 @@ +Index: Linux-PAM-1.4.0/modules/pam_cracklib/pam_cracklib.c +=================================================================== +--- Linux-PAM-1.4.0.orig/modules/pam_cracklib/pam_cracklib.c ++++ Linux-PAM-1.4.0/modules/pam_cracklib/pam_cracklib.c +@@ -88,6 +88,7 @@ struct cracklib_options { + int reject_user; + int gecos_check; + int enforce_for_root; ++ int user_substr; + const char *cracklib_dictpath; + }; + +@@ -185,6 +186,10 @@ _pam_parse (pam_handle_t *pamh, struct c + if (!*(opt->cracklib_dictpath)) { + opt->cracklib_dictpath = CRACKLIB_DICTS; + } ++ } else if ((str = pam_str_skip_prefix(*argv, "usersubstr=")) != NULL) { ++ opt->user_substr = strtol(str, &ep, 10); ++ if (ep == str) ++ opt->user_substr = 0; + } else { + pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv); + } +@@ -525,13 +530,54 @@ static int wordcheck(const char *new, ch + return 0; + } + ++/* ++ * RETURNS: True if the password is unacceptable, else false ++ */ ++static int usersubstr(int len, const char *new, char *user) ++{ ++ int i, userlen; ++ int bad = 0; // Assume it's OK unless proven otherwise ++ char *subuser = calloc(len+1, sizeof(char)); ++ ++ if (subuser == NULL) { ++ return 1; ++ } ++ ++ userlen = strlen(user); ++ ++ if (len >= CO_MIN_WORD_LENGTH && ++ userlen > len) { ++ for(i = 0; !bad && (i <= userlen - len); i++) { ++ strncpy(subuser, user+i, len+1); ++ subuser[len] = '\0'; ++ bad = wordcheck(new, subuser); ++ } ++ } else { ++ // if we already tested substrings, there's no need to test ++ // the whole username; all substrings would've been found :) ++ if (!bad) ++ bad = wordcheck(new, user); ++ } ++ ++ free(subuser); ++ ++ return bad; ++} ++ ++/* ++ * RETURNS: True if the password is unacceptable, else false ++ */ + static int usercheck(struct cracklib_options *opt, const char *new, + char *user) + { +- if (!opt->reject_user) +- return 0; ++ int bad = 0; ++ ++ if (opt->reject_user) ++ bad = wordcheck(new, user); ++ if (!bad && opt->user_substr != 0) ++ bad = usersubstr(opt->user_substr, new, user); + +- return wordcheck(new, user); ++ return bad; + } + + static char * str_lower(char *string) diff --git a/pam-xauth_ownership.patch b/pam-xauth_ownership.patch new file mode 100644 index 0000000..9fed067 --- /dev/null +++ b/pam-xauth_ownership.patch @@ -0,0 +1,105 @@ +diff -urN Linux-PAM-1.5.0/modules/pam_xauth/pam_xauth.c Linux-PAM-1.5.0.xauth/modules/pam_xauth/pam_xauth.c +--- Linux-PAM-1.5.0/modules/pam_xauth/pam_xauth.c 2020-11-10 16:46:13.000000000 +0100 ++++ Linux-PAM-1.5.0.xauth/modules/pam_xauth/pam_xauth.c 2020-11-19 11:50:54.176925556 +0100 +@@ -355,11 +355,13 @@ + char *cookiefile = NULL, *xauthority = NULL, + *cookie = NULL, *display = NULL, *tmp = NULL, + *xauthlocalhostname = NULL; +- const char *user, *xauth = NULL; ++ const char *user, *xauth = NULL, *login_name; + struct passwd *tpwd, *rpwd; + int fd, i, debug = 0; + int retval = PAM_SUCCESS; +- uid_t systemuser = 499, targetuser = 0; ++ uid_t systemuser = 499, targetuser = 0, uid; ++ gid_t gid; ++ struct stat st; + + /* Parse arguments. We don't understand many, so no sense in breaking + * this into a separate function. */ +@@ -429,7 +431,16 @@ + retval = PAM_SESSION_ERR; + goto cleanup; + } +- rpwd = pam_modutil_getpwuid(pamh, getuid()); ++ ++ login_name = pam_modutil_getlogin(pamh); ++ if (login_name == NULL) { ++ login_name = ""; ++ } ++ if (*login_name) ++ rpwd = pam_modutil_getpwnam(pamh, login_name); ++ else ++ rpwd = pam_modutil_getpwuid(pamh, getuid()); ++ + if (rpwd == NULL) { + pam_syslog(pamh, LOG_ERR, + "error determining invoking user's name"); +@@ -518,18 +529,26 @@ + cookiefile); + } + ++ /* Get owner and group of the cookiefile */ ++ uid = getuid(); ++ gid = getgid(); ++ if (stat(cookiefile, &st) == 0) { ++ uid = st.st_uid; ++ gid = st.st_gid; ++ } ++ + /* Read the user's .Xauthority file. Because the current UID is + * the original user's UID, this will only fail if something has + * gone wrong, or we have no cookies. */ + if (debug) { + pam_syslog(pamh, LOG_DEBUG, +- "running \"%s %s %s %s %s\" as %lu/%lu", +- xauth, "-f", cookiefile, "nlist", display, +- (unsigned long) getuid(), (unsigned long) getgid()); ++ "running \"%s %s %s %s %s %s\" as %lu/%lu", ++ xauth, "-i", "-f", cookiefile, "nlist", display, ++ (unsigned long) uid, (unsigned long) gid); + } + if (run_coprocess(pamh, NULL, &cookie, +- getuid(), getgid(), +- xauth, "-f", cookiefile, "nlist", display, ++ uid, gid, ++ xauth, "-i", "-f", cookiefile, "nlist", display, + NULL) == 0) { + #ifdef WITH_SELINUX + char *context_raw = NULL; +@@ -583,12 +602,12 @@ + cookiefile, + "nlist", + t, +- (unsigned long) getuid(), +- (unsigned long) getgid()); ++ (unsigned long) uid, ++ (unsigned long) gid); + } + run_coprocess(pamh, NULL, &cookie, +- getuid(), getgid(), +- xauth, "-f", cookiefile, ++ uid, gid, ++ xauth, "-i", "-f", cookiefile, + "nlist", t, NULL); + } + free(t); +@@ -673,13 +692,17 @@ + goto cleanup; + } + ++ if (debug) { ++ pam_syslog(pamh, LOG_DEBUG, "set environment variable '%s'", ++ xauthority); ++ } + /* Set the new variable in the environment. */ + if (pam_putenv (pamh, xauthority) != PAM_SUCCESS) + pam_syslog(pamh, LOG_ERR, + "can't set environment variable '%s'", + xauthority); + putenv (xauthority); /* The environment owns this string now. */ +- xauthority = NULL; /* Don't free environment variables. */ ++ /* Don't free environment variables nor set them to NULL. */ + + /* set $DISPLAY in pam handle to make su - work */ + { diff --git a/pam.changes b/pam.changes index f2c199e..c43791d 100644 --- a/pam.changes +++ b/pam.changes @@ -1,3 +1,82 @@ +------------------------------------------------------------------- +Thu Nov 19 15:43:33 UTC 2020 - Thorsten Kukuk + +- Update to 1.5.0 + - obsoletes pam-bsc1178727-initialize-daysleft.patch + - Multiple minor bug fixes, portability fixes, and documentation improvements. + - Extended libpam API with pam_modutil_check_user_in_passwd function. + - pam_faillock: changed /run/faillock/$USER permissions from 0600 to 0660. + - pam_motd: read motd files with target user credentials skipping unreadable ones. + - pam_pwhistory: added a SELinux helper executable. + - pam_unix, pam_usertype: implemented avoidance of certain timing attacks. + - pam_wheel: implemented PAM_RUSER fallback for the case when getlogin fails. + - pam_env: Reading of the user environment is deprecated and will be removed + at some point in the future. + - libpam: pam_modutil_drop_priv() now correctly sets the target user's + supplementary groups, allowing pam_motd to filter messages accordingly +- Refresh pam-xauth_ownership.patch +- pam_tally2-removal.patch: Re-add pam_tally2 for deprecated sub-package +- pam_cracklib-removal.patch: Re-add pam_cracklib for deprecated sub-package + +------------------------------------------------------------------- +Wed Nov 18 13:02:15 UTC 2020 - Josef Möllers + +- pam_cracklib: added code to check whether the password contains + a substring of of the user's name of at least characters length + in some form. + This is enabled by the new parameter "usersubstr=" + See https://github.com/libpwquality/libpwquality/commit/bfef79dbe6aa525e9557bf4b0a61e6dde12749c4 + [jsc#SLE-16719, jsc#SLE-16720, pam-pam_cracklib-add-usersubstr.patch] + +------------------------------------------------------------------- +Wed Nov 18 10:02:32 UTC 2020 - Josef Möllers + +- pam_xauth.c: do not free() a string which has been (successfully) + passed to putenv(). + [bsc#1177858, pam-bsc1177858-dont-free-environment-string.patch] + +------------------------------------------------------------------- +Fri Nov 13 09:13:18 UTC 2020 - Josef Möllers + +- Initialize pam_unix pam_sm_acct_mgmt() local variable "daysleft" + to avoid spurious (and misleading) + Warning: your password will expire in ... days. + fixed upstream with commit db6b293046a + [bsc#1178727, pam-bsc1178727-initialize-daysleft.patch] + +------------------------------------------------------------------- +Tue Nov 10 11:09:39 UTC 2020 - Thorsten Kukuk + +- Enable pam_faillock [bnc#1171562] + +------------------------------------------------------------------- +Wed Oct 8 13:31:39 UTC 2020 - Josef Möllers + +- /usr/bin/xauth chokes on the old user's $HOME being on an NFS + file system. Run /usr/bin/xauth using the old user's uid/gid + Patch courtesy of Dr. Werner Fink. + [bsc#1174593, pam-xauth_ownership.patch] + +------------------------------------------------------------------- +Thu Oct 8 02:33:16 UTC 2020 - Stanislav Brabec + +- pam-login_defs-check.sh: Fix the regexp to get a real variable + list (boo#1164274). + +------------------------------------------------------------------- +Wed Jun 24 13:06:33 UTC 2020 - Josef Möllers + +- Revert the previous change [SR#815713]. + The group is not necessary for PAM functionality but used only + during testing. The test system should therefore create this group. + [bsc#1171016, pam.spec] + +------------------------------------------------------------------- +Mon Jun 15 15:05:18 UTC 2020 - Josef Möllers + +- Add requirement for group "wheel" to spec file. + [bsc#1171016, pam.spec] + ------------------------------------------------------------------- Mon Jun 8 13:19:12 UTC 2020 - Thorsten Kukuk diff --git a/pam.spec b/pam.spec index cff51f0..0585c87 100644 --- a/pam.spec +++ b/pam.spec @@ -27,7 +27,7 @@ %endif Name: pam # -Version: 1.4.0 +Version: 1.5.0 Release: 0 Summary: A Security Tool that Provides Authentication for Applications License: GPL-2.0-or-later OR BSD-3-Clause @@ -47,6 +47,11 @@ Source11: unix2_chkpwd.8 Source12: pam-login_defs-check.sh Patch2: pam-limit-nproc.patch Patch4: pam-hostnames-in-access_conf.patch +Patch5: pam-xauth_ownership.patch +Patch6: pam_cracklib-removal.patch +Patch7: pam_tally2-removal.patch +Patch8: pam-bsc1177858-dont-free-environment-string.patch +Patch9: pam-pam_cracklib-add-usersubstr.patch BuildRequires: audit-devel BuildRequires: bison BuildRequires: cracklib-devel @@ -139,6 +144,11 @@ removed with one of the next releases. cp -a %{SOURCE12} . %patch2 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -R -p1 +%patch7 -R -p1 +%patch8 -p1 +%patch9 -p1 %build bash ./pam-login_defs-check.sh @@ -210,8 +220,6 @@ for i in pam_*/README; do cp -fpv "$i" "$DOC/modules/README.${i%/*}" done popd -# XXX Remove until whitelisted -rm %{buildroot}/%{_lib}/security/pam_faillock.so # Install unix2_chkpwd install -m 755 %{_builddir}/unix2_chkpwd %{buildroot}/sbin/ install -m 644 %{_sourcedir}/unix2_chkpwd.8 %{buildroot}/%{_mandir}/man8/ @@ -310,6 +318,7 @@ done %{_mandir}/man8/pam_sepermit.8%{?ext_man} %{_mandir}/man8/pam_setquota.8%{?ext_man} %{_mandir}/man8/pam_shells.8%{?ext_man} +%{_mandir}/man8/pam_stress.8%{?ext_man} %{_mandir}/man8/pam_succeed_if.8%{?ext_man} %{_mandir}/man8/pam_time.8%{?ext_man} %{_mandir}/man8/pam_timestamp.8%{?ext_man} @@ -321,6 +330,7 @@ done %{_mandir}/man8/pam_warn.8%{?ext_man} %{_mandir}/man8/pam_wheel.8%{?ext_man} %{_mandir}/man8/pam_xauth.8%{?ext_man} +%{_mandir}/man8/pwhistory_helper.8%{?ext_man} %{_mandir}/man8/unix2_chkpwd.8%{?ext_man} %{_mandir}/man8/unix_chkpwd.8%{?ext_man} %{_mandir}/man8/unix_update.8%{?ext_man} @@ -338,7 +348,7 @@ done /%{_lib}/security/pam_env.so /%{_lib}/security/pam_exec.so /%{_lib}/security/pam_faildelay.so -#/%{_lib}/security/pam_faillock.so +/%{_lib}/security/pam_faillock.so /%{_lib}/security/pam_filter.so %dir /%{_lib}/security/pam_filter /%{_lib}/security//pam_filter/upperLOWER @@ -386,6 +396,7 @@ done /sbin/mkhomedir_helper /sbin/pam_namespace_helper /sbin/pam_timestamp_check +/sbin/pwhistory_helper %verify(not mode) %attr(4755,root,shadow) /sbin/unix_chkpwd %verify(not mode) %attr(4755,root,shadow) /sbin/unix2_chkpwd %attr(0700,root,root) /sbin/unix_update @@ -401,8 +412,6 @@ done /%{_lib}/security/pam_cracklib.so /%{_lib}/security/pam_tally2.so /sbin/pam_tally2 -%{_mandir}/man8/pam_cracklib.8%{?ext_man} -%{_mandir}/man8/pam_tally2.8%{?ext_man} %files doc %defattr(644,root,root,755) diff --git a/pam_cracklib-removal.patch b/pam_cracklib-removal.patch new file mode 100644 index 0000000..22dbdcb --- /dev/null +++ b/pam_cracklib-removal.patch @@ -0,0 +1,1740 @@ +From d702ff714c309069111899fd07c09e31c414c166 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Thu, 29 Oct 2020 08:00:00 +0000 +Subject: [PATCH] Remove deprecated pam_cracklib module + +* ci/install-dependencies.sh: Remove libcrack2-dev. +* ci/run-build-and-tests.sh (DISTCHECK_CONFIGURE_FLAGS): Remove +--enable-cracklib=check. +* conf/pam.conf: Remove references to pam_cracklib.so. +* configure.ac: Remove --enable-cracklib option. +(AC_SUBST): Remove LIBCRACK. +(AM_CONDITIONAL): Remove COND_BUILD_PAM_CRACKLIB. +(AC_CONFIG_FILES): Remove modules/pam_cracklib/Makefile. +* doc/sag/pam_cracklib.xml: Remove. +* doc/sag/Linux-PAM_SAG.xml: Do not include pam_cracklib.xml. +* modules/Makefile.am (MAYBE_PAM_CRACKLIB): Remove. +(SUBDIRS): Remove MAYBE_PAM_CRACKLIB. +* modules/pam_cracklib/Makefile.am: Remove. +* modules/pam_cracklib/README.xml: Likewise. +* modules/pam_cracklib/pam_cracklib.8.xml: Likewise. +* modules/pam_cracklib/pam_cracklib.c: Likewise. +* modules/pam_cracklib/tst-pam_cracklib: Likewise. +* xtests/tst-pam_cracklib1.c: Likewise. +* xtests/tst-pam_cracklib1.pamd: Likewise. +* xtests/tst-pam_cracklib2.c: Likewise. +* xtests/tst-pam_cracklib2.pamd: Likewise. +* modules/pam_pwhistory/pam_pwhistory.8.xml: Replace pam_cracklib +in examples with pam_passwdqc. +* modules/pam_unix/pam_unix.8.xml: Likewise. +* po/POTFILES.in: Remove ./modules/pam_cracklib/pam_cracklib.c. +* xtests/.gitignore: Remove tst-pam_cracklib1 and tst-pam_cracklib2. +* xtests/Makefile.am (EXTRA_DIST): Remove tst-pam_cracklib1.pamd +and tst-pam_cracklib2.pamd. +(XTESTS): Remove tst-pam_cracklib1 and tst-pam_cracklib2. +* NEWS: Document this change. +--- + NEWS | 2 + + ci/install-dependencies.sh | 1 - + ci/run-build-and-tests.sh | 2 +- + conf/pam.conf | 5 - + configure.ac | 25 +- + doc/sag/Linux-PAM_SAG.xml | 2 - + doc/sag/pam_cracklib.xml | 34 - + modules/Makefile.am | 5 - + modules/pam_cracklib/Makefile.am | 33 - + modules/pam_cracklib/README.xml | 41 - + modules/pam_cracklib/pam_cracklib.8.xml | 592 -------------- + modules/pam_cracklib/pam_cracklib.c | 899 ---------------------- + modules/pam_cracklib/tst-pam_cracklib | 2 - + modules/pam_pwhistory/pam_pwhistory.8.xml | 6 +- + modules/pam_unix/pam_unix.8.xml | 6 +- + po/POTFILES.in | 1 - + xtests/.gitignore | 2 - + xtests/Makefile.am | 2 - + xtests/tst-pam_cracklib1.c | 135 ---- + xtests/tst-pam_cracklib1.pamd | 2 - + xtests/tst-pam_cracklib2.c | 143 ---- + xtests/tst-pam_cracklib2.pamd | 2 - + 22 files changed, 10 insertions(+), 1932 deletions(-) + delete mode 100644 doc/sag/pam_cracklib.xml + delete mode 100644 modules/pam_cracklib/Makefile.am + delete mode 100644 modules/pam_cracklib/README.xml + delete mode 100644 modules/pam_cracklib/pam_cracklib.8.xml + delete mode 100644 modules/pam_cracklib/pam_cracklib.c + delete mode 100755 modules/pam_cracklib/tst-pam_cracklib + delete mode 100644 xtests/tst-pam_cracklib1.c + delete mode 100644 xtests/tst-pam_cracklib1.pamd + delete mode 100644 xtests/tst-pam_cracklib2.c + delete mode 100644 xtests/tst-pam_cracklib2.pamd + +diff --git a/configure.ac b/configure.ac +index 59327a75..4397124d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -334,28 +334,6 @@ case "$ac_cv_search_dlopen" in + esac + AC_SUBST(LIBDL) + +-AC_ARG_ENABLE([cracklib], +- [AS_HELP_STRING([--enable-cracklib], +- [build deprecated pam_cracklib module])], +- [], [enable_cracklib=no]) +-LIBCRACK="" +-case "$enable_cracklib" in +- no) ;; +- yes|check) +- dnl Check for cracklib +- AC_CHECK_HEADERS([crack.h], +- [AC_CHECK_LIB([crack], [FascistCheck], +- [LIBCRACK="-lcrack"])]) +- if test -z "$LIBCRACK"; then +- if test "$enable_cracklib" = yes; then +- AC_MSG_FAILURE([failed to find cracklib]) +- fi +- fi +- ;; +- *) AC_MSG_ERROR([bad value $enable_cracklib for --enable-cracklib option]) ;; +-esac +-AC_SUBST(LIBCRACK) +- + dnl Look for Linux Auditing library - see documentation + AC_ARG_ENABLE([audit], + AS_HELP_STRING([--disable-audit],[do not enable audit support]), +@@ -662,7 +640,6 @@ case "$enable_unix" in + *) AC_MSG_ERROR([bad value $enable_unix for --enable-unix option]) ;; + esac + +-AM_CONDITIONAL([COND_BUILD_PAM_CRACKLIB], [test -n "$LIBCRACK"]) + AM_CONDITIONAL([COND_BUILD_PAM_KEYINIT], [test "$have_key_syscalls" = 1]) + AM_CONDITIONAL([COND_BUILD_PAM_LASTLOG], [test "$ac_cv_func_logwtmp" = yes]) + AM_CONDITIONAL([COND_BUILD_PAM_NAMESPACE], [test "$ac_cv_func_unshare" = yes]) +@@ -682,7 +659,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile + po/Makefile.in \ + Make.xml.rules \ + modules/Makefile \ +- modules/pam_access/Makefile modules/pam_cracklib/Makefile \ ++ modules/pam_access/Makefile \ + modules/pam_debug/Makefile modules/pam_deny/Makefile \ + modules/pam_echo/Makefile modules/pam_env/Makefile \ + modules/pam_faildelay/Makefile modules/pam_faillock/Makefile \ +diff --git a/modules/Makefile.am b/modules/Makefile.am +index 641108dd..aa03e319 100644 +--- a/modules/Makefile.am ++++ b/modules/Makefile.am +@@ -2,10 +2,6 @@ + # Copyright (c) 2005, 2006, 2008 Thorsten Kukuk + # + +-if COND_BUILD_PAM_CRACKLIB +- MAYBE_PAM_CRACKLIB = pam_cracklib +-endif +- + if COND_BUILD_PAM_KEYINIT + MAYBE_PAM_KEYINIT = pam_keyinit + endif +@@ -56,7 +52,6 @@ endif + + SUBDIRS := \ + pam_access \ +- $(MAYBE_PAM_CRACKLIB) \ + pam_debug \ + pam_deny \ + pam_echo \ +diff --git a/modules/pam_cracklib/Makefile.am b/modules/pam_cracklib/Makefile.am +deleted file mode 100644 +index e11c42d7..00000000 +--- a/modules/pam_cracklib/Makefile.am ++++ /dev/null +@@ -1,33 +0,0 @@ +-# +-# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk +-# +- +-CLEANFILES = *~ +-MAINTAINERCLEANFILES = $(MANS) README +- +-EXTRA_DIST = $(XMLS) +- +-#if HAVE_DOC +-#dist_man_MANS = pam_cracklib.8 +-#endif +-XMLS = README.xml pam_cracklib.8.xml +-dist_check_SCRIPTS = tst-pam_cracklib +-TESTS = $(dist_check_SCRIPTS) +- +-securelibdir = $(SECUREDIR) +-secureconfdir = $(SCONFIGDIR) +- +-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ +- $(WARN_CFLAGS) +-AM_LDFLAGS = -no-undefined -avoid-version -module +-if HAVE_VERSIONING +- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +-endif +-pam_cracklib_la_LIBADD = $(top_builddir)/libpam/libpam.la \ +- @LIBCRACK@ @LIBCRYPT@ +-securelib_LTLIBRARIES = pam_cracklib.la +- +-if ENABLE_REGENERATE_MAN +-dist_noinst_DATA = README +--include $(top_srcdir)/Make.xml.rules +-endif +diff --git a/modules/pam_cracklib/README.xml b/modules/pam_cracklib/README.xml +deleted file mode 100644 +index c4a7b54c..00000000 +--- a/modules/pam_cracklib/README.xml ++++ /dev/null +@@ -1,41 +0,0 @@ +- +- +---> +-]> +- +-
+- +- +- +- +- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" +- href="pam_cracklib.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_cracklib-name"]/*)'/> +- +- +- +- +-
+- +-
+- +-
+- +-
+- +-
+- +-
+- +-
+- +-
+- +-
+diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml +deleted file mode 100644 +index 75e44e2d..00000000 +--- a/modules/pam_cracklib/pam_cracklib.8.xml ++++ /dev/null +@@ -1,592 +0,0 @@ +- +- +- +- +- +- +- pam_cracklib +- 8 +- Linux-PAM Manual +- +- +- +- pam_cracklib +- PAM module to check the password against dictionary words +- +- +- +- +- pam_cracklib.so +- +- ... +- +- +- +- +- +- +- 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? +- +- +- +- +- Case Change Only +- +- +- Is the new password 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, +- which is a number of character changes +- (inserts, removals, or replacements) between the old and new +- password that are enough to accept the new password. +- This defaults to 5 changes. +- +- +- +- +- Simple +- +- +- Is the new password too small? +- This is controlled by 6 arguments , +- , +- , , +- , and . 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? +- +- +- +- +- Same consecutive characters +- +- +- Optional check for same consecutive characters. +- +- +- +- +- Too long monotonic character sequence +- +- +- Optional check for too long monotonic character sequence. +- +- +- +- +- Contains user name +- +- +- Optional check whether the password contains the user's name +- in some form. +- +- +- +- +- +- 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 +- +- +- +- +- +- +- +- +- +- This option makes the module write information to +- +- syslog3 +- +- indicating the behavior of the module (this option does +- not write password information to the log file). +- +- +- +- +- +- +- +- +- +- +- The default action is for the module to use the +- following prompts when requesting passwords: +- "New UNIX password: " and "Retype UNIX password: ". +- The example word UNIX can +- be replaced with this option, by default it is empty. +- +- +- +- +- +- +- +- +- +- +- Prompt user at most N times +- before returning with error. The default is +- 1. +- +- +- +- +- +- +- +- +- +- +- This argument will change the default of +- 5 for the number of character +- changes in the new password that differentiate it +- from the old password. +- +- +- +- +- +- +- +- +- +- +- 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 . +- If you want to allow passwords as short as 5 characters you +- should not use this module. +- +- +- +- +- +- +- +- +- +- +- (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 +- value. The default for +- is 1 which is the recommended +- value for less than 10. +- +- +- (N < 0) This is the minimum number of digits that must +- be met for a new password. +- +- +- +- +- +- +- +- +- +- +- (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 +- value. The default for +- is 1 which +- is the recommended value for less +- than 10. +- +- +- (N < 0) This is the minimum number of upper +- case letters that must be met for a new password. +- +- +- +- +- +- +- +- +- +- +- (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 value. The default for +- is 1 which is the recommended +- value for less than 10. +- +- +- (N < 0) This is the minimum number of lower +- case letters that must be met for a new password. +- +- +- +- +- +- +- +- +- +- +- (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 +- value. The default for +- is 1 which is the recommended +- value for less than 10. +- +- +- (N < 0) This is the minimum number of other +- characters that must be met for a new password. +- +- +- +- +- +- +- +- +- +- +- 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 check is +- that a specific class if of characters is not required. +- Instead N out of four of the +- classes are required. +- +- +- +- +- +- +- +- +- +- +- Reject passwords which contain more than N same consecutive +- characters. The default is 0 which means that this check +- is disabled. +- +- +- +- +- +- +- +- +- +- +- Reject passwords which contain monotonic character sequences +- longer than N. The default is 0 which means that this check +- is disabled. Examples of such sequence are '12345' or 'fedcb'. +- Note that most such passwords will not pass the simplicity +- check unless the sequence is only a minor part of the password. +- +- +- +- +- +- +- +- +- +- +- Reject passwords which contain more than N consecutive +- characters of the same class. The default is 0 which means +- that this check is disabled. +- +- +- +- +- +- +- +- +- +- +- Check whether the name of the user in straight or reversed +- form is contained in the new password. If it is found the +- new password is rejected. +- +- +- +- +- +- +- +- +- +- +- Check whether the words from the GECOS field (usually full name +- of the user) longer than 3 characters in straight or reversed +- form are contained in the new password. If any such word is +- found the new password is rejected. +- +- +- +- +- +- +- +- +- +- +- The module will return error on failed check also if the user +- changing the password is root. This option is off by default +- which means that just the message about the failed check is +- printed but root can change the password anyway. +- Note that root is not asked for an old password so the checks +- that compare the old and new password are not performed. +- +- +- +- +- +- +- +- +- +- +- 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. +- +- +- +- +- +- +- +- +- +- +- Path to the cracklib dictionaries. +- +- +- +- +- +- +- +- +- +- MODULE TYPES PROVIDED +- +- Only the module type is provided. +- +- +- +- +- RETURN VALUES +- +- +- +- +- PAM_SUCCESS +- +- +- The new password passes all checks. +- +- +- +- +- +- PAM_AUTHTOK_ERR +- +- +- No new password was entered, +- the username could not be determined or the new +- password fails the strength checks. +- +- +- +- +- +- PAM_AUTHTOK_RECOVERY_ERR +- +- +- The old password was not supplied by a previous stacked +- module or got not requested from the user. +- The first error can happen if +- is specified. +- +- +- +- +- +- PAM_SERVICE_ERR +- +- +- A internal error occurred. +- +- +- +- +- +- +- +- +- +- EXAMPLES +- +- For an example of the use of this module, we show how it may be +- stacked with the password component of +- +- pam_unix8 +- +- +-# +-# 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 +- +- +- +- +- +- +- SEE ALSO +- +- +- pam.conf5 +- , +- +- pam.d5 +- , +- +- pam8 +- +- +- +- +- +- AUTHOR +- +- pam_cracklib was written by Cristian Gafton <gafton@redhat.com> +- +- +- +- +diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c +deleted file mode 100644 +index 01291305..00000000 +--- a/modules/pam_cracklib/pam_cracklib.c ++++ /dev/null +@@ -1,899 +0,0 @@ +-/* +- * 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 fed to cracklib for verify after typed once +- * 0.1. First release +- * +- * Written by Cristian Gafton 1996/09/10 +- * Long password support by Philip W. Dalrymple 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 +-#ifdef HAVE_LIBXCRYPT +-# include +-#elif defined(HAVE_CRYPT_H) +-# include +-#endif +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef HAVE_CRACK_H +-#include +-#else +-extern char *FascistCheck(char *pw, const char *dictpath); +-#endif +- +-#ifndef CRACKLIB_DICTS +-#define CRACKLIB_DICTS NULL +-#endif +- +-#ifdef MIN +-#undef MIN +-#endif +-#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +- +-#include +-#include +-#include +-#include "pam_inline.h" +- +-/* argument parsing */ +-#define PAM_DEBUG_ARG 0x0001 +- +-struct cracklib_options { +- int retry_times; +- int diff_ok; +- int min_length; +- int dig_credit; +- int up_credit; +- int low_credit; +- int oth_credit; +- int min_class; +- int max_repeat; +- int max_sequence; +- int max_class_repeat; +- int reject_user; +- int gecos_check; +- int enforce_for_root; +- const char *cracklib_dictpath; +-}; +- +-#define CO_RETRY_TIMES 1 +-#define CO_DIFF_OK 5 +-#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_MIN_WORD_LENGTH 4 +- +-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) { +- const char *str; +- char *ep = NULL; +- +- /* generic options */ +- +- if (!strcmp(*argv,"debug")) +- ctrl |= PAM_DEBUG_ARG; +- else if ((str = pam_str_skip_prefix(*argv, "type=")) != NULL) +- pam_set_item (pamh, PAM_AUTHTOK_TYPE, str); +- else if ((str = pam_str_skip_prefix(*argv, "retry=")) != NULL) { +- opt->retry_times = strtol(str, &ep, 10); +- if (!ep || (opt->retry_times < 1)) +- opt->retry_times = CO_RETRY_TIMES; +- } else if ((str = pam_str_skip_prefix(*argv, "difok=")) != NULL) { +- opt->diff_ok = strtol(str, &ep, 10); +- if (!ep || (opt->diff_ok < 0)) +- opt->diff_ok = CO_DIFF_OK; +- } else if (pam_str_skip_prefix(*argv, "difignore=") != NULL) { +- /* just ignore */ +- } else if ((str = pam_str_skip_prefix(*argv, "minlen=")) != NULL) { +- opt->min_length = strtol(str, &ep, 10); +- if (!ep || (opt->min_length < CO_MIN_LENGTH_BASE)) +- opt->min_length = CO_MIN_LENGTH_BASE; +- } else if ((str = pam_str_skip_prefix(*argv, "dcredit=")) != NULL) { +- opt->dig_credit = strtol(str, &ep, 10); +- if (!ep) +- opt->dig_credit = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "ucredit=")) != NULL) { +- opt->up_credit = strtol(str, &ep, 10); +- if (!ep) +- opt->up_credit = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "lcredit=")) != NULL) { +- opt->low_credit = strtol(str, &ep, 10); +- if (!ep) +- opt->low_credit = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "ocredit=")) != NULL) { +- opt->oth_credit = strtol(str, &ep, 10); +- if (!ep) +- opt->oth_credit = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "minclass=")) != NULL) { +- opt->min_class = strtol(str, &ep, 10); +- if (!ep) +- opt->min_class = 0; +- if (opt->min_class > 4) +- opt->min_class = 4; +- } else if ((str = pam_str_skip_prefix(*argv, "maxrepeat=")) != NULL) { +- opt->max_repeat = strtol(str, &ep, 10); +- if (!ep) +- opt->max_repeat = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "maxsequence=")) != NULL) { +- opt->max_sequence = strtol(str, &ep, 10); +- if (!ep) +- opt->max_sequence = 0; +- } else if ((str = pam_str_skip_prefix(*argv, "maxclassrepeat=")) != NULL) { +- opt->max_class_repeat = strtol(str, &ep, 10); +- if (!ep) +- opt->max_class_repeat = 0; +- } else if (!strcmp(*argv, "reject_username")) { +- opt->reject_user = 1; +- } else if (!strcmp(*argv, "gecoscheck")) { +- opt->gecos_check = 1; +- } else if (!strcmp(*argv, "enforce_for_root")) { +- opt->enforce_for_root = 1; +- } else if (pam_str_skip_prefix(*argv, "authtok_type=") != NULL) { +- /* for pam_get_authtok, ignore */; +- } else if (!strcmp(*argv, "use_authtok")) { +- /* for pam_get_authtok, ignore */; +- } else if (!strcmp(*argv, "use_first_pass")) { +- /* for pam_get_authtok, ignore */; +- } else if (!strcmp(*argv, "try_first_pass")) { +- /* for pam_get_authtok, ignore */; +- } else if ((str = pam_str_skip_prefix(*argv, "dictpath=")) != NULL) { +- opt->cracklib_dictpath = str; +- if (!*(opt->cracklib_dictpath)) { +- opt->cracklib_dictpath = CRACKLIB_DICTS; +- } +- } else { +- pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv); +- } +- } +- +- return ctrl; +-} +- +-/* Helper functions */ +- +-/* +- * 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 characters +- */ +- +-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; +- enum { NONE, DIGIT, UCASE, LCASE, OTHER } prevclass = NONE; +- int sameclass = 0; +- +- for (i = 0;new[i];i++) { +- if (isdigit (new[i])) { +- digits++; +- if (prevclass != DIGIT) { +- prevclass = DIGIT; +- sameclass = 1; +- } else +- sameclass++; +- } +- else if (isupper (new[i])) { +- uppers++; +- if (prevclass != UCASE) { +- prevclass = UCASE; +- sameclass = 1; +- } else +- sameclass++; +- } +- else if (islower (new[i])) { +- lowers++; +- if (prevclass != LCASE) { +- prevclass = LCASE; +- sameclass = 1; +- } else +- sameclass++; +- } +- else { +- others++; +- if (prevclass != OTHER) { +- prevclass = OTHER; +- sameclass = 1; +- } else +- sameclass++; +- } +- if (opt->max_class_repeat > 0 && sameclass > opt->max_class_repeat) { +- return 1; +- } +- } +- +- /* +- * 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 int consecutive(struct cracklib_options *opt, const char *new) +-{ +- char c; +- int i; +- int same; +- +- if (opt->max_repeat == 0) +- return 0; +- +- for (i = 0; new[i]; i++) { +- if (i > 0 && new[i] == c) { +- ++same; +- if (same > opt->max_repeat) +- return 1; +- } else { +- c = new[i]; +- same = 1; +- } +- } +- return 0; +-} +- +-static int sequence(struct cracklib_options *opt, const char *new) +-{ +- char c; +- int i; +- int sequp = 1; +- int seqdown = 1; +- +- if (opt->max_sequence == 0) +- return 0; +- +- if (new[0] == '\0') +- return 0; +- +- for (i = 1; new[i]; i++) { +- c = new[i-1]; +- if (new[i] == c+1) { +- ++sequp; +- if (sequp > opt->max_sequence) +- return 1; +- seqdown = 1; +- } else if (new[i] == c-1) { +- ++seqdown; +- if (seqdown > opt->max_sequence) +- return 1; +- sequp = 1; +- } else { +- sequp = 1; +- seqdown = 1; +- } +- } +- return 0; +-} +- +-static int wordcheck(const char *new, char *word) +-{ +- char *f, *b; +- +- if (strstr(new, word) != NULL) +- return 1; +- +- /* now reverse the word, we can do that in place +- as it is strdup-ed */ +- f = word; +- b = word+strlen(word)-1; +- while (f < b) { +- char c; +- +- c = *f; +- *f = *b; +- *b = c; +- --b; +- ++f; +- } +- +- if (strstr(new, word) != NULL) +- return 1; +- return 0; +-} +- +-static int usercheck(struct cracklib_options *opt, const char *new, +- char *user) +-{ +- if (!opt->reject_user) +- return 0; +- +- return wordcheck(new, user); +-} +- +-static char * str_lower(char *string) +-{ +- char *cp; +- +- if (!string) +- return NULL; +- +- for (cp = string; *cp; cp++) +- *cp = tolower(*cp); +- return string; +-} +- +-static int gecoscheck(pam_handle_t *pamh, struct cracklib_options *opt, const char *new, +- const char *user) +-{ +- struct passwd *pwd; +- char *list; +- char *p; +- char *next; +- +- if (!opt->gecos_check) +- return 0; +- +- if ((pwd = pam_modutil_getpwnam(pamh, user)) == NULL) { +- return 0; +- } +- +- list = strdup(pwd->pw_gecos); +- +- if (list == NULL || *list == '\0') { +- free(list); +- return 0; +- } +- +- for (p = list;;p = next + 1) { +- next = strchr(p, ' '); +- if (next) +- *next = '\0'; +- +- if (strlen(p) >= CO_MIN_WORD_LENGTH) { +- str_lower(p); +- if (wordcheck(new, p)) { +- free(list); +- return 1; +- } +- } +- +- if (!next) +- break; +- } +- +- free(list); +- return 0; +-} +- +-static const char *password_check(pam_handle_t *pamh, struct cracklib_options *opt, +- const char *old, const char *new, +- const char *user) +-{ +- const char *msg = NULL; +- char *oldmono = NULL, *newmono, *wrapped = NULL; +- char *usermono = NULL; +- +- if (old && strcmp(new, old) == 0) { +- msg = _("is the same as the old one"); +- return msg; +- } +- +- newmono = str_lower(strdup(new)); +- if (!newmono) +- msg = _("memory allocation error"); +- +- usermono = str_lower(strdup(user)); +- if (!usermono) +- msg = _("memory allocation error"); +- +- if (!msg && old) { +- oldmono = str_lower(strdup(old)); +- if (oldmono) +- wrapped = malloc(strlen(oldmono) * 2 + 1); +- if (wrapped) { +- strcpy (wrapped, oldmono); +- strcat (wrapped, oldmono); +- } else { +- msg = _("memory allocation error"); +- } +- } +- +- if (!msg && 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"); +- +- if (!msg && consecutive(opt, new)) +- msg = _("contains too many same characters consecutively"); +- +- if (!msg && sequence(opt, new)) +- msg = _("contains too long of a monotonic character sequence"); +- +- if (!msg && (usercheck(opt, newmono, usermono) || gecoscheck(pamh, opt, newmono, user))) +- msg = _("contains the user name in some form"); +- +- free(usermono); +- if (newmono) { +- memset(newmono, 0, strlen(newmono)); +- free(newmono); +- } +- if (oldmono) { +- memset(oldmono, 0, strlen(oldmono)); +- free(oldmono); +- } +- if (wrapped) { +- memset(wrapped, 0, strlen(wrapped)); +- free(wrapped); +- } +- +- 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 char *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 has been supplied.") : +- _("The password has not been changed.")); +- return PAM_AUTHTOK_ERR; +- } +- +- retval = pam_get_user(pamh, &user, NULL); +- if (retval != PAM_SUCCESS) { +- if (ctrl & PAM_DEBUG_ARG) +- pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s", +- pam_strerror(pamh, retval)); +- return PAM_AUTHTOK_ERR; +- } +- /* +- * if one wanted to hardwire authentication token strength +- * checking this would be the place +- */ +- msg = password_check(pamh, opt, pass_old, pass_new, user); +- +- 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) +- */ +-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.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.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; +- const void *oldtoken; +- int tries; +- +- 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; +- } +- +- tries = 0; +- while (tries < options.retry_times) { +- const char *crack_msg; +- const char *newtoken = NULL; +- +- +- tries++; +- +- /* 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 +- */ +- +- retval = pam_get_authtok_noverify (pamh, &newtoken, NULL); +- if (retval != PAM_SUCCESS) { +- pam_syslog(pamh, LOG_ERR, "pam_get_authtok_noverify returned error: %s", +- pam_strerror (pamh, retval)); +- continue; +- } else if (newtoken == NULL) { /* user aborted password change, quit */ +- return PAM_AUTHTOK_ERR; +- } +- +- D(("testing password")); +- /* now test this passwd against cracklib */ +- +- D(("against cracklib")); +- if ((crack_msg = FascistCheck (newtoken, 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() || options.enforce_for_root || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) +- { +- pam_set_item (pamh, PAM_AUTHTOK, NULL); +- retval = PAM_AUTHTOK_ERR; +- continue; +- } +- } +- +- /* check it for strength too... */ +- D(("for strength")); +- retval = _pam_unix_approve_pass (pamh, ctrl, &options, +- oldtoken, newtoken); +- if (retval != PAM_SUCCESS) { +- if (getuid() || options.enforce_for_root || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) +- { +- pam_set_item(pamh, PAM_AUTHTOK, NULL); +- retval = PAM_AUTHTOK_ERR; +- continue; +- } +- } +- +- retval = pam_get_authtok_verify (pamh, &newtoken, NULL); +- if (retval != PAM_SUCCESS) { +- pam_syslog(pamh, LOG_ERR, "pam_get_authtok_verify returned error: %s", +- pam_strerror (pamh, retval)); +- pam_set_item(pamh, PAM_AUTHTOK, NULL); +- continue; +- } else if (newtoken == NULL) { /* user aborted password change, quit */ +- return PAM_AUTHTOK_ERR; +- } +- +- return PAM_SUCCESS; +- } +- +- D(("returning because maxtries reached")); +- +- pam_set_item (pamh, PAM_AUTHTOK, NULL); +- +- /* if we have only one try, we can use the real reason, +- else say that there were too many tries. */ +- if (options.retry_times > 1) +- return PAM_MAXTRIES; +- else +- return retval; +- +- } 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; +-} +- +- +- +-/* +- * Copyright (c) Cristian Gafton , 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 +- * 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 +deleted file mode 100755 +index 46a7060d..00000000 +--- a/modules/pam_cracklib/tst-pam_cracklib ++++ /dev/null +@@ -1,2 +0,0 @@ +-#!/bin/sh +-../../tests/tst-dlopen .libs/pam_cracklib.so diff --git a/pam_tally2-removal.patch b/pam_tally2-removal.patch new file mode 100644 index 0000000..59fc8dc --- /dev/null +++ b/pam_tally2-removal.patch @@ -0,0 +1,1332 @@ +From 709e37b7e131d35b0ec30d31f858bc6917dd2b2e Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Thu, 29 Oct 2020 08:00:00 +0000 +Subject: [PATCH] Remove deprecated pam_tally and pam_tally2 modules + +* ci/run-build-and-tests.sh (DISTCHECK_CONFIGURE_FLAGS): Remove +--enable-tally --enable-tally2. +* configure.ac: Remove --enable-tally and --enable-tally2 options. +(AM_CONDITIONAL): Remove COND_BUILD_PAM_TALLY and COND_BUILD_PAM_TALLY2. +(AC_CONFIG_FILES): Remove modules/pam_tally/Makefile and +modules/pam_tally2/Makefile. +* doc/sag/pam_tally.xml: Remove. +* doc/sag/pam_tally2.xml: Likewise. +* doc/sag/Linux-PAM_SAG.xml: Do not include pam_tally.xml and +pam_tally2.xml. +* modules/Makefile.am (MAYBE_PAM_TALLY, MAYBE_PAM_TALLY2): Remove. +(SUBDIRS): Remove MAYBE_PAM_TALLY and MAYBE_PAM_TALLY2. +* modules/pam_tally/.gitignore: Remove. +* modules/pam_tally/Makefile.am: Likewise. +* modules/pam_tally/README.xml: Likewise. +* modules/pam_tally/faillog.h: Likewise. +* modules/pam_tally/pam_tally.8.xml: Likewise. +* modules/pam_tally/pam_tally.c: Likewise. +* modules/pam_tally/pam_tally_app.c: Likewise. +* modules/pam_tally/tst-pam_tally: Likewise. +* modules/pam_tally2/.gitignore: Likewise. +* modules/pam_tally2/Makefile.am: Likewise. +* modules/pam_tally2/README.xml: Likewise. +* modules/pam_tally2/pam_tally2.8.xml: Likewise. +* modules/pam_tally2/pam_tally2.c: Likewise. +* modules/pam_tally2/pam_tally2_app.c: Likewise. +* modules/pam_tally2/tallylog.h: Likewise. +* modules/pam_tally2/tst-pam_tally2: Likewise. +* modules/pam_timestamp/pam_timestamp_check.8.xml: Fix typo by replacing +pam_tally with pam_timestamp. +* po/POTFILES.in: Remove ./modules/pam_tally/pam_tally_app.c, +./modules/pam_tally/pam_tally.c, ./modules/pam_tally2/pam_tally2_app.c, +and ./modules/pam_tally2/pam_tally2.c. +* NEWS: Document this change. +--- + NEWS | 1 + + ci/run-build-and-tests.sh | 2 +- + configure.ac | 23 +- + doc/sag/Linux-PAM_SAG.xml | 4 - + doc/sag/pam_tally.xml | 38 - + doc/sag/pam_tally2.xml | 46 - + modules/Makefile.am | 10 - + modules/pam_tally/.gitignore | 1 - + modules/pam_tally/Makefile.am | 41 - + modules/pam_tally/README.xml | 41 - + modules/pam_tally/faillog.h | 55 - + modules/pam_tally/pam_tally.8.xml | 459 -------- + modules/pam_tally/pam_tally.c | 854 -------------- + modules/pam_tally/pam_tally_app.c | 6 - + modules/pam_tally/tst-pam_tally | 2 - + modules/pam_tally2/.gitignore | 1 - + modules/pam_tally2/Makefile.am | 45 - + modules/pam_tally2/README.xml | 46 - + modules/pam_tally2/pam_tally2.8.xml | 450 ------- + modules/pam_tally2/pam_tally2.c | 1036 ----------------- + modules/pam_tally2/pam_tally2_app.c | 6 - + modules/pam_tally2/tallylog.h | 52 - + modules/pam_tally2/tst-pam_tally2 | 2 - + .../pam_timestamp/pam_timestamp_check.8.xml | 2 +- + po/POTFILES.in | 4 - + 25 files changed, 4 insertions(+), 3223 deletions(-) + delete mode 100644 doc/sag/pam_tally.xml + delete mode 100644 doc/sag/pam_tally2.xml + delete mode 100644 modules/pam_tally/.gitignore + delete mode 100644 modules/pam_tally/Makefile.am + delete mode 100644 modules/pam_tally/README.xml + delete mode 100644 modules/pam_tally/faillog.h + delete mode 100644 modules/pam_tally/pam_tally.8.xml + delete mode 100644 modules/pam_tally/pam_tally.c + delete mode 100644 modules/pam_tally/pam_tally_app.c + delete mode 100755 modules/pam_tally/tst-pam_tally + delete mode 100644 modules/pam_tally2/.gitignore + delete mode 100644 modules/pam_tally2/Makefile.am + delete mode 100644 modules/pam_tally2/README.xml + delete mode 100644 modules/pam_tally2/pam_tally2.8.xml + delete mode 100644 modules/pam_tally2/pam_tally2.c + delete mode 100644 modules/pam_tally2/pam_tally2_app.c + delete mode 100644 modules/pam_tally2/tallylog.h + delete mode 100755 modules/pam_tally2/tst-pam_tally2 + +diff --git a/configure.ac b/configure.ac +index 4397124d..ad36a6bc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -613,24 +613,6 @@ test -n "$opt_kerneloverflowuid" || + opt_kerneloverflowuid=65534 + AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.]) + +-#AC_ARG_ENABLE([tally], +-# [AS_HELP_STRING([--enable-tally], +-# [build deprecated pam_tally module])], +-# [], [enable_tally=no]) +-#case "$enable_tally" in +-# yes|no) ;; +-# *) AC_MSG_ERROR([bad value $enable_tally for --enable-tally option]) ;; +-#esac +- +-AC_ARG_ENABLE([tally2], +- [AS_HELP_STRING([--enable-tally2], +- [build deprecated pam_tally2 module])], +- [], [enable_tally2=no]) +-case "$enable_tally2" in +- yes|no) ;; +- *) AC_MSG_ERROR([bad value $enable_tally2 for --enable-tally2 option]) ;; +-esac +- + AC_ARG_ENABLE([unix], + [AS_HELP_STRING([--disable-unix], + [do not build pam_unix module])], +@@ -647,8 +629,6 @@ AM_CONDITIONAL([COND_BUILD_PAM_RHOSTS], [test "$ac_cv_func_ruserok_af" = yes -o + AM_CONDITIONAL([COND_BUILD_PAM_SELINUX], [test -n "$LIBSELINUX"]) + AM_CONDITIONAL([COND_BUILD_PAM_SEPERMIT], [test -n "$LIBSELINUX"]) + AM_CONDITIONAL([COND_BUILD_PAM_SETQUOTA], [test "$ac_cv_func_quotactl" = yes]) +-#AM_CONDITIONAL([COND_BUILD_PAM_TALLY], [test "$enable_tally" = yes]) +-AM_CONDITIONAL([COND_BUILD_PAM_TALLY2], [test "$enable_tally2" = yes]) + AM_CONDITIONAL([COND_BUILD_PAM_TTY_AUDIT], [test "$HAVE_AUDIT_TTY_STATUS" = yes]) + AM_CONDITIONAL([COND_BUILD_PAM_UNIX], [test "$enable_unix" = yes]) + AM_CONDITIONAL([COND_BUILD_PAM_USERDB], [test -n "$LIBDB"]) +@@ -678,8 +658,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile + modules/pam_securetty/Makefile modules/pam_selinux/Makefile \ + modules/pam_sepermit/Makefile modules/pam_setquota/Makefile \ + modules/pam_shells/Makefile modules/pam_stress/Makefile \ +- modules/pam_succeed_if/Makefile \ +- modules/pam_tally2/Makefile modules/pam_time/Makefile \ ++ modules/pam_succeed_if/Makefile modules/pam_time/Makefile \ + modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \ + modules/pam_umask/Makefile \ + modules/pam_unix/Makefile modules/pam_userdb/Makefile \ +diff --git a/modules/Makefile.am b/modules/Makefile.am +index aa03e319..8da46410 100644 +--- a/modules/Makefile.am ++++ b/modules/Makefile.am +@@ -30,14 +30,6 @@ if COND_BUILD_PAM_SETQUOTA + MAYBE_PAM_SETQUOTA = pam_setquota + endif + +-#if COND_BUILD_PAM_TALLY +-# MAYBE_PAM_TALLY = pam_tally +-#endif +- +-if COND_BUILD_PAM_TALLY2 +- MAYBE_PAM_TALLY2 = pam_tally2 +-endif +- + if COND_BUILD_PAM_TTY_AUDIT + MAYBE_PAM_TTY_AUDIT = pam_tty_audit + endif +@@ -85,8 +77,6 @@ SUBDIRS := \ + pam_shells \ + pam_stress \ + pam_succeed_if \ +- $(MAYBE_PAM_TALLY) \ +- $(MAYBE_PAM_TALLY2) \ + pam_time \ + pam_timestamp \ + $(MAYBE_PAM_TTY_AUDIT) \ +diff --git a/modules/pam_tally2/Makefile.am b/modules/pam_tally2/Makefile.am +deleted file mode 100644 +index 9ca7eabf..00000000 +--- a/modules/pam_tally2/Makefile.am ++++ /dev/null +@@ -1,45 +0,0 @@ +-# +-# Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk +-# Copyright (c) 2008 Red Hat, Inc. +-# +- +-CLEANFILES = *~ +-MAINTAINERCLEANFILES = $(MANS) README +- +-EXTRA_DIST = $(XMLS) +- +-#if HAVE_DOC +-#dist_man_MANS = pam_tally2.8 +-#endif +-XMLS = README.xml pam_tally2.8.xml +-dist_check_SCRIPTS = tst-pam_tally2 +-TESTS = $(dist_check_SCRIPTS) +- +-securelibdir = $(SECUREDIR) +-secureconfdir = $(SCONFIGDIR) +- +-noinst_HEADERS = tallylog.h +- +-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ +- $(WARN_CFLAGS) +- +-pam_tally2_la_LDFLAGS = -no-undefined -avoid-version -module +-pam_tally2_la_LIBADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) +-if HAVE_VERSIONING +- pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +-endif +- +-pam_tally2_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ +-pam_tally2_LDFLAGS = @EXE_LDFLAGS@ +-pam_tally2_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) +- +-securelib_LTLIBRARIES = pam_tally2.la +-sbin_PROGRAMS = pam_tally2 +- +-pam_tally2_la_SOURCES = pam_tally2.c +-pam_tally2_SOURCES = pam_tally2_app.c +- +-if ENABLE_REGENERATE_MAN +-dist_noinst_DATA = README +--include $(top_srcdir)/Make.xml.rules +-endif +diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c +deleted file mode 100644 +index bcf3188c..00000000 +--- a/modules/pam_tally2/pam_tally2.c ++++ /dev/null +@@ -1,1036 +0,0 @@ +-/* +- * pam_tally2 module +- * +- * By Tim Baverstock , Multi Media Machine Ltd. +- * 5 March 1997 +- * +- * Stuff stolen from pam_rootok and pam_listfile +- * +- * Changes by Tomas Mraz 5 January 2005, 26 January 2006 +- * Audit option added for Tomas patch by Sebastien Tricaud 13 January 2005 +- * Portions Copyright 2006, Red Hat, Inc. +- * Portions Copyright 1989 - 1993, Julianne Frances Haugh +- * 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, this list of conditions and the following disclaimer. +- * 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. Neither the name of Julianne F. Haugh nor the names of its contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. +- */ +- +-#include "config.h" +- +-#if defined(MAIN) && defined(MEMORY_DEBUG) +-# undef exit +-#endif /* defined(MAIN) && defined(MEMORY_DEBUG) */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef HAVE_LIBAUDIT +-#include +-#endif +- +-#include +-#include +-#include +-#include +-#include +-#include "tallylog.h" +- +-#ifndef TRUE +-#define TRUE 1L +-#define FALSE 0L +-#endif +- +-#ifndef HAVE_FSEEKO +-#define fseeko fseek +-#endif +- +-#ifndef MAIN +-#include +-#endif +-#include +-#include +-#include "pam_inline.h" +- +-/*---------------------------------------------------------------------*/ +- +-#define DEFAULT_LOGFILE "/var/log/tallylog" +-#define MODULE_NAME "pam_tally2" +- +-#define tally_t uint16_t +-#define TALLY_HI ((tally_t)~0L) +- +-struct tally_options { +- const char *filename; +- tally_t deny; +- long lock_time; +- long unlock_time; +- long root_unlock_time; +- unsigned int ctrl; +-}; +- +-#define PHASE_UNKNOWN 0 +-#define PHASE_AUTH 1 +-#define PHASE_ACCOUNT 2 +-#define PHASE_SESSION 3 +- +-#define OPT_MAGIC_ROOT 01 +-#define OPT_FAIL_ON_ERROR 02 +-#define OPT_DENY_ROOT 04 +-#define OPT_QUIET 040 +-#define OPT_AUDIT 0100 +-#define OPT_NOLOGNOTICE 0400 +-#define OPT_SERIALIZE 01000 +-#define OPT_DEBUG 02000 +- +-#define MAX_LOCK_WAITING_TIME 10 +- +-/*---------------------------------------------------------------------*/ +- +-/* some syslogging */ +- +-#ifdef MAIN +-#define pam_syslog tally_log +-static void +-PAM_FORMAT((printf, 3, 4)) +-tally_log (const pam_handle_t *pamh UNUSED, int priority UNUSED, +- const char *fmt, ...) +-{ +- va_list args; +- +- va_start(args, fmt); +- fprintf(stderr, "%s: ", MODULE_NAME); +- vfprintf(stderr, fmt, args); +- fprintf(stderr,"\n"); +- va_end(args); +-} +- +-#define pam_modutil_getpwnam(pamh, user) getpwnam(user) +-#endif +- +-/*---------------------------------------------------------------------*/ +- +-/* --- Support function: parse arguments --- */ +- +-#ifndef MAIN +- +-static void +-log_phase_no_auth(pam_handle_t *pamh, int phase, const char *argv) +-{ +- if ( phase != PHASE_AUTH ) { +- pam_syslog(pamh, LOG_ERR, +- "option %s allowed in auth phase only", argv); +- } +-} +- +-static int +-tally_parse_args(pam_handle_t *pamh, struct tally_options *opts, +- int phase, int argc, const char **argv) +-{ +- memset(opts, 0, sizeof(*opts)); +- opts->filename = DEFAULT_LOGFILE; +- opts->ctrl = OPT_FAIL_ON_ERROR; +- opts->root_unlock_time = -1; +- +- for ( ; argc-- > 0; ++argv ) { +- const char *str; +- +- if ((str = pam_str_skip_prefix(*argv, "file=")) != NULL) { +- const char *from = str; +- if ( *from!='/' ) { +- pam_syslog(pamh, LOG_ERR, +- "filename not /rooted; %s", *argv); +- return PAM_AUTH_ERR; +- } +- opts->filename = from; +- } +- else if ( ! strcmp( *argv, "onerr=fail" ) ) { +- opts->ctrl |= OPT_FAIL_ON_ERROR; +- } +- else if ( ! strcmp( *argv, "onerr=succeed" ) ) { +- opts->ctrl &= ~OPT_FAIL_ON_ERROR; +- } +- else if ( ! strcmp( *argv, "magic_root" ) ) { +- opts->ctrl |= OPT_MAGIC_ROOT; +- } +- else if ( ! strcmp( *argv, "serialize" ) ) { +- opts->ctrl |= OPT_SERIALIZE; +- } +- else if ( ! strcmp( *argv, "debug" ) ) { +- opts->ctrl |= OPT_DEBUG; +- } +- else if ( ! strcmp( *argv, "even_deny_root_account" ) || +- ! strcmp( *argv, "even_deny_root" ) ) { +- log_phase_no_auth(pamh, phase, *argv); +- opts->ctrl |= OPT_DENY_ROOT; +- } +- else if ((str = pam_str_skip_prefix(*argv, "deny=")) != NULL) { +- log_phase_no_auth(pamh, phase, *argv); +- if (sscanf(str, "%hu", &opts->deny) != 1) { +- pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); +- return PAM_AUTH_ERR; +- } +- } +- else if ((str = pam_str_skip_prefix(*argv, "lock_time=")) != NULL) { +- log_phase_no_auth(pamh, phase, *argv); +- if (sscanf(str, "%ld", &opts->lock_time) != 1) { +- pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); +- return PAM_AUTH_ERR; +- } +- } +- else if ((str = pam_str_skip_prefix(*argv, "unlock_time=")) != NULL) { +- log_phase_no_auth(pamh, phase, *argv); +- if (sscanf(str, "%ld", &opts->unlock_time) != 1) { +- pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); +- return PAM_AUTH_ERR; +- } +- } +- else if ((str = pam_str_skip_prefix(*argv, "root_unlock_time=")) != NULL) { +- log_phase_no_auth(pamh, phase, *argv); +- if (sscanf(str, "%ld", &opts->root_unlock_time) != 1) { +- pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); +- return PAM_AUTH_ERR; +- } +- opts->ctrl |= OPT_DENY_ROOT; /* even_deny_root implied */ +- } +- else if ( ! strcmp( *argv, "quiet" ) || +- ! strcmp ( *argv, "silent")) { +- opts->ctrl |= OPT_QUIET; +- } +- else if ( ! strcmp ( *argv, "no_log_info") ) { +- opts->ctrl |= OPT_NOLOGNOTICE; +- } +- else if ( ! strcmp ( *argv, "audit") ) { +- opts->ctrl |= OPT_AUDIT; +- } +- else { +- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); +- } +- } +- +- if (opts->root_unlock_time == -1) +- opts->root_unlock_time = opts->unlock_time; +- +- return PAM_SUCCESS; +-} +- +-#endif /* #ifndef MAIN */ +- +-/*---------------------------------------------------------------------*/ +- +-/* --- Support function: get uid (and optionally username) from PAM or +- cline_user --- */ +- +-#ifdef MAIN +-static const char *cline_user=0; /* cline_user is used in the administration prog */ +-#endif +- +-static int +-pam_get_uid(pam_handle_t *pamh, uid_t *uid, const char **userp, struct tally_options *opts) +-{ +- const char *user = NULL; +- struct passwd *pw; +- +-#ifdef MAIN +- user = cline_user; +- +- if ( !user ) { +- pam_syslog(pamh, LOG_NOTICE, "cannot determine user name"); +- return PAM_AUTH_ERR; +- } +-#else +- if ((pam_get_user( pamh, &user, NULL )) != PAM_SUCCESS) { +- user = NULL; +- } +-#endif +- +- if ( ! ( pw = pam_modutil_getpwnam( pamh, user ) ) ) { +- opts->ctrl & OPT_AUDIT ? +- pam_syslog(pamh, LOG_NOTICE, "pam_get_uid; no such user %s", user) : +- pam_syslog(pamh, LOG_NOTICE, "pam_get_uid; no such user"); +- return PAM_USER_UNKNOWN; +- } +- +- if ( uid ) *uid = pw->pw_uid; +- if ( userp ) *userp = user; +- return PAM_SUCCESS; +-} +- +-/*---------------------------------------------------------------------*/ +- +-/* --- Support functions: set/get tally data --- */ +- +-#ifndef MAIN +- +-struct tally_data { +- time_t time; +- int tfile; +-}; +- +-static void +-_cleanup(pam_handle_t *pamh UNUSED, void *void_data, int error_status UNUSED) +-{ +- struct tally_data *data = void_data; +- if (data->tfile != -1) +- close(data->tfile); +- free(data); +-} +- +-static void +-tally_set_data( pam_handle_t *pamh, time_t oldtime, int tfile ) +-{ +- struct tally_data *data; +- +- if ( (data=malloc(sizeof(*data))) != NULL ) { +- data->time = oldtime; +- data->tfile = tfile; +- pam_set_data(pamh, MODULE_NAME, (void *)data, _cleanup); +- } +-} +- +-static int +-tally_get_data( pam_handle_t *pamh, time_t *oldtime, int *tfile ) +-{ +- int rv; +- const void *void_data; +- const struct tally_data *data; +- +- rv = pam_get_data(pamh, MODULE_NAME, &void_data); +- if ( rv == PAM_SUCCESS && void_data != NULL && oldtime != NULL ) { +- data = void_data; +- *oldtime = data->time; +- *tfile = data->tfile; +- } +- else { +- rv = -1; +- *oldtime = 0; +- } +- return rv; +-} +-#endif /* #ifndef MAIN */ +- +-/*---------------------------------------------------------------------*/ +- +-/* --- Support function: open/create tallyfile and return tally for uid --- */ +- +-/* If on entry tallyfile doesn't exist, creation is attempted. */ +- +-static void +-alarm_handler(int sig UNUSED) +-{ /* we just need to ignore it */ +-} +- +-static int +-get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, +- int *tfile, struct tallylog *tally, unsigned int ctrl) +-{ +- struct stat fileinfo; +- int lstat_ret; +- void *void_tally = tally; +- int preopened = 0; +- +- if (*tfile != -1) { +- preopened = 1; +- goto skip_open; +- } +- +- lstat_ret = lstat(filename, &fileinfo); +- if (lstat_ret) { +- *tfile=open(filename, O_APPEND|O_CREAT, S_IRUSR|S_IWUSR); +- /* Create file, or append-open in pathological case. */ +- if (*tfile == -1) { +-#ifndef MAIN +- if (errno == EACCES) { +- return PAM_IGNORE; /* called with insufficient access rights */ +- } +-#endif +- pam_syslog(pamh, LOG_ALERT, "Couldn't create %s: %m", filename); +- return PAM_AUTH_ERR; +- } +- lstat_ret = fstat(*tfile, &fileinfo); +- close(*tfile); +- } +- +- *tfile = -1; +- +- if ( lstat_ret ) { +- pam_syslog(pamh, LOG_ALERT, "Couldn't stat %s", filename); +- return PAM_AUTH_ERR; +- } +- +- if ((fileinfo.st_mode & S_IWOTH) || !S_ISREG(fileinfo.st_mode)) { +- /* If the file is world writable or is not a +- normal file, return error */ +- pam_syslog(pamh, LOG_ALERT, +- "%s is either world writable or not a normal file", +- filename); +- return PAM_AUTH_ERR; +- } +- +- if ((*tfile = open(filename, O_RDWR)) == -1) { +-#ifndef MAIN +- if (errno == EACCES) /* called with insufficient access rights */ +- return PAM_IGNORE; +-#endif +- pam_syslog(pamh, LOG_ALERT, "Error opening %s for update: %m", filename); +- +- return PAM_AUTH_ERR; +- } +- +-skip_open: +- if (lseek(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET) == (off_t)-1) { +- pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename); +- if (!preopened) { +- close(*tfile); +- *tfile = -1; +- } +- return PAM_AUTH_ERR; +- } +- +- if (!preopened && (ctrl & OPT_SERIALIZE)) { +- /* this code is not thread safe as it uses fcntl locks and alarm() +- so never use serialize with multithreaded services */ +- struct sigaction newsa, oldsa; +- unsigned int oldalarm; +- int rv; +- +- memset(&newsa, '\0', sizeof(newsa)); +- newsa.sa_handler = alarm_handler; +- sigaction(SIGALRM, &newsa, &oldsa); +- oldalarm = alarm(MAX_LOCK_WAITING_TIME); +- +- rv = lockf(*tfile, F_LOCK, sizeof(*tally)); +- /* lock failure is not fatal, we attempt to read the tally anyway */ +- +- /* reinstate the eventual old alarm handler */ +- if (rv == -1 && errno == EINTR) { +- if (oldalarm > MAX_LOCK_WAITING_TIME) { +- oldalarm -= MAX_LOCK_WAITING_TIME; +- } else if (oldalarm > 0) { +- oldalarm = 1; +- } +- } +- sigaction(SIGALRM, &oldsa, NULL); +- alarm(oldalarm); +- } +- +- if (pam_modutil_read(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { +- memset(tally, 0, sizeof(*tally)); +- } +- +- tally->fail_line[sizeof(tally->fail_line)-1] = '\0'; +- +- return PAM_SUCCESS; +-} +- +-/*---------------------------------------------------------------------*/ +- +-/* --- Support function: update tallyfile with tally!=TALLY_HI --- */ +- +-static int +-set_tally(pam_handle_t *pamh, uid_t uid, +- const char *filename, int *tfile, struct tallylog *tally) +-{ +- void *void_tally = tally; +- if (tally->fail_cnt != TALLY_HI) { +- if (lseek(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET) == (off_t)-1) { +- pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename); +- return PAM_AUTH_ERR; +- } +- if (pam_modutil_write(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { +- pam_syslog(pamh, LOG_ALERT, "update (write) failed for %s: %m", filename); +- return PAM_AUTH_ERR; +- } +- } +- +- return PAM_SUCCESS; +-} +- +-/*---------------------------------------------------------------------*/ +- +-/* --- PAM bits --- */ +- +-#ifndef MAIN +- +-#define RETURN_ERROR(i) return ((opts->ctrl & OPT_FAIL_ON_ERROR)?(i):(PAM_SUCCESS)) +- +-/*---------------------------------------------------------------------*/ +- +-static int +-tally_check (tally_t oldcnt, time_t oldtime, pam_handle_t *pamh, uid_t uid, +- const char *user, struct tally_options *opts, +- struct tallylog *tally) +-{ +- int rv = PAM_SUCCESS; +- int loglevel = LOG_DEBUG; +-#ifdef HAVE_LIBAUDIT +- char buf[64]; +- int audit_fd = -1; +- const void *rhost = NULL, *tty = NULL; +-#endif +- +- if ((opts->ctrl & OPT_MAGIC_ROOT) && getuid() == 0) { +- return PAM_SUCCESS; +- } +- /* magic_root skips tally check */ +-#ifdef HAVE_LIBAUDIT +- audit_fd = audit_open(); +- /* If there is an error & audit support is in the kernel report error */ +- if ((audit_fd < 0) && !(errno == EINVAL || errno == EPROTONOSUPPORT || +- errno == EAFNOSUPPORT)) +- return PAM_SYSTEM_ERR; +- (void)pam_get_item(pamh, PAM_TTY, &tty); +- (void)pam_get_item(pamh, PAM_RHOST, &rhost); +-#endif +- if (opts->deny != 0 && /* deny==0 means no deny */ +- tally->fail_cnt > opts->deny && /* tally>deny means exceeded */ +- ((opts->ctrl & OPT_DENY_ROOT) || uid)) { /* even_deny stops uid check */ +-#ifdef HAVE_LIBAUDIT +- if (tally->fail_cnt == opts->deny+1) { +- /* First say that max number was hit. */ +- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); +- audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf, +- rhost, NULL, tty, 1); +- } +-#endif +- if (uid) { +- /* Unlock time check */ +- if (opts->unlock_time && oldtime) { +- if (opts->unlock_time + oldtime <= time(NULL)) { +- /* ignore deny check after unlock_time elapsed */ +-#ifdef HAVE_LIBAUDIT +- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); +- audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, +- rhost, NULL, tty, 1); +-#endif +- rv = PAM_SUCCESS; +- goto cleanup; +- } +- } +- } else { +- /* Root unlock time check */ +- if (opts->root_unlock_time && oldtime) { +- if (opts->root_unlock_time + oldtime <= time(NULL)) { +- /* ignore deny check after unlock_time elapsed */ +-#ifdef HAVE_LIBAUDIT +- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); +- audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, +- rhost, NULL, tty, 1); +-#endif +- rv = PAM_SUCCESS; +- goto cleanup; +- } +- } +- } +- +-#ifdef HAVE_LIBAUDIT +- if (tally->fail_cnt == opts->deny+1) { +- /* First say that max number was hit. */ +- audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf, +- rhost, NULL, tty, 1); +- } +-#endif +- +- if (!(opts->ctrl & OPT_QUIET)) { +- pam_info(pamh, _("The account is locked due to %u failed logins."), +- (unsigned int)tally->fail_cnt); +- } +- loglevel = LOG_NOTICE; +- rv = PAM_AUTH_ERR; /* Only unconditional failure */ +- goto cleanup; +- } +- +- /* Lock time check */ +- if (opts->lock_time && oldtime) { +- if (opts->lock_time + oldtime > time(NULL)) { +- /* don't increase fail_cnt or update fail_time when +- lock_time applies */ +- tally->fail_cnt = oldcnt; +- tally->fail_time = oldtime; +- +- if (!(opts->ctrl & OPT_QUIET)) { +- pam_info(pamh, +- _("The account is temporarily locked (%ld seconds left)."), +- (long int) (oldtime+opts->lock_time-time(NULL))); +- } +- if (!(opts->ctrl & OPT_NOLOGNOTICE)) { +- pam_syslog(pamh, LOG_NOTICE, +- "user %s (%lu) has time limit [%lds left]" +- " since last failure.", +- user, (unsigned long)uid, +- (long int) (oldtime+opts->lock_time-time(NULL))); +- } +- rv = PAM_AUTH_ERR; +- goto cleanup; +- } +- } +- +-cleanup: +- if (!(opts->ctrl & OPT_NOLOGNOTICE) && (loglevel != LOG_DEBUG || opts->ctrl & OPT_DEBUG)) { +- pam_syslog(pamh, loglevel, +- "user %s (%lu) tally %hu, deny %hu", +- user, (unsigned long)uid, tally->fail_cnt, opts->deny); +- } +-#ifdef HAVE_LIBAUDIT +- if (audit_fd != -1) { +- close(audit_fd); +- } +-#endif +- return rv; +-} +- +-/* --- tally bump function: bump tally for uid by (signed) inc --- */ +- +-static int +-tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh, +- uid_t uid, const char *user, struct tally_options *opts, int *tfile) +-{ +- struct tallylog tally; +- tally_t oldcnt; +- const void *remote_host = NULL; +- int i, rv; +- +- tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ +- +- i = get_tally(pamh, uid, opts->filename, tfile, &tally, opts->ctrl); +- if (i != PAM_SUCCESS) { +- if (*tfile != -1) { +- close(*tfile); +- *tfile = -1; +- } +- RETURN_ERROR(i); +- } +- +- /* to remember old fail time (for locktime) */ +- if (oldtime) { +- *oldtime = (time_t)tally.fail_time; +- } +- +- tally.fail_time = time(NULL); +- +- (void) pam_get_item(pamh, PAM_RHOST, &remote_host); +- if (!remote_host) { +- (void) pam_get_item(pamh, PAM_TTY, &remote_host); +- if (!remote_host) { +- remote_host = "unknown"; +- } +- } +- +- strncpy(tally.fail_line, remote_host, +- sizeof(tally.fail_line)-1); +- tally.fail_line[sizeof(tally.fail_line)-1] = 0; +- +- oldcnt = tally.fail_cnt; +- +- if (!(opts->ctrl & OPT_MAGIC_ROOT) || getuid()) { +- /* magic_root doesn't change tally */ +- tally.fail_cnt += inc; +- +- if (tally.fail_cnt == TALLY_HI) { /* Overflow *and* underflow. :) */ +- tally.fail_cnt -= inc; +- pam_syslog(pamh, LOG_ALERT, "Tally %sflowed for user %s", +- (inc<0)?"under":"over",user); +- } +- } +- +- rv = tally_check(oldcnt, *oldtime, pamh, uid, user, opts, &tally); +- +- i = set_tally(pamh, uid, opts->filename, tfile, &tally); +- if (i != PAM_SUCCESS) { +- if (*tfile != -1) { +- close(*tfile); +- *tfile = -1; +- } +- if (rv == PAM_SUCCESS) +- RETURN_ERROR( i ); +- /* fallthrough */ +- } else if (!(opts->ctrl & OPT_SERIALIZE)) { +- close(*tfile); +- *tfile = -1; +- } +- +- return rv; +-} +- +-static int +-tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts, int old_tfile) +-{ +- struct tallylog tally; +- int tfile = old_tfile; +- int i; +- +- /* resets only if not magic root */ +- +- if ((opts->ctrl & OPT_MAGIC_ROOT) && getuid() == 0) { +- return PAM_SUCCESS; +- } +- +- tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ +- +- i=get_tally(pamh, uid, opts->filename, &tfile, &tally, opts->ctrl); +- if (i != PAM_SUCCESS) { +- if (tfile != old_tfile) /* the descriptor is not owned by pam data */ +- close(tfile); +- RETURN_ERROR(i); +- } +- +- memset(&tally, 0, sizeof(tally)); +- +- i=set_tally(pamh, uid, opts->filename, &tfile, &tally); +- if (i != PAM_SUCCESS) { +- if (tfile != old_tfile) /* the descriptor is not owned by pam data */ +- close(tfile); +- RETURN_ERROR(i); +- } +- +- if (tfile != old_tfile) +- close(tfile); +- +- return PAM_SUCCESS; +-} +- +-/*---------------------------------------------------------------------*/ +- +-/* --- authentication management functions (only) --- */ +- +-int +-pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, +- int argc, const char **argv) +-{ +- int +- rv, tfile = -1; +- time_t +- oldtime = 0; +- struct tally_options +- options, *opts = &options; +- uid_t +- uid; +- const char +- *user; +- +- rv = tally_parse_args(pamh, opts, PHASE_AUTH, argc, argv); +- if (rv != PAM_SUCCESS) +- RETURN_ERROR(rv); +- +- if (flags & PAM_SILENT) +- opts->ctrl |= OPT_QUIET; +- +- rv = pam_get_uid(pamh, &uid, &user, opts); +- if (rv != PAM_SUCCESS) +- RETURN_ERROR(rv); +- +- rv = tally_bump(1, &oldtime, pamh, uid, user, opts, &tfile); +- +- tally_set_data(pamh, oldtime, tfile); +- +- return rv; +-} +- +-int +-pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, +- int argc, const char **argv) +-{ +- int +- rv, tfile = -1; +- time_t +- oldtime = 0; +- struct tally_options +- options, *opts = &options; +- uid_t +- uid; +- const char +- *user; +- +- rv = tally_parse_args(pamh, opts, PHASE_AUTH, argc, argv); +- if ( rv != PAM_SUCCESS ) +- RETURN_ERROR( rv ); +- +- rv = pam_get_uid(pamh, &uid, &user, opts); +- if ( rv != PAM_SUCCESS ) +- RETURN_ERROR( rv ); +- +- if ( tally_get_data(pamh, &oldtime, &tfile) != 0 ) +- /* no data found */ +- return PAM_SUCCESS; +- +- rv = tally_reset(pamh, uid, opts, tfile); +- +- pam_set_data(pamh, MODULE_NAME, NULL, NULL); +- +- return rv; +-} +- +-/*---------------------------------------------------------------------*/ +- +-/* --- authentication management functions (only) --- */ +- +-/* To reset failcount of user on successful login */ +- +-int +-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, +- int argc, const char **argv) +-{ +- int +- rv, tfile = -1; +- time_t +- oldtime = 0; +- struct tally_options +- options, *opts = &options; +- uid_t +- uid; +- const char +- *user; +- +- rv = tally_parse_args(pamh, opts, PHASE_ACCOUNT, argc, argv); +- if ( rv != PAM_SUCCESS ) +- RETURN_ERROR( rv ); +- +- rv = pam_get_uid(pamh, &uid, &user, opts); +- if ( rv != PAM_SUCCESS ) +- RETURN_ERROR( rv ); +- +- if ( tally_get_data(pamh, &oldtime, &tfile) != 0 ) +- /* no data found */ +- return PAM_SUCCESS; +- +- rv = tally_reset(pamh, uid, opts, tfile); +- +- pam_set_data(pamh, MODULE_NAME, NULL, NULL); +- +- return rv; +-} +- +-/*-----------------------------------------------------------------------*/ +- +-#else /* #ifndef MAIN */ +- +-static const char *cline_filename = DEFAULT_LOGFILE; +-static tally_t cline_reset = TALLY_HI; /* Default is `interrogate only' */ +-static int cline_quiet = 0; +- +-/* +- * Not going to link with pamlib just for these.. :) +- */ +- +-static const char * +-pam_errors( int i ) +-{ +- switch (i) { +- case PAM_AUTH_ERR: return _("Authentication error"); +- case PAM_SERVICE_ERR: return _("Service error"); +- case PAM_USER_UNKNOWN: return _("Unknown user"); +- default: return _("Unknown error"); +- } +-} +- +-static int +-getopts( char **argv ) +-{ +- const char *pname = *argv; +- for ( ; *argv ; (void)(*argv && ++argv) ) { +- const char *str; +- if ( !strcmp (*argv,"--file") ) cline_filename=*++argv; +- else if ( !strcmp(*argv,"-f") ) cline_filename=*++argv; +- else if ((str = pam_str_skip_prefix(*argv, "--file=")) != NULL) +- cline_filename = str; +- else if ( !strcmp (*argv,"--user") ) cline_user=*++argv; +- else if ( !strcmp (*argv,"-u") ) cline_user=*++argv; +- else if ((str = pam_str_skip_prefix(*argv, "--user=")) != NULL) +- cline_user = str; +- else if ( !strcmp (*argv,"--reset") ) cline_reset=0; +- else if ( !strcmp (*argv,"-r") ) cline_reset=0; +- else if ((str = pam_str_skip_prefix(*argv, "--reset=")) != NULL) { +- if (sscanf(str, "%hu", &cline_reset) != 1) +- fprintf(stderr,_("%s: Bad number given to --reset=\n"),pname), exit(0); +- } +- else if ( !strcmp (*argv,"--quiet") ) cline_quiet=1; +- else { +- fprintf(stderr,_("%s: Unrecognised option %s\n"),pname,*argv); +- return FALSE; +- } +- } +- return TRUE; +-} +- +-static void +-print_one(const struct tallylog *tally, uid_t uid) +-{ +- static int once; +- const char *cp = "[UNKNOWN]"; +- time_t fail_time; +- struct tm *tm; +- struct passwd *pwent; +- const char *username = "[NONAME]"; +- char ptime[80]; +- +- pwent = getpwuid(uid); +- fail_time = tally->fail_time; +- if ((tm = localtime(&fail_time)) != NULL) { +- strftime (ptime, sizeof (ptime), "%D %H:%M:%S", tm); +- cp = ptime; +- } +- if (pwent) { +- username = pwent->pw_name; +- } +- if (!once) { +- printf (_("Login Failures Latest failure From\n")); +- once++; +- } +- printf ("%-15.15s %5hu ", username, tally->fail_cnt); +- if (tally->fail_time) { +- printf ("%-17.17s %s", cp, tally->fail_line); +- } +- putchar ('\n'); +-} +- +-int +-main( int argc UNUSED, char **argv ) +-{ +- struct tallylog tally; +- +- if ( ! getopts( argv+1 ) ) { +- printf(_("%s: [-f rooted-filename] [--file rooted-filename]\n" +- " [-u username] [--user username]\n" +- " [-r] [--reset[=n]] [--quiet]\n"), +- *argv); +- exit(2); +- } +- +- umask(077); +- +- /* +- * Major difference between individual user and all users: +- * --user just handles one user, just like PAM. +- * without --user it handles all users, sniffing cline_filename for nonzeros +- */ +- +- if ( cline_user ) { +- uid_t uid; +- int tfile = -1; +- struct tally_options opts; +- int i; +- +- memset(&opts, 0, sizeof(opts)); +- opts.ctrl = OPT_AUDIT; +- i=pam_get_uid(NULL, &uid, NULL, &opts); +- if ( i != PAM_SUCCESS ) { +- fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); +- exit(1); +- } +- +- if (cline_reset == 0) { +- struct stat st; +- +- if (stat(cline_filename, &st) && errno == ENOENT) { +- if (!cline_quiet) { +- memset(&tally, 0, sizeof(tally)); +- print_one(&tally, uid); +- } +- return 0; /* no file => nothing to reset */ +- } +- } +- +- i=get_tally(NULL, uid, cline_filename, &tfile, &tally, 0); +- if ( i != PAM_SUCCESS ) { +- if (tfile != -1) +- close(tfile); +- fprintf(stderr, "%s: %s\n", *argv, pam_errors(i)); +- exit(1); +- } +- +- if ( !cline_quiet ) +- print_one(&tally, uid); +- +- if (cline_reset != TALLY_HI) { +-#ifdef HAVE_LIBAUDIT +- char buf[64]; +- int audit_fd = audit_open(); +- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset); +- audit_log_user_message(audit_fd, AUDIT_USER_ACCT, +- buf, NULL, NULL, ttyname(STDIN_FILENO), 1); +- if (audit_fd >=0) +- close(audit_fd); +-#endif +- if (cline_reset == 0) { +- memset(&tally, 0, sizeof(tally)); +- } else { +- tally.fail_cnt = cline_reset; +- } +- i=set_tally(NULL, uid, cline_filename, &tfile, &tally); +- close(tfile); +- if (i != PAM_SUCCESS) { +- fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); +- exit(1); +- } +- } else { +- close(tfile); +- } +- } +- else /* !cline_user (ie, operate on all users) */ { +- FILE *tfile=fopen(cline_filename, "r"); +- uid_t uid=0; +- if (!tfile && cline_reset != 0) { +- perror(*argv); +- exit(1); +- } +- +- for ( ; tfile && !feof(tfile); uid++ ) { +- if ( !fread(&tally, sizeof(tally), 1, tfile) +- || !tally.fail_cnt ) { +- continue; +- } +- print_one(&tally, uid); +- } +- if (tfile) +- fclose(tfile); +- if ( cline_reset!=0 && cline_reset!=TALLY_HI ) { +- fprintf(stderr,_("%s: Can't reset all users to non-zero\n"),*argv); +- } +- else if ( !cline_reset ) { +-#ifdef HAVE_LIBAUDIT +- char buf[64]; +- int audit_fd = audit_open(); +- snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0"); +- audit_log_user_message(audit_fd, AUDIT_USER_ACCT, +- buf, NULL, NULL, ttyname(STDIN_FILENO), 1); +- if (audit_fd >=0) +- close(audit_fd); +-#endif +- tfile=fopen(cline_filename, "w"); +- if ( !tfile ) perror(*argv), exit(0); +- fclose(tfile); +- } +- } +- return 0; +-} +- +- +-#endif /* #ifndef MAIN */ +diff --git a/modules/pam_tally2/pam_tally2_app.c b/modules/pam_tally2/pam_tally2_app.c +deleted file mode 100644 +index b72e9bfd..00000000 +--- a/modules/pam_tally2/pam_tally2_app.c ++++ /dev/null +@@ -1,6 +0,0 @@ +-/* +- # This seemed like such a good idea at the time. :) +- */ +- +-#define MAIN +-#include "pam_tally2.c" +diff --git a/modules/pam_tally2/tallylog.h b/modules/pam_tally2/tallylog.h +deleted file mode 100644 +index 596b1dac..00000000 +--- a/modules/pam_tally2/tallylog.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* +- * Copyright 2006, Red Hat, Inc. +- * 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, this list of conditions and the following disclaimer. +- * 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. Neither the name of Red Hat, Inc. nor the names of its contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY RED HAT, INC. AND CONTRIBUTORS ``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 JULIE HAUGH OR CONTRIBUTORS 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. +- */ +- +-/* +- * tallylog.h - login failure data file format +- * +- * The new login failure file is not compatible with the old faillog(8) format +- * Each record in the file represents a separate UID and the file +- * is indexed in that fashion. +- */ +- +- +-#ifndef _TALLYLOG_H +-#define _TALLYLOG_H +- +-#include +- +-struct tallylog { +- char fail_line[52]; /* rhost or tty of last failure */ +- uint16_t reserved; /* reserved for future use */ +- uint16_t fail_cnt; /* failures since last success */ +- uint64_t fail_time; /* time of last failure */ +-}; +-/* 64 bytes / entry */ +- +-#endif +diff --git a/modules/pam_tally2/tst-pam_tally2 b/modules/pam_tally2/tst-pam_tally2 +deleted file mode 100755 +index 83c71f41..00000000 +--- a/modules/pam_tally2/tst-pam_tally2 ++++ /dev/null +@@ -1,2 +0,0 @@ +-#!/bin/sh +-../../tests/tst-dlopen .libs/pam_tally2.so