Compare commits
No commits in common. "imports/c8-beta/pam-1.3.1-8.el8" and "c8" have entirely different histories.
imports/c8
...
c8
SOURCES
pam-1.3.1-access-handle-hostnames.patchpam-1.3.1-audit-error.patchpam-1.3.1-audit-messages-formatting.patchpam-1.3.1-faillock-create-tallydir.patchpam-1.3.1-faillock-load-conf-from-file.patchpam-1.3.1-inline.patchpam-1.3.1-libpam-support-long-lines.patchpam-1.3.1-namespace-gdm-doc.patchpam-1.3.1-namespace-protect-dir.patchpam-1.3.1-pam-access-local.patchpam-1.3.1-pam-access-resolve-ip.patchpam-1.3.1-pam-cc-compat.patchpam-1.3.1-pam-keyinit-thread-safe.patchpam-1.3.1-pam-limits-unlimited-value.patchpam-1.3.1-pam-misc-configurable.patchpam-1.3.1-pam-modutil-close-write.patchpam-1.3.1-pam-motd-avoid-unnecessary-logging.patchpam-1.3.1-pam-motd-fix-memory-leak.patchpam-1.3.1-pam-motd-fix-segmentation-fault.patchpam-1.3.1-pam-motd-support-multiple-motd-paths.patchpam-1.3.1-pam-pwhistory-load-conf-from-file.patchpam-1.3.1-pam-unix-shadow-password.patchpam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patchpam-1.3.1-pam-usertype-SYS_UID_MAX.patchpam-1.3.1-pam-usertype.patchpam-1.3.1-unix-default-rounds.patchpam-1.3.1-unix-enable-bcrypt.patchpam-1.3.1-wheel-pam_ruser-fallback.patchpam-1.5.1-pam-faillock-avoid-logging-erroneous.patchpam-1.5.1-pam-faillock-clarify-missing-user.patchpam-1.5.1-pam-lastlog-check-localtime_r-return-value.patchpamtmp.confsmartcard-auth.pamd
SPECS
158
SOURCES/pam-1.3.1-access-handle-hostnames.patch
Normal file
158
SOURCES/pam-1.3.1-access-handle-hostnames.patch
Normal file
@ -0,0 +1,158 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames Linux-PAM-1.3.1/modules/pam_access/pam_access.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames 2024-01-19 16:45:18.319862531 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_access/pam_access.c 2024-01-19 16:50:34.239545948 +0100
|
||||
@@ -683,7 +683,7 @@ string_match (pam_handle_t *pamh, const
|
||||
/*
|
||||
* If the token has the magic value "ALL" the match always succeeds.
|
||||
* Otherwise, return YES if the token fully matches the string.
|
||||
- * "NONE" token matches NULL string.
|
||||
+ * "NONE" token matches NULL string.
|
||||
*/
|
||||
|
||||
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
|
||||
@@ -701,7 +701,8 @@ string_match (pam_handle_t *pamh, const
|
||||
|
||||
/* network_netmask_match - match a string against one token
|
||||
* where string is a hostname or ip (v4,v6) address and tok
|
||||
- * represents either a single ip (v4,v6) address or a network/netmask
|
||||
+ * represents either a hostname, a single ip (v4,v6) address
|
||||
+ * or a network/netmask
|
||||
*/
|
||||
static int
|
||||
network_netmask_match (pam_handle_t *pamh,
|
||||
@@ -710,10 +711,12 @@ network_netmask_match (pam_handle_t *pam
|
||||
char *netmask_ptr;
|
||||
char netmask_string[MAXHOSTNAMELEN + 1];
|
||||
int addr_type;
|
||||
+ struct addrinfo *ai = NULL;
|
||||
|
||||
if (item->debug)
|
||||
- pam_syslog (pamh, LOG_DEBUG,
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
"network_netmask_match: tok=%s, item=%s", tok, string);
|
||||
+
|
||||
/* OK, check if tok is of type addr/mask */
|
||||
if ((netmask_ptr = strchr(tok, '/')) != NULL)
|
||||
{
|
||||
@@ -745,52 +748,109 @@ network_netmask_match (pam_handle_t *pam
|
||||
netmask_ptr = number_to_netmask(netmask, addr_type,
|
||||
netmask_string, MAXHOSTNAMELEN);
|
||||
}
|
||||
- }
|
||||
+
|
||||
+ /*
|
||||
+ * Construct an addrinfo list from the IP address.
|
||||
+ * This should not fail as the input is a correct IP address...
|
||||
+ */
|
||||
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||
+ {
|
||||
+ return NO;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- /* NO, then check if it is only an addr */
|
||||
- if (isipaddr(tok, NULL, NULL) != YES)
|
||||
+ {
|
||||
+ /*
|
||||
+ * It is either an IP address or a hostname.
|
||||
+ * Let getaddrinfo sort everything out
|
||||
+ */
|
||||
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||
{
|
||||
+ if (item->debug)
|
||||
+ pam_syslog(pamh, LOG_DEBUG, "cannot resolve hostname \"%s\"", tok);
|
||||
+
|
||||
return NO;
|
||||
}
|
||||
+ netmask_ptr = NULL;
|
||||
+ }
|
||||
|
||||
if (isipaddr(string, NULL, NULL) != YES)
|
||||
{
|
||||
- /* Assume network/netmask with a name of a host. */
|
||||
struct addrinfo hint;
|
||||
|
||||
+ /* Assume network/netmask with a name of a host. */
|
||||
memset (&hint, '\0', sizeof (hint));
|
||||
hint.ai_flags = AI_CANONNAME;
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
|
||||
if (item->gai_rv != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
return NO;
|
||||
+ }
|
||||
else if (!item->res &&
|
||||
(item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
return NO;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
struct addrinfo *runp = item->res;
|
||||
+ struct addrinfo *runp1;
|
||||
|
||||
while (runp != NULL)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
- inet_ntop (runp->ai_family,
|
||||
- runp->ai_family == AF_INET
|
||||
- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
|
||||
- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
|
||||
- buf, sizeof (buf));
|
||||
+ if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return NO;
|
||||
+ }
|
||||
|
||||
- if (are_addresses_equal(buf, tok, netmask_ptr))
|
||||
+ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
|
||||
{
|
||||
- return YES;
|
||||
+ char buf1[INET6_ADDRSTRLEN];
|
||||
+
|
||||
+ if (runp->ai_family != runp1->ai_family)
|
||||
+ continue;
|
||||
+
|
||||
+ if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0)
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return NO;
|
||||
+ }
|
||||
+
|
||||
+ if (are_addresses_equal (buf, buf1, netmask_ptr))
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return YES;
|
||||
+ }
|
||||
}
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
- return (are_addresses_equal(string, tok, netmask_ptr));
|
||||
+ {
|
||||
+ struct addrinfo *runp1;
|
||||
+
|
||||
+ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
|
||||
+ {
|
||||
+ char buf1[INET6_ADDRSTRLEN];
|
||||
+
|
||||
+ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST);
|
||||
+
|
||||
+ if (are_addresses_equal(string, buf1, netmask_ptr))
|
||||
+ {
|
||||
+ freeaddrinfo(ai);
|
||||
+ return YES;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ freeaddrinfo(ai);
|
||||
|
||||
return NO;
|
||||
}
|
35
SOURCES/pam-1.3.1-audit-error.patch
Normal file
35
SOURCES/pam-1.3.1-audit-error.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From b429ea18b1c9c8953df5169c6a453b4255a6f23d Mon Sep 17 00:00:00 2001
|
||||
From: Iker Pedrosa <ikerpedrosam@gmail.com>
|
||||
Date: Thu, 27 Feb 2020 11:48:47 +0100
|
||||
Subject: [PATCH] pam_tty_audit: if kernel audit is disabled return PAM_IGNORE
|
||||
|
||||
If kernel audit is disabled the socket open will return
|
||||
EPROTONOSUPPORT.
|
||||
Return PAM_IGNORE from pam_tty_audit and log a warning
|
||||
in this situation so login is not blocked by the module.
|
||||
---
|
||||
modules/pam_tty_audit/pam_tty_audit.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c
|
||||
index 7dbcada2..589c60a2 100644
|
||||
--- a/modules/pam_tty_audit/pam_tty_audit.c
|
||||
+++ b/modules/pam_tty_audit/pam_tty_audit.c
|
||||
@@ -351,6 +351,14 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
|
||||
fd = nl_open ();
|
||||
if (fd == -1
|
||||
+ && errno == EPROTONOSUPPORT)
|
||||
+ {
|
||||
+ pam_syslog (pamh, LOG_WARNING, "unable to open audit socket, audit not "
|
||||
+ "supported; tty_audit skipped");
|
||||
+ free (old_status);
|
||||
+ return PAM_IGNORE;
|
||||
+ }
|
||||
+ else if (fd == -1
|
||||
|| nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
|
||||
|| nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
|
||||
{
|
||||
--
|
||||
2.25.2
|
||||
|
33
SOURCES/pam-1.3.1-audit-messages-formatting.patch
Normal file
33
SOURCES/pam-1.3.1-audit-messages-formatting.patch
Normal file
@ -0,0 +1,33 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.audit-messages-formatting Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.audit-messages-formatting 2024-03-11 16:21:51.928946604 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c 2024-03-11 16:21:51.934946609 +0100
|
||||
@@ -334,7 +334,7 @@ check_tally(pam_handle_t *pamh, struct o
|
||||
|
||||
(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);
|
||||
+ snprintf(buf, sizeof(buf), "op=pam_faillock suid=%u ", opts->uid);
|
||||
audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf,
|
||||
rhost, NULL, tty, 1);
|
||||
}
|
||||
@@ -450,7 +450,7 @@ write_tally(pam_handle_t *pamh, struct o
|
||||
errno == EAFNOSUPPORT))
|
||||
return PAM_SYSTEM_ERR;
|
||||
|
||||
- snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid);
|
||||
+ snprintf(buf, sizeof(buf), "op=pam_faillock suid=%u ", opts->uid);
|
||||
audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf,
|
||||
NULL, NULL, NULL, 1);
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_selinux/pam_selinux.c.audit-messages-formatting Linux-PAM-1.3.1/modules/pam_selinux/pam_selinux.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_selinux/pam_selinux.c.audit-messages-formatting 2024-03-11 16:21:51.934946609 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_selinux/pam_selinux.c 2024-03-11 16:23:24.521025061 +0100
|
||||
@@ -106,7 +106,7 @@ int send_audit_message(pam_handle_t *pam
|
||||
pam_syslog(pamh, LOG_ERR, "Error translating selected context.");
|
||||
selected_raw = NULL;
|
||||
}
|
||||
- if (asprintf(&msg, "pam: default-context=%s selected-context=%s",
|
||||
+ if (asprintf(&msg, "op=pam_selinux default-context=%s selected-context=%s",
|
||||
default_raw ? default_raw : (default_context ? default_context : "?"),
|
||||
selected_raw ? selected_raw : (selected_context ? selected_context : "?")) < 0) {
|
||||
pam_syslog(pamh, LOG_ERR, "Error allocating memory.");
|
13
SOURCES/pam-1.3.1-faillock-create-tallydir.patch
Normal file
13
SOURCES/pam-1.3.1-faillock-create-tallydir.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir Linux-PAM-1.3.1/modules/pam_faillock/faillock.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir 2024-01-08 11:32:02.122392119 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.c 2024-01-08 11:33:10.916515943 +0100
|
||||
@@ -74,6 +74,9 @@ open_tally (const char *dir, const char
|
||||
|
||||
if (create) {
|
||||
flags |= O_CREAT;
|
||||
+ if (access(dir, F_OK) != 0) {
|
||||
+ mkdir(dir, 0755);
|
||||
+ }
|
||||
}
|
||||
|
||||
fd = open(path, flags, 0600);
|
1212
SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch
Normal file
1212
SOURCES/pam-1.3.1-faillock-load-conf-from-file.patch
Normal file
File diff suppressed because it is too large
Load Diff
105
SOURCES/pam-1.3.1-inline.patch
Normal file
105
SOURCES/pam-1.3.1-inline.patch
Normal file
@ -0,0 +1,105 @@
|
||||
diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h
|
||||
--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline 2022-05-26 10:44:31.702623614 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:44:31.703623621 +0200
|
||||
@@ -44,4 +44,17 @@
|
||||
# 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 */
|
||||
diff -up Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline Linux-PAM-1.3.1/libpam/include/pam_inline.h
|
||||
--- Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline 2022-05-26 10:44:31.703623621 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam/include/pam_inline.h 2022-05-26 10:44:31.703623621 +0200
|
||||
@@ -0,0 +1,67 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 Dmitry V. Levin <ldv@altlinux.org>
|
||||
+ *
|
||||
+ * 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 <string.h>
|
||||
+
|
||||
+/*
|
||||
+ * 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_))
|
||||
+
|
||||
+#endif /* PAM_INLINE_H */
|
||||
diff -up Linux-PAM-1.3.1/libpam/Makefile.am.inline Linux-PAM-1.3.1/libpam/Makefile.am
|
||||
--- Linux-PAM-1.3.1/libpam/Makefile.am.inline 2022-05-26 10:44:31.702623614 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:45:21.146977780 +0200
|
||||
@@ -18,7 +18,8 @@ include_HEADERS = include/security/_pam_
|
||||
include/security/pam_ext.h include/security/pam_modutil.h
|
||||
|
||||
noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
|
||||
- pam_modutil_private.h include/pam_cc_compat.h
|
||||
+ pam_modutil_private.h include/pam_cc_compat.h \
|
||||
+ include/pam_inline.h
|
||||
|
||||
libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84
|
||||
libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@
|
595
SOURCES/pam-1.3.1-libpam-support-long-lines.patch
Normal file
595
SOURCES/pam-1.3.1-libpam-support-long-lines.patch
Normal file
@ -0,0 +1,595 @@
|
||||
diff -up Linux-PAM-1.3.1/libpam/pam_handlers.c.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_handlers.c
|
||||
--- Linux-PAM-1.3.1/libpam/pam_handlers.c.libpam-support-long-lines 2024-11-04 13:17:27.395991844 +0100
|
||||
+++ Linux-PAM-1.3.1/libpam/pam_handlers.c 2024-11-04 14:45:22.583441849 +0100
|
||||
@@ -16,21 +16,30 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-#define BUF_SIZE 1024
|
||||
#define MODULE_CHUNK 4
|
||||
#define UNKNOWN_MODULE "<*unknown module*>"
|
||||
#ifndef _PAM_ISA
|
||||
#define _PAM_ISA "."
|
||||
#endif
|
||||
|
||||
-static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
|
||||
+struct line_buffer {
|
||||
+ char *assembled;
|
||||
+ char *chunk;
|
||||
+ size_t chunk_size;
|
||||
+ size_t len;
|
||||
+ size_t size;
|
||||
+};
|
||||
+
|
||||
+static void _pam_buffer_init(struct line_buffer *buffer);
|
||||
+
|
||||
+static int _pam_assemble_line(FILE *f, struct line_buffer *buf);
|
||||
|
||||
static void _pam_free_handlers_aux(struct handler **hp);
|
||||
|
||||
static int _pam_add_handler(pam_handle_t *pamh
|
||||
, int must_fail, int other, int stack_level, int type
|
||||
, int *actions, const char *mod_path
|
||||
- , int argc, char **argv, int argvlen);
|
||||
+ , int argc, char **argv, size_t argvlen);
|
||||
|
||||
/* Values for module type */
|
||||
|
||||
@@ -58,12 +67,15 @@ static int _pam_parse_conf_file(pam_hand
|
||||
#endif /* PAM_READ_BOTH_CONFS */
|
||||
)
|
||||
{
|
||||
- char buf[BUF_SIZE];
|
||||
+ struct line_buffer buffer;
|
||||
int x; /* read a line from the FILE *f ? */
|
||||
+
|
||||
+ _pam_buffer_init(&buffer);
|
||||
/*
|
||||
* read a line from the configuration (FILE *) f
|
||||
*/
|
||||
- while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) {
|
||||
+ while ((x = _pam_assemble_line(f, &buffer)) > 0) {
|
||||
+ char *buf = buffer.assembled;
|
||||
char *tok, *nexttok=NULL;
|
||||
const char *this_service;
|
||||
const char *mod_path;
|
||||
@@ -73,7 +85,7 @@ static int _pam_parse_conf_file(pam_hand
|
||||
int handler_type = PAM_HT_MODULE; /* regular handler from a module */
|
||||
int argc;
|
||||
char **argv;
|
||||
- int argvlen;
|
||||
+ size_t argvlen;
|
||||
|
||||
D(("_pam_init_handler: LINE: %s", buf));
|
||||
if (known_service != NULL) {
|
||||
@@ -232,10 +244,11 @@ static int _pam_parse_conf_file(pam_hand
|
||||
if (nexttok != NULL) {
|
||||
D(("list: %s",nexttok));
|
||||
argvlen = _pam_mkargv(nexttok, &argv, &argc);
|
||||
- D(("argvlen = %d",argvlen));
|
||||
+ D(("argvlen = %zu",argvlen));
|
||||
} else { /* there are no arguments so fix by hand */
|
||||
D(("_pam_init_handlers: empty argument list"));
|
||||
- argvlen = argc = 0;
|
||||
+ argvlen = 0;
|
||||
+ argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
|
||||
@@ -548,88 +561,243 @@ int _pam_init_handlers(pam_handle_t *pam
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
+static int _pam_buffer_add(struct line_buffer *buffer, char *start, char *end)
|
||||
+{
|
||||
+ size_t len = end - start;
|
||||
+
|
||||
+ D(("assembled: [%zu/%zu] '%s', adding [%zu] '%s'",
|
||||
+ buffer->len, buffer->size,
|
||||
+ buffer->assembled == NULL ? "" : buffer->assembled, len, start));
|
||||
+
|
||||
+ if (start == end)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (buffer->assembled == NULL && buffer->chunk == start) {
|
||||
+ /* no extra allocation needed, just move chunk to assembled */
|
||||
+ buffer->assembled = buffer->chunk;
|
||||
+ buffer->len = len;
|
||||
+ buffer->size = buffer->chunk_size;
|
||||
+
|
||||
+ buffer->chunk = NULL;
|
||||
+ buffer->chunk_size = 0;
|
||||
+
|
||||
+ D(("exiting with quick exchange"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (buffer->len + len + 1 > buffer->size) {
|
||||
+ size_t size;
|
||||
+ char *p;
|
||||
+
|
||||
+ size = buffer->len + len + 1;
|
||||
+ if ((p = realloc(buffer->assembled, size)) == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ buffer->assembled = p;
|
||||
+ buffer->size = size;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(buffer->assembled + buffer->len, start, len);
|
||||
+ buffer->len += len;
|
||||
+ buffer->assembled[buffer->len] = '\0';
|
||||
+
|
||||
+ D(("exiting"));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int _pam_buffer_add_eol(struct line_buffer *buffer,
|
||||
+ char *start, char *end)
|
||||
+{
|
||||
+ if (buffer->assembled != NULL || (*start != '\0' && *start != '\n'))
|
||||
+ return _pam_buffer_add(buffer, start, end);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void _pam_buffer_clear(struct line_buffer *buffer)
|
||||
+{
|
||||
+ _pam_drop(buffer->assembled);
|
||||
+ _pam_drop(buffer->chunk);
|
||||
+ buffer->chunk_size = 0;
|
||||
+ buffer->len = 0;
|
||||
+ buffer->size = 0;
|
||||
+}
|
||||
+
|
||||
+static void _pam_buffer_init(struct line_buffer *buffer)
|
||||
+{
|
||||
+ buffer->assembled = NULL;
|
||||
+ buffer->chunk = NULL;
|
||||
+ _pam_buffer_clear(buffer);
|
||||
+}
|
||||
+
|
||||
+static void _pam_buffer_purge(struct line_buffer *buffer)
|
||||
+{
|
||||
+ _pam_drop(buffer->chunk);
|
||||
+ buffer->chunk_size = 0;
|
||||
+}
|
||||
+
|
||||
+static void _pam_buffer_shift(struct line_buffer *buffer)
|
||||
+{
|
||||
+ if (buffer->assembled == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ _pam_buffer_purge(buffer);
|
||||
+ buffer->chunk = buffer->assembled;
|
||||
+ buffer->chunk_size = buffer->size;
|
||||
+
|
||||
+ buffer->assembled = NULL;
|
||||
+ buffer->size = 0;
|
||||
+ buffer->len = 0;
|
||||
+}
|
||||
+
|
||||
+static inline int _pam_buffer_valid(struct line_buffer *buffer)
|
||||
+{
|
||||
+ return buffer->assembled != NULL && *buffer->assembled != '\0';
|
||||
+}
|
||||
+
|
||||
/*
|
||||
- * This is where we read a line of the PAM config file. The line may be
|
||||
- * preceeded by lines of comments and also extended with "\\\n"
|
||||
+ * Trim string to relevant parts of a configuration line.
|
||||
+ *
|
||||
+ * Preceding whitespaces are skipped and comment (#) marks the end of
|
||||
+ * configuration line.
|
||||
+ *
|
||||
+ * Returns start of configuration line.
|
||||
*/
|
||||
+static inline char *_pam_str_trim(char *str)
|
||||
+{
|
||||
+ /* skip leading spaces */
|
||||
+ str += strspn(str, " \t");
|
||||
+ /*
|
||||
+ * we are only interested in characters before the first '#'
|
||||
+ * character
|
||||
+ */
|
||||
+ str[strcspn(str, "#")] = '\0';
|
||||
|
||||
-static int _pam_assemble_line(FILE *f, char *buffer, int buf_len)
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Remove escaped newline from end of string.
|
||||
+ *
|
||||
+ * Configuration lines may span across multiple lines in a file
|
||||
+ * by ending a line with a backslash (\).
|
||||
+ *
|
||||
+ * If an escaped newline is encountered, the backslash will be
|
||||
+ * replaced with a blank ' ' and the newline itself removed.
|
||||
+ * Then the variable "end" will point to the new end of line.
|
||||
+ *
|
||||
+ * Returns 0 if escaped newline was found and replaced, 1 otherwise.
|
||||
+ */
|
||||
+static inline int _pam_str_unescnl(char *start, char **end)
|
||||
{
|
||||
- char *p = buffer;
|
||||
- char *endp = buffer + buf_len;
|
||||
- char *s, *os;
|
||||
- int used = 0;
|
||||
+ int ret = 1;
|
||||
+ char *p = *end;
|
||||
|
||||
- /* loop broken with a 'break' when a non-'\\n' ended line is read */
|
||||
+ /*
|
||||
+ * Check for backslash by scanning back from the end of
|
||||
+ * the entered line, the '\n' should be included since
|
||||
+ * normally a line is terminated with this character.
|
||||
+ */
|
||||
+ while (p > start && ((*--p == ' ') || (*p == '\t') || (*p == '\n')))
|
||||
+ ;
|
||||
+ if (*p == '\\') {
|
||||
+ *p++ = ' '; /* replace backslash with ' ' */
|
||||
+ *p = '\0'; /* truncate the line here */
|
||||
+ *end = p;
|
||||
+ ret = 0;
|
||||
+ }
|
||||
|
||||
- D(("called."));
|
||||
- for (;;) {
|
||||
- if (p >= endp) {
|
||||
- /* Overflow */
|
||||
- D(("_pam_assemble_line: overflow"));
|
||||
- return -1;
|
||||
- }
|
||||
- if (fgets(p, endp - p, f) == NULL) {
|
||||
- if (used) {
|
||||
- /* Incomplete read */
|
||||
- return -1;
|
||||
- } else {
|
||||
- /* EOF */
|
||||
- return 0;
|
||||
- }
|
||||
- }
|
||||
+ return ret;
|
||||
+}
|
||||
|
||||
- /* skip leading spaces --- line may be blank */
|
||||
+/*
|
||||
+ * Prepare line from file for configuration line parsing.
|
||||
+ *
|
||||
+ * A configuration line may span across multiple lines in a file.
|
||||
+ * Remove comments and skip preceding whitespaces.
|
||||
+ *
|
||||
+ * Returns 0 if line spans across multiple lines, 1 if
|
||||
+ * end of line is encountered.
|
||||
+ */
|
||||
+static inline int _pam_str_prepare(char *line, ssize_t len,
|
||||
+ char **start, char **end)
|
||||
+{
|
||||
+ int ret;
|
||||
|
||||
- s = p + strspn(p, " \n\t");
|
||||
- if (*s && (*s != '#')) {
|
||||
- os = s;
|
||||
+ *start = line;
|
||||
+ *end = line + len;
|
||||
|
||||
- /*
|
||||
- * we are only interested in characters before the first '#'
|
||||
- * character
|
||||
- */
|
||||
+ ret = _pam_str_unescnl(*start, end) || strchr(*start, '#') != NULL;
|
||||
|
||||
- while (*s && *s != '#')
|
||||
- ++s;
|
||||
- if (*s == '#') {
|
||||
- *s = '\0';
|
||||
- used += strlen(os);
|
||||
- break; /* the line has been read */
|
||||
- }
|
||||
+ *start = _pam_str_trim(*start);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * This is where we read a line of the PAM config file. The line may be
|
||||
+ * preceded by lines of comments and also extended with "\\\n"
|
||||
+ *
|
||||
+ * Returns 0 on EOF, 1 on successful line parsing, or -1 on error.
|
||||
+ */
|
||||
+
|
||||
+static int _pam_assemble_line(FILE *f, struct line_buffer *buffer)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* loop broken with a 'break' when a non-'\\n' ended line is read */
|
||||
|
||||
- s = os;
|
||||
+ D(("called."));
|
||||
|
||||
- /*
|
||||
- * Check for backslash by scanning back from the end of
|
||||
- * the entered line, the '\n' has been included since
|
||||
- * normally a line is terminated with this
|
||||
- * character. fgets() should only return one though!
|
||||
- */
|
||||
+ _pam_buffer_shift(buffer);
|
||||
|
||||
- s += strlen(s);
|
||||
- while (s > os && ((*--s == ' ') || (*s == '\t')
|
||||
- || (*s == '\n')));
|
||||
+ for (;;) {
|
||||
+ char *start, *end;
|
||||
+ ssize_t n;
|
||||
+ int eol;
|
||||
|
||||
- /* check if it ends with a backslash */
|
||||
- if (*s == '\\') {
|
||||
- *s++ = ' '; /* replace backslash with ' ' */
|
||||
- *s = '\0'; /* truncate the line here */
|
||||
- used += strlen(os);
|
||||
- p = s; /* there is more ... */
|
||||
+ if ((n = getline(&buffer->chunk, &buffer->chunk_size, f)) == -1) {
|
||||
+ if (ret) {
|
||||
+ /* Incomplete read */
|
||||
+ ret = -1;
|
||||
} else {
|
||||
- /* End of the line! */
|
||||
- used += strlen(os);
|
||||
- break; /* this is the complete line */
|
||||
+ /* EOF */
|
||||
+ ret = 0;
|
||||
}
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ eol = _pam_str_prepare(buffer->chunk, n, &start, &end);
|
||||
|
||||
+ if (eol) {
|
||||
+ if (_pam_buffer_add_eol(buffer, start, end)) {
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (_pam_buffer_valid(buffer)) {
|
||||
+ /* Successfully parsed a line */
|
||||
+ ret = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ /* Start parsing next line */
|
||||
+ _pam_buffer_shift(buffer);
|
||||
+ ret = 0;
|
||||
} else {
|
||||
- /* Nothing in this line */
|
||||
- /* Don't move p */
|
||||
+ /* Configuration line spans across multiple lines in file */
|
||||
+ if (_pam_buffer_add(buffer, start, end)) {
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ /* Keep parsing line */
|
||||
+ ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- return used;
|
||||
+ if (ret == 1)
|
||||
+ _pam_buffer_purge(buffer);
|
||||
+ else
|
||||
+ _pam_buffer_clear(buffer);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -761,7 +929,7 @@ _pam_load_module(pam_handle_t *pamh, con
|
||||
int _pam_add_handler(pam_handle_t *pamh
|
||||
, int handler_type, int other, int stack_level, int type
|
||||
, int *actions, const char *mod_path
|
||||
- , int argc, char **argv, int argvlen)
|
||||
+ , int argc, char **argv, size_t argvlen)
|
||||
{
|
||||
struct loaded_module *mod = NULL;
|
||||
struct handler **handler_p;
|
||||
diff -up Linux-PAM-1.3.1/libpam/pam_misc.c.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_misc.c
|
||||
--- Linux-PAM-1.3.1/libpam/pam_misc.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/libpam/pam_misc.c 2024-11-04 14:47:31.147672755 +0100
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
@@ -163,60 +165,55 @@ char *_pam_memdup(const char *x, int len
|
||||
/* Generate argv, argc from s */
|
||||
/* caller must free(argv) */
|
||||
|
||||
-int _pam_mkargv(char *s, char ***argv, int *argc)
|
||||
+size_t _pam_mkargv(const char *s, char ***argv, int *argc)
|
||||
{
|
||||
- int l;
|
||||
- int argvlen = 0;
|
||||
- char *sbuf, *sbuf_start;
|
||||
+ size_t l;
|
||||
+ size_t argvlen = 0;
|
||||
char **our_argv = NULL;
|
||||
- char **argvbuf;
|
||||
- char *argvbufp;
|
||||
-#ifdef PAM_DEBUG
|
||||
- int count=0;
|
||||
-#endif
|
||||
|
||||
- D(("_pam_mkargv called: %s",s));
|
||||
+ D(("called: %s",s));
|
||||
|
||||
*argc = 0;
|
||||
|
||||
l = strlen(s);
|
||||
- if (l) {
|
||||
- if ((sbuf = sbuf_start = _pam_strdup(s)) == NULL) {
|
||||
- pam_syslog(NULL, LOG_CRIT,
|
||||
- "pam_mkargv: null returned by _pam_strdup");
|
||||
- D(("arg NULL"));
|
||||
+ if (l && l < SIZE_MAX / (sizeof(char) + sizeof(char *))) {
|
||||
+ char **argvbuf;
|
||||
+ /* Overkill on the malloc, but not large */
|
||||
+ argvlen = (l + 1) * (sizeof(char) + sizeof(char *));
|
||||
+ if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
|
||||
+ pam_syslog(NULL, LOG_CRIT, "pam_mkargv: null returned by malloc");
|
||||
+ argvlen = 0;
|
||||
} else {
|
||||
- /* Overkill on the malloc, but not large */
|
||||
- argvlen = (l + 1) * ((sizeof(char)) + sizeof(char *));
|
||||
- if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
|
||||
- pam_syslog(NULL, LOG_CRIT,
|
||||
- "pam_mkargv: null returned by malloc");
|
||||
- } else {
|
||||
- char *tmp=NULL;
|
||||
-
|
||||
- argvbufp = (char *) argvbuf + (l * sizeof(char *));
|
||||
- D(("[%s]",sbuf));
|
||||
- while ((sbuf = _pam_StrTok(sbuf, " \n\t", &tmp))) {
|
||||
- D(("arg #%d",++count));
|
||||
- D(("->[%s]",sbuf));
|
||||
- strcpy(argvbufp, sbuf);
|
||||
- D(("copied token"));
|
||||
- *argvbuf = argvbufp;
|
||||
- argvbufp += strlen(argvbufp) + 1;
|
||||
- D(("stepped in argvbufp"));
|
||||
- (*argc)++;
|
||||
- argvbuf++;
|
||||
- sbuf = NULL;
|
||||
- D(("loop again?"));
|
||||
+ char *argvbufp;
|
||||
+ char *tmp=NULL;
|
||||
+ char *tok;
|
||||
+#ifdef PAM_DEBUG
|
||||
+ unsigned count=0;
|
||||
+#endif
|
||||
+ argvbufp = (char *) argvbuf + (l * sizeof(char *));
|
||||
+ strcpy(argvbufp, s);
|
||||
+ D(("[%s]",argvbufp));
|
||||
+ while ((tok = _pam_StrTok(argvbufp, " \n\t", &tmp))) {
|
||||
+ D(("arg #%u",++count));
|
||||
+ D(("->[%s]",tok));
|
||||
+ *argvbuf++ = tok;
|
||||
+ if (*argc == INT_MAX) {
|
||||
+ pam_syslog(NULL, LOG_CRIT,
|
||||
+ "pam_mkargv: too many arguments");
|
||||
+ argvlen = 0;
|
||||
+ _pam_drop(our_argv);
|
||||
+ break;
|
||||
}
|
||||
+ (*argc)++;
|
||||
+ argvbufp = NULL;
|
||||
+ D(("loop again?"));
|
||||
}
|
||||
- _pam_drop(sbuf_start);
|
||||
}
|
||||
}
|
||||
|
||||
*argv = our_argv;
|
||||
|
||||
- D(("_pam_mkargv returned"));
|
||||
+ D(("exiting"));
|
||||
|
||||
return(argvlen);
|
||||
}
|
||||
diff -up Linux-PAM-1.3.1/libpam/pam_private.h.libpam-support-long-lines Linux-PAM-1.3.1/libpam/pam_private.h
|
||||
--- Linux-PAM-1.3.1/libpam/pam_private.h.libpam-support-long-lines 2024-11-04 13:17:27.404991868 +0100
|
||||
+++ Linux-PAM-1.3.1/libpam/pam_private.h 2024-11-04 14:51:31.654635328 +0100
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
+#include <stddef.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
@@ -266,7 +267,7 @@ char *_pam_strdup(const char *s);
|
||||
|
||||
char *_pam_memdup(const char *s, int len);
|
||||
|
||||
-int _pam_mkargv(char *s, char ***argv, int *argc);
|
||||
+size_t _pam_mkargv(const char *s, char ***argv, int *argc);
|
||||
|
||||
void _pam_sanitize(pam_handle_t *pamh);
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_exec/pam_exec.c 2024-11-04 13:17:27.434991946 +0100
|
||||
@@ -408,7 +408,7 @@ call_exec (const char *pam_type, pam_han
|
||||
_exit (err);
|
||||
}
|
||||
|
||||
- arggv = calloc (argc + 4, sizeof (char *));
|
||||
+ arggv = calloc ((size_t) argc + 1, sizeof (char *));
|
||||
if (arggv == NULL)
|
||||
_exit (ENOMEM);
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_filter/pam_filter.c 2024-11-04 13:17:27.434991946 +0100
|
||||
@@ -101,7 +101,8 @@ static int process_args(pam_handle_t *pa
|
||||
char **levp;
|
||||
const char *user = NULL;
|
||||
const void *tmp;
|
||||
- int i,size, retval;
|
||||
+ int i, retval;
|
||||
+ size_t size;
|
||||
|
||||
*filtername = *++argv;
|
||||
if (ctrl & FILTER_DEBUG) {
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines 2024-11-04 13:17:27.423991918 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2024-11-04 13:17:27.434991946 +0100
|
||||
@@ -83,14 +83,14 @@ static void try_to_display_fd(pam_handle
|
||||
* 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 ***out_arg_split, size_t *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;
|
||||
+ size_t i = 0;
|
||||
+ size_t num_strs = 0;
|
||||
int retval = 0;
|
||||
|
||||
delim_str[0] = delim;
|
||||
@@ -184,13 +184,13 @@ static int filter_dirents(const struct d
|
||||
}
|
||||
|
||||
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)
|
||||
+ char **motd_dir_path_split, size_t 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;
|
||||
+ size_t i;
|
||||
int i_dirnames = 0;
|
||||
|
||||
if (pamh == NULL || motd_dir_path_split == NULL) {
|
||||
@@ -302,11 +302,11 @@ int pam_sm_open_session(pam_handle_t *pa
|
||||
int retval = PAM_IGNORE;
|
||||
const char *motd_path = NULL;
|
||||
char *motd_path_copy = NULL;
|
||||
- unsigned int num_motd_paths = 0;
|
||||
+ size_t 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;
|
||||
+ size_t num_motd_dir_paths = 0;
|
||||
char **motd_dir_path_split = NULL;
|
||||
int report_missing;
|
||||
|
68
SOURCES/pam-1.3.1-namespace-gdm-doc.patch
Normal file
68
SOURCES/pam-1.3.1-namespace-gdm-doc.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 491e5500b6b3913f531574208274358a2df88659 Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Mon, 5 Oct 2020 10:41:29 +0200
|
||||
Subject: [PATCH] pam_namespace: polyinstantiation refer to gdm doc
|
||||
|
||||
modules/pam_namespace/pam_namespace.8.xml: delete obsolete information
|
||||
about polyinstantiation and refer to gdm's documentation.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1861841
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.8.xml | 41 ++---------------------
|
||||
1 file changed, 2 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml
|
||||
index f0f80d33..57c44c4b 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.8.xml
|
||||
+++ b/modules/pam_namespace/pam_namespace.8.xml
|
||||
@@ -343,45 +343,8 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
- To use polyinstantiation with graphical display manager gdm, insert the
|
||||
- following line, before exit 0, in /etc/gdm/PostSession/Default:
|
||||
- </para>
|
||||
-
|
||||
- <para>
|
||||
- /usr/sbin/gdm-safe-restart
|
||||
- </para>
|
||||
-
|
||||
- <para>
|
||||
- This allows gdm to restart after each session and appropriately adjust
|
||||
- namespaces of display manager and the X server. If polyinstantiation
|
||||
- of /tmp is desired along with the graphical environment, then additional
|
||||
- configuration changes are needed to address the interaction of X server
|
||||
- and font server namespaces with their use of /tmp to create
|
||||
- communication sockets. Please use the initialization script
|
||||
- <filename>/etc/security/namespace.init</filename> to ensure that
|
||||
- the X server and its clients can appropriately access the
|
||||
- communication socket X0. Please refer to the sample instructions
|
||||
- provided in the comment section of the instance initialization script
|
||||
- <filename>/etc/security/namespace.init</filename>. In addition,
|
||||
- perform the following changes to use graphical environment with
|
||||
- polyinstantiation of /tmp:
|
||||
- </para>
|
||||
-
|
||||
- <para>
|
||||
- <literallayout>
|
||||
- 1. Disable the use of font server by commenting out "FontPath"
|
||||
- line in /etc/X11/xorg.conf. If you do want to use the font server
|
||||
- then you will have to augment the instance initialization
|
||||
- script to appropriately provide /tmp/.font-unix from the
|
||||
- polyinstantiated /tmp.
|
||||
- 2. Ensure that the gdm service is setup to use pam_namespace,
|
||||
- as described above, by modifying /etc/pam.d/gdm.
|
||||
- 3. Ensure that the display manager is configured to restart X server
|
||||
- with each new session. This default setup can be verified by
|
||||
- making sure that /usr/share/gdm/defaults.conf contains
|
||||
- "AlwaysRestartServer=true", and it is not overridden by
|
||||
- /etc/gdm/custom.conf.
|
||||
- </literallayout>
|
||||
+ To use polyinstantiation with graphical display manager gdm, please refer
|
||||
+ to gdm's documentation.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
--
|
||||
2.26.2
|
||||
|
58
SOURCES/pam-1.3.1-namespace-protect-dir.patch
Normal file
58
SOURCES/pam-1.3.1-namespace-protect-dir.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 031bb5a5d0d950253b68138b498dc93be69a64cb Mon Sep 17 00:00:00 2001
|
||||
From: Matthias Gerstner <matthias.gerstner@suse.de>
|
||||
Date: Wed, 27 Dec 2023 14:01:59 +0100
|
||||
Subject: [PATCH] pam_namespace: protect_dir(): use O_DIRECTORY to prevent
|
||||
local DoS situations
|
||||
|
||||
Without O_DIRECTORY the path crawling logic is subject to e.g. FIFOs
|
||||
being placed in user controlled directories, causing the PAM module to
|
||||
block indefinitely during `openat()`.
|
||||
|
||||
Pass O_DIRECTORY to cause the `openat()` to fail if the path does not
|
||||
refer to a directory.
|
||||
|
||||
With this the check whether the final path element is a directory
|
||||
becomes unnecessary, drop it.
|
||||
---
|
||||
modules/pam_namespace/pam_namespace.c | 18 +-----------------
|
||||
1 file changed, 1 insertion(+), 17 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||
index 2528cff8..f72d6718 100644
|
||||
--- a/modules/pam_namespace/pam_namespace.c
|
||||
+++ b/modules/pam_namespace/pam_namespace.c
|
||||
@@ -1201,7 +1201,7 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
||||
int dfd = AT_FDCWD;
|
||||
int dfd_next;
|
||||
int save_errno;
|
||||
- int flags = O_RDONLY;
|
||||
+ int flags = O_RDONLY | O_DIRECTORY;
|
||||
int rv = -1;
|
||||
struct stat st;
|
||||
|
||||
@@ -1255,22 +1255,6 @@ static int protect_dir(const char *path, mode_t mode, int do_mkdir,
|
||||
rv = openat(dfd, dir, flags);
|
||||
}
|
||||
|
||||
- if (rv != -1) {
|
||||
- if (fstat(rv, &st) != 0) {
|
||||
- save_errno = errno;
|
||||
- close(rv);
|
||||
- rv = -1;
|
||||
- errno = save_errno;
|
||||
- goto error;
|
||||
- }
|
||||
- if (!S_ISDIR(st.st_mode)) {
|
||||
- close(rv);
|
||||
- errno = ENOTDIR;
|
||||
- rv = -1;
|
||||
- goto error;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (flags & O_NOFOLLOW) {
|
||||
/* we are inside user-owned dir - protect */
|
||||
if (protect_mount(rv, p, idata) == -1) {
|
||||
--
|
||||
2.43.0
|
||||
|
215
SOURCES/pam-1.3.1-pam-access-local.patch
Normal file
215
SOURCES/pam-1.3.1-pam-access-local.patch
Normal file
@ -0,0 +1,215 @@
|
||||
From 08992030c56c940c0707ccbc442b1c325aa01e6d Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tmraz@fedoraproject.org>
|
||||
Date: Tue, 6 Apr 2021 12:27:38 +0200
|
||||
Subject: [PATCH] pam_access: clean up the remote host matching code
|
||||
|
||||
* modules/pam_access/pam_access.c (from_match): Split out remote_match()
|
||||
function and avoid calling it when matching against LOCAL keyword.
|
||||
There is also no point in doing domain match against TTY or SERVICE.
|
||||
---
|
||||
modules/pam_access/pam_access.c | 44 +++++++++++++++++++++------------
|
||||
1 file changed, 28 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||||
index 98848c54..277192b9 100644
|
||||
--- a/modules/pam_access/pam_access.c
|
||||
+++ b/modules/pam_access/pam_access.c
|
||||
@@ -160,6 +160,7 @@ static int list_match (pam_handle_t *, char *, char *, struct login_info *,
|
||||
static int user_match (pam_handle_t *, char *, struct login_info *);
|
||||
static int group_match (pam_handle_t *, const char *, const char *, int);
|
||||
static int from_match (pam_handle_t *, char *, struct login_info *);
|
||||
+static int remote_match (pam_handle_t *, char *, struct login_info *);
|
||||
static int string_match (pam_handle_t *, const char *, const char *, int);
|
||||
static int network_netmask_match (pam_handle_t *, const char *, const char *, struct login_info *);
|
||||
|
||||
@@ -589,11 +590,9 @@ group_match (pam_handle_t *pamh, const char *tok, const char* usr,
|
||||
/* from_match - match a host or tty against a list of tokens */
|
||||
|
||||
static int
|
||||
-from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||
+from_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||
{
|
||||
const char *string = item->from;
|
||||
- int tok_len;
|
||||
- int str_len;
|
||||
int rv;
|
||||
|
||||
if (item->debug)
|
||||
@@ -616,14 +615,29 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||
} else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
|
||||
/* ALL or exact match */
|
||||
return rv;
|
||||
- } else if (tok[0] == '.') { /* domain: match last fields */
|
||||
- if ((str_len = strlen(string)) > (tok_len = strlen(tok))
|
||||
- && strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||
- return (YES);
|
||||
- } else if (item->from_remote_host == 0) { /* local: no PAM_RHOSTS */
|
||||
- if (strcasecmp(tok, "LOCAL") == 0)
|
||||
- return (YES);
|
||||
- } else if (tok[(tok_len = strlen(tok)) - 1] == '.') {
|
||||
+ } else if (strcasecmp(tok, "LOCAL") == 0) {
|
||||
+ /* LOCAL matches only local accesses */
|
||||
+ if (!item->from_remote_host)
|
||||
+ return YES;
|
||||
+ return NO;
|
||||
+ } else if (item->from_remote_host) {
|
||||
+ return remote_match(pamh, tok, item);
|
||||
+ }
|
||||
+ return NO;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
|
||||
+{
|
||||
+ const char *string = item->from;
|
||||
+ size_t tok_len = strlen(tok);
|
||||
+ size_t str_len;
|
||||
+
|
||||
+ if (tok[0] == '.') { /* domain: match last fields */
|
||||
+ if ((str_len = strlen(string)) > tok_len
|
||||
+ && strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||
+ return YES;
|
||||
+ } else if (tok[tok_len - 1] == '.') {
|
||||
struct addrinfo hint;
|
||||
|
||||
memset (&hint, '\0', sizeof (hint));
|
||||
@@ -661,13 +675,11 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item)
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
}
|
||||
- } else {
|
||||
- /* Assume network/netmask with a IP of a host. */
|
||||
- if (network_netmask_match(pamh, tok, string, item))
|
||||
- return YES;
|
||||
+ return NO;
|
||||
}
|
||||
|
||||
- return NO;
|
||||
+ /* Assume network/netmask with an IP of a host. */
|
||||
+ return network_netmask_match(pamh, tok, string, item);
|
||||
}
|
||||
|
||||
/* string_match - match a string against one token */
|
||||
--
|
||||
2.47.0
|
||||
|
||||
|
||||
From ecaaf4456e5aeacae1acdb1775bb5aadd3b19e13 Mon Sep 17 00:00:00 2001
|
||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
Date: Wed, 16 Oct 2024 12:41:09 +0200
|
||||
Subject: [PATCH 1/2] pam_access: always match local address
|
||||
|
||||
* modules/pam_access/pam_access.c: match the local address regardless of
|
||||
the IP version in use.
|
||||
|
||||
In some circumstances the `localhost` may be translated to IPv4 or IPv6,
|
||||
but the configuration file only indicated the address for one of the two
|
||||
versions. Since the originating value is set in `PAM_RHOST` and PAM has
|
||||
no control over it, let's match the local addresses regardless of the IP
|
||||
version in use.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-23018
|
||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
---
|
||||
modules/pam_access/pam_access.c | 30 ++++++++++++++++++++++++++++--
|
||||
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
|
||||
index bfbc6d57..48e7c7e9 100644
|
||||
--- a/modules/pam_access/pam_access.c
|
||||
+++ b/modules/pam_access/pam_access.c
|
||||
@@ -306,6 +306,23 @@ isipaddr (const char *string, int *addr_type,
|
||||
return is_ip;
|
||||
}
|
||||
|
||||
+/* is_local_addr - checks if the IP address is local */
|
||||
+static int
|
||||
+is_local_addr (const char *string, int addr_type)
|
||||
+{
|
||||
+ if (addr_type == AF_INET) {
|
||||
+ if (strcmp(string, "127.0.0.1") == 0) {
|
||||
+ return YES;
|
||||
+ }
|
||||
+ } else if (addr_type == AF_INET6) {
|
||||
+ if (strcmp(string, "::1") == 0) {
|
||||
+ return YES;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NO;
|
||||
+}
|
||||
+
|
||||
|
||||
/* are_addresses_equal - translate IP address strings to real IP
|
||||
* addresses and compare them to find out if they are equal.
|
||||
@@ -327,9 +344,18 @@ are_addresses_equal (const char *ipaddr0, const char *ipaddr1,
|
||||
if (isipaddr (ipaddr1, &addr_type1, &addr1) == NO)
|
||||
return NO;
|
||||
|
||||
- if (addr_type0 != addr_type1)
|
||||
- /* different address types */
|
||||
+ if (addr_type0 != addr_type1) {
|
||||
+ /* different address types, but there is still a possibility that they are
|
||||
+ * both local addresses
|
||||
+ */
|
||||
+ int local1 = is_local_addr(ipaddr0, addr_type0);
|
||||
+ int local2 = is_local_addr(ipaddr1, addr_type1);
|
||||
+
|
||||
+ if (local1 == YES && local2 == YES)
|
||||
+ return YES;
|
||||
+
|
||||
return NO;
|
||||
+ }
|
||||
|
||||
if (netmask != NULL) {
|
||||
/* Got a netmask, so normalize addresses? */
|
||||
--
|
||||
2.47.0
|
||||
|
||||
|
||||
From 641dfd1084508c63f3590e93a35b80ffc50774e5 Mon Sep 17 00:00:00 2001
|
||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
Date: Fri, 18 Oct 2024 10:27:07 +0200
|
||||
Subject: [PATCH 2/2] pam_access: clarify `LOCAL` keyword behaviour
|
||||
|
||||
* modules/pam_access/access.conf.5.xml: `LOCAL` keyword behaviour
|
||||
explanation was focused on the development internals. Let's clarify it
|
||||
by rephrasing it to something a sysadmin can understand.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-39943
|
||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
---
|
||||
modules/pam_access/access.conf.5.xml | 17 ++++++-----------
|
||||
1 file changed, 6 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml
|
||||
index 35a1a8fe..0b93db00 100644
|
||||
--- a/modules/pam_access/access.conf.5.xml
|
||||
+++ b/modules/pam_access/access.conf.5.xml
|
||||
@@ -79,17 +79,12 @@
|
||||
with network mask (where network mask can be a decimal number or an
|
||||
internet address also), <emphasis>ALL</emphasis> (which always matches)
|
||||
or <emphasis>LOCAL</emphasis>. The <emphasis>LOCAL</emphasis>
|
||||
- keyword matches if and only if
|
||||
- <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
- when called with an <parameter>item_type</parameter> of
|
||||
- <emphasis>PAM_RHOST</emphasis>, returns <code>NULL</code> or an
|
||||
- empty string (and therefore the
|
||||
- <replaceable>origins</replaceable> field is compared against the
|
||||
- return value of
|
||||
- <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
- called with an <parameter>item_type</parameter> of
|
||||
- <emphasis>PAM_TTY</emphasis> or, absent that,
|
||||
- <emphasis>PAM_SERVICE</emphasis>).
|
||||
+ keyword matches when the user connects without a network
|
||||
+ connection (e.g., <emphasis>su</emphasis>,
|
||||
+ <emphasis>login</emphasis>). A connection through the loopback
|
||||
+ device (e.g., <command>ssh user@localhost</command>) is
|
||||
+ considered a network connection, and thus, the
|
||||
+ <emphasis>LOCAL</emphasis> keyword does not match.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
--
|
||||
2.47.0
|
||||
|
211
SOURCES/pam-1.3.1-pam-access-resolve-ip.patch
Normal file
211
SOURCES/pam-1.3.1-pam-access-resolve-ip.patch
Normal file
@ -0,0 +1,211 @@
|
||||
diff -up Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml
|
||||
--- Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
|
||||
+++ Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml 2024-11-21 10:04:58.553127026 +0100
|
||||
@@ -226,6 +226,14 @@
|
||||
item and the line will be most probably ignored. For this reason, it is not
|
||||
recommended to put spaces around the ':' characters.
|
||||
</para>
|
||||
+ <para>
|
||||
+ An IPv6 link local host address must contain the interface
|
||||
+ identifier. IPv6 link local network/netmask is not supported.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Hostnames should be written as Fully-Qualified Host Name (FQHN) to avoid
|
||||
+ confusion with device names or PAM service names.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="access.conf-see_also">
|
||||
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml
|
||||
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
|
||||
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml 2024-11-21 10:04:58.553127026 +0100
|
||||
@@ -25,11 +25,14 @@
|
||||
<arg choice="opt">
|
||||
debug
|
||||
</arg>
|
||||
+ <arg choice="opt" rep="norepeat">
|
||||
+ noaudit
|
||||
+ </arg>
|
||||
<arg choice="opt">
|
||||
nodefgroup
|
||||
</arg>
|
||||
- <arg choice="opt">
|
||||
- noaudit
|
||||
+ <arg choice="opt" rep="norepeat">
|
||||
+ nodns
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
accessfile=<replaceable>file</replaceable>
|
||||
@@ -114,7 +117,46 @@
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
- <option>fieldsep=<replaceable>separators</replaceable></option>
|
||||
+ nodefgroup
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ User tokens which are not enclosed in parentheses will not be
|
||||
+ matched against the group database. The backwards compatible default is
|
||||
+ to try the group database match even for tokens not enclosed
|
||||
+ in parentheses.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ nodns
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not try to resolve tokens as hostnames, only IPv4 and IPv6
|
||||
+ addresses will be resolved. Which means to allow login from a
|
||||
+ remote host, the IP addresses need to be specified in <filename>access.conf</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ quiet_log
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Do not log denials with
|
||||
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ fieldsep=separators
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
@@ -152,20 +194,6 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
-
|
||||
- <varlistentry>
|
||||
- <term>
|
||||
- <option>nodefgroup</option>
|
||||
- </term>
|
||||
- <listitem>
|
||||
- <para>
|
||||
- User tokens which are not enclosed in parentheses will not be
|
||||
- matched against the group database. The backwards compatible default is
|
||||
- to try the group database match even for tokens not enclosed
|
||||
- in parentheses.
|
||||
- </para>
|
||||
- </listitem>
|
||||
- </varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.c
|
||||
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip 2024-11-21 10:04:58.547127010 +0100
|
||||
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.c 2024-11-21 10:04:58.553127026 +0100
|
||||
@@ -92,6 +92,7 @@ struct login_info {
|
||||
int debug; /* Print debugging messages. */
|
||||
int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
|
||||
int noaudit; /* Do not audit denials */
|
||||
+ int nodns; /* Do not try to resolve tokens as hostnames */
|
||||
const char *fs; /* field separator */
|
||||
const char *sep; /* list-element separator */
|
||||
int from_remote_host; /* If PAM_RHOST was used for from */
|
||||
@@ -143,6 +144,8 @@ parse_args(pam_handle_t *pamh, struct lo
|
||||
loginfo->only_new_group_syntax = YES;
|
||||
} else if (strcmp (argv[i], "noaudit") == 0) {
|
||||
loginfo->noaudit = YES;
|
||||
+ } else if (strcmp (argv[i], "nodns") == 0) {
|
||||
+ loginfo->nodns = YES;
|
||||
} else {
|
||||
pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
|
||||
}
|
||||
@@ -700,6 +703,39 @@ string_match (pam_handle_t *pamh, const
|
||||
}
|
||||
|
||||
|
||||
+static int
|
||||
+is_device (pam_handle_t *pamh, const char *tok)
|
||||
+{
|
||||
+ struct stat st;
|
||||
+ const char *dev = "/dev/";
|
||||
+ char *devname;
|
||||
+
|
||||
+ devname = malloc (strlen(dev) + strlen (tok) + 1);
|
||||
+ if (devname == NULL) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory for device name: %m");
|
||||
+ /*
|
||||
+ * We should return an error and abort, but pam_access has no good
|
||||
+ * error handling.
|
||||
+ */
|
||||
+ return NO;
|
||||
+ }
|
||||
+
|
||||
+ char *cp = stpcpy (devname, dev);
|
||||
+ strcpy (cp, tok);
|
||||
+
|
||||
+ if (lstat(devname, &st) != 0)
|
||||
+ {
|
||||
+ free (devname);
|
||||
+ return NO;
|
||||
+ }
|
||||
+ free (devname);
|
||||
+
|
||||
+ if (S_ISCHR(st.st_mode))
|
||||
+ return YES;
|
||||
+
|
||||
+ return NO;
|
||||
+}
|
||||
+
|
||||
/* network_netmask_match - match a string against one token
|
||||
* where string is a hostname or ip (v4,v6) address and tok
|
||||
* represents either a hostname, a single ip (v4,v6) address
|
||||
@@ -761,10 +797,42 @@ network_netmask_match (pam_handle_t *pam
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
+ else if (isipaddr(tok, NULL, NULL) == YES)
|
||||
+ {
|
||||
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
||||
+ {
|
||||
+ if (item->debug)
|
||||
+ pam_syslog(pamh, LOG_DEBUG, "cannot resolve IP address \"%s\"", tok);
|
||||
+
|
||||
+ return NO;
|
||||
+ }
|
||||
+ netmask_ptr = NULL;
|
||||
+ }
|
||||
+ else if (item->nodns)
|
||||
+ {
|
||||
+ /* Only hostnames are left, which we would need to resolve via DNS */
|
||||
+ return NO;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
+ /* Bail out on X11 Display entries and ttys. */
|
||||
+ if (tok[0] == ':')
|
||||
+ {
|
||||
+ if (item->debug)
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
+ "network_netmask_match: tok=%s is X11 display", tok);
|
||||
+ return NO;
|
||||
+ }
|
||||
+ if (is_device (pamh, tok))
|
||||
+ {
|
||||
+ if (item->debug)
|
||||
+ pam_syslog (pamh, LOG_DEBUG,
|
||||
+ "network_netmask_match: tok=%s is a TTY", tok);
|
||||
+ return NO;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
- * It is either an IP address or a hostname.
|
||||
+ * It is most likely a hostname.
|
||||
* Let getaddrinfo sort everything out
|
||||
*/
|
||||
if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
|
63
SOURCES/pam-1.3.1-pam-cc-compat.patch
Normal file
63
SOURCES/pam-1.3.1-pam-cc-compat.patch
Normal file
@ -0,0 +1,63 @@
|
||||
diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h
|
||||
--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:43:50.436328027 +0200
|
||||
@@ -0,0 +1,47 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2020 Dmitry V. Levin <ldv@altlinux.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef PAM_CC_COMPAT_H
|
||||
+#define PAM_CC_COMPAT_H
|
||||
+
|
||||
+#include "config.h"
|
||||
+#include <security/_pam_types.h>
|
||||
+
|
||||
+#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(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
|
||||
+
|
||||
+#endif /* PAM_CC_COMPAT_H */
|
||||
diff -up Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat Linux-PAM-1.3.1/libpam/Makefile.am
|
||||
--- Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:44:00.865402730 +0200
|
||||
@@ -18,7 +18,7 @@ include_HEADERS = include/security/_pam_
|
||||
include/security/pam_ext.h include/security/pam_modutil.h
|
||||
|
||||
noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
|
||||
- pam_modutil_private.h
|
||||
+ pam_modutil_private.h include/pam_cc_compat.h
|
||||
|
||||
libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84
|
||||
libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@
|
125
SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch
Normal file
125
SOURCES/pam-1.3.1-pam-keyinit-thread-safe.patch
Normal file
@ -0,0 +1,125 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c 2022-04-25 12:10:28.071240439 +0200
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <security/pam_modutil.h>
|
||||
#include <security/pam_ext.h>
|
||||
#include <sys/syscall.h>
|
||||
+#include <stdatomic.h>
|
||||
|
||||
#define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */
|
||||
#define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */
|
||||
@@ -30,12 +31,12 @@
|
||||
#define KEYCTL_REVOKE 3 /* revoke a key */
|
||||
#define KEYCTL_LINK 8 /* link a key into a keyring */
|
||||
|
||||
-static int my_session_keyring;
|
||||
-static int session_counter;
|
||||
-static int do_revoke;
|
||||
-static int revoke_as_uid;
|
||||
-static int revoke_as_gid;
|
||||
-static int xdebug = 0;
|
||||
+static _Thread_local int my_session_keyring = 0;
|
||||
+static _Atomic int session_counter = 0;
|
||||
+static _Thread_local int do_revoke = 0;
|
||||
+static _Thread_local uid_t revoke_as_uid;
|
||||
+static _Thread_local gid_t revoke_as_gid;
|
||||
+static _Thread_local int xdebug = 0;
|
||||
|
||||
static void debug(pam_handle_t *pamh, const char *fmt, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
@@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
+static int pam_setreuid(uid_t ruid, uid_t euid)
|
||||
+{
|
||||
+#if defined(SYS_setreuid32)
|
||||
+ return syscall(SYS_setreuid32, ruid, euid);
|
||||
+#else
|
||||
+ return syscall(SYS_setreuid, ruid, euid);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static int pam_setregid(gid_t rgid, gid_t egid)
|
||||
+{
|
||||
+#if defined(SYS_setregid32)
|
||||
+ return syscall(SYS_setregid32, rgid, egid);
|
||||
+#else
|
||||
+ return syscall(SYS_setregid, rgid, egid);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
||||
+{
|
||||
+#if defined(SYS_setresuid32)
|
||||
+ return syscall(SYS_setresuid32, ruid, euid, suid);
|
||||
+#else
|
||||
+ return syscall(SYS_setresuid, ruid, euid, suid);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* initialise the session keyring for this process
|
||||
*/
|
||||
@@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t *
|
||||
|
||||
/* switch to the real UID and GID so that we have permission to
|
||||
* revoke the key */
|
||||
- if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0)
|
||||
+ if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0)
|
||||
error(pamh, "Unable to change GID to %d temporarily\n",
|
||||
revoke_as_gid);
|
||||
|
||||
- if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0)
|
||||
+ if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0)
|
||||
error(pamh, "Unable to change UID to %d temporarily\n",
|
||||
revoke_as_uid);
|
||||
+ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
|
||||
+ error(pamh, "Unable to change GID back to %d\n", old_gid);
|
||||
|
||||
syscall(__NR_keyctl,
|
||||
KEYCTL_REVOKE,
|
||||
my_session_keyring);
|
||||
|
||||
/* return to the orignal UID and GID (probably root) */
|
||||
- if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0)
|
||||
+ if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0)
|
||||
error(pamh, "Unable to change UID back to %d\n", old_uid);
|
||||
|
||||
- if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0)
|
||||
+ if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0)
|
||||
error(pamh, "Unable to change GID back to %d\n", old_gid);
|
||||
|
||||
my_session_keyring = 0;
|
||||
@@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa
|
||||
|
||||
/* switch to the real UID and GID so that the keyring ends up owned by
|
||||
* the right user */
|
||||
- if (gid != old_gid && setregid(gid, -1) < 0) {
|
||||
+ if (gid != old_gid && pam_setregid(gid, -1) < 0) {
|
||||
error(pamh, "Unable to change GID to %d temporarily\n", gid);
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
- if (uid != old_uid && setreuid(uid, -1) < 0) {
|
||||
+ if (uid != old_uid && pam_setreuid(uid, -1) < 0) {
|
||||
error(pamh, "Unable to change UID to %d temporarily\n", uid);
|
||||
- if (setregid(old_gid, -1) < 0)
|
||||
+ if (pam_setregid(old_gid, -1) < 0)
|
||||
error(pamh, "Unable to change GID back to %d\n", old_gid);
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
@@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa
|
||||
ret = init_keyrings(pamh, force);
|
||||
|
||||
/* return to the orignal UID and GID (probably root) */
|
||||
- if (uid != old_uid && setreuid(old_uid, -1) < 0)
|
||||
+ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0)
|
||||
ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
|
||||
|
||||
- if (gid != old_gid && setregid(old_gid, -1) < 0)
|
||||
+ if (gid != old_gid && pam_setregid(old_gid, -1) < 0)
|
||||
ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
|
||||
|
||||
return ret;
|
78
SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch
Normal file
78
SOURCES/pam-1.3.1-pam-limits-unlimited-value.patch
Normal file
@ -0,0 +1,78 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value 2022-01-28 09:45:41.431606850 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml 2022-01-28 09:47:31.732430391 +0100
|
||||
@@ -275,6 +275,8 @@
|
||||
All items support the values <emphasis>-1</emphasis>,
|
||||
<emphasis>unlimited</emphasis> or <emphasis>infinity</emphasis> indicating no limit,
|
||||
except for <emphasis remap='B'>priority</emphasis> and <emphasis remap='B'>nice</emphasis>.
|
||||
+ If <emphasis remap='B'>nofile</emphasis> is to be set to one of these values,
|
||||
+ it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)).
|
||||
</para>
|
||||
<para>
|
||||
If a hard limit or soft limit of a resource is set to a valid value,
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value 2022-01-28 09:45:41.415606731 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c 2022-01-28 09:45:41.431606850 +0100
|
||||
@@ -487,6 +487,41 @@ static int init_limits(pam_handle_t *pam
|
||||
return retval;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Read the contents of <pathname> and return it in *valuep
|
||||
+ * return 1 if conversion succeeds, result is in *valuep
|
||||
+ * return 0 if conversion fails, *valuep is untouched.
|
||||
+ */
|
||||
+static int
|
||||
+value_from_file(const char *pathname, rlim_t *valuep)
|
||||
+{
|
||||
+ char buf[128];
|
||||
+ FILE *fp;
|
||||
+ int retval;
|
||||
+
|
||||
+ retval = 0;
|
||||
+
|
||||
+ if ((fp = fopen(pathname, "r")) != NULL) {
|
||||
+ if (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
+ char *endptr;
|
||||
+ unsigned long long value;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ value = strtoull(buf, &endptr, 10);
|
||||
+ if (endptr != buf &&
|
||||
+ (value != ULLONG_MAX || errno == 0) &&
|
||||
+ (unsigned long long) (rlim_t) value == value) {
|
||||
+ *valuep = (rlim_t) value;
|
||||
+ retval = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fclose(fp);
|
||||
+ }
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
|
||||
const char *lim_item, const char *lim_value,
|
||||
@@ -652,6 +687,20 @@ process_limit (const pam_handle_t *pamh,
|
||||
rlimit_value = 20 - int_value;
|
||||
break;
|
||||
#endif
|
||||
+ case RLIMIT_NOFILE:
|
||||
+ /*
|
||||
+ * If nofile is to be set to "unlimited", try to set it to
|
||||
+ * the value in /proc/sys/fs/nr_open instead.
|
||||
+ */
|
||||
+ if (rlimit_value == RLIM_INFINITY) {
|
||||
+ if (!value_from_file("/proc/sys/fs/nr_open", &rlimit_value))
|
||||
+ pam_syslog(pamh, LOG_WARNING,
|
||||
+ "Cannot set \"nofile\" to a sensible value");
|
||||
+ else if (ctrl & PAM_DEBUG_ARG)
|
||||
+ pam_syslog(pamh, LOG_DEBUG, "Setting \"nofile\" limit to %llu",
|
||||
+ (unsigned long long) rlimit_value);
|
||||
+ }
|
||||
+ break;
|
||||
}
|
||||
|
||||
if ( (limit_item != LIMIT_LOGIN)
|
29
SOURCES/pam-1.3.1-pam-misc-configurable.patch
Normal file
29
SOURCES/pam-1.3.1-pam-misc-configurable.patch
Normal file
@ -0,0 +1,29 @@
|
||||
diff -up Linux-PAM-1.3.1/configure.ac.pam-misc-configurable Linux-PAM-1.3.1/configure.ac
|
||||
--- Linux-PAM-1.3.1/configure.ac.pam-misc-configurable 2023-06-26 09:57:00.243146563 +0200
|
||||
+++ Linux-PAM-1.3.1/configure.ac 2023-06-26 09:59:45.353636685 +0200
|
||||
@@ -621,6 +621,13 @@ if test x"$opt_kerneloverflowuid" == x;
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
|
||||
|
||||
+AC_ARG_WITH([misc-conv-bufsize],
|
||||
+AS_HELP_STRING([--with-misc-conv-bufsize=<number>],
|
||||
+ [Size of input buffer for libpam_misc's misc_conv() conversation function, default=4096]),
|
||||
+ [],
|
||||
+ [with_misc_conv_bufsize=4096])
|
||||
+AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
|
||||
+
|
||||
dnl Files to be created from when we run configure
|
||||
AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
|
||||
libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
|
||||
diff -up Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable Linux-PAM-1.3.1/libpam_misc/misc_conv.c
|
||||
--- Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable 2023-06-26 09:57:00.242146560 +0200
|
||||
+++ Linux-PAM-1.3.1/libpam_misc/misc_conv.c 2023-06-26 10:00:38.023787972 +0200
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
-#define INPUTSIZE PAM_MAX_MSG_SIZE /* maximum length of input+1 */
|
||||
+#define INPUTSIZE PAM_MISC_CONV_BUFSIZE /* maximum length of input+1 */
|
||||
#define CONV_ECHO_ON 1 /* types of echo state */
|
||||
#define CONV_ECHO_OFF 0
|
||||
|
74
SOURCES/pam-1.3.1-pam-modutil-close-write.patch
Normal file
74
SOURCES/pam-1.3.1-pam-modutil-close-write.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From b6f73810a2e7afd02a231e2dfa14b05752c83db7 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
||||
Date: Wed, 26 Feb 2020 19:20:58 +0000
|
||||
Subject: [PATCH] pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of
|
||||
PAM_MODUTIL_PIPE_FD
|
||||
|
||||
When pam_modutil_sanitize_helper_fds() is invoked with
|
||||
PAM_MODUTIL_PIPE_FD to provide a dummy pipe descriptor for stdout
|
||||
or stderr, it closes the read end of the newly created dummy pipe.
|
||||
The negative side effect of this approach is that any write to such
|
||||
descriptor triggers a SIGPIPE. Avoid this by closing the write end of
|
||||
the dummy pipe and using its read end as a dummy pipe descriptor for
|
||||
output. Any read from such descriptor returns 0, and any write just
|
||||
fails with EBADF, which should work better with unprepared writers.
|
||||
|
||||
* libpam/pam_modutil_sanitize.c (redirect_out_pipe): Remove.
|
||||
(redirect_out): Call redirect_in_pipe instead of redirect_out_pipe.
|
||||
|
||||
Fixes: b0ec5d1e ("Introduce pam_modutil_sanitize_helper_fds")
|
||||
---
|
||||
libpam/pam_modutil_sanitize.c | 30 +-----------------------------
|
||||
1 file changed, 1 insertion(+), 29 deletions(-)
|
||||
|
||||
diff --git a/libpam/pam_modutil_sanitize.c b/libpam/pam_modutil_sanitize.c
|
||||
index 605c859d..58b9537c 100644
|
||||
--- a/libpam/pam_modutil_sanitize.c
|
||||
+++ b/libpam/pam_modutil_sanitize.c
|
||||
@@ -46,34 +46,6 @@ redirect_in_pipe(pam_handle_t *pamh, int fd, const char *name)
|
||||
return fd;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Creates a pipe, closes its read end, redirects fd to its write end.
|
||||
- * Returns fd on success, -1 otherwise.
|
||||
- */
|
||||
-static int
|
||||
-redirect_out_pipe(pam_handle_t *pamh, int fd, const char *name)
|
||||
-{
|
||||
- int out[2];
|
||||
-
|
||||
- if (pipe(out) < 0) {
|
||||
- pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- close(out[0]);
|
||||
-
|
||||
- if (out[1] == fd)
|
||||
- return fd;
|
||||
-
|
||||
- if (dup2(out[1], fd) != fd) {
|
||||
- pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name);
|
||||
- fd = -1;
|
||||
- }
|
||||
-
|
||||
- close(out[1]);
|
||||
- return fd;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Opens /dev/null for writing, redirects fd there.
|
||||
* Returns fd on success, -1 otherwise.
|
||||
@@ -106,7 +78,7 @@ redirect_out(pam_handle_t *pamh, enum pam_modutil_redirect_fd mode,
|
||||
{
|
||||
switch (mode) {
|
||||
case PAM_MODUTIL_PIPE_FD:
|
||||
- if (redirect_out_pipe(pamh, fd, name) < 0)
|
||||
+ if (redirect_in_pipe(pamh, fd, name) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case PAM_MODUTIL_NULL_FD:
|
||||
--
|
||||
2.25.3
|
||||
|
283
SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
Normal file
283
SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
Normal file
@ -0,0 +1,283 @@
|
||||
From d57ab22133654033ee1da89f128a81572d320985 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tmraz@fedoraproject.org>
|
||||
Date: Thu, 20 Dec 2018 13:59:25 +0100
|
||||
Subject: [PATCH] pam_motd: Cleanup the code and avoid unnecessary logging
|
||||
|
||||
The pam_motd module will not log if the default motd.d directories
|
||||
are missing.
|
||||
|
||||
Also cleanup some code cleanliness issues and fix compilation
|
||||
warnings.
|
||||
|
||||
* modules/pam_motd/pam_motd.c: Constification of constant strings.
|
||||
(try_to_display_directory): Removed unused function.
|
||||
(pam_split_string): Replace uint with unsigned int. Fix warnings.
|
||||
(compare_strings): Fix warnings by proper constification.
|
||||
(try_to_display_directories_with_overrides): Cleanups. Switch
|
||||
off the logging if the motd.d directories are missing and they
|
||||
are default ones.
|
||||
(pam_sm_open_session): Cleanup warnings. Pass the information
|
||||
to try_to_display_directories_with_overrides() that non-default
|
||||
motd options are used.
|
||||
---
|
||||
modules/pam_motd/pam_motd.c | 88 ++++++++++++++++---------------------
|
||||
1 file changed, 37 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
|
||||
index ec3ebd58..dbd718b6 100644
|
||||
--- a/modules/pam_motd/pam_motd.c
|
||||
+++ b/modules/pam_motd/pam_motd.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
+#include <errno.h>
|
||||
|
||||
#include <security/_pam_macros.h>
|
||||
#include <security/pam_ext.h>
|
||||
@@ -48,8 +49,8 @@ pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED,
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
-static char default_motd[] = DEFAULT_MOTD;
|
||||
-static char default_motd_dir[] = DEFAULT_MOTD_D;
|
||||
+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)
|
||||
{
|
||||
@@ -75,28 +76,6 @@ static void try_to_display_fd(pam_handle_t *pamh, int fd)
|
||||
_pam_drop(mtmp);
|
||||
}
|
||||
|
||||
-static void try_to_display_directory(pam_handle_t *pamh, const char *dirname)
|
||||
-{
|
||||
- DIR *dirp;
|
||||
-
|
||||
- dirp = opendir(dirname);
|
||||
-
|
||||
- if (dirp != NULL) {
|
||||
- struct dirent *entry;
|
||||
-
|
||||
- while ((entry = readdir(dirp))) {
|
||||
- int fd = openat(dirfd(dirp), entry->d_name, O_RDONLY);
|
||||
-
|
||||
- if (fd >= 0) {
|
||||
- try_to_display_fd(pamh, fd);
|
||||
- close(fd);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- closedir(dirp);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Split a DELIM-separated string ARG into an array.
|
||||
* Outputs a newly allocated array of strings OUT_ARG_SPLIT
|
||||
@@ -104,14 +83,14 @@ static void try_to_display_directory(pam_handle_t *pamh, const char *dirname)
|
||||
* 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, uint *out_num_strs)
|
||||
+ 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];
|
||||
- int i = 0;
|
||||
- uint num_strs = 0;
|
||||
+ unsigned int i = 0;
|
||||
+ unsigned int num_strs = 0;
|
||||
int retval = 0;
|
||||
|
||||
delim_str[0] = delim;
|
||||
@@ -126,7 +105,7 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
|
||||
arg_ptr = strchr(arg_ptr + sizeof(const char), delim);
|
||||
}
|
||||
|
||||
- arg_split = (char **)calloc(num_strs, sizeof(char *));
|
||||
+ arg_split = calloc(num_strs, sizeof(char *));
|
||||
if (arg_split == NULL) {
|
||||
pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array");
|
||||
goto out;
|
||||
@@ -180,10 +159,10 @@ static int join_dir_strings(char **strp_out, const char *a_str, const char *b_st
|
||||
return retval;
|
||||
}
|
||||
|
||||
-static int compare_strings(const void * a, const void * b)
|
||||
+static int compare_strings(const void *a, const void *b)
|
||||
{
|
||||
- const char *a_str = *(char **)a;
|
||||
- const char *b_str = *(char **)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;
|
||||
@@ -205,13 +184,13 @@ static int filter_dirents(const struct dirent *d)
|
||||
}
|
||||
|
||||
static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
- char **motd_dir_path_split, int num_motd_dirs)
|
||||
+ char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing)
|
||||
{
|
||||
struct dirent ***dirscans = NULL;
|
||||
- int *dirscans_sizes = NULL;
|
||||
- int dirscans_size_total = 0;
|
||||
+ unsigned int *dirscans_sizes = NULL;
|
||||
+ unsigned int dirscans_size_total = 0;
|
||||
char **dirnames_all = NULL;
|
||||
- int i;
|
||||
+ unsigned int i;
|
||||
int i_dirnames = 0;
|
||||
|
||||
if (pamh == NULL || motd_dir_path_split == NULL) {
|
||||
@@ -221,29 +200,31 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if ((dirscans = (struct dirent ***)calloc(num_motd_dirs,
|
||||
- sizeof(struct dirent **))) == NULL) {
|
||||
+ if ((dirscans = calloc(num_motd_dirs, sizeof(struct dirent **))) == NULL) {
|
||||
pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent arrays");
|
||||
goto out;
|
||||
}
|
||||
- if ((dirscans_sizes = (int *)calloc(num_motd_dirs, sizeof(int))) == NULL) {
|
||||
+ if ((dirscans_sizes = calloc(num_motd_dirs, sizeof(int))) == NULL) {
|
||||
pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent array sizes");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_motd_dirs; i++) {
|
||||
- dirscans_sizes[i] = scandir(motd_dir_path_split[i], &(dirscans[i]),
|
||||
+ int rv;
|
||||
+ rv = scandir(motd_dir_path_split[i], &(dirscans[i]),
|
||||
filter_dirents, alphasort);
|
||||
- if (dirscans_sizes[i] < 0) {
|
||||
- pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s", motd_dir_path_split[i]);
|
||||
- dirscans_sizes[i] = 0;
|
||||
+ if (rv < 0) {
|
||||
+ if (errno != ENOENT || report_missing) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m",
|
||||
+ motd_dir_path_split[i]);
|
||||
+ }
|
||||
+ dirscans_sizes[i] = rv;
|
||||
}
|
||||
dirscans_size_total += dirscans_sizes[i];
|
||||
}
|
||||
|
||||
/* Allocate space for all file names found in the directories, including duplicates. */
|
||||
- if ((dirnames_all = (char **)calloc(dirscans_size_total,
|
||||
- sizeof(char *))) == NULL) {
|
||||
+ if ((dirnames_all = calloc(dirscans_size_total, sizeof(char *))) == NULL) {
|
||||
pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array");
|
||||
goto out;
|
||||
}
|
||||
@@ -253,7 +234,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
}
|
||||
|
||||
for (i = 0; i < num_motd_dirs; i++) {
|
||||
- int j;
|
||||
+ unsigned int j;
|
||||
|
||||
for (j = 0; j < dirscans_sizes[i]; j++) {
|
||||
dirnames_all[i_dirnames] = dirscans[i][j]->d_name;
|
||||
@@ -265,7 +246,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
sizeof(const char *), compare_strings);
|
||||
|
||||
for (i = 0; i < dirscans_size_total; i++) {
|
||||
- int j;
|
||||
+ unsigned int j;
|
||||
|
||||
if (dirnames_all[i] == NULL) {
|
||||
continue;
|
||||
@@ -301,7 +282,8 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
out:
|
||||
_pam_drop(dirnames_all);
|
||||
for (i = 0; i < num_motd_dirs; i++) {
|
||||
- int j;
|
||||
+ unsigned int j;
|
||||
+
|
||||
for (j = 0; j < dirscans_sizes[i]; j++) {
|
||||
_pam_drop(dirscans[i][j]);
|
||||
}
|
||||
@@ -319,12 +301,13 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
int retval = PAM_IGNORE;
|
||||
const char *motd_path = NULL;
|
||||
char *motd_path_copy = NULL;
|
||||
- int num_motd_paths = 0;
|
||||
+ unsigned int num_motd_paths = 0;
|
||||
char **motd_path_split = NULL;
|
||||
const char *motd_dir_path = NULL;
|
||||
char *motd_dir_path_copy = NULL;
|
||||
- int num_motd_dir_paths = 0;
|
||||
+ unsigned int num_motd_dir_paths = 0;
|
||||
char **motd_dir_path_split = NULL;
|
||||
+ int report_missing;
|
||||
|
||||
if (flags & PAM_SILENT) {
|
||||
return retval;
|
||||
@@ -360,6 +343,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
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;
|
||||
}
|
||||
|
||||
if (motd_path != NULL) {
|
||||
@@ -385,7 +371,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
}
|
||||
|
||||
if (motd_path_split != NULL) {
|
||||
- int i;
|
||||
+ unsigned int i;
|
||||
|
||||
for (i = 0; i < num_motd_paths; i++) {
|
||||
int fd = open(motd_path_split[i], O_RDONLY, 0);
|
||||
@@ -402,7 +388,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
|
||||
if (motd_dir_path_split != NULL)
|
||||
try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
|
||||
- num_motd_dir_paths);
|
||||
+ num_motd_dir_paths, report_missing);
|
||||
|
||||
out:
|
||||
_pam_drop(motd_path_copy);
|
||||
--
|
||||
2.37.3
|
||||
|
||||
From c2c0434bd634a817f2b16ce7f58fc96c04e88b03 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
||||
Date: Sun, 26 Apr 2020 11:12:59 +0000
|
||||
Subject: [PATCH] pam_motd: fix NULL dereference when at least one of motd
|
||||
directories is not available
|
||||
|
||||
* modules/pam_motd/pam_motd.c
|
||||
(try_to_display_directories_with_overrides): Do not assign -1U to
|
||||
dirscans_sizes[i] when scandir(motd_dir_path_split[i]) returns an error.
|
||||
|
||||
Resolves: https://bugzilla.altlinux.org/38389
|
||||
Fixes: d57ab221 ("pam_motd: Cleanup the code and avoid unnecessary logging")
|
||||
---
|
||||
modules/pam_motd/pam_motd.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
|
||||
index df09b7d0..8147c6fd 100644
|
||||
--- a/modules/pam_motd/pam_motd.c
|
||||
+++ b/modules/pam_motd/pam_motd.c
|
||||
@@ -219,6 +219,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m",
|
||||
motd_dir_path_split[i]);
|
||||
}
|
||||
+ } else {
|
||||
dirscans_sizes[i] = rv;
|
||||
}
|
||||
dirscans_size_total += dirscans_sizes[i];
|
||||
--
|
||||
2.37.3
|
||||
|
57
SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch
Normal file
57
SOURCES/pam-1.3.1-pam-motd-fix-memory-leak.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 62cd745d730e5ba13d5d7092ac566fc0b2148e61 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
||||
Date: Sun, 26 Apr 2020 11:12:59 +0000
|
||||
Subject: [PATCH] pam_motd: fix memory leak
|
||||
|
||||
pam_motd used to leak memory allocated for each motd file
|
||||
successfully opened in try_to_display_directories_with_overrides.
|
||||
|
||||
* modules/pam_motd/pam_motd.c
|
||||
(try_to_display_directories_with_overrides): Free abs_path.
|
||||
|
||||
Fixes: f9c9c721 ("pam_motd: Support multiple motd paths specified, with filename overrides (#69)")
|
||||
---
|
||||
modules/pam_motd/pam_motd.c | 20 ++++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
|
||||
index f0cd317d..3be129a5 100644
|
||||
--- a/modules/pam_motd/pam_motd.c
|
||||
+++ b/modules/pam_motd/pam_motd.c
|
||||
@@ -259,23 +259,23 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
|
||||
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) {
|
||||
+ dirnames_all[i]) < 0 || abs_path == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (abs_path != NULL) {
|
||||
- int fd = open(abs_path, O_RDONLY, 0);
|
||||
- if (fd >= 0) {
|
||||
- try_to_display_fd(pamh, fd);
|
||||
- close(fd);
|
||||
+ fd = open(abs_path, O_RDONLY, 0);
|
||||
+ _pam_drop(abs_path);
|
||||
|
||||
- /* We displayed a file, skip to the next file name. */
|
||||
- break;
|
||||
- }
|
||||
+ if (fd >= 0) {
|
||||
+ try_to_display_fd(pamh, fd);
|
||||
+ close(fd);
|
||||
+
|
||||
+ /* We displayed a file, skip to the next file name. */
|
||||
+ break;
|
||||
}
|
||||
- _pam_drop(abs_path);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
133
SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch
Normal file
133
SOURCES/pam-1.3.1-pam-motd-fix-segmentation-fault.patch
Normal file
@ -0,0 +1,133 @@
|
||||
From 8eaf5570cf011148a0b55c53570df5edaafebdb0 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Fairley <rfairley@users.noreply.github.com>
|
||||
Date: Wed, 21 Nov 2018 02:46:02 -0500
|
||||
Subject: [PATCH] pam_motd: Fix segmentation fault when no motd_dir specified
|
||||
(#76)
|
||||
|
||||
This fixes a regression introduced by #69, where motd_path was set
|
||||
to NULL and passed into strdup() if the motd_dir argument was
|
||||
not specified in the configuration file. This caused a segmentation
|
||||
fault.
|
||||
|
||||
* modules/pam_motd/pam_motd.c: fix checks for NULL in arguments
|
||||
* xtests/Makefile.am: add test scripts and config file
|
||||
* xtests/tst-pam_motd.sh: add running tst-pam_motd4.sh
|
||||
* xtests/tst-pam_motd4.pamd: create
|
||||
* xtests/tst-pam_motd4.sh: create
|
||||
---
|
||||
modules/pam_motd/pam_motd.c | 15 ++++++++++-----
|
||||
xtests/Makefile.am | 4 ++--
|
||||
xtests/tst-pam_motd.sh | 1 +
|
||||
xtests/tst-pam_motd4.pamd | 3 +++
|
||||
xtests/tst-pam_motd4.sh | 27 +++++++++++++++++++++++++++
|
||||
5 files changed, 43 insertions(+), 7 deletions(-)
|
||||
create mode 100644 xtests/tst-pam_motd4.pamd
|
||||
create mode 100755 xtests/tst-pam_motd4.sh
|
||||
|
||||
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
|
||||
index 1c1cfcfa..ec3ebd58 100644
|
||||
--- a/modules/pam_motd/pam_motd.c
|
||||
+++ b/modules/pam_motd/pam_motd.c
|
||||
@@ -132,7 +132,6 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
|
||||
goto out;
|
||||
}
|
||||
|
||||
-
|
||||
arg_extracted = strtok_r(arg, delim_str, &arg);
|
||||
while (arg_extracted != NULL && i < num_strs) {
|
||||
arg_split[i++] = arg_extracted;
|
||||
@@ -363,15 +362,21 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
motd_dir_path = default_motd_dir;
|
||||
}
|
||||
|
||||
- motd_path_copy = strdup(motd_path);
|
||||
+ if (motd_path != NULL) {
|
||||
+ motd_path_copy = strdup(motd_path);
|
||||
+ }
|
||||
+
|
||||
if (motd_path_copy != NULL) {
|
||||
- if (pam_split_string(pamh, motd_path_copy, ':', &motd_path_split,
|
||||
- &num_motd_paths) == 0) {
|
||||
+ if (pam_split_string(pamh, motd_path_copy, ':',
|
||||
+ &motd_path_split, &num_motd_paths) == 0) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
- motd_dir_path_copy = strdup(motd_dir_path);
|
||||
+ if (motd_dir_path != NULL) {
|
||||
+ motd_dir_path_copy = strdup(motd_dir_path);
|
||||
+ }
|
||||
+
|
||||
if (motd_dir_path_copy != NULL) {
|
||||
if (pam_split_string(pamh, motd_dir_path_copy, ':',
|
||||
&motd_dir_path_split, &num_motd_dir_paths) == 0) {
|
||||
diff --git a/xtests/Makefile.am b/xtests/Makefile.am
|
||||
index 555d5e33..4d5aba3d 100644
|
||||
--- a/xtests/Makefile.am
|
||||
+++ b/xtests/Makefile.am
|
||||
@@ -34,8 +34,8 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
|
||||
tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
|
||||
tst-pam_time1.pamd time.conf \
|
||||
tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
|
||||
- tst-pam_motd3.sh tst-pam_motd1.pamd \
|
||||
- tst-pam_motd2.pamd tst-pam_motd3.pamd
|
||||
+ tst-pam_motd3.sh tst-pam_motd4.sh tst-pam_motd1.pamd \
|
||||
+ tst-pam_motd2.pamd tst-pam_motd3.pamd tst-pam_motd4.pamd
|
||||
|
||||
XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
|
||||
tst-pam_dispatch4 tst-pam_dispatch5 \
|
||||
diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh
|
||||
index 9b0c38f6..90801280 100755
|
||||
--- a/xtests/tst-pam_motd.sh
|
||||
+++ b/xtests/tst-pam_motd.sh
|
||||
@@ -5,3 +5,4 @@ set -e
|
||||
./tst-pam_motd1.sh
|
||||
./tst-pam_motd2.sh
|
||||
./tst-pam_motd3.sh
|
||||
+./tst-pam_motd4.sh
|
||||
diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd
|
||||
new file mode 100644
|
||||
index 00000000..9dc311ad
|
||||
--- /dev/null
|
||||
+++ b/xtests/tst-pam_motd4.pamd
|
||||
@@ -0,0 +1,3 @@
|
||||
+#%PAM-1.0
|
||||
+session required pam_permit.so
|
||||
+session optional pam_motd.so motd=tst-pam_motd4.d/etc/motd
|
||||
diff --git a/xtests/tst-pam_motd4.sh b/xtests/tst-pam_motd4.sh
|
||||
new file mode 100755
|
||||
index 00000000..6022177f
|
||||
--- /dev/null
|
||||
+++ b/xtests/tst-pam_motd4.sh
|
||||
@@ -0,0 +1,27 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+TST_DIR="tst-pam_motd4.d"
|
||||
+
|
||||
+function tst_cleanup() {
|
||||
+ rm -rf "${TST_DIR}"
|
||||
+ rm -f tst-pam_motd4.out
|
||||
+}
|
||||
+
|
||||
+mkdir -p ${TST_DIR}/etc
|
||||
+
|
||||
+# Verify the case of single motd with no motd_dir given in tst-pam_motd4.pamd
|
||||
+echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
|
||||
+
|
||||
+./tst-pam_motd tst-pam_motd4 > tst-pam_motd4.out
|
||||
+
|
||||
+RET=$?
|
||||
+
|
||||
+motd_to_show_output=$(cat tst-pam_motd4.out | grep "motd: /etc/motd")
|
||||
+if [ -z "${motd_to_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+tst_cleanup
|
||||
+exit $RET
|
||||
--
|
||||
2.35.1
|
||||
|
691
SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
Normal file
691
SOURCES/pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
Normal file
@ -0,0 +1,691 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.939663167 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2022-04-25 12:34:43.506582206 +0200
|
||||
@@ -21,6 +21,9 @@
|
||||
<arg choice="opt">
|
||||
motd=<replaceable>/path/filename</replaceable>
|
||||
</arg>
|
||||
+ <arg choice="opt">
|
||||
+ motd_dir=<replaceable>/path/dirname.d</replaceable>
|
||||
+ </arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -31,18 +34,49 @@
|
||||
<para>
|
||||
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 <filename>/etc/motd</filename> file and
|
||||
- all files from <filename>/etc/motd.d</filename> are
|
||||
- shown. The message size is limited to 64KB.
|
||||
+ login. By default, pam_motd shows files in the
|
||||
+ following locations:
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ <simplelist type='vert'>
|
||||
+ <member><filename>/etc/motd</filename></member>
|
||||
+ <member><filename>/run/motd</filename></member>
|
||||
+ <member><filename>/usr/lib/motd</filename></member>
|
||||
+ <member><filename>/etc/motd.d/</filename></member>
|
||||
+ <member><filename>/run/motd.d/</filename></member>
|
||||
+ <member><filename>/usr/lib/motd.d/</filename></member>
|
||||
+ </simplelist>
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Each message size is limited to 64KB.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ If <filename>/etc/motd</filename> does not exist,
|
||||
+ then <filename>/run/motd</filename> is shown. If
|
||||
+ <filename>/run/motd</filename> does not exist, then
|
||||
+ <filename>/usr/lib/motd</filename> is shown.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Similar overriding behavior applies to the directories.
|
||||
+ Files in <filename>/etc/motd.d/</filename> override files
|
||||
+ with the same name in <filename>/run/motd.d/</filename> and
|
||||
+ <filename>/usr/lib/motd.d/</filename>. Files in <filename>/run/motd.d/</filename>
|
||||
+ override files with the same name in <filename>/usr/lib/motd.d/</filename>.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ 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.
|
||||
</para>
|
||||
<para>
|
||||
To silence a message,
|
||||
a symbolic link with target <filename>/dev/null</filename>
|
||||
may be placed in <filename>/etc/motd.d</filename> with
|
||||
the same filename as the message to be silenced. Example:
|
||||
+ Creating a symbolic link as follows silences <filename>/usr/lib/motd.d/my_motd</filename>.
|
||||
</para>
|
||||
<para>
|
||||
- <command>ln -sfn /dev/null /etc/motd.d/my_motd</command>
|
||||
+ <command>ln -s /dev/null /etc/motd.d/my_motd</command>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@@ -56,8 +90,10 @@
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
- The <filename>/path/filename</filename> file is displayed
|
||||
- as message of the day.
|
||||
+ The <filename>/path/filename</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 <filename>/etc/motd:/run/motd:/usr/lib/motd</filename>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -68,16 +104,17 @@
|
||||
<listitem>
|
||||
<para>
|
||||
The <filename>/path/dirname.d</filename> directory is scanned
|
||||
- and each file contained inside of it is displayed.
|
||||
+ 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 <filename>/etc/motd.d:/run/motd.d:/usr/lib/motd.d</filename>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
- When no options are given, the default is to display both
|
||||
- <filename>/etc/motd</filename> and the contents of
|
||||
- <filename>/etc/motd.d</filename>. Specifying either option (or both)
|
||||
- will disable this default behavior.
|
||||
+ 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.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 2018-05-18 11:50:46.000000000 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -33,8 +33,8 @@
|
||||
*/
|
||||
|
||||
#define PAM_SM_SESSION
|
||||
-#define DEFAULT_MOTD "/etc/motd"
|
||||
-#define DEFAULT_MOTD_D "/etc/motd.d"
|
||||
+#define DEFAULT_MOTD "/etc/motd:/run/motd:/usr/lib/motd"
|
||||
+#define DEFAULT_MOTD_D "/etc/motd.d:/run/motd.d:/usr/lib/motd.d"
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_modutil.h>
|
||||
@@ -97,12 +97,235 @@ static void try_to_display_directory(pam
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 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, uint *out_num_strs)
|
||||
+{
|
||||
+ char *arg_extracted = NULL;
|
||||
+ const char *arg_ptr = arg;
|
||||
+ char **arg_split = NULL;
|
||||
+ char delim_str[2];
|
||||
+ int i = 0;
|
||||
+ uint 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 = (char **)calloc(num_strs, sizeof(char *));
|
||||
+ if (arg_split == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "pam_motd: 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 = *(char **)a;
|
||||
+ const char *b_str = *(char **)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 int filter_dirents(const struct dirent *d)
|
||||
+{
|
||||
+ return (d->d_type == DT_REG || d->d_type == DT_LNK);
|
||||
+}
|
||||
+
|
||||
+static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
|
||||
+ char **motd_dir_path_split, int num_motd_dirs)
|
||||
+{
|
||||
+ struct dirent ***dirscans = NULL;
|
||||
+ int *dirscans_sizes = NULL;
|
||||
+ int dirscans_size_total = 0;
|
||||
+ char **dirnames_all = NULL;
|
||||
+ 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 = (struct dirent ***)calloc(num_motd_dirs,
|
||||
+ sizeof(struct dirent **))) == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent arrays");
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((dirscans_sizes = (int *)calloc(num_motd_dirs, sizeof(int))) == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent array sizes");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num_motd_dirs; i++) {
|
||||
+ dirscans_sizes[i] = scandir(motd_dir_path_split[i], &(dirscans[i]),
|
||||
+ filter_dirents, alphasort);
|
||||
+ if (dirscans_sizes[i] < 0) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s", motd_dir_path_split[i]);
|
||||
+ dirscans_sizes[i] = 0;
|
||||
+ }
|
||||
+ dirscans_size_total += dirscans_sizes[i];
|
||||
+ }
|
||||
+
|
||||
+ /* Allocate space for all file names found in the directories, including duplicates. */
|
||||
+ if ((dirnames_all = (char **)calloc(dirscans_size_total,
|
||||
+ sizeof(char *))) == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < dirscans_size_total; i++) {
|
||||
+ dirnames_all[i] = NULL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num_motd_dirs; i++) {
|
||||
+ int j;
|
||||
+
|
||||
+ for (j = 0; j < dirscans_sizes[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++) {
|
||||
+ 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;
|
||||
+
|
||||
+ if (join_dir_strings(&abs_path, motd_dir_path_split[j],
|
||||
+ dirnames_all[i]) < 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (abs_path != NULL) {
|
||||
+ int fd = open(abs_path, O_RDONLY, 0);
|
||||
+ if (fd >= 0) {
|
||||
+ try_to_display_fd(pamh, fd);
|
||||
+ close(fd);
|
||||
+
|
||||
+ /* We displayed a file, skip to the next file name. */
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ _pam_drop(abs_path);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ out:
|
||||
+ _pam_drop(dirnames_all);
|
||||
+ for (i = 0; i < num_motd_dirs; i++) {
|
||||
+ 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);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
int retval = PAM_IGNORE;
|
||||
const char *motd_path = NULL;
|
||||
+ char *motd_path_copy = NULL;
|
||||
+ int num_motd_paths = 0;
|
||||
+ char **motd_path_split = NULL;
|
||||
const char *motd_dir_path = NULL;
|
||||
+ char *motd_dir_path_copy = NULL;
|
||||
+ int num_motd_dir_paths = 0;
|
||||
+ char **motd_dir_path_split = NULL;
|
||||
|
||||
if (flags & PAM_SILENT) {
|
||||
return retval;
|
||||
@@ -140,17 +363,47 @@ int pam_sm_open_session(pam_handle_t *pa
|
||||
motd_dir_path = default_motd_dir;
|
||||
}
|
||||
|
||||
- if (motd_path != NULL) {
|
||||
- int fd = open(motd_path, O_RDONLY, 0);
|
||||
+ motd_path_copy = strdup(motd_path);
|
||||
+ if (motd_path_copy != NULL) {
|
||||
+ if (pam_split_string(pamh, motd_path_copy, ':', &motd_path_split,
|
||||
+ &num_motd_paths) == 0) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ motd_dir_path_copy = strdup(motd_dir_path);
|
||||
+ 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;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (motd_path_split != NULL) {
|
||||
+ 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);
|
||||
+ 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 != NULL)
|
||||
- try_to_display_directory(pamh, motd_dir_path);
|
||||
+ if (motd_dir_path_split != NULL)
|
||||
+ try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
|
||||
+ num_motd_dir_paths);
|
||||
+
|
||||
+ out:
|
||||
+ _pam_drop(motd_path_copy);
|
||||
+ _pam_drop(motd_path_split);
|
||||
+ _pam_drop(motd_dir_path_copy);
|
||||
+ _pam_drop(motd_dir_path_split);
|
||||
|
||||
return retval;
|
||||
}
|
||||
diff -up Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/Makefile.am
|
||||
--- Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/xtests/Makefile.am 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispa
|
||||
tst-pam_substack5.pamd tst-pam_substack5a.pamd tst-pam_substack5.sh \
|
||||
tst-pam_assemble_line1.pamd tst-pam_assemble_line1.sh \
|
||||
tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
|
||||
- tst-pam_time1.pamd time.conf
|
||||
+ tst-pam_time1.pamd time.conf \
|
||||
+ tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
|
||||
+ tst-pam_motd3.sh tst-pam_motd1.pamd \
|
||||
+ tst-pam_motd2.pamd tst-pam_motd3.pamd
|
||||
|
||||
XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
|
||||
tst-pam_dispatch4 tst-pam_dispatch5 \
|
||||
@@ -41,7 +44,7 @@ XTESTS = tst-pam_dispatch1 tst-pam_dispa
|
||||
tst-pam_access1 tst-pam_access2 tst-pam_access3 \
|
||||
tst-pam_access4 tst-pam_limits1 tst-pam_succeed_if1 \
|
||||
tst-pam_group1 tst-pam_authfail tst-pam_authsucceed \
|
||||
- tst-pam_pwhistory1 tst-pam_time1
|
||||
+ tst-pam_pwhistory1 tst-pam_time1 tst-pam_motd
|
||||
|
||||
NOSRCTESTS = tst-pam_substack1 tst-pam_substack2 tst-pam_substack3 \
|
||||
tst-pam_substack4 tst-pam_substack5 tst-pam_assemble_line1
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,3 @@
|
||||
+#%PAM-1.0
|
||||
+session required pam_permit.so
|
||||
+session optional pam_motd.so motd=tst-pam_motd1.d/etc/motd motd_dir=tst-pam_motd1.d/etc/motd.d
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,36 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+TST_DIR="tst-pam_motd1.d"
|
||||
+
|
||||
+function tst_cleanup() {
|
||||
+ rm -rf "${TST_DIR}"
|
||||
+ rm -f tst-pam_motd1.out
|
||||
+}
|
||||
+
|
||||
+mkdir -p ${TST_DIR}
|
||||
+mkdir -p ${TST_DIR}/etc/motd.d
|
||||
+
|
||||
+# Verify the case of single motd and motd.d directory works
|
||||
+echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
|
||||
+echo "motd: /etc/motd.d/test" > ${TST_DIR}/etc/motd.d/test
|
||||
+
|
||||
+./tst-pam_motd tst-pam_motd1 > tst-pam_motd1.out
|
||||
+
|
||||
+RET=$?
|
||||
+
|
||||
+motd_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd")
|
||||
+if [ -z "${motd_to_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+motd_dir_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd.d/test")
|
||||
+if [ -z "${motd_dir_to_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+tst_cleanup
|
||||
+exit $RET
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,3 @@
|
||||
+#%PAM-1.0
|
||||
+session required pam_permit.so
|
||||
+session optional pam_motd.so motd=tst-pam_motd2.d/etc/motd:tst-pam_motd2.d/run/motd:tst-pam_motd2.d/usr/lib/motd motd_dir=tst-pam_motd2.d/etc/motd.d:tst-pam_motd2.d/run/motd.d:tst-pam_motd2.d/usr/lib/motd.d
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,53 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+TST_DIR="tst-pam_motd2.d"
|
||||
+
|
||||
+function tst_cleanup() {
|
||||
+ rm -rf "${TST_DIR}"
|
||||
+ rm -f tst-pam_motd2.out
|
||||
+}
|
||||
+
|
||||
+mkdir -p ${TST_DIR}
|
||||
+mkdir -p ${TST_DIR}/etc/motd.d
|
||||
+mkdir -p ${TST_DIR}/run/motd.d
|
||||
+mkdir -p ${TST_DIR}/usr/lib/motd.d
|
||||
+
|
||||
+echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
|
||||
+echo "motd: /run/motd" > ${TST_DIR}/run/motd
|
||||
+echo "motd: /usr/lib/motd" > ${TST_DIR}/usr/lib/motd
|
||||
+
|
||||
+# Drop a motd file in test directories such that every overriding
|
||||
+# condition (for 3 directories in this case) will be seen.
|
||||
+echo "motd: e0r0u1 in usr/lib - will show" > ${TST_DIR}/usr/lib/motd.d/e0r0u1.motd
|
||||
+echo "motd: e0r1u0 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u0.motd
|
||||
+echo "motd: e0r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e0r1u1.motd
|
||||
+echo "motd: e0r1u1 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u1.motd
|
||||
+echo "motd: e1r0u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u0.motd
|
||||
+echo "motd: e1r0u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r0u1.motd
|
||||
+echo "motd: e1r0u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u1.motd
|
||||
+echo "motd: e1r1u0 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u0.motd
|
||||
+echo "motd: e1r1u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u0.motd
|
||||
+echo "motd: e1r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r1u1.motd
|
||||
+echo "motd: e1r1u1 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u1.motd
|
||||
+echo "motd: e1r1u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u1.motd
|
||||
+
|
||||
+./tst-pam_motd tst-pam_motd2 > tst-pam_motd2.out
|
||||
+
|
||||
+RET=$?
|
||||
+
|
||||
+motd_to_show_output=$(cat tst-pam_motd2.out | grep "motd: /etc/motd")
|
||||
+if [ -z "${motd_to_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+motd_dir_not_show_output=$(cat tst-pam_motd2.out | grep "not show")
|
||||
+if [ -n "${motd_dir_not_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+tst_cleanup
|
||||
+exit $RET
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,3 @@
|
||||
+#%PAM-1.0
|
||||
+session required pam_permit.so
|
||||
+session optional pam_motd.so motd=tst-pam_motd3.d/etc/motd:tst-pam_motd3.d/run/motd:tst-pam_motd3.d/usr/lib/motd motd_dir=tst-pam_motd3.d/etc/motd.d:tst-pam_motd3.d/run/motd.d:tst-pam_motd3.d/usr/lib/motd.d
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,53 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+TST_DIR="tst-pam_motd3.d"
|
||||
+
|
||||
+function tst_cleanup() {
|
||||
+ rm -rf "${TST_DIR}"
|
||||
+ rm -f tst-pam_motd3.out
|
||||
+}
|
||||
+
|
||||
+mkdir -p ${TST_DIR}
|
||||
+mkdir -p ${TST_DIR}/etc/motd.d
|
||||
+mkdir -p ${TST_DIR}/run/motd.d
|
||||
+mkdir -p ${TST_DIR}/usr/lib/motd.d
|
||||
+
|
||||
+# Verify motd is still displayed when not overridden
|
||||
+echo "motd: test-show in run - show" > ${TST_DIR}/run/motd.d/test-show.motd
|
||||
+
|
||||
+# Test overridden by a symlink to a file that isn't /dev/null; symlink target should show
|
||||
+echo "motd: hidden-by-symlink in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/hidden-by-symlink.motd
|
||||
+echo "motd: test-from-symlink - show" > ${TST_DIR}/test-from-symlink.motd
|
||||
+ln -sr ${TST_DIR}/test-from-symlink.motd ${TST_DIR}/run/motd.d/hidden-by-symlink.motd
|
||||
+
|
||||
+# Test hidden by a null symlink
|
||||
+echo "motd: hidden-by-null-symlink in run - not show" > ${TST_DIR}/run/motd.d/hidden-by-null-symlink.motd
|
||||
+ln -s /dev/null ${TST_DIR}/etc/motd.d/hidden-by-null-symlink.motd
|
||||
+
|
||||
+./tst-pam_motd tst-pam_motd3 > tst-pam_motd3.out
|
||||
+
|
||||
+RET=$?
|
||||
+
|
||||
+motd_dir_not_show_output=$(cat tst-pam_motd3.out | grep "not show")
|
||||
+if [ -n "${motd_dir_not_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+motd_test_show_output=$(cat tst-pam_motd3.out | grep "test-show.*- show")
|
||||
+if [ -z "${motd_test_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+motd_general_symlink_show_output=$(cat tst-pam_motd3.out | grep "test-from-symlink.*- show")
|
||||
+if [ -z "${motd_general_symlink_show_output}" ];
|
||||
+then
|
||||
+ tst_cleanup
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+tst_cleanup
|
||||
+exit $RET
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.c
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd.c 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include <config.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <security/pam_appl.h>
|
||||
+#include <security/pam_misc.h>
|
||||
+
|
||||
+static struct pam_conv conv = {
|
||||
+ misc_conv,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+int main(int argc, char *argv[])
|
||||
+{
|
||||
+ pam_handle_t *pamh=NULL;
|
||||
+ char *tst_arg = NULL;
|
||||
+ int retval;
|
||||
+
|
||||
+ if (argc > 1)
|
||||
+ tst_arg = argv[1];
|
||||
+
|
||||
+ retval = pam_start(tst_arg, NULL, &conv, &pamh);
|
||||
+
|
||||
+ retval = pam_open_session(pamh, 0);
|
||||
+
|
||||
+ retval = pam_close_session(pamh, 0);
|
||||
+
|
||||
+ if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
|
||||
+ pamh = NULL;
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
|
||||
+}
|
||||
diff -up Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.sh
|
||||
--- Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
|
||||
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd.sh 2022-04-25 12:32:36.947663225 +0200
|
||||
@@ -0,0 +1,7 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+./tst-pam_motd1.sh
|
||||
+./tst-pam_motd2.sh
|
||||
+./tst-pam_motd3.sh
|
573
SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
Normal file
573
SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
Normal file
@ -0,0 +1,573 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.709355179 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am 2022-09-29 10:13:35.780355766 +0200
|
||||
@@ -10,9 +10,10 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst-
|
||||
|
||||
TESTS = tst-pam_pwhistory
|
||||
|
||||
-man_MANS = pam_pwhistory.8 pwhistory_helper.8
|
||||
+man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5
|
||||
|
||||
-XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
|
||||
+XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml \
|
||||
+ pwhistory.conf.5.xml
|
||||
|
||||
securelibdir = $(SECUREDIR)
|
||||
secureconfdir = $(SCONFIGDIR)
|
||||
@@ -25,12 +26,14 @@ if HAVE_VERSIONING
|
||||
pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||||
endif
|
||||
|
||||
-noinst_HEADERS = opasswd.h
|
||||
+noinst_HEADERS = opasswd.h pwhistory_config.h
|
||||
+
|
||||
+dist_secureconf_DATA = pwhistory.conf
|
||||
|
||||
securelib_LTLIBRARIES = pam_pwhistory.la
|
||||
pam_pwhistory_la_CFLAGS = $(AM_CFLAGS)
|
||||
pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@
|
||||
-pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c
|
||||
+pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c pwhistory_config.c
|
||||
|
||||
sbin_PROGRAMS = pwhistory_helper
|
||||
pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml 2022-09-29 10:13:35.780355766 +0200
|
||||
@@ -36,6 +36,9 @@
|
||||
<arg choice="opt">
|
||||
authtok_type=<replaceable>STRING</replaceable>
|
||||
</arg>
|
||||
+ <arg choice="opt">
|
||||
+ conf=<replaceable>/path/to/config-file</replaceable>
|
||||
+ </arg>
|
||||
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -104,7 +107,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
The last <replaceable>N</replaceable> passwords for each
|
||||
- user are saved in <filename>/etc/security/opasswd</filename>.
|
||||
+ user are saved.
|
||||
The default is <emphasis>10</emphasis>. Value of
|
||||
<emphasis>0</emphasis> makes the module to keep the existing
|
||||
contents of the <filename>opasswd</filename> file unchanged.
|
||||
@@ -137,7 +140,26 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>conf=<replaceable>/path/to/config-file</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Use another configuration file instead of the default
|
||||
+ <filename>/etc/security/pwhistory.conf</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
</variablelist>
|
||||
+ <para>
|
||||
+ The options for configuring the module behavior are described in the
|
||||
+ <citerefentry><refentrytitle>pwhistory.conf</refentrytitle>
|
||||
+ <manvolnum>5</manvolnum></citerefentry> manual page. The options
|
||||
+ specified on the module command line override the values from the
|
||||
+ configuration file.
|
||||
+ </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="pam_pwhistory-types">
|
||||
@@ -223,6 +245,9 @@ password required pam_unix.so
|
||||
<title>SEE ALSO</title>
|
||||
<para>
|
||||
<citerefentry>
|
||||
+ <refentrytitle>pwhistory.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
</citerefentry>,
|
||||
<citerefentry>
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.711355195 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c 2022-09-29 10:13:35.780355766 +0200
|
||||
@@ -62,18 +62,11 @@
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
#include "opasswd.h"
|
||||
+#include "pwhistory_config.h"
|
||||
|
||||
#define DEFAULT_BUFLEN 2048
|
||||
#define MAX_FD_NO 20000
|
||||
|
||||
-struct options_t {
|
||||
- int debug;
|
||||
- int enforce_for_root;
|
||||
- int remember;
|
||||
- int tries;
|
||||
-};
|
||||
-typedef struct options_t options_t;
|
||||
-
|
||||
|
||||
static void
|
||||
parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
|
||||
@@ -304,6 +297,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
|
||||
options.remember = 10;
|
||||
options.tries = 1;
|
||||
|
||||
+ parse_config_file(pamh, argc, argv, &options);
|
||||
+
|
||||
/* Parse parameters for module */
|
||||
for ( ; argc-- > 0; argv++)
|
||||
parse_option (pamh, *argv, &options);
|
||||
@@ -311,7 +306,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
|
||||
if (options.debug)
|
||||
pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered");
|
||||
|
||||
-
|
||||
if (options.remember == 0)
|
||||
return PAM_IGNORE;
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.780355766 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml 2022-09-29 10:13:35.780355766 +0200
|
||||
@@ -0,0 +1,155 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+<refentry id="pwhistory.conf">
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pwhistory.conf</refentrytitle>
|
||||
+ <manvolnum>5</manvolnum>
|
||||
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id="pwhistory.conf-name">
|
||||
+ <refname>pwhistory.conf</refname>
|
||||
+ <refpurpose>pam_pwhistory configuration file</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-description">
|
||||
+
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ <emphasis remap='B'>pwhistory.conf</emphasis> provides a way to configure the
|
||||
+ default settings for saving the last passwords for each user.
|
||||
+ This file is read by the <emphasis>pam_pwhistory</emphasis> module and is the
|
||||
+ preferred method over configuring <emphasis>pam_pwhistory</emphasis> directly.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ The file has a very simple <emphasis>name = value</emphasis> format with possible comments
|
||||
+ starting with <emphasis>#</emphasis> character. The whitespace at the beginning of line, end
|
||||
+ of line, and around the <emphasis>=</emphasis> sign is ignored.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-options">
|
||||
+
|
||||
+ <title>OPTIONS</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>debug</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Turns on debugging via
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
|
||||
+ </citerefentry>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>enforce_for_root</option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ If this option is set, the check is enforced for root, too.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>remember=<replaceable>N</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The last <replaceable>N</replaceable> passwords for each
|
||||
+ user are saved.
|
||||
+ The default is <emphasis>10</emphasis>. Value of
|
||||
+ <emphasis>0</emphasis> makes the module to keep the existing
|
||||
+ contents of the <filename>opasswd</filename> file unchanged.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>retry=<replaceable>N</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Prompt user at most <replaceable>N</replaceable> times
|
||||
+ before returning with error. The default is 1.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term>
|
||||
+ <option>file=<replaceable>/path/filename</replaceable></option>
|
||||
+ </term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Store password history in file
|
||||
+ <replaceable>/path/filename</replaceable> rather than the default
|
||||
+ location. The default location is
|
||||
+ <filename>/etc/security/opasswd</filename>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory.conf-examples'>
|
||||
+ <title>EXAMPLES</title>
|
||||
+ <para>
|
||||
+ /etc/security/pwhistory.conf file example:
|
||||
+ </para>
|
||||
+ <programlisting>
|
||||
+debug
|
||||
+remember=5
|
||||
+file=/tmp/opasswd
|
||||
+ </programlisting>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pwhistory.conf-files">
|
||||
+ <title>FILES</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><filename>/etc/security/pwhistory.conf</filename></term>
|
||||
+ <listitem>
|
||||
+ <para>the config file for custom options</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory.conf-see_also'>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pwhistory</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pwhistory.conf-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>
|
||||
+ pam_pwhistory was written by Thorsten Kukuk. The support for
|
||||
+ pwhistory.conf was written by Iker Pedrosa.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c 2022-09-29 10:14:33.377832622 +0200
|
||||
@@ -0,0 +1,195 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2022 Iker Pedrosa <ipedrosa@redhat.com>
|
||||
+ *
|
||||
+ * 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 <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <syslog.h>
|
||||
+#include <ctype.h>
|
||||
+
|
||||
+#include <security/pam_modutil.h>
|
||||
+
|
||||
+#include "pam_inline.h"
|
||||
+#include "pwhistory_config.h"
|
||||
+
|
||||
+#define PWHISTORY_DEFAULT_CONF "/etc/security/pwhistory.conf"
|
||||
+
|
||||
+/* lookup a value for key in login.defs file or similar key value format */
|
||||
+static char *
|
||||
+pwhistory_search_key(pam_handle_t *pamh UNUSED,
|
||||
+ const char *file_name,
|
||||
+ const char *key)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char *buf = NULL;
|
||||
+ size_t buflen = 0;
|
||||
+ char *retval = NULL;
|
||||
+
|
||||
+#ifdef USE_ECONF
|
||||
+ if (strcmp (file_name, LOGIN_DEFS) == 0)
|
||||
+ return econf_search_key ("login", ".defs", key);
|
||||
+#endif
|
||||
+
|
||||
+ fp = fopen(file_name, "r");
|
||||
+ if (NULL == fp)
|
||||
+ return NULL;
|
||||
+
|
||||
+ while (!feof(fp)) {
|
||||
+ char *tmp, *cp;
|
||||
+#if defined(HAVE_GETLINE)
|
||||
+ ssize_t n = getline(&buf, &buflen, fp);
|
||||
+#elif defined (HAVE_GETDELIM)
|
||||
+ ssize_t n = getdelim(&buf, &buflen, '\n', fp);
|
||||
+#else
|
||||
+ ssize_t n;
|
||||
+
|
||||
+ if (buf == NULL) {
|
||||
+ buflen = BUF_SIZE;
|
||||
+ buf = malloc(buflen);
|
||||
+ if (buf == NULL) {
|
||||
+ fclose(fp);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ buf[0] = '\0';
|
||||
+ if (fgets(buf, buflen - 1, fp) == NULL)
|
||||
+ break;
|
||||
+ else if (buf != NULL)
|
||||
+ n = strlen(buf);
|
||||
+ else
|
||||
+ n = 0;
|
||||
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
|
||||
+ cp = buf;
|
||||
+
|
||||
+ if (n < 1)
|
||||
+ break;
|
||||
+ if (cp[n - 1] == '\n')
|
||||
+ cp[n - 1] = '\0';
|
||||
+
|
||||
+ tmp = strchr(cp, '#'); /* remove comments */
|
||||
+ if (tmp)
|
||||
+ *tmp = '\0';
|
||||
+ while (isspace((int)*cp)) /* remove spaces and tabs */
|
||||
+ ++cp;
|
||||
+ if (*cp == '\0') /* ignore empty lines */
|
||||
+ continue;
|
||||
+
|
||||
+ tmp = strsep (&cp, " \t=");
|
||||
+ if (cp != NULL)
|
||||
+ while (isspace((int)*cp) || *cp == '=')
|
||||
+ ++cp;
|
||||
+ else
|
||||
+ cp = buf + n; /* empty string */
|
||||
+
|
||||
+ if (strcasecmp(tmp, key) == 0) {
|
||||
+ retval = strdup(cp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ fclose(fp);
|
||||
+
|
||||
+ free(buf);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+parse_config_file(pam_handle_t *pamh, int argc, const char **argv,
|
||||
+ struct options_t *options)
|
||||
+{
|
||||
+ const char *fname = NULL;
|
||||
+ int i;
|
||||
+ char *val;
|
||||
+
|
||||
+ for (i = 0; i < argc; ++i) {
|
||||
+ const char *str = pam_str_skip_prefix(argv[i], "conf=");
|
||||
+
|
||||
+ if (str != NULL) {
|
||||
+ fname = str;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (fname == NULL) {
|
||||
+ fname = PWHISTORY_DEFAULT_CONF;
|
||||
+ }
|
||||
+
|
||||
+ val = pwhistory_search_key (pamh, fname, "debug");
|
||||
+ if (val != NULL) {
|
||||
+ options->debug = 1;
|
||||
+ free(val);
|
||||
+ }
|
||||
+
|
||||
+ val = pwhistory_search_key (pamh, fname, "enforce_for_root");
|
||||
+ if (val != NULL) {
|
||||
+ options->enforce_for_root = 1;
|
||||
+ free(val);
|
||||
+ }
|
||||
+
|
||||
+ val = pwhistory_search_key (pamh, fname, "remember");
|
||||
+ if (val != NULL) {
|
||||
+ unsigned int temp;
|
||||
+ if (sscanf(val, "%u", &temp) != 1) {
|
||||
+ pam_syslog(pamh, LOG_ERR,
|
||||
+ "Bad number supplied for remember argument");
|
||||
+ } else {
|
||||
+ options->remember = temp;
|
||||
+ }
|
||||
+ free(val);
|
||||
+ }
|
||||
+
|
||||
+ val = pwhistory_search_key (pamh, fname, "retry");
|
||||
+ if (val != NULL) {
|
||||
+ unsigned int temp;
|
||||
+ if (sscanf(val, "%u", &temp) != 1) {
|
||||
+ pam_syslog(pamh, LOG_ERR,
|
||||
+ "Bad number supplied for retry argument");
|
||||
+ } else {
|
||||
+ options->tries = temp;
|
||||
+ }
|
||||
+ free(val);
|
||||
+ }
|
||||
+
|
||||
+ val = pwhistory_search_key (pamh, fname, "file");
|
||||
+ if (val != NULL) {
|
||||
+ if (*val != '/') {
|
||||
+ pam_syslog (pamh, LOG_ERR,
|
||||
+ "File path should be absolute: %s", val);
|
||||
+ } else {
|
||||
+ options->filename = val;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h 2022-09-29 10:13:35.781355775 +0200
|
||||
@@ -0,0 +1,54 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2022 Iker Pedrosa <ipedrosa@redhat.com>
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _PWHISTORY_CONFIG_H
|
||||
+#define _PWHISTORY_CONFIG_H
|
||||
+
|
||||
+#include <security/pam_ext.h>
|
||||
+
|
||||
+struct options_t {
|
||||
+ int debug;
|
||||
+ int enforce_for_root;
|
||||
+ int remember;
|
||||
+ int tries;
|
||||
+ const char *filename;
|
||||
+};
|
||||
+typedef struct options_t options_t;
|
||||
+
|
||||
+void
|
||||
+parse_config_file(pam_handle_t *pamh, int argc, const char **argv,
|
||||
+ struct options_t *options);
|
||||
+
|
||||
+#endif /* _PWHISTORY_CONFIG_H */
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file 2022-09-29 10:13:35.781355775 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf 2022-09-29 10:13:35.781355775 +0200
|
||||
@@ -0,0 +1,21 @@
|
||||
+# Configuration for remembering the last passwords used by a user.
|
||||
+#
|
||||
+# Enable the debugging logs.
|
||||
+# Enabled if option is present.
|
||||
+# debug
|
||||
+#
|
||||
+# root account's passwords are also remembered.
|
||||
+# Enabled if option is present.
|
||||
+# enforce_for_root
|
||||
+#
|
||||
+# Number of passwords to remember.
|
||||
+# The default is 10.
|
||||
+# remember = 10
|
||||
+#
|
||||
+# Number of times to prompt for the password.
|
||||
+# The default is 1.
|
||||
+# retry = 1
|
||||
+#
|
||||
+# The directory where the last passwords are kept.
|
||||
+# The default is /etc/security/opasswd.
|
||||
+# file = /etc/security/opasswd
|
47
SOURCES/pam-1.3.1-pam-unix-shadow-password.patch
Normal file
47
SOURCES/pam-1.3.1-pam-unix-shadow-password.patch
Normal file
@ -0,0 +1,47 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.pam-unix-shadow-password Linux-PAM-1.3.1/modules/pam_unix/passverify.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.pam-unix-shadow-password 2024-11-05 13:02:14.637785962 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2024-11-05 13:02:14.643785975 +0100
|
||||
@@ -73,9 +73,13 @@ verify_pwd_hash(const char *p, char *has
|
||||
|
||||
strip_hpux_aging(hash);
|
||||
hash_len = strlen(hash);
|
||||
- if (!hash_len) {
|
||||
+
|
||||
+ if (p && p[0] == '\0' && !nullok) {
|
||||
+ /* The passed password is empty */
|
||||
+ retval = PAM_AUTH_ERR;
|
||||
+ } else if (!hash_len) {
|
||||
/* the stored password is NULL */
|
||||
- if (nullok) { /* this means we've succeeded */
|
||||
+ if (p && p[0] == '\0' && nullok) { /* this means we've succeeded */
|
||||
D(("user has empty password - access granted"));
|
||||
retval = PAM_SUCCESS;
|
||||
} else {
|
||||
@@ -192,17 +196,21 @@ PAMH_ARG_DECL(int get_account_info,
|
||||
return PAM_UNIX_RUN_HELPER;
|
||||
#endif
|
||||
} else if (is_pwd_shadowed(*pwd)) {
|
||||
+#ifdef HELPER_COMPILE
|
||||
/*
|
||||
- * ...and shadow password file entry for this user,
|
||||
+ * shadow password file entry for this user,
|
||||
* if shadowing is enabled
|
||||
*/
|
||||
-#ifndef HELPER_COMPILE
|
||||
- if (geteuid() || SELINUX_ENABLED)
|
||||
- return PAM_UNIX_RUN_HELPER;
|
||||
-#endif
|
||||
- *spwdent = pam_modutil_getspnam(pamh, name);
|
||||
+ *spwdent = getspnam(name);
|
||||
if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL)
|
||||
return PAM_AUTHINFO_UNAVAIL;
|
||||
+#else
|
||||
+ /*
|
||||
+ * The helper has to be invoked to deal with
|
||||
+ * the shadow password file entry.
|
||||
+ */
|
||||
+ return PAM_UNIX_RUN_HELPER;
|
||||
+#endif
|
||||
}
|
||||
} else {
|
||||
return PAM_USER_UNKNOWN;
|
@ -0,0 +1,111 @@
|
||||
From a7453aeeb398d6cbb7a709c4e2a1d75905220fff Mon Sep 17 00:00:00 2001
|
||||
From: Stanislav Zidek <szidek@redhat.com>
|
||||
Date: Fri, 16 Apr 2021 19:14:18 +0200
|
||||
Subject: [PATCH] pam_userdb: Prevent garbage characters from db
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791965
|
||||
---
|
||||
modules/pam_userdb/pam_userdb.8.xml | 3 +-
|
||||
modules/pam_userdb/pam_userdb.c | 56 +++++++++++++++++------------
|
||||
2 files changed, 36 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml
|
||||
index fa628ada..bce92850 100644
|
||||
--- a/modules/pam_userdb/pam_userdb.8.xml
|
||||
+++ b/modules/pam_userdb/pam_userdb.8.xml
|
||||
@@ -100,7 +100,8 @@
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
- Print debug information.
|
||||
+ Print debug information. Note that password hashes, both from db
|
||||
+ and computed, will be printed to syslog.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
|
||||
index dc2ca232..d59801bf 100644
|
||||
--- a/modules/pam_userdb/pam_userdb.c
|
||||
+++ b/modules/pam_userdb/pam_userdb.c
|
||||
@@ -194,7 +194,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
|
||||
}
|
||||
|
||||
if (data.dptr != NULL) {
|
||||
- int compare = 0;
|
||||
+ int compare = -2;
|
||||
|
||||
if (ctrl & PAM_KEY_ONLY_ARG)
|
||||
{
|
||||
@@ -209,36 +209,48 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
|
||||
char *cryptpw = NULL;
|
||||
|
||||
if (data.dsize < 13) {
|
||||
- compare = -2;
|
||||
+ /* hash is too short */
|
||||
+ pam_syslog(pamh, LOG_INFO, "password hash in database is too short");
|
||||
} else if (ctrl & PAM_ICASE_ARG) {
|
||||
- compare = -2;
|
||||
+ pam_syslog(pamh, LOG_INFO,
|
||||
+ "case-insensitive comparison only works with plaintext passwords");
|
||||
} else {
|
||||
+ /* libdb is not guaranteed to produce null terminated strings */
|
||||
+ char *pwhash = strndup(data.dptr, data.dsize);
|
||||
+
|
||||
+ if (pwhash == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr");
|
||||
+ } else {
|
||||
#ifdef HAVE_CRYPT_R
|
||||
- struct crypt_data *cdata = NULL;
|
||||
- cdata = malloc(sizeof(*cdata));
|
||||
- if (cdata != NULL) {
|
||||
- cdata->initialized = 0;
|
||||
- cryptpw = crypt_r(pass, data.dptr, cdata);
|
||||
- }
|
||||
+ struct crypt_data *cdata = NULL;
|
||||
+ cdata = malloc(sizeof(*cdata));
|
||||
+ if (cdata == NULL) {
|
||||
+ pam_syslog(pamh, LOG_CRIT, "malloc failed: struct crypt_data");
|
||||
+ } else {
|
||||
+ cdata->initialized = 0;
|
||||
+ cryptpw = crypt_r(pass, pwhash, cdata);
|
||||
+ }
|
||||
#else
|
||||
- cryptpw = crypt (pass, data.dptr);
|
||||
+ cryptpw = crypt (pass, pwhash);
|
||||
#endif
|
||||
- if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
|
||||
- compare = memcmp(data.dptr, cryptpw, data.dsize);
|
||||
- } else {
|
||||
- compare = -2;
|
||||
- if (ctrl & PAM_DEBUG_ARG) {
|
||||
- if (cryptpw)
|
||||
- pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
|
||||
- else
|
||||
- pam_syslog(pamh, LOG_INFO, "crypt() returned NULL");
|
||||
+ if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
|
||||
+ compare = memcmp(data.dptr, cryptpw, data.dsize);
|
||||
+ } else {
|
||||
+ if (ctrl & PAM_DEBUG_ARG) {
|
||||
+ if (cryptpw) {
|
||||
+ pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
|
||||
+ pam_syslog(pamh, LOG_INFO, "computed hash: %s", cryptpw);
|
||||
+ } else {
|
||||
+ pam_syslog(pamh, LOG_ERR, "crypt() returned NULL");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
#ifdef HAVE_CRYPT_R
|
||||
- free(cdata);
|
||||
+ free(cdata);
|
||||
#endif
|
||||
+ }
|
||||
+ free(pwhash);
|
||||
}
|
||||
-
|
||||
} else {
|
||||
|
||||
/* Unknown password encryption method -
|
||||
--
|
||||
2.30.2
|
||||
|
75
SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
Normal file
75
SOURCES/pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
Normal file
@ -0,0 +1,75 @@
|
||||
diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/configure.ac
|
||||
--- Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.169146826 +0200
|
||||
+++ Linux-PAM-1.3.1/configure.ac 2022-06-22 16:43:54.343373619 +0200
|
||||
@@ -615,12 +615,6 @@ if test x"$opt_uidmin" == x; then
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
|
||||
|
||||
-AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
|
||||
-if test x"$opt_sysuidmin" == x; then
|
||||
- opt_sysuidmin=101
|
||||
-fi
|
||||
-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
|
||||
-
|
||||
AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
|
||||
if test x"$opt_kerneloverflowuid" == x; then
|
||||
opt_kerneloverflowuid=65534
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2022-06-22 16:41:09.169146826 +0200
|
||||
@@ -31,7 +31,7 @@
|
||||
pam_usertype.so is designed to succeed or fail authentication
|
||||
based on type of the account of the authenticated user.
|
||||
The type of the account is decided with help of
|
||||
- <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
|
||||
+ <emphasis>SYS_UID_MAX</emphasis>
|
||||
settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
|
||||
whether to load other modules based on this test.
|
||||
</para>
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2022-06-22 16:41:09.169146826 +0200
|
||||
@@ -277,7 +277,6 @@ static int
|
||||
pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
|
||||
{
|
||||
uid_t uid_min;
|
||||
- uid_t sys_min;
|
||||
uid_t sys_max;
|
||||
|
||||
if (uid == (uid_t)-1) {
|
||||
@@ -285,21 +284,19 @@ pam_usertype_is_system(pam_handle_t *pam
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
- if (uid <= 99) {
|
||||
- /* Reserved. */
|
||||
- return PAM_SUCCESS;
|
||||
- }
|
||||
-
|
||||
if (uid == PAM_USERTYPE_OVERFLOW_UID) {
|
||||
/* nobody */
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
|
||||
- sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
|
||||
sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
|
||||
|
||||
- return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
|
||||
+ if (uid <= sys_max && uid < uid_min) {
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ return PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -336,7 +333,7 @@ pam_usertype_evaluate(struct pam_usertyp
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
- * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
|
||||
+ * - issystem: uid less than SYS_UID_MAX
|
||||
* - isregular: not issystem
|
||||
* - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
|
||||
* - audit: log unknown users to syslog
|
712
SOURCES/pam-1.3.1-pam-usertype.patch
Normal file
712
SOURCES/pam-1.3.1-pam-usertype.patch
Normal file
@ -0,0 +1,712 @@
|
||||
diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype Linux-PAM-1.3.1/configure.ac
|
||||
--- Linux-PAM-1.3.1/configure.ac.pam-usertype 2020-05-15 10:03:27.247468160 +0200
|
||||
+++ Linux-PAM-1.3.1/configure.ac 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -606,6 +606,27 @@ AC_SUBST([HAVE_KEY_MANAGEMENT], $HAVE_KE
|
||||
|
||||
AM_CONDITIONAL([HAVE_KEY_MANAGEMENT], [test "$have_key_syscalls" = 1])
|
||||
|
||||
+dnl
|
||||
+dnl Get values for default uid ranges in login.defs used in pam_usertype
|
||||
+dnl
|
||||
+AC_ARG_WITH([uidmin], AS_HELP_STRING([--with-uidmin=<number>],[default value for regular user min uid (1000)]), opt_uidmin=$withval)
|
||||
+if test x"$opt_uidmin" == x; then
|
||||
+ opt_uidmin=1000
|
||||
+fi
|
||||
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
|
||||
+
|
||||
+AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
|
||||
+if test x"$opt_sysuidmin" == x; then
|
||||
+ opt_sysuidmin=101
|
||||
+fi
|
||||
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
|
||||
+
|
||||
+AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
|
||||
+if test x"$opt_kerneloverflowuid" == x; then
|
||||
+ opt_kerneloverflowuid=65534
|
||||
+fi
|
||||
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
|
||||
+
|
||||
dnl Files to be created from when we run configure
|
||||
AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
|
||||
libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
|
||||
@@ -636,6 +657,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
|
||||
modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \
|
||||
modules/pam_umask/Makefile \
|
||||
modules/pam_unix/Makefile modules/pam_userdb/Makefile \
|
||||
+ modules/pam_usertype/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 \
|
||||
diff -up Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/Makefile.am
|
||||
--- Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype 2020-05-15 10:03:27.247468160 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/Makefile.am 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -12,7 +12,7 @@ SUBDIRS = pam_access pam_cracklib pam_de
|
||||
pam_selinux pam_sepermit pam_shells pam_stress \
|
||||
pam_succeed_if pam_time pam_timestamp \
|
||||
pam_tty_audit pam_umask \
|
||||
- pam_unix pam_userdb pam_warn pam_wheel pam_xauth
|
||||
+ pam_unix pam_userdb pam_usertype pam_warn pam_wheel pam_xauth
|
||||
|
||||
CLEANFILES = *~
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -0,0 +1,34 @@
|
||||
+#
|
||||
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
|
||||
+# Copyright (c) 2020 Red Hat, Inc.
|
||||
+#
|
||||
+
|
||||
+CLEANFILES = *~
|
||||
+MAINTAINERCLEANFILES = $(MANS) README
|
||||
+
|
||||
+EXTRA_DIST = README ${MANS} ${XMLS} tst-pam_usertype
|
||||
+
|
||||
+TESTS = tst-pam_usertype
|
||||
+
|
||||
+man_MANS = pam_usertype.8
|
||||
+
|
||||
+XMLS = README.xml pam_usertype.8.xml
|
||||
+
|
||||
+securelibdir = $(SECUREDIR)
|
||||
+secureconfdir = $(SCONFIGDIR)
|
||||
+
|
||||
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
||||
+ $(WARN_CFLAGS)
|
||||
+AM_LDFLAGS = -no-undefined -avoid-version -module
|
||||
+if HAVE_VERSIONING
|
||||
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
||||
+endif
|
||||
+
|
||||
+securelib_LTLIBRARIES = pam_usertype.la
|
||||
+pam_usertype_la_LIBADD = $(top_builddir)/libpam/libpam.la
|
||||
+
|
||||
+if ENABLE_REGENERATE_MAN
|
||||
+noinst_DATA = README
|
||||
+README: pam_usertype.8.xml
|
||||
+-include $(top_srcdir)/Make.xml.rules
|
||||
+endif
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -0,0 +1,170 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
|
||||
+
|
||||
+
|
||||
+<refentry id='pam_usertype'>
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>pam_usertype</refentrytitle>
|
||||
+ <manvolnum>8</manvolnum>
|
||||
+ <refmiscinfo class='sectdesc'>Linux-PAM</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv id='pam_usertype-name'>
|
||||
+ <refname>pam_usertype</refname>
|
||||
+ <refpurpose>check if the authenticated user is a system or regular account</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+
|
||||
+ <refsynopsisdiv>
|
||||
+ <cmdsynopsis id='pam_usertype-cmdsynopsis'>
|
||||
+ <command>pam_usertype.so</command>
|
||||
+ <arg choice='opt' rep='repeat'><replaceable>flag</replaceable></arg>
|
||||
+ <arg choice='req'><replaceable>condition</replaceable></arg>
|
||||
+ </cmdsynopsis>
|
||||
+ </refsynopsisdiv>
|
||||
+
|
||||
+
|
||||
+ <refsect1 id='pam_usertype-description'>
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ pam_usertype.so is designed to succeed or fail authentication
|
||||
+ based on type of the account of the authenticated user.
|
||||
+ The type of the account is decided with help of
|
||||
+ <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
|
||||
+ settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
|
||||
+ whether to load other modules based on this test.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>
|
||||
+ The module should be given only one condition as module argument.
|
||||
+ Authentication will succeed only if the condition is met.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_usertype-options">
|
||||
+ <title>OPTIONS</title>
|
||||
+ <para>
|
||||
+ The following <emphasis>flag</emphasis>s are supported:
|
||||
+ </para>
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><option>use_uid</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Evaluate conditions using the account of the user whose UID
|
||||
+ the application is running under instead of the user being
|
||||
+ authenticated.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>audit</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Log unknown users to the system log.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+
|
||||
+ <para>
|
||||
+ Available <emphasis>condition</emphasis>s are:
|
||||
+ </para>
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><option>issystem</option></term>
|
||||
+ <listitem>
|
||||
+ <para>Succeed if the user is a system user.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>isregular</option></term>
|
||||
+ <listitem>
|
||||
+ <para>Succeed if the user is a regular user.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id="pam_usertype-types">
|
||||
+ <title>MODULE TYPES PROVIDED</title>
|
||||
+ <para>
|
||||
+ All module types (<option>account</option>, <option>auth</option>,
|
||||
+ <option>password</option> and <option>session</option>) are provided.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_usertype-return_values'>
|
||||
+ <title>RETURN VALUES</title>
|
||||
+ <variablelist>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SUCCESS</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The condition was true.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_AUTH_ERR</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The condition was false.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_SERVICE_ERR</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ A service error occurred or the arguments can't be
|
||||
+ parsed correctly.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>PAM_USER_UNKNOWN</term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ User was not found.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+
|
||||
+ <refsect1 id='pam_usertype-examples'>
|
||||
+ <title>EXAMPLES</title>
|
||||
+ <para>
|
||||
+ Skip remaining modules if the user is a system user:
|
||||
+ </para>
|
||||
+ <programlisting>
|
||||
+account sufficient pam_usertype.so issystem
|
||||
+ </programlisting>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_usertype-see_also'>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
|
||||
+ </citerefentry>,
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
|
||||
+ </citerefentry>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1 id='pam_usertype-author'>
|
||||
+ <title>AUTHOR</title>
|
||||
+ <para>Pavel Březina <pbrezina@redhat.com></para>
|
||||
+ </refsect1>
|
||||
+</refentry>
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2020-05-15 10:16:08.053198025 +0200
|
||||
@@ -0,0 +1,394 @@
|
||||
+/******************************************************************************
|
||||
+ * Check user type based on login.defs.
|
||||
+ *
|
||||
+ * Copyright (c) 2020 Red Hat, Inc.
|
||||
+ * Written by Pavel Březina <pbrezina@redhat.com>
|
||||
+ *
|
||||
+ * 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 <sys/types.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <syslog.h>
|
||||
+#include <unistd.h>
|
||||
+#include <pwd.h>
|
||||
+#include <ctype.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#define PAM_SM_AUTH
|
||||
+#define PAM_SM_ACCOUNT
|
||||
+#define PAM_SM_SESSION
|
||||
+#define PAM_SM_PASSWORD
|
||||
+
|
||||
+#include <security/pam_modules.h>
|
||||
+#include <security/pam_modutil.h>
|
||||
+#include <security/pam_ext.h>
|
||||
+
|
||||
+#define LOGIN_DEFS "/etc/login.defs"
|
||||
+
|
||||
+enum pam_usertype_op {
|
||||
+ OP_IS_SYSTEM,
|
||||
+ OP_IS_REGULAR,
|
||||
+
|
||||
+ OP_SENTINEL
|
||||
+};
|
||||
+
|
||||
+struct pam_usertype_opts {
|
||||
+ enum pam_usertype_op op;
|
||||
+ int use_uid;
|
||||
+ int audit;
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+pam_usertype_parse_args(struct pam_usertype_opts *opts,
|
||||
+ pam_handle_t *pamh,
|
||||
+ int argc,
|
||||
+ const char **argv)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ memset(opts, 0, sizeof(struct pam_usertype_opts));
|
||||
+ opts->op = OP_SENTINEL;
|
||||
+
|
||||
+ for (i = 0; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], "use_uid") == 0) {
|
||||
+ opts->use_uid = 1;
|
||||
+ } else if (strcmp(argv[i], "audit") == 0) {
|
||||
+ opts->audit = 1;
|
||||
+ } else if (strcmp(argv[i], "issystem") == 0) {
|
||||
+ opts->op = OP_IS_SYSTEM;
|
||||
+ } else if (strcmp(argv[i], "isregular") == 0) {
|
||||
+ opts->op = OP_IS_REGULAR;
|
||||
+ } else {
|
||||
+ pam_syslog(pamh, LOG_WARNING, "Unknown argument: %s", argv[i]);
|
||||
+ /* Just continue. */
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (opts->op == OP_SENTINEL) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "Operation not specified");
|
||||
+ return PAM_SERVICE_ERR;
|
||||
+ }
|
||||
+
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+pam_usertype_get_uid(struct pam_usertype_opts *opts,
|
||||
+ pam_handle_t *pamh,
|
||||
+ uid_t *_uid)
|
||||
+{
|
||||
+ struct passwd *pwd;
|
||||
+ const void *prompt;
|
||||
+ const char *username;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Get uid of user that runs the application. */
|
||||
+ if (opts->use_uid) {
|
||||
+ pwd = pam_modutil_getpwuid(pamh, getuid());
|
||||
+ if (pwd == NULL) {
|
||||
+ pam_syslog(pamh, LOG_ERR,
|
||||
+ "error retrieving information about user %lu",
|
||||
+ (unsigned long)getuid());
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ }
|
||||
+
|
||||
+ *_uid = pwd->pw_uid;
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ /* Get uid of user that is being authenticated. */
|
||||
+ ret = pam_get_item(pamh, PAM_USER_PROMPT, &prompt);
|
||||
+ if (ret != PAM_SUCCESS || prompt == NULL || strlen(prompt) == 0) {
|
||||
+ prompt = "login: ";
|
||||
+ }
|
||||
+
|
||||
+ ret = pam_get_user(pamh, &username, prompt);
|
||||
+ if (ret != PAM_SUCCESS || username == NULL) {
|
||||
+ pam_syslog(pamh, LOG_ERR, "error retrieving user name: %s",
|
||||
+ pam_strerror(pamh, ret));
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ pwd = pam_modutil_getpwnam(pamh, username);
|
||||
+ if (pwd == NULL) {
|
||||
+ if (opts->audit) {
|
||||
+ pam_syslog(pamh, LOG_NOTICE,
|
||||
+ "error retrieving information about user %s", username);
|
||||
+ }
|
||||
+
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ }
|
||||
+
|
||||
+ *_uid = pwd->pw_uid;
|
||||
+
|
||||
+ return PAM_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#define MAX_UID_VALUE 0xFFFFFFFFUL
|
||||
+
|
||||
+/* lookup a value for key in login.defs file or similar key value format */
|
||||
+char *
|
||||
+pam_usertype_search_key(pam_handle_t *pamh UNUSED,
|
||||
+ const char *file_name,
|
||||
+ const char *key)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char *buf = NULL;
|
||||
+ size_t buflen = 0;
|
||||
+ char *retval = NULL;
|
||||
+
|
||||
+ fp = fopen(file_name, "r");
|
||||
+ if (NULL == fp)
|
||||
+ return NULL;
|
||||
+
|
||||
+ while (!feof(fp)) {
|
||||
+ char *tmp, *cp;
|
||||
+#if defined(HAVE_GETLINE)
|
||||
+ ssize_t n = getline(&buf, &buflen, fp);
|
||||
+#elif defined (HAVE_GETDELIM)
|
||||
+ ssize_t n = getdelim(&buf, &buflen, '\n', fp);
|
||||
+#else
|
||||
+ ssize_t n;
|
||||
+
|
||||
+ if (buf == NULL) {
|
||||
+ buflen = BUF_SIZE;
|
||||
+ buf = malloc(buflen);
|
||||
+ if (buf == NULL) {
|
||||
+ fclose(fp);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ buf[0] = '\0';
|
||||
+ if (fgets(buf, buflen - 1, fp) == NULL)
|
||||
+ break;
|
||||
+ else if (buf != NULL)
|
||||
+ n = strlen(buf);
|
||||
+ else
|
||||
+ n = 0;
|
||||
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
|
||||
+ cp = buf;
|
||||
+
|
||||
+ if (n < 1)
|
||||
+ break;
|
||||
+ if (cp[n - 1] == '\n')
|
||||
+ cp[n - 1] = '\0';
|
||||
+
|
||||
+ tmp = strchr(cp, '#'); /* remove comments */
|
||||
+ if (tmp)
|
||||
+ *tmp = '\0';
|
||||
+ while (isspace((int)*cp)) /* remove spaces and tabs */
|
||||
+ ++cp;
|
||||
+ if (*cp == '\0') /* ignore empty lines */
|
||||
+ continue;
|
||||
+
|
||||
+ tmp = strsep (&cp, " \t=");
|
||||
+ if (cp != NULL)
|
||||
+ while (isspace((int)*cp) || *cp == '=')
|
||||
+ ++cp;
|
||||
+ else
|
||||
+ cp = "";
|
||||
+
|
||||
+ if (strcasecmp(tmp, key) == 0) {
|
||||
+ retval = strdup(cp);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ fclose(fp);
|
||||
+
|
||||
+ free(buf);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static uid_t
|
||||
+pam_usertype_get_id(pam_handle_t *pamh,
|
||||
+ const char *key,
|
||||
+ uid_t default_value)
|
||||
+{
|
||||
+ unsigned long ul;
|
||||
+ char *value;
|
||||
+ char *ep;
|
||||
+ uid_t uid;
|
||||
+
|
||||
+ value = pam_usertype_search_key(pamh, LOGIN_DEFS, key);
|
||||
+ if (value == NULL) {
|
||||
+ return default_value;
|
||||
+ }
|
||||
+
|
||||
+ /* taken from get_lastlog_uid_max() */
|
||||
+ ep = value + strlen(value);
|
||||
+ while (ep > value && isspace(*(--ep))) {
|
||||
+ *ep = '\0';
|
||||
+ }
|
||||
+
|
||||
+ errno = 0;
|
||||
+ ul = strtoul(value, &ep, 10);
|
||||
+ if (!(ul >= MAX_UID_VALUE
|
||||
+ || (uid_t)ul >= MAX_UID_VALUE
|
||||
+ || (errno != 0 && ul == 0)
|
||||
+ || value == ep
|
||||
+ || *ep != '\0')) {
|
||||
+ uid = (uid_t)ul;
|
||||
+ } else {
|
||||
+ uid = default_value;
|
||||
+ }
|
||||
+
|
||||
+ free(value);
|
||||
+
|
||||
+ return uid;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
|
||||
+{
|
||||
+ uid_t uid_min;
|
||||
+ uid_t sys_min;
|
||||
+ uid_t sys_max;
|
||||
+
|
||||
+ if (uid == (uid_t)-1) {
|
||||
+ pam_syslog(pamh, LOG_WARNING, "invalid uid");
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ }
|
||||
+
|
||||
+ if (uid <= 99) {
|
||||
+ /* Reserved. */
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ if (uid == PAM_USERTYPE_OVERFLOW_UID) {
|
||||
+ /* nobody */
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
+
|
||||
+ uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
|
||||
+ sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
|
||||
+ sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
|
||||
+
|
||||
+ return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+pam_usertype_is_regular(pam_handle_t *pamh, uid_t uid)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pam_usertype_is_system(pamh, uid);
|
||||
+ switch (ret) {
|
||||
+ case PAM_SUCCESS:
|
||||
+ return PAM_AUTH_ERR;
|
||||
+ case PAM_USER_UNKNOWN:
|
||||
+ return PAM_USER_UNKNOWN;
|
||||
+ default:
|
||||
+ return PAM_SUCCESS;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+pam_usertype_evaluate(struct pam_usertype_opts *opts,
|
||||
+ pam_handle_t *pamh,
|
||||
+ uid_t uid)
|
||||
+{
|
||||
+ switch (opts->op) {
|
||||
+ case OP_IS_SYSTEM:
|
||||
+ return pam_usertype_is_system(pamh, uid);
|
||||
+ case OP_IS_REGULAR:
|
||||
+ return pam_usertype_is_regular(pamh, uid);
|
||||
+ default:
|
||||
+ pam_syslog(pamh, LOG_ERR, "Unknown operation: %d", opts->op);
|
||||
+ return PAM_SERVICE_ERR;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Arguments:
|
||||
+ * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
|
||||
+ * - isregular: not issystem
|
||||
+ * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
|
||||
+ * - audit: log unknown users to syslog
|
||||
+ */
|
||||
+int
|
||||
+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
|
||||
+ int argc, const char **argv)
|
||||
+{
|
||||
+ struct pam_usertype_opts opts;
|
||||
+ uid_t uid;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pam_usertype_parse_args(&opts, pamh, argc, argv);
|
||||
+ if (ret != PAM_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = pam_usertype_get_uid(&opts, pamh, &uid);
|
||||
+ if (ret != PAM_SUCCESS) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return pam_usertype_evaluate(&opts, pamh, uid);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
|
||||
+ int argc UNUSED, const char **argv UNUSED)
|
||||
+{
|
||||
+ return PAM_IGNORE;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
+{
|
||||
+ return pam_sm_authenticate(pamh, flags, argc, argv);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
+{
|
||||
+ return pam_sm_authenticate(pamh, flags, argc, argv);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
+{
|
||||
+ return pam_sm_authenticate(pamh, flags, argc, argv);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
+{
|
||||
+ return pam_sm_authenticate(pamh, flags, argc, argv);
|
||||
+}
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/README.xml
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/README.xml 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -0,0 +1,41 @@
|
||||
+<?xml version="1.0" encoding='UTF-8'?>
|
||||
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
+"http://www.docbook.org/xml/4.3/docbookx.dtd"
|
||||
+[
|
||||
+<!--
|
||||
+<!ENTITY pamaccess SYSTEM "pam_usertype.8.xml">
|
||||
+-->
|
||||
+]>
|
||||
+
|
||||
+<article>
|
||||
+
|
||||
+ <articleinfo>
|
||||
+
|
||||
+ <title>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_usertype.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_usertype-name"]/*)'/>
|
||||
+ </title>
|
||||
+
|
||||
+ </articleinfo>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-description"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-options"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-examples"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+ <section>
|
||||
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-author"]/*)'/>
|
||||
+ </section>
|
||||
+
|
||||
+</article>
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype
|
||||
--- Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype 2020-05-15 10:03:27.270468089 +0200
|
||||
@@ -0,0 +1,2 @@
|
||||
+#!/bin/sh
|
||||
+../../tests/tst-dlopen .libs/pam_usertype.so
|
12
SOURCES/pam-1.3.1-unix-default-rounds.patch
Normal file
12
SOURCES/pam-1.3.1-unix-default-rounds.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds 2023-11-02 09:59:54.533238124 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c 2023-11-02 10:40:58.017404936 +0100
|
||||
@@ -607,7 +607,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
|
||||
unsigned int ctrl, lctrl;
|
||||
int retval;
|
||||
int remember = -1;
|
||||
- int rounds = -1;
|
||||
+ int rounds = 0;
|
||||
int pass_min_len = 0;
|
||||
|
||||
/* <DO NOT free() THESE> */
|
174
SOURCES/pam-1.3.1-unix-enable-bcrypt.patch
Normal file
174
SOURCES/pam-1.3.1-unix-enable-bcrypt.patch
Normal file
@ -0,0 +1,174 @@
|
||||
From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
|
||||
Date: Thu, 15 Nov 2018 15:01:57 +0100
|
||||
Subject: [PATCH] pam_unix: Use bcrypt b-variant for computing new hashes.
|
||||
|
||||
Bcrypt hashes used the "$2a$" prefix since 1997.
|
||||
However, in 2011 an implementation bug was discovered in bcrypt
|
||||
affecting the handling of characters in passphrases with the 8th
|
||||
bit set.
|
||||
|
||||
Besides fixing the bug, OpenBSD 5.5 introduced the "$2b$" prefix
|
||||
for a behavior that exactly matches crypt_blowfish's "$2y$", and
|
||||
the crypt_blowfish implementation supports it as well since v1.1.
|
||||
|
||||
That said new computed bcrypt hashes should use the "$2b$" prefix.
|
||||
|
||||
* modules/pam_unix/passverify.c: Use bcrypt b-variant.
|
||||
---
|
||||
modules/pam_unix/passverify.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
|
||||
index 9c1771e2..1f433b3a 100644
|
||||
--- a/modules/pam_unix/passverify.c
|
||||
+++ b/modules/pam_unix/passverify.c
|
||||
@@ -385,7 +385,7 @@ PAMH_ARG_DECL(char * create_password_hash,
|
||||
/* algoid = "$1" */
|
||||
return crypt_md5_wrapper(password);
|
||||
} else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
|
||||
- algoid = "$2a$";
|
||||
+ algoid = "$2b$";
|
||||
} else if (on(UNIX_SHA256_PASS, ctrl)) {
|
||||
algoid = "$5$";
|
||||
} else if (on(UNIX_SHA512_PASS, ctrl)) {
|
||||
--
|
||||
2.41.0
|
||||
|
||||
diff -up Linux-PAM-1.3.1/configure.ac.legacy-xcrypt Linux-PAM-1.3.1/configure.ac
|
||||
--- Linux-PAM-1.3.1/configure.ac.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200
|
||||
+++ Linux-PAM-1.3.1/configure.ac 2023-10-26 12:10:38.289654696 +0200
|
||||
@@ -395,19 +395,32 @@ AC_SUBST(LIBAUDIT)
|
||||
AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
|
||||
[test "x$HAVE_AUDIT_TTY_STATUS" = xyes])
|
||||
|
||||
-AC_CHECK_HEADERS(xcrypt.h crypt.h)
|
||||
-AS_IF([test "x$ac_cv_header_xcrypt_h" = "xyes"],
|
||||
- [crypt_libs="xcrypt crypt"],
|
||||
- [crypt_libs="crypt"])
|
||||
+AC_CHECK_HEADERS(crypt.h)
|
||||
|
||||
BACKUP_LIBS=$LIBS
|
||||
-AC_SEARCH_LIBS([crypt],[$crypt_libs], LIBCRYPT="${ac_lib:+-l$ac_lib}", LIBCRYPT="")
|
||||
-AC_CHECK_FUNCS(crypt_r crypt_gensalt_r)
|
||||
+LIBCRYPT=""
|
||||
+PKG_CHECK_MODULES([CRYPT], [libcrypt], [
|
||||
+ CFLAGS="$CFLAGS $CRYPT_CFLAGS"
|
||||
+ CPPFLAGS="$CPPFLAGS $CRYPT_CFLAGS"
|
||||
+ LIBS="$LIBS $CRYPT_LIBS"
|
||||
+ LIBCRYPT="$CRYPT_LIBS"
|
||||
+], [
|
||||
+ AC_SEARCH_LIBS([crypt_gensalt_rn],[crypt])
|
||||
+ case "$ac_cv_search_crypt_gensalt_rn" in
|
||||
+ -l*) LIBCRYPT="$ac_cv_search_crypt_gensalt_rn" ;;
|
||||
+ no) AC_SEARCH_LIBS([crypt_r],[crypt])
|
||||
+ case "$ac_cv_search_crypt_r" in
|
||||
+ -l*) LIBCRYPT="$ac_cv_search_crypt_r" ;;
|
||||
+ no ) AC_SEARCH_LIBS([crypt],[crypt])
|
||||
+ case "$ac_cv_search_crypt" in
|
||||
+ -l*) LIBCRYPT="$ac_cv_search_crypt" ;;
|
||||
+ esac ;;
|
||||
+ esac ;;
|
||||
+ esac
|
||||
+])
|
||||
+AC_CHECK_FUNCS([crypt_r])
|
||||
LIBS=$BACKUP_LIBS
|
||||
AC_SUBST(LIBCRYPT)
|
||||
-if test "$LIBCRYPT" = "-lxcrypt" -a "$ac_cv_header_xcrypt_h" = "yes" ; then
|
||||
- AC_DEFINE([HAVE_LIBXCRYPT], 1, [Define to 1 if xcrypt support should be compiled in.])
|
||||
-fi
|
||||
|
||||
AC_ARG_WITH([randomdev], AS_HELP_STRING([--with-randomdev=(<path>|yes|no)],[use specified random device instead of /dev/urandom or 'no' to disable]), opt_randomdev=$withval)
|
||||
if test "$opt_randomdev" = yes -o -z "$opt_randomdev"; then
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c 2023-10-26 12:11:14.437725259 +0200
|
||||
@@ -52,9 +52,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
-#if defined (HAVE_XCRYPT_H)
|
||||
-#include <xcrypt.h>
|
||||
-#elif defined (HAVE_CRYPT_H)
|
||||
+#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt 2017-02-10 11:10:15.000000000 +0100
|
||||
+++ Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c 2023-10-26 12:08:46.896437225 +0200
|
||||
@@ -29,9 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <security/_pam_macros.h>
|
||||
-#ifdef HAVE_LIBXCRYPT
|
||||
-#include <xcrypt.h>
|
||||
-#elif defined(HAVE_CRYPT_H)
|
||||
+#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/passverify.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt 2023-10-26 12:08:46.895437223 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2023-10-26 12:16:25.470320408 +0200
|
||||
@@ -19,9 +19,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
-#ifdef HAVE_LIBXCRYPT
|
||||
-#include <xcrypt.h>
|
||||
-#elif defined(HAVE_CRYPT_H)
|
||||
+#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
@@ -406,23 +404,19 @@ PAMH_ARG_DECL(char * create_password_has
|
||||
return crypted;
|
||||
}
|
||||
|
||||
-#ifdef HAVE_CRYPT_GENSALT_R
|
||||
- if (on(UNIX_BLOWFISH_PASS, ctrl)) {
|
||||
- char entropy[17];
|
||||
- crypt_make_salt(entropy, sizeof(entropy) - 1);
|
||||
- sp = crypt_gensalt_r (algoid, rounds,
|
||||
- entropy, sizeof(entropy),
|
||||
- salt, sizeof(salt));
|
||||
- } else {
|
||||
-#endif
|
||||
- sp = stpcpy(salt, algoid);
|
||||
- if (on(UNIX_ALGO_ROUNDS, ctrl)) {
|
||||
- sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds);
|
||||
- }
|
||||
- crypt_make_salt(sp, 16);
|
||||
-#ifdef HAVE_CRYPT_GENSALT_R
|
||||
+#if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY
|
||||
+ /*
|
||||
+ * Any version of libcrypt supporting auto entropy is
|
||||
+ * guaranteed to have crypt_gensalt_rn().
|
||||
+ */
|
||||
+ sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt));
|
||||
+#else
|
||||
+ sp = stpcpy(salt, algoid);
|
||||
+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
|
||||
+ sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds);
|
||||
}
|
||||
-#endif
|
||||
+ crypt_make_salt(sp, 16);
|
||||
+#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */
|
||||
#ifdef HAVE_CRYPT_R
|
||||
sp = NULL;
|
||||
cdata = malloc(sizeof(*cdata));
|
||||
diff -up Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c
|
||||
--- Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt 2023-10-26 12:08:46.880437194 +0200
|
||||
+++ Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c 2023-10-26 12:08:46.896437225 +0200
|
||||
@@ -17,9 +17,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
-#ifdef HAVE_LIBXCRYPT
|
||||
-#include <xcrypt.h>
|
||||
-#elif defined(HAVE_CRYPT_H)
|
||||
+#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
134
SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch
Normal file
134
SOURCES/pam-1.3.1-wheel-pam_ruser-fallback.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From 6bf9b454eb971083f0cce49faa2aa1cde329ff5d Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Wed, 26 Aug 2020 14:44:23 +0200
|
||||
Subject: [PATCH 1/3] pam_wheel: improve coding style
|
||||
|
||||
modules/pam_wheel/pam_wheel.c: improve indentation and explicitly state
|
||||
condition statements
|
||||
---
|
||||
modules/pam_wheel/pam_wheel.c | 36 ++++++++++++++++++-----------------
|
||||
1 file changed, 19 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c
|
||||
index a025ebaf..94cb7d89 100644
|
||||
--- a/modules/pam_wheel/pam_wheel.c
|
||||
+++ b/modules/pam_wheel/pam_wheel.c
|
||||
@@ -130,25 +130,27 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group)
|
||||
}
|
||||
|
||||
if (ctrl & PAM_USE_UID_ARG) {
|
||||
- tpwd = pam_modutil_getpwuid (pamh, getuid());
|
||||
- if (!tpwd) {
|
||||
- if (ctrl & PAM_DEBUG_ARG) {
|
||||
+ tpwd = pam_modutil_getpwuid (pamh, getuid());
|
||||
+ if (tpwd == NULL) {
|
||||
+ if (ctrl & PAM_DEBUG_ARG) {
|
||||
pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
|
||||
- }
|
||||
- return PAM_SERVICE_ERR;
|
||||
- }
|
||||
- fromsu = tpwd->pw_name;
|
||||
+ }
|
||||
+ return PAM_SERVICE_ERR;
|
||||
+ }
|
||||
+ fromsu = tpwd->pw_name;
|
||||
} else {
|
||||
- fromsu = pam_modutil_getlogin(pamh);
|
||||
- if (fromsu) {
|
||||
- tpwd = pam_modutil_getpwnam (pamh, fromsu);
|
||||
- }
|
||||
- if (!fromsu || !tpwd) {
|
||||
- if (ctrl & PAM_DEBUG_ARG) {
|
||||
- pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
|
||||
- }
|
||||
- return PAM_SERVICE_ERR;
|
||||
- }
|
||||
+ fromsu = pam_modutil_getlogin(pamh);
|
||||
+
|
||||
+ if (fromsu != NULL) {
|
||||
+ tpwd = pam_modutil_getpwnam (pamh, fromsu);
|
||||
+ }
|
||||
+
|
||||
+ if (fromsu == NULL || tpwd == NULL) {
|
||||
+ if (ctrl & PAM_DEBUG_ARG) {
|
||||
+ pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
|
||||
+ }
|
||||
+ return PAM_SERVICE_ERR;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From 9091ea1d81e85f49a221b0325d27b22ce69e444a Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Thu, 27 Aug 2020 09:16:15 +0200
|
||||
Subject: [PATCH 2/3] pam_wheel: if getlogin fails fallback to PAM_RUSER
|
||||
|
||||
modules/pam_wheel/pam_wheel.c: if getlogin fails to obtain the real user
|
||||
ID, then try with PAM_RUSER.
|
||||
|
||||
Resolves:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1866866
|
||||
---
|
||||
modules/pam_wheel/pam_wheel.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c
|
||||
index 94cb7d89..7fa3cfa9 100644
|
||||
--- a/modules/pam_wheel/pam_wheel.c
|
||||
+++ b/modules/pam_wheel/pam_wheel.c
|
||||
@@ -141,6 +141,16 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group)
|
||||
} else {
|
||||
fromsu = pam_modutil_getlogin(pamh);
|
||||
|
||||
+ /* if getlogin fails try a fallback to PAM_RUSER */
|
||||
+ if (fromsu == NULL) {
|
||||
+ const char *rhostname;
|
||||
+
|
||||
+ retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhostname);
|
||||
+ if (retval != PAM_SUCCESS || rhostname == NULL) {
|
||||
+ retval = pam_get_item(pamh, PAM_RUSER, (const void **)&fromsu);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (fromsu != NULL) {
|
||||
tpwd = pam_modutil_getpwnam (pamh, fromsu);
|
||||
}
|
||||
--
|
||||
2.26.2
|
||||
|
||||
|
||||
From a3a5cbf86083c43026b558e2023f597530626267 Mon Sep 17 00:00:00 2001
|
||||
From: ikerexxe <ipedrosa@redhat.com>
|
||||
Date: Wed, 9 Sep 2020 10:32:03 +0200
|
||||
Subject: [PATCH 3/3] pam_wheel: clarify use_uid option in man page
|
||||
|
||||
modules/pam_wheel/pam_wheel.8.xml: indicate that use_uid option uses the
|
||||
real uid of the calling process.
|
||||
---
|
||||
modules/pam_wheel/pam_wheel.8.xml | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_wheel/pam_wheel.8.xml b/modules/pam_wheel/pam_wheel.8.xml
|
||||
index b32f5e2b..ee8c7d26 100644
|
||||
--- a/modules/pam_wheel/pam_wheel.8.xml
|
||||
+++ b/modules/pam_wheel/pam_wheel.8.xml
|
||||
@@ -122,9 +122,9 @@
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
- The check for wheel membership will be done against
|
||||
- the current uid instead of the original one (useful when
|
||||
- jumping with su from one account to another for example).
|
||||
+ The check will be done against the real uid of the calling process,
|
||||
+ instead of trying to obtain the user from the login session
|
||||
+ associated with the terminal in use.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
--
|
||||
2.26.2
|
||||
|
37
SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
Normal file
37
SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 10086bc69663fa819277af244eeb5b629a2403b8 Mon Sep 17 00:00:00 2001
|
||||
From: Deepak Das <ddas@redhat.com>
|
||||
Date: Mon, 10 Oct 2022 21:21:35 +0530
|
||||
Subject: [PATCH] pam_faillock: avoid logging an erroneous consecutive login
|
||||
failure message
|
||||
|
||||
* modules/pam_faillock/pam_faillock.c (write_tally): Avoid logging
|
||||
a consecutive login failure message for the root user in case when
|
||||
even_deny_root is not set.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2082442
|
||||
---
|
||||
modules/pam_faillock/pam_faillock.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
|
||||
index ddbb90e7..ca1c7035 100644
|
||||
--- a/modules/pam_faillock/pam_faillock.c
|
||||
+++ b/modules/pam_faillock/pam_faillock.c
|
||||
@@ -374,9 +374,11 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
|
||||
}
|
||||
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 (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO) &&
|
||||
+ ((opts->flags & FAILLOCK_FLAG_DENY_ROOT) || (opts->uid != 0))) {
|
||||
+ pam_syslog(pamh, LOG_INFO,
|
||||
+ "Consecutive login failures for user %s account temporarily locked",
|
||||
+ opts->user);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
53
SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch
Normal file
53
SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From bcbf145ce925934214e48200c27c9ff736452549 Mon Sep 17 00:00:00 2001
|
||||
From: Deepak Das <ddas@redhat.com>
|
||||
Date: Mon, 10 Oct 2022 17:55:53 +0530
|
||||
Subject: [PATCH] pam_faillock: Clarify missing user faillock files after
|
||||
reboot
|
||||
|
||||
* modules/pam_faillock/faillock.conf.5.xml: Adding note related to missing
|
||||
user specific faillock files after reboot.
|
||||
|
||||
* modules/pam_faillock/pam_faillock.8.xml: Adding note related to missing
|
||||
user specific faillock files after reboot.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2062512
|
||||
---
|
||||
modules/pam_faillock/faillock.conf.5.xml | 4 ++++
|
||||
modules/pam_faillock/pam_faillock.8.xml | 6 ++++++
|
||||
2 files changed, 10 insertions(+)
|
||||
|
||||
diff --git a/modules/pam_faillock/faillock.conf.5.xml b/modules/pam_faillock/faillock.conf.5.xml
|
||||
index 04a84107..8faa5915 100644
|
||||
--- a/modules/pam_faillock/faillock.conf.5.xml
|
||||
+++ b/modules/pam_faillock/faillock.conf.5.xml
|
||||
@@ -44,6 +44,10 @@
|
||||
The directory where the user files with the failure records are kept. The
|
||||
default is <filename>/var/run/faillock</filename>.
|
||||
</para>
|
||||
+ <para>
|
||||
+ Note: These files will disappear after reboot on systems configured with
|
||||
+ directory <filename>/var/run/faillock</filename> mounted on virtual memory.
|
||||
+ </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml
|
||||
index 79bcbbd0..b7b7b0db 100644
|
||||
--- a/modules/pam_faillock/pam_faillock.8.xml
|
||||
+++ b/modules/pam_faillock/pam_faillock.8.xml
|
||||
@@ -327,6 +327,12 @@ session required pam_selinux.so open
|
||||
<term><filename>/var/run/faillock/*</filename></term>
|
||||
<listitem>
|
||||
<para>the files logging the authentication failures for users</para>
|
||||
+ <para>
|
||||
+ Note: These files will disappear after reboot on systems configured with
|
||||
+ directory <filename>/var/run/faillock</filename> mounted on virtual memory.
|
||||
+ For persistent storage use the option <emphasis>dir=</emphasis> in
|
||||
+ file <filename>/etc/security/faillock.conf</filename>.
|
||||
+ </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
--
|
||||
2.38.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 40c271164dbcebfc5304d0537a42fb42e6b6803c Mon Sep 17 00:00:00 2001
|
||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
Date: Mon, 26 Sep 2022 12:16:53 +0200
|
||||
Subject: [PATCH] pam_lastlog: check localtime_r() return value
|
||||
|
||||
Check the return value of localtime_r() before calling strftime(). This
|
||||
function crashes if the argument is NULL.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012871
|
||||
|
||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||
---
|
||||
modules/pam_lastlog/pam_lastlog.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
|
||||
index abd048df..121e7560 100644
|
||||
--- a/modules/pam_lastlog/pam_lastlog.c
|
||||
+++ b/modules/pam_lastlog/pam_lastlog.c
|
||||
@@ -573,12 +573,12 @@ last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t llt
|
||||
time_t lf_time;
|
||||
|
||||
lf_time = utuser.ut_tv.tv_sec;
|
||||
- tm = localtime_r (&lf_time, &tm_buf);
|
||||
- strftime (the_time, sizeof (the_time),
|
||||
- /* TRANSLATORS: "strftime options for date of last login" */
|
||||
- _(" %a %b %e %H:%M:%S %Z %Y"), tm);
|
||||
-
|
||||
- date = the_time;
|
||||
+ if ((tm = localtime_r (&lf_time, &tm_buf)) != NULL) {
|
||||
+ strftime (the_time, sizeof (the_time),
|
||||
+ /* TRANSLATORS: "strftime options for date of last login" */
|
||||
+ _(" %a %b %e %H:%M:%S %Z %Y"), tm);
|
||||
+ date = the_time;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* we want & have the host? */
|
||||
--
|
||||
2.38.1
|
||||
|
@ -1,3 +1,4 @@
|
||||
d /run/console 0755 root root -
|
||||
d /run/faillock 0755 root root -
|
||||
d /run/sepermit 0755 root root -
|
||||
d /run/motd.d 0755 root root -
|
||||
|
@ -1,19 +1,4 @@
|
||||
#%PAM-1.0
|
||||
# This file is auto-generated.
|
||||
# User changes will be destroyed the next time authselect is run.
|
||||
auth required pam_env.so
|
||||
auth [success=done ignore=ignore default=die] pam_pkcs11.so wait_for_card
|
||||
auth required pam_deny.so
|
||||
|
||||
account required pam_unix.so
|
||||
account sufficient pam_localuser.so
|
||||
account sufficient pam_succeed_if.so uid < 500 quiet
|
||||
account required pam_permit.so
|
||||
|
||||
password optional pam_pkcs11.so
|
||||
|
||||
session optional pam_keyinit.so revoke
|
||||
session required pam_limits.so
|
||||
-session optional pam_systemd.so
|
||||
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
|
||||
session required pam_unix.so
|
||||
auth sufficient pam_sss.so allow_missing_name
|
||||
|
201
SPECS/pam.spec
201
SPECS/pam.spec
@ -3,7 +3,7 @@
|
||||
Summary: An extensible library which provides authentication for applications
|
||||
Name: pam
|
||||
Version: 1.3.1
|
||||
Release: 8%{?dist}
|
||||
Release: 36%{?dist}
|
||||
# The library is BSD licensed with option to relicense as GPLv2+
|
||||
# - this option is redundant as the BSD license allows that anyway.
|
||||
# pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+.
|
||||
@ -53,6 +53,76 @@ Patch41: pam-1.3.1-tty-audit-manfix.patch
|
||||
Patch42: pam-1.3.1-fds-closing.patch
|
||||
Patch43: pam-1.3.1-authtok-verify-fix.patch
|
||||
Patch44: pam-1.3.1-motd-manpage.patch
|
||||
# Upstreamed
|
||||
Patch45: pam-1.3.1-pam-usertype.patch
|
||||
# Upstreamed
|
||||
Patch46: pam-1.3.1-audit-error.patch
|
||||
# Upstreamed
|
||||
Patch47: pam-1.3.1-pam-modutil-close-write.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/6bf9b454eb971083f0cce49faa2aa1cde329ff5d
|
||||
# https://github.com/linux-pam/linux-pam/commit/9091ea1d81e85f49a221b0325d27b22ce69e444a
|
||||
# https://github.com/linux-pam/linux-pam/commit/a3a5cbf86083c43026b558e2023f597530626267
|
||||
Patch48: pam-1.3.1-wheel-pam_ruser-fallback.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/491e5500b6b3913f531574208274358a2df88659
|
||||
Patch49: pam-1.3.1-namespace-gdm-doc.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/a7453aeeb398d6cbb7a709c4e2a1d75905220fff
|
||||
Patch50: pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff
|
||||
Patch51: pam-1.3.1-pam-limits-unlimited-value.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62
|
||||
Patch52: pam-1.3.1-pam-keyinit-thread-safe.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/f9c9c72121eada731e010ab3620762bcf63db08f
|
||||
Patch53: pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/8eaf5570cf011148a0b55c53570df5edaafebdb0
|
||||
Patch54: pam-1.3.1-pam-motd-fix-segmentation-fault.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/62cd745d730e5ba13d5d7092ac566fc0b2148e61
|
||||
Patch55: pam-1.3.1-pam-motd-fix-memory-leak.patch
|
||||
# Needed by the next patch. Already upstreamed
|
||||
Patch56: pam-1.3.1-pam-cc-compat.patch
|
||||
Patch57: pam-1.3.1-inline.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/9bcbe96d9e82a23d983c0618178a8dc25596ac2d
|
||||
# https://github.com/linux-pam/linux-pam/commit/fc867a9e22eac2c9a0ed0577776bba4df21c9aad
|
||||
Patch58: pam-1.3.1-faillock-load-conf-from-file.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/370064ef6f99581b08d473a42bb3417d5dda3e4e
|
||||
Patch59: pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/ba2f6dd8b81ea2a58262c1709bec906b6852591d
|
||||
# https://github.com/linux-pam/linux-pam/commit/1180bde923a22605fe8075cd1fe7992ed7513411
|
||||
Patch60: pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/d57ab22133654033ee1da89f128a81572d320985
|
||||
# https://github.com/linux-pam/linux-pam/commit/c2c0434bd634a817f2b16ce7f58fc96c04e88b03
|
||||
Patch61: pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/40c271164dbcebfc5304d0537a42fb42e6b6803c
|
||||
Patch62: pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/bcbf145ce925934214e48200c27c9ff736452549
|
||||
Patch63: pam-1.5.1-pam-faillock-clarify-missing-user.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/10086bc69663fa819277af244eeb5b629a2403b8
|
||||
Patch64: pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/55f206447a1e4ee26e307e7a9c069236e823b1a5
|
||||
# https://github.com/linux-pam/linux-pam/commit/80bfda5962e5be3daa70e0fc8c75fc97d1c55121
|
||||
Patch65: pam-1.3.1-pam-misc-configurable.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/530c9f9e2d746e1d168c6b17863debda7664ac7c
|
||||
# https://github.com/linux-pam/linux-pam/commit/f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016
|
||||
Patch66: pam-1.3.1-unix-enable-bcrypt.patch
|
||||
Patch67: pam-1.3.1-unix-default-rounds.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/d54870f993e97fe75e2cd0470a3701d5af22877c
|
||||
Patch68: pam-1.3.1-faillock-create-tallydir.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f
|
||||
Patch69: pam-1.3.1-access-handle-hostnames.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/031bb5a5d0d950253b68138b498dc93be69a64cb
|
||||
Patch70: pam-1.3.1-namespace-protect-dir.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/c85513220c1bd3150e39c6277422d29cfa44acc7
|
||||
# https://github.com/linux-pam/linux-pam/commit/1648734a69c31e9ce834da70144ac9a453296807
|
||||
Patch71: pam-1.3.1-audit-messages-formatting.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/b3020da7da384d769f27a8713257fbe1001878be
|
||||
# https://github.com/linux-pam/linux-pam/commit/8d0c575336ad301cd14e16ad2fdec6fe621764b8
|
||||
Patch72: pam-1.3.1-pam-unix-shadow-password.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/08992030c56c940c0707ccbc442b1c325aa01e6d
|
||||
# https://github.com/linux-pam/linux-pam/commit/641dfd1084508c63f3590e93a35b80ffc50774e5
|
||||
Patch73: pam-1.3.1-pam-access-local.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/ec1fb9ddc6c252d8c61379e9385ca19c036fcb96
|
||||
Patch74: pam-1.3.1-libpam-support-long-lines.patch
|
||||
# https://github.com/linux-pam/linux-pam/commit/940747f88c16e029b69a74e80a2e94f65cb3e628
|
||||
Patch75: pam-1.3.1-pam-access-resolve-ip.patch
|
||||
|
||||
%define _pamlibdir %{_libdir}
|
||||
%define _moduledir %{_libdir}/security
|
||||
@ -145,6 +215,38 @@ cp %{SOURCE18} .
|
||||
%patch42 -p1 -b .fds-closing
|
||||
%patch43 -p1 -b .authtok-verify-fix
|
||||
%patch44 -p1 -b .motd-manpage
|
||||
%patch45 -p1 -b .pam-usertype
|
||||
%patch46 -p1 -b .audit-error
|
||||
%patch47 -p1 -b .pam-modutil-close-write
|
||||
%patch48 -p1 -b .wheel-pam_ruser-fallback
|
||||
%patch49 -p1 -b .namespace-gdm-doc
|
||||
%patch50 -p1 -b .pam-userdb-prevent-garbage-characters-from-db
|
||||
%patch51 -p1 -b .pam-limits-unlimited-value
|
||||
%patch52 -p1 -b .pam-keyinit-thread-safe
|
||||
%patch53 -p1 -b .pam-motd-support-multiple-motd-paths
|
||||
%patch54 -p1 -b .pam-motd-fix-segmentation-fault
|
||||
%patch55 -p1 -b .pam-motd-fix-memory-leak
|
||||
%patch56 -p1 -b .pam-cc-compat
|
||||
%patch57 -p1 -b .inline
|
||||
%patch58 -p1 -b .faillock-load-conf-from-file
|
||||
%patch59 -p1 -b .pam-usertype-SYS_UID_MAX
|
||||
%patch60 -p1 -b .pam-pwhistory-load-conf-from-file
|
||||
%patch61 -p1 -b .pam-motd-avoid-unnecessary-logging
|
||||
%patch62 -p1 -b .pam-lastlog-check-localtime_r-return-value
|
||||
%patch63 -p1 -b .pam-faillock-clarify-missing-user
|
||||
%patch64 -p1 -b .pam-faillock-avoid-logging-erroneous
|
||||
%patch65 -p1 -b .pam-misc-configurable
|
||||
%patch66 -p1 -b .unix-enable-bcrypt
|
||||
%patch67 -p1 -b .unix-default-rounds
|
||||
%patch68 -p1 -b .faillock-create-tallydir
|
||||
%patch69 -p1 -b .access-handle-hostnames
|
||||
%patch70 -p1 -b .namespace-protect-dir
|
||||
%patch71 -p1 -b .audit-messages-formatting
|
||||
%patch72 -p1 -b .pam-unix-shadow-password
|
||||
%patch73 -p1 -b .pam-access-local
|
||||
%patch74 -p1 -b .libpam-support-long-lines
|
||||
%patch75 -p1 -b .pam-access-resolve-ip
|
||||
|
||||
autoreconf -i
|
||||
|
||||
%build
|
||||
@ -198,6 +300,9 @@ install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_pamconfdir}/postlogin
|
||||
install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd
|
||||
install -d -m 755 $RPM_BUILD_ROOT/var/log
|
||||
install -d -m 755 $RPM_BUILD_ROOT/var/run/faillock
|
||||
install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/motd.d
|
||||
install -d -m 755 $RPM_BUILD_ROOT/usr/lib/motd.d
|
||||
install -d -m 755 $RPM_BUILD_ROOT/run/motd.d
|
||||
|
||||
# Install man pages.
|
||||
install -m 644 %{SOURCE12} %{SOURCE13} %{SOURCE17} $RPM_BUILD_ROOT%{_mandir}/man5/
|
||||
@ -347,6 +452,7 @@ done
|
||||
%{_moduledir}/pam_unix_passwd.so
|
||||
%{_moduledir}/pam_unix_session.so
|
||||
%{_moduledir}/pam_userdb.so
|
||||
%{_moduledir}/pam_usertype.so
|
||||
%{_moduledir}/pam_warn.so
|
||||
%{_moduledir}/pam_wheel.so
|
||||
%{_moduledir}/pam_xauth.so
|
||||
@ -364,6 +470,7 @@ done
|
||||
%dir %{_secconfdir}/namespace.d
|
||||
%attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init
|
||||
%config(noreplace) %{_secconfdir}/pam_env.conf
|
||||
%config(noreplace) %{_secconfdir}/pwhistory.conf
|
||||
%config(noreplace) %{_secconfdir}/time.conf
|
||||
%config(noreplace) %{_secconfdir}/opasswd
|
||||
%dir %{_secconfdir}/console.apps
|
||||
@ -374,6 +481,9 @@ done
|
||||
%dir /var/run/sepermit
|
||||
%endif
|
||||
%dir /var/run/faillock
|
||||
%dir %{_sysconfdir}/motd.d
|
||||
%dir /run/motd.d
|
||||
%dir /usr/lib/motd.d
|
||||
%{_prefix}/lib/tmpfiles.d/pam.conf
|
||||
%{_mandir}/man5/*
|
||||
%{_mandir}/man8/*
|
||||
@ -389,6 +499,95 @@ done
|
||||
%doc doc/specs/rfc86.0.txt
|
||||
|
||||
%changelog
|
||||
* Mon Nov 25 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-36
|
||||
- pam_access: rework resolving of tokens as hostname.
|
||||
Resolves: CVE-2024-10963 and RHEL-66242
|
||||
|
||||
* Mon Nov 4 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-35
|
||||
- pam_unix: always run the helper to obtain shadow password file entries.
|
||||
CVE-2024-10041. Resolves: RHEL-62877
|
||||
- pam_access: always match local address and clarify LOCAL keyword behaviour.
|
||||
Resolves: RHEL-23018
|
||||
- libpam: support long lines in service files. Resolves: RHEL-5051
|
||||
|
||||
* Thu Apr 4 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-34
|
||||
- fix formatting of audit messages. Resolves: RHEL-28620
|
||||
|
||||
* Mon Feb 12 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-33
|
||||
- pam_namespace: protect_dir(): use O_DIRECTORY to prevent local DoS
|
||||
situations. CVE-2024-22365. Resolves: RHEL-21242
|
||||
|
||||
* Fri Jan 26 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-32
|
||||
- pam_access: handle hostnames in access.conf. Resolves: RHEL-3374
|
||||
|
||||
* Mon Jan 8 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-31
|
||||
- pam_faillock: create tallydir before creating tallyfile. Resolves: RHEL-19810
|
||||
|
||||
* Thu Nov 2 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-30
|
||||
- pam_unix: enable bcrypt. Resolves: RHEL-5057
|
||||
|
||||
* Mon Jun 26 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-27
|
||||
- pam_misc: make length of misc_conv() configurable and set to 4096. Resolves: #2209785
|
||||
|
||||
* Tue May 16 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-26
|
||||
- smartcard-auth: modify the content to remove unnecessary modules. Resolves: #1983683
|
||||
|
||||
* Tue Nov 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-25
|
||||
- pam_motd: avoid unnecessary logging. Resolves: #2091062
|
||||
- pam_lastlog: check localtime_r() return value. Resolves: #2012871
|
||||
- pam_faillock: clarify missing user faillock files after reboot. Resolves: #2062512
|
||||
- pam_faillock: avoid logging an erroneous consecutive login failure message. Resolves: #2082442
|
||||
|
||||
* Thu Sep 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-24
|
||||
- pam_pwhistory: load configuration from file. Resolves: #2068461
|
||||
|
||||
* Wed Jul 13 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-22
|
||||
- Regenerate the /run/motd.d at each boot. Resolves: #2104878
|
||||
|
||||
* Thu Jun 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-21
|
||||
- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #1949137
|
||||
|
||||
* Thu May 26 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-20
|
||||
- faillock: load configuration from file. Resolves: #1978029
|
||||
|
||||
* Mon May 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-19
|
||||
- Add the motd.d directories (empty) to silence warnings and to
|
||||
provide proper ownership for them. Resolves: #2014458
|
||||
|
||||
* Thu May 19 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-18
|
||||
- pam_motd: fix memory leak. Resolves: #2014458
|
||||
|
||||
* Tue May 17 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-17
|
||||
- pam_keyinit: thread-safe implementation. Resolves: #1997969
|
||||
- pam_motd: support multiple motd paths specified, with filename overrides. Resolves: #2014458
|
||||
|
||||
* Fri Jan 28 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-16
|
||||
- pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #2047655
|
||||
|
||||
* Mon May 3 2021 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-15
|
||||
- pam_userdb: Prevent garbage characters from db (#1791965)
|
||||
|
||||
* Thu Nov 5 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-14
|
||||
- Revert 1.3.1-12
|
||||
|
||||
* Fri Oct 30 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-13
|
||||
- pam_wheel: if getlogin fails fallback to PAM_RUSER: fixed malformed patch (#1866866)
|
||||
- pam_namespace: polyinstantiation refer to gdm doc (#1861841)
|
||||
|
||||
* Thu Jul 16 2020 Peter Robinson <pbrobinson@redhat.com> - 1.3.1-12
|
||||
- Add the motd.d directories (empty) to silence warnings and to
|
||||
provide proper ownership for them (#1847501)
|
||||
|
||||
* Fri May 15 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-11
|
||||
- pam_usertype: fixed malformed patch
|
||||
|
||||
* Tue Apr 21 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-10
|
||||
- pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of PAM_MODUTIL_PIPE_FD (#1791970)
|
||||
|
||||
* Fri Apr 17 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-9
|
||||
- pam_usertype: new module to tell if uid is in login.defs ranges (#1810474)
|
||||
- pam_tty_audit: if kernel audit is disabled return PAM_IGNORE (#1775357)
|
||||
|
||||
* Thu Dec 19 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-8
|
||||
- pam_motd: Document how to properly silence unwanted motd messages
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user