commit 9546c864db9964c213c6d3db0ac41346a408bbd8 Author: zyppe <210hcl@gmail.com> Date: Mon Feb 5 14:46:13 2024 +0800 Initialize for pam diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b3b1b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Linux-PAM-1.3.0-docs.tar.bz2 +Linux-PAM-1.3.0.tar.bz2 diff --git a/.pam.metadata b/.pam.metadata new file mode 100644 index 0000000..d35b710 --- /dev/null +++ b/.pam.metadata @@ -0,0 +1,2 @@ +f3a6433f5f732d14e03e6d89b174680a429ff1c71505f639e18b83bac238d80a Linux-PAM-1.3.0-docs.tar.bz2 +27955d4d03d175a86f40c97ba2486ed86d63a7ed953139efbba5e7848ffe955e Linux-PAM-1.3.0.tar.bz2 diff --git a/baselibs.conf b/baselibs.conf new file mode 100644 index 0000000..0b527f9 --- /dev/null +++ b/baselibs.conf @@ -0,0 +1,4 @@ +pam + arch i586 requires "systemd-32bit" +pam-devel +pam-extra diff --git a/bsc1184358-prevent-LOCAL-from-being-resolved.patch b/bsc1184358-prevent-LOCAL-from-being-resolved.patch new file mode 100644 index 0000000..2f223a4 --- /dev/null +++ b/bsc1184358-prevent-LOCAL-from-being-resolved.patch @@ -0,0 +1,90 @@ +From c4dbba499f335ad88536244254d2d444b8e1c17c Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Tue, 6 Apr 2021 12:27:38 +0200 +Subject: [PATCH] pam_access: clean up the remote host matching code + +* modules/pam_access/pam_access.c (from_match): Split out remote_match() + function and avoid calling it when matching against LOCAL keyword. + There is also no point in doing domain match against TTY or SERVICE. +--- + modules/pam_access/pam_access.c | 42 +++++++++++++++++++++------------ + 1 file changed, 27 insertions(+), 15 deletions(-) + +Index: Linux-PAM-1.3.0/modules/pam_access/pam_access.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_access/pam_access.c ++++ Linux-PAM-1.3.0/modules/pam_access/pam_access.c +@@ -166,6 +166,7 @@ static int list_match (pam_handle_t *, c + static int user_match (pam_handle_t *, char *, struct login_info *); + static int group_match (pam_handle_t *, const char *, const char *, int); + static int from_match (pam_handle_t *, char *, struct login_info *); ++static int remote_match (pam_handle_t *, char *, struct login_info *); + static int string_match (pam_handle_t *, const char *, const char *, int); + static int network_netmask_match (pam_handle_t *, const char *, const char *, struct login_info *); + +@@ -584,11 +585,9 @@ group_match (pam_handle_t *pamh, const c + /* from_match - match a host or tty against a list of tokens */ + + static int +-from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item) ++from_match (pam_handle_t *pamh, char *tok, struct login_info *item) + { + const char *string = item->from; +- int tok_len; +- int str_len; + int rv; + + if (item->debug) +@@ -611,13 +610,28 @@ from_match (pam_handle_t *pamh UNUSED, c + } else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) { + /* ALL or exact match */ + return rv; +- } else if (tok[0] == '.') { /* domain: match last fields */ +- if ((str_len = strlen(string)) > (tok_len = strlen(tok)) +- && strcasecmp(tok, string + str_len - tok_len) == 0) +- return (YES); +- } else if (item->from_remote_host == 0) { /* local: no PAM_RHOSTS */ +- if (strcasecmp(tok, "LOCAL") == 0) +- return (YES); ++ } else if (strcasecmp(tok, "LOCAL") == 0) { ++ /* LOCAL matches only local accesses */ ++ if (!item->from_remote_host) ++ return YES; ++ return NO; ++ } else if (item->from_remote_host) { ++ return remote_match(pamh, tok, item); ++ } ++ return NO; ++} ++ ++static int ++remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) ++{ ++ const char *string = item->from; ++ size_t tok_len = strlen(tok); ++ size_t str_len; ++ ++ if (tok[0] == '.') { /* domain: match last fields */ ++ if ((str_len = strlen(string)) > tok_len ++ && strcasecmp(tok, string + str_len - tok_len) == 0) ++ return YES; + } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { + struct addrinfo hint; + +@@ -654,13 +668,11 @@ from_match (pam_handle_t *pamh UNUSED, c + runp = runp->ai_next; + } + } +- } else { +- /* Assume network/netmask with a IP of a host. */ +- if (network_netmask_match(pamh, tok, string, item)) +- return YES; ++ return NO; + } + +- return NO; ++ /* Assume network/netmask with an IP of a host. */ ++ return network_netmask_match(pamh, tok, string, item); + } + + /* string_match - match a string against one token */ diff --git a/common-account.pamd b/common-account.pamd new file mode 100644 index 0000000..5e724e8 --- /dev/null +++ b/common-account.pamd @@ -0,0 +1,9 @@ +# +# /etc/pam.d/common-account - account settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the account modules that define +# the central access policy for use on the system. The default is to +# only deny service to users whose accounts are expired. +# +account required pam_unix.so try_first_pass diff --git a/common-auth.pamd b/common-auth.pamd new file mode 100644 index 0000000..4fa5eea --- /dev/null +++ b/common-auth.pamd @@ -0,0 +1,11 @@ +# +# /etc/pam.d/common-auth - authentication settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the authentication modules that define +# the central authentication scheme for use on the system +# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the +# traditional Unix authentication mechanisms. +# +auth required pam_env.so +auth required pam_unix.so try_first_pass diff --git a/common-password.pamd b/common-password.pamd new file mode 100644 index 0000000..5e7e0bc --- /dev/null +++ b/common-password.pamd @@ -0,0 +1,12 @@ +# +# /etc/pam.d/common-password - password-related modules common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of modules that define the services to be +# used to change user passwords. +# +# The "nullok" option allows users to change an empty password, else +# empty passwords are treated as locked accounts. +# +password requisite pam_cracklib.so +password required pam_unix.so use_authtok nullok try_first_pass diff --git a/common-session.pamd b/common-session.pamd new file mode 100644 index 0000000..79e1e39 --- /dev/null +++ b/common-session.pamd @@ -0,0 +1,13 @@ +# +# /etc/pam.d/common-session - session-related modules common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of modules that define tasks to be performed +# at the start and end of sessions of *any* kind (both interactive and +# non-interactive). +# +session required pam_limits.so +session required pam_unix.so try_first_pass +session optional pam_umask.so +session optional pam_env.so +session optional pam_systemd.so diff --git a/encryption_method_nis.diff b/encryption_method_nis.diff new file mode 100644 index 0000000..da156be --- /dev/null +++ b/encryption_method_nis.diff @@ -0,0 +1,71 @@ +--- modules/pam_unix/pam_unix_passwd.c ++++ modules/pam_unix/pam_unix_passwd.c 2016/04/11 13:49:32 +@@ -840,6 +840,29 @@ + * rebuild the password database file. + */ + ++ ++ /* if it is a NIS account, check for special hash algo */ ++ if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1)) { ++ /* preset encryption method with value from /etc/login.defs */ ++ int j; ++ char *val = _unix_search_key ("ENCRYPT_METHOD_NIS", LOGIN_DEFS); ++ if (val) { ++ for (j = 0; j < UNIX_CTRLS_; ++j) { ++ if (unix_args[j].token && unix_args[j].is_hash_algo ++ && !strncasecmp(val, unix_args[j].token, strlen(unix_args[j].token))) { ++ break; ++ } ++ } ++ if (j >= UNIX_CTRLS_) { ++ pam_syslog(pamh, LOG_WARNING, "unrecognized ENCRYPT_METHOD_NIS value [%s]", val); ++ } else { ++ ctrl &= unix_args[j].mask; /* for turning things off */ ++ ctrl |= unix_args[j].flag; /* for turning things on */ ++ } ++ free (val); ++ } ++ } ++ + /* + * First we encrypt the new password. + */ +--- modules/pam_unix/support.c ++++ modules/pam_unix/support.c 2016/04/11 13:49:32 +@@ -31,8 +31,8 @@ + #include "support.h" + #include "passverify.h" + +-static char * +-search_key (const char *key, const char *filename) ++char * ++_unix_search_key (const char *key, const char *filename) + { + FILE *fp; + char *buf = NULL; +@@ -153,7 +153,7 @@ + } + + /* preset encryption method with value from /etc/login.defs */ +- val = search_key ("ENCRYPT_METHOD", LOGIN_DEFS); ++ val = _unix_search_key ("ENCRYPT_METHOD", LOGIN_DEFS); + if (val) { + for (j = 0; j < UNIX_CTRLS_; ++j) { + if (unix_args[j].token && unix_args[j].is_hash_algo +@@ -171,7 +171,7 @@ + + /* read number of rounds for crypt algo */ + if (rounds && (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl))) { +- val=search_key ("SHA_CRYPT_MAX_ROUNDS", LOGIN_DEFS); ++ val=_unix_search_key ("SHA_CRYPT_MAX_ROUNDS", LOGIN_DEFS); + + if (val) { + *rounds = strtol(val, NULL, 10); +--- modules/pam_unix/support.h ++++ modules/pam_unix/support.h 2016/04/11 13:49:32 +@@ -174,4 +174,5 @@ + + extern int _unix_run_verify_binary(pam_handle_t *pamh, + unsigned int ctrl, const char *user, int *daysleft); ++extern char *_unix_search_key(const char *key, const char *filename); + #endif /* _PAM_UNIX_SUPPORT_H */ diff --git a/etc.environment b/etc.environment new file mode 100644 index 0000000..f46b8d9 --- /dev/null +++ b/etc.environment @@ -0,0 +1,5 @@ +# +# This file is parsed by pam_env module +# +# Syntax: simple "KEY=VAL" pairs on seperate lines +# diff --git a/fix-man-links.dif b/fix-man-links.dif new file mode 100644 index 0000000..f79666e --- /dev/null +++ b/fix-man-links.dif @@ -0,0 +1,56 @@ +Index: Linux-PAM-1.1.8/doc/man/pam.8 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam.8 ++++ Linux-PAM-1.1.8/doc/man/pam.8 +@@ -1 +1 @@ +-.so PAM.8 ++.so man8/PAM.8 +Index: Linux-PAM-1.1.8/doc/man/pam.d.5 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam.d.5 ++++ Linux-PAM-1.1.8/doc/man/pam.d.5 +@@ -1 +1 @@ +-.so pam.conf.5 ++.so man5/pam.conf.5 +Index: Linux-PAM-1.1.8/doc/man/pam_get_authtok_noverify.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_get_authtok_noverify.3 ++++ Linux-PAM-1.1.8/doc/man/pam_get_authtok_noverify.3 +@@ -1 +1 @@ +-.so pam_get_authtok.3 ++.so man3/pam_get_authtok.3 +Index: Linux-PAM-1.1.8/doc/man/pam_get_authtok_verify.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_get_authtok_verify.3 ++++ Linux-PAM-1.1.8/doc/man/pam_get_authtok_verify.3 +@@ -1 +1 @@ +-.so pam_get_authtok.3 ++.so man3/pam_get_authtok.3 +Index: Linux-PAM-1.1.8/doc/man/pam_verror.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_verror.3 ++++ Linux-PAM-1.1.8/doc/man/pam_verror.3 +@@ -1 +1 @@ +-.so pam_error.3 ++.so man3/pam_error.3 +Index: Linux-PAM-1.1.8/doc/man/pam_vinfo.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_vinfo.3 ++++ Linux-PAM-1.1.8/doc/man/pam_vinfo.3 +@@ -1 +1 @@ +-.so pam_info.3 ++.so man3/pam_info.3 +Index: Linux-PAM-1.1.8/doc/man/pam_vprompt.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_vprompt.3 ++++ Linux-PAM-1.1.8/doc/man/pam_vprompt.3 +@@ -1 +1 @@ +-.so pam_prompt.3 ++.so man3/pam_prompt.3 +Index: Linux-PAM-1.1.8/doc/man/pam_vsyslog.3 +=================================================================== +--- Linux-PAM-1.1.8.orig/doc/man/pam_vsyslog.3 ++++ Linux-PAM-1.1.8/doc/man/pam_vsyslog.3 +@@ -1 +1 @@ +-.so pam_syslog.3 ++.so man3/pam_syslog.3 diff --git a/macros.pam b/macros.pam new file mode 100644 index 0000000..4993394 --- /dev/null +++ b/macros.pam @@ -0,0 +1,7 @@ +%_pam_libdir /%{_libdir} +%_pam_moduledir /%{_lib}/security +%_pam_secconfdir /%{_sysconfdir}/security +%_pam_confdir /%{_sysconfdir}/pam.d +%_pam_vendordir /%{_sysconfdir}/pam.d +# legacy, to be retired +%_pamdir /%{_pam_moduledir} diff --git a/other.pamd b/other.pamd new file mode 100644 index 0000000..840eb77 --- /dev/null +++ b/other.pamd @@ -0,0 +1,10 @@ +#%PAM-1.0 +auth required pam_warn.so +auth required pam_deny.so +account required pam_warn.so +account required pam_deny.so +password required pam_warn.so +password required pam_deny.so +session required pam_warn.so +session required pam_deny.so + diff --git a/pam-bsc1177858-dont-free-environment-string.patch b/pam-bsc1177858-dont-free-environment-string.patch new file mode 100644 index 0000000..9db2eda --- /dev/null +++ b/pam-bsc1177858-dont-free-environment-string.patch @@ -0,0 +1,26 @@ +Index: Linux-PAM-1.3.0/modules/pam_xauth/pam_xauth.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_xauth/pam_xauth.c ++++ Linux-PAM-1.3.0/modules/pam_xauth/pam_xauth.c +@@ -697,8 +697,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 */ + { +@@ -761,7 +762,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-bsc1178727-initialize-daysleft.patch b/pam-bsc1178727-initialize-daysleft.patch new file mode 100644 index 0000000..68ff207 --- /dev/null +++ b/pam-bsc1178727-initialize-daysleft.patch @@ -0,0 +1,13 @@ +Index: Linux-PAM-1.3.0/modules/pam_unix/pam_unix_acct.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_unix/pam_unix_acct.c ++++ Linux-PAM-1.3.0/modules/pam_unix/pam_unix_acct.c +@@ -188,7 +188,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int + unsigned int ctrl; + const void *void_uname; + const char *uname; +- int retval, daysleft; ++ int retval, daysleft = -1; + struct spwd *spent; + struct passwd *pwent; + char buf[256]; diff --git a/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch b/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch new file mode 100644 index 0000000..e7a7904 --- /dev/null +++ b/pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch @@ -0,0 +1,171 @@ +Index: Linux-PAM-1.3.0/modules/pam_limits/pam_limits.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_limits/pam_limits.c ++++ Linux-PAM-1.3.0/modules/pam_limits/pam_limits.c +@@ -487,6 +487,55 @@ static int init_limits(pam_handle_t *pam + return retval; + } + ++/* ++ * Read the contents of /proc/sys/fs/ ++ * return 1 if conversion succeeds, result is in *valuep ++ * return 0 if conversion fails. ++ */ ++static int ++value_from_proc_sys_fs(const char *name, rlim_t *valuep) ++{ ++ char pathname[128]; ++ char buf[128]; ++ FILE *fp; ++ int retval; ++ ++ retval = 0; ++ ++ snprintf(pathname, sizeof(pathname), "/proc/sys/fs/%s", name); ++ ++ if ((fp = fopen(pathname, "r")) != NULL) { ++ if (fgets(buf, sizeof(buf), fp) != NULL) { ++ char *endptr; ++ ++#ifdef __USE_FILE_OFFSET64 ++ *valuep = strtoull(buf, &endptr, 10); ++#else ++ *valuep = strtoul(buf, &endptr, 10); ++#endif ++ ++ retval = (endptr != buf); ++ } ++ ++ fclose(fp); ++ } ++ ++ return retval; ++} ++ ++/* ++ * Check if the string passed as the argument corresponds to ++ * "unlimited" ++ */ ++static inline int ++is_unlimited(const char *lim_value) ++{ ++ return strcmp(lim_value, "-1") == 0 ++ || strcmp(lim_value, "-") == 0 ++ || strcmp(lim_value, "unlimited") == 0 ++ || strcmp(lim_value, "infinity") == 0; ++} ++ + static void + process_limit (const pam_handle_t *pamh, int source, const char *lim_type, + const char *lim_item, const char *lim_value, +@@ -569,13 +618,12 @@ process_limit (const pam_handle_t *pamh, + pam_syslog(pamh, LOG_DEBUG, "unknown limit type '%s'", lim_type); + return; + } ++ + if (limit_item != LIMIT_PRI + #ifdef RLIMIT_NICE + && limit_item != RLIMIT_NICE + #endif +- && (strcmp(lim_value, "-1") == 0 +- || strcmp(lim_value, "-") == 0 || strcmp(lim_value, "unlimited") == 0 +- || strcmp(lim_value, "infinity") == 0)) { ++ && is_unlimited(lim_value)) { + int_value = -1; + rlimit_value = RLIM_INFINITY; + } else if (limit_item == LIMIT_PRI || limit_item == LIMIT_LOGIN || +@@ -591,7 +639,7 @@ process_limit (const pam_handle_t *pamh, + pam_syslog(pamh, LOG_DEBUG, + "wrong limit value '%s' for limit type '%s'", + lim_value, lim_type); +- return; ++ return; + } + } else { + #ifdef __USE_FILE_OFFSET64 +@@ -652,6 +700,19 @@ process_limit (const pam_handle_t *pamh, + rlimit_value = 20 - int_value; + break; + #endif ++ case RLIMIT_NOFILE: ++ /* ++ * If nofile is to be set to "unlimited", try to set it to ++ * the value in /proc/sys/fs/nr_open instead. ++ */ ++ if (rlimit_value == RLIM_INFINITY) { ++ if (!value_from_proc_sys_fs("nr_open", &rlimit_value)) ++ pam_syslog(pamh, LOG_DEBUG, ++ "Cannot set \"nofile\" to a sensible value"); ++ else ++ pam_syslog(pamh, LOG_WARNING, "Setting \"nofile\" limit to %lu", (long unsigned) rlimit_value); ++ } ++ break; + } + + if ( (limit_item != LIMIT_LOGIN) +Index: Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/Linux-PAM_SAG.txt ++++ Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +@@ -2408,7 +2408,10 @@ The fields listed above should be filled + 2.6.12 and higher) + + All items support the values -1, unlimited or infinity indicating no limit, +-except for priority and nice. ++except for priority, and nice. ++ ++If nofile is to be set to one of these values, ++it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)). + + If a hard limit or soft limit of a resource is set to a valid value, but + outside of the supported range of the local system, the system may reject the +Index: Linux-PAM-1.3.0/doc/sag/html/sag-pam_limits.html +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/html/sag-pam_limits.html ++++ Linux-PAM-1.3.0/doc/sag/html/sag-pam_limits.html +@@ -102,6 +102,9 @@ + All items support the values -1, + unlimited or infinity indicating no limit, + except for priority and nice. ++ If nofile is to be set to one of these values, ++ it will be set to the contents of /proc/sys/fs/nr_open instead ++ (see setrlimit(3)). +

