Compare commits
No commits in common. 'c9' and 'i10cs' have entirely different histories.
@ -1,2 +1,2 @@
|
|||||||
SOURCES/Linux-PAM-1.5.1.tar.xz
|
SOURCES/Linux-PAM-1.6.1.tar.xz
|
||||||
SOURCES/pam-redhat-1.1.4.tar.bz2
|
SOURCES/pam-redhat-1.2.0.tar.xz
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
ad43b7fbdfdd38886fdf27e098b49f2db1c2a13d SOURCES/Linux-PAM-1.5.1.tar.xz
|
633dfd431955044f7a4087553a5b00b509897197 SOURCES/Linux-PAM-1.6.1.tar.xz
|
||||||
bf661c44f34c2d4d34eaee695b36e638f4d44ba8 SOURCES/pam-redhat-1.1.4.tar.bz2
|
d84f186748f6b9ff84980a39acdaf76531c4990e SOURCES/pam-redhat-1.2.0.tar.xz
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQIcBAABCAAGBQJfvo0CAAoJEKgEH6g54W42L+0P/19bgVH4cRd7ONZLwYvWvWlQ
|
|
||||||
NXkjwn26MEXElWESlKnQQz08W5QASWCz3vgAn9NGDmS+lJ38i4Li4aGpn3COPE2g
|
|
||||||
BAN9LEaAErK60b3ZkWwDEARDs1JntA1vUuuHx0EoLEMtFEeU20h5PPMrsDwu7LGF
|
|
||||||
sD6KYdM6TWLMXcRybqGOeWmWxfp8S8MVNwVN3C3q0aVIOMxky0i4rzCL7zRTJztQ
|
|
||||||
q7FaX2xrTGfUiAI7smT/KGoK7pbQTzZtoR67uE/2WZ4bSyWMZcuDkt16WP/L6x9v
|
|
||||||
c5DnVaLazM9xYUAOn4tlPiG8LLmfXo1MjD+KOS9byAx+uTij3avxaC/vv0BDcATH
|
|
||||||
jywxH8iTPkvYXP0uJIa4Gbs1qi3vNZn+gaQt/T+rCVNo3dfFZZxBvLbTQ8AN1hKr
|
|
||||||
MnoQbIQh0buuSuwmAxF0EDIefX3bDCurKOTQrRajK7huFm0w2NgBqL8WR8f1Wmm9
|
|
||||||
mGSdKuVpWSk5uEygCUFOfwviYbi1I1K2Dmo3TsLBgNPKvAF3LAGJC7KzD+Q+Nmos
|
|
||||||
XBOljilcAfdJ7t2P8W7xTSMEnXu7nI1TM+Er80ukfu0fipJEP0xyi+XWh+2n0Bx+
|
|
||||||
3wwt8fSL7rmI4I4l6GRb3Jk/Gq1bKy956tgm3TE6gXTXVGZqNs0E28rNRURXDqZu
|
|
||||||
XrjVwhlpsH/Auk17hU65
|
|
||||||
=E0ev
|
|
||||||
-----END PGP SIGNATURE-----
|
|
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQIcBAABCgAGBQJmFWt/AAoJEKgEH6g54W42NCwP/iWl8igdScTreVF6zV79Dqu1
|
||||||
|
sl+ZjBr/dL+DOTcotsRnoAZUOy4ug3iktMZr1t0BMpWUorNmUofH4SZuhsX0CgRq
|
||||||
|
47t5mVqCakwn4JLq8J9cLOciMno6ips5ZT4RbMgzRYd1WcBurCAxQSNLP3aQGgub
|
||||||
|
RFObkqw5814ksz9Ge6QVhJ4l9P0wUoKfcpkzHj2Vq+cy0EzlBtnBGCHrMDgrz5aT
|
||||||
|
mXqGVvWTPO+lR2S+7wOLUtPoRv0uvN6h97ZszaoGoJ6wa6yYwOYz12/AiIsVQhet
|
||||||
|
cnr29ymuwPDqlrYGD1Hb0+ZUQExjVDQY90hdJ/ZntUlK7CY/2SotpDGB9kR8dTYJ
|
||||||
|
fpIVmR6GEZ+xSjBqa7RaiL8ieZCgT3TIvsMqteiFkqI+2lhlSGHX3g3oNSd3sbqd
|
||||||
|
PLok6W4L+xWDp89aMyYDDs/ISjBt5sSNK4NOOTZIMK4oeScGJJvrDL3S5DOSk1ku
|
||||||
|
o3l9N62WStD7fk0LYnyUGZORg/ccK6Yy2fV22zBMm/76PoyA1yHfFxCW+HwwmcqR
|
||||||
|
0riaFjA8cesZ3Dj79q24U3FRVdW5fTF9gS/5mK/Yj51KMMzTkUmbjksEC/AEBKzB
|
||||||
|
9laXxPdIeKUwNlGs7Heo/NE87u4OZfyihwpzLaTcOzbpN3zDyH6aH5poDs1FSaQ2
|
||||||
|
UoUkHsbCWJU/ksn/9BIQ
|
||||||
|
=Dbz2
|
||||||
|
-----END PGP SIGNATURE-----
|
@ -1,19 +0,0 @@
|
|||||||
#%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 sufficient pam_fprintd.so
|
|
||||||
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 required pam_deny.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
|
|
@ -0,0 +1,5 @@
|
|||||||
|
%_pam_libdir %{_libdir}
|
||||||
|
%_pam_moduledir %{_libdir}/security
|
||||||
|
%_pam_secconfdir %{_sysconfdir}/security
|
||||||
|
%_pam_confdir %{_sysconfdir}/pam.d
|
||||||
|
%_pam_vendordir %{_datadir}/pam.d
|
@ -1,144 +0,0 @@
|
|||||||
From 244b46908df930626535c0cd7c2867407fe8714a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Thorsten Kukuk <kukuk@suse.com>
|
|
||||||
Date: Tue, 14 Feb 2023 14:57:40 +0100
|
|
||||||
Subject: [PATCH] libpam: use getlogin() from libc and not utmp
|
|
||||||
|
|
||||||
utmp uses 32bit time_t for compatibility with 32bit userland on some
|
|
||||||
64bit systems and is thus not Y2038 safe. Use getlogin() from libc
|
|
||||||
which avoids using utmp and is more safe than the old utmp-based
|
|
||||||
implementation by using /proc/self/loginuid.
|
|
||||||
|
|
||||||
* libpam/pam_modutil_getlogin.c: Use getlogin() instead of parsing utmp
|
|
||||||
---
|
|
||||||
libpam/pam_modutil_getlogin.c | 52 ++++++++---------------------------
|
|
||||||
1 file changed, 11 insertions(+), 41 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libpam/pam_modutil_getlogin.c b/libpam/pam_modutil_getlogin.c
|
|
||||||
index 04a20fd8..633dd676 100644
|
|
||||||
--- a/libpam/pam_modutil_getlogin.c
|
|
||||||
+++ b/libpam/pam_modutil_getlogin.c
|
|
||||||
@@ -10,7 +10,6 @@
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
-#include <utmp.h>
|
|
||||||
|
|
||||||
#define _PAMMODUTIL_GETLOGIN "_pammodutil_getlogin"
|
|
||||||
|
|
||||||
@@ -19,62 +18,33 @@ pam_modutil_getlogin(pam_handle_t *pamh)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
const void *logname;
|
|
||||||
- const void *void_curr_tty;
|
|
||||||
- const char *curr_tty;
|
|
||||||
char *curr_user;
|
|
||||||
- struct utmp *ut, line;
|
|
||||||
+ size_t curr_user_len;
|
|
||||||
|
|
||||||
status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN, &logname);
|
|
||||||
if (status == PAM_SUCCESS) {
|
|
||||||
return logname;
|
|
||||||
}
|
|
||||||
|
|
||||||
- status = pam_get_item(pamh, PAM_TTY, &void_curr_tty);
|
|
||||||
- if ((status != PAM_SUCCESS) || (void_curr_tty == NULL))
|
|
||||||
- curr_tty = ttyname(0);
|
|
||||||
- else
|
|
||||||
- curr_tty = (const char*)void_curr_tty;
|
|
||||||
-
|
|
||||||
- if (curr_tty == NULL) {
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (curr_tty[0] == '/') { /* full path */
|
|
||||||
- const char *t;
|
|
||||||
- curr_tty++;
|
|
||||||
- if ((t = strchr(curr_tty, '/')) != NULL) {
|
|
||||||
- curr_tty = t + 1;
|
|
||||||
- }
|
|
||||||
+ logname = getlogin();
|
|
||||||
+ if (logname == NULL) {
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
- logname = NULL;
|
|
||||||
|
|
||||||
- setutent();
|
|
||||||
- strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
|
|
||||||
-
|
|
||||||
- if ((ut = getutline(&line)) == NULL) {
|
|
||||||
- goto clean_up_and_go_home;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- curr_user = calloc(sizeof(line.ut_user)+1, 1);
|
|
||||||
+ curr_user_len = strlen(logname)+1;
|
|
||||||
+ curr_user = calloc(curr_user_len, 1);
|
|
||||||
if (curr_user == NULL) {
|
|
||||||
- goto clean_up_and_go_home;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
|
|
||||||
- /* calloc already zeroed the memory */
|
|
||||||
+ memcpy(curr_user, logname, curr_user_len);
|
|
||||||
|
|
||||||
status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
|
|
||||||
pam_modutil_cleanup);
|
|
||||||
if (status != PAM_SUCCESS) {
|
|
||||||
- free(curr_user);
|
|
||||||
- goto clean_up_and_go_home;
|
|
||||||
+ free(curr_user);
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- logname = curr_user;
|
|
||||||
-
|
|
||||||
-clean_up_and_go_home:
|
|
||||||
-
|
|
||||||
- endutent();
|
|
||||||
-
|
|
||||||
- return logname;
|
|
||||||
+ return curr_user;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
From f26d873435be9f35fa7953493cc07a9bc4e31876 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
|
||||||
Date: Sat, 18 Feb 2023 14:37:04 +0100
|
|
||||||
Subject: [PATCH] libpam: simplify string copying using strdup
|
|
||||||
|
|
||||||
---
|
|
||||||
libpam/pam_modutil_getlogin.c | 6 +-----
|
|
||||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libpam/pam_modutil_getlogin.c b/libpam/pam_modutil_getlogin.c
|
|
||||||
index 633dd676..2e7a0116 100644
|
|
||||||
--- a/libpam/pam_modutil_getlogin.c
|
|
||||||
+++ b/libpam/pam_modutil_getlogin.c
|
|
||||||
@@ -19,7 +19,6 @@ pam_modutil_getlogin(pam_handle_t *pamh)
|
|
||||||
int status;
|
|
||||||
const void *logname;
|
|
||||||
char *curr_user;
|
|
||||||
- size_t curr_user_len;
|
|
||||||
|
|
||||||
status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN, &logname);
|
|
||||||
if (status == PAM_SUCCESS) {
|
|
||||||
@@ -31,14 +30,11 @@ pam_modutil_getlogin(pam_handle_t *pamh)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- curr_user_len = strlen(logname)+1;
|
|
||||||
- curr_user = calloc(curr_user_len, 1);
|
|
||||||
+ curr_user = strdup(logname);
|
|
||||||
if (curr_user == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- memcpy(curr_user, logname, curr_user_len);
|
|
||||||
-
|
|
||||||
status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
|
|
||||||
pam_modutil_cleanup);
|
|
||||||
if (status != PAM_SUCCESS) {
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.0/doc/Makefile.am.noflex Linux-PAM-1.5.0/doc/Makefile.am
|
|
||||||
--- Linux-PAM-1.5.0/doc/Makefile.am.noflex 2020-11-10 16:46:13.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.0/doc/Makefile.am 2020-11-11 11:39:00.980421433 +0100
|
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
|
|
||||||
#
|
|
||||||
|
|
||||||
-SUBDIRS = man specs sag adg mwg
|
|
||||||
+SUBDIRS = man sag adg mwg
|
|
||||||
|
|
||||||
CLEANFILES = *~
|
|
||||||
|
|
||||||
diff -up Linux-PAM-1.5.0/Makefile.am.noflex Linux-PAM-1.5.0/Makefile.am
|
|
||||||
--- Linux-PAM-1.5.0/Makefile.am.noflex 2020-11-11 11:39:00.980421433 +0100
|
|
||||||
+++ Linux-PAM-1.5.0/Makefile.am 2020-11-11 11:39:15.887625418 +0100
|
|
||||||
@@ -4,7 +4,7 @@
|
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = 1.9 gnu dist-xz no-dist-gzip check-news
|
|
||||||
|
|
||||||
-SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests
|
|
||||||
+SUBDIRS = libpam tests libpamc libpam_misc modules po doc examples xtests
|
|
||||||
|
|
||||||
if HAVE_DOC
|
|
||||||
SUBDIRS += doc
|
|
@ -1,25 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.0/configure.ac.redhat-modules Linux-PAM-1.5.0/configure.ac
|
|
||||||
--- Linux-PAM-1.5.0/configure.ac.redhat-modules 2020-11-11 11:21:21.947857371 +0100
|
|
||||||
+++ Linux-PAM-1.5.0/configure.ac 2020-11-11 11:22:58.638193747 +0100
|
|
||||||
@@ -639,6 +639,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
|
|
||||||
po/Makefile.in \
|
|
||||||
Make.xml.rules \
|
|
||||||
modules/Makefile \
|
|
||||||
+ modules/pam_chroot/Makefile modules/pam_console/Makefile \
|
|
||||||
+ modules/pam_postgresok/Makefile \
|
|
||||||
modules/pam_access/Makefile \
|
|
||||||
modules/pam_debug/Makefile modules/pam_deny/Makefile \
|
|
||||||
modules/pam_echo/Makefile modules/pam_env/Makefile \
|
|
||||||
diff -up Linux-PAM-1.5.0/modules/Makefile.am.redhat-modules Linux-PAM-1.5.0/modules/Makefile.am
|
|
||||||
--- Linux-PAM-1.5.0/modules/Makefile.am.redhat-modules 2020-11-10 16:46:13.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.0/modules/Makefile.am 2020-11-11 11:21:21.947857371 +0100
|
|
||||||
@@ -47,6 +47,9 @@ SUBDIRS := \
|
|
||||||
pam_debug \
|
|
||||||
pam_deny \
|
|
||||||
pam_echo \
|
|
||||||
+ pam_chroot \
|
|
||||||
+ pam_console \
|
|
||||||
+ pam_postgresok \
|
|
||||||
pam_env \
|
|
||||||
pam_exec \
|
|
||||||
pam_faildelay \
|
|
@ -1,168 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames Linux-PAM-1.5.1/modules/pam_access/pam_access.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.c 2024-01-22 15:56:09.977868880 +0100
|
|
||||||
@@ -662,7 +662,7 @@ from_match (pam_handle_t *pamh UNUSED, c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
- /* Assume network/netmask with a IP of a host. */
|
|
||||||
+ /* Assume network/netmask, IP address or hostname. */
|
|
||||||
if (network_netmask_match(pamh, tok, string, item))
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
@@ -684,7 +684,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 */
|
|
||||||
@@ -702,7 +702,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,
|
|
||||||
@@ -711,10 +712,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)
|
|
||||||
{
|
|
||||||
@@ -748,54 +751,108 @@ 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)
|
|
||||||
{
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "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];
|
|
||||||
|
|
||||||
- DIAG_PUSH_IGNORE_CAST_ALIGN;
|
|
||||||
- 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));
|
|
||||||
- DIAG_POP_IGNORE_CAST_ALIGN;
|
|
||||||
+ 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;
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
From c85513220c1bd3150e39c6277422d29cfa44acc7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Steve Grubb <sgrubb@redhat.com>
|
|
||||||
Date: Thu, 27 Jul 2023 13:14:42 -0400
|
|
||||||
Subject: [PATCH 1/2] pam_faillock: fix formatting of audit messages
|
|
||||||
|
|
||||||
pam_faillock uses audit_log_user_message to write to the audit system.
|
|
||||||
It does not take an op argument, so you have to add one yourself. Otherwise
|
|
||||||
the pam_faillock part of the message is lost because it's not in key=value
|
|
||||||
format.
|
|
||||||
|
|
||||||
Also, we can't use uid in that event because the kernel already adds that
|
|
||||||
field. What we normally do is use 'suid' (meaning sender uid) as the
|
|
||||||
field name.
|
|
||||||
---
|
|
||||||
modules/pam_faillock/pam_faillock.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
|
|
||||||
index ca1c7035..a89909ab 100644
|
|
||||||
--- a/modules/pam_faillock/pam_faillock.c
|
|
||||||
+++ b/modules/pam_faillock/pam_faillock.c
|
|
||||||
@@ -248,7 +248,7 @@ check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
|
|
||||||
|
|
||||||
(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);
|
|
||||||
}
|
|
||||||
@@ -364,7 +364,7 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
|
|
||||||
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);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
|
|
||||||
From 1648734a69c31e9ce834da70144ac9a453296807 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Steve Grubb <sgrubb@redhat.com>
|
|
||||||
Date: Fri, 4 Aug 2023 17:45:45 -0400
|
|
||||||
Subject: [PATCH 2/2] pam_selinux: fix formatting of audit messages
|
|
||||||
|
|
||||||
pam_selinux uses audit_log_user_message to write to the audit system.
|
|
||||||
It does not take an op argument, so you have to add one yourself. Otherwise
|
|
||||||
the pam_selinux part of the message is lost because it's not in key=value
|
|
||||||
format.
|
|
||||||
---
|
|
||||||
modules/pam_selinux/pam_selinux.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
|
|
||||||
index e52e0fc4..713b3f73 100644
|
|
||||||
--- a/modules/pam_selinux/pam_selinux.c
|
|
||||||
+++ b/modules/pam_selinux/pam_selinux.c
|
|
||||||
@@ -97,7 +97,7 @@ send_audit_message(const pam_handle_t *pamh, int success, const char *default_co
|
|
||||||
pam_syslog(pamh, LOG_ERR, "Error translating selected context '%s'.", 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) {
|
|
||||||
msg = NULL; /* asprintf leaves msg in undefined state on failure */
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From d54870f993e97fe75e2cd0470a3701d5af22877c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Changqing Li <changqing.li@windriver.com>
|
|
||||||
Date: Tue, 12 Jan 2021 14:45:34 +0800
|
|
||||||
Subject: [PATCH] faillock: create tallydir before creating tallyfile
|
|
||||||
|
|
||||||
The default tallydir is "/var/run/faillock", and this default
|
|
||||||
tallydir may not exist.
|
|
||||||
|
|
||||||
Function open may fail as tallydir does not exist when creating
|
|
||||||
the tallyfile. Therefore, faillock will not work well.
|
|
||||||
|
|
||||||
Fix this problem by creating tallydir before creating tallyfile
|
|
||||||
when the tallydir does not exist.
|
|
||||||
|
|
||||||
Signed-off-by: Changqing Li <changqing.li@windriver.com>
|
|
||||||
---
|
|
||||||
modules/pam_faillock/faillock.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_faillock/faillock.c b/modules/pam_faillock/faillock.c
|
|
||||||
index 4ea94cbe..091f253a 100644
|
|
||||||
--- a/modules/pam_faillock/faillock.c
|
|
||||||
+++ b/modules/pam_faillock/faillock.c
|
|
||||||
@@ -74,6 +74,9 @@ open_tally (const char *dir, const char *user, uid_t uid, int create)
|
|
||||||
|
|
||||||
if (create) {
|
|
||||||
flags |= O_CREAT;
|
|
||||||
+ if (access(dir, F_OK) != 0) {
|
|
||||||
+ mkdir(dir, 0755);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, flags, 0660);
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
@ -1,848 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml 2022-05-25 15:30:33.700518571 +0200
|
|
||||||
@@ -57,12 +57,29 @@
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
+ <option>--conf <replaceable>/path/to/config-file</replaceable></option>
|
|
||||||
+ </term>
|
|
||||||
+ <listitem>
|
|
||||||
+ <para>
|
|
||||||
+ The file where the configuration is located. The default is
|
|
||||||
+ <filename>/etc/security/faillock.conf</filename>.
|
|
||||||
+ </para>
|
|
||||||
+ </listitem>
|
|
||||||
+ </varlistentry>
|
|
||||||
+ <varlistentry>
|
|
||||||
+ <term>
|
|
||||||
<option>--dir <replaceable>/path/to/tally-directory</replaceable></option>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
- The directory where the user files with the failure records are kept. The
|
|
||||||
- default is <filename>/var/run/faillock</filename>.
|
|
||||||
+ The directory where the user files with the failure records are kept.
|
|
||||||
+ </para>
|
|
||||||
+ <para>
|
|
||||||
+ The priority to set this option is to use the value provided
|
|
||||||
+ from the command line. If this isn't provided, then the value
|
|
||||||
+ from the configuration file is used. Finally, if neither of
|
|
||||||
+ them has been provided, then
|
|
||||||
+ <filename>/var/run/faillock</filename> is used.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c 2022-05-25 15:30:33.700518571 +0200
|
|
||||||
@@ -0,0 +1,263 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (c) 2022 Tomas Mraz <tm@t8m.info>
|
|
||||||
+ * 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 <ctype.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <syslog.h>
|
|
||||||
+
|
|
||||||
+#include <security/pam_modules.h>
|
|
||||||
+
|
|
||||||
+#include "faillock_config.h"
|
|
||||||
+#include "faillock.h"
|
|
||||||
+
|
|
||||||
+#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf"
|
|
||||||
+
|
|
||||||
+static void PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3))
|
|
||||||
+config_log(const pam_handle_t *pamh, int priority, const char *fmt, ...)
|
|
||||||
+{
|
|
||||||
+ va_list args;
|
|
||||||
+
|
|
||||||
+ va_start(args, fmt);
|
|
||||||
+ if (pamh) {
|
|
||||||
+ pam_vsyslog(pamh, priority, fmt, args);
|
|
||||||
+ } else {
|
|
||||||
+ char *buf = NULL;
|
|
||||||
+
|
|
||||||
+ if (vasprintf(&buf, fmt, args) < 0) {
|
|
||||||
+ fprintf(stderr, "vasprintf: %m");
|
|
||||||
+ va_end(args);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ fprintf(stderr, "%s\n", buf);
|
|
||||||
+ free(buf);
|
|
||||||
+ }
|
|
||||||
+ va_end(args);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* parse a single configuration file */
|
|
||||||
+int
|
|
||||||
+read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile)
|
|
||||||
+{
|
|
||||||
+ char linebuf[FAILLOCK_CONF_MAX_LINELEN+1];
|
|
||||||
+ const char *fname = (cfgfile != NULL) ? cfgfile : FAILLOCK_DEFAULT_CONF;
|
|
||||||
+ FILE *f = fopen(fname, "r");
|
|
||||||
+
|
|
||||||
+#ifdef VENDOR_FAILLOCK_DEFAULT_CONF
|
|
||||||
+ if (f == NULL && errno == ENOENT && cfgfile == NULL) {
|
|
||||||
+ /*
|
|
||||||
+ * If the default configuration file in /etc does not exist,
|
|
||||||
+ * try the vendor configuration file as fallback.
|
|
||||||
+ */
|
|
||||||
+ f = fopen(VENDOR_FAILLOCK_DEFAULT_CONF, "r");
|
|
||||||
+ }
|
|
||||||
+#endif /* VENDOR_FAILLOCK_DEFAULT_CONF */
|
|
||||||
+
|
|
||||||
+ if (f == NULL) {
|
|
||||||
+ /* ignore non-existent default config file */
|
|
||||||
+ if (errno == ENOENT && cfgfile == NULL)
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+ return PAM_SERVICE_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (fgets(linebuf, sizeof(linebuf), f) != NULL) {
|
|
||||||
+ size_t len;
|
|
||||||
+ char *ptr;
|
|
||||||
+ char *name;
|
|
||||||
+ int eq;
|
|
||||||
+
|
|
||||||
+ len = strlen(linebuf);
|
|
||||||
+ /* len cannot be 0 unless there is a bug in fgets */
|
|
||||||
+ if (len && linebuf[len - 1] != '\n' && !feof(f)) {
|
|
||||||
+ (void) fclose(f);
|
|
||||||
+ return PAM_SERVICE_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((ptr=strchr(linebuf, '#')) != NULL) {
|
|
||||||
+ *ptr = '\0';
|
|
||||||
+ } else {
|
|
||||||
+ ptr = linebuf + len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* drop terminating whitespace including the \n */
|
|
||||||
+ while (ptr > linebuf) {
|
|
||||||
+ if (!isspace(*(ptr-1))) {
|
|
||||||
+ *ptr = '\0';
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ --ptr;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* skip initial whitespace */
|
|
||||||
+ for (ptr = linebuf; isspace(*ptr); ptr++);
|
|
||||||
+ if (*ptr == '\0')
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ /* grab the key name */
|
|
||||||
+ eq = 0;
|
|
||||||
+ name = ptr;
|
|
||||||
+ while (*ptr != '\0') {
|
|
||||||
+ if (isspace(*ptr) || *ptr == '=') {
|
|
||||||
+ eq = *ptr == '=';
|
|
||||||
+ *ptr = '\0';
|
|
||||||
+ ++ptr;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ ++ptr;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* grab the key value */
|
|
||||||
+ while (*ptr != '\0') {
|
|
||||||
+ if (*ptr != '=' || eq) {
|
|
||||||
+ if (!isspace(*ptr)) {
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ eq = 1;
|
|
||||||
+ }
|
|
||||||
+ ++ptr;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* set the key:value pair on opts */
|
|
||||||
+ set_conf_opt(pamh, opts, name, ptr);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ (void)fclose(f);
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
|
|
||||||
+ const char *value)
|
|
||||||
+{
|
|
||||||
+ if (strcmp(name, "dir") == 0) {
|
|
||||||
+ if (value[0] != '/') {
|
|
||||||
+ config_log(pamh, LOG_ERR,
|
|
||||||
+ "Tally directory is not absolute path (%s); keeping value",
|
|
||||||
+ value);
|
|
||||||
+ } else {
|
|
||||||
+ free(opts->dir);
|
|
||||||
+ opts->dir = strdup(value);
|
|
||||||
+ if (opts->dir == NULL) {
|
|
||||||
+ opts->fatal_error = 1;
|
|
||||||
+ config_log(pamh, LOG_CRIT, "Error allocating memory: %m");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "deny") == 0) {
|
|
||||||
+ if (sscanf(value, "%hu", &opts->deny) != 1) {
|
|
||||||
+ config_log(pamh, LOG_ERR,
|
|
||||||
+ "Bad number supplied for deny argument");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "fail_interval") == 0) {
|
|
||||||
+ unsigned int temp;
|
|
||||||
+ if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
+ temp > MAX_TIME_INTERVAL) {
|
|
||||||
+ config_log(pamh, LOG_ERR,
|
|
||||||
+ "Bad number supplied for fail_interval argument");
|
|
||||||
+ } else {
|
|
||||||
+ opts->fail_interval = temp;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "unlock_time") == 0) {
|
|
||||||
+ unsigned int temp;
|
|
||||||
+
|
|
||||||
+ if (strcmp(value, "never") == 0) {
|
|
||||||
+ opts->unlock_time = 0;
|
|
||||||
+ }
|
|
||||||
+ else if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
+ temp > MAX_TIME_INTERVAL) {
|
|
||||||
+ config_log(pamh, LOG_ERR,
|
|
||||||
+ "Bad number supplied for unlock_time argument");
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ opts->unlock_time = temp;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "root_unlock_time") == 0) {
|
|
||||||
+ unsigned int temp;
|
|
||||||
+
|
|
||||||
+ if (strcmp(value, "never") == 0) {
|
|
||||||
+ opts->root_unlock_time = 0;
|
|
||||||
+ }
|
|
||||||
+ else if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
+ temp > MAX_TIME_INTERVAL) {
|
|
||||||
+ config_log(pamh, LOG_ERR,
|
|
||||||
+ "Bad number supplied for root_unlock_time argument");
|
|
||||||
+ } else {
|
|
||||||
+ opts->root_unlock_time = temp;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "admin_group") == 0) {
|
|
||||||
+ free(opts->admin_group);
|
|
||||||
+ opts->admin_group = strdup(value);
|
|
||||||
+ if (opts->admin_group == NULL) {
|
|
||||||
+ opts->fatal_error = 1;
|
|
||||||
+ config_log(pamh, LOG_CRIT, "Error allocating memory: %m");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "even_deny_root") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_DENY_ROOT;
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "audit") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_AUDIT;
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "silent") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_SILENT;
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "no_log_info") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO;
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "local_users_only") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY;
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(name, "nodelay") == 0) {
|
|
||||||
+ opts->flags |= FAILLOCK_FLAG_NO_DELAY;
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ config_log(pamh, LOG_ERR, "Unknown option: %s", name);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+const char *get_tally_dir(const struct options *opts)
|
|
||||||
+{
|
|
||||||
+ return (opts->dir != NULL) ? opts->dir : FAILLOCK_DEFAULT_TALLYDIR;
|
|
||||||
+}
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h 2022-05-25 15:30:33.700518571 +0200
|
|
||||||
@@ -0,0 +1,89 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (c) 2022 Tomas Mraz <tm@t8m.info>
|
|
||||||
+ * 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.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * faillock_config.h - load configuration options from file
|
|
||||||
+ *
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef _FAILLOCK_CONFIG_H
|
|
||||||
+#define _FAILLOCK_CONFIG_H
|
|
||||||
+
|
|
||||||
+#include <limits.h>
|
|
||||||
+#include <stdint.h>
|
|
||||||
+#include <sys/types.h>
|
|
||||||
+
|
|
||||||
+#include <security/pam_ext.h>
|
|
||||||
+
|
|
||||||
+#define FAILLOCK_FLAG_DENY_ROOT 0x1
|
|
||||||
+#define FAILLOCK_FLAG_AUDIT 0x2
|
|
||||||
+#define FAILLOCK_FLAG_SILENT 0x4
|
|
||||||
+#define FAILLOCK_FLAG_NO_LOG_INFO 0x8
|
|
||||||
+#define FAILLOCK_FLAG_UNLOCKED 0x10
|
|
||||||
+#define FAILLOCK_FLAG_LOCAL_ONLY 0x20
|
|
||||||
+#define FAILLOCK_FLAG_NO_DELAY 0x40
|
|
||||||
+
|
|
||||||
+#define FAILLOCK_CONF_MAX_LINELEN 1023
|
|
||||||
+#define MAX_TIME_INTERVAL 604800 /* 7 days */
|
|
||||||
+
|
|
||||||
+struct options {
|
|
||||||
+ unsigned int action;
|
|
||||||
+ unsigned int flags;
|
|
||||||
+ unsigned short deny;
|
|
||||||
+ unsigned int fail_interval;
|
|
||||||
+ unsigned int unlock_time;
|
|
||||||
+ unsigned int root_unlock_time;
|
|
||||||
+ char *dir;
|
|
||||||
+ const char *user;
|
|
||||||
+ char *admin_group;
|
|
||||||
+ int failures;
|
|
||||||
+ uint64_t latest_time;
|
|
||||||
+ uid_t uid;
|
|
||||||
+ int is_admin;
|
|
||||||
+ uint64_t now;
|
|
||||||
+ int fatal_error;
|
|
||||||
+
|
|
||||||
+ unsigned int reset;
|
|
||||||
+ const char *progname;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+int read_config_file(pam_handle_t *pamh, struct options *opts,
|
|
||||||
+ const char *cfgfile);
|
|
||||||
+void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name,
|
|
||||||
+ const char *value);
|
|
||||||
+const char *get_tally_dir(const struct options *opts);
|
|
||||||
+
|
|
||||||
+#endif /* _FAILLOCK_CONFIG_H */
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/main.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/main.c 2022-05-25 15:37:05.801216176 +0200
|
|
||||||
@@ -51,33 +51,40 @@
|
|
||||||
#define AUDIT_NO_ID ((unsigned int) -1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#include "pam_inline.h"
|
|
||||||
#include "faillock.h"
|
|
||||||
-
|
|
||||||
-struct options {
|
|
||||||
- unsigned int reset;
|
|
||||||
- const char *dir;
|
|
||||||
- const char *user;
|
|
||||||
- const char *progname;
|
|
||||||
-};
|
|
||||||
+#include "faillock_config.h"
|
|
||||||
|
|
||||||
static int
|
|
||||||
args_parse(int argc, char **argv, struct options *opts)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
+ int rv;
|
|
||||||
+ const char *dir = NULL;
|
|
||||||
+ const char *conf = NULL;
|
|
||||||
+
|
|
||||||
memset(opts, 0, sizeof(*opts));
|
|
||||||
|
|
||||||
- opts->dir = FAILLOCK_DEFAULT_TALLYDIR;
|
|
||||||
opts->progname = argv[0];
|
|
||||||
|
|
||||||
for (i = 1; i < argc; ++i) {
|
|
||||||
-
|
|
||||||
- if (strcmp(argv[i], "--dir") == 0) {
|
|
||||||
+ if (strcmp(argv[i], "--conf") == 0) {
|
|
||||||
+ ++i;
|
|
||||||
+ if (i >= argc || strlen(argv[i]) == 0) {
|
|
||||||
+ fprintf(stderr, "%s: No configuration file supplied.\n",
|
|
||||||
+ argv[0]);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ conf = argv[i];
|
|
||||||
+ }
|
|
||||||
+ else if (strcmp(argv[i], "--dir") == 0) {
|
|
||||||
++i;
|
|
||||||
if (i >= argc || strlen(argv[i]) == 0) {
|
|
||||||
- fprintf(stderr, "%s: No directory supplied.\n", argv[0]);
|
|
||||||
+ fprintf(stderr, "%s: No records directory supplied.\n",
|
|
||||||
+ argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- opts->dir = argv[i];
|
|
||||||
+ dir = argv[i];
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[i], "--user") == 0) {
|
|
||||||
++i;
|
|
||||||
@@ -85,7 +92,7 @@ args_parse(int argc, char **argv, struct
|
|
||||||
fprintf(stderr, "%s: No user name supplied.\n", argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- opts->user = argv[i];
|
|
||||||
+ opts->user = argv[i];
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[i], "--reset") == 0) {
|
|
||||||
opts->reset = 1;
|
|
||||||
@@ -95,6 +102,21 @@ args_parse(int argc, char **argv, struct
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if ((rv = read_config_file(NULL, opts, conf)) != PAM_SUCCESS) {
|
|
||||||
+ fprintf(stderr, "Configuration file missing or broken");
|
|
||||||
+ return rv;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (dir != NULL) {
|
|
||||||
+ free(opts->dir);
|
|
||||||
+ opts->dir = strdup(dir);
|
|
||||||
+ if (opts->dir == NULL) {
|
|
||||||
+ fprintf(stderr, "Error allocating memory: %m");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -112,10 +134,11 @@ do_user(struct options *opts, const char
|
|
||||||
int rv;
|
|
||||||
struct tally_data tallies;
|
|
||||||
struct passwd *pwd;
|
|
||||||
+ const char *dir = get_tally_dir(opts);
|
|
||||||
|
|
||||||
pwd = getpwnam(user);
|
|
||||||
|
|
||||||
- fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0);
|
|
||||||
+ fd = open_tally(dir, user, pwd != NULL ? pwd->pw_uid : 0, 0);
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
@@ -191,8 +214,9 @@ do_allusers(struct options *opts)
|
|
||||||
{
|
|
||||||
struct dirent **userlist;
|
|
||||||
int rv, i;
|
|
||||||
+ const char *dir = get_tally_dir(opts);
|
|
||||||
|
|
||||||
- rv = scandir(opts->dir, &userlist, NULL, alphasort);
|
|
||||||
+ rv = scandir(dir, &userlist, NULL, alphasort);
|
|
||||||
if (rv < 0) {
|
|
||||||
fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname);
|
|
||||||
return 2;
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am 2022-05-25 15:30:33.700518571 +0200
|
|
||||||
@@ -20,7 +20,7 @@ TESTS = $(dist_check_SCRIPTS)
|
|
||||||
securelibdir = $(SECUREDIR)
|
|
||||||
secureconfdir = $(SCONFIGDIR)
|
|
||||||
|
|
||||||
-noinst_HEADERS = faillock.h
|
|
||||||
+noinst_HEADERS = faillock.h faillock_config.h
|
|
||||||
|
|
||||||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
|
||||||
$(WARN_CFLAGS)
|
|
||||||
@@ -41,8 +41,8 @@ dist_secureconf_DATA = faillock.conf
|
|
||||||
securelib_LTLIBRARIES = pam_faillock.la
|
|
||||||
sbin_PROGRAMS = faillock
|
|
||||||
|
|
||||||
-pam_faillock_la_SOURCES = pam_faillock.c faillock.c
|
|
||||||
-faillock_SOURCES = main.c faillock.c
|
|
||||||
+pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c
|
|
||||||
+faillock_SOURCES = main.c faillock.c faillock_config.c
|
|
||||||
|
|
||||||
if ENABLE_REGENERATE_MAN
|
|
||||||
dist_noinst_DATA = README
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c 2022-05-25 15:33:03.885551825 +0200
|
|
||||||
@@ -38,7 +38,6 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
-#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <time.h>
|
|
||||||
@@ -56,55 +55,12 @@
|
|
||||||
|
|
||||||
#include "pam_inline.h"
|
|
||||||
#include "faillock.h"
|
|
||||||
+#include "faillock_config.h"
|
|
||||||
|
|
||||||
#define FAILLOCK_ACTION_PREAUTH 0
|
|
||||||
#define FAILLOCK_ACTION_AUTHSUCC 1
|
|
||||||
#define FAILLOCK_ACTION_AUTHFAIL 2
|
|
||||||
|
|
||||||
-#define FAILLOCK_FLAG_DENY_ROOT 0x1
|
|
||||||
-#define FAILLOCK_FLAG_AUDIT 0x2
|
|
||||||
-#define FAILLOCK_FLAG_SILENT 0x4
|
|
||||||
-#define FAILLOCK_FLAG_NO_LOG_INFO 0x8
|
|
||||||
-#define FAILLOCK_FLAG_UNLOCKED 0x10
|
|
||||||
-#define FAILLOCK_FLAG_LOCAL_ONLY 0x20
|
|
||||||
-#define FAILLOCK_FLAG_NO_DELAY 0x40
|
|
||||||
-
|
|
||||||
-#define MAX_TIME_INTERVAL 604800 /* 7 days */
|
|
||||||
-#define FAILLOCK_CONF_MAX_LINELEN 1023
|
|
||||||
-
|
|
||||||
-static const char default_faillock_conf[] = FAILLOCK_DEFAULT_CONF;
|
|
||||||
-
|
|
||||||
-struct options {
|
|
||||||
- unsigned int action;
|
|
||||||
- unsigned int flags;
|
|
||||||
- unsigned short deny;
|
|
||||||
- unsigned int fail_interval;
|
|
||||||
- unsigned int unlock_time;
|
|
||||||
- unsigned int root_unlock_time;
|
|
||||||
- char *dir;
|
|
||||||
- const char *user;
|
|
||||||
- char *admin_group;
|
|
||||||
- int failures;
|
|
||||||
- uint64_t latest_time;
|
|
||||||
- uid_t uid;
|
|
||||||
- int is_admin;
|
|
||||||
- uint64_t now;
|
|
||||||
- int fatal_error;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static int read_config_file(
|
|
||||||
- pam_handle_t *pamh,
|
|
||||||
- struct options *opts,
|
|
||||||
- const char *cfgfile
|
|
||||||
-);
|
|
||||||
-
|
|
||||||
-static void set_conf_opt(
|
|
||||||
- pam_handle_t *pamh,
|
|
||||||
- struct options *opts,
|
|
||||||
- const char *name,
|
|
||||||
- const char *value
|
|
||||||
-);
|
|
||||||
-
|
|
||||||
static int
|
|
||||||
args_parse(pam_handle_t *pamh, int argc, const char **argv,
|
|
||||||
int flags, struct options *opts)
|
|
||||||
@@ -112,11 +68,10 @@ args_parse(pam_handle_t *pamh, int argc,
|
|
||||||
int i;
|
|
||||||
int config_arg_index = -1;
|
|
||||||
int rv;
|
|
||||||
- const char *conf = default_faillock_conf;
|
|
||||||
+ const char *conf = NULL;
|
|
||||||
|
|
||||||
memset(opts, 0, sizeof(*opts));
|
|
||||||
|
|
||||||
- opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR);
|
|
||||||
opts->deny = 3;
|
|
||||||
opts->fail_interval = 900;
|
|
||||||
opts->unlock_time = 600;
|
|
||||||
@@ -174,185 +129,11 @@ args_parse(pam_handle_t *pamh, int argc,
|
|
||||||
if (flags & PAM_SILENT)
|
|
||||||
opts->flags |= FAILLOCK_FLAG_SILENT;
|
|
||||||
|
|
||||||
- if (opts->dir == NULL) {
|
|
||||||
- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
|
|
||||||
- opts->fatal_error = 1;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
if (opts->fatal_error)
|
|
||||||
return PAM_BUF_ERR;
|
|
||||||
return PAM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* parse a single configuration file */
|
|
||||||
-static int
|
|
||||||
-read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile)
|
|
||||||
-{
|
|
||||||
- FILE *f;
|
|
||||||
- char linebuf[FAILLOCK_CONF_MAX_LINELEN+1];
|
|
||||||
-
|
|
||||||
- f = fopen(cfgfile, "r");
|
|
||||||
- if (f == NULL) {
|
|
||||||
- /* ignore non-existent default config file */
|
|
||||||
- if (errno == ENOENT && cfgfile == default_faillock_conf)
|
|
||||||
- return PAM_SUCCESS;
|
|
||||||
- return PAM_SERVICE_ERR;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- while (fgets(linebuf, sizeof(linebuf), f) != NULL) {
|
|
||||||
- size_t len;
|
|
||||||
- char *ptr;
|
|
||||||
- char *name;
|
|
||||||
- int eq;
|
|
||||||
-
|
|
||||||
- len = strlen(linebuf);
|
|
||||||
- /* len cannot be 0 unless there is a bug in fgets */
|
|
||||||
- if (len && linebuf[len - 1] != '\n' && !feof(f)) {
|
|
||||||
- (void) fclose(f);
|
|
||||||
- return PAM_SERVICE_ERR;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if ((ptr=strchr(linebuf, '#')) != NULL) {
|
|
||||||
- *ptr = '\0';
|
|
||||||
- } else {
|
|
||||||
- ptr = linebuf + len;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* drop terminating whitespace including the \n */
|
|
||||||
- while (ptr > linebuf) {
|
|
||||||
- if (!isspace(*(ptr-1))) {
|
|
||||||
- *ptr = '\0';
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- --ptr;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* skip initial whitespace */
|
|
||||||
- for (ptr = linebuf; isspace(*ptr); ptr++);
|
|
||||||
- if (*ptr == '\0')
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- /* grab the key name */
|
|
||||||
- eq = 0;
|
|
||||||
- name = ptr;
|
|
||||||
- while (*ptr != '\0') {
|
|
||||||
- if (isspace(*ptr) || *ptr == '=') {
|
|
||||||
- eq = *ptr == '=';
|
|
||||||
- *ptr = '\0';
|
|
||||||
- ++ptr;
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- ++ptr;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* grab the key value */
|
|
||||||
- while (*ptr != '\0') {
|
|
||||||
- if (*ptr != '=' || eq) {
|
|
||||||
- if (!isspace(*ptr)) {
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- } else {
|
|
||||||
- eq = 1;
|
|
||||||
- }
|
|
||||||
- ++ptr;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* set the key:value pair on opts */
|
|
||||||
- set_conf_opt(pamh, opts, name, ptr);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- (void)fclose(f);
|
|
||||||
- return PAM_SUCCESS;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static void
|
|
||||||
-set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value)
|
|
||||||
-{
|
|
||||||
- if (strcmp(name, "dir") == 0) {
|
|
||||||
- if (value[0] != '/') {
|
|
||||||
- pam_syslog(pamh, LOG_ERR,
|
|
||||||
- "Tally directory is not absolute path (%s); keeping default", value);
|
|
||||||
- } else {
|
|
||||||
- free(opts->dir);
|
|
||||||
- opts->dir = strdup(value);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "deny") == 0) {
|
|
||||||
- if (sscanf(value, "%hu", &opts->deny) != 1) {
|
|
||||||
- pam_syslog(pamh, LOG_ERR,
|
|
||||||
- "Bad number supplied for deny argument");
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "fail_interval") == 0) {
|
|
||||||
- unsigned int temp;
|
|
||||||
- if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
- temp > MAX_TIME_INTERVAL) {
|
|
||||||
- pam_syslog(pamh, LOG_ERR,
|
|
||||||
- "Bad number supplied for fail_interval argument");
|
|
||||||
- } else {
|
|
||||||
- opts->fail_interval = temp;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "unlock_time") == 0) {
|
|
||||||
- unsigned int temp;
|
|
||||||
-
|
|
||||||
- if (strcmp(value, "never") == 0) {
|
|
||||||
- opts->unlock_time = 0;
|
|
||||||
- }
|
|
||||||
- else if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
- temp > MAX_TIME_INTERVAL) {
|
|
||||||
- pam_syslog(pamh, LOG_ERR,
|
|
||||||
- "Bad number supplied for unlock_time argument");
|
|
||||||
- }
|
|
||||||
- else {
|
|
||||||
- opts->unlock_time = temp;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "root_unlock_time") == 0) {
|
|
||||||
- unsigned int temp;
|
|
||||||
-
|
|
||||||
- if (strcmp(value, "never") == 0) {
|
|
||||||
- opts->root_unlock_time = 0;
|
|
||||||
- }
|
|
||||||
- else if (sscanf(value, "%u", &temp) != 1 ||
|
|
||||||
- temp > MAX_TIME_INTERVAL) {
|
|
||||||
- pam_syslog(pamh, LOG_ERR,
|
|
||||||
- "Bad number supplied for root_unlock_time argument");
|
|
||||||
- } else {
|
|
||||||
- opts->root_unlock_time = temp;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "admin_group") == 0) {
|
|
||||||
- free(opts->admin_group);
|
|
||||||
- opts->admin_group = strdup(value);
|
|
||||||
- if (opts->admin_group == NULL) {
|
|
||||||
- opts->fatal_error = 1;
|
|
||||||
- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "even_deny_root") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_DENY_ROOT;
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "audit") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_AUDIT;
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "silent") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_SILENT;
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "no_log_info") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO;
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "local_users_only") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY;
|
|
||||||
- }
|
|
||||||
- else if (strcmp(name, "nodelay") == 0) {
|
|
||||||
- opts->flags |= FAILLOCK_FLAG_NO_DELAY;
|
|
||||||
- }
|
|
||||||
- else {
|
|
||||||
- pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name);
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int
|
|
||||||
check_local_user (pam_handle_t *pamh, const char *user)
|
|
||||||
{
|
|
||||||
@@ -406,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct o
|
|
||||||
unsigned int i;
|
|
||||||
uint64_t latest_time;
|
|
||||||
int failures;
|
|
||||||
+ const char *dir = get_tally_dir(opts);
|
|
||||||
|
|
||||||
opts->now = time(NULL);
|
|
||||||
|
|
||||||
- tfd = open_tally(opts->dir, opts->user, opts->uid, 0);
|
|
||||||
+ tfd = open_tally(dir, opts->user, opts->uid, 0);
|
|
||||||
|
|
||||||
*fd = tfd;
|
|
||||||
|
|
||||||
@@ -483,9 +265,10 @@ static void
|
|
||||||
reset_tally(pam_handle_t *pamh, struct options *opts, int *fd)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
+ const char *dir = get_tally_dir(opts);
|
|
||||||
|
|
||||||
if (*fd == -1) {
|
|
||||||
- *fd = open_tally(opts->dir, opts->user, opts->uid, 1);
|
|
||||||
+ *fd = open_tally(dir, opts->user, opts->uid, 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR);
|
|
||||||
@@ -504,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct o
|
|
||||||
unsigned int oldest;
|
|
||||||
uint64_t oldtime;
|
|
||||||
const void *source = NULL;
|
|
||||||
+ const char *dir = get_tally_dir(opts);
|
|
||||||
|
|
||||||
if (*fd == -1) {
|
|
||||||
- *fd = open_tally(opts->dir, opts->user, opts->uid, 1);
|
|
||||||
+ *fd = open_tally(dir, opts->user, opts->uid, 1);
|
|
||||||
}
|
|
||||||
if (*fd == -1) {
|
|
||||||
if (errno == EACCES) {
|
|
||||||
diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h
|
|
||||||
index b22a9dfb..0ea0ffba 100644
|
|
||||||
--- a/modules/pam_faillock/faillock.h
|
|
||||||
+++ b/modules/pam_faillock/faillock.h
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.h
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.h 2022-05-25 15:33:03.885551825 +0200
|
|
||||||
@@ -67,7 +67,6 @@ struct tally_data {
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock"
|
|
||||||
-#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf"
|
|
||||||
|
|
||||||
int open_tally(const char *dir, const char *user, uid_t uid, int create);
|
|
||||||
int read_tally(int fd, struct tally_data *tallies);
|
|
@ -1,55 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/configure.ac.libpam-close-range Linux-PAM-1.5.1/configure.ac
|
|
||||||
--- Linux-PAM-1.5.1/configure.ac.libpam-close-range 2023-11-10 10:35:00.142833269 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/configure.ac 2023-11-10 10:36:29.158987392 +0100
|
|
||||||
@@ -552,6 +552,7 @@ AC_CHECK_FUNCS(inet_ntop inet_pton innet
|
|
||||||
AC_CHECK_FUNCS(quotactl)
|
|
||||||
AC_CHECK_FUNCS(unshare)
|
|
||||||
AC_CHECK_FUNCS([ruserok_af ruserok], [break])
|
|
||||||
+AC_CHECK_FUNCS(close_range)
|
|
||||||
BACKUP_LIBS=$LIBS
|
|
||||||
LIBS="$LIBS -lutil"
|
|
||||||
AC_CHECK_FUNCS([logwtmp])
|
|
||||||
diff -up Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c.libpam-close-range Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c
|
|
||||||
--- Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c.libpam-close-range 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c 2023-11-10 10:35:00.142833269 +0100
|
|
||||||
@@ -11,6 +11,10 @@
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
|
|
||||||
+#ifndef CLOSE_RANGE_UNSHARE
|
|
||||||
+#define CLOSE_RANGE_UNSHARE (1U << 1)
|
|
||||||
+#endif /* CLOSE_RANGE_UNSHARE */
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Creates a pipe, closes its write end, redirects fd to its read end.
|
|
||||||
* Returns fd on success, -1 otherwise.
|
|
||||||
@@ -84,9 +88,8 @@ redirect_out(pam_handle_t *pamh, enum pa
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* Closes all descriptors after stderr. */
|
|
||||||
static void
|
|
||||||
-close_fds(void)
|
|
||||||
+close_fds_iteratively(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* An arbitrary upper limit for the maximum file descriptor number
|
|
||||||
@@ -111,6 +114,18 @@ close_fds(void)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Closes all descriptors after stderr. */
|
|
||||||
+static void
|
|
||||||
+close_fds(void)
|
|
||||||
+{
|
|
||||||
+#ifdef HAVE_CLOSE_RANGE
|
|
||||||
+ if (close_range(STDERR_FILENO+1, -1U, CLOSE_RANGE_UNSHARE) == 0)
|
|
||||||
+ return;
|
|
||||||
+#endif /* HAVE_CLOSE_RANGE */
|
|
||||||
+
|
|
||||||
+ close_fds_iteratively();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
pam_modutil_sanitize_helper_fds(pam_handle_t *pamh,
|
|
||||||
enum pam_modutil_redirect_fd stdin_mode,
|
|
@ -1,654 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/libpam/pam_handlers.c.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_handlers.c
|
|
||||||
--- Linux-PAM-1.5.1/libpam/pam_handlers.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/libpam/pam_handlers.c 2024-06-18 10:07:12.434785557 +0200
|
|
||||||
@@ -17,21 +17,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 */
|
|
||||||
|
|
||||||
@@ -59,12 +68,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;
|
|
||||||
@@ -74,7 +86,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) {
|
|
||||||
@@ -233,10 +245,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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -557,88 +570,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';
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * 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';
|
|
||||||
+
|
|
||||||
+ 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)
|
|
||||||
+{
|
|
||||||
+ int ret = 1;
|
|
||||||
+ char *p = *end;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * 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;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * 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;
|
|
||||||
+
|
|
||||||
+ *start = line;
|
|
||||||
+ *end = line + len;
|
|
||||||
+
|
|
||||||
+ ret = _pam_str_unescnl(*start, end) || strchr(*start, '#') != NULL;
|
|
||||||
+
|
|
||||||
+ *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, char *buffer, int buf_len)
|
|
||||||
+static int _pam_assemble_line(FILE *f, struct line_buffer *buffer)
|
|
||||||
{
|
|
||||||
- char *p = buffer;
|
|
||||||
- char *endp = buffer + buf_len;
|
|
||||||
- char *s, *os;
|
|
||||||
- int used = 0;
|
|
||||||
+ int ret = 0;
|
|
||||||
|
|
||||||
/* loop broken with a 'break' when a non-'\\n' ended line is read */
|
|
||||||
|
|
||||||
D(("called."));
|
|
||||||
+
|
|
||||||
+ _pam_buffer_shift(buffer);
|
|
||||||
+
|
|
||||||
for (;;) {
|
|
||||||
- if (p >= endp) {
|
|
||||||
- /* Overflow */
|
|
||||||
- D(("_pam_assemble_line: overflow"));
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
- if (fgets(p, endp - p, f) == NULL) {
|
|
||||||
- if (used) {
|
|
||||||
+ char *start, *end;
|
|
||||||
+ ssize_t n;
|
|
||||||
+ int eol;
|
|
||||||
+
|
|
||||||
+ if ((n = getline(&buffer->chunk, &buffer->chunk_size, f)) == -1) {
|
|
||||||
+ if (ret) {
|
|
||||||
/* Incomplete read */
|
|
||||||
- return -1;
|
|
||||||
+ ret = -1;
|
|
||||||
} else {
|
|
||||||
/* EOF */
|
|
||||||
- return 0;
|
|
||||||
+ ret = 0;
|
|
||||||
}
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* skip leading spaces --- line may be blank */
|
|
||||||
-
|
|
||||||
- s = p + strspn(p, " \n\t");
|
|
||||||
- if (*s && (*s != '#')) {
|
|
||||||
- os = s;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * we are only interested in characters before the first '#'
|
|
||||||
- * character
|
|
||||||
- */
|
|
||||||
-
|
|
||||||
- while (*s && *s != '#')
|
|
||||||
- ++s;
|
|
||||||
- if (*s == '#') {
|
|
||||||
- *s = '\0';
|
|
||||||
- used += strlen(os);
|
|
||||||
- break; /* the line has been read */
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- s = os;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * 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!
|
|
||||||
- */
|
|
||||||
-
|
|
||||||
- s += strlen(s);
|
|
||||||
- while (s > os && ((*--s == ' ') || (*s == '\t')
|
|
||||||
- || (*s == '\n')));
|
|
||||||
-
|
|
||||||
- /* 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 ... */
|
|
||||||
- } else {
|
|
||||||
- /* End of the line! */
|
|
||||||
- used += strlen(os);
|
|
||||||
- break; /* this is the complete line */
|
|
||||||
- }
|
|
||||||
+ 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 *
|
|
||||||
@@ -777,7 +945,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.5.1/libpam/pam_misc.c.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_misc.c
|
|
||||||
--- Linux-PAM-1.5.1/libpam/pam_misc.c.libpam-support-long-lines 2024-06-18 09:52:38.726482849 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/libpam/pam_misc.c 2024-06-18 10:02:13.132973447 +0200
|
|
||||||
@@ -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 +164,55 @@ char *_pam_memdup(const char *x, int len
|
|
||||||
/* Generate argv, argc from s */
|
|
||||||
/* caller must free(argv) */
|
|
||||||
|
|
||||||
-int _pam_mkargv(const 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.5.1/libpam/pam_private.h.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_private.h
|
|
||||||
--- Linux-PAM-1.5.1/libpam/pam_private.h.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/libpam/pam_private.h 2024-06-18 09:52:38.726482849 +0200
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
+#include <stddef.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include <security/pam_appl.h>
|
|
||||||
@@ -272,7 +273,7 @@ char *_pam_strdup(const char *s);
|
|
||||||
|
|
||||||
char *_pam_memdup(const char *s, int len);
|
|
||||||
|
|
||||||
-int _pam_mkargv(const 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.5.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c 2024-06-18 09:52:38.725482846 +0200
|
|
||||||
@@ -407,7 +407,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.5.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines 2024-06-18 09:52:38.725482846 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c 2024-06-18 09:54:17.102732759 +0200
|
|
||||||
@@ -96,7 +96,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.5.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c 2024-06-18 09:55:44.530954883 +0200
|
|
||||||
@@ -71,14 +71,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;
|
|
||||||
@@ -172,13 +172,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) {
|
|
||||||
@@ -304,9 +304,8 @@ static int drop_privileges(pam_handle_t
|
|
||||||
}
|
|
||||||
|
|
||||||
static int try_to_display(pam_handle_t *pamh, char **motd_path_split,
|
|
||||||
- unsigned int num_motd_paths,
|
|
||||||
- char **motd_dir_path_split,
|
|
||||||
- unsigned int num_motd_dir_paths, int report_missing)
|
|
||||||
+ size_t num_motd_paths, char **motd_dir_path_split,
|
|
||||||
+ size_t num_motd_dir_paths, int report_missing)
|
|
||||||
{
|
|
||||||
PAM_MODUTIL_DEF_PRIVS(privs);
|
|
||||||
|
|
||||||
@@ -316,7 +315,7 @@ static int try_to_display(pam_handle_t *
|
|
||||||
}
|
|
||||||
|
|
||||||
if (motd_path_split != NULL) {
|
|
||||||
- unsigned int i;
|
|
||||||
+ size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < num_motd_paths; i++) {
|
|
||||||
int fd = open(motd_path_split[i], O_RDONLY, 0);
|
|
||||||
@@ -354,11 +353,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;
|
|
||||||
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c 2024-06-18 09:52:38.726482849 +0200
|
|
||||||
@@ -52,6 +52,35 @@ main(void)
|
|
||||||
ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
|
||||||
pamh = NULL;
|
|
||||||
|
|
||||||
+ /* Perform a test dedicated to configuration file parsing. */
|
|
||||||
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
|
|
||||||
+ ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
|
|
||||||
+ "# ignore escaped newlines in comments \\\n"
|
|
||||||
+ "auth required \\\n"
|
|
||||||
+ " %s/.libs/%s.so\n"
|
|
||||||
+ "# allow unneeded whitespaces\n"
|
|
||||||
+ " account required %s/.libs/%s.so%c\\\n"
|
|
||||||
+ "line after NUL byte continues up to here\n"
|
|
||||||
+ "password required %s/.libs/%s.so # eol comment\n"
|
|
||||||
+ "session required %s/.libs/%s.so",
|
|
||||||
+ cwd, MODULE_NAME,
|
|
||||||
+ cwd, MODULE_NAME, '\0',
|
|
||||||
+ cwd, MODULE_NAME,
|
|
||||||
+ cwd, MODULE_NAME));
|
|
||||||
+ ASSERT_EQ(0, fclose(fp));
|
|
||||||
+
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS,
|
|
||||||
+ pam_start_confdir(service_file, user_name, &conv, ".", &pamh));
|
|
||||||
+ ASSERT_NE(NULL, pamh);
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_setcred(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_acct_mgmt(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_chauthtok(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_open_session(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_close_session(pamh, 0));
|
|
||||||
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
|
|
||||||
+ pamh = NULL;
|
|
||||||
+
|
|
||||||
ASSERT_EQ(0, unlink(service_file));
|
|
||||||
|
|
||||||
return 0;
|
|
@ -1,58 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
|||||||
From a35e092e24ee7632346a0e1b4a203c04d4cd2c62 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
Date: Mon, 24 Jan 2022 15:43:23 +0100
|
|
||||||
Subject: [PATCH] pam_keyinit: thread-safe implementation
|
|
||||||
|
|
||||||
* modules/pam_keyinit/pam_keyinit.c: Bypass setre*id() C library calls
|
|
||||||
with kernel calls and change global variables definitions to be
|
|
||||||
thread-safe.
|
|
||||||
|
|
||||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1997969
|
|
||||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
Co-Authored-By: Andreas Schneider <asn@samba.org>
|
|
||||||
---
|
|
||||||
modules/pam_keyinit/pam_keyinit.c | 60 ++++++++++++++++++++++---------
|
|
||||||
1 file changed, 44 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c
|
|
||||||
index 92e4953b..df9804b9 100644
|
|
||||||
--- a/modules/pam_keyinit/pam_keyinit.c
|
|
||||||
+++ b/modules/pam_keyinit/pam_keyinit.c
|
|
||||||
@@ -21,6 +21,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 */
|
|
||||||
@@ -31,12 +32,12 @@
|
|
||||||
#define KEYCTL_REVOKE 3 /* revoke a key */
|
|
||||||
#define KEYCTL_LINK 8 /* link a key into a keyring */
|
|
||||||
|
|
||||||
-static int my_session_keyring = 0;
|
|
||||||
-static int session_counter = 0;
|
|
||||||
-static int do_revoke = 0;
|
|
||||||
-static uid_t revoke_as_uid;
|
|
||||||
-static gid_t 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)));
|
|
||||||
@@ -64,6 +65,33 @@ static void error(pam_handle_t *pamh, const char *fmt, ...)
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
+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
|
|
||||||
*/
|
|
||||||
@@ -140,14 +168,14 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
return error_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
- 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 && setregid(-1, old_gid) < 0)
|
|
||||||
+ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
|
|
||||||
error(pamh, "Unable to change GID back to %d\n", old_gid);
|
|
||||||
return error_ret;
|
|
||||||
}
|
|
||||||
@@ -157,12 +185,12 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return to the original 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);
|
|
||||||
ret = error_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
- 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);
|
|
||||||
ret = error_ret;
|
|
||||||
}
|
|
||||||
@@ -215,14 +243,14 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
|
|
||||||
|
|
||||||
/* 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 error_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
- 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 error_ret;
|
|
||||||
}
|
|
||||||
@@ -230,12 +258,12 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
|
|
||||||
ret = init_keyrings(pamh, force, error_ret);
|
|
||||||
|
|
||||||
/* return to the original UID and GID (probably root) */
|
|
||||||
- if (uid != old_uid && setreuid(old_uid, -1) < 0) {
|
|
||||||
+ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) {
|
|
||||||
error(pamh, "Unable to change UID back to %d\n", old_uid);
|
|
||||||
ret = error_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (gid != old_gid && setregid(old_gid, -1) < 0) {
|
|
||||||
+ if (gid != old_gid && pam_setregid(old_gid, -1) < 0) {
|
|
||||||
error(pamh, "Unable to change GID back to %d\n", old_gid);
|
|
||||||
ret = error_ret;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.35.1
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
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,99 +0,0 @@
|
|||||||
From 3234488f2c52a021eec87df1990d256314c21bff Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Moellers <jmoellers@suse.de>
|
|
||||||
Date: Wed, 14 Apr 2021 16:39:28 +0200
|
|
||||||
Subject: [PATCH] pam_limits: "Unlimited" is not a valid value for
|
|
||||||
RLIMIT_NOFILE.
|
|
||||||
|
|
||||||
Replace it with a value obtained from /proc/sys/fs/nr_open
|
|
||||||
|
|
||||||
* modules/pam_limits/limits.conf.5.xml: Document the replacement.
|
|
||||||
* modules/pam_limits/pam_limits.c: Replace unlimited RLIMIT_NOFILE
|
|
||||||
value with a value obtained from /proc/sys/fs/nr_open
|
|
||||||
---
|
|
||||||
modules/pam_limits/limits.conf.5.xml | 2 ++
|
|
||||||
modules/pam_limits/pam_limits.c | 49 ++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 51 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml
|
|
||||||
index cd64ac90..c5bd6768 100644
|
|
||||||
--- a/modules/pam_limits/limits.conf.5.xml
|
|
||||||
+++ b/modules/pam_limits/limits.conf.5.xml
|
|
||||||
@@ -283,6 +283,8 @@
|
|
||||||
<emphasis>unlimited</emphasis> or <emphasis>infinity</emphasis> indicating no limit,
|
|
||||||
except for <emphasis remap='B'>priority</emphasis>, <emphasis remap='B'>nice</emphasis>,
|
|
||||||
and <emphasis remap='B'>nonewprivs</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 --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
|
|
||||||
index 10049973..7cc45d77 100644
|
|
||||||
--- a/modules/pam_limits/pam_limits.c
|
|
||||||
+++ b/modules/pam_limits/pam_limits.c
|
|
||||||
@@ -487,6 +487,41 @@ static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
|
|
||||||
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,
|
|
||||||
@@ -666,6 +701,20 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
|
|
||||||
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)
|
|
||||||
--
|
|
||||||
2.33.1
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
From 55f206447a1e4ee26e307e7a9c069236e823b1a5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jeff Squyres <jsquyres@cisco.com>
|
|
||||||
Date: Fri, 30 Apr 2021 15:16:38 -0700
|
|
||||||
Subject: [PATCH 1/2] pam_misc: make length of misc_conv() configurable
|
|
||||||
|
|
||||||
Add --with-misc-conv-bufsize=<number> option to configure to allow
|
|
||||||
a longer buffer size for libpam_misc's misc_conv() function (it still
|
|
||||||
defaults to 512 bytes).
|
|
||||||
|
|
||||||
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
|
|
||||||
---
|
|
||||||
configure.ac | 7 +++++++
|
|
||||||
libpam_misc/misc_conv.c | 2 +-
|
|
||||||
2 files changed, 8 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index 9c92d0de..b283db1b 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -648,6 +648,13 @@ case "$enable_unix" in
|
|
||||||
*) AC_MSG_ERROR([bad value $enable_unix for --enable-unix option]) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
+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=512]),
|
|
||||||
+ [],
|
|
||||||
+ [with_misc_conv_bufsize=512])
|
|
||||||
+AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
|
|
||||||
+
|
|
||||||
AM_CONDITIONAL([COND_BUILD_PAM_KEYINIT], [test "$have_key_syscalls" = 1])
|
|
||||||
AM_CONDITIONAL([COND_BUILD_PAM_LASTLOG], [test "$ac_cv_func_logwtmp" = yes])
|
|
||||||
AM_CONDITIONAL([COND_BUILD_PAM_NAMESPACE], [test "$ac_cv_func_unshare" = yes])
|
|
||||||
diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
|
|
||||||
index f28b1093..908ee890 100644
|
|
||||||
--- a/libpam_misc/misc_conv.c
|
|
||||||
+++ b/libpam_misc/misc_conv.c
|
|
||||||
@@ -18,7 +18,7 @@
|
|
||||||
#include <security/pam_appl.h>
|
|
||||||
#include <security/pam_misc.h>
|
|
||||||
|
|
||||||
-#define INPUTSIZE PAM_MAX_RESP_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
|
|
||||||
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
|
|
||||||
From 80bfda5962e5be3daa70e0fc8c75fc97d1c55121 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jeff Squyres <jsquyres@cisco.com>
|
|
||||||
Date: Fri, 30 Apr 2021 15:28:33 -0700
|
|
||||||
Subject: [PATCH 2/2] pam_misc: set default length of misc_conv() buffer to
|
|
||||||
4096
|
|
||||||
|
|
||||||
---
|
|
||||||
configure.ac | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index b283db1b..8e5d0ff7 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -650,9 +650,9 @@ esac
|
|
||||||
|
|
||||||
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=512]),
|
|
||||||
+ [Size of input buffer for libpam_misc's misc_conv() conversation function, default=4096]),
|
|
||||||
[],
|
|
||||||
- [with_misc_conv_bufsize=512])
|
|
||||||
+ [with_misc_conv_bufsize=4096])
|
|
||||||
AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
|
|
||||||
|
|
||||||
AM_CONDITIONAL([COND_BUILD_PAM_KEYINIT], [test "$have_key_syscalls" = 1])
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
@ -1,489 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
@@ -9,9 +9,10 @@ MAINTAINERCLEANFILES = $(MANS) README
|
|
||||||
EXTRA_DIST = $(XMLS)
|
|
||||||
|
|
||||||
if HAVE_DOC
|
|
||||||
-dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8
|
|
||||||
+dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5
|
|
||||||
endif
|
|
||||||
-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
|
|
||||||
dist_check_SCRIPTS = tst-pam_pwhistory
|
|
||||||
TESTS = $(dist_check_SCRIPTS)
|
|
||||||
|
|
||||||
@@ -26,12 +27,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\" @EXE_CFLAGS@
|
|
||||||
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml 2022-08-22 09:13:08.715628372 +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.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c 2022-08-22 09:11:34.949855242 +0200
|
|
||||||
@@ -63,14 +63,8 @@
|
|
||||||
|
|
||||||
#include "opasswd.h"
|
|
||||||
#include "pam_inline.h"
|
|
||||||
+#include "pwhistory_config.h"
|
|
||||||
|
|
||||||
-struct options_t {
|
|
||||||
- int debug;
|
|
||||||
- int enforce_for_root;
|
|
||||||
- int remember;
|
|
||||||
- int tries;
|
|
||||||
-};
|
|
||||||
-typedef struct options_t options_t;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -299,6 +293,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);
|
|
||||||
@@ -306,7 +302,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.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml 2022-08-22 09:08:48.916487811 +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.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
@@ -0,0 +1,115 @@
|
|
||||||
+/*
|
|
||||||
+ * 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 <security/pam_modutil.h>
|
|
||||||
+
|
|
||||||
+#include "pam_inline.h"
|
|
||||||
+#include "pwhistory_config.h"
|
|
||||||
+
|
|
||||||
+#define PWHISTORY_DEFAULT_CONF "/etc/security/pwhistory.conf"
|
|
||||||
+
|
|
||||||
+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 = pam_modutil_search_key (pamh, fname, "debug");
|
|
||||||
+ if (val != NULL) {
|
|
||||||
+ options->debug = 1;
|
|
||||||
+ free(val);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ val = pam_modutil_search_key (pamh, fname, "enforce_for_root");
|
|
||||||
+ if (val != NULL) {
|
|
||||||
+ options->enforce_for_root = 1;
|
|
||||||
+ free(val);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ val = pam_modutil_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 = pam_modutil_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 = pam_modutil_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.5.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h 2022-08-22 09:08:48.916487811 +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.5.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf 2022-08-22 09:08:48.916487811 +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
|
|
@ -1,114 +0,0 @@
|
|||||||
diff -up Linux-PAM-1.5.1/modules/pam_unix/passverify.c.fail1 Linux-PAM-1.5.1/modules/pam_unix/passverify.c
|
|
||||||
--- Linux-PAM-1.5.1/modules/pam_unix/passverify.c.fail1 2024-11-04 11:42:51.962791265 +0100
|
|
||||||
+++ Linux-PAM-1.5.1/modules/pam_unix/passverify.c 2024-11-04 11:45:18.246218579 +0100
|
|
||||||
@@ -239,17 +239,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;
|
|
||||||
|
|
||||||
|
|
||||||
From 8d0c575336ad301cd14e16ad2fdec6fe621764b8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergei Trofimovich <slyich@gmail.com>
|
|
||||||
Date: Thu, 28 Mar 2024 21:58:35 +0000
|
|
||||||
Subject: [PATCH] pam_unix: allow empty passwords with non-empty hashes
|
|
||||||
|
|
||||||
Before the change pam_unix has different behaviours for a user with
|
|
||||||
empty password for these two `/etc/shadow` entries:
|
|
||||||
|
|
||||||
nulloktest:$6$Yy4ty2jJ$bsVQWo8qlXC6UHq1/qTC3UR60ZJKmKApJ3Wj7DreAy8FxlVKtlDnplFQ7jMLVlDqordE7e4t49GvTb.aI59TP0:1::::::
|
|
||||||
nulloktest::1::::::
|
|
||||||
|
|
||||||
The entry with a hash was rejected and the entry without was accepted.
|
|
||||||
|
|
||||||
The rejection happened because 9e74e90147c "pam_unix: avoid determining
|
|
||||||
if user exists" introduced the following rejection check (slightly
|
|
||||||
simplified):
|
|
||||||
|
|
||||||
...
|
|
||||||
} else if (p[0] == '\0' && nullok) {
|
|
||||||
if (hash[0] != '\0') {
|
|
||||||
retval = PAM_AUTH_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
We should not reject the user with a hash assuming it's non-empty.
|
|
||||||
The change does that by pushing empty password check into
|
|
||||||
`verify_pwd_hash()`.
|
|
||||||
|
|
||||||
`NixOS` generates such hashed entries for empty passwords as if they
|
|
||||||
were non-empty using the following perl code:
|
|
||||||
|
|
||||||
sub hashPassword {
|
|
||||||
my ($password) = @_;
|
|
||||||
my $salt = "";
|
|
||||||
my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
|
|
||||||
$salt .= $chars[rand 64] for (1..8);
|
|
||||||
return crypt($password, '$6$' . $salt . '$');
|
|
||||||
}
|
|
||||||
|
|
||||||
Resolves: https://github.com/linux-pam/linux-pam/issues/758
|
|
||||||
Fixes: 9e74e90147c "pam_unix: avoid determining if user exists"
|
|
||||||
Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
|
|
||||||
---
|
|
||||||
modules/pam_unix/passverify.c | 14 ++++++--------
|
|
||||||
1 file changed, 6 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
|
|
||||||
index 30045333..1c83f1aa 100644
|
|
||||||
--- a/modules/pam_unix/passverify.c
|
|
||||||
+++ b/modules/pam_unix/passverify.c
|
|
||||||
@@ -76,9 +76,13 @@ PAMH_ARG_DECL(int verify_pwd_hash,
|
|
||||||
|
|
||||||
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 {
|
|
||||||
@@ -1109,12 +1113,6 @@ helper_verify_password(const char *name, const char *p, int nullok)
|
|
||||||
if (pwd == NULL || hash == NULL) {
|
|
||||||
helper_log_err(LOG_NOTICE, "check pass; user unknown");
|
|
||||||
retval = PAM_USER_UNKNOWN;
|
|
||||||
- } else if (p[0] == '\0' && nullok) {
|
|
||||||
- if (hash[0] == '\0') {
|
|
||||||
- retval = PAM_SUCCESS;
|
|
||||||
- } else {
|
|
||||||
- retval = PAM_AUTH_ERR;
|
|
||||||
- }
|
|
||||||
} else {
|
|
||||||
retval = verify_pwd_hash(p, hash, nullok);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.47.0
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
|||||||
From 370064ef6f99581b08d473a42bb3417d5dda3e4e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
Date: Thu, 17 Feb 2022 10:24:03 +0100
|
|
||||||
Subject: [PATCH] pam_usertype: only use SYS_UID_MAX for system users
|
|
||||||
|
|
||||||
* modules/pam_usertype/pam_usertype.c (pam_usertype_is_system): Stop
|
|
||||||
using SYS_UID_MIN to check if it is a system account, because all
|
|
||||||
accounts below the SYS_UID_MAX are system users.
|
|
||||||
* modules/pam_usertype/pam_usertype.8.xml: Remove reference to SYS_UID_MIN
|
|
||||||
as it is no longer used to calculate the system accounts.
|
|
||||||
* configure.ac: Remove PAM_USERTYPE_SYSUIDMIN.
|
|
||||||
|
|
||||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1949137
|
|
||||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
---
|
|
||||||
configure.ac | 5 -----
|
|
||||||
modules/pam_usertype/pam_usertype.8.xml | 2 +-
|
|
||||||
modules/pam_usertype/pam_usertype.c | 15 ++++++---------
|
|
||||||
3 files changed, 7 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index 639fc1ad..79113ad1 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -632,11 +632,6 @@ test -n "$opt_uidmin" ||
|
|
||||||
opt_uidmin=1000
|
|
||||||
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)
|
|
||||||
-test -n "$opt_sysuidmin" ||
|
|
||||||
- opt_sysuidmin=101
|
|
||||||
-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
|
|
||||||
-
|
|
||||||
AC_ARG_WITH([kernel-overflow-uid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
|
|
||||||
test -n "$opt_kerneloverflowuid" ||
|
|
||||||
opt_kerneloverflowuid=65534
|
|
||||||
diff --git a/modules/pam_usertype/pam_usertype.8.xml b/modules/pam_usertype/pam_usertype.8.xml
|
|
||||||
index 7651da6e..d9307ba3 100644
|
|
||||||
--- a/modules/pam_usertype/pam_usertype.8.xml
|
|
||||||
+++ b/modules/pam_usertype/pam_usertype.8.xml
|
|
||||||
@@ -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 --git a/modules/pam_usertype/pam_usertype.c b/modules/pam_usertype/pam_usertype.c
|
|
||||||
index d03b73b5..cfd9c8bb 100644
|
|
||||||
--- a/modules/pam_usertype/pam_usertype.c
|
|
||||||
+++ b/modules/pam_usertype/pam_usertype.c
|
|
||||||
@@ -194,7 +194,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) {
|
|
||||||
@@ -202,21 +201,19 @@ pam_usertype_is_system(pam_handle_t *pamh, uid_t 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;
|
|
||||||
+ if (uid <= sys_max && uid < uid_min) {
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
@@ -253,7 +250,7 @@ pam_usertype_evaluate(struct pam_usertype_opts *opts,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
--
|
|
||||||
2.36.1
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From ec0e724fe53188c5c762c34ca9db6681c0de01b8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
Date: Thu, 1 Jul 2021 12:14:29 +0200
|
|
||||||
Subject: [PATCH] pam_filter: Close file after controlling tty
|
|
||||||
|
|
||||||
Failing to check the descriptor value meant that there was a bug in the
|
|
||||||
attempt to close the controlling tty. Moreover, this would lead to a
|
|
||||||
file descriptor leak as pointed out by the static analyzer tool:
|
|
||||||
|
|
||||||
Error: RESOURCE_LEAK (CWE-772): [#def26]
|
|
||||||
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:356: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
|
|
||||||
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:356: var_assign: Assigning: "t" = handle returned from "open("/dev/tty", 2)".
|
|
||||||
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:357: off_by_one: Testing whether handle "t" is strictly greater than zero is suspicious. "t" leaks when it is zero.
|
|
||||||
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:357: remediation: Did you intend to include equality with zero?
|
|
||||||
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:367: leaked_handle: Handle variable "t" going out of scope leaks the handle.
|
|
||||||
365| pam_syslog(pamh, LOG_ERR,
|
|
||||||
366| "child cannot become new session: %m");
|
|
||||||
367|-> return PAM_ABORT;
|
|
||||||
368| }
|
|
||||||
369|
|
|
||||||
|
|
||||||
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
---
|
|
||||||
modules/pam_filter/pam_filter.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c
|
|
||||||
index 2f0af4fb..6e6def37 100644
|
|
||||||
--- a/modules/pam_filter/pam_filter.c
|
|
||||||
+++ b/modules/pam_filter/pam_filter.c
|
|
||||||
@@ -354,7 +354,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl,
|
|
||||||
int t = open("/dev/tty", O_RDWR|O_NOCTTY);
|
|
||||||
#else
|
|
||||||
int t = open("/dev/tty",O_RDWR);
|
|
||||||
- if (t > 0) {
|
|
||||||
+ if (t >= 0) {
|
|
||||||
(void) ioctl(t, TIOCNOTTY, NULL);
|
|
||||||
close(t);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -1,738 +0,0 @@
|
|||||||
From b3bb13e18a74e9ece825b7de1b81db97ebb107a0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Iker Pedrosa <ipedrosa@redhat.com>
|
|
||||||
Date: Thu, 25 Mar 2021 09:43:30 +0100
|
|
||||||
Subject: [PATCH] pam_timestamp: replace hmac implementation
|
|
||||||
|
|
||||||
sha1 is no longer recommended as a cryptographic algorithm for
|
|
||||||
authentication. Thus, the idea of this change is to replace the
|
|
||||||
implementation provided by hmacsha1 included in pam_timestamp module by
|
|
||||||
the one in the openssl library. This way, there's no need to maintain
|
|
||||||
the cryptographic algorithm implementation and it can be easily changed
|
|
||||||
with a single configuration change.
|
|
||||||
|
|
||||||
modules/pam_timestamp/hmac_openssl_wrapper.c: implement wrapper
|
|
||||||
functions around openssl's hmac implementation. Moreover, manage the key
|
|
||||||
generation and its read and write in a file. Include an option to
|
|
||||||
configure the cryptographic algorithm in login.defs file.
|
|
||||||
modules/pam_timestamp/hmac_openssl_wrapper.h: likewise.
|
|
||||||
modules/pam_timestamp/pam_timestamp.c: replace calls to functions
|
|
||||||
provided by hmacsha1 by functions provided by openssl's wrapper.
|
|
||||||
configure.ac: include openssl dependecy if it is enabled.
|
|
||||||
modules/pam_timestamp/Makefile.am: include new files and openssl library
|
|
||||||
to compilation.
|
|
||||||
ci/install-dependencies.sh: include openssl library to dependencies.
|
|
||||||
NEWS: add new item to next release.
|
|
||||||
Make.xml.rules.in: add stringparam profiling for hmac
|
|
||||||
doc/custom-man.xsl: change import docbook to one with profiling
|
|
||||||
modules/pam_timestamp/pam_timestamp.8.xml: add conditional paragraph to
|
|
||||||
indicate the value in /etc/login.defs that holds the value for the
|
|
||||||
encryption algorithm
|
|
||||||
|
|
||||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1947294
|
|
||||||
---
|
|
||||||
Make.xml.rules.in | 2 +-
|
|
||||||
NEWS | 5 +
|
|
||||||
configure.ac | 16 +
|
|
||||||
doc/custom-man.xsl | 2 +-
|
|
||||||
modules/pam_timestamp/Makefile.am | 15 +-
|
|
||||||
modules/pam_timestamp/hmac_openssl_wrapper.c | 381 +++++++++++++++++++
|
|
||||||
modules/pam_timestamp/hmac_openssl_wrapper.h | 57 +++
|
|
||||||
modules/pam_timestamp/pam_timestamp.8.xml | 5 +
|
|
||||||
modules/pam_timestamp/pam_timestamp.c | 53 ++-
|
|
||||||
10 files changed, 524 insertions(+), 13 deletions(-)
|
|
||||||
create mode 100644 modules/pam_timestamp/hmac_openssl_wrapper.c
|
|
||||||
create mode 100644 modules/pam_timestamp/hmac_openssl_wrapper.h
|
|
||||||
|
|
||||||
diff --git a/Make.xml.rules.in b/Make.xml.rules.in
|
|
||||||
index daa1b97b..27bb510e 100644
|
|
||||||
--- a/Make.xml.rules.in
|
|
||||||
+++ b/Make.xml.rules.in
|
|
||||||
@@ -21,6 +21,6 @@ README: README.xml
|
|
||||||
|
|
||||||
%.8: %.8.xml
|
|
||||||
$(XMLLINT) --nonet --xinclude --postvalid --noout $<
|
|
||||||
- $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude @STRINGPARAM_VENDORDIR@ --nonet $(top_srcdir)/doc/custom-man.xsl $<
|
|
||||||
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude @STRINGPARAM_VENDORDIR@ @STRINGPARAM_HMAC@ --nonet $(top_srcdir)/doc/custom-man.xsl $<
|
|
||||||
|
|
||||||
#CLEANFILES += $(man_MANS) README
|
|
||||||
diff --git a/NEWS b/NEWS
|
|
||||||
index 2d49ec39..f4d11303 100644
|
|
||||||
--- a/NEWS
|
|
||||||
+++ b/NEWS
|
|
||||||
@@ -1,5 +1,10 @@
|
|
||||||
Linux-PAM NEWS -- history of user-visible changes.
|
|
||||||
|
|
||||||
+Release next
|
|
||||||
+* pam_timestamp: change hmac algorithm to call openssl instead of the bundled
|
|
||||||
+ sha1 implementation if selected. Add option to select the hash
|
|
||||||
+ algorithm to use with HMAC.
|
|
||||||
+
|
|
||||||
Release 1.5.1
|
|
||||||
* pam_unix: fixed CVE-2020-27780 - authentication bypass when a user
|
|
||||||
doesn't exist and root password is blank
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index bd806473..9c92d0de 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -504,6 +504,22 @@ else
|
|
||||||
fi
|
|
||||||
AC_SUBST([STRINGPARAM_VENDORDIR])
|
|
||||||
|
|
||||||
+AC_ARG_ENABLE([openssl],
|
|
||||||
+ AS_HELP_STRING([--enable-openssl],[use OpenSSL crypto libraries]),
|
|
||||||
+ [OPENSSL_ENABLED=$enableval], OPENSSL_ENABLED=no)
|
|
||||||
+if test "$OPENSSL_ENABLED" = "yes" ; then
|
|
||||||
+ AC_CHECK_LIB([crypto], [EVP_MAC_CTX_new],
|
|
||||||
+ [CRYPTO_LIBS="-lcrypto"
|
|
||||||
+ use_openssl=yes
|
|
||||||
+ AC_DEFINE([WITH_OPENSSL], 1, [OpenSSL provides crypto algorithm for hmac])
|
|
||||||
+ STRINGPARAM_HMAC="--stringparam profile.condition 'openssl_hmac'"],
|
|
||||||
+ [CRYPTO_LIBS=""
|
|
||||||
+ STRINGPARAM_HMAC="--stringparam profile.condition 'no_openssl_hmac'"])
|
|
||||||
+fi
|
|
||||||
+AC_SUBST([CRYPTO_LIBS])
|
|
||||||
+AC_SUBST([STRINGPARAM_HMAC])
|
|
||||||
+AM_CONDITIONAL([COND_USE_OPENSSL], [test "x$use_openssl" = "xyes"])
|
|
||||||
+
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_HEADER_DIRENT
|
|
||||||
AC_HEADER_STDC
|
|
||||||
diff --git a/doc/custom-man.xsl b/doc/custom-man.xsl
|
|
||||||
index 4c35e839..a3408e6c 100644
|
|
||||||
--- a/doc/custom-man.xsl
|
|
||||||
+++ b/doc/custom-man.xsl
|
|
||||||
@@ -1,6 +1,6 @@
|
|
||||||
<?xml version='1.0'?>
|
|
||||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ss="http://docbook.sf.net/xmlns/string.subst/1.0" version="1.0">
|
|
||||||
- <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"/>
|
|
||||||
+ <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/profile-docbook.xsl"/>
|
|
||||||
<xsl:param name="vendordir"/>
|
|
||||||
|
|
||||||
<xsl:param name="man.string.subst.map.local.pre">
|
|
||||||
diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am
|
|
||||||
index 1faa324a..d290b85f 100644
|
|
||||||
--- a/modules/pam_timestamp/Makefile.am
|
|
||||||
+++ b/modules/pam_timestamp/Makefile.am
|
|
||||||
@@ -18,12 +18,12 @@ TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
|
|
||||||
securelibdir = $(SECUREDIR)
|
|
||||||
secureconfdir = $(SCONFIGDIR)
|
|
||||||
|
|
||||||
-noinst_HEADERS = hmacsha1.h sha1.h
|
|
||||||
+noinst_HEADERS = hmacsha1.h sha1.h hmac_openssl_wrapper.h
|
|
||||||
|
|
||||||
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
|
|
||||||
$(WARN_CFLAGS)
|
|
||||||
|
|
||||||
-pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS)
|
|
||||||
+pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS) $(CRYPTO_LIBS)
|
|
||||||
pam_timestamp_la_LIBADD = $(top_builddir)/libpam/libpam.la
|
|
||||||
if HAVE_VERSIONING
|
|
||||||
pam_timestamp_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
|
|
||||||
@@ -32,7 +32,12 @@ endif
|
|
||||||
securelib_LTLIBRARIES = pam_timestamp.la
|
|
||||||
sbin_PROGRAMS = pam_timestamp_check
|
|
||||||
|
|
||||||
-pam_timestamp_la_SOURCES = pam_timestamp.c hmacsha1.c sha1.c
|
|
||||||
+pam_timestamp_la_SOURCES = pam_timestamp.c
|
|
||||||
+if COND_USE_OPENSSL
|
|
||||||
+pam_timestamp_la_SOURCES += hmac_openssl_wrapper.c
|
|
||||||
+else
|
|
||||||
+pam_timestamp_la_SOURCES += hmacsha1.c sha1.c
|
|
||||||
+endif
|
|
||||||
pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
|
|
||||||
|
|
||||||
pam_timestamp_check_SOURCES = pam_timestamp_check.c
|
|
||||||
@@ -40,7 +45,11 @@ pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@
|
|
||||||
pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
|
|
||||||
pam_timestamp_check_LDFLAGS = @EXE_LDFLAGS@
|
|
||||||
|
|
||||||
+if COND_USE_OPENSSL
|
|
||||||
+hmacfile_SOURCES = hmac_openssl_wrapper.c
|
|
||||||
+else
|
|
||||||
hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c
|
|
||||||
+endif
|
|
||||||
hmacfile_LDADD = $(top_builddir)/libpam/libpam.la
|
|
||||||
|
|
||||||
check_PROGRAMS = hmacfile
|
|
||||||
diff --git a/modules/pam_timestamp/hmac_openssl_wrapper.c b/modules/pam_timestamp/hmac_openssl_wrapper.c
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..926c2fb9
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/modules/pam_timestamp/hmac_openssl_wrapper.c
|
|
||||||
@@ -0,0 +1,381 @@
|
|
||||||
+/* Wrapper for hmac openssl implementation.
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2021 Red Hat, Inc.
|
|
||||||
+ * Written by 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"
|
|
||||||
+
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+
|
|
||||||
+#include <sys/stat.h>
|
|
||||||
+#include <fcntl.h>
|
|
||||||
+#include <syslog.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <openssl/evp.h>
|
|
||||||
+#include <openssl/params.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
+
|
|
||||||
+#include <security/pam_ext.h>
|
|
||||||
+#include <security/pam_modutil.h>
|
|
||||||
+
|
|
||||||
+#include "hmac_openssl_wrapper.h"
|
|
||||||
+
|
|
||||||
+#define LOGIN_DEFS "/etc/login.defs"
|
|
||||||
+#define CRYPTO_KEY "HMAC_CRYPTO_ALGO"
|
|
||||||
+#define DEFAULT_ALGORITHM "SHA512"
|
|
||||||
+#define MAX_HMAC_LENGTH 512
|
|
||||||
+#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
|
|
||||||
+
|
|
||||||
+static char *
|
|
||||||
+get_crypto_algorithm(pam_handle_t *pamh, int debug){
|
|
||||||
+ char *config_value = NULL;
|
|
||||||
+
|
|
||||||
+ config_value = pam_modutil_search_key(pamh, LOGIN_DEFS, CRYPTO_KEY);
|
|
||||||
+
|
|
||||||
+ if (config_value == NULL) {
|
|
||||||
+ config_value = strdup(DEFAULT_ALGORITHM);
|
|
||||||
+ if (debug) {
|
|
||||||
+ pam_syslog(pamh, LOG_DEBUG,
|
|
||||||
+ "Key [%s] not found, falling back to default algorithm [%s]\n",
|
|
||||||
+ CRYPTO_KEY, DEFAULT_ALGORITHM);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return config_value;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+generate_key(pam_handle_t *pamh, char **key, size_t key_size)
|
|
||||||
+{
|
|
||||||
+ int fd = 0;
|
|
||||||
+ size_t bytes_read = 0;
|
|
||||||
+ char * tmp = NULL;
|
|
||||||
+
|
|
||||||
+ fd = open("/dev/urandom", O_RDONLY);
|
|
||||||
+ if (fd == -1) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Cannot open /dev/urandom: %m");
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ tmp = malloc(key_size);
|
|
||||||
+ if (!tmp) {
|
|
||||||
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
|
|
||||||
+ close(fd);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bytes_read = pam_modutil_read(fd, tmp, key_size);
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (bytes_read < key_size) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Short read on random device");
|
|
||||||
+ free(tmp);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *key = tmp;
|
|
||||||
+
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+read_file(pam_handle_t *pamh, int fd, char **text, size_t *text_length)
|
|
||||||
+{
|
|
||||||
+ struct stat st;
|
|
||||||
+ size_t bytes_read = 0;
|
|
||||||
+ char *tmp = NULL;
|
|
||||||
+
|
|
||||||
+ if (fstat(fd, &st) == -1) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to stat file: %m");
|
|
||||||
+ close(fd);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (st.st_size == 0) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Key file size cannot be 0");
|
|
||||||
+ close(fd);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ tmp = malloc(st.st_size);
|
|
||||||
+ if (!tmp) {
|
|
||||||
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
|
|
||||||
+ close(fd);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bytes_read = pam_modutil_read(fd, tmp, st.st_size);
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (bytes_read < (size_t)st.st_size) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Short read on key file");
|
|
||||||
+ memset(tmp, 0, st.st_size);
|
|
||||||
+ free(tmp);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *text = tmp;
|
|
||||||
+ *text_length = st.st_size;
|
|
||||||
+
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+write_file(pam_handle_t *pamh, const char *file_name, char *text,
|
|
||||||
+ size_t text_length, uid_t owner, gid_t group)
|
|
||||||
+{
|
|
||||||
+ int fd = 0;
|
|
||||||
+ size_t bytes_written = 0;
|
|
||||||
+
|
|
||||||
+ fd = open(file_name,
|
|
||||||
+ O_WRONLY | O_CREAT | O_TRUNC,
|
|
||||||
+ S_IRUSR | S_IWUSR);
|
|
||||||
+ if (fd == -1) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to open [%s]: %m", file_name);
|
|
||||||
+ memset(text, 0, text_length);
|
|
||||||
+ free(text);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (fchown(fd, owner, group) == -1) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to change ownership [%s]: %m", file_name);
|
|
||||||
+ memset(text, 0, text_length);
|
|
||||||
+ free(text);
|
|
||||||
+ close(fd);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bytes_written = pam_modutil_write(fd, text, text_length);
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (bytes_written < text_length) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Short write on %s", file_name);
|
|
||||||
+ free(text);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+key_management(pam_handle_t *pamh, const char *file_name, char **text,
|
|
||||||
+ size_t text_length, uid_t owner, gid_t group)
|
|
||||||
+{
|
|
||||||
+ int fd = 0;
|
|
||||||
+
|
|
||||||
+ fd = open(file_name, O_RDONLY | O_NOFOLLOW);
|
|
||||||
+ if (fd == -1) {
|
|
||||||
+ if (errno == ENOENT) {
|
|
||||||
+ if (generate_key(pamh, text, text_length)) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to generate key");
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (write_file(pamh, file_name, *text, text_length, owner, group)) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to write key");
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to open %s: %m", file_name);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (read_file(pamh, fd, text, &text_length)) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Error reading key file %s\n", file_name);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+hmac_management(pam_handle_t *pamh, int debug, void **out, size_t *out_length,
|
|
||||||
+ char *key, size_t key_length,
|
|
||||||
+ const void *text, size_t text_length)
|
|
||||||
+{
|
|
||||||
+ int ret = PAM_AUTH_ERR;
|
|
||||||
+ EVP_MAC *evp_mac = NULL;
|
|
||||||
+ EVP_MAC_CTX *ctx = NULL;
|
|
||||||
+ unsigned char *hmac_message = NULL;
|
|
||||||
+ size_t hmac_length;
|
|
||||||
+ char *algo = NULL;
|
|
||||||
+ OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
||||||
+
|
|
||||||
+ algo = get_crypto_algorithm(pamh, debug);
|
|
||||||
+
|
|
||||||
+ subalg_param[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
|
|
||||||
+ algo,
|
|
||||||
+ 0);
|
|
||||||
+
|
|
||||||
+ evp_mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
|
|
||||||
+ if (evp_mac == NULL) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac implementation");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ctx = EVP_MAC_CTX_new(evp_mac);
|
|
||||||
+ if (ctx == NULL) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac context");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = EVP_MAC_init(ctx, (const unsigned char *)key, key_length, subalg_param);
|
|
||||||
+ if (ret == 0) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to initialize hmac context");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = EVP_MAC_update(ctx, (const unsigned char *)text, text_length);
|
|
||||||
+ if (ret == 0) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to update hmac context");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ hmac_message = (unsigned char*)malloc(sizeof(unsigned char) * MAX_HMAC_LENGTH);
|
|
||||||
+ if (!hmac_message) {
|
|
||||||
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = EVP_MAC_final(ctx, hmac_message, &hmac_length, MAX_HMAC_LENGTH);
|
|
||||||
+ if (ret == 0) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to calculate hmac message");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *out_length = hmac_length;
|
|
||||||
+ *out = malloc(*out_length);
|
|
||||||
+ if (*out == NULL) {
|
|
||||||
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memcpy(*out, hmac_message, *out_length);
|
|
||||||
+ ret = PAM_SUCCESS;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ if (hmac_message != NULL) {
|
|
||||||
+ free(hmac_message);
|
|
||||||
+ }
|
|
||||||
+ if (key != NULL) {
|
|
||||||
+ memset(key, 0, key_length);
|
|
||||||
+ free(key);
|
|
||||||
+ }
|
|
||||||
+ if (ctx != NULL) {
|
|
||||||
+ EVP_MAC_CTX_free(ctx);
|
|
||||||
+ }
|
|
||||||
+ if (evp_mac != NULL) {
|
|
||||||
+ EVP_MAC_free(evp_mac);
|
|
||||||
+ }
|
|
||||||
+ free(algo);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+hmac_size(pam_handle_t *pamh, int debug, size_t *hmac_length)
|
|
||||||
+{
|
|
||||||
+ int ret = PAM_AUTH_ERR;
|
|
||||||
+ EVP_MAC *evp_mac = NULL;
|
|
||||||
+ EVP_MAC_CTX *ctx = NULL;
|
|
||||||
+ const unsigned char key[] = "ThisIsJustAKey";
|
|
||||||
+ size_t key_length = MAX_KEY_LENGTH;
|
|
||||||
+ char *algo = NULL;
|
|
||||||
+ OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
||||||
+
|
|
||||||
+ algo = get_crypto_algorithm(pamh, debug);
|
|
||||||
+
|
|
||||||
+ subalg_param[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
|
|
||||||
+ algo,
|
|
||||||
+ 0);
|
|
||||||
+
|
|
||||||
+ evp_mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
|
|
||||||
+ if (evp_mac == NULL) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac implementation");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ctx = EVP_MAC_CTX_new(evp_mac);
|
|
||||||
+ if (ctx == NULL) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac context");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = EVP_MAC_init(ctx, key, key_length, subalg_param);
|
|
||||||
+ if (ret == 0) {
|
|
||||||
+ pam_syslog(pamh, LOG_ERR, "Unable to initialize hmac context");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *hmac_length = EVP_MAC_CTX_get_mac_size(ctx);
|
|
||||||
+ ret = PAM_SUCCESS;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ if (ctx != NULL) {
|
|
||||||
+ EVP_MAC_CTX_free(ctx);
|
|
||||||
+ }
|
|
||||||
+ if (evp_mac != NULL) {
|
|
||||||
+ EVP_MAC_free(evp_mac);
|
|
||||||
+ }
|
|
||||||
+ free(algo);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+hmac_generate(pam_handle_t *pamh, int debug, void **mac, size_t *mac_length,
|
|
||||||
+ const char *key_file, uid_t owner, gid_t group,
|
|
||||||
+ const void *text, size_t text_length)
|
|
||||||
+{
|
|
||||||
+ char *key = NULL;
|
|
||||||
+ size_t key_length = MAX_KEY_LENGTH;
|
|
||||||
+
|
|
||||||
+ if (key_management(pamh, key_file, &key, key_length, owner, group)) {
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (hmac_management(pamh, debug, mac, mac_length, key, key_length,
|
|
||||||
+ text, text_length)) {
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return PAM_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
diff --git a/modules/pam_timestamp/hmac_openssl_wrapper.h b/modules/pam_timestamp/hmac_openssl_wrapper.h
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..cc27c811
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/modules/pam_timestamp/hmac_openssl_wrapper.h
|
|
||||||
@@ -0,0 +1,57 @@
|
|
||||||
+/* Wrapper for hmac openssl implementation.
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2021 Red Hat, Inc.
|
|
||||||
+ * Written by 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 PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H
|
|
||||||
+#define PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H
|
|
||||||
+
|
|
||||||
+#include "config.h"
|
|
||||||
+
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+
|
|
||||||
+#include <openssl/hmac.h>
|
|
||||||
+#include <security/pam_modules.h>
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+hmac_size(pam_handle_t *pamh, int debug, size_t *hmac_length);
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+hmac_generate(pam_handle_t *pamh, int debug, void **mac, size_t *mac_length,
|
|
||||||
+ const char *key_file, uid_t owner, gid_t group,
|
|
||||||
+ const void *text, size_t text_length);
|
|
||||||
+
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
+#endif /* PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H */
|
|
||||||
diff --git a/modules/pam_timestamp/pam_timestamp.8.xml b/modules/pam_timestamp/pam_timestamp.8.xml
|
|
||||||
index e19a0bcf..83e5aea8 100644
|
|
||||||
--- a/modules/pam_timestamp/pam_timestamp.8.xml
|
|
||||||
+++ b/modules/pam_timestamp/pam_timestamp.8.xml
|
|
||||||
@@ -50,6 +50,11 @@ for the user. When an application attempts to authenticate the user, a
|
|
||||||
<emphasis>pam_timestamp</emphasis> will treat a sufficiently recent timestamp
|
|
||||||
file as grounds for succeeding.
|
|
||||||
</para>
|
|
||||||
+ <para condition="openssl_hmac">
|
|
||||||
+ The default encryption hash is taken from the
|
|
||||||
+ <emphasis remap='B'>HMAC_CRYPTO_ALGO</emphasis> variable from
|
|
||||||
+ <emphasis>/etc/login.defs</emphasis>.
|
|
||||||
+ </para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="pam_timestamp-options">
|
|
||||||
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c
|
|
||||||
index 30be883c..01dd1385 100644
|
|
||||||
--- a/modules/pam_timestamp/pam_timestamp.c
|
|
||||||
+++ b/modules/pam_timestamp/pam_timestamp.c
|
|
||||||
@@ -56,7 +56,11 @@
|
|
||||||
#include <utmp.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <paths.h>
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+#include "hmac_openssl_wrapper.h"
|
|
||||||
+#else
|
|
||||||
#include "hmacsha1.h"
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
|
|
||||||
#include <security/pam_modules.h>
|
|
||||||
#include <security/_pam_macros.h>
|
|
||||||
@@ -79,6 +83,9 @@
|
|
||||||
#define BUFLEN PATH_MAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#define ROOT_USER 0
|
|
||||||
+#define ROOT_GROUP 0
|
|
||||||
+
|
|
||||||
/* Return PAM_SUCCESS if the given directory looks "safe". */
|
|
||||||
static int
|
|
||||||
check_dir_perms(pam_handle_t *pamh, const char *tdir)
|
|
||||||
@@ -449,6 +456,13 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
|
||||||
return PAM_AUTH_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+ if (hmac_size(pamh, debug, &maclen)) {
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
+ maclen = hmac_sha1_size();
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
/* Check that the file is the expected size. */
|
|
||||||
if (st.st_size == 0) {
|
|
||||||
/* Invalid, but may have been created by sudo. */
|
|
||||||
@@ -456,7 +470,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
|
||||||
return PAM_AUTH_ERR;
|
|
||||||
}
|
|
||||||
if (st.st_size !=
|
|
||||||
- (off_t)(strlen(path) + 1 + sizeof(then) + hmac_sha1_size())) {
|
|
||||||
+ (off_t)(strlen(path) + 1 + sizeof(then) + maclen)) {
|
|
||||||
pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' "
|
|
||||||
"appears to be corrupted", path);
|
|
||||||
close(fd);
|
|
||||||
@@ -487,8 +501,17 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
|
||||||
message_end = message + strlen(path) + 1 + sizeof(then);
|
|
||||||
|
|
||||||
/* Regenerate the MAC. */
|
|
||||||
- hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, 0, 0,
|
|
||||||
- message, message_end - message);
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+ if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY,
|
|
||||||
+ ROOT_USER, ROOT_GROUP, message, message_end - message)) {
|
|
||||||
+ close(fd);
|
|
||||||
+ free(message);
|
|
||||||
+ return PAM_AUTH_ERR;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
+ hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY,
|
|
||||||
+ ROOT_USER, ROOT_GROUP, message, message_end - message);
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
if ((mac == NULL) ||
|
|
||||||
(memcmp(path, message, strlen(path)) != 0) ||
|
|
||||||
(memcmp(mac, message_end, maclen) != 0)) {
|
|
||||||
@@ -605,8 +628,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char *
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+ if (hmac_size(pamh, debug, &maclen)) {
|
|
||||||
+ return PAM_SESSION_ERR;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
+ maclen = hmac_sha1_size();
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
+
|
|
||||||
/* Generate the message. */
|
|
||||||
- text = malloc(strlen(path) + 1 + sizeof(now) + hmac_sha1_size());
|
|
||||||
+ text = malloc(strlen(path) + 1 + sizeof(now) + maclen);
|
|
||||||
if (text == NULL) {
|
|
||||||
pam_syslog(pamh, LOG_CRIT, "unable to allocate memory: %m");
|
|
||||||
return PAM_SESSION_ERR;
|
|
||||||
@@ -621,15 +652,21 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char *
|
|
||||||
p += sizeof(now);
|
|
||||||
|
|
||||||
/* Generate the MAC and append it to the plaintext. */
|
|
||||||
- hmac_sha1_generate_file(pamh, &mac, &maclen,
|
|
||||||
- TIMESTAMPKEY,
|
|
||||||
- 0, 0,
|
|
||||||
- text, p - text);
|
|
||||||
+#ifdef WITH_OPENSSL
|
|
||||||
+ if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY,
|
|
||||||
+ ROOT_USER, ROOT_GROUP, text, p - text)) {
|
|
||||||
+ free(text);
|
|
||||||
+ return PAM_SESSION_ERR;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
+ hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY,
|
|
||||||
+ ROOT_USER, ROOT_GROUP, text, p - text);
|
|
||||||
if (mac == NULL) {
|
|
||||||
pam_syslog(pamh, LOG_ERR, "failure generating MAC: %m");
|
|
||||||
free(text);
|
|
||||||
return PAM_SESSION_ERR;
|
|
||||||
}
|
|
||||||
+#endif /* WITH_OPENSSL */
|
|
||||||
memmove(p, mac, maclen);
|
|
||||||
p += maclen;
|
|
||||||
free(mac);
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
diff -up Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c
|
Index: Linux-PAM-1.5.3/modules/pam_unix/pam_unix_passwd.c
|
||||||
--- Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg 2016-04-11 13:08:47.000000000 +0200
|
===================================================================
|
||||||
+++ Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c 2017-04-20 16:51:24.853106709 +0200
|
--- Linux-PAM-1.5.3.orig/modules/pam_unix/pam_unix_passwd.c
|
||||||
@@ -687,12 +687,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
|
+++ Linux-PAM-1.5.3/modules/pam_unix/pam_unix_passwd.c
|
||||||
|
@@ -678,12 +678,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
|
||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
} else if (off(UNIX__IAMROOT, ctrl) ||
|
} else if (off(UNIX__IAMROOT, ctrl) ||
|
||||||
(on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1))) {
|
(on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1))) {
|
@ -0,0 +1,24 @@
|
|||||||
|
diff -up Linux-PAM-1.6.0/configure.ac.redhat-modules Linux-PAM-1.6.0/configure.ac
|
||||||
|
--- Linux-PAM-1.6.0/configure.ac.redhat-modules 2024-01-23 13:16:34.854753145 +0100
|
||||||
|
+++ Linux-PAM-1.6.0/configure.ac 2024-01-23 13:17:52.855859922 +0100
|
||||||
|
@@ -774,6 +774,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
|
||||||
|
po/Makefile.in \
|
||||||
|
Make.xml.rules \
|
||||||
|
modules/Makefile \
|
||||||
|
+ modules/pam_chroot/Makefile \
|
||||||
|
+ modules/pam_postgresok/Makefile \
|
||||||
|
modules/pam_access/Makefile \
|
||||||
|
modules/pam_canonicalize_user/Makefile \
|
||||||
|
modules/pam_debug/Makefile modules/pam_deny/Makefile \
|
||||||
|
diff -up Linux-PAM-1.6.0/modules/Makefile.am.redhat-modules Linux-PAM-1.6.0/modules/Makefile.am
|
||||||
|
--- Linux-PAM-1.6.0/modules/Makefile.am.redhat-modules 2024-01-17 11:29:36.000000000 +0100
|
||||||
|
+++ Linux-PAM-1.6.0/modules/Makefile.am 2024-01-23 13:16:34.855753147 +0100
|
||||||
|
@@ -48,6 +48,8 @@ SUBDIRS := \
|
||||||
|
pam_debug \
|
||||||
|
pam_deny \
|
||||||
|
pam_echo \
|
||||||
|
+ pam_chroot \
|
||||||
|
+ pam_postgresok \
|
||||||
|
pam_env \
|
||||||
|
pam_exec \
|
||||||
|
pam_faildelay \
|
@ -0,0 +1,24 @@
|
|||||||
|
diff -up Linux-PAM-1.6.1/doc/Makefile.am.noflex Linux-PAM-1.6.1/doc/Makefile.am
|
||||||
|
--- Linux-PAM-1.6.1/doc/Makefile.am.noflex 2024-04-09 18:22:59.000000000 +0200
|
||||||
|
+++ Linux-PAM-1.6.1/doc/Makefile.am 2024-04-10 11:09:39.304086982 +0200
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
|
||||||
|
#
|
||||||
|
|
||||||
|
-SUBDIRS = man specs sag adg mwg
|
||||||
|
+SUBDIRS = man sag adg mwg
|
||||||
|
|
||||||
|
CLEANFILES = *~
|
||||||
|
DISTCLEANFILES = custom-html.xsl custom-man.xsl
|
||||||
|
diff -up Linux-PAM-1.6.1/Makefile.am.noflex Linux-PAM-1.6.1/Makefile.am
|
||||||
|
--- Linux-PAM-1.6.1/Makefile.am.noflex 2024-04-10 11:09:39.304086982 +0200
|
||||||
|
+++ Linux-PAM-1.6.1/Makefile.am 2024-04-10 11:13:15.057352362 +0200
|
||||||
|
@@ -4,7 +4,7 @@
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = 1.9 gnu dist-xz no-dist-gzip check-news
|
||||||
|
|
||||||
|
-SUBDIRS = libpam_internal libpam tests libpamc libpam_misc modules po conf \
|
||||||
|
+SUBDIRS = libpam_internal libpam tests libpamc libpam_misc modules po doc \
|
||||||
|
xtests
|
||||||
|
|
||||||
|
if HAVE_DOC
|
@ -0,0 +1,119 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,86 @@
|
|||||||
|
From aabd5314a6d76968c377969b49118a2df3f97003 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Dmitry V. Levin" <ldv@strace.io>
|
||||||
|
Date: Sun, 19 May 2024 15:00:00 +0000
|
||||||
|
Subject: [PATCH 1/2] pam_env: fix NULL dereference on error path in
|
||||||
|
econf_read_file
|
||||||
|
|
||||||
|
* modules/pam_env/pam_env.c [USE_ECONF] (econf_read_file): Handle NULL
|
||||||
|
value returned by econf_getStringValue().
|
||||||
|
|
||||||
|
Resolves: https://github.com/linux-pam/linux-pam/issues/796
|
||||||
|
---
|
||||||
|
modules/pam_env/pam_env.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c
|
||||||
|
index 2cc58228..6d39bb24 100644
|
||||||
|
--- a/modules/pam_env/pam_env.c
|
||||||
|
+++ b/modules/pam_env/pam_env.c
|
||||||
|
@@ -287,7 +287,7 @@ econf_read_file(const pam_handle_t *pamh, const char *filename, const char *deli
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
error = econf_getStringValue (key_file, NULL, keys[i], &val);
|
||||||
|
- if (error != ECONF_SUCCESS) {
|
||||||
|
+ if (error != ECONF_SUCCESS || val == NULL) {
|
||||||
|
pam_syslog(pamh, LOG_ERR, "Unable to get string from key %s: %s",
|
||||||
|
keys[i],
|
||||||
|
econf_errString(error));
|
||||||
|
--
|
||||||
|
2.45.1
|
||||||
|
|
||||||
|
|
||||||
|
From 75292685a625153c6e28bdd820e97421c258c04a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Dmitry V. Levin" <ldv@strace.io>
|
||||||
|
Date: Sun, 19 May 2024 15:00:00 +0000
|
||||||
|
Subject: [PATCH 2/2] pam_env: fix error handling in econf_read_file
|
||||||
|
|
||||||
|
* modules/pam_env/pam_env.c [USE_ECONF] (econf_read_file): Make sure
|
||||||
|
the returned array of strings is properly initialized
|
||||||
|
when econf_getStringValue() fails to return a value.
|
||||||
|
---
|
||||||
|
modules/pam_env/pam_env.c | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c
|
||||||
|
index 6d39bb24..7c146439 100644
|
||||||
|
--- a/modules/pam_env/pam_env.c
|
||||||
|
+++ b/modules/pam_env/pam_env.c
|
||||||
|
@@ -273,7 +273,7 @@ econf_read_file(const pam_handle_t *pamh, const char *filename, const char *deli
|
||||||
|
return PAM_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- *lines = malloc((key_number +1)* sizeof(char**));
|
||||||
|
+ *lines = calloc((key_number + 1), sizeof(char**));
|
||||||
|
if (*lines == NULL) {
|
||||||
|
pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
|
||||||
|
econf_free(keys);
|
||||||
|
@@ -281,8 +281,7 @@ econf_read_file(const pam_handle_t *pamh, const char *filename, const char *deli
|
||||||
|
return PAM_BUF_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (*lines)[key_number] = 0;
|
||||||
|
-
|
||||||
|
+ size_t n = 0;
|
||||||
|
for (size_t i = 0; i < key_number; i++) {
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
@@ -293,7 +292,7 @@ econf_read_file(const pam_handle_t *pamh, const char *filename, const char *deli
|
||||||
|
econf_errString(error));
|
||||||
|
} else {
|
||||||
|
econf_unescnl(val);
|
||||||
|
- if (asprintf(&(*lines)[i],"%s%c%s", keys[i], delim[0], val) < 0) {
|
||||||
|
+ if (asprintf(&(*lines)[n],"%s%c%s", keys[i], delim[0], val) < 0) {
|
||||||
|
pam_syslog(pamh, LOG_ERR, "Cannot allocate memory.");
|
||||||
|
econf_free(keys);
|
||||||
|
econf_freeFile(key_file);
|
||||||
|
@@ -303,6 +302,7 @@ econf_read_file(const pam_handle_t *pamh, const char *filename, const char *deli
|
||||||
|
return PAM_BUF_ERR;
|
||||||
|
}
|
||||||
|
free (val);
|
||||||
|
+ n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.45.1
|
||||||
|
|
@ -0,0 +1,212 @@
|
|||||||
|
From 5eccaf9b3488d3f6da800281363697e4e4834e77 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 11:16:28 +0200
|
||||||
|
Subject: [PATCH 1/5] pam_faillock: close the audit socket after use
|
||||||
|
|
||||||
|
* modules/pam_faillock/pam_faillock.c (check_tally): Close the audit
|
||||||
|
socket when it will no longer be used.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: RESOURCE_LEAK (CWE-772):
|
||||||
|
Linux-PAM-1.6.0/modules/pam_faillock/pam_faillock.c:247: open_fn: Returning handle opened by "audit_open".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_faillock/pam_faillock.c:247: var_assign: Assigning: "audit_fd" = handle returned from "audit_open()".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_faillock/pam_faillock.c:256: noescape: Resource "audit_fd" is not freed or pointed-to in "audit_log_user_message".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_faillock/pam_faillock.c:258: leaked_handle: Handle variable "audit_fd" going out of scope leaks the handle.
|
||||||
|
256| audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf,
|
||||||
|
257| rhost, NULL, tty, 1);
|
||||||
|
258|-> }
|
||||||
|
259| #endif
|
||||||
|
260| opts->flags |= FAILLOCK_FLAG_UNLOCKED;
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-36475
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_faillock/pam_faillock.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
|
||||||
|
index e636a24e..f39a9d95 100644
|
||||||
|
--- a/modules/pam_faillock/pam_faillock.c
|
||||||
|
+++ b/modules/pam_faillock/pam_faillock.c
|
||||||
|
@@ -255,6 +255,7 @@ check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
|
||||||
|
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);
|
||||||
|
+ audit_close(audit_fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
opts->flags |= FAILLOCK_FLAG_UNLOCKED;
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
|
|
||||||
|
From d00f6cb366b492de455f9b72fcbd2e49abf323e0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 11:20:02 +0200
|
||||||
|
Subject: [PATCH 2/5] pam_rootok: close the audit socket on error path
|
||||||
|
|
||||||
|
* modules/pam_rootok/pam_rootok.c (log_callback): Close the audit socket
|
||||||
|
if vasprintf returned an error.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: RESOURCE_LEAK (CWE-772):
|
||||||
|
Linux-PAM-1.6.0/modules/pam_rootok/pam_rootok.c:59: open_fn: Returning handle opened by "audit_open".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_rootok/pam_rootok.c:59: var_assign: Assigning: "audit_fd" = handle returned from "audit_open()".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_rootok/pam_rootok.c:69: leaked_handle: Handle variable "audit_fd" going out of scope leaks the handle.
|
||||||
|
67| va_end(ap);
|
||||||
|
68| if (ret < 0) {
|
||||||
|
69|-> return 0;
|
||||||
|
70| }
|
||||||
|
71| audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-36475
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_rootok/pam_rootok.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c
|
||||||
|
index 6d2dfa07..1b88fb19 100644
|
||||||
|
--- a/modules/pam_rootok/pam_rootok.c
|
||||||
|
+++ b/modules/pam_rootok/pam_rootok.c
|
||||||
|
@@ -66,6 +66,7 @@ log_callback (int type UNUSED, const char *fmt, ...)
|
||||||
|
ret = vasprintf (&buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (ret < 0) {
|
||||||
|
+ audit_close(audit_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
|
|
||||||
|
From 1ca5bfed50bd9f6c2f1e3e36c2df3253923dadf6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 12:27:00 +0200
|
||||||
|
Subject: [PATCH 3/5] pam_timestamp: close the timestamp file on error path
|
||||||
|
|
||||||
|
* modules/pam_timestamp/pam_timestamp.c (pam_sm_authenticate)
|
||||||
|
[WITH_OPENSSL]: Close the timestamp file if hmac_size returned
|
||||||
|
an error.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: RESOURCE_LEAK (CWE-772):
|
||||||
|
Linux-PAM-1.6.0/modules/pam_timestamp/pam_timestamp.c:450: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
|
||||||
|
Linux-PAM-1.6.0/modules/pam_timestamp/pam_timestamp.c:450: var_assign: Assigning: "fd" = handle returned from "open(path, 131072)".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_timestamp/pam_timestamp.c:460: noescape: Resource "fd" is not freed or pointed-to in "fstat".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_timestamp/pam_timestamp.c:484: leaked_handle: Handle variable "fd" going out of scope leaks the handle.
|
||||||
|
482| #ifdef WITH_OPENSSL
|
||||||
|
483| if (hmac_size(pamh, debug, &maclen)) {
|
||||||
|
484|-> return PAM_AUTH_ERR;
|
||||||
|
485| }
|
||||||
|
486| #else
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-36475
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_timestamp/pam_timestamp.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c
|
||||||
|
index 7c5457c4..edecc052 100644
|
||||||
|
--- a/modules/pam_timestamp/pam_timestamp.c
|
||||||
|
+++ b/modules/pam_timestamp/pam_timestamp.c
|
||||||
|
@@ -481,6 +481,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
if (hmac_size(pamh, debug, &maclen)) {
|
||||||
|
+ close(fd);
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
|
|
||||||
|
From 667204d7e3e4a0341c529f7566d62dd64dd80866 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 12:25:34 +0200
|
||||||
|
Subject: [PATCH 4/5] pam_namespace: free SELinux context
|
||||||
|
|
||||||
|
* modules/pam_namespace/pam_namespace.c [WITH_SELINUX] (form_context):
|
||||||
|
Free SELinux context before returning.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: RESOURCE_LEAK (CWE-772):
|
||||||
|
Linux-PAM-1.6.0/modules/pam_namespace/pam_namespace.c:928: alloc_arg: "getexeccon" allocates memory that is stored into "scon".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_namespace/pam_namespace.c:1004: leaked_storage: Variable "scon" going out of scope leaks the storage it points to.
|
||||||
|
1002| }
|
||||||
|
1003| /* Should never get here */
|
||||||
|
1004|-> return PAM_SUCCESS;
|
||||||
|
1005| }
|
||||||
|
1006| #endif
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-36475
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_namespace/pam_namespace.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||||
|
index e499d95a..781dac20 100644
|
||||||
|
--- a/modules/pam_namespace/pam_namespace.c
|
||||||
|
+++ b/modules/pam_namespace/pam_namespace.c
|
||||||
|
@@ -1003,6 +1003,7 @@ static int form_context(const struct polydir_s *polyptr,
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
/* Should never get here */
|
||||||
|
+ freecon(scon);
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
|
|
||||||
|
From bd2f695b3d89efe0c52bba975f9540634125178a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Wed, 22 May 2024 12:29:07 +0200
|
||||||
|
Subject: [PATCH 5/5] pam_namespace: free SELinux context on error path
|
||||||
|
|
||||||
|
* modules/pam_namespace/pam_namespace.c (create_polydir) [WITH_SELINUX]:
|
||||||
|
Free SELinux context in case of an error.
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: RESOURCE_LEAK (CWE-772):
|
||||||
|
Linux-PAM-1.6.0/modules/pam_namespace/pam_namespace.c:1433: alloc_arg: "getfscreatecon_raw" allocates memory that is stored into "oldcon_raw".
|
||||||
|
Linux-PAM-1.6.0/modules/pam_namespace/pam_namespace.c:1462: leaked_storage: Variable "oldcon_raw" going out of scope leaks the storage it points to.
|
||||||
|
1460| pam_syslog(idata->pamh, LOG_ERR,
|
||||||
|
1461| "Error creating directory %s: %m", dir);
|
||||||
|
1462|-> return PAM_SESSION_ERR;
|
||||||
|
1463| }
|
||||||
|
1464|
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolves: https://issues.redhat.com/browse/RHEL-36475
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
---
|
||||||
|
modules/pam_namespace/pam_namespace.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
|
||||||
|
index 781dac20..2dab49ef 100644
|
||||||
|
--- a/modules/pam_namespace/pam_namespace.c
|
||||||
|
+++ b/modules/pam_namespace/pam_namespace.c
|
||||||
|
@@ -1462,6 +1462,9 @@ static int create_polydir(struct polydir_s *polyptr,
|
||||||
|
if (rc == -1) {
|
||||||
|
pam_syslog(idata->pamh, LOG_ERR,
|
||||||
|
"Error creating directory %s: %m", dir);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ freecon(oldcon_raw);
|
||||||
|
+#endif
|
||||||
|
return PAM_SESSION_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
#%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 sufficient pam_unix.so try_first_pass nullok
|
|
||||||
auth required pam_deny.so
|
|
||||||
|
|
||||||
account required pam_unix.so
|
|
||||||
|
|
||||||
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
|
|
||||||
password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow
|
|
||||||
password required pam_deny.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
|
|
@ -1,8 +0,0 @@
|
|||||||
#%PAM-1.0
|
|
||||||
# This file is auto-generated.
|
|
||||||
# User changes will be destroyed the next time authselect is run.
|
|
||||||
|
|
||||||
session optional pam_umask.so silent
|
|
||||||
session [success=1 default=ignore] pam_succeed_if.so service !~ gdm* service !~ su* quiet
|
|
||||||
session [default=1] pam_lastlog.so nowtmp showfailed
|
|
||||||
session optional pam_lastlog.so silent noupdate showfailed
|
|
@ -1,19 +0,0 @@
|
|||||||
#%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
|
|
@ -1,18 +0,0 @@
|
|||||||
#%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 sufficient pam_unix.so try_first_pass nullok
|
|
||||||
auth required pam_deny.so
|
|
||||||
|
|
||||||
account required pam_unix.so
|
|
||||||
|
|
||||||
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
|
|
||||||
password sufficient pam_unix.so try_first_pass use_authtok nullok sha512 shadow
|
|
||||||
password required pam_deny.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
|
|
Loading…
Reference in new issue