+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 @@
+
+
+
++
++
++ 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
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 .
++
++
++
++
++
++ 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 .
+
+
+
+
++
++ 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 motd_dir= 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 @@
+ ]
+ 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='[0;31m'; \
++ grn='[0;32m'; \
++ lgn='[1;32m'; \
++ blu='[1;34m'; \
++ mgn='[0;35m'; \
++ brg='[1m'; \
++ std='[m'; \
++ 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 @@
++
++
++-->
++]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+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
++
++
++
++ --dir /path/to/tally-directory
++
++
++
++ The directory where the user files with the failure records are kept. The
++ default is /var/run/faillock .
++
++
++
++
++
++ --user username
++
++
++
++ The user whose failure records should be displayed or cleared.
++
++
++
++
++
++ --reset
++
++
++
++ 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_faillock 8
++ ,
++
++ pam 8
++
++
++
++
++
++ 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
++
++
++
++ dir=/path/to/tally-directory
++
++
++
++ The directory where the user files with the failure records are kept. The
++ default is /var/run/faillock .
++
++
++
++
++
++ audit
++
++
++
++ Will log the user name into the system log if the user is not found.
++
++
++
++
++
++ silent
++
++
++
++ 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.
++
++
++
++
++
++ no_log_info
++
++
++
++ Don't log informative messages via syslog 3 .
++
++
++
++
++
++ local_users_only
++
++
++
++ Only track failed user authentications attempts for local users
++ in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc.) users.
++ The faillock 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.
++
++
++
++
++
++ nodelay
++
++
++
++ Don't enforce a delay after authentication failures.
++
++
++
++
++
++ deny=n
++
++
++
++ Deny access if the number of consecutive authentication failures
++ for this user during the recent interval exceeds
++ n . The default is 3.
++
++
++
++
++
++ fail_interval=n
++
++
++
++ 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).
++
++
++
++
++
++ unlock_time=n
++
++
++
++ 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 8 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 dir 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.
++
++
++
++
++
++ even_deny_root
++
++
++
++ Root account can become locked as well as regular accounts.
++
++
++
++
++
++ root_unlock_time=n
++
++
++
++ This option implies 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.
++
++
++
++
++
++ admin_group=name
++
++
++
++ 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.
++
++
++
++
++
++
++
++ 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
++
++
++ faillock 8
++ ,
++
++ pam_faillock 8
++ ,
++
++ pam.conf 5
++ ,
++
++ pam.d 5
++ ,
++
++ pam 8
++
++
++
++
++
++ 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
++
++
++
++ {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.
++
++
++
++
++ MODULE TYPES PROVIDED
++
++ The auth and account 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 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
++
++
++
++
++ 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
++
++
++ faillock 8
++ ,
++
++ faillock.conf 5
++ ,
++
++ pam.conf 5
++ ,
++
++ pam.d 5
++ ,
++
++ pam 8
++
++
++
++
++
++ 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;
+ }