+ If a hard limit or soft limit of a resource is set to a valid value, + but outside of the supported range of the local system, the system +Index: Linux-PAM-1.3.0/modules/pam_limits/limits.conf.5 +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_limits/limits.conf.5 ++++ Linux-PAM-1.3.0/modules/pam_limits/limits.conf.5 +@@ -282,6 +282,8 @@ indicating no limit, except for + \fBpriority\fR + and + \fBnice\fR\&. ++If \fBnofile\fP is to be set to one of these values, ++it will be set to the contents of \fI/proc/sys/fs/nr_open\fP instead (see \fBsetrlimit\fP(3))\&. + .PP + If a hard limit or soft limit of a resource is set to a valid value, but outside of the supported range of the local system, the system may reject the new limit or unexpected behavior may occur\&. If the control value + \fIrequired\fR +@@ -331,7 +333,8 @@ ftp hard nproc + \fBpam_limits\fR(8), + \fBpam.d\fR(5), + \fBpam\fR(8), +-\fBgetrlimit\fR(2)\fBgetrlimit\fR(3p) ++\fBgetrlimit\fR(2), ++\fBgetrlimit\fR(3p) + .SH "AUTHOR" + .PP + pam_limits was initially written by Cristian Gafton +Index: Linux-PAM-1.3.0/modules/pam_limits/limits.conf.5.xml +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_limits/limits.conf.5.xml ++++ Linux-PAM-1.3.0/modules/pam_limits/limits.conf.5.xml +@@ -275,6 +275,8 @@ + All items support the values -1, + unlimited or infinity indicating no limit, + except for priority and nice. ++ If nofile is to be set to one of these values, ++ it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)). + + + If a hard limit or soft limit of a resource is set to a valid value, diff --git a/pam-bsc1197024-free-addrinfo-before-return.patch b/pam-bsc1197024-free-addrinfo-before-return.patch new file mode 100644 index 0000000..05386f5 --- /dev/null +++ b/pam-bsc1197024-free-addrinfo-before-return.patch @@ -0,0 +1,21 @@ +Index: Linux-PAM-1.3.0/modules/pam_access/pam_access.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_access/pam_access.c ++++ Linux-PAM-1.3.0/modules/pam_access/pam_access.c +@@ -801,10 +801,16 @@ network_netmask_match (pam_handle_t *pam + hint.ai_family = AF_UNSPEC; + + if (item->gai_rv != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else if (!item->res && + (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else + { + struct addrinfo *runp = item->res; diff --git a/pam-bsc1197794-do-not-include-obsolete-header-files.patch b/pam-bsc1197794-do-not-include-obsolete-header-files.patch new file mode 100644 index 0000000..9582f20 --- /dev/null +++ b/pam-bsc1197794-do-not-include-obsolete-header-files.patch @@ -0,0 +1,43 @@ +Index: Linux-PAM-1.3.0/modules/pam_selinux/pam_selinux.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_selinux/pam_selinux.c ++++ Linux-PAM-1.3.0/modules/pam_selinux/pam_selinux.c +@@ -63,8 +63,8 @@ + + #include + #include +-#include +-#include ++// #include ++// #include + #include + #include + #include +@@ -554,6 +554,7 @@ static int + compute_tty_context(const pam_handle_t *pamh, module_data_t *data) + { + const char *tty = get_item(pamh, PAM_TTY); ++ security_class_t tclass; + + if (!tty || !*tty || !strcmp(tty, "ssh") || !strncmp(tty, "NODEV", 5)) { + tty = ttyname(STDIN_FILENO); +@@ -589,8 +590,18 @@ compute_tty_context(const pam_handle_t * + return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS; + } + ++ tclass = string_to_security_class("chr_file"); ++ if (tclass == 0) { ++ pam_syslog(pamh, LOG_ERR, "Failed to get chr_file security class"); ++ freecon(data->prev_tty_context); ++ data->prev_tty_context = NULL; ++ free(data->tty_path); ++ data->tty_path = NULL; ++ return (security_getenforce() == 1) ? PAM_SESSION_ERR : PAM_SUCCESS; ++ } ++ + if (security_compute_relabel(data->exec_context, data->prev_tty_context, +- SECCLASS_CHR_FILE, &data->tty_context)) { ++ tclass, &data->tty_context)) { + data->tty_context = NULL; + pam_syslog(pamh, LOG_ERR, "Failed to compute new context for %s: %m", + data->tty_path); diff --git a/pam-bsc1217000-pam_lastlog-check-localtime_r-return-value.patch b/pam-bsc1217000-pam_lastlog-check-localtime_r-return-value.patch new file mode 100644 index 0000000..dbf5134 --- /dev/null +++ b/pam-bsc1217000-pam_lastlog-check-localtime_r-return-value.patch @@ -0,0 +1,41 @@ +From 40c271164dbcebfc5304d0537a42fb42e6b6803c Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 26 Sep 2022 12:16:53 +0200 +Subject: [PATCH] pam_lastlog: check localtime_r() return value + +Check the return value of localtime_r() before calling strftime(). This +function crashes if the argument is NULL. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012871 + +Signed-off-by: Iker Pedrosa +--- + modules/pam_lastlog/pam_lastlog.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c +index abd048df..121e7560 100644 +--- a/modules/pam_lastlog/pam_lastlog.c ++++ b/modules/pam_lastlog/pam_lastlog.c +@@ -573,12 +573,12 @@ last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t llt + time_t lf_time; + + lf_time = utuser.ut_tv.tv_sec; +- tm = localtime_r (&lf_time, &tm_buf); +- strftime (the_time, sizeof (the_time), +- /* TRANSLATORS: "strftime options for date of last login" */ +- _(" %a %b %e %H:%M:%S %Z %Y"), tm); +- +- date = the_time; ++ if ((tm = localtime_r (&lf_time, &tm_buf)) != NULL) { ++ strftime (the_time, sizeof (the_time), ++ /* TRANSLATORS: "strftime options for date of last login" */ ++ _(" %a %b %e %H:%M:%S %Z %Y"), tm); ++ date = the_time; ++ } + } + + /* we want & have the host? */ +-- +2.35.3 + diff --git a/pam-bsc1218475-pam_namespace-O_DIRECTORY-flag.patch b/pam-bsc1218475-pam_namespace-O_DIRECTORY-flag.patch new file mode 100644 index 0000000..b80cf14 --- /dev/null +++ b/pam-bsc1218475-pam_namespace-O_DIRECTORY-flag.patch @@ -0,0 +1,34 @@ +--- Linux-PAM-1.3.0.old/modules/pam_namespace/pam_namespace.c 2024-01-02 22:59:07.885482449 +0100 ++++ Linux-PAM-1.3.0/modules/pam_namespace/pam_namespace.c 2024-01-02 23:01:56.195614994 +0100 +@@ -1027,7 +1027,7 @@ static int protect_dir(const char *path, + int dfd = AT_FDCWD; + int dfd_next; + int save_errno; +- int flags = O_RDONLY; ++ int flags = O_RDONLY | O_DIRECTORY; + int rv = -1; + struct stat st; + +@@ -1081,22 +1081,6 @@ static int protect_dir(const char *path, + rv = openat(dfd, dir, flags); + } + +- if (rv != -1) { +- if (fstat(rv, &st) != 0) { +- save_errno = errno; +- close(rv); +- rv = -1; +- errno = save_errno; +- goto error; +- } +- if (!S_ISDIR(st.st_mode)) { +- close(rv); +- errno = ENOTDIR; +- rv = -1; +- goto error; +- } +- } +- + if (flags & O_NOFOLLOW) { + /* we are inside user-owned dir - protect */ + if (protect_mount(rv, p, idata) == -1) { diff --git a/pam-fix-config-order-in-manpage.patch b/pam-fix-config-order-in-manpage.patch new file mode 100644 index 0000000..5172e22 --- /dev/null +++ b/pam-fix-config-order-in-manpage.patch @@ -0,0 +1,71 @@ +Index: Linux-PAM-1.3.0/modules/pam_umask/pam_umask.8.xml +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_umask/pam_umask.8.xml ++++ Linux-PAM-1.3.0/modules/pam_umask/pam_umask.8.xml +@@ -48,22 +48,22 @@ + + + +- umask= argument ++ umask= entry in the user's GECOS field + + + + +- umask= entry in the user's GECOS field ++ umask= argument + + + + +- UMASK= entry from /etc/default/login ++ UMASK= entry from /etc/login.defs + + + + +- UMASK entry from /etc/login.defs ++ UMASK= entry from /etc/default/login + + + +Index: Linux-PAM-1.3.0/modules/pam_umask/pam_umask.8 +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_umask/pam_umask.8 ++++ Linux-PAM-1.3.0/modules/pam_umask/pam_umask.8 +@@ -46,7 +46,7 @@ The PAM module tries to get the umask va + .sp -1 + .IP \(bu 2.3 + .\} +-umask= argument ++umask= entry in the user\*(Aqs GECOS field + .RE + .sp + .RS 4 +@@ -57,7 +57,7 @@ umask= argument + .sp -1 + .IP \(bu 2.3 + .\} +-umask= entry in the user\*(Aqs GECOS field ++umask= argument + .RE + .sp + .RS 4 +@@ -68,7 +68,7 @@ umask= entry in the user\*(Aqs GECOS fie + .sp -1 + .IP \(bu 2.3 + .\} +-UMASK= entry from /etc/default/login ++UMASK= entry from /etc/login\&.defs + .RE + .sp + .RS 4 +@@ -79,7 +79,7 @@ UMASK= entry from /etc/default/login + .sp -1 + .IP \(bu 2.3 + .\} +-UMASK entry from /etc/login\&.defs ++UMASK= entry from /etc/default/login + .RE + .PP + The GECOS field is split on comma \*(Aq,\*(Aq characters\&. The module also in addition to the umask= entry recognizes pri= entry, which sets the nice priority value for the session, and ulimit= entry, which sets the maximum size of files the processes in the session can create\&. diff --git a/pam-hostnames-in-access_conf.patch b/pam-hostnames-in-access_conf.patch new file mode 100644 index 0000000..770d3a6 --- /dev/null +++ b/pam-hostnames-in-access_conf.patch @@ -0,0 +1,156 @@ +Index: modules/pam_access/pam_access.c +=================================================================== +--- modules/pam_access/pam_access.c.orig ++++ modules/pam_access/pam_access.c +@@ -692,10 +692,10 @@ string_match (pam_handle_t *pamh, const + return (NO); + } + +- + /* network_netmask_match - match a string against one token + * where string is a hostname or ip (v4,v6) address and tok +- * represents either a single ip (v4,v6) address or a network/netmask ++ * represents either a hostname, a single ip (v4,v6) address ++ * or a network/netmask + */ + static int + network_netmask_match (pam_handle_t *pamh, +@@ -704,10 +704,14 @@ network_netmask_match (pam_handle_t *pam + char *netmask_ptr; + char netmask_string[MAXHOSTNAMELEN + 1]; + int addr_type; ++ struct addrinfo *ai; ++ struct sockaddr_storage tok_addr; ++ struct addrinfo hint; + + if (item->debug) +- pam_syslog (pamh, LOG_DEBUG, ++ pam_syslog (pamh, LOG_DEBUG, + "network_netmask_match: tok=%s, item=%s", tok, string); ++ + /* OK, check if tok is of type addr/mask */ + if ((netmask_ptr = strchr(tok, '/')) != NULL) + { +@@ -717,7 +721,7 @@ network_netmask_match (pam_handle_t *pam + *netmask_ptr = 0; + netmask_ptr++; + +- if (isipaddr(tok, &addr_type, NULL) == NO) ++ if (isipaddr(tok, &addr_type, &tok_addr) == NO) + { /* no netaddr */ + return NO; + } +@@ -739,19 +743,47 @@ network_netmask_match (pam_handle_t *pam + netmask_ptr = number_to_netmask(netmask, addr_type, + netmask_string, MAXHOSTNAMELEN); + } +- } ++ ++ /* ++ * Although isipaddr() has already converted the IP address, ++ * we call getaddrinfo here to properly construct an addrinfo list ++ */ ++ memset (&hint, '\0', sizeof (hint)); ++ hint.ai_flags = 0; ++ hint.ai_family = AF_UNSPEC; ++ ++ ai = NULL; /* just to be on the safe side */ ++ ++ /* The following should not fail ... */ ++ if (getaddrinfo (tok, NULL, &hint, &ai) != 0) ++ { ++ return NO; ++ } ++ } + else +- /* NO, then check if it is only an addr */ +- if (isipaddr(tok, NULL, NULL) != YES) ++ { ++ /* ++ * It is either an IP address or a hostname. ++ * Let getaddrinfo sort everything out ++ */ ++ memset (&hint, '\0', sizeof (hint)); ++ hint.ai_flags = 0; ++ hint.ai_family = AF_UNSPEC; ++ ++ ai = NULL; /* just to be on the safe side */ ++ ++ if (getaddrinfo (string, NULL, &hint, &ai) != 0) + { ++ pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", string); ++ + return NO; + } ++ netmask_ptr = NULL; ++ } + + if (isipaddr(string, NULL, NULL) != YES) + { + /* Assume network/netmask with a name of a host. */ +- struct addrinfo hint; +- + memset (&hint, '\0', sizeof (hint)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = AF_UNSPEC; +@@ -764,27 +796,52 @@ network_netmask_match (pam_handle_t *pam + else + { + struct addrinfo *runp = item->res; ++ struct addrinfo *runp1; + + while (runp != NULL) + { + char buf[INET6_ADDRSTRLEN]; + +- inet_ntop (runp->ai_family, +- runp->ai_family == AF_INET +- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr +- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, +- buf, sizeof (buf)); ++ (void) getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST); + +- if (are_addresses_equal(buf, tok, netmask_ptr)) ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) + { +- return YES; ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ if (runp->ai_family != runp1->ai_family) ++ continue; ++ ++ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); ++ ++ if (are_addresses_equal (buf, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } + } + runp = runp->ai_next; + } + } + } + else +- return (are_addresses_equal(string, tok, netmask_ptr)); ++ { ++ struct addrinfo *runp1; ++ ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) ++ { ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); ++ ++ if (are_addresses_equal(string, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } ++ } ++ } ++ ++ freeaddrinfo(ai); + + return NO; + } diff --git a/pam-pam_cracklib-add-usersubstr.patch b/pam-pam_cracklib-add-usersubstr.patch new file mode 100644 index 0000000..b74fc21 --- /dev/null +++ b/pam-pam_cracklib-add-usersubstr.patch @@ -0,0 +1,209 @@ +Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.c ++++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.c +@@ -106,6 +106,7 @@ struct cracklib_options { + int reject_user; + int gecos_check; + int enforce_for_root; ++ int user_substr; + const char *cracklib_dictpath; + }; + +@@ -118,6 +119,15 @@ struct cracklib_options { + #define CO_LOW_CREDIT 1 + #define CO_OTH_CREDIT 1 + #define CO_MIN_WORD_LENGTH 4 ++#define CO_MIN_WORD_LENGTH 4 ++ ++static inline const char * ++pam_str_skip_prefix(const char *str, const char *prefix) ++{ ++ size_t prefix_len = strlen(prefix); ++ ++ return strncmp(str, prefix, prefix_len) ? NULL : str + prefix_len; ++} + + static int + _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, +@@ -127,6 +137,7 @@ _pam_parse (pam_handle_t *pamh, struct c + + /* step through arguments */ + for (ctrl=0; argc-- > 0; ++argv) { ++ const char *str; + char *ep = NULL; + + /* generic options */ +@@ -202,6 +213,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); + } +@@ -542,13 +557,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) +Index: Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/Linux-PAM_SAG.txt ++++ Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +@@ -990,6 +990,14 @@ reject_username + 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. + ++usersubstr=N ++ ++ Reject passwords which contain any substring of N or more consecutive ++ characters of the user's name straight or in reverse order. ++ N must be at least 4 for this to be applicable. ++ Also, usernames shorter than N are not checked. ++ If such a substring is found, the password is rejected. ++ + gecoscheck + + Check whether the words from the GECOS field (usualy full name of the user) +Index: Linux-PAM-1.3.0/doc/sag/html/sag-pam_cracklib.html +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/html/sag-pam_cracklib.html ++++ Linux-PAM-1.3.0/doc/sag/html/sag-pam_cracklib.html +@@ -197,6 +197,15 @@ + 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. ++

++ usersubstr=N ++

++ Reject passwords which contain any substring of N or more ++ consecutive characters of the user's name straight or in ++ reverse order. ++ N must be at least 4 for this to be applicable. ++ Also, usernames shorter than N are not checked. ++ If such a substring is found, the password is rejected. +

+ gecoscheck +

+Index: Linux-PAM-1.3.0/modules/pam_cracklib/README +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/README ++++ Linux-PAM-1.3.0/modules/pam_cracklib/README +@@ -179,6 +179,14 @@ reject_username + 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. + ++usersubstr=N ++ ++ Reject passwords which contain any substring of N or more consecutive ++ characters of the user's name straight or in reverse order. ++ N must be at least 4 for this to be applicable. ++ Also, usernames shorter than N are not checked. ++ If such a substring is found, the password is rejected. ++ + gecoscheck + + Check whether the words from the GECOS field (usualy full name of the user) +Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8 +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.8 ++++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8 +@@ -232,6 +232,15 @@ Reject passwords which contain more than + 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\&. + .RE + .PP ++\fBusersubstr=\fR\fB\fIN\fR\fR ++.RS 4 ++Reject passwords which contain any substring of N or more consecutive characters of the user\*(Aqs name straight or in ++reverse order\&. ++N must be at least 4 for this to be applicable\&. ++Also, usernames shorter than N are not checked\&. ++If such a substring is found, the password is rejected\&. ++.RE ++.PP + \fBgecoscheck\fR + .RS 4 + Check whether the words from the GECOS field (usualy 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\&. +Index: Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8.xml +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_cracklib/pam_cracklib.8.xml ++++ Linux-PAM-1.3.0/modules/pam_cracklib/pam_cracklib.8.xml +@@ -396,6 +396,21 @@ + + + ++ ++ ++ ++ ++ ++ ++ Reject passwords which contain any substring of N or more ++ consecutive characters of the user's name straight or in ++ reverse order. N must be at least 4 for this to be applicable. ++ Also, usernames shorter than N are not checked. ++ If such a substring is found, the password is rejected. ++ ++ ++ ++ + + + diff --git a/pam-ped1712-pam_motd-directory-feature.patch b/pam-ped1712-pam_motd-directory-feature.patch new file mode 100644 index 0000000..b80d791 --- /dev/null +++ b/pam-ped1712-pam_motd-directory-feature.patch @@ -0,0 +1,1043 @@ +Index: Linux-PAM-1.3.0/modules/pam_motd/pam_motd.8.xml +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_motd/pam_motd.8.xml ++++ Linux-PAM-1.3.0/modules/pam_motd/pam_motd.8.xml +@@ -21,6 +21,9 @@ + + motd=/path/filename + ++ ++ motd_dir=/path/dirname.d ++ + + + +@@ -31,10 +34,55 @@ + + pam_motd is a PAM module that can be used to display + arbitrary motd (message of the day) files after a successful +- login. By default the /etc/motd file is +- shown. The message size is limited to 64KB. ++ login. By default, pam_motd shows files in the ++ following locations: ++ ++ ++ ++ /etc/motd ++ /run/motd ++ /usr/lib/motd ++ /etc/motd.d/ ++ /run/motd.d/ ++ /usr/lib/motd.d/ ++ ++ ++ ++ Each message size is limited to 64KB. ++ ++ ++ If /etc/motd does not exist, ++ then /run/motd is shown. If ++ /run/motd does not exist, then ++ /usr/lib/motd is shown. ++ ++ ++ Similar overriding behavior applies to the directories. ++ Files in /etc/motd.d/ override files ++ with the same name in /run/motd.d/ and ++ /usr/lib/motd.d/. Files in /run/motd.d/ ++ override files with the same name in /usr/lib/motd.d/. ++ ++ ++ Files in the directories listed above are displayed in lexicographic ++ order by name. Moreover, the files are filtered by reading them with the ++ credentials of the target user authenticating on the system. ++ ++ ++ To silence a message, ++ a symbolic link with target /dev/null ++ may be placed in /etc/motd.d with ++ the same filename as the message to be silenced. Example: ++ Creating a symbolic link as follows silences /usr/lib/motd.d/my_motd. ++ ++ ++ ln -s /dev/null /etc/motd.d/my_motd ++ ++ ++ The MOTD_SHOWN=pam environment variable ++ is set after showing the motd files, even when all of them were silenced ++ using symbolic links. + +- + + + +@@ -47,12 +95,32 @@ + + + +- The /path/filename file is displayed +- as message of the day. ++ The /path/filename file is displayed ++ as message of the day. Multiple paths to try can be ++ specified as a colon-separated list. By default this option ++ is set to /etc/motd:/run/motd:/usr/lib/motd. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The /path/dirname.d directory is scanned ++ and each file contained inside of it is displayed. Multiple ++ directories to scan can be specified as a colon-separated list. ++ By default this option is set to /etc/motd.d:/run/motd.d:/usr/lib/motd.d. + + + + ++ ++ When no options are given, the default behavior applies for both ++ options. Specifying either option (or both) will disable the ++ default behavior for both options. ++ + + + +@@ -66,10 +134,26 @@ + RETURN VALUES + + ++ PAM_ABORT ++ ++ ++ Not all relevant data or options could be obtained. ++ ++ ++ ++ ++ PAM_BUF_ERR ++ ++ ++ Memory buffer error. ++ ++ ++ ++ + PAM_IGNORE + + +- This is the only return value of this module. ++ This is the default return value of this module. + + + +@@ -81,7 +165,20 @@ + + The suggested usage for /etc/pam.d/login is: + +-session optional pam_motd.so motd=/etc/motd ++session optional pam_motd.so ++ ++ ++ ++ To use a motd file from a different location: ++ ++session optional pam_motd.so motd=/elsewhere/motd ++ ++ ++ ++ To use a motd file from elsewhere, along with a ++ corresponding .d directory: ++ ++session optional pam_motd.so motd=/elsewhere/motd motd_dir=/elsewhere/motd.d + + + +@@ -109,6 +206,10 @@ session optional pam_motd.so motd=/et + + pam_motd was written by Ben Collins <bcollins@debian.org>. + ++ ++ The option was added by ++ Allison Karlitskaya <allison.karlitskaya@redhat.com>. ++ + + + +Index: Linux-PAM-1.3.0/modules/pam_motd/pam_motd.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_motd/pam_motd.c ++++ Linux-PAM-1.3.0/modules/pam_motd/pam_motd.c +@@ -1,13 +1,8 @@ +-/* pam_motd module */ +- + /* +- * Modified for pam_motd by Ben Collins +- * +- * Based off of: +- * $Id$ ++ * pam_motd module + * ++ * Modified for pam_motd by Ben Collins + * Written by Michael K. Johnson 1996/10/24 +- * + */ + + #include "config.h" +@@ -17,25 +12,21 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + + #include + #include +-/* +- * here, we make a definition for the externally accessible function +- * in this file (this definition is required for static a module +- * but strongly encouraged generally) it is used to instruct the +- * modules include file to define the function prototypes. +- */ +- +-#define PAM_SM_SESSION +-#define DEFAULT_MOTD "/etc/motd" +- + #include + #include ++#include "pam_inline.h" ++ ++#define DEFAULT_MOTD "/etc/motd:/run/motd:/usr/lib/motd" ++#define DEFAULT_MOTD_D "/etc/motd.d:/run/motd.d:/usr/lib/motd.d" + + /* --- session management functions (only) --- */ + +@@ -46,24 +37,371 @@ pam_sm_close_session (pam_handle_t *pamh + return PAM_IGNORE; + } + +-static char default_motd[] = DEFAULT_MOTD; ++static const char default_motd[] = DEFAULT_MOTD; ++static const char default_motd_dir[] = DEFAULT_MOTD_D; ++ ++static void try_to_display_fd(pam_handle_t *pamh, int fd) ++{ ++ struct stat st; ++ char *mtmp = NULL; ++ ++ /* fill in message buffer with contents of motd */ ++ if ((fstat(fd, &st) < 0) || !st.st_size || st.st_size > 0x10000) ++ return; ++ ++ if (!(mtmp = malloc(st.st_size+1))) ++ return; ++ ++ if (pam_modutil_read(fd, mtmp, st.st_size) == st.st_size) { ++ if (mtmp[st.st_size-1] == '\n') ++ mtmp[st.st_size-1] = '\0'; ++ else ++ mtmp[st.st_size] = '\0'; ++ ++ pam_info (pamh, "%s", mtmp); ++ } ++ ++ _pam_drop(mtmp); ++} ++ ++/* ++ * Split a DELIM-separated string ARG into an array. ++ * Outputs a newly allocated array of strings OUT_ARG_SPLIT ++ * and the number of strings OUT_NUM_STRS. ++ * Returns 0 in case of error, 1 in case of success. ++ */ ++static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim, ++ char ***out_arg_split, unsigned int *out_num_strs) ++{ ++ char *arg_extracted = NULL; ++ const char *arg_ptr = arg; ++ char **arg_split = NULL; ++ char delim_str[2]; ++ unsigned int i = 0; ++ unsigned int num_strs = 0; ++ int retval = 0; ++ ++ delim_str[0] = delim; ++ delim_str[1] = '\0'; ++ ++ if (arg == NULL) { ++ goto out; ++ } ++ ++ while (arg_ptr != NULL) { ++ num_strs++; ++ arg_ptr = strchr(arg_ptr + sizeof(const char), delim); ++ } ++ ++ arg_split = calloc(num_strs, sizeof(*arg_split)); ++ if (arg_split == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "failed to allocate string array"); ++ goto out; ++ } ++ ++ arg_extracted = strtok_r(arg, delim_str, &arg); ++ while (arg_extracted != NULL && i < num_strs) { ++ arg_split[i++] = arg_extracted; ++ arg_extracted = strtok_r(NULL, delim_str, &arg); ++ } ++ ++ retval = 1; ++ ++ out: ++ *out_num_strs = num_strs; ++ *out_arg_split = arg_split; ++ ++ return retval; ++} ++ ++/* Join A_STR and B_STR, inserting a "/" between them if one is not already trailing ++ * in A_STR or beginning B_STR. A pointer to a newly allocated string holding the ++ * joined string is returned in STRP_OUT. ++ * Returns -1 in case of error, or the number of bytes in the joined string in ++ * case of success. */ ++static int join_dir_strings(char **strp_out, const char *a_str, const char *b_str) ++{ ++ int has_sep = 0; ++ int retval = -1; ++ char *join_strp = NULL; ++ ++ if (strp_out == NULL || a_str == NULL || b_str == NULL) { ++ goto out; ++ } ++ if (strlen(a_str) == 0) { ++ goto out; ++ } ++ ++ has_sep = (a_str[strlen(a_str) - 1] == '/') || (b_str[0] == '/'); ++ ++ retval = asprintf(&join_strp, "%s%s%s", a_str, ++ (has_sep == 1) ? "" : "/", b_str); ++ ++ if (retval < 0) { ++ goto out; ++ } ++ ++ *strp_out = join_strp; ++ ++ out: ++ return retval; ++} ++ ++static int compare_strings(const void *a, const void *b) ++{ ++ const char *a_str = *(const char * const *)a; ++ const char *b_str = *(const char * const *)b; ++ ++ if (a_str == NULL && b_str == NULL) { ++ return 0; ++ } ++ else if (a_str == NULL) { ++ return -1; ++ } ++ else if (b_str == NULL) { ++ return 1; ++ } ++ else { ++ return strcmp(a_str, b_str); ++ } ++} ++ ++static void try_to_display_directories_with_overrides(pam_handle_t *pamh, ++ char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing) ++{ ++ struct dirent ***dirscans = NULL; ++ unsigned int *dirscans_sizes = NULL; ++ unsigned int dirscans_size_total = 0; ++ char **dirnames_all = NULL; ++ unsigned int i; ++ int i_dirnames = 0; ++ ++ if (pamh == NULL || motd_dir_path_split == NULL) { ++ goto out; ++ } ++ if (num_motd_dirs < 1) { ++ goto out; ++ } ++ ++ if ((dirscans = calloc(num_motd_dirs, sizeof(*dirscans))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "failed to allocate dirent arrays"); ++ goto out; ++ } ++ if ((dirscans_sizes = calloc(num_motd_dirs, sizeof(*dirscans_sizes))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "failed to allocate dirent array sizes"); ++ goto out; ++ } ++ ++ for (i = 0; i < num_motd_dirs; i++) { ++ int rv; ++ rv = scandir(motd_dir_path_split[i], &(dirscans[i]), NULL, NULL); ++ if (rv < 0) { ++ if (errno != ENOENT || report_missing) { ++ pam_syslog(pamh, LOG_ERR, "error scanning directory %s: %m", ++ motd_dir_path_split[i]); ++ } ++ } else { ++ dirscans_sizes[i] = rv; ++ } ++ dirscans_size_total += dirscans_sizes[i]; ++ } ++ ++ if (dirscans_size_total == 0) ++ goto out; ++ ++ /* filter out unwanted names, directories, and complement data with lstat() */ ++ for (i = 0; i < num_motd_dirs; i++) { ++ struct dirent **d = dirscans[i]; ++ for (unsigned int j = 0; j < dirscans_sizes[i]; j++) { ++ int rc; ++ char *fullpath; ++ struct stat s; ++ ++ switch(d[j]->d_type) { /* the filetype determines how to proceed */ ++ case DT_REG: /* regular files and */ ++ case DT_LNK: /* symlinks */ ++ continue; /* are good. */ ++ case DT_UNKNOWN: /* for file systems that do not provide */ ++ /* a filetype, we use lstat() */ ++ if (join_dir_strings(&fullpath, motd_dir_path_split[i], ++ d[j]->d_name) <= 0) ++ break; ++ rc = lstat(fullpath, &s); ++ _pam_drop(fullpath); /* free the memory alloc'ed by join_dir_strings */ ++ if (rc != 0) /* if the lstat() somehow failed */ ++ break; ++ ++ if (S_ISREG(s.st_mode) || /* regular files and */ ++ S_ISLNK(s.st_mode)) continue; /* symlinks are good */ ++ break; ++ case DT_DIR: /* We don't want directories */ ++ default: /* nor anything else */ ++ break; ++ } ++ _pam_drop(d[j]); /* free memory */ ++ d[j] = NULL; /* indicate this one was dropped */ ++ dirscans_size_total--; ++ } ++ } ++ ++ /* Allocate space for all file names found in the directories, including duplicates. */ ++ if ((dirnames_all = calloc(dirscans_size_total, sizeof(*dirnames_all))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "failed to allocate dirname array"); ++ goto out; ++ } ++ ++ for (i = 0; i < num_motd_dirs; i++) { ++ unsigned int j; ++ ++ for (j = 0; j < dirscans_sizes[i]; j++) { ++ if (NULL != dirscans[i][j]) { ++ dirnames_all[i_dirnames] = dirscans[i][j]->d_name; ++ i_dirnames++; ++ } ++ } ++ } ++ ++ qsort(dirnames_all, dirscans_size_total, ++ sizeof(const char *), compare_strings); ++ ++ for (i = 0; i < dirscans_size_total; i++) { ++ unsigned int j; ++ ++ if (dirnames_all[i] == NULL) { ++ continue; ++ } ++ ++ /* Skip duplicate file names. */ ++ if (i > 0 && strcmp(dirnames_all[i], dirnames_all[i - 1]) == 0) { ++ continue; ++ } ++ ++ for (j = 0; j < num_motd_dirs; j++) { ++ char *abs_path = NULL; ++ int fd; ++ ++ if (join_dir_strings(&abs_path, motd_dir_path_split[j], ++ dirnames_all[i]) < 0 || abs_path == NULL) { ++ continue; ++ } ++ ++ fd = open(abs_path, O_RDONLY, 0); ++ _pam_drop(abs_path); ++ ++ if (fd >= 0) { ++ try_to_display_fd(pamh, fd); ++ close(fd); ++ ++ /* We displayed a file, skip to the next file name. */ ++ break; ++ } ++ } ++ } ++ ++ out: ++ _pam_drop(dirnames_all); ++ if (dirscans_sizes != NULL) { ++ for (i = 0; i < num_motd_dirs; i++) { ++ unsigned int j; ++ ++ for (j = 0; j < dirscans_sizes[i]; j++) ++ _pam_drop(dirscans[i][j]); ++ _pam_drop(dirscans[i]); ++ } ++ _pam_drop(dirscans_sizes); ++ } ++ _pam_drop(dirscans); ++} ++ ++static int drop_privileges(pam_handle_t *pamh, struct pam_modutil_privs *privs) ++{ ++ struct passwd *pw; ++ const char *username; ++ int retval; ++ ++ retval = pam_get_user(pamh, &username, NULL); ++ ++ if (retval == PAM_SUCCESS) { ++ pw = pam_modutil_getpwnam (pamh, username); ++ } else { ++ return PAM_SESSION_ERR; ++ } ++ ++ if (pw == NULL || pam_modutil_drop_priv(pamh, privs, pw)) { ++ return PAM_SESSION_ERR; ++ } ++ ++ return PAM_SUCCESS; ++} ++ ++static int try_to_display(pam_handle_t *pamh, char **motd_path_split, ++ unsigned int num_motd_paths, ++ char **motd_dir_path_split, ++ unsigned int num_motd_dir_paths, int report_missing) ++{ ++ PAM_MODUTIL_DEF_PRIVS(privs); ++ ++ if (drop_privileges(pamh, &privs) != PAM_SUCCESS) { ++ pam_syslog(pamh, LOG_ERR, "Unable to drop privileges"); ++ return PAM_SESSION_ERR; ++ } ++ ++ if (motd_path_split != NULL) { ++ unsigned int i; ++ ++ for (i = 0; i < num_motd_paths; i++) { ++ int fd = open(motd_path_split[i], O_RDONLY, 0); ++ ++ if (fd >= 0) { ++ try_to_display_fd(pamh, fd); ++ close(fd); ++ ++ /* We found and displayed a file, ++ * move onto next filename. ++ */ ++ break; ++ } ++ } ++ } ++ ++ if (motd_dir_path_split != NULL) { ++ try_to_display_directories_with_overrides(pamh, ++ motd_dir_path_split, ++ num_motd_dir_paths, ++ report_missing); ++ } ++ ++ if (pam_modutil_regain_priv(pamh, &privs)) { ++ pam_syslog(pamh, LOG_ERR, "Unable to regain privileges"); ++ return PAM_SESSION_ERR; ++ } ++ ++ return PAM_SUCCESS; ++} + + int pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) + { + int retval = PAM_IGNORE; +- int fd; + const char *motd_path = NULL; +- char *mtmp = NULL; ++ char *motd_path_copy = NULL; ++ unsigned int num_motd_paths = 0; ++ char **motd_path_split = NULL; ++ const char *motd_dir_path = NULL; ++ char *motd_dir_path_copy = NULL; ++ unsigned int num_motd_dir_paths = 0; ++ char **motd_dir_path_split = NULL; ++ int report_missing; + + if (flags & PAM_SILENT) { + return retval; + } + + for (; argc-- > 0; ++argv) { +- if (!strncmp(*argv,"motd=",5)) { ++ const char *str; ++ if ((str = pam_str_skip_prefix(*argv, "motd=")) != NULL) { + +- motd_path = 5 + *argv; ++ motd_path = str; + if (*motd_path != '\0') { + D(("set motd path: %s", motd_path)); + } else { +@@ -72,41 +410,67 @@ int pam_sm_open_session(pam_handle_t *pa + "motd= specification missing argument - ignored"); + } + } ++ else if ((str = pam_str_skip_prefix(*argv, "motd_dir=")) != NULL) { ++ ++ motd_dir_path = str; ++ if (*motd_dir_path != '\0') { ++ D(("set motd.d path: %s", motd_dir_path)); ++ } else { ++ motd_dir_path = NULL; ++ pam_syslog(pamh, LOG_ERR, ++ "motd_dir= specification missing argument - ignored"); ++ } ++ } + else + pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); + } + +- if (motd_path == NULL) ++ if (motd_path == NULL && motd_dir_path == NULL) { + motd_path = default_motd; ++ motd_dir_path = default_motd_dir; ++ report_missing = 0; ++ } else { ++ report_missing = 1; ++ } + +- while ((fd = open(motd_path, O_RDONLY, 0)) >= 0) { +- struct stat st; +- +- /* fill in message buffer with contents of motd */ +- if ((fstat(fd, &st) < 0) || !st.st_size || st.st_size > 0x10000) +- break; +- +- if (!(mtmp = malloc(st.st_size+1))) +- break; +- +- if (pam_modutil_read(fd, mtmp, st.st_size) != st.st_size) +- break; +- +- if (mtmp[st.st_size-1] == '\n') +- mtmp[st.st_size-1] = '\0'; +- else +- mtmp[st.st_size] = '\0'; ++ if (motd_path != NULL) { ++ motd_path_copy = strdup(motd_path); ++ } + +- pam_info (pamh, "%s", mtmp); +- break; ++ if (motd_path_copy != NULL) { ++ if (pam_split_string(pamh, motd_path_copy, ':', ++ &motd_path_split, &num_motd_paths) == 0) { ++ goto out; ++ } + } + +- _pam_drop (mtmp); ++ if (motd_dir_path != NULL) { ++ motd_dir_path_copy = strdup(motd_dir_path); ++ } + +- if (fd >= 0) +- close(fd); ++ if (motd_dir_path_copy != NULL) { ++ if (pam_split_string(pamh, motd_dir_path_copy, ':', ++ &motd_dir_path_split, &num_motd_dir_paths) == 0) { ++ goto out; ++ } ++ } + +- return retval; ++ retval = try_to_display(pamh, motd_path_split, num_motd_paths, ++ motd_dir_path_split, num_motd_dir_paths, ++ report_missing); ++ ++ out: ++ _pam_drop(motd_path_copy); ++ _pam_drop(motd_path_split); ++ _pam_drop(motd_dir_path_copy); ++ _pam_drop(motd_dir_path_split); ++ ++ if (retval == PAM_SUCCESS) { ++ retval = pam_putenv(pamh, "MOTD_SHOWN=pam"); ++ return retval == PAM_SUCCESS ? PAM_IGNORE : retval; ++ } else { ++ return retval; ++ } + } + + /* end of module definition */ +Index: Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/Linux-PAM_SAG.txt ++++ Linux-PAM-1.3.0/doc/sag/Linux-PAM_SAG.txt +@@ -2938,13 +2938,38 @@ pam_mkhomedir was written by Jason Gunth + + 6.21. pam_motd - display the motd file + +-pam_motd.so [ motd=/path/filename ] ++pam_motd.so [ motd=/path/filename ] [ motd_dir=/path/dirname.d ] + + 6.21.1. DESCRIPTION + + pam_motd is a PAM module that can be used to display arbitrary motd (message of +-the day) files after a successful login. By default the /etc/motd file is +-shown. The message size is limited to 64KB. ++the day) files after a successful login. By default, pam_motd shows files in ++the following locations: ++ /etc/motd ++ /run/motd ++ /usr/lib/motd ++ /etc/motd.d/ ++ /run/motd.d/ ++ /usr/lib/motd.d/ ++Each message size is limited to 64KB. ++ ++Similar overriding behavior applies to the directories. ++Files in /etc/motd.d/ override files with the same name in ++/run/motd.d/ and /usr/lib/motd.d/. Files in /run/motd.d/ ++override files with the same name in /usr/lib/motd.d/. ++ ++Files in the directories listed above are displayed in lexicographic ++order by name. Moreover, the files are filtered by reading them with the ++credentials of the target user authenticating on the system. ++ ++To silence a message, ++a symbolic link with target /dev/null may be placed in /etc/motd.d with ++the same filename as the message to be silenced. Example: ++Creating a symbolic link as follows silences /usr/lib/motd.d/my_motd ++ ln -s /dev/null /etc/motd.d/my_motd ++ ++The MOTD_SWHOWN=pam environment variable is set after showing the ++motdfiles, even when all of them were silenced using symbolic links. + + 6.21.2. OPTIONS + +@@ -2952,6 +2977,10 @@ motd=/path/filename + + The /path/filename file is displayed as message of the day. + ++motd_dir=/path/dirname.d ++ ++ The files in /path/dirname.d directory are diplayed as message of the day. ++ + 6.21.3. MODULE TYPES PROVIDED + + Only the session module type is provided. +@@ -2966,7 +2995,7 @@ PAM_IGNORE + + The suggested usage for /etc/pam.d/login is: + +-session optional pam_motd.so motd=/etc/motd ++session optional pam_motd.so motd=/etc/motd motd_dir=/etc/motd.d + + + 6.21.6. AUTHOR +Index: Linux-PAM-1.3.0/doc/sag/html/sag-pam_motd.html +=================================================================== +--- Linux-PAM-1.3.0.orig/doc/sag/html/sag-pam_motd.html ++++ Linux-PAM-1.3.0/doc/sag/html/sag-pam_motd.html +@@ -3,13 +3,40 @@ + ]

6.21.1. DESCRIPTION

+ pam_motd is a PAM module that can be used to display + arbitrary motd (message of the day) files after a successful +- login. By default the /etc/motd file is +- shown. The message size is limited to 64KB. ++ login. ++

++ By default, pam_motd shows files in the followiing locations: ++

++ /etc/motd ++

++ /run/motd ++

++ /usr/lib/motd ++

++ /etc/motd.d/ ++

++ /run/motd.d ++

++ /usr/lib/motd.d ++

++ Each message size is limited to 64KB. ++

++ If /etc/motd does not exists, then /run/motd is shown, then /usr/lib/motd is shown. Similar overriding behavior applies to the directories. ++

++ Files in the directories listed above are displayed in lexicographic order by name. Moreover, the files are filtered by reading them with the credentials of the target user authenticating on the system ++

++ To silence a message, a symbolic link with target /dev/null may be placed in /etc/motd.d with the same filename as the message to be silenced. +

6.21.2. OPTIONS

+ motd=/path/filename +

+ The /path/filename file is displayed +- as message of the day. ++ as message of the day. Multiple paths to try can be specified as a colon-separated list. ++ By default this option is set to /etc/motd:/run/motd:/usr/lib/motd ++

++ motd_dir=/path/dirname.d ++

++ The /path/dirname.d directory is scanned and each file contained inside of it is displayed. Multiple directories to scan can be specified as a colon-separated list. ++ By default this option is set to etc/motd.d:/run/motd.d:/usr/lib/motd.d +

6.21.3. MODULE TYPES PROVIDED

+ Only the session module type is provided. +

6.21.4. RETURN VALUES

PAM_IGNORE

+@@ -17,7 +44,7 @@ +

6.21.5. EXAMPLES

+ The suggested usage for /etc/pam.d/login is: +

+-session  optional  pam_motd.so  motd=/etc/motd
++session  optional  pam_motd.so
+       

+

6.21.6. AUTHOR

+ pam_motd was written by Ben Collins <bcollins@debian.org>. +Index: Linux-PAM-1.3.0/modules/pam_motd/README +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_motd/README ++++ Linux-PAM-1.3.0/modules/pam_motd/README +@@ -4,21 +4,40 @@ pam_motd — Display the motd file + + DESCRIPTION + +-pam_motd is a PAM module that can be used to display arbitrary motd (message of +-the day) files after a successful login. By default the /etc/motd file is +-shown. The message size is limited to 64KB. ++pam_motd is a PAM module that can be used to display arbitrary motd (message of ++the day) files after a successful login. By default, pam_motd shows files in the ++following locations: /etc/motd, /run/motd, /usr/lib/motd, /etc/motd.d, /run/motd.d/, ++/usr/lib/motd.d. Each message size is limited to 64KB. ++ ++If /etc/motd does not exist, then /run/motd is shown. If /run/motd does not exist, then ++/usr/lib/motd is shown. Similar overriding behavior applies to the directories. ++ ++Files in the directories listed above are displayed in lexicographic ++order by name. Moreover, the files are filtered by reading them with the ++credentials of the target user authenticating on the system. ++ ++To silence a message, a symbolic link with target /dev/null may be placed ++in /etc/motd.d with the same filename as the message to be silenced. + + OPTIONS + + motd=/path/filename + + The /path/filename file is displayed as message of the day. ++ Multiple paths to try can be specified as a colon-separated list. By default this option ++ is set to /etc/motd:/run/motd:/usr/lib/motd. ++ ++motd_dir=/path/firname.d ++ ++ The /path/dirname.d directory is scanned and each file contained inside of it is displayed. ++ Multiple directories to scan can be specified as a colon-separated list. By default ++ this option is set to /etc/motd.d:/run/motd.d:/usr/lib/motd.d + + EXAMPLES + + The suggested usage for /etc/pam.d/login is: + +-session optional pam_motd.so motd=/etc/motd ++session optional pam_motd.so + + + AUTHOR +Index: Linux-PAM-1.3.0/modules/pam_motd/pam_motd.8 +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_motd/pam_motd.8 ++++ Linux-PAM-1.3.0/modules/pam_motd/pam_motd.8 +@@ -1,13 +1,13 @@ + '\" t + .\" Title: pam_motd + .\" Author: [see the "AUTHOR" section] +-.\" Generator: DocBook XSL Stylesheets v1.78.1 +-.\" Date: 04/01/2016 ++.\" Generator: DocBook XSL Stylesheets vsnapshot ++.\" Date: 09/07/2022 + .\" Manual: Linux-PAM Manual + .\" Source: Linux-PAM Manual + .\" Language: English + .\" +-.TH "PAM_MOTD" "8" "04/01/2016" "Linux-PAM Manual" "Linux\-PAM Manual" ++.TH "PAM_MOTD" "8" "09/07/2022" "Linux-PAM Manual" "Linux\-PAM Manual" + .\" ----------------------------------------------------------------- + .\" * Define some portability stuff + .\" ----------------------------------------------------------------- +@@ -31,20 +31,85 @@ + pam_motd \- Display the motd file + .SH "SYNOPSIS" + .HP \w'\fBpam_motd\&.so\fR\ 'u +-\fBpam_motd\&.so\fR [motd=\fI/path/filename\fR] ++\fBpam_motd\&.so\fR [motd=\fI/path/filename\fR] [motd_dir=\fI/path/dirname\&.d\fR] + .SH "DESCRIPTION" + .PP +-pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful login\&. By default the ++pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful login\&. By default, pam_motd shows files in the following locations: ++.PP ++.RS 4 + /etc/motd +-file is shown\&. The message size is limited to 64KB\&. ++.RE ++.RS 4 ++/run/motd ++.RE ++.RS 4 ++/usr/lib/motd ++.RE ++.RS 4 ++/etc/motd\&.d/ ++.RE ++.RS 4 ++/run/motd\&.d/ ++.RE ++.RS 4 ++/usr/lib/motd\&.d/ ++.RE ++.PP ++Each message size is limited to 64KB\&. ++.PP ++If ++/etc/motd ++does not exist, then ++/run/motd ++is shown\&. If ++/run/motd ++does not exist, then ++/usr/lib/motd ++is shown\&. ++.PP ++Similar overriding behavior applies to the directories\&. Files in ++/etc/motd\&.d/ ++override files with the same name in ++/run/motd\&.d/ ++and ++/usr/lib/motd\&.d/\&. Files in ++/run/motd\&.d/ ++override files with the same name in ++/usr/lib/motd\&.d/\&. ++.PP ++Files in the directories listed above are displayed in lexicographic order by name\&. Moreover, the files are filtered by reading them with the credentials of the target user authenticating on the system\&. ++.PP ++To silence a message, a symbolic link with target ++/dev/null ++may be placed in ++/etc/motd\&.d ++with the same filename as the message to be silenced\&. Example: Creating a symbolic link as follows silences ++/usr/lib/motd\&.d/my_motd\&. ++.PP ++\fBln \-s /dev/null /etc/motd\&.d/my_motd\fR ++.PP ++The ++\fBMOTD_SHOWN=pam\fR ++environment variable is set after showing the motd files, even when all of them were silenced using symbolic links\&. + .SH "OPTIONS" + .PP + \fBmotd=\fR\fB\fI/path/filename\fR\fR + .RS 4 + The + /path/filename +-file is displayed as message of the day\&. ++file is displayed as message of the day\&. Multiple paths to try can be specified as a colon\-separated list\&. By default this option is set to ++/etc/motd:/run/motd:/usr/lib/motd\&. + .RE ++.PP ++\fBmotd_dir=\fR\fB\fI/path/dirname\&.d\fR\fR ++.RS 4 ++The ++/path/dirname\&.d ++directory is scanned and each file contained inside of it is displayed\&. Multiple directories to scan can be specified as a colon\-separated list\&. By default this option is set to ++/etc/motd\&.d:/run/motd\&.d:/usr/lib/motd\&.d\&. ++.RE ++.PP ++When no options are given, the default behavior applies for both options\&. Specifying either option (or both) will disable the default behavior for both options\&. + .SH "MODULE TYPES PROVIDED" + .PP + Only the +@@ -52,9 +117,19 @@ Only the + module type is provided\&. + .SH "RETURN VALUES" + .PP ++PAM_ABORT ++.RS 4 ++Not all relevant data or options could be obtained\&. ++.RE ++.PP ++PAM_BUF_ERR ++.RS 4 ++Memory buffer error\&. ++.RE ++.PP + PAM_IGNORE + .RS 4 +-This is the only return value of this module\&. ++This is the default return value of this module\&. + .RE + .SH "EXAMPLES" + .PP +@@ -66,7 +141,39 @@ is: + .RS 4 + .\} + .nf +-session optional pam_motd\&.so motd=/etc/motd ++session optional pam_motd\&.so ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.PP ++To use a ++motd ++file from a different location: ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++session optional pam_motd\&.so motd=/elsewhere/motd ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.PP ++To use a ++motd ++file from elsewhere, along with a corresponding ++\&.d ++directory: ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++session optional pam_motd\&.so motd=/elsewhere/motd motd_dir=/elsewhere/motd\&.d + + .fi + .if n \{\ +@@ -82,3 +189,7 @@ session optional pam_motd\&.so motd=/ + .SH "AUTHOR" + .PP + pam_motd was written by Ben Collins \&. ++.PP ++The ++\fBmotd_dir=\fR ++option was added by Allison Karlitskaya \&. diff --git a/pam-sle20638-add-pam_faillock.patch b/pam-sle20638-add-pam_faillock.patch new file mode 100644 index 0000000..3119864 --- /dev/null +++ b/pam-sle20638-add-pam_faillock.patch @@ -0,0 +1,6797 @@ +Index: Linux-PAM-1.3.0/modules/pam_faillock/Makefile.am +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/Makefile.am +@@ -0,0 +1,48 @@ ++# ++# Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk ++# Copyright (c) 2008, 2018, 2020 Red Hat, Inc. ++# Copyright (c) 2010 Tomas Mraz ++# ++ ++CLEANFILES = *~ ++MAINTAINERCLEANFILES = $(MANS) README ++ ++EXTRA_DIST = $(XMLS) ++ ++dist_man_MANS = pam_faillock.8 faillock.8 faillock.conf.5 ++XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml ++ ++dist_check_SCRIPTS = tst-pam_faillock ++TESTS = $(dist_check_SCRIPTS) ++ ++securelibdir = $(SECUREDIR) ++secureconfdir = $(SCONFIGDIR) ++ ++noinst_HEADERS = faillock.h ++ ++AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ ++ $(WARN_CFLAGS) ++ ++faillock_CFLAGS = $(AM_CFLAGS) ++ ++pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module ++pam_faillock_la_LIBADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) ++if HAVE_VERSIONING ++ pam_faillock_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map ++endif ++ ++faillock_LDFLAGS = ++faillock_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) ++ ++dist_secureconf_DATA = faillock.conf ++ ++securelib_LTLIBRARIES = pam_faillock.la ++sbin_PROGRAMS = faillock ++ ++pam_faillock_la_SOURCES = pam_faillock.c faillock.c ++faillock_SOURCES = main.c faillock.c ++ ++if ENABLE_REGENERATE_MAN ++dist_noinst_DATA = README ++-include $(top_srcdir)/Make.xml.rules ++endif +Index: Linux-PAM-1.3.0/modules/pam_faillock/Makefile.in +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/Makefile.in +@@ -0,0 +1,1339 @@ ++# Makefile.in generated by automake 1.16.2 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994-2020 Free Software Foundation, Inc. ++ ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++# ++# Copyright (c) 2005, 2006, 2007, 2009 Thorsten Kukuk ++# Copyright (c) 2008, 2018, 2020 Red Hat, Inc. ++# Copyright (c) 2010 Tomas Mraz ++# ++ ++ ++ ++ ++VPATH = @srcdir@ ++am__is_gnu_make = { \ ++ if test -z '$(MAKELEVEL)'; then \ ++ false; \ ++ elif test -n '$(MAKE_HOST)'; then \ ++ true; \ ++ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ ++ true; \ ++ else \ ++ false; \ ++ fi; \ ++} ++am__make_running_with_option = \ ++ case $${target_option-} in \ ++ ?) ;; \ ++ *) echo "am__make_running_with_option: internal error: invalid" \ ++ "target option '$${target_option-}' specified" >&2; \ ++ exit 1;; \ ++ esac; \ ++ has_opt=no; \ ++ sane_makeflags=$$MAKEFLAGS; \ ++ if $(am__is_gnu_make); then \ ++ sane_makeflags=$$MFLAGS; \ ++ else \ ++ case $$MAKEFLAGS in \ ++ *\\[\ \ ]*) \ ++ bs=\\; \ ++ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ ++ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ ++ esac; \ ++ fi; \ ++ skip_next=no; \ ++ strip_trailopt () \ ++ { \ ++ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ ++ }; \ ++ for flg in $$sane_makeflags; do \ ++ test $$skip_next = yes && { skip_next=no; continue; }; \ ++ case $$flg in \ ++ *=*|--*) continue;; \ ++ -*I) strip_trailopt 'I'; skip_next=yes;; \ ++ -*I?*) strip_trailopt 'I';; \ ++ -*O) strip_trailopt 'O'; skip_next=yes;; \ ++ -*O?*) strip_trailopt 'O';; \ ++ -*l) strip_trailopt 'l'; skip_next=yes;; \ ++ -*l?*) strip_trailopt 'l';; \ ++ -[dEDm]) skip_next=yes;; \ ++ -[JT]) skip_next=yes;; \ ++ esac; \ ++ case $$flg in \ ++ *$$target_option*) has_opt=yes; break;; \ ++ esac; \ ++ done; \ ++ test $$has_opt = yes ++am__make_dryrun = (target_option=n; $(am__make_running_with_option)) ++am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map ++sbin_PROGRAMS = faillock$(EXEEXT) ++subdir = modules/pam_faillock ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ ++ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ ++ $(top_srcdir)/m4/intlmacosx.m4 \ ++ $(top_srcdir)/m4/jh_path_xml_catalog.m4 \ ++ $(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \ ++ $(top_srcdir)/m4/ld-no-undefined.m4 \ ++ $(top_srcdir)/m4/ld-z-now.m4 $(top_srcdir)/m4/lib-ld.m4 \ ++ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ ++ $(top_srcdir)/m4/libprelude.m4 $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ ++ $(top_srcdir)/m4/progtest.m4 \ ++ $(top_srcdir)/m4/warn_lang_flags.m4 \ ++ $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \ ++ $(am__dist_noinst_DATA_DIST) $(dist_secureconf_DATA) \ ++ $(noinst_HEADERS) $(am__DIST_COMMON) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(securelibdir)" \ ++ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \ ++ "$(DESTDIR)$(secureconfdir)" ++PROGRAMS = $(sbin_PROGRAMS) ++am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; ++am__vpath_adj = case $$p in \ ++ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ ++ *) f=$$p;; \ ++ esac; ++am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; ++am__install_max = 40 ++am__nobase_strip_setup = \ ++ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` ++am__nobase_strip = \ ++ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" ++am__nobase_list = $(am__nobase_strip_setup); \ ++ for p in $$list; do echo "$$p $$p"; done | \ ++ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ ++ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ ++ if (++n[$$2] == $(am__install_max)) \ ++ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ ++ END { for (dir in files) print dir, files[dir] }' ++am__base_list = \ ++ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ ++ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' ++am__uninstall_files_from_dir = { \ ++ test -z "$$files" \ ++ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ ++ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ ++ $(am__cd) "$$dir" && rm -f $$files; }; \ ++ } ++LTLIBRARIES = $(securelib_LTLIBRARIES) ++am__DEPENDENCIES_1 = ++pam_faillock_la_DEPENDENCIES = $(top_builddir)/libpam/libpam.la \ ++ $(am__DEPENDENCIES_1) ++am_pam_faillock_la_OBJECTS = pam_faillock.lo faillock.lo ++pam_faillock_la_OBJECTS = $(am_pam_faillock_la_OBJECTS) ++AM_V_lt = $(am__v_lt_@AM_V@) ++am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) ++am__v_lt_0 = --silent ++am__v_lt_1 = ++pam_faillock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(AM_CFLAGS) $(CFLAGS) $(pam_faillock_la_LDFLAGS) $(LDFLAGS) \ ++ -o $@ ++am_faillock_OBJECTS = faillock-main.$(OBJEXT) \ ++ faillock-faillock.$(OBJEXT) ++faillock_OBJECTS = $(am_faillock_OBJECTS) ++faillock_DEPENDENCIES = $(top_builddir)/libpam/libpam.la \ ++ $(am__DEPENDENCIES_1) ++faillock_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(faillock_CFLAGS) \ ++ $(CFLAGS) $(faillock_LDFLAGS) $(LDFLAGS) -o $@ ++AM_V_P = $(am__v_P_@AM_V@) ++am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) ++am__v_P_0 = false ++am__v_P_1 = : ++AM_V_GEN = $(am__v_GEN_@AM_V@) ++am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) ++am__v_GEN_0 = @echo " GEN " $@; ++am__v_GEN_1 = ++AM_V_at = $(am__v_at_@AM_V@) ++am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) ++am__v_at_0 = @ ++am__v_at_1 = ++DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) ++depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp ++am__maybe_remake_depfiles = depfiles ++am__depfiles_remade = ./$(DEPDIR)/faillock-faillock.Po \ ++ ./$(DEPDIR)/faillock-main.Po ./$(DEPDIR)/faillock.Plo \ ++ ./$(DEPDIR)/pam_faillock.Plo ++am__mv = mv -f ++COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ ++ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ ++ $(AM_CFLAGS) $(CFLAGS) ++AM_V_CC = $(am__v_CC_@AM_V@) ++am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) ++am__v_CC_0 = @echo " CC " $@; ++am__v_CC_1 = ++CCLD = $(CC) ++LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ ++ $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++AM_V_CCLD = $(am__v_CCLD_@AM_V@) ++am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) ++am__v_CCLD_0 = @echo " CCLD " $@; ++am__v_CCLD_1 = ++SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) ++DIST_SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) ++am__can_run_installinfo = \ ++ case $$AM_UPDATE_INFO_DIR in \ ++ n|no|NO) false;; \ ++ *) (install-info --version) >/dev/null 2>&1;; \ ++ esac ++man5dir = $(mandir)/man5 ++man8dir = $(mandir)/man8 ++NROFF = nroff ++MANS = $(dist_man_MANS) ++am__dist_noinst_DATA_DIST = README ++DATA = $(dist_noinst_DATA) $(dist_secureconf_DATA) ++HEADERS = $(noinst_HEADERS) ++am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) ++# Read a list of newline-separated strings from the standard input, ++# and print each of them once, without duplicates. Input order is ++# *not* preserved. ++am__uniquify_input = $(AWK) '\ ++ BEGIN { nonempty = 0; } \ ++ { items[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in items) print i; }; } \ ++' ++# Make sure the list of sources is unique. This is necessary because, ++# e.g., the same source file might be shared among _SOURCES variables ++# for different programs/libraries. ++am__define_uniq_tagged_files = \ ++ list='$(am__tagged_files)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | $(am__uniquify_input)` ++ETAGS = etags ++CTAGS = ctags ++am__tty_colors_dummy = \ ++ mgn= red= grn= lgn= blu= brg= std=; \ ++ am__color_tests=no ++am__tty_colors = { \ ++ $(am__tty_colors_dummy); \ ++ if test "X$(AM_COLOR_TESTS)" = Xno; then \ ++ am__color_tests=no; \ ++ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ ++ am__color_tests=yes; \ ++ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ ++ am__color_tests=yes; \ ++ fi; \ ++ if test $$am__color_tests = yes; then \ ++ red=''; \ ++ grn=''; \ ++ lgn=''; \ ++ blu=''; \ ++ mgn=''; \ ++ brg=''; \ ++ std=''; \ ++ fi; \ ++} ++am__recheck_rx = ^[ ]*:recheck:[ ]* ++am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* ++am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* ++# A command that, given a newline-separated list of test names on the ++# standard input, print the name of the tests that are to be re-run ++# upon "make recheck". ++am__list_recheck_tests = $(AWK) '{ \ ++ recheck = 1; \ ++ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ ++ { \ ++ if (rc < 0) \ ++ { \ ++ if ((getline line2 < ($$0 ".log")) < 0) \ ++ recheck = 0; \ ++ break; \ ++ } \ ++ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ ++ { \ ++ recheck = 0; \ ++ break; \ ++ } \ ++ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ ++ { \ ++ break; \ ++ } \ ++ }; \ ++ if (recheck) \ ++ print $$0; \ ++ close ($$0 ".trs"); \ ++ close ($$0 ".log"); \ ++}' ++# A command that, given a newline-separated list of test names on the ++# standard input, create the global log from their .trs and .log files. ++am__create_global_log = $(AWK) ' \ ++function fatal(msg) \ ++{ \ ++ print "fatal: making $@: " msg | "cat >&2"; \ ++ exit 1; \ ++} \ ++function rst_section(header) \ ++{ \ ++ print header; \ ++ len = length(header); \ ++ for (i = 1; i <= len; i = i + 1) \ ++ printf "="; \ ++ printf "\n\n"; \ ++} \ ++{ \ ++ copy_in_global_log = 1; \ ++ global_test_result = "RUN"; \ ++ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ ++ { \ ++ if (rc < 0) \ ++ fatal("failed to read from " $$0 ".trs"); \ ++ if (line ~ /$(am__global_test_result_rx)/) \ ++ { \ ++ sub("$(am__global_test_result_rx)", "", line); \ ++ sub("[ ]*$$", "", line); \ ++ global_test_result = line; \ ++ } \ ++ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ ++ copy_in_global_log = 0; \ ++ }; \ ++ if (copy_in_global_log) \ ++ { \ ++ rst_section(global_test_result ": " $$0); \ ++ while ((rc = (getline line < ($$0 ".log"))) != 0) \ ++ { \ ++ if (rc < 0) \ ++ fatal("failed to read from " $$0 ".log"); \ ++ print line; \ ++ }; \ ++ printf "\n"; \ ++ }; \ ++ close ($$0 ".trs"); \ ++ close ($$0 ".log"); \ ++}' ++# Restructured Text title. ++am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } ++# Solaris 10 'make', and several other traditional 'make' implementations, ++# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it ++# by disabling -e (using the XSI extension "set +e") if it's set. ++am__sh_e_setup = case $$- in *e*) set +e;; esac ++# Default flags passed to test drivers. ++am__common_driver_flags = \ ++ --color-tests "$$am__color_tests" \ ++ --enable-hard-errors "$$am__enable_hard_errors" \ ++ --expect-failure "$$am__expect_failure" ++# To be inserted before the command running the test. Creates the ++# directory for the log if needed. Stores in $dir the directory ++# containing $f, in $tst the test, in $log the log. Executes the ++# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and ++# passes TESTS_ENVIRONMENT. Set up options for the wrapper that ++# will run the test scripts (or their associated LOG_COMPILER, if ++# thy have one). ++am__check_pre = \ ++$(am__sh_e_setup); \ ++$(am__vpath_adj_setup) $(am__vpath_adj) \ ++$(am__tty_colors); \ ++srcdir=$(srcdir); export srcdir; \ ++case "$@" in \ ++ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ ++ *) am__odir=.;; \ ++esac; \ ++test "x$$am__odir" = x"." || test -d "$$am__odir" \ ++ || $(MKDIR_P) "$$am__odir" || exit $$?; \ ++if test -f "./$$f"; then dir=./; \ ++elif test -f "$$f"; then dir=; \ ++else dir="$(srcdir)/"; fi; \ ++tst=$$dir$$f; log='$@'; \ ++if test -n '$(DISABLE_HARD_ERRORS)'; then \ ++ am__enable_hard_errors=no; \ ++else \ ++ am__enable_hard_errors=yes; \ ++fi; \ ++case " $(XFAIL_TESTS) " in \ ++ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ ++ am__expect_failure=yes;; \ ++ *) \ ++ am__expect_failure=no;; \ ++esac; \ ++$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) ++# A shell command to get the names of the tests scripts with any registered ++# extension removed (i.e., equivalently, the names of the test logs, with ++# the '.log' extension removed). The result is saved in the shell variable ++# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, ++# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", ++# since that might cause problem with VPATH rewrites for suffix-less tests. ++# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. ++am__set_TESTS_bases = \ ++ bases='$(TEST_LOGS)'; \ ++ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ ++ bases=`echo $$bases` ++AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' ++RECHECK_LOGS = $(TEST_LOGS) ++AM_RECURSIVE_TARGETS = check recheck ++TEST_SUITE_LOG = test-suite.log ++TEST_EXTENSIONS = @EXEEXT@ .test ++LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver ++LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) ++am__set_b = \ ++ case '$@' in \ ++ */*) \ ++ case '$*' in \ ++ */*) b='$*';; \ ++ *) b=`echo '$@' | sed 's/\.log$$//'`; \ ++ esac;; \ ++ *) \ ++ b='$*';; \ ++ esac ++am__test_logs1 = $(TESTS:=.log) ++am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) ++TEST_LOGS = $(am__test_logs2:.test.log=.log) ++TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver ++TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ ++ $(TEST_LOG_FLAGS) ++am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ ++ $(top_srcdir)/build-aux/depcomp \ ++ $(top_srcdir)/build-aux/test-driver ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = @ACLOCAL@ ++AMTAR = @AMTAR@ ++AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ++AR = @AR@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++BROWSER = @BROWSER@ ++BUILD_CFLAGS = @BUILD_CFLAGS@ ++BUILD_CPPFLAGS = @BUILD_CPPFLAGS@ ++BUILD_LDFLAGS = @BUILD_LDFLAGS@ ++CC = @CC@ ++CCDEPMODE = @CCDEPMODE@ ++CC_FOR_BUILD = @CC_FOR_BUILD@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEFS = @DEFS@ ++DEPDIR = @DEPDIR@ ++DLLTOOL = @DLLTOOL@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++ECONF_CFLAGS = @ECONF_CFLAGS@ ++ECONF_LIBS = @ECONF_LIBS@ ++EGREP = @EGREP@ ++EXEEXT = @EXEEXT@ ++EXE_CFLAGS = ++EXE_LDFLAGS = ++FGREP = @FGREP@ ++FO2PDF = @FO2PDF@ ++GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ ++GMSGFMT = @GMSGFMT@ ++GMSGFMT_015 = @GMSGFMT_015@ ++GREP = @GREP@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++INTLLIBS = @INTLLIBS@ ++INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LEX = @LEX@ ++LEXLIB = @LEXLIB@ ++LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ ++LIBAUDIT = @LIBAUDIT@ ++LIBCRYPT = @LIBCRYPT@ ++LIBDB = @LIBDB@ ++LIBDL = @LIBDL@ ++LIBICONV = @LIBICONV@ ++LIBINTL = @LIBINTL@ ++LIBOBJS = @LIBOBJS@ ++LIBPRELUDE_CFLAGS = @LIBPRELUDE_CFLAGS@ ++LIBPRELUDE_CONFIG = @LIBPRELUDE_CONFIG@ ++LIBPRELUDE_CONFIG_PREFIX = @LIBPRELUDE_CONFIG_PREFIX@ ++LIBPRELUDE_LDFLAGS = @LIBPRELUDE_LDFLAGS@ ++LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@ ++LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@ ++LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@ ++LIBS = @LIBS@ ++LIBSELINUX = @LIBSELINUX@ ++LIBTOOL = @LIBTOOL@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBICONV = @LTLIBICONV@ ++LTLIBINTL = @LTLIBINTL@ ++LTLIBOBJS = @LTLIBOBJS@ ++LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ ++MAKEINFO = @MAKEINFO@ ++MANIFEST_TOOL = @MANIFEST_TOOL@ ++MKDIR_P = @MKDIR_P@ ++MSGFMT = @MSGFMT@ ++MSGFMT_015 = @MSGFMT_015@ ++MSGMERGE = @MSGMERGE@ ++NIS_CFLAGS = @NIS_CFLAGS@ ++NIS_LIBS = @NIS_LIBS@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++NSL_CFLAGS = @NSL_CFLAGS@ ++NSL_LIBS = @NSL_LIBS@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PKG_CONFIG = @PKG_CONFIG@ ++PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ ++PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ ++POSUB = @POSUB@ ++RANLIB = @RANLIB@ ++SCONFIGDIR = @SCONFIGDIR@ ++SECUREDIR = @SECUREDIR@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SHELL = @SHELL@ ++STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@ ++STRIP = @STRIP@ ++TIRPC_CFLAGS = @TIRPC_CFLAGS@ ++TIRPC_LIBS = @TIRPC_LIBS@ ++USE_NLS = @USE_NLS@ ++VERSION = @VERSION@ ++WARN_CFLAGS = ++XGETTEXT = @XGETTEXT@ ++XGETTEXT_015 = @XGETTEXT_015@ ++XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ ++XMLCATALOG = @XMLCATALOG@ ++XMLLINT = @XMLLINT@ ++XML_CATALOG_FILE = @XML_CATALOG_FILE@ ++XSLTPROC = @XSLTPROC@ ++YACC = @YACC@ ++YFLAGS = @YFLAGS@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_AR = @ac_ct_AR@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pam_xauth_path = @pam_xauth_path@ ++pdfdir = @pdfdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++CLEANFILES = *~ ++MAINTAINERCLEANFILES = $(MANS) README ++EXTRA_DIST = $(XMLS) ++dist_man_MANS = pam_faillock.8 faillock.8 faillock.conf.5 ++XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml ++dist_check_SCRIPTS = tst-pam_faillock ++TESTS = $(dist_check_SCRIPTS) ++securelibdir = $(SECUREDIR) ++secureconfdir = $(SCONFIGDIR) ++noinst_HEADERS = faillock.h ++AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ ++ $(WARN_CFLAGS) ++ ++faillock_CFLAGS = $(AM_CFLAGS) ++pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module \ ++ $(am__append_1) ++pam_faillock_la_LIBADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) ++faillock_LDFLAGS = ++faillock_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) ++dist_secureconf_DATA = faillock.conf ++securelib_LTLIBRARIES = pam_faillock.la ++pam_faillock_la_SOURCES = pam_faillock.c faillock.c ++faillock_SOURCES = main.c faillock.c ++@ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README ++all: all-am ++ ++.SUFFIXES: ++.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/pam_faillock/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --gnu modules/pam_faillock/Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++install-sbinPROGRAMS: $(sbin_PROGRAMS) ++ @$(NORMAL_INSTALL) ++ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ ++ if test -n "$$list"; then \ ++ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ ++ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ ++ fi; \ ++ for p in $$list; do echo "$$p $$p"; done | \ ++ sed 's/$(EXEEXT)$$//' | \ ++ while read p p1; do if test -f $$p \ ++ || test -f $$p1 \ ++ ; then echo "$$p"; echo "$$p"; else :; fi; \ ++ done | \ ++ sed -e 'p;s,.*/,,;n;h' \ ++ -e 's|.*|.|' \ ++ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ ++ sed 'N;N;N;s,\n, ,g' | \ ++ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ ++ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ ++ if ($$2 == $$4) files[d] = files[d] " " $$1; \ ++ else { print "f", $$3 "/" $$4, $$1; } } \ ++ END { for (d in files) print "f", d, files[d] }' | \ ++ while read type dir files; do \ ++ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ ++ test -z "$$files" || { \ ++ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ ++ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ ++ } \ ++ ; done ++ ++uninstall-sbinPROGRAMS: ++ @$(NORMAL_UNINSTALL) ++ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ ++ files=`for p in $$list; do echo "$$p"; done | \ ++ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ ++ -e 's/$$/$(EXEEXT)/' \ ++ `; \ ++ test -n "$$list" || exit 0; \ ++ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ ++ cd "$(DESTDIR)$(sbindir)" && rm -f $$files ++ ++clean-sbinPROGRAMS: ++ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ ++ echo " rm -f" $$list; \ ++ rm -f $$list || exit $$?; \ ++ test -n "$(EXEEXT)" || exit 0; \ ++ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ ++ echo " rm -f" $$list; \ ++ rm -f $$list ++ ++install-securelibLTLIBRARIES: $(securelib_LTLIBRARIES) ++ @$(NORMAL_INSTALL) ++ @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \ ++ list2=; for p in $$list; do \ ++ if test -f $$p; then \ ++ list2="$$list2 $$p"; \ ++ else :; fi; \ ++ done; \ ++ test -z "$$list2" || { \ ++ echo " $(MKDIR_P) '$(DESTDIR)$(securelibdir)'"; \ ++ $(MKDIR_P) "$(DESTDIR)$(securelibdir)" || exit 1; \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(securelibdir)'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(securelibdir)"; \ ++ } ++ ++uninstall-securelibLTLIBRARIES: ++ @$(NORMAL_UNINSTALL) ++ @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \ ++ for p in $$list; do \ ++ $(am__strip_dir) \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(securelibdir)/$$f'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(securelibdir)/$$f"; \ ++ done ++ ++clean-securelibLTLIBRARIES: ++ -test -z "$(securelib_LTLIBRARIES)" || rm -f $(securelib_LTLIBRARIES) ++ @list='$(securelib_LTLIBRARIES)'; \ ++ locs=`for p in $$list; do echo $$p; done | \ ++ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ ++ sort -u`; \ ++ test -z "$$locs" || { \ ++ echo rm -f $${locs}; \ ++ rm -f $${locs}; \ ++ } ++ ++pam_faillock.la: $(pam_faillock_la_OBJECTS) $(pam_faillock_la_DEPENDENCIES) $(EXTRA_pam_faillock_la_DEPENDENCIES) ++ $(AM_V_CCLD)$(pam_faillock_la_LINK) -rpath $(securelibdir) $(pam_faillock_la_OBJECTS) $(pam_faillock_la_LIBADD) $(LIBS) ++ ++faillock$(EXEEXT): $(faillock_OBJECTS) $(faillock_DEPENDENCIES) $(EXTRA_faillock_DEPENDENCIES) ++ @rm -f faillock$(EXEEXT) ++ $(AM_V_CCLD)$(faillock_LINK) $(faillock_OBJECTS) $(faillock_LDADD) $(LIBS) ++ ++mostlyclean-compile: ++ -rm -f *.$(OBJEXT) ++ ++distclean-compile: ++ -rm -f *.tab.c ++ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock-faillock.Po@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock-main.Po@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_faillock.Plo@am__quote@ # am--include-marker ++ ++$(am__depfiles_remade): ++ @$(MKDIR_P) $(@D) ++ @echo '# dummy' >$@-t && $(am__mv) $@-t $@ ++ ++am--depfiles: $(am__depfiles_remade) ++ ++.c.o: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< ++ ++.c.obj: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ++ ++.c.lo: ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< ++ ++faillock-main.o: main.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-main.o -MD -MP -MF $(DEPDIR)/faillock-main.Tpo -c -o faillock-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-main.Tpo $(DEPDIR)/faillock-main.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='faillock-main.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c ++ ++faillock-main.obj: main.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-main.obj -MD -MP -MF $(DEPDIR)/faillock-main.Tpo -c -o faillock-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-main.Tpo $(DEPDIR)/faillock-main.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='faillock-main.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` ++ ++faillock-faillock.o: faillock.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-faillock.o -MD -MP -MF $(DEPDIR)/faillock-faillock.Tpo -c -o faillock-faillock.o `test -f 'faillock.c' || echo '$(srcdir)/'`faillock.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-faillock.Tpo $(DEPDIR)/faillock-faillock.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='faillock.c' object='faillock-faillock.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-faillock.o `test -f 'faillock.c' || echo '$(srcdir)/'`faillock.c ++ ++faillock-faillock.obj: faillock.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-faillock.obj -MD -MP -MF $(DEPDIR)/faillock-faillock.Tpo -c -o faillock-faillock.obj `if test -f 'faillock.c'; then $(CYGPATH_W) 'faillock.c'; else $(CYGPATH_W) '$(srcdir)/faillock.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-faillock.Tpo $(DEPDIR)/faillock-faillock.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='faillock.c' object='faillock-faillock.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-faillock.obj `if test -f 'faillock.c'; then $(CYGPATH_W) 'faillock.c'; else $(CYGPATH_W) '$(srcdir)/faillock.c'; fi` ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++install-man5: $(dist_man_MANS) ++ @$(NORMAL_INSTALL) ++ @list1=''; \ ++ list2='$(dist_man_MANS)'; \ ++ test -n "$(man5dir)" \ ++ && test -n "`echo $$list1$$list2`" \ ++ || exit 0; \ ++ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ ++ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ ++ { for i in $$list1; do echo "$$i"; done; \ ++ if test -n "$$list2"; then \ ++ for i in $$list2; do echo "$$i"; done \ ++ | sed -n '/\.5[a-z]*$$/p'; \ ++ fi; \ ++ } | while read p; do \ ++ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ ++ echo "$$d$$p"; echo "$$p"; \ ++ done | \ ++ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ ++ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ ++ sed 'N;N;s,\n, ,g' | { \ ++ list=; while read file base inst; do \ ++ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ ++ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ ++ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ ++ fi; \ ++ done; \ ++ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ ++ while read files; do \ ++ test -z "$$files" || { \ ++ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ ++ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ ++ done; } ++ ++uninstall-man5: ++ @$(NORMAL_UNINSTALL) ++ @list=''; test -n "$(man5dir)" || exit 0; \ ++ files=`{ for i in $$list; do echo "$$i"; done; \ ++ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ ++ sed -n '/\.5[a-z]*$$/p'; \ ++ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ ++ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ ++ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) ++install-man8: $(dist_man_MANS) ++ @$(NORMAL_INSTALL) ++ @list1=''; \ ++ list2='$(dist_man_MANS)'; \ ++ test -n "$(man8dir)" \ ++ && test -n "`echo $$list1$$list2`" \ ++ || exit 0; \ ++ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ ++ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ ++ { for i in $$list1; do echo "$$i"; done; \ ++ if test -n "$$list2"; then \ ++ for i in $$list2; do echo "$$i"; done \ ++ | sed -n '/\.8[a-z]*$$/p'; \ ++ fi; \ ++ } | while read p; do \ ++ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ ++ echo "$$d$$p"; echo "$$p"; \ ++ done | \ ++ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ ++ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ ++ sed 'N;N;s,\n, ,g' | { \ ++ list=; while read file base inst; do \ ++ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ ++ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ ++ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ ++ fi; \ ++ done; \ ++ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ ++ while read files; do \ ++ test -z "$$files" || { \ ++ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ ++ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ ++ done; } ++ ++uninstall-man8: ++ @$(NORMAL_UNINSTALL) ++ @list=''; test -n "$(man8dir)" || exit 0; \ ++ files=`{ for i in $$list; do echo "$$i"; done; \ ++ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ ++ sed -n '/\.8[a-z]*$$/p'; \ ++ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ ++ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ ++ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) ++install-dist_secureconfDATA: $(dist_secureconf_DATA) ++ @$(NORMAL_INSTALL) ++ @list='$(dist_secureconf_DATA)'; test -n "$(secureconfdir)" || list=; \ ++ if test -n "$$list"; then \ ++ echo " $(MKDIR_P) '$(DESTDIR)$(secureconfdir)'"; \ ++ $(MKDIR_P) "$(DESTDIR)$(secureconfdir)" || exit 1; \ ++ fi; \ ++ for p in $$list; do \ ++ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ ++ echo "$$d$$p"; \ ++ done | $(am__base_list) | \ ++ while read files; do \ ++ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(secureconfdir)'"; \ ++ $(INSTALL_DATA) $$files "$(DESTDIR)$(secureconfdir)" || exit $$?; \ ++ done ++ ++uninstall-dist_secureconfDATA: ++ @$(NORMAL_UNINSTALL) ++ @list='$(dist_secureconf_DATA)'; test -n "$(secureconfdir)" || list=; \ ++ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ ++ dir='$(DESTDIR)$(secureconfdir)'; $(am__uninstall_files_from_dir) ++ ++ID: $(am__tagged_files) ++ $(am__define_uniq_tagged_files); mkid -fID $$unique ++tags: tags-am ++TAGS: tags ++ ++tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) ++ set x; \ ++ here=`pwd`; \ ++ $(am__define_uniq_tagged_files); \ ++ shift; \ ++ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ ++ test -n "$$unique" || unique=$$empty_fix; \ ++ if test $$# -gt 0; then \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ "$$@" $$unique; \ ++ else \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ $$unique; \ ++ fi; \ ++ fi ++ctags: ctags-am ++ ++CTAGS: ctags ++ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) ++ $(am__define_uniq_tagged_files); \ ++ test -z "$(CTAGS_ARGS)$$unique" \ ++ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ ++ $$unique ++ ++GTAGS: ++ here=`$(am__cd) $(top_builddir) && pwd` \ ++ && $(am__cd) $(top_srcdir) \ ++ && gtags -i $(GTAGS_ARGS) "$$here" ++cscopelist: cscopelist-am ++ ++cscopelist-am: $(am__tagged_files) ++ list='$(am__tagged_files)'; \ ++ case "$(srcdir)" in \ ++ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ ++ *) sdir=$(subdir)/$(srcdir) ;; \ ++ esac; \ ++ for i in $$list; do \ ++ if test -f "$$i"; then \ ++ echo "$(subdir)/$$i"; \ ++ else \ ++ echo "$$sdir/$$i"; \ ++ fi; \ ++ done >> $(top_builddir)/cscope.files ++ ++distclean-tags: ++ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags ++ ++# Recover from deleted '.trs' file; this should ensure that ++# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create ++# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells ++# to avoid problems with "make -n". ++.log.trs: ++ rm -f $< $@ ++ $(MAKE) $(AM_MAKEFLAGS) $< ++ ++# Leading 'am--fnord' is there to ensure the list of targets does not ++# expand to empty, as could happen e.g. with make check TESTS=''. ++am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) ++am--force-recheck: ++ @: ++ ++$(TEST_SUITE_LOG): $(TEST_LOGS) ++ @$(am__set_TESTS_bases); \ ++ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ ++ redo_bases=`for i in $$bases; do \ ++ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ ++ done`; \ ++ if test -n "$$redo_bases"; then \ ++ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ ++ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ ++ if $(am__make_dryrun); then :; else \ ++ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ ++ fi; \ ++ fi; \ ++ if test -n "$$am__remaking_logs"; then \ ++ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ ++ "recursion detected" >&2; \ ++ elif test -n "$$redo_logs"; then \ ++ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ ++ fi; \ ++ if $(am__make_dryrun); then :; else \ ++ st=0; \ ++ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ ++ for i in $$redo_bases; do \ ++ test -f $$i.trs && test -r $$i.trs \ ++ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ ++ test -f $$i.log && test -r $$i.log \ ++ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ ++ done; \ ++ test $$st -eq 0 || exit 1; \ ++ fi ++ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ++ ws='[ ]'; \ ++ results=`for b in $$bases; do echo $$b.trs; done`; \ ++ test -n "$$results" || results=/dev/null; \ ++ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ ++ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ ++ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ ++ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ ++ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ ++ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ ++ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ ++ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ ++ success=true; \ ++ else \ ++ success=false; \ ++ fi; \ ++ br='==================='; br=$$br$$br$$br$$br; \ ++ result_count () \ ++ { \ ++ if test x"$$1" = x"--maybe-color"; then \ ++ maybe_colorize=yes; \ ++ elif test x"$$1" = x"--no-color"; then \ ++ maybe_colorize=no; \ ++ else \ ++ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ ++ fi; \ ++ shift; \ ++ desc=$$1 count=$$2; \ ++ if test $$maybe_colorize = yes && test $$count -gt 0; then \ ++ color_start=$$3 color_end=$$std; \ ++ else \ ++ color_start= color_end=; \ ++ fi; \ ++ echo "$${color_start}# $$desc $$count$${color_end}"; \ ++ }; \ ++ create_testsuite_report () \ ++ { \ ++ result_count $$1 "TOTAL:" $$all "$$brg"; \ ++ result_count $$1 "PASS: " $$pass "$$grn"; \ ++ result_count $$1 "SKIP: " $$skip "$$blu"; \ ++ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ ++ result_count $$1 "FAIL: " $$fail "$$red"; \ ++ result_count $$1 "XPASS:" $$xpass "$$red"; \ ++ result_count $$1 "ERROR:" $$error "$$mgn"; \ ++ }; \ ++ { \ ++ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ ++ $(am__rst_title); \ ++ create_testsuite_report --no-color; \ ++ echo; \ ++ echo ".. contents:: :depth: 2"; \ ++ echo; \ ++ for b in $$bases; do echo $$b; done \ ++ | $(am__create_global_log); \ ++ } >$(TEST_SUITE_LOG).tmp || exit 1; \ ++ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ ++ if $$success; then \ ++ col="$$grn"; \ ++ else \ ++ col="$$red"; \ ++ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ ++ fi; \ ++ echo "$${col}$$br$${std}"; \ ++ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ ++ echo "$${col}$$br$${std}"; \ ++ create_testsuite_report --maybe-color; \ ++ echo "$$col$$br$$std"; \ ++ if $$success; then :; else \ ++ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ ++ if test -n "$(PACKAGE_BUGREPORT)"; then \ ++ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ ++ fi; \ ++ echo "$$col$$br$$std"; \ ++ fi; \ ++ $$success || exit 1 ++ ++check-TESTS: $(dist_check_SCRIPTS) ++ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list ++ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list ++ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) ++ @set +e; $(am__set_TESTS_bases); \ ++ log_list=`for i in $$bases; do echo $$i.log; done`; \ ++ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ ++ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ ++ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ ++ exit $$?; ++recheck: all $(dist_check_SCRIPTS) ++ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) ++ @set +e; $(am__set_TESTS_bases); \ ++ bases=`for i in $$bases; do echo $$i; done \ ++ | $(am__list_recheck_tests)` || exit 1; \ ++ log_list=`for i in $$bases; do echo $$i.log; done`; \ ++ log_list=`echo $$log_list`; \ ++ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ ++ am__force_recheck=am--force-recheck \ ++ TEST_LOGS="$$log_list"; \ ++ exit $$? ++tst-pam_faillock.log: tst-pam_faillock ++ @p='tst-pam_faillock'; \ ++ b='tst-pam_faillock'; \ ++ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ ++ --log-file $$b.log --trs-file $$b.trs \ ++ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ ++ "$$tst" $(AM_TESTS_FD_REDIRECT) ++.test.log: ++ @p='$<'; \ ++ $(am__set_b); \ ++ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ ++ --log-file $$b.log --trs-file $$b.trs \ ++ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ ++ "$$tst" $(AM_TESTS_FD_REDIRECT) ++@am__EXEEXT_TRUE@.test$(EXEEXT).log: ++@am__EXEEXT_TRUE@ @p='$<'; \ ++@am__EXEEXT_TRUE@ $(am__set_b); \ ++@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ ++@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ ++@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ ++@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) ++ ++distdir: $(BUILT_SOURCES) ++ $(MAKE) $(AM_MAKEFLAGS) distdir-am ++ ++distdir-am: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++ $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS) ++ $(MAKE) $(AM_MAKEFLAGS) check-TESTS ++check: check-am ++all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) ++installdirs: ++ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(secureconfdir)"; do \ ++ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ ++ done ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ if test -z '$(STRIP)'; then \ ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ install; \ ++ else \ ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ ++ fi ++mostlyclean-generic: ++ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) ++ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) ++ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) ++ ++clean-generic: ++ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ ++ clean-securelibLTLIBRARIES mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f ./$(DEPDIR)/faillock-faillock.Po ++ -rm -f ./$(DEPDIR)/faillock-main.Po ++ -rm -f ./$(DEPDIR)/faillock.Plo ++ -rm -f ./$(DEPDIR)/pam_faillock.Plo ++ -rm -f Makefile ++distclean-am: clean-am distclean-compile distclean-generic \ ++ distclean-tags ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: install-dist_secureconfDATA install-man \ ++ install-securelibLTLIBRARIES ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-sbinPROGRAMS ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: install-man5 install-man8 ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f ./$(DEPDIR)/faillock-faillock.Po ++ -rm -f ./$(DEPDIR)/faillock-main.Po ++ -rm -f ./$(DEPDIR)/faillock.Plo ++ -rm -f ./$(DEPDIR)/pam_faillock.Plo ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-compile mostlyclean-generic \ ++ mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: uninstall-dist_secureconfDATA uninstall-man \ ++ uninstall-sbinPROGRAMS uninstall-securelibLTLIBRARIES ++ ++uninstall-man: uninstall-man5 uninstall-man8 ++ ++.MAKE: check-am install-am install-strip ++ ++.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ ++ check-am clean clean-generic clean-libtool clean-sbinPROGRAMS \ ++ clean-securelibLTLIBRARIES cscopelist-am ctags ctags-am \ ++ distclean distclean-compile distclean-generic \ ++ distclean-libtool distclean-tags distdir dvi dvi-am html \ ++ html-am info info-am install install-am install-data \ ++ install-data-am install-dist_secureconfDATA install-dvi \ ++ install-dvi-am install-exec install-exec-am install-html \ ++ install-html-am install-info install-info-am install-man \ ++ install-man5 install-man8 install-pdf install-pdf-am \ ++ install-ps install-ps-am install-sbinPROGRAMS \ ++ install-securelibLTLIBRARIES install-strip installcheck \ ++ installcheck-am installdirs maintainer-clean \ ++ maintainer-clean-generic mostlyclean mostlyclean-compile \ ++ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ ++ recheck tags tags-am uninstall uninstall-am \ ++ uninstall-dist_secureconfDATA uninstall-man uninstall-man5 \ ++ uninstall-man8 uninstall-sbinPROGRAMS \ ++ uninstall-securelibLTLIBRARIES ++ ++.PRECIOUS: Makefile ++ ++@ENABLE_REGENERATE_MAN_TRUE@-include $(top_srcdir)/Make.xml.rules ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +Index: Linux-PAM-1.3.0/modules/pam_faillock/README +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/README +@@ -0,0 +1,140 @@ ++pam_faillock — Module counting authentication failures during a specified ++interval ++ ++━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ++ ++DESCRIPTION ++ ++This module maintains a list of failed authentication attempts per user during ++a specified interval and locks the account in case there were more than deny ++consecutive failed authentications. ++ ++Normally, failed attempts to authenticate root will not cause the root account ++to become blocked, to prevent denial-of-service: if your users aren't given ++shell accounts and root may only login via su or at the machine console (not ++telnet/rsh, etc), this is safe. ++ ++OPTIONS ++ ++{preauth|authfail|authsucc} ++ ++ This argument must be set accordingly to the position of this module ++ instance in the PAM stack. ++ ++ The preauth argument must be used when the module is called before the ++ modules which ask for the user credentials such as the password. The module ++ just examines whether the user should be blocked from accessing the service ++ in case there were anomalous number of failed consecutive authentication ++ attempts recently. This call is optional if authsucc is used. ++ ++ The authfail argument must be used when the module is called after the ++ modules which determine the authentication outcome, failed. Unless the user ++ is already blocked due to previous authentication failures, the module will ++ record the failure into the appropriate user tally file. ++ ++ The authsucc argument must be used when the module is called after the ++ modules which determine the authentication outcome, succeeded. Unless the ++ user is already blocked due to previous authentication failures, the module ++ will then clear the record of the failures in the respective user tally ++ file. Otherwise it will return authentication error. If this call is not ++ done, the pam_faillock will not distinguish between consecutive and ++ non-consecutive failed authentication attempts. The preauth call must be ++ used in such case. Due to complications in the way the PAM stack can be ++ configured it is also possible to call pam_faillock as an account module. ++ In such configuration the module must be also called in the preauth stage. ++ ++conf=/path/to/config-file ++ ++ Use another configuration file instead of the default /etc/security/ ++ faillock.conf. ++ ++The options for configuring the module behavior are described in the ++faillock.conf(5) manual page. The options specified on the module command line ++override the values from the configuration file. ++ ++NOTES ++ ++Configuring options on the module command line is not recommend. The /etc/ ++security/faillock.conf should be used instead. ++ ++The setup of pam_faillock in the PAM stack is different from the pam_tally2 ++module setup. ++ ++Individual files with the failure records are created as owned by the user. ++This allows pam_faillock.so module to work correctly when it is called from a ++screensaver. ++ ++Note that using the module in preauth without the silent option specified in / ++etc/security/faillock.conf or with requisite control field leaks an information ++about existence or non-existence of a user account in the system because the ++failures are not recorded for the unknown users. The message about the user ++account being locked is never displayed for non-existing user accounts allowing ++the adversary to infer that a particular account is not existing on a system. ++ ++EXAMPLES ++ ++Here are two possible configuration examples for /etc/pam.d/login. They make ++pam_faillock to lock the account after 4 consecutive failed logins during the ++default interval of 15 minutes. Root account will be locked as well. The ++accounts will be automatically unlocked after 20 minutes. ++ ++In the first example the module is called only in the auth phase and the module ++does not print any information about the account being blocked by pam_faillock. ++The preauth call can be added to tell users that their logins are blocked by ++the module and also to abort the authentication without even asking for ++password in such case. ++ ++/etc/security/faillock.conf file example: ++ ++deny=4 ++unlock_time=1200 ++silent ++ ++ ++/etc/pam.d/config file example: ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++# optionally call: auth requisite pam_faillock.so preauth ++# to display the message about account being locked ++auth [success=1 default=bad] pam_unix.so ++auth [default=die] pam_faillock.so authfail ++auth sufficient pam_faillock.so authsucc ++auth required pam_deny.so ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++In the second example the module is called both in the auth and account phases ++and the module informs the authenticating user when the account is locked if ++silent option is not specified in the faillock.conf. ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++auth required pam_faillock.so preauth ++# optionally use requisite above if you do not want to prompt for the password ++# on locked accounts ++auth sufficient pam_unix.so ++auth [default=die] pam_faillock.so authfail ++auth required pam_deny.so ++account required pam_faillock.so ++# if you drop the above call to pam_faillock.so the lock will be done also ++# on non-consecutive authentication failures ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++AUTHOR ++ ++pam_faillock was written by Tomas Mraz. ++ +Index: Linux-PAM-1.3.0/modules/pam_faillock/README.xml +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/README.xml +@@ -0,0 +1,46 @@ ++ ++ ++--> ++]> ++ ++

++ ++ ++ ++ ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="pam_faillock.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_faillock-name"]/*)'/> ++ ++ ++ ++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
++ ++
+Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.8 +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.8 +@@ -0,0 +1,78 @@ ++'\" t ++.\" Title: faillock ++.\" Author: [see the "AUTHOR" section] ++.\" Generator: DocBook XSL Stylesheets v1.79.1 ++.\" Date: 11/25/2020 ++.\" Manual: Linux-PAM Manual ++.\" Source: Linux-PAM Manual ++.\" Language: English ++.\" ++.TH "FAILLOCK" "8" "11/25/2020" "Linux-PAM Manual" "Linux\-PAM Manual" ++.\" ----------------------------------------------------------------- ++.\" * Define some portability stuff ++.\" ----------------------------------------------------------------- ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.\" http://bugs.debian.org/507673 ++.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.ie \n(.g .ds Aq \(aq ++.el .ds Aq ' ++.\" ----------------------------------------------------------------- ++.\" * set default formatting ++.\" ----------------------------------------------------------------- ++.\" disable hyphenation ++.nh ++.\" disable justification (adjust text to left margin only) ++.ad l ++.\" ----------------------------------------------------------------- ++.\" * MAIN CONTENT STARTS HERE * ++.\" ----------------------------------------------------------------- ++.SH "NAME" ++faillock \- Tool for displaying and modifying the authentication failure record files ++.SH "SYNOPSIS" ++.HP \w'\fBfaillock\fR\ 'u ++\fBfaillock\fR [\-\-dir\ \fI/path/to/tally\-directory\fR] [\-\-user\ \fIusername\fR] [\-\-reset] ++.SH "DESCRIPTION" ++.PP ++The ++\fIpam_faillock\&.so\fR ++module maintains a list of failed authentication attempts per user during a specified interval and locks the account in case there were more than ++\fIdeny\fR ++consecutive failed authentications\&. It stores the failure records into per\-user files in the tally directory\&. ++.PP ++The ++\fBfaillock\fR ++command is an application which can be used to examine and modify the contents of the tally files\&. It can display the recent failed authentication attempts of the ++\fIusername\fR ++or clear the tally files of all or individual ++\fIusernames\fR\&. ++.SH "OPTIONS" ++.PP ++\fB\-\-dir \fR\fB\fI/path/to/tally\-directory\fR\fR ++.RS 4 ++The directory where the user files with the failure records are kept\&. The default is ++/var/run/faillock\&. ++.RE ++.PP ++\fB\-\-user \fR\fB\fIusername\fR\fR ++.RS 4 ++The user whose failure records should be displayed or cleared\&. ++.RE ++.PP ++\fB\-\-reset\fR ++.RS 4 ++Instead of displaying the user\*(Aqs failure records, clear them\&. ++.RE ++.SH "FILES" ++.PP ++/var/run/faillock/* ++.RS 4 ++the files logging the authentication failures for users ++.RE ++.SH "SEE ALSO" ++.PP ++\fBpam_faillock\fR(8), ++\fBpam\fR(8) ++.SH "AUTHOR" ++.PP ++faillock was written by Tomas Mraz\&. +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.8.xml +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.8.xml +@@ -0,0 +1,123 @@ ++ ++ ++ ++ ++ ++ ++ faillock ++ 8 ++ Linux-PAM Manual ++ ++ ++ ++ faillock ++ Tool for displaying and modifying the authentication failure record files ++ ++ ++ ++ ++ faillock ++ ++ --dir /path/to/tally-directory ++ ++ ++ --user username ++ ++ ++ --reset ++ ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ ++ The pam_faillock.so module maintains a list of ++ failed authentication attempts per user during a specified interval ++ and locks the account in case there were more than ++ deny consecutive failed authentications. ++ It stores the failure records into per-user files in the tally ++ directory. ++ ++ ++ The faillock command is an application which ++ can be used to examine and modify the contents of the ++ tally files. It can display the recent failed authentication ++ attempts of the username or clear the tally ++ files of all or individual usernames. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ The directory where the user files with the failure records are kept. The ++ default is /var/run/faillock. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The user whose failure records should be displayed or cleared. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Instead of displaying the user's failure records, clear them. ++ ++ ++ ++ ++ ++ ++ ++ FILES ++ ++ ++ /var/run/faillock/* ++ ++ the files logging the authentication failures for users ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ pam_faillock8 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ faillock was written by Tomas Mraz. ++ ++ ++ ++ +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.c +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.c +@@ -0,0 +1,173 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * Copyright (c) 2010, 2016, 2017 Red Hat, Inc. ++ * ++ * 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. ++ */ ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "faillock.h" ++ ++#define ignore_return(x) if (1==((int)x)) {;} ++ ++int ++open_tally (const char *dir, const char *user, uid_t uid, int create) ++{ ++ char *path; ++ int flags = O_RDWR; ++ int fd; ++ ++ if (dir == NULL || strstr(user, "../") != NULL) ++ /* just a defensive programming as the user must be a ++ * valid user on the system anyway ++ */ ++ return -1; ++ path = malloc(strlen(dir) + strlen(user) + 2); ++ if (path == NULL) ++ return -1; ++ ++ strcpy(path, dir); ++ if (*dir && dir[strlen(dir) - 1] != '/') { ++ strcat(path, "/"); ++ } ++ strcat(path, user); ++ ++ if (create) { ++ flags |= O_CREAT; ++ } ++ ++ fd = open(path, flags, 0660); ++ ++ free(path); ++ ++ if (fd != -1) { ++ struct stat st; ++ ++ while (flock(fd, LOCK_EX) == -1 && errno == EINTR); ++ if (fstat(fd, &st) == 0) { ++ if (st.st_uid != uid) { ++ ignore_return(fchown(fd, uid, -1)); ++ } ++ ++ /* ++ * If umask is set to 022, as will probably in most systems, then the ++ * group will not be able to write to the file. So, change the file ++ * permissions just in case. ++ * Note: owners of this file are user:root, so if the permissions are ++ * not changed the root process writing to this file will require ++ * CAP_DAC_OVERRIDE. ++ */ ++ if (!(st.st_mode & S_IWGRP)) { ++ ignore_return(fchmod(fd, 0660)); ++ } ++ } ++ } ++ ++ return fd; ++} ++ ++#define CHUNK_SIZE (64 * sizeof(struct tally)) ++#define MAX_RECORDS 1024 ++ ++int ++read_tally(int fd, struct tally_data *tallies) ++{ ++ void *data = NULL, *newdata; ++ unsigned int count = 0; ++ ssize_t chunk = 0; ++ ++ do { ++ newdata = realloc(data, count * sizeof(struct tally) + CHUNK_SIZE); ++ if (newdata == NULL) { ++ free(data); ++ return -1; ++ } ++ ++ data = newdata; ++ ++ chunk = pam_modutil_read(fd, (char *)data + count * sizeof(struct tally), CHUNK_SIZE); ++ if (chunk < 0) { ++ free(data); ++ return -1; ++ } ++ ++ count += chunk/sizeof(struct tally); ++ ++ if (count >= MAX_RECORDS) ++ break; ++ } ++ while (chunk == CHUNK_SIZE); ++ ++ tallies->records = data; ++ tallies->count = count; ++ ++ return 0; ++} ++ ++int ++update_tally(int fd, struct tally_data *tallies) ++{ ++ void *data = tallies->records; ++ unsigned int count = tallies->count; ++ ssize_t chunk; ++ ++ if (tallies->count > MAX_RECORDS) { ++ data = tallies->records + (count - MAX_RECORDS); ++ count = MAX_RECORDS; ++ } ++ ++ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { ++ return -1; ++ } ++ ++ chunk = pam_modutil_write(fd, data, count * sizeof(struct tally)); ++ ++ if (chunk != (ssize_t)(count * sizeof(struct tally))) { ++ return -1; ++ } ++ ++ if (ftruncate(fd, count * sizeof(struct tally)) == -1) ++ return -1; ++ ++ return 0; ++} +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf +@@ -0,0 +1,62 @@ ++# Configuration for locking the user after multiple failed ++# authentication attempts. ++# ++# The directory where the user files with the failure records are kept. ++# The default is /var/run/faillock. ++# dir = /var/run/faillock ++# ++# Will log the user name into the system log if the user is not found. ++# Enabled if option is present. ++# audit ++# ++# Don't print informative messages. ++# Enabled if option is present. ++# silent ++# ++# Don't log informative messages via syslog. ++# Enabled if option is present. ++# no_log_info ++# ++# Only track failed user authentications attempts for local users ++# in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users. ++# The `faillock` command will also no longer track user failed ++# authentication attempts. Enabling this option will prevent a ++# double-lockout scenario where a user is locked out locally and ++# in the centralized mechanism. ++# Enabled if option is present. ++# local_users_only ++# ++# Deny access if the number of consecutive authentication failures ++# for this user during the recent interval exceeds n tries. ++# The default is 3. ++# deny = 3 ++# ++# The length of the interval during which the consecutive ++# authentication failures must happen for the user account ++# lock out is n seconds. ++# The default is 900 (15 minutes). ++# fail_interval = 900 ++# ++# The access will be re-enabled after n seconds after the lock out. ++# The value 0 has the same meaning as value `never` - the access ++# will not be re-enabled without resetting the faillock ++# entries by the `faillock` command. ++# The default is 600 (10 minutes). ++# unlock_time = 600 ++# ++# Root account can become locked as well as regular accounts. ++# Enabled if option is present. ++# even_deny_root ++# ++# This option implies the `even_deny_root` option. ++# Allow access after n seconds to root account after the ++# account is locked. In case the option is not specified ++# the value is the same as of the `unlock_time` option. ++# root_unlock_time = 900 ++# ++# If a group name is specified with this option, members ++# of the group will be handled by this module the same as ++# the root account (the options `even_deny_root>` and ++# `root_unlock_time` will apply to them. ++# By default, the option is not set. ++# admin_group = +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf.5 +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf.5 +@@ -0,0 +1,171 @@ ++'\" t ++.\" Title: faillock.conf ++.\" Author: [see the "AUTHOR" section] ++.\" Generator: DocBook XSL Stylesheets v1.79.1 ++.\" Date: 11/25/2020 ++.\" Manual: Linux-PAM Manual ++.\" Source: Linux-PAM Manual ++.\" Language: English ++.\" ++.TH "FAILLOCK\&.CONF" "5" "11/25/2020" "Linux-PAM Manual" "Linux\-PAM Manual" ++.\" ----------------------------------------------------------------- ++.\" * Define some portability stuff ++.\" ----------------------------------------------------------------- ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.\" http://bugs.debian.org/507673 ++.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.ie \n(.g .ds Aq \(aq ++.el .ds Aq ' ++.\" ----------------------------------------------------------------- ++.\" * set default formatting ++.\" ----------------------------------------------------------------- ++.\" disable hyphenation ++.nh ++.\" disable justification (adjust text to left margin only) ++.ad l ++.\" ----------------------------------------------------------------- ++.\" * MAIN CONTENT STARTS HERE * ++.\" ----------------------------------------------------------------- ++.SH "NAME" ++faillock.conf \- pam_faillock configuration file ++.SH "DESCRIPTION" ++.PP ++\fBfaillock\&.conf\fR ++provides a way to configure the default settings for locking the user after multiple failed authentication attempts\&. This file is read by the ++\fIpam_faillock\fR ++module and is the preferred method over configuring ++\fIpam_faillock\fR ++directly\&. ++.PP ++The file has a very simple ++\fIname = value\fR ++format with possible comments starting with ++\fI#\fR ++character\&. The whitespace at the beginning of line, end of line, and around the ++\fI=\fR ++sign is ignored\&. ++.SH "OPTIONS" ++.PP ++\fBdir=\fR\fB\fI/path/to/tally\-directory\fR\fR ++.RS 4 ++The directory where the user files with the failure records are kept\&. The default is ++/var/run/faillock\&. ++.RE ++.PP ++\fBaudit\fR ++.RS 4 ++Will log the user name into the system log if the user is not found\&. ++.RE ++.PP ++\fBsilent\fR ++.RS 4 ++Don\*(Aqt print informative messages to the user\&. Please note that when this option is not used there will be difference in the authentication behavior for users which exist on the system and non\-existing users\&. ++.RE ++.PP ++\fBno_log_info\fR ++.RS 4 ++Don\*(Aqt log informative messages via ++\fBsyslog\fR(3)\&. ++.RE ++.PP ++\fBlocal_users_only\fR ++.RS 4 ++Only track failed user authentications attempts for local users in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc\&.) users\&. The ++\fBfaillock\fR(8) ++command will also no longer track user failed authentication attempts\&. Enabling this option will prevent a double\-lockout scenario where a user is locked out locally and in the centralized mechanism\&. ++.RE ++.PP ++\fBnodelay\fR ++.RS 4 ++Don\*(Aqt enforce a delay after authentication failures\&. ++.RE ++.PP ++\fBdeny=\fR\fB\fIn\fR\fR ++.RS 4 ++Deny access if the number of consecutive authentication failures for this user during the recent interval exceeds ++\fIn\fR\&. The default is 3\&. ++.RE ++.PP ++\fBfail_interval=\fR\fB\fIn\fR\fR ++.RS 4 ++The length of the interval during which the consecutive authentication failures must happen for the user account lock out is ++\fIn\fR ++seconds\&. The default is 900 (15 minutes)\&. ++.RE ++.PP ++\fBunlock_time=\fR\fB\fIn\fR\fR ++.RS 4 ++The access will be re\-enabled after ++\fIn\fR ++seconds after the lock out\&. The value 0 has the same meaning as value ++\fInever\fR ++\- the access will not be re\-enabled without resetting the faillock entries by the ++\fBfaillock\fR(8) ++command\&. The default is 600 (10 minutes)\&. ++.sp ++Note that the default directory that ++\fIpam_faillock\fR ++uses is usually cleared on system boot so the access will be also re\-enabled after system reboot\&. If that is undesirable a different tally directory must be set with the ++\fBdir\fR ++option\&. ++.sp ++Also note that it is usually undesirable to permanently lock out users as they can become easily a target of denial of service attack unless the usernames are random and kept secret to potential attackers\&. ++.RE ++.PP ++\fBeven_deny_root\fR ++.RS 4 ++Root account can become locked as well as regular accounts\&. ++.RE ++.PP ++\fBroot_unlock_time=\fR\fB\fIn\fR\fR ++.RS 4 ++This option implies ++\fBeven_deny_root\fR ++option\&. Allow access after ++\fIn\fR ++seconds to root account after the account is locked\&. In case the option is not specified the value is the same as of the ++\fBunlock_time\fR ++option\&. ++.RE ++.PP ++\fBadmin_group=\fR\fB\fIname\fR\fR ++.RS 4 ++If a group name is specified with this option, members of the group will be handled by this module the same as the root account (the options ++\fBeven_deny_root\fR ++and ++\fBroot_unlock_time\fR ++will apply to them\&. By default the option is not set\&. ++.RE ++.SH "EXAMPLES" ++.PP ++/etc/security/faillock\&.conf file example: ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++deny=4 ++unlock_time=1200 ++silent ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.SH "FILES" ++.PP ++/etc/security/faillock\&.conf ++.RS 4 ++the config file for custom options ++.RE ++.SH "SEE ALSO" ++.PP ++\fBfaillock\fR(8), ++\fBpam_faillock\fR(8), ++\fBpam.conf\fR(5), ++\fBpam.d\fR(5), ++\fBpam\fR(8) ++.SH "AUTHOR" ++.PP ++pam_faillock was written by Tomas Mraz\&. The support for faillock\&.conf was written by Brian Ward\&. +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf.5.xml +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.conf.5.xml +@@ -0,0 +1,253 @@ ++ ++ ++ ++ ++ ++ ++ faillock.conf ++ 5 ++ Linux-PAM Manual ++ ++ ++ ++ faillock.conf ++ pam_faillock configuration file ++ ++ ++ ++ ++ DESCRIPTION ++ ++ faillock.conf provides a way to configure the ++ default settings for locking the user after multiple failed authentication attempts. ++ This file is read by the pam_faillock module and is the ++ preferred method over configuring pam_faillock directly. ++ ++ ++ The file has a very simple name = value format with possible comments ++ starting with # character. The whitespace at the beginning of line, end ++ of line, and around the = sign is ignored. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ The directory where the user files with the failure records are kept. The ++ default is /var/run/faillock. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Will log the user name into the system log if the user is not found. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't print informative messages to the user. Please note that when ++ this option is not used there will be difference in the authentication ++ behavior for users which exist on the system and non-existing users. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't log informative messages via syslog3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Only track failed user authentications attempts for local users ++ in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users. ++ The faillock8 ++ command will also no longer track user failed ++ authentication attempts. Enabling this option will prevent a ++ double-lockout scenario where a user is locked out locally and ++ in the centralized mechanism. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Don't enforce a delay after authentication failures. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Deny access if the number of consecutive authentication failures ++ for this user during the recent interval exceeds ++ n. The default is 3. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The length of the interval during which the consecutive ++ authentication failures must happen for the user account ++ lock out is n seconds. ++ The default is 900 (15 minutes). ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ The access will be re-enabled after ++ n seconds after the lock out. ++ The value 0 has the same meaning as value ++ never - the access ++ will not be re-enabled without resetting the faillock ++ entries by the faillock8 command. ++ The default is 600 (10 minutes). ++ ++ ++ Note that the default directory that pam_faillock ++ uses is usually cleared on system boot so the access will be also re-enabled ++ after system reboot. If that is undesirable a different tally directory ++ must be set with the option. ++ ++ ++ Also note that it is usually undesirable to permanently lock ++ out users as they can become easily a target of denial of service ++ attack unless the usernames are random and kept secret to potential ++ attackers. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Root account can become locked as well as regular accounts. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This option implies option. ++ Allow access after n seconds ++ to root account after the account is locked. In case the ++ option is not specified the value is the same as of the ++ option. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ If a group name is specified with this option, members ++ of the group will be handled by this module the same as ++ the root account (the options ++ and will apply to them. ++ By default the option is not set. ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLES ++ ++ /etc/security/faillock.conf file example: ++ ++ ++deny=4 ++unlock_time=1200 ++silent ++ ++ ++ ++ ++ FILES ++ ++ ++ /etc/security/faillock.conf ++ ++ the config file for custom options ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ faillock8 ++ , ++ ++ pam_faillock8 ++ , ++ ++ pam.conf5 ++ , ++ ++ pam.d5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ pam_faillock was written by Tomas Mraz. The support for faillock.conf was written by Brian Ward. ++ ++ ++ ++ +Index: Linux-PAM-1.3.0/modules/pam_faillock/faillock.h +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/faillock.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * ++ * 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. ++ */ ++ ++/* ++ * faillock.h - authentication failure data file record structure ++ * ++ * Each record in the file represents an instance of login failure of ++ * the user at the recorded time. ++ */ ++ ++ ++#ifndef _FAILLOCK_H ++#define _FAILLOCK_H ++ ++#include ++#include ++ ++#define TALLY_STATUS_VALID 0x1 /* the tally file entry is valid */ ++#define TALLY_STATUS_RHOST 0x2 /* the source is rhost */ ++#define TALLY_STATUS_TTY 0x4 /* the source is tty */ ++/* If neither TALLY_FLAG_RHOST nor TALLY_FLAG_TTY are set the source is service. */ ++ ++struct tally { ++ char source[52]; /* rhost or tty of the login failure */ ++ /* (not necessarily NULL terminated) */ ++ uint16_t reserved; /* reserved for future use */ ++ uint16_t status; /* record status */ ++ uint64_t time; /* time of the login failure */ ++}; ++/* 64 bytes per entry */ ++ ++struct tally_data { ++ struct tally *records; /* array of tallies */ ++ unsigned int count; /* number of records */ ++}; ++ ++#define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" ++#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" ++ ++int open_tally(const char *dir, const char *user, uid_t uid, int create); ++int read_tally(int fd, struct tally_data *tallies); ++int update_tally(int fd, struct tally_data *tallies); ++#endif +Index: Linux-PAM-1.3.0/modules/pam_faillock/main.c +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/main.c +@@ -0,0 +1,232 @@ ++/* ++ * Copyright (c) 2010 Tomas Mraz ++ * Copyright (c) 2010 Red Hat, Inc. ++ * ++ * 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. ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_LIBAUDIT ++#include ++ ++#define AUDIT_NO_ID ((unsigned int) -1) ++#endif ++ ++#include "faillock.h" ++ ++struct options { ++ unsigned int reset; ++ const char *dir; ++ const char *user; ++ const char *progname; ++}; ++ ++static int ++args_parse(int argc, char **argv, struct options *opts) ++{ ++ int i; ++ memset(opts, 0, sizeof(*opts)); ++ ++ opts->dir = FAILLOCK_DEFAULT_TALLYDIR; ++ opts->progname = argv[0]; ++ ++ for (i = 1; i < argc; ++i) { ++ ++ if (strcmp(argv[i], "--dir") == 0) { ++ ++i; ++ if (i >= argc || strlen(argv[i]) == 0) { ++ fprintf(stderr, "%s: No directory supplied.\n", argv[0]); ++ return -1; ++ } ++ opts->dir = argv[i]; ++ } ++ else if (strcmp(argv[i], "--user") == 0) { ++ ++i; ++ if (i >= argc || strlen(argv[i]) == 0) { ++ fprintf(stderr, "%s: No user name supplied.\n", argv[0]); ++ return -1; ++ } ++ opts->user = argv[i]; ++ } ++ else if (strcmp(argv[i], "--reset") == 0) { ++ opts->reset = 1; ++ } ++ else { ++ fprintf(stderr, "%s: Unknown option: %s\n", argv[0], argv[i]); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static void ++usage(const char *progname) ++{ ++ fprintf(stderr, _("Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n"), ++ progname); ++} ++ ++static int ++do_user(struct options *opts, const char *user) ++{ ++ int fd; ++ int rv; ++ struct tally_data tallies; ++ struct passwd *pwd; ++ ++ pwd = getpwnam(user); ++ ++ fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); ++ ++ if (fd == -1) { ++ if (errno == ENOENT) { ++ return 0; ++ } ++ else { ++ fprintf(stderr, "%s: Error opening the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++ return 3; ++ } ++ } ++ if (opts->reset) { ++#ifdef HAVE_LIBAUDIT ++ int audit_fd; ++#endif ++ ++ while ((rv=ftruncate(fd, 0)) == -1 && errno == EINTR); ++ if (rv == -1) { ++ fprintf(stderr, "%s: Error clearing the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++#ifdef HAVE_LIBAUDIT ++ } ++ if ((audit_fd=audit_open()) >= 0) { ++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL, ++ "faillock-reset", user, ++ pwd != NULL ? pwd->pw_uid : AUDIT_NO_ID, ++ NULL, NULL, NULL, rv == 0); ++ close(audit_fd); ++ } ++ if (rv == -1) { ++#endif ++ close(fd); ++ return 4; ++ } ++ } ++ else { ++ unsigned int i; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ if (read_tally(fd, &tallies) == -1) { ++ fprintf(stderr, "%s: Error reading the tally file for %s:", ++ opts->progname, user); ++ perror(NULL); ++ close(fd); ++ return 5; ++ } ++ ++ printf("%s:\n", user); ++ printf("%-19s %-5s %-48s %-5s\n", "When", "Type", "Source", "Valid"); ++ ++ for (i = 0; i < tallies.count; i++) { ++ struct tm *tm; ++ char timebuf[80]; ++ uint16_t status = tallies.records[i].status; ++ time_t when = tallies.records[i].time; ++ ++ tm = localtime(&when); ++ strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm); ++ printf("%-19s %-5s %-52.52s %s\n", timebuf, ++ status & TALLY_STATUS_RHOST ? "RHOST" : (status & TALLY_STATUS_TTY ? "TTY" : "SVC"), ++ tallies.records[i].source, status & TALLY_STATUS_VALID ? "V":"I"); ++ } ++ free(tallies.records); ++ } ++ close(fd); ++ return 0; ++} ++ ++static int ++do_allusers(struct options *opts) ++{ ++ struct dirent **userlist; ++ int rv, i; ++ ++ rv = scandir(opts->dir, &userlist, NULL, alphasort); ++ if (rv < 0) { ++ fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname); ++ return 2; ++ } ++ ++ for (i = 0; i < rv; i++) { ++ if (userlist[i]->d_name[0] == '.') { ++ if ((userlist[i]->d_name[1] == '.' && userlist[i]->d_name[2] == '\0') || ++ userlist[i]->d_name[1] == '\0') ++ continue; ++ } ++ do_user(opts, userlist[i]->d_name); ++ free(userlist[i]); ++ } ++ free(userlist); ++ ++ return 0; ++} ++ ++ ++/*-----------------------------------------------------------------------*/ ++int ++main (int argc, char *argv[]) ++{ ++ struct options opts; ++ ++ if (args_parse(argc, argv, &opts)) { ++ usage(argv[0]); ++ return 1; ++ } ++ ++ if (opts.user == NULL) { ++ return do_allusers(&opts); ++ } ++ ++ return do_user(&opts, opts.user); ++} +Index: Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8 +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8 +@@ -0,0 +1,262 @@ ++'\" t ++.\" Title: pam_faillock ++.\" Author: [see the "AUTHOR" section] ++.\" Generator: DocBook XSL Stylesheets v1.79.1 ++.\" Date: 11/25/2020 ++.\" Manual: Linux-PAM Manual ++.\" Source: Linux-PAM Manual ++.\" Language: English ++.\" ++.TH "PAM_FAILLOCK" "8" "11/25/2020" "Linux-PAM Manual" "Linux\-PAM Manual" ++.\" ----------------------------------------------------------------- ++.\" * Define some portability stuff ++.\" ----------------------------------------------------------------- ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.\" http://bugs.debian.org/507673 ++.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.ie \n(.g .ds Aq \(aq ++.el .ds Aq ' ++.\" ----------------------------------------------------------------- ++.\" * set default formatting ++.\" ----------------------------------------------------------------- ++.\" disable hyphenation ++.nh ++.\" disable justification (adjust text to left margin only) ++.ad l ++.\" ----------------------------------------------------------------- ++.\" * MAIN CONTENT STARTS HERE * ++.\" ----------------------------------------------------------------- ++.SH "NAME" ++pam_faillock \- Module counting authentication failures during a specified interval ++.SH "SYNOPSIS" ++.HP \w'\fBauth\ \&.\&.\&.\ pam_faillock\&.so\fR\ 'u ++\fBauth \&.\&.\&. pam_faillock\&.so\fR {preauth|authfail|authsucc} [conf=\fI/path/to/config\-file\fR] [dir=\fI/path/to/tally\-directory\fR] [even_deny_root] [deny=\fIn\fR] [fail_interval=\fIn\fR] [unlock_time=\fIn\fR] [root_unlock_time=\fIn\fR] [admin_group=\fIname\fR] [audit] [silent] [no_log_info] ++.HP \w'\fBaccount\ \&.\&.\&.\ pam_faillock\&.so\fR\ 'u ++\fBaccount \&.\&.\&. pam_faillock\&.so\fR [dir=\fI/path/to/tally\-directory\fR] [no_log_info] ++.SH "DESCRIPTION" ++.PP ++This module maintains a list of failed authentication attempts per user during a specified interval and locks the account in case there were more than ++\fIdeny\fR ++consecutive failed authentications\&. ++.PP ++Normally, failed attempts to authenticate ++\fIroot\fR ++will ++\fBnot\fR ++cause the root account to become blocked, to prevent denial\-of\-service: if your users aren\*(Aqt given shell accounts and root may only login via ++\fBsu\fR ++or at the machine console (not telnet/rsh, etc), this is safe\&. ++.SH "OPTIONS" ++.PP ++\fB{preauth|authfail|authsucc}\fR ++.RS 4 ++This argument must be set accordingly to the position of this module instance in the PAM stack\&. ++.sp ++The ++\fIpreauth\fR ++argument must be used when the module is called before the modules which ask for the user credentials such as the password\&. The module just examines whether the user should be blocked from accessing the service in case there were anomalous number of failed consecutive authentication attempts recently\&. This call is optional if ++\fIauthsucc\fR ++is used\&. ++.sp ++The ++\fIauthfail\fR ++argument must be used when the module is called after the modules which determine the authentication outcome, failed\&. Unless the user is already blocked due to previous authentication failures, the module will record the failure into the appropriate user tally file\&. ++.sp ++The ++\fIauthsucc\fR ++argument must be used when the module is called after the modules which determine the authentication outcome, succeeded\&. Unless the user is already blocked due to previous authentication failures, the module will then clear the record of the failures in the respective user tally file\&. Otherwise it will return authentication error\&. If this call is not done, the pam_faillock will not distinguish between consecutive and non\-consecutive failed authentication attempts\&. The ++\fIpreauth\fR ++call must be used in such case\&. Due to complications in the way the PAM stack can be configured it is also possible to call ++\fIpam_faillock\fR ++as an account module\&. In such configuration the module must be also called in the ++\fIpreauth\fR ++stage\&. ++.RE ++.PP ++\fBconf=/path/to/config\-file\fR ++.RS 4 ++Use another configuration file instead of the default ++/etc/security/faillock\&.conf\&. ++.RE ++.PP ++The options for configuring the module behavior are described in the ++\fBfaillock.conf\fR(5) ++manual page\&. The options specified on the module command line override the values from the configuration file\&. ++.SH "MODULE TYPES PROVIDED" ++.PP ++The ++\fBauth\fR ++and ++\fBaccount\fR ++module types are provided\&. ++.SH "RETURN VALUES" ++.PP ++PAM_AUTH_ERR ++.RS 4 ++An invalid option was given, the module was not able to retrieve the user name, no valid counter file was found, or too many failed logins\&. ++.RE ++.PP ++PAM_BUF_ERR ++.RS 4 ++Memory buffer error\&. ++.RE ++.PP ++PAM_CONV_ERR ++.RS 4 ++The conversation method supplied by the application failed to obtain the username\&. ++.RE ++.PP ++PAM_INCOMPLETE ++.RS 4 ++The conversation method supplied by the application returned PAM_CONV_AGAIN\&. ++.RE ++.PP ++PAM_SUCCESS ++.RS 4 ++Everything was successful\&. ++.RE ++.PP ++PAM_IGNORE ++.RS 4 ++User not present in passwd database\&. ++.RE ++.SH "NOTES" ++.PP ++Configuring options on the module command line is not recommend\&. The ++/etc/security/faillock\&.conf ++should be used instead\&. ++.PP ++The setup of ++\fIpam_faillock\fR ++in the PAM stack is different from the ++\fIpam_tally2\fR ++module setup\&. ++.PP ++Individual files with the failure records are created as owned by the user\&. This allows ++\fBpam_faillock\&.so\fR ++module to work correctly when it is called from a screensaver\&. ++.PP ++Note that using the module in ++\fBpreauth\fR ++without the ++\fBsilent\fR ++option specified in ++/etc/security/faillock\&.conf ++or with ++\fIrequisite\fR ++control field leaks an information about existence or non\-existence of a user account in the system because the failures are not recorded for the unknown users\&. The message about the user account being locked is never displayed for non\-existing user accounts allowing the adversary to infer that a particular account is not existing on a system\&. ++.SH "EXAMPLES" ++.PP ++Here are two possible configuration examples for ++/etc/pam\&.d/login\&. They make ++\fIpam_faillock\fR ++to lock the account after 4 consecutive failed logins during the default interval of 15 minutes\&. Root account will be locked as well\&. The accounts will be automatically unlocked after 20 minutes\&. ++.PP ++In the first example the module is called only in the ++\fIauth\fR ++phase and the module does not print any information about the account being blocked by ++\fIpam_faillock\fR\&. The ++\fIpreauth\fR ++call can be added to tell users that their logins are blocked by the module and also to abort the authentication without even asking for password in such case\&. ++.PP ++/etc/security/faillock\&.conf ++file example: ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++deny=4 ++unlock_time=1200 ++silent ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.PP ++/etc/pam\&.d/config file example: ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++auth required pam_securetty\&.so ++auth required pam_env\&.so ++auth required pam_nologin\&.so ++# optionally call: auth requisite pam_faillock\&.so preauth ++# to display the message about account being locked ++auth [success=1 default=bad] pam_unix\&.so ++auth [default=die] pam_faillock\&.so authfail ++auth sufficient pam_faillock\&.so authsucc ++auth required pam_deny\&.so ++account required pam_unix\&.so ++password required pam_unix\&.so shadow ++session required pam_selinux\&.so close ++session required pam_loginuid\&.so ++session required pam_unix\&.so ++session required pam_selinux\&.so open ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.PP ++In the second example the module is called both in the ++\fIauth\fR ++and ++\fIaccount\fR ++phases and the module informs the authenticating user when the account is locked if ++\fBsilent\fR ++option is not specified in the ++faillock\&.conf\&. ++.sp ++.if n \{\ ++.RS 4 ++.\} ++.nf ++auth required pam_securetty\&.so ++auth required pam_env\&.so ++auth required pam_nologin\&.so ++auth required pam_faillock\&.so preauth ++# optionally use requisite above if you do not want to prompt for the password ++# on locked accounts ++auth sufficient pam_unix\&.so ++auth [default=die] pam_faillock\&.so authfail ++auth required pam_deny\&.so ++account required pam_faillock\&.so ++# if you drop the above call to pam_faillock\&.so the lock will be done also ++# on non\-consecutive authentication failures ++account required pam_unix\&.so ++password required pam_unix\&.so shadow ++session required pam_selinux\&.so close ++session required pam_loginuid\&.so ++session required pam_unix\&.so ++session required pam_selinux\&.so open ++ ++.fi ++.if n \{\ ++.RE ++.\} ++.SH "FILES" ++.PP ++/var/run/faillock/* ++.RS 4 ++the files logging the authentication failures for users ++.RE ++.PP ++/etc/security/faillock\&.conf ++.RS 4 ++the config file for pam_faillock options ++.RE ++.SH "SEE ALSO" ++.PP ++\fBfaillock\fR(8), ++\fBfaillock.conf\fR(5), ++\fBpam.conf\fR(5), ++\fBpam.d\fR(5), ++\fBpam\fR(8) ++.SH "AUTHOR" ++.PP ++pam_faillock was written by Tomas Mraz\&. +Index: Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml +@@ -0,0 +1,362 @@ ++ ++ ++ ++ ++ ++ ++ pam_faillock ++ 8 ++ Linux-PAM Manual ++ ++ ++ ++ pam_faillock ++ Module counting authentication failures during a specified interval ++ ++ ++ ++ ++ auth ... pam_faillock.so ++ ++ preauth|authfail|authsucc ++ ++ ++ conf=/path/to/config-file ++ ++ ++ dir=/path/to/tally-directory ++ ++ ++ even_deny_root ++ ++ ++ deny=n ++ ++ ++ fail_interval=n ++ ++ ++ unlock_time=n ++ ++ ++ root_unlock_time=n ++ ++ ++ admin_group=name ++ ++ ++ audit ++ ++ ++ silent ++ ++ ++ no_log_info ++ ++ ++ ++ account ... pam_faillock.so ++ ++ dir=/path/to/tally-directory ++ ++ ++ no_log_info ++ ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ ++ This module maintains a list of failed authentication attempts per ++ user during a specified interval and locks the account in case ++ there were more than deny consecutive ++ failed authentications. ++ ++ ++ Normally, failed attempts to authenticate root will ++ not cause the root account to become ++ blocked, to prevent denial-of-service: if your users aren't given ++ shell accounts and root may only login via su or ++ at the machine console (not telnet/rsh, etc), this is safe. ++ ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ ++ This argument must be set accordingly to the position of this module ++ instance in the PAM stack. ++ ++ ++ The preauth argument must be used when the module ++ is called before the modules which ask for the user credentials such ++ as the password. The module just examines whether the user should ++ be blocked from accessing the service in case there were anomalous ++ number of failed consecutive authentication attempts recently. This ++ call is optional if authsucc is used. ++ ++ ++ The authfail argument must be used when the module ++ is called after the modules which determine the authentication outcome, ++ failed. Unless the user is already blocked due to previous authentication ++ failures, the module will record the failure into the appropriate user ++ tally file. ++ ++ ++ The authsucc argument must be used when the module ++ is called after the modules which determine the authentication outcome, ++ succeeded. Unless the user is already blocked due to previous authentication ++ failures, the module will then clear the record of the failures in the ++ respective user tally file. Otherwise it will return authentication error. ++ If this call is not done, the pam_faillock will not distinguish between ++ consecutive and non-consecutive failed authentication attempts. The ++ preauth call must be used in such case. Due to ++ complications in the way the PAM stack can be configured it is also ++ possible to call pam_faillock as an account module. ++ In such configuration the module must be also called in the ++ preauth stage. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Use another configuration file instead of the default ++ /etc/security/faillock.conf. ++ ++ ++ ++ ++ ++ The options for configuring the module behavior are described in the ++ faillock.conf5 ++ manual page. The options specified on the module command ++ line override the values from the configuration file. ++ ++ ++ ++ ++ MODULE TYPES PROVIDED ++ ++ The and module types are ++ provided. ++ ++ ++ ++ ++ RETURN VALUES ++ ++ ++ PAM_AUTH_ERR ++ ++ ++ An invalid option was given, the module was not able ++ to retrieve the user name, no valid counter file ++ was found, or too many failed logins. ++ ++ ++ ++ ++ PAM_BUF_ERR ++ ++ ++ Memory buffer error. ++ ++ ++ ++ ++ PAM_CONV_ERR ++ ++ ++ The conversation method supplied by the application ++ failed to obtain the username. ++ ++ ++ ++ ++ PAM_INCOMPLETE ++ ++ ++ The conversation method supplied by the application ++ returned PAM_CONV_AGAIN. ++ ++ ++ ++ ++ PAM_SUCCESS ++ ++ ++ Everything was successful. ++ ++ ++ ++ ++ PAM_IGNORE ++ ++ ++ User not present in passwd database. ++ ++ ++ ++ ++ ++ ++ ++ NOTES ++ ++ Configuring options on the module command line is not recommend. The ++ /etc/security/faillock.conf should be used instead. ++ ++ ++ The setup of pam_faillock in the PAM stack is different ++ from the pam_tally2 module setup. ++ ++ ++ Individual files with the failure records are created as owned by ++ the user. This allows pam_faillock.so module ++ to work correctly when it is called from a screensaver. ++ ++ ++ Note that using the module in without the ++ option specified in /etc/security/faillock.conf ++ or with requisite control field leaks an information about ++ existence or non-existence of a user account in the system because ++ the failures are not recorded for the unknown users. The message ++ about the user account being locked is never displayed for non-existing ++ user accounts allowing the adversary to infer that a particular account ++ is not existing on a system. ++ ++ ++ ++ ++ EXAMPLES ++ ++ Here are two possible configuration examples for /etc/pam.d/login. ++ They make pam_faillock to lock the account after 4 consecutive ++ failed logins during the default interval of 15 minutes. Root account will be locked ++ as well. The accounts will be automatically unlocked after 20 minutes. ++ ++ ++ In the first example the module is called only in the auth ++ phase and the module does not print any information about the account being blocked ++ by pam_faillock. The preauth call can ++ be added to tell users that their logins are blocked by the module and also to abort ++ the authentication without even asking for password in such case. ++ ++ ++ /etc/security/faillock.conf file example: ++ ++ ++deny=4 ++unlock_time=1200 ++silent ++ ++ ++ /etc/pam.d/config file example: ++ ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++# optionally call: auth requisite pam_faillock.so preauth ++# to display the message about account being locked ++auth [success=1 default=bad] pam_unix.so ++auth [default=die] pam_faillock.so authfail ++auth sufficient pam_faillock.so authsucc ++auth required pam_deny.so ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++ In the second example the module is called both in the auth ++ and account phases and the module informs the authenticating ++ user when the account is locked if option is not ++ specified in the faillock.conf. ++ ++ ++auth required pam_securetty.so ++auth required pam_env.so ++auth required pam_nologin.so ++auth required pam_faillock.so preauth ++# optionally use requisite above if you do not want to prompt for the password ++# on locked accounts ++auth sufficient pam_unix.so ++auth [default=die] pam_faillock.so authfail ++auth required pam_deny.so ++account required pam_faillock.so ++# if you drop the above call to pam_faillock.so the lock will be done also ++# on non-consecutive authentication failures ++account required pam_unix.so ++password required pam_unix.so shadow ++session required pam_selinux.so close ++session required pam_loginuid.so ++session required pam_unix.so ++session required pam_selinux.so open ++ ++ ++ ++ ++ FILES ++ ++ ++ /var/run/faillock/* ++ ++ the files logging the authentication failures for users ++ ++ ++ ++ /etc/security/faillock.conf ++ ++ the config file for pam_faillock options ++ ++ ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ faillock8 ++ , ++ ++ faillock.conf5 ++ , ++ ++ pam.conf5 ++ , ++ ++ pam.d5 ++ , ++ ++ pam8 ++ ++ ++ ++ ++ ++ AUTHOR ++ ++ pam_faillock was written by Tomas Mraz. ++ ++ ++ ++ +Index: Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c +@@ -0,0 +1,750 @@ ++/* ++ * Copyright (c) 2010, 2017, 2019 Tomas Mraz ++ * Copyright (c) 2010, 2017, 2019 Red Hat, Inc. ++ * ++ * 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. ++ */ ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_LIBAUDIT ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include "pam_inline.h" ++#include "faillock.h" ++ ++#define FAILLOCK_ACTION_PREAUTH 0 ++#define FAILLOCK_ACTION_AUTHSUCC 1 ++#define FAILLOCK_ACTION_AUTHFAIL 2 ++ ++#define FAILLOCK_FLAG_DENY_ROOT 0x1 ++#define FAILLOCK_FLAG_AUDIT 0x2 ++#define FAILLOCK_FLAG_SILENT 0x4 ++#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 ++#define FAILLOCK_FLAG_UNLOCKED 0x10 ++#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 ++#define FAILLOCK_FLAG_NO_DELAY 0x40 ++ ++#define MAX_TIME_INTERVAL 604800 /* 7 days */ ++#define FAILLOCK_CONF_MAX_LINELEN 1023 ++ ++static const char default_faillock_conf[] = FAILLOCK_DEFAULT_CONF; ++ ++struct options { ++ unsigned int action; ++ unsigned int flags; ++ unsigned short deny; ++ unsigned int fail_interval; ++ unsigned int unlock_time; ++ unsigned int root_unlock_time; ++ char *dir; ++ const char *user; ++ char *admin_group; ++ int failures; ++ uint64_t latest_time; ++ uid_t uid; ++ int is_admin; ++ uint64_t now; ++ int fatal_error; ++}; ++ ++static int read_config_file( ++ pam_handle_t *pamh, ++ struct options *opts, ++ const char *cfgfile ++); ++ ++static void set_conf_opt( ++ pam_handle_t *pamh, ++ struct options *opts, ++ const char *name, ++ const char *value ++); ++ ++static int ++args_parse(pam_handle_t *pamh, int argc, const char **argv, ++ int flags, struct options *opts) ++{ ++ int i; ++ int config_arg_index = -1; ++ int rv; ++ const char *conf = default_faillock_conf; ++ ++ memset(opts, 0, sizeof(*opts)); ++ ++ opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR); ++ opts->deny = 3; ++ opts->fail_interval = 900; ++ opts->unlock_time = 600; ++ opts->root_unlock_time = MAX_TIME_INTERVAL+1; ++ ++ for (i = 0; i < argc; ++i) { ++ const char *str = pam_str_skip_prefix(argv[i], "conf="); ++ ++ if (str != NULL) { ++ conf = str; ++ config_arg_index = i; ++ } ++ } ++ ++ if ((rv = read_config_file(pamh, opts, conf)) != PAM_SUCCESS) { ++ pam_syslog(pamh, LOG_ERR, ++ "Configuration file missing or broken"); ++ return rv; ++ } ++ ++ for (i = 0; i < argc; ++i) { ++ if (i == config_arg_index) { ++ continue; ++ } ++ else if (strcmp(argv[i], "preauth") == 0) { ++ opts->action = FAILLOCK_ACTION_PREAUTH; ++ } ++ else if (strcmp(argv[i], "authfail") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHFAIL; ++ } ++ else if (strcmp(argv[i], "authsucc") == 0) { ++ opts->action = FAILLOCK_ACTION_AUTHSUCC; ++ } ++ else { ++ char buf[FAILLOCK_CONF_MAX_LINELEN + 1]; ++ char *val; ++ ++ strncpy(buf, argv[i], sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ ++ val = strchr(buf, '='); ++ if (val != NULL) { ++ *val = '\0'; ++ ++val; ++ } ++ else { ++ val = buf + sizeof(buf) - 1; ++ } ++ set_conf_opt(pamh, opts, buf, val); ++ } ++ } ++ ++ if (opts->root_unlock_time == MAX_TIME_INTERVAL+1) ++ opts->root_unlock_time = opts->unlock_time; ++ if (flags & PAM_SILENT) ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ ++ if (opts->dir == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); ++ opts->fatal_error = 1; ++ } ++ ++ if (opts->fatal_error) ++ return PAM_BUF_ERR; ++ return PAM_SUCCESS; ++} ++ ++/* parse a single configuration file */ ++static int ++read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) ++{ ++ FILE *f; ++ char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; ++ ++ f = fopen(cfgfile, "r"); ++ if (f == NULL) { ++ /* ignore non-existent default config file */ ++ if (errno == ENOENT && cfgfile == default_faillock_conf) ++ return PAM_SUCCESS; ++ return PAM_SERVICE_ERR; ++ } ++ ++ while (fgets(linebuf, sizeof(linebuf), f) != NULL) { ++ size_t len; ++ char *ptr; ++ char *name; ++ int eq; ++ ++ len = strlen(linebuf); ++ /* len cannot be 0 unless there is a bug in fgets */ ++ if (len && linebuf[len - 1] != '\n' && !feof(f)) { ++ (void) fclose(f); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if ((ptr=strchr(linebuf, '#')) != NULL) { ++ *ptr = '\0'; ++ } else { ++ ptr = linebuf + len; ++ } ++ ++ /* drop terminating whitespace including the \n */ ++ while (ptr > linebuf) { ++ if (!isspace(*(ptr-1))) { ++ *ptr = '\0'; ++ break; ++ } ++ --ptr; ++ } ++ ++ /* skip initial whitespace */ ++ for (ptr = linebuf; isspace(*ptr); ptr++); ++ if (*ptr == '\0') ++ continue; ++ ++ /* grab the key name */ ++ eq = 0; ++ name = ptr; ++ while (*ptr != '\0') { ++ if (isspace(*ptr) || *ptr == '=') { ++ eq = *ptr == '='; ++ *ptr = '\0'; ++ ++ptr; ++ break; ++ } ++ ++ptr; ++ } ++ ++ /* grab the key value */ ++ while (*ptr != '\0') { ++ if (*ptr != '=' || eq) { ++ if (!isspace(*ptr)) { ++ break; ++ } ++ } else { ++ eq = 1; ++ } ++ ++ptr; ++ } ++ ++ /* set the key:value pair on opts */ ++ set_conf_opt(pamh, opts, name, ptr); ++ } ++ ++ (void)fclose(f); ++ return PAM_SUCCESS; ++} ++ ++static void ++set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value) ++{ ++ if (strcmp(name, "dir") == 0) { ++ if (value[0] != '/') { ++ pam_syslog(pamh, LOG_ERR, ++ "Tally directory is not absolute path (%s); keeping default", value); ++ } else { ++ free(opts->dir); ++ opts->dir = strdup(value); ++ } ++ } ++ else if (strcmp(name, "deny") == 0) { ++ if (sscanf(value, "%hu", &opts->deny) != 1) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for deny argument"); ++ } ++ } ++ else if (strcmp(name, "fail_interval") == 0) { ++ unsigned int temp; ++ if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for fail_interval argument"); ++ } else { ++ opts->fail_interval = temp; ++ } ++ } ++ else if (strcmp(name, "unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->unlock_time = 0; ++ } ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for unlock_time argument"); ++ } ++ else { ++ opts->unlock_time = temp; ++ } ++ } ++ else if (strcmp(name, "root_unlock_time") == 0) { ++ unsigned int temp; ++ ++ if (strcmp(value, "never") == 0) { ++ opts->root_unlock_time = 0; ++ } ++ else if (sscanf(value, "%u", &temp) != 1 || ++ temp > MAX_TIME_INTERVAL) { ++ pam_syslog(pamh, LOG_ERR, ++ "Bad number supplied for root_unlock_time argument"); ++ } else { ++ opts->root_unlock_time = temp; ++ } ++ } ++ else if (strcmp(name, "admin_group") == 0) { ++ free(opts->admin_group); ++ opts->admin_group = strdup(value); ++ if (opts->admin_group == NULL) { ++ opts->fatal_error = 1; ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); ++ } ++ } ++ else if (strcmp(name, "even_deny_root") == 0) { ++ opts->flags |= FAILLOCK_FLAG_DENY_ROOT; ++ } ++ else if (strcmp(name, "audit") == 0) { ++ opts->flags |= FAILLOCK_FLAG_AUDIT; ++ } ++ else if (strcmp(name, "silent") == 0) { ++ opts->flags |= FAILLOCK_FLAG_SILENT; ++ } ++ else if (strcmp(name, "no_log_info") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; ++ } ++ else if (strcmp(name, "local_users_only") == 0) { ++ opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; ++ } ++ else if (strcmp(name, "nodelay") == 0) { ++ opts->flags |= FAILLOCK_FLAG_NO_DELAY; ++ } ++ else { ++ pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name); ++ } ++} ++ ++static int ++check_local_user (pam_handle_t *pamh, const char *user) ++{ ++ return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS; ++} ++ ++static int ++get_pam_user(pam_handle_t *pamh, struct options *opts) ++{ ++ const char *user; ++ int rv; ++ struct passwd *pwd; ++ ++ if ((rv=pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { ++ return rv == PAM_CONV_AGAIN ? PAM_INCOMPLETE : rv; ++ } ++ ++ if (*user == '\0') { ++ return PAM_IGNORE; ++ } ++ ++ if ((pwd=pam_modutil_getpwnam(pamh, user)) == NULL) { ++ if (opts->flags & FAILLOCK_FLAG_AUDIT) { ++ pam_syslog(pamh, LOG_NOTICE, "User unknown: %s", user); ++ } ++ else { ++ pam_syslog(pamh, LOG_NOTICE, "User unknown"); ++ } ++ return PAM_IGNORE; ++ } ++ opts->user = user; ++ opts->uid = pwd->pw_uid; ++ ++ if (pwd->pw_uid == 0) { ++ opts->is_admin = 1; ++ return PAM_SUCCESS; ++ } ++ ++ if (opts->admin_group && *opts->admin_group) { ++ opts->is_admin = pam_modutil_user_in_group_uid_nam(pamh, ++ pwd->pw_uid, opts->admin_group); ++ } ++ ++ return PAM_SUCCESS; ++} ++ ++static int ++check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies, int *fd) ++{ ++ int tfd; ++ unsigned int i; ++ uint64_t latest_time; ++ int failures; ++ ++ opts->now = time(NULL); ++ ++ tfd = open_tally(opts->dir, opts->user, opts->uid, 0); ++ ++ *fd = tfd; ++ ++ if (tfd == -1) { ++ if (errno == EACCES || errno == ENOENT) { ++ return PAM_SUCCESS; ++ } ++ pam_syslog(pamh, LOG_ERR, "Error opening the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ if (read_tally(tfd, tallies) != 0) { ++ pam_syslog(pamh, LOG_ERR, "Error reading the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ if (opts->is_admin && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ return PAM_SUCCESS; ++ } ++ ++ latest_time = 0; ++ for (i = 0; i < tallies->count; i++) { ++ if ((tallies->records[i].status & TALLY_STATUS_VALID) && ++ tallies->records[i].time > latest_time) ++ latest_time = tallies->records[i].time; ++ } ++ ++ opts->latest_time = latest_time; ++ ++ failures = 0; ++ for (i = 0; i < tallies->count; i++) { ++ if ((tallies->records[i].status & TALLY_STATUS_VALID) && ++ latest_time - tallies->records[i].time < opts->fail_interval) { ++ ++failures; ++ } ++ } ++ ++ opts->failures = failures; ++ ++ if (opts->deny && failures >= opts->deny) { ++ if ((!opts->is_admin && opts->unlock_time && latest_time + opts->unlock_time < opts->now) || ++ (opts->is_admin && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) { ++#ifdef HAVE_LIBAUDIT ++ if (opts->action != FAILLOCK_ACTION_PREAUTH) { /* do not audit in preauth */ ++ char buf[64]; ++ int audit_fd; ++ const void *rhost = NULL, *tty = NULL; ++ ++ 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); ++ snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid); ++ audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, ++ rhost, NULL, tty, 1); ++ } ++#endif ++ opts->flags |= FAILLOCK_FLAG_UNLOCKED; ++ return PAM_SUCCESS; ++ } ++ return PAM_AUTH_ERR; ++ } ++ return PAM_SUCCESS; ++} ++ ++static void ++reset_tally(pam_handle_t *pamh, struct options *opts, int *fd) ++{ ++ int rv; ++ ++ if (*fd == -1) { ++ *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ } ++ else { ++ while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR); ++ if (rv == -1) { ++ pam_syslog(pamh, LOG_ERR, "Error clearing the tally file for %s: %m", opts->user); ++ } ++ } ++} ++ ++static int ++write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies, int *fd) ++{ ++ struct tally *records; ++ unsigned int i; ++ int failures; ++ unsigned int oldest; ++ uint64_t oldtime; ++ const void *source = NULL; ++ ++ if (*fd == -1) { ++ *fd = open_tally(opts->dir, opts->user, opts->uid, 1); ++ } ++ if (*fd == -1) { ++ if (errno == EACCES) { ++ return PAM_SUCCESS; ++ } ++ pam_syslog(pamh, LOG_ERR, "Error opening the tally file for %s: %m", opts->user); ++ return PAM_SYSTEM_ERR; ++ } ++ ++ oldtime = 0; ++ oldest = 0; ++ failures = 0; ++ ++ for (i = 0; i < tallies->count; ++i) { ++ if (oldtime == 0 || tallies->records[i].time < oldtime) { ++ oldtime = tallies->records[i].time; ++ oldest = i; ++ } ++ if (opts->flags & FAILLOCK_FLAG_UNLOCKED || ++ opts->now - tallies->records[i].time >= opts->fail_interval ) { ++ tallies->records[i].status &= ~TALLY_STATUS_VALID; ++ } else { ++ ++failures; ++ } ++ } ++ ++ if (oldest >= tallies->count || (tallies->records[oldest].status & TALLY_STATUS_VALID)) { ++ oldest = tallies->count; ++ ++ if ((records=realloc(tallies->records, (oldest+1) * sizeof (*tallies->records))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "Error allocating memory for tally records: %m"); ++ return PAM_BUF_ERR; ++ } ++ ++ ++tallies->count; ++ tallies->records = records; ++ } ++ ++ memset(&tallies->records[oldest], 0, sizeof (*tallies->records)); ++ ++ tallies->records[oldest].status = TALLY_STATUS_VALID; ++ if (pam_get_item(pamh, PAM_RHOST, &source) != PAM_SUCCESS || source == NULL) { ++ if (pam_get_item(pamh, PAM_TTY, &source) != PAM_SUCCESS || source == NULL) { ++ if (pam_get_item(pamh, PAM_SERVICE, &source) != PAM_SUCCESS || source == NULL) { ++ source = ""; ++ } ++ } ++ else { ++ tallies->records[oldest].status |= TALLY_STATUS_TTY; ++ } ++ } ++ else { ++ tallies->records[oldest].status |= TALLY_STATUS_RHOST; ++ } ++ ++ strncpy(tallies->records[oldest].source, source, sizeof(tallies->records[oldest].source)); ++ /* source does not have to be null terminated */ ++ ++ tallies->records[oldest].time = opts->now; ++ ++ ++failures; ++ ++ if (opts->deny && failures == opts->deny) { ++#ifdef HAVE_LIBAUDIT ++ char buf[64]; ++ int audit_fd; ++ ++ 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; ++ ++ snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid); ++ audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf, ++ NULL, NULL, NULL, 1); ++ ++ if (!opts->is_admin || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) { ++ audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf, ++ NULL, NULL, NULL, 1); ++ } ++ close(audit_fd); ++#endif ++ if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO)) { ++ pam_syslog(pamh, LOG_INFO, "Consecutive login failures for user %s account temporarily locked", ++ opts->user); ++ } ++ } ++ ++ if (update_tally(*fd, tallies) == 0) ++ return PAM_SUCCESS; ++ ++ return PAM_SYSTEM_ERR; ++} ++ ++static void ++faillock_message(pam_handle_t *pamh, struct options *opts) ++{ ++ int64_t left; ++ ++ if (!(opts->flags & FAILLOCK_FLAG_SILENT)) { ++ if (opts->is_admin) { ++ left = opts->latest_time + opts->root_unlock_time - opts->now; ++ } ++ else { ++ left = opts->latest_time + opts->unlock_time - opts->now; ++ } ++ ++ pam_info(pamh, _("The account is locked due to %u failed logins."), ++ (unsigned int)opts->failures); ++ if (left > 0) { ++ left = (left + 59)/60; /* minutes */ ++ ++ pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); ++ } ++ } ++} ++ ++static void ++tally_cleanup(struct tally_data *tallies, int fd) ++{ ++ if (fd != -1) { ++ close(fd); ++ } ++ ++ free(tallies->records); ++} ++ ++static void ++opts_cleanup(struct options *opts) ++{ ++ free(opts->dir); ++ free(opts->admin_group); ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++int ++pam_sm_authenticate(pam_handle_t *pamh, int flags, ++ int argc, const char **argv) ++{ ++ struct options opts; ++ int rv, fd = -1; ++ struct tally_data tallies; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ ++ rv = args_parse(pamh, argc, argv, flags, &opts); ++ if (rv != PAM_SUCCESS) ++ goto err; ++ ++ if (!(opts.flags & FAILLOCK_FLAG_NO_DELAY)) { ++ pam_fail_delay(pamh, 2000000); /* 2 sec delay on failure */ ++ } ++ ++ if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { ++ goto err; ++ } ++ ++ if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) || ++ check_local_user (pamh, opts.user) != 0) { ++ switch (opts.action) { ++ case FAILLOCK_ACTION_PREAUTH: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_AUTH_ERR && !(opts.flags & FAILLOCK_FLAG_SILENT)) { ++ faillock_message(pamh, &opts); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHSUCC: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ reset_tally(pamh, &opts, &fd); ++ } ++ break; ++ ++ case FAILLOCK_ACTION_AUTHFAIL: ++ rv = check_tally(pamh, &opts, &tallies, &fd); ++ if (rv == PAM_SUCCESS) { ++ rv = PAM_IGNORE; /* this return value should be ignored */ ++ write_tally(pamh, &opts, &tallies, &fd); ++ } ++ break; ++ } ++ } ++ ++ tally_cleanup(&tallies, fd); ++ ++err: ++ opts_cleanup(&opts); ++ ++ return rv; ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++int ++pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, ++ int argc UNUSED, const char **argv UNUSED) ++{ ++ return PAM_SUCCESS; ++} ++ ++/*---------------------------------------------------------------------*/ ++ ++int ++pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, ++ int argc, const char **argv) ++{ ++ struct options opts; ++ int rv, fd = -1; ++ struct tally_data tallies; ++ ++ memset(&tallies, 0, sizeof(tallies)); ++ ++ rv = args_parse(pamh, argc, argv, flags, &opts); ++ ++ if (rv != PAM_SUCCESS) ++ goto err; ++ ++ opts.action = FAILLOCK_ACTION_AUTHSUCC; ++ ++ if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { ++ goto err; ++ } ++ ++ if (!(opts.flags & FAILLOCK_FLAG_LOCAL_ONLY) || ++ check_local_user (pamh, opts.user) != 0) { ++ check_tally(pamh, &opts, &tallies, &fd); /* for auditing */ ++ reset_tally(pamh, &opts, &fd); ++ } ++ ++ tally_cleanup(&tallies, fd); ++ ++err: ++ opts_cleanup(&opts); ++ ++ return rv; ++} ++ ++/*-----------------------------------------------------------------------*/ +Index: Linux-PAM-1.3.0/modules/pam_faillock/tst-pam_faillock +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/modules/pam_faillock/tst-pam_faillock +@@ -0,0 +1,2 @@ ++#!/bin/sh ++../../tests/tst-dlopen .libs/pam_faillock.so +Index: Linux-PAM-1.3.0/doc/sag/pam_faillock.xml +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/doc/sag/pam_faillock.xml +@@ -0,0 +1,38 @@ ++ ++ ++
++ pam_faillock - temporarily locking access based on failed authentication attempts during an interval ++ ++ ++ ++ ++ ++ ++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
++ ++
++
+Index: Linux-PAM-1.3.0/libpam/include/pam_cc_compat.h +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/libpam/include/pam_cc_compat.h +@@ -0,0 +1,66 @@ ++/* ++ * Copyright (c) 2020 Dmitry V. Levin ++ */ ++ ++#ifndef PAM_CC_COMPAT_H ++#define PAM_CC_COMPAT_H ++ ++#include "config.h" ++#include ++ ++#if defined __clang__ && defined __clang_major__ && defined __clang_minor__ ++# define PAM_CLANG_PREREQ(maj, min) \ ++ ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) ++#else ++# define PAM_CLANG_PREREQ(maj, min) 0 ++#endif ++ ++#if PAM_GNUC_PREREQ(2, 7) ++# define PAM_ATTRIBUTE_ALIGNED(arg) __attribute__((__aligned__(arg))) ++#else ++# define PAM_ATTRIBUTE_ALIGNED(arg) /* empty */ ++#endif ++ ++#if PAM_GNUC_PREREQ(4, 6) ++# define DIAG_PUSH_IGNORE_CAST_QUAL \ ++ _Pragma("GCC diagnostic push"); \ ++ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") ++# define DIAG_POP_IGNORE_CAST_QUAL \ ++ _Pragma("GCC diagnostic pop") ++# define DIAG_PUSH_IGNORE_CAST_ALIGN \ ++ _Pragma("GCC diagnostic push"); \ ++ _Pragma("GCC diagnostic ignored \"-Wcast-align\"") ++# define DIAG_POP_IGNORE_CAST_ALIGN \ ++ _Pragma("GCC diagnostic pop") ++#elif PAM_CLANG_PREREQ(2, 6) ++# define DIAG_PUSH_IGNORE_CAST_QUAL \ ++ _Pragma("clang diagnostic push"); \ ++ _Pragma("clang diagnostic ignored \"-Wcast-qual\"") ++# define DIAG_POP_IGNORE_CAST_QUAL \ ++ _Pragma("clang diagnostic pop") ++# define DIAG_PUSH_IGNORE_CAST_ALIGN \ ++ _Pragma("clang diagnostic push"); \ ++ _Pragma("clang diagnostic ignored \"-Wcast-align\"") ++# define DIAG_POP_IGNORE_CAST_ALIGN \ ++ _Pragma("clang diagnostic pop") ++#else ++# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */ ++# define DIAG_POP_IGNORE_CAST_QUAL /* empty */ ++# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */ ++# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */ ++#endif ++ ++/* ++ * Evaluates to ++ * 1, if the given two types are known to be the same ++ * 0, otherwise. ++ */ ++#if PAM_GNUC_PREREQ(3, 0) ++# define PAM_IS_SAME_TYPE(x_, y_) \ ++ __builtin_types_compatible_p(__typeof__(x_), __typeof__(y_)) ++#else ++/* Cannot tell whether these types are the same. */ ++# define PAM_IS_SAME_TYPE(x_, y_) 0 ++#endif ++ ++#endif /* PAM_CC_COMPAT_H */ +Index: Linux-PAM-1.3.0/libpam/include/pam_inline.h +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/libpam/include/pam_inline.h +@@ -0,0 +1,118 @@ ++/* ++ * Copyright (c) 2020 Dmitry V. Levin ++ * ++ * Handy inline functions and macros providing some convenient functionality ++ * to libpam and its modules. ++ */ ++ ++#ifndef PAM_INLINE_H ++#define PAM_INLINE_H ++ ++#include "pam_cc_compat.h" ++#include ++#include ++#include ++ ++/* ++ * Evaluates to ++ * - a syntax error if the argument is 0, ++ * 0, otherwise. ++ */ ++#define PAM_FAIL_BUILD_ON_ZERO(e_) (sizeof(int[-1 + 2 * !!(e_)]) * 0) ++ ++/* ++ * Evaluates to ++ * 1, if the given type is known to be a non-array type ++ * 0, otherwise. ++ */ ++#define PAM_IS_NOT_ARRAY(a_) PAM_IS_SAME_TYPE((a_), &(a_)[0]) ++ ++/* ++ * Evaluates to ++ * - a syntax error if the argument is not an array, ++ * 0, otherwise. ++ */ ++#define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_)) ++ ++/* Evaluates to the number of elements in the specified array. */ ++#define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_)) ++ ++/* ++ * Returns NULL if STR does not start with PREFIX, ++ * or a pointer to the first char in STR after PREFIX. ++ * The length of PREFIX is specified by PREFIX_LEN. ++ */ ++static inline const char * ++pam_str_skip_prefix_len(const char *str, const char *prefix, size_t prefix_len) ++{ ++ return strncmp(str, prefix, prefix_len) ? NULL : str + prefix_len; ++} ++ ++#define pam_str_skip_prefix(str_, prefix_) \ ++ pam_str_skip_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) ++ ++/* ++ * Returns NULL if STR does not start with PREFIX ++ * (ignoring the case of the characters), ++ * or a pointer to the first char in STR after PREFIX. ++ * The length of PREFIX is specified by PREFIX_LEN. ++ */ ++static inline const char * ++pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix_len) ++{ ++ return strncasecmp(str, prefix, prefix_len) ? NULL : str + prefix_len; ++} ++ ++#define pam_str_skip_icase_prefix(str_, prefix_) \ ++ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_)) ++ ++static inline int ++pam_read_passwords(int fd, int npass, char **passwords) ++{ ++ /* ++ * The passwords array must contain npass preallocated ++ * buffers of length PAM_MAX_RESP_SIZE + 1. ++ */ ++ int rbytes = 0; ++ int offset = 0; ++ int i = 0; ++ char *pptr; ++ while (npass > 0) { ++ rbytes = read(fd, passwords[i]+offset, PAM_MAX_RESP_SIZE+1-offset); ++ ++ if (rbytes < 0) { ++ if (errno == EINTR) { ++ continue; ++ } ++ break; ++ } ++ if (rbytes == 0) { ++ break; ++ } ++ ++ while (npass > 0 && ++ (pptr = memchr(passwords[i] + offset, '\0', rbytes)) != NULL) { ++ ++pptr; /* skip the '\0' */ ++ rbytes -= pptr - (passwords[i] + offset); ++ i++; ++ offset = 0; ++ npass--; ++ if (rbytes > 0) { ++ if (npass > 0) { ++ memcpy(passwords[i], pptr, rbytes); ++ } ++ memset(pptr, '\0', rbytes); ++ } ++ } ++ offset += rbytes; ++ } ++ ++ /* clear up */ ++ if (offset > 0 && npass > 0) { ++ memset(passwords[i], '\0', offset); ++ } ++ ++ return i; ++} ++ ++#endif /* PAM_INLINE_H */ +Index: Linux-PAM-1.3.0/libpam/pam_modutil_check_user.c +=================================================================== +--- /dev/null ++++ Linux-PAM-1.3.0/libpam/pam_modutil_check_user.c +@@ -0,0 +1,92 @@ ++#include "pam_modutil_private.h" ++#include ++ ++#include ++#include ++#include ++ ++int ++pam_modutil_check_user_in_passwd(pam_handle_t *pamh, ++ const char *user_name, ++ const char *file_name) ++{ ++ int rc; ++ size_t user_len; ++ FILE *fp; ++ char line[BUFSIZ]; ++ ++ /* Validate the user name. */ ++ if ((user_len = strlen(user_name)) == 0) { ++ pam_syslog(pamh, LOG_NOTICE, "user name is not valid"); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if (user_len > sizeof(line) - sizeof(":")) { ++ pam_syslog(pamh, LOG_NOTICE, "user name is too long"); ++ return PAM_SERVICE_ERR; ++ } ++ ++ if (strchr(user_name, ':') != NULL) { ++ /* ++ * "root:x" is not a local user name even if the passwd file ++ * contains a line starting with "root:x:". ++ */ ++ return PAM_PERM_DENIED; ++ } ++ ++ /* Open the passwd file. */ ++ if (file_name == NULL) { ++ file_name = "/etc/passwd"; ++ } ++ if ((fp = fopen(file_name, "r")) == NULL) { ++ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file_name); ++ return PAM_SERVICE_ERR; ++ } ++ ++ /* ++ * Scan the file using fgets() instead of fgetpwent_r() because ++ * the latter is not flexible enough in handling long lines ++ * in passwd files. ++ */ ++ rc = PAM_PERM_DENIED; ++ while (fgets(line, sizeof(line), fp) != NULL) { ++ size_t line_len; ++ const char *str; ++ ++ /* ++ * Does this line start with the user name ++ * followed by a colon? ++ */ ++ if (strncmp(user_name, line, user_len) == 0 && ++ line[user_len] == ':') { ++ rc = PAM_SUCCESS; ++ /* ++ * Continue reading the file to avoid timing attacks. ++ */ ++ } ++ /* Has a newline been read? */ ++ line_len = strlen(line); ++ if (line_len < sizeof(line) - 1 || ++ line[line_len - 1] == '\n') { ++ /* Yes, continue with the next line. */ ++ continue; ++ } ++ ++ /* No, read till the end of this line first. */ ++ while ((str = fgets(line, sizeof(line), fp)) != NULL) { ++ line_len = strlen(line); ++ if (line_len == 0 || ++ line[line_len - 1] == '\n') { ++ break; ++ } ++ } ++ if (str == NULL) { ++ /* fgets returned NULL, we are done. */ ++ break; ++ } ++ /* Continue with the next line. */ ++ } ++ ++ fclose(fp); ++ return rc; ++} +Index: Linux-PAM-1.3.0/build-aux/test-driver +=================================================================== +--- Linux-PAM-1.3.0.orig/build-aux/test-driver ++++ Linux-PAM-1.3.0/build-aux/test-driver +@@ -1,9 +1,9 @@ + #! /bin/sh + # test-driver - basic testsuite driver script. + +-scriptversion=2012-06-27.10; # UTC ++scriptversion=2018-03-07.03; # UTC + +-# Copyright (C) 2011-2013 Free Software Foundation, Inc. ++# Copyright (C) 2011-2020 Free Software Foundation, Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -16,7 +16,7 @@ scriptversion=2012-06-27.10; # UTC + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License +-# along with this program. If not, see . ++# along with this program. If not, see . + + # As a special exception to the GNU General Public License, if you + # distribute this file as part of a program that contains a +@@ -42,15 +42,16 @@ print_usage () + { + cat <$log_file 2>&1 + estatus=$? ++ + if test $enable_hard_errors = no && test $estatus -eq 99; then +- estatus=1 ++ tweaked_estatus=1 ++else ++ tweaked_estatus=$estatus + fi + +-case $estatus:$expect_failure in ++case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; +@@ -107,6 +124,12 @@ case $estatus:$expect_failure in + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; + esac + ++# Report the test outcome and exit status in the logs, so that one can ++# know whether the test passed or failed simply by looking at the '.log' ++# file, without the need of also peaking into the corresponding '.trs' ++# file (automake bug#11814). ++echo "$res $test_name (exit status: $estatus)" >>$log_file ++ + # Report outcome to console. + echo "${col}${res}${std}: $test_name" + +@@ -119,9 +142,9 @@ echo ":copy-in-global-log: $gcopy" >> $t + # Local Variables: + # mode: shell-script + # sh-indentation: 2 +-# eval: (add-hook 'write-file-hooks 'time-stamp) ++# eval: (add-hook 'before-save-hook 'time-stamp) + # time-stamp-start: "scriptversion=" + # time-stamp-format: "%:y-%02m-%02d.%02H" +-# time-stamp-time-zone: "UTC" ++# time-stamp-time-zone: "UTC0" + # time-stamp-end: "; # UTC" + # End: +Index: Linux-PAM-1.3.0/libpam/Makefile.am +=================================================================== +--- Linux-PAM-1.3.0.orig/libpam/Makefile.am ++++ Linux-PAM-1.3.0/libpam/Makefile.am +@@ -35,6 +35,7 @@ libpam_la_SOURCES = pam_account.c pam_au + pam_misc.c pam_password.c pam_prelude.c \ + pam_session.c pam_start.c pam_strerror.c \ + pam_vprompt.c pam_syslog.c pam_dynamic.c pam_audit.c \ ++ pam_modutil_check_user.c \ + pam_modutil_cleanup.c pam_modutil_getpwnam.c pam_modutil_ioloop.c \ + pam_modutil_getgrgid.c pam_modutil_getpwuid.c pam_modutil_getgrnam.c \ + pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c \ +Index: Linux-PAM-1.3.0/libpam/Makefile.in +=================================================================== +--- Linux-PAM-1.3.0.orig/libpam/Makefile.in ++++ Linux-PAM-1.3.0/libpam/Makefile.in +@@ -144,6 +144,7 @@ am_libpam_la_OBJECTS = pam_account.lo pa + pam_get_authtok.lo pam_handlers.lo pam_item.lo pam_misc.lo \ + pam_password.lo pam_prelude.lo pam_session.lo pam_start.lo \ + pam_strerror.lo pam_vprompt.lo pam_syslog.lo pam_dynamic.lo \ ++ pam_modutil_check_user.lo \ + pam_audit.lo pam_modutil_cleanup.lo pam_modutil_getpwnam.lo \ + pam_modutil_ioloop.lo pam_modutil_getgrgid.lo \ + pam_modutil_getpwuid.lo pam_modutil_getgrnam.lo \ +@@ -421,6 +422,7 @@ libpam_la_SOURCES = pam_account.c pam_au + pam_misc.c pam_password.c pam_prelude.c \ + pam_session.c pam_start.c pam_strerror.c \ + pam_vprompt.c pam_syslog.c pam_dynamic.c pam_audit.c \ ++ pam_modutil_check_user.c \ + pam_modutil_cleanup.c pam_modutil_getpwnam.c pam_modutil_ioloop.c \ + pam_modutil_getgrgid.c pam_modutil_getpwuid.c pam_modutil_getgrnam.c \ + pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c \ +@@ -518,6 +520,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_handlers.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_item.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_misc.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_modutil_check_user.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_modutil_cleanup.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_modutil_getgrgid.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_modutil_getgrnam.Plo@am__quote@ +Index: Linux-PAM-1.3.0/libpam/include/security/pam_modutil.h +=================================================================== +--- Linux-PAM-1.3.0.orig/libpam/include/security/pam_modutil.h ++++ Linux-PAM-1.3.0/libpam/include/security/pam_modutil.h +@@ -58,6 +58,11 @@ extern "C" { + + #include + ++extern int PAM_NONNULL((1,2)) ++pam_modutil_check_user_in_passwd(pam_handle_t *pamh, ++ const char *user_name, ++ const char *file_name); ++ + extern struct passwd * PAM_NONNULL((1,2)) + pam_modutil_getpwnam(pam_handle_t *pamh, const char *user); + +Index: Linux-PAM-1.3.0/libpam/libpam.map +=================================================================== +--- Linux-PAM-1.3.0.orig/libpam/libpam.map ++++ Linux-PAM-1.3.0/libpam/libpam.map +@@ -66,6 +66,7 @@ LIBPAM_MODUTIL_1.1.3 { + global: + pam_modutil_drop_priv; + pam_modutil_regain_priv; ++ pam_modutil_check_user_in_passwd; + } LIBPAM_MODUTIL_1.1; + + LIBPAM_MODUTIL_1.1.9 { +Index: Linux-PAM-1.3.0/configure +=================================================================== +--- Linux-PAM-1.3.0.orig/configure ++++ Linux-PAM-1.3.0/configure +@@ -18402,7 +18402,7 @@ else + fi + + +-ac_config_files="$ac_config_files Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile po/Makefile.in modules/Makefile modules/pam_access/Makefile modules/pam_cracklib/Makefile modules/pam_debug/Makefile modules/pam_deny/Makefile modules/pam_echo/Makefile modules/pam_env/Makefile modules/pam_faildelay/Makefile modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile modules/pam_ftp/Makefile modules/pam_group/Makefile modules/pam_issue/Makefile modules/pam_keyinit/Makefile modules/pam_lastlog/Makefile modules/pam_limits/Makefile modules/pam_listfile/Makefile modules/pam_localuser/Makefile modules/pam_loginuid/Makefile modules/pam_mail/Makefile modules/pam_mkhomedir/Makefile modules/pam_motd/Makefile modules/pam_namespace/Makefile modules/pam_nologin/Makefile modules/pam_permit/Makefile modules/pam_pwhistory/Makefile modules/pam_rhosts/Makefile modules/pam_rootok/Makefile modules/pam_exec/Makefile modules/pam_securetty/Makefile modules/pam_selinux/Makefile modules/pam_sepermit/Makefile modules/pam_shells/Makefile modules/pam_stress/Makefile modules/pam_succeed_if/Makefile modules/pam_tally/Makefile modules/pam_tally2/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 modules/pam_warn/Makefile modules/pam_wheel/Makefile modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile doc/man/Makefile doc/sag/Makefile doc/adg/Makefile doc/mwg/Makefile examples/Makefile tests/Makefile xtests/Makefile" ++ac_config_files="$ac_config_files Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile po/Makefile.in modules/Makefile modules/pam_access/Makefile modules/pam_cracklib/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 modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile modules/pam_ftp/Makefile modules/pam_group/Makefile modules/pam_issue/Makefile modules/pam_keyinit/Makefile modules/pam_lastlog/Makefile modules/pam_limits/Makefile modules/pam_listfile/Makefile modules/pam_localuser/Makefile modules/pam_loginuid/Makefile modules/pam_mail/Makefile modules/pam_mkhomedir/Makefile modules/pam_motd/Makefile modules/pam_namespace/Makefile modules/pam_nologin/Makefile modules/pam_permit/Makefile modules/pam_pwhistory/Makefile modules/pam_rhosts/Makefile modules/pam_rootok/Makefile modules/pam_exec/Makefile modules/pam_securetty/Makefile modules/pam_selinux/Makefile modules/pam_sepermit/Makefile modules/pam_shells/Makefile modules/pam_stress/Makefile modules/pam_succeed_if/Makefile modules/pam_tally/Makefile modules/pam_tally2/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 modules/pam_warn/Makefile modules/pam_wheel/Makefile modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile doc/man/Makefile doc/sag/Makefile doc/adg/Makefile doc/mwg/Makefile examples/Makefile tests/Makefile xtests/Makefile" + + cat >confcache <<\_ACEOF + # This file is a shell script that caches the results of configure +Index: Linux-PAM-1.3.0/modules/Makefile.am +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/Makefile.am ++++ Linux-PAM-1.3.0/modules/Makefile.am +@@ -10,7 +10,7 @@ SUBDIRS = pam_access pam_cracklib pam_de + pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ + pam_selinux pam_sepermit pam_shells pam_stress \ + pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \ +- pam_tty_audit pam_umask \ ++ pam_tty_audit pam_umask pam_faillock \ + pam_unix pam_userdb pam_warn pam_wheel pam_xauth + + CLEANFILES = *~ +Index: Linux-PAM-1.3.0/modules/Makefile.in +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/Makefile.in ++++ Linux-PAM-1.3.0/modules/Makefile.in +@@ -369,7 +369,7 @@ SUBDIRS = pam_access pam_cracklib pam_de + pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ + pam_selinux pam_sepermit pam_shells pam_stress \ + pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \ +- pam_tty_audit pam_umask \ ++ pam_tty_audit pam_umask pam_faillock \ + pam_unix pam_userdb pam_warn pam_wheel pam_xauth + + CLEANFILES = *~ +Index: Linux-PAM-1.3.0/po/Linux-PAM.pot +=================================================================== +--- Linux-PAM-1.3.0.orig/po/Linux-PAM.pot ++++ Linux-PAM-1.3.0/po/Linux-PAM.pot +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/af.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/af.po ++++ Linux-PAM-1.3.0/po/af.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/am.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/am.po ++++ Linux-PAM-1.3.0/po/am.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ar.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ar.po ++++ Linux-PAM-1.3.0/po/ar.po +@@ -578,3 +578,20 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "يجب الانتظار فترة أطول لتغيير كلمة السر" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/as.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/as.po ++++ Linux-PAM-1.3.0/po/as.po +@@ -575,3 +575,20 @@ msgstr "%s ৰ বাবে গুপ্ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "আপোনাৰ গুপ্তশব্দ সলনি কৰিবলৈ আপুনি আৰু কিছু পৰ অপেক্ষা কৰিব লাগিব" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u বিফল প্ৰৱেশৰ বাবে হিচাপ লক কৰা হৈছে" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/be.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/be.po ++++ Linux-PAM-1.3.0/po/be.po +@@ -571,3 +571,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/bg.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/bg.po ++++ Linux-PAM-1.3.0/po/bg.po +@@ -579,3 +579,20 @@ msgstr "Смяна на паролата + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Трябва да изчакате повече, за да промените Вашата парола" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Акаунтът е заключен поради %u неуспешни опита за влизане" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/bn.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/bn.po ++++ Linux-PAM-1.3.0/po/bn.po +@@ -583,3 +583,20 @@ msgstr "%s-র পাসওয়ার্ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "কিছু কাল পরে পাসওয়ার্ড পরিবর্তন করা সম্ভব হবে" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u ব্যর্থ লগ-ইনের ফলে অ্যাকাউন্ট লক করা হয়েছে" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/bn_IN.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/bn_IN.po ++++ Linux-PAM-1.3.0/po/bn_IN.po +@@ -578,3 +578,20 @@ msgstr "%s-র পাসওয়ার্ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "কিছু কাল পরে পাসওয়ার্ড পরিবর্তন করা সম্ভব হবে" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u ব্যর্থ লগ-ইনের ফলে অ্যাকাউন্ট লক করা হয়েছে" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/bs.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/bs.po ++++ Linux-PAM-1.3.0/po/bs.po +@@ -569,3 +569,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ca.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ca.po ++++ Linux-PAM-1.3.0/po/ca.po +@@ -580,3 +580,21 @@ msgstr "S'està canviant la contrasenya + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Heu d'esperar més temps abans de canviar la contrasenya" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Forma d’ús: %s: [--dir /directori/path/to/tally] [--user nom_usuari] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "El compte està bloquejat a causa de %u inicis fallits de sessió." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(resten %d minuts per desbloquejar)" +Index: Linux-PAM-1.3.0/po/cs.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/cs.po ++++ Linux-PAM-1.3.0/po/cs.po +@@ -576,3 +576,21 @@ msgstr "Změna hesla pro %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Na změnu svého hesla musíte počkat déle" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Použití: %s [--dir /cesta/k/tally-adresari] [--user uzivatelske_jmeno] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Účet je uzamčen z důvodu %u neúspěšných pokusů o přihlášení." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minut zbývá do odemčení)" +Index: Linux-PAM-1.3.0/po/cy.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/cy.po ++++ Linux-PAM-1.3.0/po/cy.po +@@ -571,3 +571,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/da.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/da.po ++++ Linux-PAM-1.3.0/po/da.po +@@ -572,3 +572,20 @@ msgstr "Ændrer adgangskode for %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Du skal vente lidt længere for at ændre din adgangskode" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Anvendelse: %s [--dir /sti/til/tally-mappe] [--user brugernavn] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Konto låst på grund af %u fejlende logins." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minutter tilbage hvor der kan låses op)" +Index: Linux-PAM-1.3.0/po/de.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/de.po ++++ Linux-PAM-1.3.0/po/de.po +@@ -580,3 +580,21 @@ msgstr "Ändern des Passworts für %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Sie können Ihr Passwort noch nicht ändern" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Aufruf: %s [--dir /path/to/tally-Verzeichnis] [--user Benutzername] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Das Konto ist wegen %u fehlgeschlagener Anmelde-Versuche gesperrt." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(noch %d Minuten zum Entsperren)" +Index: Linux-PAM-1.3.0/po/de_CH.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/de_CH.po ++++ Linux-PAM-1.3.0/po/de_CH.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/el.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/el.po ++++ Linux-PAM-1.3.0/po/el.po +@@ -565,3 +565,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/eo.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/eo.po ++++ Linux-PAM-1.3.0/po/eo.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/es.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/es.po ++++ Linux-PAM-1.3.0/po/es.po +@@ -585,3 +585,21 @@ msgstr "Cambiando la contraseña de %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Debe esperar más tiempo para cambiar la contraseña" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file nombre de archivo-raíz] [--user nombre de usuario] [--reset[=n]] " ++"[--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "La cuenta está bloqueada debido a %u logueo fallidos" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/et.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/et.po ++++ Linux-PAM-1.3.0/po/et.po +@@ -568,3 +568,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/eu.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/eu.po ++++ Linux-PAM-1.3.0/po/eu.po +@@ -567,3 +567,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/fa.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/fa.po ++++ Linux-PAM-1.3.0/po/fa.po +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/fi.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/fi.po ++++ Linux-PAM-1.3.0/po/fi.po +@@ -584,3 +584,21 @@ msgstr "Vaihdetaan käyttäjän %s salas + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Sinun täytyy odottaa kauemmin vaihtaaksesi salasanan" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file juurrutettu-tiedostonimi] [--user käyttäjätunnus] [--reset[=n]] " ++"[--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Käyttäjätili on lukittu %u epäonnistuneen kirjautumisen vuoksi." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/fr.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/fr.po ++++ Linux-PAM-1.3.0/po/fr.po +@@ -593,3 +593,21 @@ msgstr "Changement du mot de passe pour + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Vous devez encore attendre avant de changer votre mot de passe" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Utilisation : %s [--dir /chemin/vers/dossier-tally] [--user nom " ++"d’utilisateur] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Le compte est temporairement verrouillé dû aux %u connexions échouées." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minutes restantes pour déverrouiller)" +Index: Linux-PAM-1.3.0/po/ga.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ga.po ++++ Linux-PAM-1.3.0/po/ga.po +@@ -601,3 +601,21 @@ msgstr "Focal faire %s á athrú." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Caithfidh tú fanacht níos faide chun d'fhocal faire a athrú" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file ainm-comhad-le-fréamh] [--user úsáideoir] [--reset[=u]]\n" ++"[--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Cuireadh an cuntas faoi ghlas mar gheall ar %u logáil isteach teipthe" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/gl.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/gl.po ++++ Linux-PAM-1.3.0/po/gl.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/gu.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/gu.po ++++ Linux-PAM-1.3.0/po/gu.po +@@ -575,3 +575,20 @@ msgstr "%s માટે પાસવર + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "તમારો પાસવર્ડ બદલવા માટે તમારે લાંબો સમય રાહ જોવી જ પડશે" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u પ્રવેશો ને નિષ્ફળ કરે છે તે દરમ્યાન ખાતાને તાળુ મારેલ છે" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/he.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/he.po ++++ Linux-PAM-1.3.0/po/he.po +@@ -568,3 +568,20 @@ msgstr "משנה ססמה עבור %s. + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "אתה חייב לחכות יותר כדי לשנות את הססמה" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "החשבון ננעל בעקבות %u ניסיונות התחברות שנכשלו." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(נותרו %d דקות לשחרור)" +Index: Linux-PAM-1.3.0/po/hi.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/hi.po ++++ Linux-PAM-1.3.0/po/hi.po +@@ -574,3 +574,20 @@ msgstr "%s के लिए कूटश + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "आपको अपना शब्दकूट बदलने के लिए लंबी प्रतीक्षा करनी होगी" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "खाता %u विफल लॉगिन के कारण लॉक" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/hr.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/hr.po ++++ Linux-PAM-1.3.0/po/hr.po +@@ -569,3 +569,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/hu.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/hu.po ++++ Linux-PAM-1.3.0/po/hu.po +@@ -580,3 +580,20 @@ msgstr "%s jelszavának megváltoztatás + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Tovább kell várnia míg megváltoztathatja a jelszavát" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-fájlnév] [--user használó] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Felhasználói azonosító zárolva, többszöri, %u sikertelen belépés miatt" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ia.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ia.po ++++ Linux-PAM-1.3.0/po/ia.po +@@ -580,3 +580,20 @@ msgstr "Cambiamento del contrasigno pro + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Attende ancora pro cambiar le contrasigno" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file percurso-integre] [--user usator] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Le conto es blocate a causa de %u insuccessos al authentication" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/id.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/id.po ++++ Linux-PAM-1.3.0/po/id.po +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/is.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/is.po ++++ Linux-PAM-1.3.0/po/is.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/it.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/it.po ++++ Linux-PAM-1.3.0/po/it.po +@@ -589,3 +589,20 @@ msgstr "Cambio password per %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Attendere ancora per cambiare la password" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Uso: %s [--dir /path/to/tally-directory] [--user nomeutente] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Account bloccato a causa di %u accessi non riusciti." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minuti rimanenti per sbloccare)" +Index: Linux-PAM-1.3.0/po/ja.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ja.po ++++ Linux-PAM-1.3.0/po/ja.po +@@ -575,3 +575,20 @@ msgstr "%s 用にパスワードを変 + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "パスワードを変更するには長く待つ必要があります" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u のログイン失敗の理由で アカウントはロックされました" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ka.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ka.po ++++ Linux-PAM-1.3.0/po/ka.po +@@ -565,3 +565,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/kk.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/kk.po ++++ Linux-PAM-1.3.0/po/kk.po +@@ -574,3 +574,21 @@ msgstr "%s үшін парольді ө + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Пароліңізді өзгерті үшін біраз күтуіңіз керек" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Қолданылуы: %s: [--dir /tally-бумасына/дейінгі/жол] [--user пайдаланушы] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Тіркелгі %u рет қате кіру талабы салдарынан бұғатталды." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(бұғатты шешуге дейін %d минут қалды)" +Index: Linux-PAM-1.3.0/po/km.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/km.po ++++ Linux-PAM-1.3.0/po/km.po +@@ -569,3 +569,20 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "អ្នក​ត្រូវ​តែ​រង់ចាំ​បន្តិច ដើម្បី​ផ្លាស់ប្ដូរ​ពាក្យសម្ងាត់​របស់​អ្នក" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s ៖ [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/kn.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/kn.po ++++ Linux-PAM-1.3.0/po/kn.po +@@ -575,3 +575,20 @@ msgstr "%s ಗಾಗಿ ಗುಪ್ತ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "ನಿಮ್ಮ ಗುಪ್ತಪದವನ್ನು ಬದಲಾಯಿಸಲು ನೀವು ಬಹಳ ಸಮಯ ಕಾಯಬೇಕು" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "ವಿಫಲಗೊಂಡ %u ಪ್ರವೇಶಗಳಿಂದಾಗಿ ಖಾತೆಯನ್ನು ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ko.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ko.po ++++ Linux-PAM-1.3.0/po/ko.po +@@ -573,3 +573,20 @@ msgstr "%s에 대한 암호 변경 중 + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "암호 변경을 위해 조금더 기다려 주십시오." ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u 로그인 실패로 인해 계정이 잠김 " ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/kw_GB.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/kw_GB.po ++++ Linux-PAM-1.3.0/po/kw_GB.po +@@ -563,3 +563,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ky.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ky.po ++++ Linux-PAM-1.3.0/po/ky.po +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/lt.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/lt.po ++++ Linux-PAM-1.3.0/po/lt.po +@@ -569,3 +569,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/lv.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/lv.po ++++ Linux-PAM-1.3.0/po/lv.po +@@ -569,3 +569,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/mk.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/mk.po ++++ Linux-PAM-1.3.0/po/mk.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ml.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ml.po ++++ Linux-PAM-1.3.0/po/ml.po +@@ -574,3 +574,20 @@ msgstr "%s-നുളള അടയാള + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "നിങ്ങളുടെ അടയാളവാക്ക് മാറ്റുന്നതിനായി ഇനിയും കാത്തിരിക്കേണ്ടതാണ്." ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u പരാജയപ്പെട്ട ലോഗിനുകള്‍ കാരണം അക്കൌണ്ട് താല്‍ക്കാലികമായി പൂട്ടിയിരിക്കുന്നു" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/mn.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/mn.po ++++ Linux-PAM-1.3.0/po/mn.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/mr.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/mr.po ++++ Linux-PAM-1.3.0/po/mr.po +@@ -574,3 +574,20 @@ msgstr "%s करीता गुप् + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "तुमचा गुप्तशब्द बदलण्यासाठी तुम्हाला बराच वेळ वाट पहावी लागेल" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file रूटेड-फाइलनाव] [--user वापरकर्त्याचे नाव] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u अपयशी प्रवेश मुळे खाते कुलूपबंद केले" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ms.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ms.po ++++ Linux-PAM-1.3.0/po/ms.po +@@ -564,3 +564,19 @@ msgstr "Menukar katalaluan untuk %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/my.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/my.po ++++ Linux-PAM-1.3.0/po/my.po +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/nb.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/nb.po ++++ Linux-PAM-1.3.0/po/nb.po +@@ -576,3 +576,19 @@ msgstr "Endrer passord for %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Du må vente lenger før du kan endre passordet" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "Bruk: %s [--dir /sti/til/tally-mappe] [--user brukernavn] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Konto låst som følge av %u mislykkede innlogginger." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minutter igjen til å låse opp)" +Index: Linux-PAM-1.3.0/po/ne.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ne.po ++++ Linux-PAM-1.3.0/po/ne.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/nl.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/nl.po ++++ Linux-PAM-1.3.0/po/nl.po +@@ -586,3 +586,21 @@ msgstr "Veranderen van wachtwoord voor % + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "U moet langer wachten om uw wachtwoord te wijzigen" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Gebruik: %s [--dir /pad/naar/tally-directory] [--user gebruikersnaam] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Het account is vergrendeld wegens %u mislukte aanmeldingen." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(nog %d minuten om te ontgrendelen)" +Index: Linux-PAM-1.3.0/po/nn.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/nn.po ++++ Linux-PAM-1.3.0/po/nn.po +@@ -565,3 +565,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/or.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/or.po ++++ Linux-PAM-1.3.0/po/or.po +@@ -576,3 +576,20 @@ msgstr "%s ପାଇଁ ପ୍ରବେ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "ପ୍ରବେଶ ସଙ୍କେତକୁ ବଦଳାଇବା ପାଇଁ ଆପଣ ଅଧିକ ସମୟ ଅପେକ୍ଷା କରିବା ଉଚିତ" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u ବିଫଳତା ଲଗଇନ କାରଣରୁ ଖାତା ଅପରିବର୍ତ୍ତନଶୀଳ ହୋଇଯାଇଛି।" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/pa.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/pa.po ++++ Linux-PAM-1.3.0/po/pa.po +@@ -574,3 +574,19 @@ msgstr "%s ਲਈ ਪਾਸਵਰਡ ਤ + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "ਤੁਹਾਨੂੰ ਲੰਬੇ ਸਮੇਂ ਲਈ ਆਪਣੇ ਪਾਸਵਰਡ ਲਈ ਉਡੀਕ ਕਰਨੀ ਪਵੇਗੀ" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "ਵਰਤੋਂ: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u ਫੇਲ੍ਹ ਹੋਏ ਲਾਗਇਨਾਂ ਕਰਕੇ ਖਾਤਾ ਲਾਕ ਕੀਤਾ ਹੈ।" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(ਅਣਲਾਕ ਕਰਨ ਲਈ %d ਮਿੰਟ ਬਚੇ ਹਨ)" +Index: Linux-PAM-1.3.0/po/pl.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/pl.po ++++ Linux-PAM-1.3.0/po/pl.po +@@ -582,3 +582,21 @@ msgstr "Zmienianie hasła dla %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Należy poczekać dłużej na zmianę hasła" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Użycie: %s [--dir /ścieżka/do/katalogu-tally] [--user nazwa-użytkownika] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Konto zostało zablokowane z powodu %u nieudanych logowań." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(pozostało %d min do odblokowania)" +Index: Linux-PAM-1.3.0/po/pt.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/pt.po ++++ Linux-PAM-1.3.0/po/pt.po +@@ -583,3 +583,21 @@ msgstr "A alterar senha para %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Tem de esperar mais antes de poder alterar a sua senha" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Utilização: %s [--dir / path/to/tally-directory] [--user nome de utilizador] " ++"[--reset]]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Conta bloqueada devido a %u inícios de sessão falhados." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(Minutos restantes para desbloquear: %d)" +Index: Linux-PAM-1.3.0/po/pt_BR.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/pt_BR.po ++++ Linux-PAM-1.3.0/po/pt_BR.po +@@ -578,3 +578,21 @@ msgstr "Mudando senha para %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Aguarde mais tempo para mudar a senha" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Uso: %s [--dir /caminho/para/diretório-tally] [--user nome-utilizador] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Conta bloqueada devido a %u falhas de login." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(minutos restantes para desbloquear: %d)" +Index: Linux-PAM-1.3.0/po/ro.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ro.po ++++ Linux-PAM-1.3.0/po/ro.po +@@ -569,3 +569,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/ru.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ru.po ++++ Linux-PAM-1.3.0/po/ru.po +@@ -586,3 +586,23 @@ msgstr "Смена пароля для % + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "До смены пароля должно пройти больше времени" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Использование: %s: [--dir /путь/к/каталогу-tally] [--user имя_пользователя] " ++"[--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++"Учетная запись заблокирована как следствие неудачных попыток входа (всего -- " ++"%u)." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(осталось %d мин. до разблокировки)" +Index: Linux-PAM-1.3.0/po/si.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/si.po ++++ Linux-PAM-1.3.0/po/si.po +@@ -571,3 +571,20 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "ඔබගේ රහස්පදය වෙනස් කිරීමට බොහෝ වෙලාවක් රැදී සිටීය යුතුම වේ" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/sk.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sk.po ++++ Linux-PAM-1.3.0/po/sk.po +@@ -588,3 +588,21 @@ msgstr "Zmena hesla pre %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Na zmenu svojho hesla musíte počkať dlhšie" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Použitie: %s [--dir /cesta/k/zhodujú-directory] [--user pouzivatelske_meno] " ++"[--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Účet uzamknutý z dôvodu %u neúspešných prihlásení." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(odomknutie zostáva %d minút)" +Index: Linux-PAM-1.3.0/po/sl.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sl.po ++++ Linux-PAM-1.3.0/po/sl.po +@@ -571,3 +571,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/sq.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sq.po ++++ Linux-PAM-1.3.0/po/sq.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/sr.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sr.po ++++ Linux-PAM-1.3.0/po/sr.po +@@ -581,3 +581,21 @@ msgstr "Мењам лозинку за % + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Морате дуже сачекати на промену лозинке" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file коренски-називдатотеке] [--user корисничкоиме] [--reset[=n]] [--" ++"quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Налог је закључан због %u неуспелих пријава" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/sr@latin.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sr@latin.po ++++ Linux-PAM-1.3.0/po/sr@latin.po +@@ -581,3 +581,21 @@ msgstr "Menjam lozinku za %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Morate duže sačekati na promenu lozinke" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file korenski-nazivdatoteke] [--user korisničkoime] [--reset[=n]] [--" ++"quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Nalog je zaključan zbog %u neuspelih prijava" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/sv.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/sv.po ++++ Linux-PAM-1.3.0/po/sv.po +@@ -581,3 +581,21 @@ msgstr "Ändrar lösenord för %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Du måste vänta längre innan du kan ändra lösenord" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Användning: %s [--dir /sökväg/till/tally-katalog] [--user användarnamn] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Kontot är låst på grund av %u misslyckade inloggningar." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d minuter kvar till upplåsning)" +Index: Linux-PAM-1.3.0/po/ta.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ta.po ++++ Linux-PAM-1.3.0/po/ta.po +@@ -575,3 +575,20 @@ msgstr "%sக்கு கடவுச + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "உங்கள் கடவுச்சொல்லை மாற்ற சிறிது காத்திருக்க வேண்டும்" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u தோல்வி புகுபதிவுகளால் கணக்கு பூட்டப்பட்டுள்ளது" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/te.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/te.po ++++ Linux-PAM-1.3.0/po/te.po +@@ -574,3 +574,20 @@ msgstr "%s కొరకు సంకే + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "మీ సంకేతపదమును మార్చుటకు మీరు ఎక్కువసేపు వేచివుండాలి" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u లాగిన్‌ల వైఫల్యం కారణంగా ఖాతా లాక్అయింది" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/tg.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/tg.po ++++ Linux-PAM-1.3.0/po/tg.po +@@ -566,3 +566,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/th.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/th.po ++++ Linux-PAM-1.3.0/po/th.po +@@ -564,3 +564,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/tr.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/tr.po ++++ Linux-PAM-1.3.0/po/tr.po +@@ -580,3 +580,21 @@ msgstr "%s kullanıcısının parolası + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Parolanızı değiştirmek için daha sonra denemelisiniz" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Kullanım: %s [--dir KayıtlarınTutulduğuDizininYolu] [--user KullanıcıAdı] [--" ++"reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "%u başarısız oturum açma nedeniyle hesap kilitlendi." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(kilidi açmak için %d dakika kaldı)" +Index: Linux-PAM-1.3.0/po/uk.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/uk.po ++++ Linux-PAM-1.3.0/po/uk.po +@@ -586,3 +586,21 @@ msgstr "Зміна пароля %s." + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Ви повинні зачекати, щоб змінити ваш пароль" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"Користування: %s [--dir /шлях/до/каталогу/tally] [--user ім'я користувача] " ++"[--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Обліковий запис заблоковано через %u помилок під час спроби входу." ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(лишилося %d хвилин до розблокування)" +Index: Linux-PAM-1.3.0/po/ur.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/ur.po ++++ Linux-PAM-1.3.0/po/ur.po +@@ -565,3 +565,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/vi.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/vi.po ++++ Linux-PAM-1.3.0/po/vi.po +@@ -577,3 +577,21 @@ msgstr "Thay đổi mật khẩu cho %s. + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Bạn phải đợi thêm nữa, để thay đổi mật khẩu" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [- tập bắt rễ-filename] [- người sử dụng tên người dùng] [- đặt lại [= " ++"n]] [- yên tĩnh]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, fuzzy, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "Tài khoản bị khóa do đăng nhập %u không thành công" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/yo.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/yo.po ++++ Linux-PAM-1.3.0/po/yo.po +@@ -562,3 +562,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/zh_CN.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/zh_CN.po ++++ Linux-PAM-1.3.0/po/zh_CN.po +@@ -572,3 +572,20 @@ msgstr "为 %s 更改 STRESS 密码。" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "您必须等待更长时间以更改密码" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"用法:%s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "由于 %u 次登录失败,此帐户已锁定。" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d 分钟后解锁)" +Index: Linux-PAM-1.3.0/po/zh_HK.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/zh_HK.po ++++ Linux-PAM-1.3.0/po/zh_HK.po +@@ -563,3 +563,19 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/po/zh_TW.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/zh_TW.po ++++ Linux-PAM-1.3.0/po/zh_TW.po +@@ -570,3 +570,20 @@ msgstr "正在更改 %s 的 STRESS 密 + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "您必須久候,以更改您的密碼" ++ ++#: modules/pam_faillock/main.c:104 ++#, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"用法:%s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "因為 %u 次登入皆失敗,帳號已鎖定。" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "(%d 分鐘後解鎖)" +Index: Linux-PAM-1.3.0/po/zu.po +=================================================================== +--- Linux-PAM-1.3.0.orig/po/zu.po ++++ Linux-PAM-1.3.0/po/zu.po +@@ -576,3 +576,20 @@ msgstr "" + #: modules/pam_unix/pam_unix_passwd.c:722 + msgid "You must wait longer to change your password" + msgstr "Kumelwe ulinde isikhashana ukuze ushintshe iphasiwedi yakho" ++ ++#: modules/pam_faillock/main.c:104 ++#, fuzzy, c-format ++msgid "" ++"Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n" ++msgstr "" ++"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n" ++ ++#: modules/pam_faillock/pam_faillock.c:618 ++#, c-format ++msgid "The account is locked due to %u failed logins." ++msgstr "" ++ ++#: modules/pam_faillock/pam_faillock.c:623 ++#, c-format ++msgid "(%d minutes left to unlock)" ++msgstr "" +Index: Linux-PAM-1.3.0/configure.ac +=================================================================== +--- Linux-PAM-1.3.0.orig/configure.ac ++++ Linux-PAM-1.3.0/configure.ac +@@ -615,6 +615,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil + modules/pam_debug/Makefile modules/pam_deny/Makefile \ + modules/pam_echo/Makefile modules/pam_env/Makefile \ + modules/pam_faildelay/Makefile \ ++ modules/pam_faillock/Makefile \ + modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile \ + modules/pam_ftp/Makefile modules/pam_group/Makefile \ + modules/pam_issue/Makefile modules/pam_keyinit/Makefile \ diff --git a/pam-xauth_ownership.patch b/pam-xauth_ownership.patch new file mode 100644 index 0000000..f9e08b0 --- /dev/null +++ b/pam-xauth_ownership.patch @@ -0,0 +1,106 @@ +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 +@@ -355,11 +355,13 @@ pam_sm_open_session (pam_handle_t *pamh, + 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 @@ pam_sm_open_session (pam_handle_t *pamh, + 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 @@ pam_sm_open_session (pam_handle_t *pamh, + 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 + security_context_t context = NULL; +@@ -583,12 +602,12 @@ pam_sm_open_session (pam_handle_t *pamh, + 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 @@ pam_sm_open_session (pam_handle_t *pamh, + 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 new file mode 100644 index 0000000..bdcef51 --- /dev/null +++ b/pam.changes @@ -0,0 +1,855 @@ +* Mon Jan 8 2024 valentin.lefebvre@suse.com +- Add missing O_DIRECTORY flag in `protect_dir()` for pam_namespace module. + [bsc#1218475, pam-bsc1218475-pam_namespace-O_DIRECTORY-flag.patch] +* Fri Dec 29 2023 tabraham@suse.com +- pam_lastlog: check localtime_r() return value (bsc#1217000) + * Added: pam-bsc1217000-pam_lastlog-check-localtime_r-return-value.patch +* Wed Sep 7 2022 valentin.lefebvre@suse.com +- Update pam_motd to the most current version. This fixes various issues + and adds support for mot.d directories [jsc#PED-1712]. + * Added: pam-ped1712-pam_motd-directory-feature.patch +* Fri Apr 1 2022 josef.moellers@suse.com +- Do not include obsolete libselinux header files flask.h and + av_permissions.h. + [bsc#1197794, pam-bsc1197794-do-not-include-obsolete-header-files.patch] +* Wed Mar 16 2022 josef.moellers@suse.com +- Between allocating the variable "ai" and free'ing them, there are + two "return NO" were we don't free this variable. This patch + inserts freaddrinfo() calls before the "return NO;"s. + [bsc#1197024, pam-bsc1197024-free-addrinfo-before-return.patch] +* Thu Feb 24 2022 josef.moellers@suse.com +- Define _pam_vendordir as "/%%{_sysconfdir}/pam.d" + The variable is needed by systemd and others. + [bsc#1196093, macros.pam] +* Thu Oct 21 2021 josef.moellers@suse.com +- Corrected a bad directive file which resulted in + the "securetty" file to be installed as "macros.pam". + [pam.spec] +* Thu Oct 14 2021 josef.moellers@suse.com +- Added tmpfiles for pam to set up directory for pam_faillock. + [pam.conf] +* Wed Oct 6 2021 josef.moellers@suse.com +- Corrected macros.pam entry for %%_pam_moduledir + Cleanup in pam.spec: + * Replaced all references to ${_lib}/security in pam.spec by + %%{_pam_moduledir} + * Removed definition of (unused) "amdir". +* Wed Sep 1 2021 josef.moellers@suse.com +- Added new file macros.pam on request of systemd. + [bsc#1190052, macros.pam] +* Wed Aug 25 2021 josef.moellers@suse.com +- Added pam_faillock to the set of modules. + [jsc#sle-20638, pam-sle20638-add-pam_faillock.patch] +* Tue May 11 2021 josef.moellers@suse.com +- In the 32-bit compatibility package for 64-bit architectures, + require "systemd-32bit" to be also installed as it contains + pam_systemd.so for 32 bit applications. + [bsc#1185562, baselibs.conf] +* Tue Apr 6 2021 josef.moellers@suse.com +- If "LOCAL" is configured in access.conf, and a login attempt from + a remote host is made, pam_access tries to resolve "LOCAL" as + a hostname and logs a failure. + Checking explicitly for "LOCAL" and rejecting access in this case + resolves this issue. + [bsc#1184358, bsc1184358-prevent-LOCAL-from-being-resolved.patch] +* Wed Mar 10 2021 josef.moellers@suse.com +- pam_limits: "unlimited" is not a legitimate value for "nofile" + (see setrlimit(2)). So, when "nofile" is set to one of the + "unlimited" values, it is set to the contents of + "/proc/sys/fs/nr_open" instead. + Also changed the manpage of pam_limits to express this. + [bsc#1181443, pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch] +* Mon Feb 8 2021 josef.moellers@suse.com +- Add a definition for pamdir to pam.spec + So that a proper contents of macros.pam can be constructed. + [pam.spec] +* Fri Jan 15 2021 josef.moellers@suse.com +- Create macros.pam with definition of %%_pamdir so packages which + are commonly shared between Factory and SLE can use this macro + [pam.spec] +* Thu Nov 19 2020 josef.moellers@suse.com +- 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 2020 josef.moellers@suse.com +- 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 2020 josef.moellers@suse.com +- 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] +* Thu Oct 15 2020 josef.moellers@suse.com +- /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] +* Fri Mar 20 2020 josef.moellers@suse.com +- Moved pam_userdb to a separate package pam-extra. + [bsc#1166510, pam.spec] +* Fri Mar 13 2020 meissner@suse.com +- disable libdb usage and pam_userdb again, as this causes some license + conflicts. (bsc#1166510) +* Fri Feb 21 2020 josef.moellers@suse.com +- Add libdb as build-time dependency to enable pam_userdb module. + Enable pam_userdb.so + [jsc#sle-7258, bsc#1164562, pam.spec] +* Mon Nov 19 2018 josef.moellers@suse.com +- When comparing an incoming IP address with an entry in + access.conf that only specified a single host (ie no netmask), + the incoming IP address was used rather than the IP address from + access.conf, effectively comparing the incoming address with + itself. (Also fixed a small typo while I was at it) + [bsc#1115640, use-correct-IP-address.patch, CVE-2018-17953] +* Thu Oct 11 2018 josef.moellers@suse.com +- Remove limits for nproc from /etc/security/limits.conf + ie remove pam-limit-nproc.patch + [bsc#1110700, pam-limit-nproc.patch] +* Thu May 3 2018 josef.moellers@suse.com +- pam_umask.8 needed to be patched as well. + [bsc#1089884, pam-fix-config-order-in-manpage.patch] +* Wed May 2 2018 josef.moellers@suse.com +- Changed order of configuration files to reflect actual code. + [bsc#1089884, pam-fix-config-order-in-manpage.patch] +* Thu Feb 22 2018 fvogt@suse.com +- Use %%license (boo#1082318) +* Thu Oct 12 2017 schwab@suse.de +- Prerequire group(shadow), user(root) +* Fri Jan 27 2017 josef.moellers@suse.com +- Allow symbolic hostnames in access.conf file. + [pam-hostnames-in-access_conf.patch, boo#1019866] +* Thu Dec 8 2016 josef.moellers@suse.com +- Increased nproc limits for non-privileged users to 4069/16384. + Removed limits for "root". + [pam-limit-nproc.patch, bsc#1012494, bsc#1013706] +* Sun Jul 31 2016 develop7@develop7.info +- pam-limit-nproc.patch: increased process limit to help + Chrome/Chromuim users with really lots of tabs. New limit gets + closer to UserTasksMax parameter in logind.conf +* Thu Jul 28 2016 kukuk@suse.de +- Add doc directory to filelist. +* Mon May 2 2016 kukuk@suse.de +- Remove obsolete README.pam_tally [bsc#977973] +* Thu Apr 28 2016 kukuk@suse.de +- Update Linux-PAM to version 1.3.0 +- Rediff encryption_method_nis.diff +- Link pam_unix against libtirpc and external libnsl to enable + IPv6 support. +* Thu Apr 14 2016 kukuk@suse.de +- Add /sbin/unix2_chkpwd (moved from pam-modules) +* Mon Apr 11 2016 kukuk@suse.de +- Remove (since accepted upstream): + - 0001-Remove-YP-dependencies-from-pam_access-they-were-nev.patch + - 0002-Remove-enable-static-modules-option-and-support-from.patch + - 0003-fix-nis-checks.patch + - 0004-PAM_EXTERN-isn-t-needed-anymore-but-don-t-remove-it-.patch + - 0005-Use-TI-RPC-functions-if-we-compile-and-link-against-.patch +* Fri Apr 1 2016 kukuk@suse.de +- Add 0005-Use-TI-RPC-functions-if-we-compile-and-link-against-.patch + - Replace IPv4 only functions +* Fri Apr 1 2016 kukuk@suse.de +- Fix typo in common-account.pamd [bnc#959439] +* Tue Mar 29 2016 kukuk@suse.de +- Add 0004-PAM_EXTERN-isn-t-needed-anymore-but-don-t-remove-it-.patch + - readd PAM_EXTERN for external PAM modules +* Wed Mar 23 2016 kukuk@suse.de +- Add 0001-Remove-YP-dependencies-from-pam_access-they-were-nev.patch +- Add 0002-Remove-enable-static-modules-option-and-support-from.patch +- Add 0003-fix-nis-checks.patch +* Sat Jul 25 2015 joschibrauchle@gmx.de +- Add folder /etc/security/limits.d as mentioned in 'man pam_limits' +* Fri Jun 26 2015 kukuk@suse.de +- Update to version 1.2.1 + - security update for CVE-2015-3238 +* Mon Apr 27 2015 kukuk@suse.de +- Update to version 1.2.0 + - obsoletes Linux-PAM-git-20150109.diff +* Fri Jan 9 2015 kukuk@suse.de +- Re-add lost patch encryption_method_nis.diff [bnc#906660] +* Fri Jan 9 2015 kukuk@suse.de +- Update to current git: + - Linux-PAM-git-20150109.diff replaces Linux-PAM-git-20140127.diff + - obsoletes pam_loginuid-log_write_errors.diff + - obsoletes pam_xauth-sigpipe.diff + - obsoletes bug-870433_pam_timestamp-fix-directory-traversal.patch +* Fri Jan 9 2015 bwiedemann@suse.com +- increase process limit to 1200 to help chromium users with many tabs +* Tue May 6 2014 bwiedemann@suse.com +- limit number of processes to 700 to harden against fork-bombs + Add pam-limit-nproc.patch +* Wed Apr 9 2014 ckornacker@suse.com +- Fix CVE-2014-2583: pam_timestamp path injection (bnc#870433) + bug-870433_pam_timestamp-fix-directory-traversal.patch +* Tue Apr 1 2014 ckornacker@suse.com +- adding sclp_line0/ttysclp0 to /etc/securetty on s390 (bnc#869664) +* Mon Jan 27 2014 kukuk@suse.de +- Add pam_loginuid-log_write_errors.diff: log significant loginuid + write errors +- pam_xauth-sigpipe.diff: avoid potential SIGPIPE when writing to + xauth process +* Mon Jan 27 2014 kukuk@suse.de +- Update to current git (Linux-PAM-git-20140127.diff), which + obsoletes pam_loginuid-part1.diff, pam_loginuid-part2.diff and + Linux-PAM-git-20140109.diff. + - Fix gratuitous use of strdup and x_strdup + - pam_xauth: log fatal errors preventing xauth process execution + - pam_loginuid: cleanup loginuid buffer initialization + - libpam_misc: fix an inconsistency in handling memory allocation errors + - pam_limits: fix utmp->ut_user handling + - pam_mkhomedir: check and create home directory for the same user + - pam_limits: detect and ignore stale utmp entries +- Disable pam_userdb (remove db-devel from build requires) +* Fri Jan 10 2014 kukuk@suse.com +- Add pam_loginuid-part1.diff: Ignore missing /proc/self/loginuid +- Add pam_loginuid-part2.diff: Workaround to run pam_loginuid inside lxc +* Thu Jan 9 2014 kukuk@suse.de +- Update to current git (Linux-PAM-git-20140109.diff, which + replaces pam_unix.diff and encryption_method_nis.diff) + - pam_access: fix debug level logging + - pam_warn: log flags passed to the module + - pam_securetty: check return value of fgets + - pam_lastlog: fix format string + - pam_loginuid: If the correct loginuid is already set, skip writing it +* Fri Nov 29 2013 schwab@linux-m68k.org +- common-session.pamd: add missing newline +* Thu Nov 28 2013 kukuk@suse.de +- Remove libtrpc support to solve dependency/build cycles, plain + glibc is enough for now. +* Tue Nov 12 2013 kukuk@suse.de +- Add encryption_method_nis.diff: + - implement pam_unix2 functionality to use another hash for + NIS passwords. +* Fri Nov 8 2013 kukuk@suse.de +- Add pam_unix.diff: + - fix if /etc/login.defs uses DES + - ask always for old password if a NIS password will be changed +* Sat Sep 28 2013 mc@suse.com +- fix manpages links (bnc#842872) [fix-man-links.dif] +* Fri Sep 20 2013 hrvoje.senjan@gmail.com +- Explicitly add pam_systemd.so to list of modules in + common-session.pamd (bnc#812462) +* Fri Sep 20 2013 kukuk@suse.de +- Update to official release 1.1.8 (1.1.7 + git-20130916.diff) +- Remove needless pam_tally-deprecated.diff patch +* Mon Sep 16 2013 kukuk@suse.de +- Replace fix-compiler-warnings.diff with current git snapshot + (git-20130916.diff) for pam_unix.so: + - fix glibc warnings + - fix syntax error in SELinux code + - fix crash at login +* Thu Sep 12 2013 kukuk@suse.de +- Remove pam_unix-login.defs.diff, not needed anymore +* Thu Sep 12 2013 kukuk@suse.de +- Update to version 1.1.7 (bugfix release) + - Drop missing-DESTDIR.diff and pam-fix-includes.patch + - fix-compiler-warnings.diff: fix unchecked setuid return code +* Tue Aug 6 2013 mc@suse.de +- adding hvc0-hvc7 to /etc/securetty on s390 (bnc#718516) +* Mon May 27 2013 kukuk@suse.de +- Fix typo in common-password [bnc#821526] +* Fri Apr 26 2013 mmeister@suse.com +- Added libtool as BuildRequire, and autoreconf -i option to fix + build with new automake +* Tue Feb 5 2013 kukuk@suse.de +- Update pam_unix-login.defs.diff patch to the final upstream + version. +* Tue Feb 5 2013 kukuk@suse.de +- Adjust URL +- Add set_permission macro and PreReq +- Read default encryption method from /etc/login.defs + (pam_unix-login.defs.diff) +* Fri Jan 25 2013 kukuk@suse.com +- Remove deprecated pam_tally.so module, it's too buggy and can + destroy config and log files. +* Mon Nov 12 2012 kukuk@suse.de +- Sync common-*.pamd config with pam-config (use pam_unix.so as + default). +* Wed Sep 19 2012 kukuk@suse.de +- Fix building in Factory (add patch missing-DESTDIR.diff) +* Fri Sep 14 2012 kukuk@suse.de +- Update to Linux-PAM 1.1.6 + - Update translations + - pam_cracklib: Add more checks for weak passwords + - pam_lastlog: Never lock out root + - Lot of bug fixes and smaller enhancements +* Thu Jun 21 2012 aj@suse.de +- Include correct headers for getrlimit (add patch pam-fix-includes.patch). +* Mon Apr 23 2012 jengelh@medozas.de +- Update homepage URL in specfile +* Sat Mar 3 2012 jengelh@medozas.de +- Update to new upstream release 1.1.5 + * pam_env: Fix CVE-2011-3148: correctly count leading whitespace + when parsing environment file in pam_env + * Fix CVE-2011-3149: when overflowing, exit with PAM_BUF_ERR in + pam_env + * pam_access: Add hostname resolution cache +* Tue Oct 25 2011 mc@suse.de +- pam_tally2: remove invalid options from manpage (bnc#726071) +- fix possible overflow and DOS in pam_env (bnc#724480) + CVE-2011-3148, CVE-2011-3149 +* Mon Jun 27 2011 kukuk@suse.de +- Update to version 1.1.4 + * pam_securetty: Honour console= kernel option, add noconsole option + * pam_limits: Add %%group syntax, drop change_uid option, add set_all option + * Lot of small bug fixes + * Add support for libtirpc +- Build against libtirpc +* Thu May 26 2011 cfarrell@novell.com +- license update: GPL-2.0+ or BSD-3-Clause + Updating to spdx.org/licenses syntax as legal-auto for some reason did + not accept the previous spec file license +* Wed May 25 2011 kukuk@suse.de +- Remove libxcrypt-devel from BuildRequires +* Wed Feb 23 2011 vcizek@novell.com +- bnc#673826 rework + * manpage is left intact, as it was + * correct parsing of "quiet" option +* Wed Feb 23 2011 vcizek@novell.com +- fix for bnc#673826 (pam_listfile) + * removed unnecessary logging when listfile is missing and quiet + option is specified + * manpage is also updated, to reflect that all option + require values +* Thu Oct 28 2010 kukuk@suse.de +- Update to Linux-PAM 1.1.3 + - fixes CVE-2010-3853, CVE-2010-3431, CVE-2010-3430 + - pam_unix: Add minlen option, change default from 6 to 0 +* Tue Aug 31 2010 kukuk@suse.de +- Update to Linux-PAM 1.1.2 +* Mon Jun 28 2010 jengelh@medozas.de +- use %%_smp_mflags +* Mon May 10 2010 kukuk@suse.de +- Update to current CVS version (pam_rootok: Add support for + chauthtok and acct_mgmt, [bnc#533249]) +* Thu Mar 11 2010 kukuk@suse.de +- Install correct documentation +* Wed Dec 16 2009 kukuk@suse.de +- Update to Linux-PAM 1.1.1 (bug fix release) +* Sat Dec 12 2009 jengelh@medozas.de +- add baselibs.conf as a source +* Wed Dec 9 2009 jengelh@medozas.de +- enable parallel building +* Fri Jun 26 2009 kukuk@suse.de +- Add fixes from CVS +* Wed Jun 24 2009 kukuk@suse.de +- Update to final version 1.1.0 (spelling fixes) +* Tue May 5 2009 kukuk@suse.de +- Update to version 1.0.92: + * Update translations + * pam_succeed_if: Use provided username + * pam_mkhomedir: Fix handling of options +* Fri Apr 3 2009 rguenther@suse.de +- Remove cracklib-dict-full and pwdutils BuildRequires again. +* Fri Mar 27 2009 kukuk@suse.de +- Update to version 1.0.91 aka 1.1 Beta2: + * Changes in the behavior of the password stack. Results of + PRELIM_CHECK are not used for the final run. + * Redefine LOCAL keyword of pam_access configuration file + * Add support for try_first_pass and use_first_pass to + pam_cracklib + * New password quality tests in pam_cracklib + * Add support for passing PAM_AUTHTOK to stdin of helpers from + pam_exec + * New options for pam_lastlog to show last failed login attempt and + to disable lastlog update + * New pam_pwhistory module to store last used passwords + * New pam_tally2 module similar to pam_tally with wordsize independent + tally data format, obsoletes pam_tally + * Make libpam not log missing module if its type is prepended with '-' + * New pam_timestamp module for authentication based on recent successful + login. + * Add blowfish support to pam_unix. + * Add support for user specific environment file to pam_env. + * Add pam_get_authtok to libpam as Linux-PAM extension. +* Wed Feb 11 2009 ro@suse.de +- use sr@latin instead of sr@Latn +* Thu Feb 5 2009 kukuk@suse.de +- Log failures of setrlimit in pam_limits [bnc#448314] +- Fix using of requisite in password stack [bnc#470337] +* Tue Jan 20 2009 kukuk@suse.de +- Regenerate documentation [bnc#448314] +* Wed Dec 10 2008 olh@suse.de +- use Obsoletes: -XXbit only for ppc64 to help solver during distupgrade + (bnc#437293) +* Thu Dec 4 2008 olh@suse.de +- obsolete old -XXbit packages (bnc#437293) +* Thu Nov 27 2008 mc@suse.de +- enhance the man page for limits.conf (bnc#448314) +* Mon Nov 24 2008 kukuk@suse.de +- pam_time: fix parsing if '|' is used [bdo#326407] +* Wed Nov 19 2008 kukuk@suse.de +- pam_xauth: update last patch +- pam_pwhistory: add missing type option +* Tue Nov 4 2008 mc@suse.de +- pam_xauth: put XAUTHLOCALHOSTNAME into new enviroment + (bnc#441314) +* Fri Oct 17 2008 kukuk@suse.de +- Add pam_tally2 +- Regenerate Documentation +* Sat Oct 11 2008 kukuk@suse.de +- Enhance pam_lastlog with status output +- Add pam_pwhistory as tech preview +* Fri Sep 26 2008 kukuk@suse.de +- pam_tally: fix fd leak +- pam_mail: fix "quiet" option +* Fri Aug 29 2008 kukuk@suse.de +- Update to version 1.0.2 (fix SELinux regression) +- enhance pam_tally [FATE#303753] +- Backport fixes from CVS +* Wed Aug 20 2008 prusnak@suse.cz +- enabled SELinux support [Fate#303662] +* Wed Apr 16 2008 kukuk@suse.de +- Update to version 1.0.1: + - Fixes regression in pam_set_item(). +* Thu Apr 10 2008 ro@suse.de +- added baselibs.conf file to build xxbit packages + for multilib support +* Fri Apr 4 2008 kukuk@suse.de +- Remove devfs lines from securetty [bnc#372241] +* Thu Apr 3 2008 kukuk@suse.de +- Update to version 1.0.0: + - Official first "stable" release + - bug fixes + - translation updates +* Fri Feb 15 2008 kukuk@suse.de +- Update to version 0.99.10.0: + - New substack directive in config file syntax + - New module pam_tty_audit.so for enabling and disabling tty + auditing + - New PAM items PAM_XDISPLAY and PAM_XAUTHDATA + - Improved functionality of pam_namespace.so module (method flags, + namespace.d configuration directory, new options). + - Finaly removed deprecated pam_rhosts_auth module. +* Wed Oct 10 2007 kukuk@suse.de +- Update to version 0.99.9.0: + - misc_conv no longer blocks SIGINT; applications that don't want + user-interruptable prompts should block SIGINT themselves + - Merge fixes from Debian + - Fix parser for pam_group and pam_time +* Wed Jul 18 2007 kukuk@suse.de +- Update to version 0.99.8.1: + - Fix regression in pam_audit +* Fri Jul 6 2007 kukuk@suse.de +- Update to version 0.99.8.0: + - Add translations for ar, ca, da, ru, sv and zu. + - Update hungarian translation. + - Add support for limits.d directory to pam_limits. + - Add minclass option to pam_cracklib + - Add new group syntax to pam_access +* Thu Apr 19 2007 mc@suse.de +- move the documentation into a seperate package (pam-doc) + [partly fixes Bug #265733] +* Mon Mar 26 2007 rguenther@suse.de +- add flex and bison BuildRequires +* Wed Jan 24 2007 mc@suse.de +- add %%verify_permissions for /sbin/unix_chkpwd + [#237625] +* Tue Jan 23 2007 kukuk@suse.de +- Update to Version 0.99.7.1 (security fix) +* Wed Jan 17 2007 kukuk@suse.de +- Update to Version 0.99.7.0 + * Add manual page for pam_unix.so. + * Add pam_faildelay module to set pam_fail_delay() value. + * Fix possible seg.fault in libpam/pam_set_data(). + * Cleanup of configure options. + * Update hungarian translation, fix german translation. +* Wed Jan 17 2007 lnussel@suse.de +- install unix_chkpwd setuid root instead of setgid shadow (#216816) +* Tue Oct 24 2006 kukuk@suse.de +- pam_unix.so/unix_chkpwd: teach about blowfish [#213929] +- pam_namespace.so: Fix two possible buffer overflow +- link against libxcrypt +* Sat Oct 7 2006 kukuk@suse.de +- Update hungarian translation [#210091] +* Tue Sep 19 2006 kukuk@suse.de +- Don't remove pam_unix.so +- Use cracklib again (goes lost with one of the last cleanups) +* Thu Sep 14 2006 kukuk@suse.de +- Add pam_umask.so to common-session [Fate#3621] +* Wed Sep 6 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.6.3 (merges all patches) +* Wed Aug 30 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.6.2 (incorporate last change) +- Add pam_loginuid and fixes from CVS [Fate#300486] +* Wed Aug 23 2006 kukuk@suse.de +- Fix seg.fault in pam_cracklib if retyped password is empty +* Tue Aug 22 2006 kukuk@suse.de +- Remove use_first_pass from pam_unix2.so in password section +* Fri Aug 11 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.6.1 (big documentation update) +* Fri Jul 28 2006 kukuk@suse.de +- Add missing namespace.init script +* Thu Jul 27 2006 kukuk@suse.de +- Reenable audit subsystem [Fate#300486] +* Wed Jun 28 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.5.0 (more manual pages, three new PAM + modules: pam_keyinit, pam_namespace, pam_rhosts) +* Mon Jun 12 2006 kukuk@suse.de +- Update to current CVS (lot of new manual pages and docu) +* Tue May 30 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.4.0 (merge all patches and translations) +* Wed May 24 2006 kukuk@suse.de +- Fix problems found by Coverity +* Wed May 17 2006 schwab@suse.de +- Don't strip binaries. +* Fri May 5 2006 kukuk@suse.de +- Fix pam_tally LFS support [#172492] +* Fri Apr 21 2006 kukuk@suse.de +- Update fr.po and pl.po +* Tue Apr 11 2006 kukuk@suse.de +- Update km.po +* Tue Apr 4 2006 kukuk@suse.de +- Remove obsolete pam-laus from the system +* Mon Mar 27 2006 kukuk@suse.de +- Update translations for pt, pl, fr, fi and cs +- Add translation for uk +* Tue Mar 21 2006 kukuk@suse.de +- Update hu.po +* Tue Mar 21 2006 kukuk@suse.de +- Add translation for tr +* Mon Mar 13 2006 kukuk@suse.de +- Fix order of NULL checks in pam_get_user +- Fix comment in pam_lastlog for translators to be visible in + pot file +- Docu update, remove pam_selinux docu +* Thu Mar 2 2006 kukuk@suse.de +- Update km translation +* Thu Feb 23 2006 kukuk@suse.de +- pam_lastlog: + - Initialize correct struct member [SF#1427401] + - Mark strftime fmt string for translation [SF#1428269] +* Sun Feb 19 2006 kukuk@suse.de +- Update more manual pages +* Sat Feb 18 2006 ro@suse.de +- really disable audit if header file not present +* Tue Feb 14 2006 kukuk@suse.de +- Update fi.po +- Add km.po +- Update pl.po +* Mon Feb 13 2006 kukuk@suse.de +- Update with better manual pages +* Thu Feb 9 2006 kukuk@suse.de +- Add translation for nl, update pt translation +* Fri Jan 27 2006 kukuk@suse.de +- Move devel manual pages to -devel package +- Mark PAM config files as noreplace +- Mark /etc/securetty as noreplace +- Run ldconfig +- Fix libdb/ndbm compat detection with gdbm +- Adjust german translation +- Add all services to pam_listfile +* Wed Jan 25 2006 mls@suse.de +- converted neededforbuild to BuildRequires +* Fri Jan 13 2006 kukuk@suse.de +- Update to Linux-PAM 0.99.3.0 release candiate tar balls + (new translations) +* Mon Jan 9 2006 kukuk@suse.de +- Fix NULL handling for LSB-pam test suite [#141240] +* Sun Jan 8 2006 kukuk@suse.de +- Fix usage of PAM_AUTHTOK_RECOVER_ERR vs. PAM_AUTHTOK_RECOVERY_ERR +* Fri Jan 6 2006 kukuk@suse.de +- NULL is allowed as thirs argument for pam_get_item [#141240] +* Wed Dec 21 2005 kukuk@suse.de +- Add fixes from CVS +* Thu Dec 15 2005 kukuk@suse.de +- Fix pam_lastlog: don't report error on first login +* Tue Dec 13 2005 kukuk@suse.de +- Update to 0.99.2.1 +* Fri Dec 9 2005 kukuk@suse.de +- Add /etc/environment to avoid warnings in syslog +* Mon Dec 5 2005 kukuk@suse.de +- disable SELinux +* Wed Nov 23 2005 kukuk@suse.de +- Update getlogin() fix to final one +* Mon Nov 21 2005 kukuk@suse.de +- Fix PAM getlogin() implementation +* Mon Nov 21 2005 kukuk@suse.de +- Update to official 0.99.2.0 release +* Tue Nov 8 2005 kukuk@suse.de +- Update to new snapshot +* Mon Oct 10 2005 kukuk@suse.de +- Enable original pam_wheel module +* Tue Sep 27 2005 kukuk@suse.de +- Update to current CVS +- Compile libpam_misc with -fno-strict-aliasing +* Mon Sep 19 2005 kukuk@suse.de +- Update to current CVS +- Fix compiling of pammodutil with -fPIC +* Sun Sep 18 2005 kukuk@suse.de +- Update to current CVS +* Tue Aug 23 2005 kukuk@suse.de +- Update to new snapshot (Major version is back to 0) +* Fri Aug 19 2005 kukuk@suse.de +- Update to Linux-PAM 0.99.0.3 snapshot +* Mon Jul 11 2005 kukuk@suse.de +- Add pam_umask +* Mon Jul 4 2005 kukuk@suse.de +- Update to current CVS snapshot +* Thu Jun 23 2005 kukuk@suse.de +- Update to current CVS snapshot +- Add pam_loginuid +* Thu Jun 9 2005 kukuk@suse.de +- Update to current CVS snapshot +* Mon Jun 6 2005 kukuk@suse.de +- Don't reset priority [#81690] +- Fix creating of symlinks +* Fri May 20 2005 kukuk@suse.de +- Update to current CVS snapshot +- Real fix for [#82687] (don't include kernel header files) +* Thu May 12 2005 schubi@suse.de +- Bug 82687 - pam_client.h redefines __u8 and __u32 +* Fri Apr 29 2005 kukuk@suse.de +- Apply lot of fixes from CVS (including SELinux support) +* Fri Apr 1 2005 kukuk@suse.de +- Update to final 0.79 release +* Mon Mar 14 2005 kukuk@suse.de +- Apply patch for pam_xauth to preserve DISPLAY variable [#66885] +* Mon Jan 24 2005 kukuk@suse.de +- Compile with large file support +* Mon Jan 24 2005 schubi@suse.de +- Made patch of latest CVS tree +- Removed patch pam_handler.diff ( included in CVS now ) +- moved Linux-PAM-0.78.dif to pam_group_time.diff +* Wed Jan 5 2005 kukuk@suse.de +- Fix seg.fault, if a PAM config line is incomplete +* Thu Nov 18 2004 kukuk@suse.de +- Update to final 0.78 +* Mon Nov 8 2004 kukuk@suse.de +- Add pam_env.so to common-auth +- Add pam_limit.so to common-session +* Wed Oct 13 2004 kukuk@suse.de +- Update to 0.78-Beta1 +* Wed Sep 22 2004 kukuk@suse.de +- Create pam.d/common-{auth,account,password,session} and include + them in pam.d/other +- Update to current CVS version of upcoming 0.78 release +* Mon Aug 23 2004 kukuk@suse.de +- Update "code cleanup" patch +- Disable reading of /etc/environment in pam_env.so per default +* Thu Aug 19 2004 kukuk@suse.de +- Reenable a "fixed" version of "code cleanup" patch +- Use pam_wheel from pam-modules package +* Wed Aug 18 2004 kukuk@suse.de +- Disable "code cleanup" patch (no more comments about security + fixes) +* Fri Aug 13 2004 kukuk@suse.de +- Apply big "code cleanup" patch [Bug #39673] +* Fri Mar 12 2004 kukuk@suse.de +- pam_wheel: Use original getlogin again, PAM internal does not + work without application help [Bug #35682] +* Sun Jan 18 2004 meissner@suse.de +- We no longer have pam in the buildsystem, so we + need some buildroot magic flags for the dlopen tests. +* Thu Jan 15 2004 kukuk@suse.de +- Cleanup neededforbuild +* Fri Dec 5 2003 kukuk@suse.de +- Add manual pages from SLES8 +* Fri Nov 28 2003 kukuk@suse.de +- Fix installing manual pages of modules +- Remove pthread check (db is now linked against pthread) +* Thu Nov 27 2003 kukuk@suse.de +- Merge with current CVS +- Apply bug fixes from bugtracking system +- Build as normal user +* Fri Nov 21 2003 kukuk@suse.de +- Compile with noexecstack +* Thu Nov 6 2003 kukuk@suse.de +- Fix pam_securetty CVS patch +* Wed Oct 29 2003 kukuk@suse.de +- Sync with current CVS version +* Thu Oct 2 2003 kukuk@suse.de +- Add patch to implement "include" statement in pamd files +* Wed Sep 10 2003 uli@suse.de +- added ttyS1 (VT220) to securetty on s390* (bug #29239) +* Mon Jul 28 2003 kukuk@suse.de +- Apply lot of fixes for various problems +* Tue Jun 10 2003 kukuk@suse.de +- Fix getlogin handling in pam_wheel.so +* Tue May 27 2003 ro@suse.de +- added cracklib-devel to neededforbuild +* Thu Feb 13 2003 kukuk@suse.de +- Update pam_localuser and pam_xauth. +* Wed Nov 13 2002 kukuk@suse.de +- Update to Linux-PAM 0.77 (minor bug fixes and enhancemants) +* Mon Nov 11 2002 ro@suse.de +- changed neededforbuild to +* Sat Sep 14 2002 ro@suse.de +- changed securetty / use extra file +* Fri Sep 13 2002 bk@suse.de +- 390: standard console (4,64)/ttyS0 ->only ttyS0 in /etc/securetty +* Tue Aug 27 2002 kukuk@suse.de +- Call password checking helper from pam_unix.so whenever the + passwd field is invalid. +* Sat Aug 24 2002 kukuk@suse.de +- Don't build ps and pdf documentation +* Fri Aug 9 2002 kukuk@suse.de +- pam-devel requires pam [Bug #17543] +* Wed Jul 17 2002 kukuk@suse.de +- Remove explicit requires +* Wed Jul 10 2002 kukuk@suse.de +- Update to Linux-PAM 0.76 +- Remove reentrant patch for original PAM modules (needs to be + rewritten for new PAM version) +- Add docu in PDF format +* Thu Jul 4 2002 kukuk@suse.de +- Fix build on different partitions +* Tue Apr 16 2002 mmj@suse.de +- Fix to not own /usr/shar/man/man3 +* Wed Mar 13 2002 kukuk@suse.de +- Add /usr/include/security to pam-devel filelist +* Mon Feb 11 2002 ro@suse.de +- tar option for bz2 is "j" +* Fri Jan 25 2002 kukuk@suse.de +- Fix last pam_securetty patch +* Thu Jan 24 2002 kukuk@suse.de +- Use reentrant getpwnam functions for most modules +- Fix unresolved symbols in pam_access and pam_userdb +* Sun Jan 20 2002 kukuk@suse.de +- libpam_misc: Don't handle Ctrl-D as error. +* Wed Jan 16 2002 kukuk@suse.de +- Remove SuSEconfig.pam +- Update pam_localuser and pam_xauth +- Add new READMEs about blowfish and cracklib +* Mon Nov 12 2001 kukuk@suse.de +- Remove pam_unix.so (is part of pam-modules) +* Fri Nov 9 2001 kukuk@suse.de +- Move extra PAM modules to separate package +- Require pam-modules package +* Fri Aug 24 2001 kukuk@suse.de +- Move susehelp config file to susehelp package +* Mon Aug 13 2001 ro@suse.de +- changed neededforbuild to +* Tue Aug 7 2001 kukuk@suse.de +- Fixes wrong symlink handling of pam_homecheck [Bug #3905] +* Wed Jul 11 2001 kukuk@suse.de +- Sync pam_homecheck and pam_unix2 fixes from 7.2 +- Always ask for the old password if it is expired +* Sat May 5 2001 kukuk@suse.de +- Cleanup Patches, make tar archive from extra pam modules +* Fri May 4 2001 kukuk@suse.de +- Use LOG_NOTICE for trace option [Bug #7673] +* Thu Apr 12 2001 kukuk@suse.de +- Linux-PAM: link pam_access against libnsl +- Add pam.conf for susehelp/pam html docu +* Tue Apr 10 2001 kukuk@suse.de +- Linux-PAM: Update to version 0.75 +* Tue Apr 3 2001 kukuk@suse.de +- Linux-PAM: link libpam_misc against libpam [Bug #6890] +* Thu Mar 8 2001 kukuk@suse.de +- Linux-PAM: Fix manual pages (.so reference) +- pam_pwcheck: fix Makefile +* Tue Mar 6 2001 kukuk@suse.de +- Update for Linux-PAM 0.74 +- Drop pwdb subpackage +* Tue Feb 13 2001 kukuk@suse.de +- pam_unix2: Create temp files with permission 0600 +* Tue Feb 6 2001 ro@suse.de +- pam_issue.c: include time.h to make it compile +* Fri Jan 5 2001 kukuk@suse.de +- Don't print error message about failed initialization from + pam_limits with kernel 2.2 [Bug #5198] +* Thu Jan 4 2001 kukuk@suse.de +- Adjust docu for pam_limits +* Sun Dec 17 2000 kukuk@suse.de +- Adjust docu for pam_pwcheck +* Thu Dec 7 2000 kukuk@suse.de +- Add fix for pam_limits from 0.73 +* Thu Oct 26 2000 kukuk@suse.de +- Add db-devel to need for build +* Fri Oct 20 2000 kukuk@suse.de +- Don't link PAM modules against old libpam library +* Wed Oct 18 2000 kukuk@suse.de +- Create new "devel" subpackage +* Thu Oct 12 2000 kukuk@suse.de +- Add SuSEconfig.pam +* Tue Oct 3 2000 kukuk@suse.de +- Fix problems with new gcc and glibc 2.2 header files +* Wed Sep 13 2000 kukuk@suse.de +- Fix problem with passwords longer then PASS_MAX_LEN +* Wed Sep 6 2000 kukuk@suse.de +- Add missing PAM modules to filelist +- Fix seg.fault in pam_pwcheck [BUG #3894] +- Clean spec file +* Fri Jun 23 2000 kukuk@suse.de +- Lot of bug fixes in pam_unix2 and pam_pwcheck +- compress postscript docu +* Mon May 15 2000 kukuk@suse.de +- Move docu to /usr/share/doc/pam +- Fix some bugs in pam_unix2 and pam_pwcheck +* Tue Apr 25 2000 kukuk@suse.de +- Add pam_homecheck Module +* Tue Apr 25 2000 kukuk@suse.de +- Add devfs devices to /etc/securetty +* Wed Mar 1 2000 kukuk@suse.de +- Fix handling of changing passwords to empty one +* Tue Feb 22 2000 kukuk@suse.de +- Set correct attr for unix_chkpwd and pwdb_chkpwd +* Tue Feb 15 2000 kukuk@suse.de +- Update pam_pwcheck +- Update pam_unix2 +* Mon Feb 7 2000 kukuk@suse.de +- pwdb: Update to 0.61 +* Thu Jan 27 2000 kukuk@suse.de +- Add config files and README for md5 passwords +- Update pam_pwcheck +- Update pam_unix2 +* Thu Jan 13 2000 kukuk@suse.de +- Update pam_unix2 +- New: pam_pwcheck +- Update to Linux-PAM 0.72 +* Wed Oct 13 1999 kukuk@suse.de +- pam_pwdb: Add security fixes from RedHat +* Mon Oct 11 1999 kukuk@suse.de +- Update to Linux-PAM 0.70 +- Update to pwdb-0.60 +- Fix more pam_unix2 shadow bugs +* Fri Oct 8 1999 kukuk@suse.de +- Add more PAM fixes +- Implement Password changing request (sp_lstchg == 0) +* Mon Sep 13 1999 bs@suse.de +- ran old prepare_spec on spec file to switch to new prepare_spec. +* Sat Sep 11 1999 kukuk@suse.de +- Add pam_wheel to file list +- pam_wheel: Minor fixes +- pam_unix2: root is allowed to change passwords with wrong + password aging information +* Mon Aug 30 1999 kukuk@suse.de +- pam_unix2: Fix typo +* Thu Aug 19 1999 kukuk@suse.de +- Linux-PAM: Update to version 0.69 +* Fri Jul 16 1999 kukuk@suse.de +- pam_unix2: Root is allowed to use the old password again. +* Tue Jul 13 1999 kukuk@suse.de +- pam_unix2: Allow root to set an empty password. +* Sat Jul 10 1999 kukuk@suse.de +- Add HP-UX password aging to pam_unix2. +* Wed Jul 7 1999 kukuk@suse.de +- Don't install .cvsignore files +- Make sure, /etc/shadow has the correct rights +* Tue Jul 6 1999 kukuk@suse.de +- Update to Linux-PAM 0.68 +* Wed Jun 30 1999 kukuk@suse.de +- pam_unix2: more bug fixes +* Tue Jun 29 1999 kukuk@suse.de +- pam_unix2: Fix "inactive" password +* Mon Jun 28 1999 kukuk@suse.de +- pam_warn: Add missing functions +- other.pamd: Update +- Add more doku +* Thu Jun 24 1999 kukuk@suse.de +- Add securetty config file +- Fix Debian pam_env patch +* Mon Jun 21 1999 kukuk@suse.de +- Update to Linux-PAM 0.67 +- Add Debian pam_env patch +* Thu Jun 17 1999 kukuk@suse.de +- pam_ftp malloc (core dump) fix +* Tue Jun 15 1999 kukuk@suse.de +- pam_unix2 fixes +* Mon Jun 7 1999 kukuk@suse.de +- First PAM package: pam 0.66, pwdb 0.57 and pam_unix2 diff --git a/pam.spec b/pam.spec new file mode 100644 index 0000000..38a53e5 --- /dev/null +++ b/pam.spec @@ -0,0 +1,427 @@ +# +# spec file for package pam +# +# Copyright (c) 2022-2023 ZhuningOS +# + + +# +%define enable_selinux 1 +# +%{load:%{_sourcedir}/macros.pam} +# +Name: pam +Url: http://www.linux-pam.org/ +BuildRequires: audit-devel +BuildRequires: bison +BuildRequires: cracklib-devel +BuildRequires: flex +%if 0%{?suse_version} > 1320 +BuildRequires: pkgconfig(libnsl) +BuildRequires: pkgconfig(libtirpc) +%endif +%if %{enable_selinux} +BuildRequires: libselinux-devel +%endif +%define libpam_so_version 0.84.2 +%define libpam_misc_so_version 0.82.1 +%define libpamc_so_version 0.82.1 +# +Version: 1.3.0 +Release: 150000.6.66.1 +Summary: A Security Tool that Provides Authentication for Applications +License: GPL-2.0+ or BSD-3-Clause +Group: System/Libraries +PreReq: permissions +%if 0%{?suse_version} >= 1330 +Requires(pre): group(shadow) +Requires(pre): user(root) +%endif + +#DL-URL: https://fedorahosted.org/releases/l/i/linux-pam/ +Source: Linux-PAM-%{version}.tar.bz2 +Source1: Linux-PAM-%{version}-docs.tar.bz2 +Source2: securetty +Source3: other.pamd +Source4: common-auth.pamd +Source5: common-account.pamd +Source6: common-password.pamd +Source7: common-session.pamd +Source8: etc.environment +Source9: baselibs.conf +Source10: unix2_chkpwd.c +Source11: unix2_chkpwd.8 +Source12: macros.pam +Source13: pam.tmpfiles +Patch0: fix-man-links.dif +Patch3: encryption_method_nis.diff +Patch4: pam-hostnames-in-access_conf.patch +Patch5: pam-fix-config-order-in-manpage.patch +Patch6: use-correct-IP-address.patch +Patch8: pam-xauth_ownership.patch +Patch9: pam-bsc1178727-initialize-daysleft.patch +Patch10: pam-bsc1177858-dont-free-environment-string.patch +Patch11: pam-pam_cracklib-add-usersubstr.patch +Patch12: pam-bsc1181443-make-nofile-unlimited-mean-nr_open.patch +Patch13: bsc1184358-prevent-LOCAL-from-being-resolved.patch +Patch14: pam-sle20638-add-pam_faillock.patch +Patch15: pam-bsc1197024-free-addrinfo-before-return.patch +Patch16: pam-bsc1197794-do-not-include-obsolete-header-files.patch +Patch17: pam-ped1712-pam_motd-directory-feature.patch +Patch18: pam-bsc1217000-pam_lastlog-check-localtime_r-return-value.patch +Patch19: pam-bsc1218475-pam_namespace-O_DIRECTORY-flag.patch +BuildRoot: %{_tmppath}/%{name}-%{version}-build +# Remove with next version update: +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool + +%description +PAM (Pluggable Authentication Modules) is a system security tool that +allows system administrators to set authentication policies without +having to recompile programs that do authentication. + +%package extra +Summary: PAM module to authenticate against a separate database +Group: System/Libraries%description +BuildRequires: libdb-4_8-devel +BuildRequires: pam-devel + +%description extra +PAM (Pluggable Authentication Modules) is a system security tool that +allows system administrators to set authentication policies without +having to recompile programs that do authentication. + +This package contains useful extra modules eg pam_userdb which is +used to verify a username/password pair against values stored in +a Berkeley DB database. + + + +%package doc +Summary: Documentation for Pluggable Authentication Modules +Group: Documentation/HTML +%if 0%{?suse_version} >= 1140 +BuildArch: noarch +%endif + +%description doc +PAM (Pluggable Authentication Modules) is a system security tool that +allows system administrators to set authentication policies without +having to recompile programs that do authentication. + +This package contains the documentation. + + + +%package devel +Summary: Include Files and Libraries for PAM-Development +Group: Development/Libraries/C and C++ +Requires: glibc-devel +Requires: pam = %{version} + +%description devel +PAM (Pluggable Authentication Modules) is a system security tool which +allows system administrators to set authentication policy without +having to recompile programs which do authentication. + +This package contains header files and static libraries used for +building both PAM-aware applications and modules for use with PAM. + +%prep +%setup -q -n Linux-PAM-%{version} -b 1 +%patch0 -p1 +%patch3 -p0 +%patch4 -p0 +%patch5 -p1 +%patch6 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 + +%build +autoreconf -fiv +export CFLAGS="%optflags -DNDEBUG" +%configure \ + --sbindir=/sbin \ + --includedir=%_includedir/security \ + --docdir=%{_docdir}/pam \ + --htmldir=%{_docdir}/pam/html \ + --pdfdir=%{_docdir}/pam/pdf \ + --libdir=/%{_lib} \ + --enable-isadir=../..%{_pam_moduledir} \ + --enable-securedir=%{_pam_moduledir} +make %{?_smp_mflags} +# These two files are introduced through a patch so they do not +# get the required execute permission. +chmod 750 build-aux/test-driver modules/pam_faillock/tst-pam_faillock +%__cc -fwhole-program -fpie -pie -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE %{optflags} -I$RPM_BUILD_DIR/Linux-PAM-%{version}/libpam/include %{SOURCE10} -o $RPM_BUILD_DIR/unix2_chkpwd -L$RPM_BUILD_DIR/Linux-PAM-%{version}/libpam/.libs/ -lpam + +%check +make %{?_smp_mflags} check + +%install +mkdir -p $RPM_BUILD_ROOT/etc/pam.d +mkdir -p $RPM_BUILD_ROOT/usr/include/security +mkdir -p $RPM_BUILD_ROOT%{_pam_moduledir} +mkdir -p $RPM_BUILD_ROOT/sbin +mkdir -p -m 755 $RPM_BUILD_ROOT%{_libdir} +make DESTDIR=$RPM_BUILD_ROOT install +/sbin/ldconfig -n $RPM_BUILD_ROOT/%{_lib} +# Install documentation +make -C doc install DESTDIR=$RPM_BUILD_ROOT +# install /etc/environment +install -m 644 %{SOURCE8} $RPM_BUILD_ROOT/etc/environment +# install securetty +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc +# install tmpfiles +install -Dm0644 %{SOURCE13} %{buildroot}%{_tmpfilesdir}/pam.conf +%ifarch s390 s390x +echo "ttyS0" >> $RPM_BUILD_ROOT/etc/securetty +echo "ttyS1" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc0" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc1" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc2" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc3" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc4" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc5" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc6" >> $RPM_BUILD_ROOT/etc/securetty +echo "hvc7" >> $RPM_BUILD_ROOT/etc/securetty +echo "sclp_line0" >> $RPM_BUILD_ROOT/etc/securetty +echo "ttysclp0" >> $RPM_BUILD_ROOT/etc/securetty +%endif +# install other.pamd and common-*.pamd +install -m 644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/other +install -m 644 %{SOURCE4} $RPM_BUILD_ROOT/etc/pam.d/common-auth +install -m 644 %{SOURCE5} $RPM_BUILD_ROOT/etc/pam.d/common-account +install -m 644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/common-password +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT/etc/pam.d/common-session +rm $RPM_BUILD_ROOT/%{_lib}/libpam.so +ln -sf ../../%{_lib}/libpam.so.%{libpam_so_version} $RPM_BUILD_ROOT%{_libdir}/libpam.so +rm $RPM_BUILD_ROOT/%{_lib}/libpamc.so +ln -sf ../../%{_lib}/libpamc.so.%{libpamc_so_version} $RPM_BUILD_ROOT%{_libdir}/libpamc.so +rm $RPM_BUILD_ROOT/%{_lib}/libpam_misc.so +ln -sf ../../%{_lib}/libpam_misc.so.%{libpam_misc_so_version} $RPM_BUILD_ROOT%{_libdir}/libpam_misc.so +# +# Remove crap +# +rm -rf $RPM_BUILD_ROOT/%{_lib}/*.la $RPM_BUILD_ROOT%{_pam_moduledir}/*.la +for x in pam_unix_auth pam_unix_acct pam_unix_passwd pam_unix_session; do + ln -f $RPM_BUILD_ROOT%{_pam_moduledir}/pam_unix.so $RPM_BUILD_ROOT%{_pam_moduledir}/$x.so +done +# +# Install READMEs of PAM modules +# +DOC=$RPM_BUILD_ROOT%{_defaultdocdir}/pam +mkdir -p $DOC/modules +( + cd modules; + for i in pam_*/README ; do + cp -fpv ${i} $DOC/modules/README.`dirname ${i}` + done +) +# +# pam_tally is deprecated since ages +# +rm -f $RPM_BUILD_ROOT%{_pam_moduledir}/pam_tally.so +rm -f $RPM_BUILD_ROOT/sbin/pam_tally +rm -f $RPM_BUILD_ROOT%{_mandir}/man8/pam_tally.8* +rm -f $RPM_BUILD_ROOT%{_defaultdocdir}/pam/modules/README.pam_tally +# Install unix2_chkpwd +install -m 755 $RPM_BUILD_DIR/unix2_chkpwd $RPM_BUILD_ROOT/sbin/ +install -m 644 $RPM_SOURCE_DIR/unix2_chkpwd.8 $RPM_BUILD_ROOT%{_mandir}/man8/ +# rpm macros +install -D -m 644 %{SOURCE12} %{buildroot}%{_rpmmacrodir}/macros.pam +# Create filelist with translatins +%{find_lang} Linux-PAM + +%verifyscript +%verify_permissions -e /sbin/unix_chkpwd +%verify_permissions -e /sbin/unix2_chkpwd + +%post +/sbin/ldconfig +%set_permissions /sbin/unix_chkpwd +%set_permissions /sbin/unix2_chkpwd +%tmpfiles_create %{_tmpfilesdir}/pam.conf + +%postun -p /sbin/ldconfig + +%files -f Linux-PAM.lang +%defattr(-,root,root) +%dir %{_sysconfdir}/pam.d +%dir %{_sysconfdir}/security +%dir %{_sysconfdir}/security/limits.d +%dir %{_defaultdocdir}/pam +%config(noreplace) %{_sysconfdir}/pam.d/other +%config(noreplace) %{_sysconfdir}/pam.d/common-* +%config(noreplace) %{_sysconfdir}/securetty +%config(noreplace) %{_sysconfdir}/environment +%config(noreplace) %{_sysconfdir}/security/access.conf +%config(noreplace) %{_sysconfdir}/security/group.conf +%config(noreplace) %{_sysconfdir}/security/limits.conf +%config(noreplace) %{_sysconfdir}/security/pam_env.conf +%if %{enable_selinux} +%config(noreplace) %{_sysconfdir}/security/sepermit.conf +%endif +%config(noreplace) %{_sysconfdir}/security/time.conf +%config(noreplace) %{_sysconfdir}/security/namespace.conf +%config(noreplace) %{_sysconfdir}/security/namespace.init +%config(noreplace) %{_sysconfdir}/security/faillock.conf +%doc NEWS +%license COPYING +%doc %{_mandir}/man5/environment.5* +%doc %{_mandir}/man5/*.conf.5* +%doc %{_mandir}/man5/pam.d.5* +%dir %{_mandir}/man8 +%doc %{_mandir}/man8/pam.8.gz +%doc %{_mandir}/man8/pam_access.8.gz +%doc %{_mandir}/man8/pam_cracklib.8.gz +%doc %{_mandir}/man8/pam_debug.8.gz +%doc %{_mandir}/man8/pam_deny.8.gz +%doc %{_mandir}/man8/pam_echo.8.gz +%doc %{_mandir}/man8/pam_env.8.gz +%doc %{_mandir}/man8/pam_exec.8.gz +%doc %{_mandir}/man8/pam_faildelay.8.gz +%doc %{_mandir}/man8/pam_faillock.8.gz +%doc %{_mandir}/man8/faillock.8.gz +%doc %{_mandir}/man8/pam_filter.8.gz +%doc %{_mandir}/man8/pam_ftp.8.gz +%doc %{_mandir}/man8/pam_group.8.gz +%doc %{_mandir}/man8/pam_issue.8.gz +%doc %{_mandir}/man8/pam_keyinit.8.gz +%doc %{_mandir}/man8/pam_lastlog.8.gz +%doc %{_mandir}/man8/pam_limits.8.gz +%doc %{_mandir}/man8/pam_listfile.8.gz +%doc %{_mandir}/man8/pam_localuser.8.gz +%doc %{_mandir}/man8/pam_loginuid.8.gz +%doc %{_mandir}/man8/pam_mail.8.gz +%doc %{_mandir}/man8/pam_mkhomedir.8.gz +%doc %{_mandir}/man8/pam_motd.8.gz +%doc %{_mandir}/man8/pam_namespace.8.gz +%doc %{_mandir}/man8/pam_nologin.8.gz +%doc %{_mandir}/man8/pam_permit.8.gz +%doc %{_mandir}/man8/pam_pwhistory.8.gz +%doc %{_mandir}/man8/pam_rhosts.8.gz +%doc %{_mandir}/man8/pam_rootok.8.gz +%doc %{_mandir}/man8/pam_securetty.8.gz +%doc %{_mandir}/man8/pam_selinux.8.gz +%doc %{_mandir}/man8/pam_sepermit.8.gz +%doc %{_mandir}/man8/pam_shells.8.gz +%doc %{_mandir}/man8/pam_succeed_if.8.gz +%doc %{_mandir}/man8/pam_tally2.8.gz +%doc %{_mandir}/man8/pam_time.8.gz +%doc %{_mandir}/man8/pam_timestamp.8.gz +%doc %{_mandir}/man8/pam_timestamp_check.8.gz +%doc %{_mandir}/man8/pam_tty_audit.8.gz +%doc %{_mandir}/man8/pam_umask.8.gz +%doc %{_mandir}/man8/pam_unix.8.gz +%doc %{_mandir}/man8/pam_warn.8.gz +%doc %{_mandir}/man8/pam_wheel.8.gz +%doc %{_mandir}/man8/pam_xauth.8.gz +%doc %{_mandir}/man8/PAM.8.gz +%doc %{_mandir}/man8/mkhomedir_helper.8.gz +%doc %{_mandir}/man8/unix2_chkpwd.8.gz +%doc %{_mandir}/man8/unix_chkpwd.8.gz +%doc %{_mandir}/man8/unix_update.8.gz +/%{_lib}/libpam.so.0 +/%{_lib}/libpam.so.%{libpam_so_version} +/%{_lib}/libpamc.so.0 +/%{_lib}/libpamc.so.%{libpamc_so_version} +/%{_lib}/libpam_misc.so.0 +/%{_lib}/libpam_misc.so.%{libpam_misc_so_version} +%dir %{_pam_moduledir} +%{_pam_moduledir}/pam_access.so +%{_pam_moduledir}/pam_cracklib.so +%{_pam_moduledir}/pam_debug.so +%{_pam_moduledir}/pam_deny.so +%{_pam_moduledir}/pam_echo.so +%{_pam_moduledir}/pam_env.so +%{_pam_moduledir}/pam_exec.so +%{_pam_moduledir}/pam_faildelay.so +%{_pam_moduledir}/pam_faillock.so +%{_pam_moduledir}/pam_filter.so +%dir %{_pam_moduledir}/pam_filter +%{_pam_moduledir}//pam_filter/upperLOWER +%{_pam_moduledir}/pam_ftp.so +%{_pam_moduledir}/pam_group.so +%{_pam_moduledir}/pam_issue.so +%{_pam_moduledir}/pam_keyinit.so +%{_pam_moduledir}/pam_lastlog.so +%{_pam_moduledir}/pam_limits.so +%{_pam_moduledir}/pam_listfile.so +%{_pam_moduledir}/pam_localuser.so +%{_pam_moduledir}/pam_loginuid.so +%{_pam_moduledir}/pam_mail.so +%{_pam_moduledir}/pam_mkhomedir.so +%{_pam_moduledir}/pam_motd.so +%{_pam_moduledir}/pam_namespace.so +%{_pam_moduledir}/pam_nologin.so +%{_pam_moduledir}/pam_permit.so +%{_pam_moduledir}/pam_pwhistory.so +%{_pam_moduledir}/pam_rhosts.so +%{_pam_moduledir}/pam_rootok.so +%{_pam_moduledir}/pam_securetty.so +%if %{enable_selinux} +%{_pam_moduledir}/pam_selinux.so +%{_pam_moduledir}/pam_sepermit.so +%endif +%{_pam_moduledir}/pam_shells.so +%{_pam_moduledir}/pam_stress.so +%{_pam_moduledir}/pam_succeed_if.so +%{_pam_moduledir}/pam_tally2.so +%{_pam_moduledir}/pam_time.so +%{_pam_moduledir}/pam_timestamp.so +%{_pam_moduledir}/pam_tty_audit.so +%{_pam_moduledir}/pam_umask.so +%{_pam_moduledir}/pam_unix.so +%{_pam_moduledir}/pam_unix_acct.so +%{_pam_moduledir}/pam_unix_auth.so +%{_pam_moduledir}/pam_unix_passwd.so +%{_pam_moduledir}/pam_unix_session.so +%{_pam_moduledir}/pam_warn.so +%{_pam_moduledir}/pam_wheel.so +%{_pam_moduledir}/pam_xauth.so +/sbin/mkhomedir_helper +/sbin/faillock +/sbin/pam_tally2 +/sbin/pam_timestamp_check +%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 +%{_tmpfilesdir}/pam.conf + +%files extra +%defattr(-,root,root,755) +%attr(755,root,root) %{_pam_moduledir}/pam_userdb.so +%attr(644,root,root) %doc %{_mandir}/man8/pam_userdb.8.gz + +%files doc +%defattr(644,root,root,755) +%dir %{_defaultdocdir}/pam +%doc %{_defaultdocdir}/pam/html +%doc %{_defaultdocdir}/pam/modules +%doc %{_defaultdocdir}/pam/pdf +%doc %{_defaultdocdir}/pam/*.txt + +%files devel +%defattr(644,root,root,755) +%dir /usr/include/security +%doc %{_mandir}/man3/pam* +%doc %{_mandir}/man3/misc_conv.3* +%{_includedir}/security/*.h +%{_libdir}/libpam.so +%{_libdir}/libpamc.so +%{_libdir}/libpam_misc.so +%{_rpmmacrodir}/macros.pam + +%changelog diff --git a/pam.tmpfiles b/pam.tmpfiles new file mode 100644 index 0000000..0bfbd8a --- /dev/null +++ b/pam.tmpfiles @@ -0,0 +1,3 @@ +#Type Path Mode User Group Age Argument +d /run/faillock 0755 root root - - +d /run/motd.d 0755 root root - - diff --git a/securetty b/securetty new file mode 100644 index 0000000..180e631 --- /dev/null +++ b/securetty @@ -0,0 +1,10 @@ +# +# This file contains the device names of tty lines (one per line, +# without leading /dev/) on which root is allowed to login. +# +tty1 +tty2 +tty3 +tty4 +tty5 +tty6 diff --git a/unix2_chkpwd.8 b/unix2_chkpwd.8 new file mode 100644 index 0000000..f072b0f --- /dev/null +++ b/unix2_chkpwd.8 @@ -0,0 +1,79 @@ +.\" Copyright (C) 2003 International Business Machines Corporation +.\" This file is distributed according to the GNU General Public License. +.\" See the file COPYING in the top level source directory for details. +.\" +.de Sh \" Subsection +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Ip \" List item +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.TH "UNIX2_CHKPWD" 8 "2003-03-21" "Linux-PAM 0.76" "Linux-PAM Manual" +.SH NAME +unix2_chkpwd \- helper binary that verifies the password of the current user +.SH "SYNOPSIS" +.ad l +.hy 0 + +/sbin/unix2_chkpwd \fIservicename\fR \fIusername\fR +.sp +.ad +.hy +.SH "DESCRIPTION" +.PP +\fBunix2_chkpwd\fR is a helper program for applications that verifies +the password of the current user. It is not intended to be run directly from +the command line and logs a security violation if done so. + +It is typically installed setuid root or setgid shadow and called by +applications, which only wishes to do an user authentification and +nothing more. + +.SH "OPTIONS" +.PP +unix2_chkpwd requires the following arguments: +.TP +\fIpam_service\fR +The name of the service using unix2_chkpwd. This is required to be one of +the services in /etc/pam.d +.TP +\fIusername\fR +The name of the user whose password you want to verify. + +.SH "INPUTS" +.PP +unix2_chkpwd expects the password via stdin. + +.SH "RETURN CODES" +.PP +\fBunix2_chkpwd\fR has the following return codes: +.TP +1 +unix2_chkpwd was inappropriately called from the command line or the password is incorrect. + +.TP +0 +The password is correct. + +.SH "HISTORY" +Written by Olaf Kirch loosely based on unix_chkpwd by Andrew Morgan + +.SH "SEE ALSO" + +.PP +\fBpam\fR(8) + +.SH AUTHOR +Emily Ratliff. diff --git a/unix2_chkpwd.c b/unix2_chkpwd.c new file mode 100644 index 0000000..f33cf5f --- /dev/null +++ b/unix2_chkpwd.c @@ -0,0 +1,337 @@ +/* + * Set*id helper program for PAM authentication. + * + * It is supposed to be called from pam_unix2's + * pam_sm_authenticate function if the function notices + * that it's unable to get the password from the shadow file + * because it doesn't have sufficient permissions. + * + * Copyright (C) 2002 SuSE Linux AG + * + * Written by okir@suse.de, loosely based on unix_chkpwd + * by Andrew Morgan. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFLEN 1024 +#ifndef LOGINDEFS +#define LOGINDEFS "/etc/login.defs" +#endif +#define LOGINDEFS_FAIL_DELAY_KEY "FAIL_DELAY" +#define DEFAULT_FAIL_DELAY_S 10 + +#define PASSWD_CRACKER_DELAY_MS 100 + +enum { + UNIX_PASSED = 0, + UNIX_FAILED = 1 +}; + +static char * program_name; +static char pass[64]; +static int npass = -1; + +/* + * Log error messages + */ +static void +_log_err(int err, const char *format,...) +{ + va_list args; + + va_start(args, format); + openlog(program_name, LOG_CONS | LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +static void +su_sighandler(int sig) +{ + if (sig > 0) { + _log_err(LOG_NOTICE, "caught signal %d.", sig); + exit(sig); + } +} + +/* + * Setup signal handlers + */ +static void +setup_signals(void) +{ + struct sigaction action; + + memset((void *) &action, 0, sizeof(action)); + action.sa_handler = su_sighandler; + action.sa_flags = SA_RESETHAND; + sigaction(SIGILL, &action, NULL); + sigaction(SIGTRAP, &action, NULL); + sigaction(SIGBUS, &action, NULL); + sigaction(SIGSEGV, &action, NULL); + action.sa_handler = SIG_IGN; + action.sa_flags = 0; + sigaction(SIGTERM, &action, NULL); + sigaction(SIGHUP, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGQUIT, &action, NULL); + sigaction(SIGALRM, &action, NULL); +} + +static int +_converse(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + struct pam_response *reply; + int num; + + if (!(reply = malloc(sizeof(*reply) * num_msg))) + return PAM_CONV_ERR; + + for (num = 0; num < num_msg; num++) { + reply[num].resp_retcode = PAM_SUCCESS; + reply[num].resp = NULL; + switch (msg[num]->msg_style) { + case PAM_PROMPT_ECHO_ON: + return PAM_CONV_ERR; + case PAM_PROMPT_ECHO_OFF: + /* read the password from stdin */ + if (npass < 0) { + npass = read(STDIN_FILENO, pass, sizeof(pass)-1); + if (npass < 0) { + _log_err(LOG_DEBUG, "error reading password"); + return UNIX_FAILED; + } + pass[npass] = '\0'; + } + reply[num].resp = strdup(pass); + break; + case PAM_TEXT_INFO: + case PAM_ERROR_MSG: + /* ignored */ + break; + default: + /* Must be an error of some sort... */ + return PAM_CONV_ERR; + } + } + + *resp = reply; + return PAM_SUCCESS; +} + +static int +_authenticate(const char *service, const char *user) +{ + struct pam_conv conv = { _converse, NULL }; + pam_handle_t *pamh; + int err; + + err = pam_start(service, user, &conv, &pamh); + if (err != PAM_SUCCESS) { + _log_err(LOG_ERR, "pam_start(%s, %s) failed (errno %d)", + service, user, err); + return UNIX_FAILED; + } + + err = pam_authenticate(pamh, 0); + if (err != PAM_SUCCESS) + _log_err(LOG_ERR, "pam_authenticate(%s, %s): %s", + service, user, + pam_strerror(pamh, err)); + + if (err == PAM_SUCCESS) + { + err = pam_acct_mgmt(pamh, 0); + if (err == PAM_SUCCESS) + { + int err2 = pam_setcred(pamh, PAM_REFRESH_CRED); + if (err2 != PAM_SUCCESS) + _log_err(LOG_ERR, "pam_setcred(%s, %s): %s", + service, user, + pam_strerror(pamh, err2)); + /* + * ignore errors on refresh credentials. + * If this did not work we use the old once. + */ + } else { + _log_err(LOG_ERR, "pam_acct_mgmt(%s, %s): %s", + service, user, + pam_strerror(pamh, err)); + } + } + + pam_end(pamh, err); + + if (err != PAM_SUCCESS) + return UNIX_FAILED; + return UNIX_PASSED; +} + +static char * +getuidname(uid_t uid) +{ + struct passwd *pw; + static char username[32]; + + pw = getpwuid(uid); + if (pw == NULL) + return NULL; + + strncpy(username, pw->pw_name, sizeof(username)); + username[sizeof(username) - 1] = '\0'; + + endpwent(); + return username; +} + +static int +sane_pam_service(const char *name) +{ + const char *sp; + char path[128]; + + if (strlen(name) > 32) + return 0; + for (sp = name; *sp; sp++) { + if (!isalnum(*sp) && *sp != '_' && *sp != '-') + return 0; + } + + snprintf(path, sizeof(path), "/etc/pam.d/%s", name); + return access(path, R_OK) == 0; +} + +static int +get_system_fail_delay (void) +{ + FILE *fs; + char buf[BUFLEN]; + long int delay = -1; + char *s; + int l; + + fs = fopen(LOGINDEFS, "r"); + if (NULL == fs) { + goto bail_out; + } + + while ((NULL != fgets(buf, BUFLEN, fs)) && (-1 == delay)) { + if (!strstr(buf, LOGINDEFS_FAIL_DELAY_KEY)) { + continue; + } + s = buf + strspn(buf, " \t"); + l = strcspn(s, " \t"); + if (strncmp(LOGINDEFS_FAIL_DELAY_KEY, s, l)) { + continue; + } + s += l; + s += strspn(s, " \t"); + errno = 0; + delay = strtol(s, NULL, 10); + if (errno) { + delay = -1; + } + break; + } + fclose (fs); +bail_out: + delay = (delay < 0) ? DEFAULT_FAIL_DELAY_S : delay; + return (int)delay; +} + +int +main(int argc, char *argv[]) +{ + const char *program_name; + char *service, *user; + int fd; + int result = UNIX_FAILED; + uid_t uid; + + uid = getuid(); + + /* + * Make sure standard file descriptors are connected. + */ + while ((fd = open("/dev/null", O_RDWR)) <= 2) + ; + close(fd); + + /* + * Get the program name + */ + if (argc == 0) + program_name = "unix2_chkpwd"; + else if ((program_name = strrchr(argv[0], '/')) != NULL) + program_name++; + else + program_name = argv[0]; + + /* + * Catch or ignore as many signal as possible. + */ + setup_signals(); + + /* + * Check argument list + */ + if (argc < 2 || argc > 3) { + _log_err(LOG_NOTICE, "Bad number of arguments (%d)", argc); + return UNIX_FAILED; + } + + /* + * Get the service name and do some sanity checks on it + */ + service = argv[1]; + if (!sane_pam_service(service)) { + _log_err(LOG_ERR, "Illegal service name '%s'", service); + return UNIX_FAILED; + } + + /* + * Discourage users messing around (fat chance) + */ + if (isatty(STDIN_FILENO) && uid != 0) { + _log_err(LOG_NOTICE, + "Inappropriate use of Unix helper binary [UID=%d]", + uid); + fprintf(stderr, + "This binary is not designed for running in this way\n" + "-- the system administrator has been informed\n"); + sleep(10); /* this should discourage/annoy the user */ + return UNIX_FAILED; + } + + /* + * determine the caller's user name + */ + user = getuidname(uid); + if (argc == 3 && strcmp(user, argv[2])) { + user = argv[2]; + } + result = _authenticate(service, user); + /* Discourage use of this program as a + * password cracker */ + usleep(PASSWD_CRACKER_DELAY_MS * 1000); + if (result != UNIX_PASSED && uid != 0) + sleep(get_system_fail_delay()); + return result; +} diff --git a/use-correct-IP-address.patch b/use-correct-IP-address.patch new file mode 100644 index 0000000..e23be80 --- /dev/null +++ b/use-correct-IP-address.patch @@ -0,0 +1,25 @@ +Index: Linux-PAM-1.3.0/modules/pam_access/pam_access.c +=================================================================== +--- Linux-PAM-1.3.0.orig/modules/pam_access/pam_access.c ++++ Linux-PAM-1.3.0/modules/pam_access/pam_access.c +@@ -728,7 +728,7 @@ network_netmask_match (pam_handle_t *pam + + /* check netmask */ + if (isipaddr(netmask_ptr, NULL, NULL) == NO) +- { /* netmask as integre value */ ++ { /* netmask as integer value */ + char *endptr = NULL; + netmask = strtol(netmask_ptr, &endptr, 0); + if ((endptr == NULL) || (*endptr != '\0')) +@@ -772,9 +772,9 @@ network_netmask_match (pam_handle_t *pam + + ai = NULL; /* just to be on the safe side */ + +- if (getaddrinfo (string, NULL, &hint, &ai) != 0) ++ if (getaddrinfo (tok, NULL, &hint, &ai) != 0) + { +- pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", string); ++ pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok); + + return NO; + }