Compare commits

...

9 Commits
rawhide ... f32

Author SHA1 Message Date
ipedrosa a4a0ff7a56 Add BuildRequires: make (#1902520) 2020-12-11 14:17:27 +01:00
Allison Karlitskaya 721d8b383e libpam: add supplementary groups on priv drop 2020-12-01 10:11:31 +01:00
ipedrosa 55e417db2c - fix CVE-2020-27780: authentication bypass when the user doesn't exist
and root password is blank (#1901173)
2020-11-27 09:20:42 +01:00
ipedrosa 456eb7078d - pam_unix: fix missing initialization of daysleft (#1887077)
- pam_motd: change privilege message prompt to default (#1861640)
2020-11-11 09:55:09 +01:00
ipedrosa c757a5f3a5 - pam_motd: read motd files with target user credentials skipping unreadable ones (#1861640)
- Clarify upstreamed patches
2020-10-26 13:05:37 +01:00
ipedrosa b3441aa346 pam_faillock: change /run/faillock/$USER permissions to 0660 2020-06-24 15:30:57 +02:00
ipedrosa c99677c8e8 pam_unix and pam_usertype: avoid determining if user exists 2020-06-22 09:41:29 +02:00
ikerexxe b173f42452 pam_selinux: check unknown object classes or permissions in current policy 2020-03-11 16:56:29 +01:00
Pavel Březina a2d2a3801b add pam_usertype 2020-03-02 17:32:46 +01:00
11 changed files with 1390 additions and 1 deletions

View File

@ -0,0 +1,126 @@
From 0fa5f9d4184928c28689b673fb06bb8b4d88a0c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 6 Feb 2020 12:41:15 +0100
Subject: [PATCH] pam_usertype: remove dependency on pam_modutil_search_key
This is needed to correctly backport the patch to this version.
---
modules/pam_usertype/pam_usertype.c | 88 ++++++++++++++++++++++++++++-
1 file changed, 87 insertions(+), 1 deletion(-)
diff --git a/modules/pam_usertype/pam_usertype.c b/modules/pam_usertype/pam_usertype.c
index d3629c137d98545871d24ff26c06d8377068141f..741956b05809d8d6247fe2eba82ae14427cfeae4 100644
--- a/modules/pam_usertype/pam_usertype.c
+++ b/modules/pam_usertype/pam_usertype.c
@@ -40,6 +40,7 @@
#include "config.h"
#include <sys/types.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
@@ -72,6 +73,91 @@ struct pam_usertype_opts {
int audit;
};
+/* taken from pam_umask.c and reformatted */
+static char *
+search_key (const char *filename,
+ const char *key)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t buflen = 0;
+ char *retval = NULL;
+
+ fp = fopen (filename, "r");
+ if (NULL == fp) {
+ return NULL;
+ }
+
+ while (!feof (fp)) {
+ char *tmp, *cp;
+#if defined(HAVE_GETLINE)
+ ssize_t n = getline (&buf, &buflen, fp);
+#elif defined (HAVE_GETDELIM)
+ ssize_t n = getdelim (&buf, &buflen, '\n', fp);
+#else
+ ssize_t n;
+
+ if (buf == NULL) {
+ buflen = BUF_SIZE;
+ buf = malloc (buflen);
+ if (buf == NULL) {
+ fclose (fp);
+ return NULL;
+ }
+ }
+
+ buf[0] = '\0';
+ if (fgets (buf, buflen - 1, fp) == NULL) {
+ break;
+ } else if (buf != NULL) {
+ n = strlen (buf);
+ } else {
+ n = 0;
+ }
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
+
+ cp = buf;
+
+ if (n < 1) {
+ break;
+ }
+
+ tmp = strchr (cp, '#'); /* remove comments */
+ if (tmp) {
+ *tmp = '\0';
+ }
+
+ while (isspace ((int)*cp)) { /* remove spaces and tabs */
+ ++cp;
+ }
+
+ if (*cp == '\0') { /* ignore empty lines */
+ continue;
+ }
+
+ if (cp[strlen (cp) - 1] == '\n') {
+ cp[strlen (cp) - 1] = '\0';
+ }
+
+ tmp = strsep (&cp, " \t=");
+ if (cp != NULL) {
+ while (isspace ((int)*cp) || *cp == '=') {
+ ++cp;
+ }
+ }
+
+ if (strcasecmp (tmp, key) == 0) {
+ retval = strdup (cp);
+ break;
+ }
+ }
+
+ fclose (fp);
+ free (buf);
+
+ return retval;
+}
+
static int
pam_usertype_parse_args(struct pam_usertype_opts *opts,
pam_handle_t *pamh,
@@ -170,7 +256,7 @@ pam_usertype_get_id(pam_handle_t *pamh,
char *ep;
uid_t uid;
- value = pam_modutil_search_key(pamh, LOGIN_DEFS, key);
+ value = search_key(LOGIN_DEFS, key);
if (value == NULL) {
return default_value;
}
--
2.24.1

View File

@ -0,0 +1,684 @@
From 88df4b5383b776b7b8ee9eb4c33231d54185b1e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 10 Jan 2020 15:53:35 +0100
Subject: [PATCH] pam_usertype: new module to tell if uid is in login.defs
ranges
This module will check if the user account type is system or regular based
on its uid. To evaluate the condition it will use 0-99 reserved range
together with `SYS_UID_MIN` and `SYS_UID_MAX` values from `/etc/login.defs`.
If these values are not set, it uses configure-time defaults
`--with-sys-uid-min` and `--with-uid-min` (according to `login.defs` man page
`SYS_UID_MAX` defaults to `UID_MIN - 1`.
This information can be used to skip specific module in pam stack
based on the account type. `pam_succeed_if uid < 1000` is used at the moment
however it does not reflect changes to `login.defs`.
---
configure.ac | 22 ++
modules/Makefile.am | 2 +-
modules/pam_usertype/Makefile.am | 34 +++
modules/pam_usertype/README.xml | 41 +++
modules/pam_usertype/pam_usertype.8.xml | 170 +++++++++++++
modules/pam_usertype/pam_usertype.c | 319 ++++++++++++++++++++++++
modules/pam_usertype/tst-pam_usertype | 2 +
7 files changed, 589 insertions(+), 1 deletion(-)
create mode 100644 modules/pam_usertype/Makefile.am
create mode 100644 modules/pam_usertype/README.xml
create mode 100644 modules/pam_usertype/pam_usertype.8.xml
create mode 100644 modules/pam_usertype/pam_usertype.c
create mode 100755 modules/pam_usertype/tst-pam_usertype
diff --git a/configure.ac b/configure.ac
index 0267202d2f56cbb641ce74d283bc4ba2a4b3d0d9..f10a09e14c10639b91c356d6ef883da4a0a87a66 100644
--- a/configure.ac
+++ b/configure.ac
@@ -606,6 +606,27 @@ AC_SUBST([HAVE_KEY_MANAGEMENT], $HAVE_KEY_MANAGEMENT)
AM_CONDITIONAL([HAVE_KEY_MANAGEMENT], [test "$have_key_syscalls" = 1])
+dnl
+dnl Get values for default uid ranges in login.defs used in pam_usertype
+dnl
+AC_ARG_WITH([uidmin], AS_HELP_STRING([--with-uidmin=<number>],[default value for regular user min uid (1000)]), opt_uidmin=$withval)
+if test x"$opt_uidmin" == x; then
+ opt_uidmin=1000
+fi
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
+
+AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
+if test x"$opt_sysuidmin" == x; then
+ opt_sysuidmin=101
+fi
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
+
+AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
+if test x"$opt_kerneloverflowuid" == x; then
+ opt_kerneloverflowuid=65534
+fi
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
+
dnl Files to be created from when we run configure
AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
@@ -636,6 +657,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile
modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \
modules/pam_umask/Makefile \
modules/pam_unix/Makefile modules/pam_userdb/Makefile \
+ modules/pam_usertype/Makefile \
modules/pam_warn/Makefile modules/pam_wheel/Makefile \
modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
doc/man/Makefile doc/sag/Makefile doc/adg/Makefile \
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 5149181e2d1aeefbab8876433e8a54848ec56fc6..c1b5c5611c79e666bbd2f94fa0712a2b78bd2f5f 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -12,7 +12,7 @@ SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \
pam_selinux pam_sepermit pam_shells pam_stress \
pam_succeed_if pam_time pam_timestamp \
pam_tty_audit pam_umask \
- pam_unix pam_userdb pam_warn pam_wheel pam_xauth
+ pam_unix pam_userdb pam_usertype pam_warn pam_wheel pam_xauth
CLEANFILES = *~
diff --git a/modules/pam_usertype/Makefile.am b/modules/pam_usertype/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..1646bc34f2fbc44032af5a5b38d160614b247b72
--- /dev/null
+++ b/modules/pam_usertype/Makefile.am
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
+# Copyright (c) 2020 Red Hat, Inc.
+#
+
+CLEANFILES = *~
+MAINTAINERCLEANFILES = $(MANS) README
+
+EXTRA_DIST = README ${MANS} ${XMLS} tst-pam_usertype
+
+TESTS = tst-pam_usertype
+
+man_MANS = pam_usertype.8
+
+XMLS = README.xml pam_usertype.8.xml
+
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ $(WARN_CFLAGS)
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+securelib_LTLIBRARIES = pam_usertype.la
+pam_usertype_la_LIBADD = $(top_builddir)/libpam/libpam.la
+
+if ENABLE_REGENERATE_MAN
+noinst_DATA = README
+README: pam_usertype.8.xml
+-include $(top_srcdir)/Make.xml.rules
+endif
diff --git a/modules/pam_usertype/README.xml b/modules/pam_usertype/README.xml
new file mode 100644
index 0000000000000000000000000000000000000000..58550465459222ace5e346c32b54cf6776eeeec5
--- /dev/null
+++ b/modules/pam_usertype/README.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.docbook.org/xml/4.3/docbookx.dtd"
+[
+<!--
+<!ENTITY pamaccess SYSTEM "pam_usertype.8.xml">
+-->
+]>
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_usertype-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-options"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-examples"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-author"]/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_usertype/pam_usertype.8.xml b/modules/pam_usertype/pam_usertype.8.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1ba4ee71dcd4faee1bf5293c718d1bdf823689f0
--- /dev/null
+++ b/modules/pam_usertype/pam_usertype.8.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+
+<refentry id='pam_usertype'>
+ <refmeta>
+ <refentrytitle>pam_usertype</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='sectdesc'>Linux-PAM</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='pam_usertype-name'>
+ <refname>pam_usertype</refname>
+ <refpurpose>check if the authenticated user is a system or regular account</refpurpose>
+ </refnamediv>
+
+
+ <refsynopsisdiv>
+ <cmdsynopsis id='pam_usertype-cmdsynopsis'>
+ <command>pam_usertype.so</command>
+ <arg choice='opt' rep='repeat'><replaceable>flag</replaceable></arg>
+ <arg choice='req'><replaceable>condition</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id='pam_usertype-description'>
+ <title>DESCRIPTION</title>
+ <para>
+ pam_usertype.so is designed to succeed or fail authentication
+ based on type of the account of the authenticated user.
+ The type of the account is decided with help of
+ <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
+ settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
+ whether to load other modules based on this test.
+ </para>
+
+ <para>
+ The module should be given only one condition as module argument.
+ Authentication will succeed only if the condition is met.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_usertype-options">
+ <title>OPTIONS</title>
+ <para>
+ The following <emphasis>flag</emphasis>s are supported:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>use_uid</option></term>
+ <listitem>
+ <para>
+ Evaluate conditions using the account of the user whose UID
+ the application is running under instead of the user being
+ authenticated.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>audit</option></term>
+ <listitem>
+ <para>
+ Log unknown users to the system log.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Available <emphasis>condition</emphasis>s are:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>issystem</option></term>
+ <listitem>
+ <para>Succeed if the user is a system user.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>isregular</option></term>
+ <listitem>
+ <para>Succeed if the user is a regular user.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_usertype-types">
+ <title>MODULE TYPES PROVIDED</title>
+ <para>
+ All module types (<option>account</option>, <option>auth</option>,
+ <option>password</option> and <option>session</option>) are provided.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-return_values'>
+ <title>RETURN VALUES</title>
+ <variablelist>
+
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ The condition was true.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_AUTH_ERR</term>
+ <listitem>
+ <para>
+ The condition was false.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SERVICE_ERR</term>
+ <listitem>
+ <para>
+ A service error occurred or the arguments can't be
+ parsed correctly.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_USER_UNKNOWN</term>
+ <listitem>
+ <para>
+ User was not found.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+
+ <refsect1 id='pam_usertype-examples'>
+ <title>EXAMPLES</title>
+ <para>
+ Skip remaining modules if the user is a system user:
+ </para>
+ <programlisting>
+account sufficient pam_usertype.so issystem
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-author'>
+ <title>AUTHOR</title>
+ <para>Pavel Březina &lt;pbrezina@redhat.com&gt;</para>
+ </refsect1>
+</refentry>
diff --git a/modules/pam_usertype/pam_usertype.c b/modules/pam_usertype/pam_usertype.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3629c137d98545871d24ff26c06d8377068141f
--- /dev/null
+++ b/modules/pam_usertype/pam_usertype.c
@@ -0,0 +1,319 @@
+/******************************************************************************
+ * Check user type based on login.defs.
+ *
+ * Copyright (c) 2020 Red Hat, Inc.
+ * Written by Pavel Březina <pbrezina@redhat.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#define PAM_SM_SESSION
+#define PAM_SM_PASSWORD
+
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+
+#define LOGIN_DEFS "/etc/login.defs"
+
+enum pam_usertype_op {
+ OP_IS_SYSTEM,
+ OP_IS_REGULAR,
+
+ OP_SENTINEL
+};
+
+struct pam_usertype_opts {
+ enum pam_usertype_op op;
+ int use_uid;
+ int audit;
+};
+
+static int
+pam_usertype_parse_args(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ int argc,
+ const char **argv)
+{
+ int i;
+
+ memset(opts, 0, sizeof(struct pam_usertype_opts));
+ opts->op = OP_SENTINEL;
+
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "use_uid") == 0) {
+ opts->use_uid = 1;
+ } else if (strcmp(argv[i], "audit") == 0) {
+ opts->audit = 1;
+ } else if (strcmp(argv[i], "issystem") == 0) {
+ opts->op = OP_IS_SYSTEM;
+ } else if (strcmp(argv[i], "isregular") == 0) {
+ opts->op = OP_IS_REGULAR;
+ } else {
+ pam_syslog(pamh, LOG_WARNING, "Unknown argument: %s", argv[i]);
+ /* Just continue. */
+ }
+ }
+
+ if (opts->op == OP_SENTINEL) {
+ pam_syslog(pamh, LOG_ERR, "Operation not specified");
+ return PAM_SERVICE_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int
+pam_usertype_get_uid(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ uid_t *_uid)
+{
+ struct passwd *pwd;
+ const void *prompt;
+ const char *username;
+ int ret;
+
+ /* Get uid of user that runs the application. */
+ if (opts->use_uid) {
+ pwd = pam_modutil_getpwuid(pamh, getuid());
+ if (pwd == NULL) {
+ pam_syslog(pamh, LOG_ERR,
+ "error retrieving information about user %lu",
+ (unsigned long)getuid());
+ return PAM_USER_UNKNOWN;
+ }
+
+ *_uid = pwd->pw_uid;
+ return PAM_SUCCESS;
+ }
+
+ /* Get uid of user that is being authenticated. */
+ ret = pam_get_item(pamh, PAM_USER_PROMPT, &prompt);
+ if (ret != PAM_SUCCESS || prompt == NULL || strlen(prompt) == 0) {
+ prompt = "login: ";
+ }
+
+ ret = pam_get_user(pamh, &username, prompt);
+ if (ret != PAM_SUCCESS || username == NULL) {
+ pam_syslog(pamh, LOG_ERR, "error retrieving user name: %s",
+ pam_strerror(pamh, ret));
+ return ret;
+ }
+
+ pwd = pam_modutil_getpwnam(pamh, username);
+ if (pwd == NULL) {
+ if (opts->audit) {
+ pam_syslog(pamh, LOG_NOTICE,
+ "error retrieving information about user %s", username);
+ }
+
+ return PAM_USER_UNKNOWN;
+ }
+
+ *_uid = pwd->pw_uid;
+
+ return PAM_SUCCESS;
+}
+
+#define MAX_UID_VALUE 0xFFFFFFFFUL
+
+static uid_t
+pam_usertype_get_id(pam_handle_t *pamh,
+ const char *key,
+ uid_t default_value)
+{
+ unsigned long ul;
+ char *value;
+ char *ep;
+ uid_t uid;
+
+ value = pam_modutil_search_key(pamh, LOGIN_DEFS, key);
+ if (value == NULL) {
+ return default_value;
+ }
+
+ /* taken from get_lastlog_uid_max() */
+ ep = value + strlen(value);
+ while (ep > value && isspace(*(--ep))) {
+ *ep = '\0';
+ }
+
+ errno = 0;
+ ul = strtoul(value, &ep, 10);
+ if (!(ul >= MAX_UID_VALUE
+ || (uid_t)ul >= MAX_UID_VALUE
+ || (errno != 0 && ul == 0)
+ || value == ep
+ || *ep != '\0')) {
+ uid = (uid_t)ul;
+ } else {
+ uid = default_value;
+ }
+
+ free(value);
+
+ return uid;
+}
+
+static int
+pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
+{
+ uid_t uid_min;
+ uid_t sys_min;
+ uid_t sys_max;
+
+ if (uid == (uid_t)-1) {
+ pam_syslog(pamh, LOG_WARNING, "invalid uid");
+ return PAM_USER_UNKNOWN;
+ }
+
+ if (uid <= 99) {
+ /* Reserved. */
+ return PAM_SUCCESS;
+ }
+
+ if (uid == PAM_USERTYPE_OVERFLOW_UID) {
+ /* nobody */
+ return PAM_SUCCESS;
+ }
+
+ uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
+ sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
+ sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
+
+ return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+
+static int
+pam_usertype_is_regular(pam_handle_t *pamh, uid_t uid)
+{
+ int ret;
+
+ ret = pam_usertype_is_system(pamh, uid);
+ switch (ret) {
+ case PAM_SUCCESS:
+ return PAM_AUTH_ERR;
+ case PAM_USER_UNKNOWN:
+ return PAM_USER_UNKNOWN;
+ default:
+ return PAM_SUCCESS;
+ }
+}
+
+static int
+pam_usertype_evaluate(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ uid_t uid)
+{
+ switch (opts->op) {
+ case OP_IS_SYSTEM:
+ return pam_usertype_is_system(pamh, uid);
+ case OP_IS_REGULAR:
+ return pam_usertype_is_regular(pamh, uid);
+ default:
+ pam_syslog(pamh, LOG_ERR, "Unknown operation: %d", opts->op);
+ return PAM_SERVICE_ERR;
+ }
+}
+
+/**
+ * Arguments:
+ * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
+ * - isregular: not issystem
+ * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
+ * - audit: log unknown users to syslog
+ */
+int
+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
+ int argc, const char **argv)
+{
+ struct pam_usertype_opts opts;
+ uid_t uid;
+ int ret;
+
+ ret = pam_usertype_parse_args(&opts, pamh, argc, argv);
+ if (ret != PAM_SUCCESS) {
+ return ret;
+ }
+
+ ret = pam_usertype_get_uid(&opts, pamh, &uid);
+ if (ret != PAM_SUCCESS) {
+ return ret;
+ }
+
+ return pam_usertype_evaluate(&opts, pamh, uid);
+}
+
+int
+pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
+{
+ return PAM_IGNORE;
+}
+
+int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
diff --git a/modules/pam_usertype/tst-pam_usertype b/modules/pam_usertype/tst-pam_usertype
new file mode 100755
index 0000000000000000000000000000000000000000..a21f8fe7cef3daf6a842bc35972976ee189d3570
--- /dev/null
+++ b/modules/pam_usertype/tst-pam_usertype
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_usertype.so
--
2.24.1

View File

@ -0,0 +1,82 @@
diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.determinine-user-exists Linux-PAM-1.3.1/modules/pam_unix/passverify.c
--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.determinine-user-exists 2020-06-17 15:34:08.089162532 +0200
+++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2020-06-17 15:36:13.233294407 +0200
@@ -1087,6 +1087,12 @@ helper_verify_password(const char *name,
if (pwd == NULL || salt == NULL) {
helper_log_err(LOG_NOTICE, "check pass; user unknown");
retval = PAM_USER_UNKNOWN;
+ } else if (p[0] == '\0' && nullok) {
+ if (salt[0] == '\0') {
+ retval = PAM_SUCCESS;
+ } else {
+ retval = PAM_AUTH_ERR;
+ }
} else {
retval = verify_pwd_hash(p, salt, nullok);
}
diff -up Linux-PAM-1.3.1/modules/pam_unix/support.c.determinine-user-exists Linux-PAM-1.3.1/modules/pam_unix/support.c
--- Linux-PAM-1.3.1/modules/pam_unix/support.c.determinine-user-exists 2020-06-17 15:34:08.090162549 +0200
+++ Linux-PAM-1.3.1/modules/pam_unix/support.c 2020-06-17 15:34:08.101162736 +0200
@@ -672,6 +672,8 @@ _unix_blankpasswd (pam_handle_t *pamh, u
struct passwd *pwd = NULL;
char *salt = NULL;
int retval;
+ int execloop = 1;
+ int nonexistent = 1;
D(("called"));
@@ -686,14 +688,31 @@ _unix_blankpasswd (pam_handle_t *pamh, u
/* UNIX passwords area */
- retval = get_pwd_hash(pamh, name, &pwd, &salt);
+ /*
+ * Execute this loop twice: one checking the password hash of an existing
+ * user and another one for a non-existing user. This way the runtimes
+ * are equal, making it more difficult to differentiate existing from
+ * non-existing users.
+ */
+ while (execloop) {
+ retval = get_pwd_hash(pamh, name, &pwd, &salt);
- if (retval == PAM_UNIX_RUN_HELPER) {
- /* salt will not be set here so we can return immediately */
- if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS)
- return 1;
- else
- return 0;
+ if (retval == PAM_UNIX_RUN_HELPER) {
+ execloop = 0;
+ if(nonexistent) {
+ get_pwd_hash(pamh, "pam_unix_non_existent:", &pwd, &salt);
+ }
+ /* salt will not be set here so we can return immediately */
+ if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS)
+ return 1;
+ else
+ return 0;
+ } else if (retval == PAM_USER_UNKNOWN) {
+ name = "root";
+ nonexistent = 0;
+ } else {
+ execloop = 0;
+ }
}
/* Does this user have a password? */
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.determinine-user-exists Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.determinine-user-exists 2020-06-17 15:34:08.098162685 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2020-06-17 15:34:08.101162736 +0200
@@ -236,8 +236,11 @@ pam_usertype_get_uid(struct pam_usertype
"error retrieving information about user %s", username);
}
+ pam_modutil_getpwnam(pamh, "root");
+
return PAM_USER_UNKNOWN;
}
+ pam_modutil_getpwnam(pamh, "pam_usertype_non_existent:");
*_uid = pwd->pw_uid;

View File

@ -0,0 +1,52 @@
From 62d826471e87e27b39a36ccbeee58999e2514a92 Mon Sep 17 00:00:00 2001
From: Allison Karlitskaya <allison.karlitskaya@redhat.com>
Date: Thu, 5 Nov 2020 14:06:53 +0100
Subject: [PATCH] libpam: add supplementary groups on priv drop
Replace the setgroups(0, NULL) call in pam_modutil_drop_priv() with a
call to initgroups(). This makes sure that the user's supplementary
groups are also configured. Fall back to setgroups(0, NULL) in case the
initgroups() call fails.
This fixes the permission check in pam_motd: this feature was intended
to allow setting permissions on a motd file to prevent it from being
shown to users who are not a member of a particular group (for example,
wheel).
Closes #292
---
libpam/pam_modutil_priv.c | 17 +++++++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/libpam/pam_modutil_priv.c b/libpam/pam_modutil_priv.c
index e22fab1a..a463e06a 100644
--- a/libpam/pam_modutil_priv.c
+++ b/libpam/pam_modutil_priv.c
@@ -107,11 +107,20 @@ int pam_modutil_drop_priv(pam_handle_t *pamh,
* We should care to leave process credentials in consistent state.
* That is, e.g. if change_gid() succeeded but change_uid() failed,
* we should try to restore old gid.
+ *
+ * We try to add the supplementary groups on a best-effort
+ * basis. If it fails, it's not fatal: we fall back to using an
+ * empty list.
*/
- if (setgroups(0, NULL)) {
- pam_syslog(pamh, LOG_ERR,
- "pam_modutil_drop_priv: setgroups failed: %m");
- return cleanup(p);
+ if (initgroups(pw->pw_name, pw->pw_gid)) {
+ pam_syslog(pamh, LOG_WARNING,
+ "pam_modutil_drop_priv: initgroups failed: %m");
+
+ if (setgroups(0, NULL)) {
+ pam_syslog(pamh, LOG_ERR,
+ "pam_modutil_drop_priv: setgroups failed: %m");
+ return cleanup(p);
+ }
}
if (change_gid(pw->pw_gid, &p->old_gid)) {
pam_syslog(pamh, LOG_ERR,
--
2.28.0

View File

@ -0,0 +1,50 @@
From 395915dae1571e10e2766c999974de864655ea3a Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Mon, 15 Jun 2020 09:52:11 +0200
Subject: [PATCH] pam_faillock: change /run/faillock/$USER permissions to 0660
Nowadays, /run/faillock/$USER files have user:root ownership and 0600
permissions. This forces the process that writes to these files to have
CAP_DAC_OVERRIDE capabilites. Just by changing the permissions to 0660
the capability can be removed, which leads to a more secure system.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1661822
---
modules/pam_faillock/faillock.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/modules/pam_faillock/faillock.c b/modules/pam_faillock/faillock.c
index e492f5f9..4ea94cbe 100644
--- a/modules/pam_faillock/faillock.c
+++ b/modules/pam_faillock/faillock.c
@@ -76,7 +76,7 @@ open_tally (const char *dir, const char *user, uid_t uid, int create)
flags |= O_CREAT;
}
- fd = open(path, flags, 0600);
+ fd = open(path, flags, 0660);
free(path);
@@ -88,6 +88,18 @@ open_tally (const char *dir, const char *user, uid_t uid, int create)
if (st.st_uid != uid) {
ignore_return(fchown(fd, uid, -1));
}
+
+ /*
+ * If umask is set to 022, as will probably in most systems, then the
+ * group will not be able to write to the file. So, change the file
+ * permissions just in case.
+ * Note: owners of this file are user:root, so if the permissions are
+ * not changed the root process writing to this file will require
+ * CAP_DAC_OVERRIDE.
+ */
+ if (!(st.st_mode & S_IWGRP)) {
+ ignore_return(fchmod(fd, 0660));
+ }
}
}
--
2.26.2

View File

@ -0,0 +1,133 @@
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-filter-files Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-filter-files 2020-10-26 11:28:41.528302216 +0100
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2020-10-26 11:28:41.542302409 +0100
@@ -64,8 +64,9 @@
override files with the same name in <filename>/usr/lib/motd.d/</filename>.
</para>
<para>
- Files the in the directories listed above are displayed in
- lexicographic order by name.
+ Files in the directories listed above are displayed in lexicographic
+ order by name. Moreover, the files are filtered by reading them with the
+ credentials of the target user authenticating on the system.
</para>
<para>
To silence a message,
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.motd-filter-files Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.motd-filter-files 2020-10-26 11:28:41.541302395 +0100
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2020-10-26 11:32:15.933258567 +0100
@@ -313,6 +313,71 @@ static void try_to_display_directories_w
return;
}
+static int drop_privileges(pam_handle_t *pamh, struct pam_modutil_privs *privs)
+{
+ struct passwd *pw;
+ const char *username;
+ int retval;
+
+ retval = pam_get_user(pamh, &username, "key user");
+
+ if (retval == PAM_SUCCESS) {
+ pw = pam_modutil_getpwnam (pamh, username);
+ } else {
+ return PAM_SESSION_ERR;
+ }
+
+ if (pw == NULL || pam_modutil_drop_priv(pamh, privs, pw)) {
+ return PAM_SESSION_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int try_to_display(pam_handle_t *pamh, char **motd_path_split,
+ unsigned int num_motd_paths,
+ char **motd_dir_path_split,
+ unsigned int num_motd_dir_paths)
+{
+ PAM_MODUTIL_DEF_PRIVS(privs);
+
+ if (drop_privileges(pamh, &privs) != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR, "Unable to drop privileges");
+ return PAM_SESSION_ERR;
+ }
+
+ if (motd_path_split != NULL) {
+ unsigned int i;
+
+ for (i = 0; i < num_motd_paths; i++) {
+ int fd = open(motd_path_split[i], O_RDONLY, 0);
+
+ if (fd >= 0) {
+ try_to_display_fd(pamh, fd);
+ close(fd);
+
+ /* We found and displayed a file,
+ * move onto next filename.
+ */
+ break;
+ }
+ }
+ }
+
+ if (motd_dir_path_split != NULL) {
+ try_to_display_directories_with_overrides(pamh,
+ motd_dir_path_split,
+ num_motd_dir_paths);
+ }
+
+ if (pam_modutil_regain_priv(pamh, &privs)) {
+ pam_syslog(pamh, LOG_ERR, "Unable to regain privileges");
+ return PAM_SESSION_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
@@ -384,25 +450,8 @@ int pam_sm_open_session(pam_handle_t *pa
}
}
- if (motd_path_split != NULL) {
- int i;
-
- for (i = 0; i < num_motd_paths; i++) {
- int fd = open(motd_path_split[i], O_RDONLY, 0);
-
- if (fd >= 0) {
- try_to_display_fd(pamh, fd);
- close(fd);
-
- /* We found and displayed a file, move onto next filename. */
- break;
- }
- }
- }
-
- if (motd_dir_path_split != NULL)
- try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
- num_motd_dir_paths);
+ retval = try_to_display(pamh, motd_path_split, num_motd_paths,
+ motd_dir_path_split, num_motd_dir_paths);
out:
_pam_drop(motd_path_copy);
@@ -410,7 +460,12 @@ int pam_sm_open_session(pam_handle_t *pa
_pam_drop(motd_dir_path_copy);
_pam_drop(motd_dir_path_split);
- return retval;
+ if (retval == PAM_SUCCESS) {
+ retval = pam_putenv(pamh, "MOTD_SHOWN=pam");
+ return retval == PAM_SUCCESS ? PAM_IGNORE : retval;
+ } else {
+ return retval;
+ }
}
/* end of module definition */
diff -up Linux-PAM-1.3.1/NEWS.motd-filter-files Linux-PAM-1.3.1/NEWS

View File

@ -0,0 +1,27 @@
From 9f24bbeeb4fe04bc396898cd9825478ad52c5ac7 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Wed, 21 Oct 2020 09:47:20 +0200
Subject: [PATCH] pam_motd: unset prompt value to drop privileges
modules/pam_motd/pam_motd.c: set NULL value instead of "key user" for the
prompt when dropping privileges.
---
modules/pam_motd/pam_motd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
index a4fd0e59..6ac8cba2 100644
--- a/modules/pam_motd/pam_motd.c
+++ b/modules/pam_motd/pam_motd.c
@@ -288,7 +288,7 @@ static int drop_privileges(pam_handle_t *pamh, struct pam_modutil_privs *privs)
const char *username;
int retval;
- retval = pam_get_user(pamh, &username, "key user");
+ retval = pam_get_user(pamh, &username, NULL);
if (retval == PAM_SUCCESS) {
pw = pam_modutil_getpwnam (pamh, username);
--
2.26.2

View File

@ -0,0 +1,96 @@
From c6c51832af8e7724cfbd454daa65a6644f5b45c2 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Fri, 6 Mar 2020 15:04:09 +0100
Subject: [PATCH] pam_selinux: check unknown object classes or permissions in
current policy
Explanation: check whether unknown object classes or permissions are allowed or denied in the current policy
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1680961
---
modules/pam_selinux/pam_selinux.c | 50 +++++--------------------------
1 file changed, 8 insertions(+), 42 deletions(-)
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
index 96f9c831..827f5942 100644
--- a/modules/pam_selinux/pam_selinux.c
+++ b/modules/pam_selinux/pam_selinux.c
@@ -157,42 +157,6 @@ query_response (pam_handle_t *pamh, const char *text, const char *def,
return rc;
}
-static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, security_context_t dst, int debug)
-{
- struct av_decision avd;
- int retval;
- security_class_t class;
- access_vector_t bit;
- context_t src_context;
- context_t dst_context;
-
- class = string_to_security_class("context");
- if (!class) {
- pam_syslog(pamh, LOG_ERR, "Failed to translate security class context. %m");
- return 0;
- }
-
- bit = string_to_av_perm(class, "contains");
- if (!bit) {
- pam_syslog(pamh, LOG_ERR, "Failed to translate av perm contains. %m");
- return 0;
- }
-
- src_context = context_new (src);
- dst_context = context_new (dst);
- context_range_set(dst_context, context_range_get(src_context));
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Checking if %s mls range valid for %s", dst, context_str(dst_context));
-
- retval = security_compute_av(context_str(dst_context), dst, class, bit, &avd);
- context_free(src_context);
- context_free(dst_context);
- if (retval || ((bit & avd.allowed) != bit))
- return 0;
-
- return 1;
-}
-
static security_context_t
config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug)
{
@@ -274,16 +238,17 @@ config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_curre
goto fail_set;
context_free(new_context);
- /* we have to check that this user is allowed to go into the
- range they have specified ... role is tied to an seuser, so that'll
- be checked at setexeccon time */
- if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+ /* we have to check that this user is allowed to go into the
+ range they have specified ... role is tied to an seuser, so that'll
+ be checked at setexeccon time */
+ if (mls_enabled &&
+ selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
send_audit_message(pamh, 0, defaultcon, newcon);
free(newcon);
- goto fail_range;
+ goto fail_range;
}
return newcon;
}
@@ -385,7 +350,8 @@ context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_par
/* we have to check that this user is allowed to go into the
range they have specified ... role is tied to an seuser, so that'll
be checked at setexeccon time */
- if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+ if (mls_enabled &&
+ selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
goto fail_set;
--
2.24.1

View File

@ -0,0 +1,69 @@
diff -up Linux-PAM-1.3.1/modules/pam_unix/support.c.my Linux-PAM-1.3.1/modules/pam_unix/support.c
--- Linux-PAM-1.3.1/modules/pam_unix/support.c.my 2020-11-20 15:43:34.987915063 +0100
+++ Linux-PAM-1.3.1/modules/pam_unix/support.c 2020-11-20 15:46:00.950864468 +0100
@@ -672,8 +672,9 @@ _unix_blankpasswd (pam_handle_t *pamh, u
struct passwd *pwd = NULL;
char *salt = NULL;
int retval;
- int execloop = 1;
- int nonexistent = 1;
+ int blank = 0;
+ int execloop;
+ int nonexistent_check = 1;
D(("called"));
@@ -694,43 +695,29 @@ _unix_blankpasswd (pam_handle_t *pamh, u
* are equal, making it more difficult to differentiate existing from
* non-existing users.
*/
- while (execloop) {
+ for (execloop = 0; execloop < 2; ++execloop) {
retval = get_pwd_hash(pamh, name, &pwd, &salt);
if (retval == PAM_UNIX_RUN_HELPER) {
- execloop = 0;
- if(nonexistent) {
- get_pwd_hash(pamh, "pam_unix_non_existent:", &pwd, &salt);
- }
- /* salt will not be set here so we can return immediately */
if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS)
- return 1;
- else
- return 0;
+ blank = nonexistent_check;
} else if (retval == PAM_USER_UNKNOWN) {
name = "root";
- nonexistent = 0;
- } else {
- execloop = 0;
+ nonexistent_check = 0;
+ continue;
+ } else if (salt != NULL) {
+ if (strlen(salt) == 0)
+ blank = nonexistent_check;
}
- }
-
- /* Does this user have a password? */
- if (salt == NULL) {
- retval = 0;
- } else {
- if (strlen(salt) == 0)
- retval = 1;
- else
- retval = 0;
+ name = "pam_unix_non_existent:";
+ /* non-existent user check will not affect the blank value */
}
/* tidy up */
-
if (salt)
_pam_delete(salt);
- return retval;
+ return blank;
}
int _unix_verify_password(pam_handle_t * pamh, const char *name

View File

@ -0,0 +1,12 @@
diff -up Linux-PAM-1.3.1/modules/pam_unix/pam_unix_acct.c.unix-init-daysleft Linux-PAM-1.3.1/modules/pam_unix/pam_unix_acct.c
--- Linux-PAM-1.3.1/modules/pam_unix/pam_unix_acct.c.unix-init-daysleft 2020-11-11 09:33:02.169597139 +0100
+++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_acct.c 2020-11-11 09:39:33.919570928 +0100
@@ -188,7 +188,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
unsigned long long ctrl;
const void *void_uname;
const char *uname;
- int retval, daysleft;
+ int retval, daysleft = -1;
struct spwd *spent;
struct passwd *pwent;
char buf[256];

View File

@ -3,7 +3,7 @@
Summary: An extensible library which provides authentication for applications
Name: pam
Version: 1.3.1
Release: 22%{?dist}
Release: 30%{?dist}
# The library is BSD licensed with option to relicense as GPLv2+
# - this option is redundant as the BSD license allows that anyway.
# pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+.
@ -60,6 +60,24 @@ Patch48: pam-1.3.1-unix-improve-logging.patch
Patch49: pam-1.3.1-tty-audit-manfix.patch
Patch50: pam-1.3.1-fds-closing.patch
Patch51: pam-1.3.1-authtok-verify-fix.patch
Patch52: pam-1.3.1-add-pam_usertype.patch
Patch53: pam-1.3.1-add-pam_usertype-fix-backport.patch
Patch54: pam-1.3.1-pam_selinux-check-unknown-objects.patch
# Upstreamed
Patch55: pam-1.3.1-determinine-user-exists.patch
# Upstreamed
Patch56: pam-1.3.1-faillock-change-file-permissions.patch
# https://github.com/linux-pam/linux-pam/commit/16cebfeb30a8bd7c7dc269190a054c25b0f8d044
# https://github.com/linux-pam/linux-pam/commit/ad8b6feaf8ea989368676acaea905998a807986e
Patch57: pam-1.3.1-motd-filter-files.patch
# https://github.com/linux-pam/linux-pam/commit/db6b293046aee4735f3aa2d1713742ed4b533219
Patch58: pam-1.3.1-unix-init-daysleft.patch
# https://github.com/linux-pam/linux-pam/commit/9f24bbeeb4fe04bc396898cd9825478ad52c5ac7
Patch59: pam-1.3.1-motd-privilege-message.patch
# https://github.com/linux-pam/linux-pam/commit/30fdfb90d9864bcc254a62760aaa149d373fd4eb
Patch60: pam-1.3.1-unix-blank-check-with-root.patch
# https://github.com/linux-pam/linux-pam/commit/62d826471e87e27b39a36ccbeee58999e2514a92
Patch61: pam-1.3.1-drop-priv-initgroups.patch
%global _pamlibdir %{_libdir}
%global _moduledir %{_libdir}/security
@ -76,6 +94,7 @@ Patch51: pam-1.3.1-authtok-verify-fix.patch
Recommends: cracklib-dicts >= 2.8
Requires: libpwquality >= 0.9.9
BuildRequires: make
BuildRequires: autoconf >= 2.60
BuildRequires: automake, libtool
BuildRequires: bison, flex, sed
@ -150,6 +169,16 @@ cp %{SOURCE18} .
%patch49 -p1 -b .tty-audit-manfix
%patch50 -p1 -b .fds-closing
%patch51 -p1 -b .authtok-verify-fix
%patch52 -p1 -b .add-pam_usertype
%patch53 -p1 -b .add-pam_usertype-backport
%patch54 -p1 -b .pam_selinux-check-unknown-objects
%patch55 -p1 -b .determinine-user-exists
%patch56 -p1 -b .faillock-change-file-permissions
%patch57 -p1 -b .motd-filter-files
%patch58 -p1 -b .unix-init-daysleft
%patch59 -p1 -b .motd-privilege-message
%patch60 -p1 -b .unix-blank-check-with-root
%patch61 -p1 -b .drop-priv-initgroups
autoreconf -i
@ -354,6 +383,7 @@ done
%{_moduledir}/pam_unix_passwd.so
%{_moduledir}/pam_unix_session.so
%{_moduledir}/pam_userdb.so
%{_moduledir}/pam_usertype.so
%{_moduledir}/pam_warn.so
%{_moduledir}/pam_wheel.so
%{_moduledir}/pam_xauth.so
@ -399,6 +429,34 @@ done
%doc doc/specs/rfc86.0.txt
%changelog
* Fri Dec 11 2020 Allison Karlitskaya <allison.karlitskaya@redhat.com> - 1.3.1-30
- libpam: add supplementary groups on priv drop (#1896452)
- Add BuildRequires: make (#1902520)
* Fri Nov 27 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-29
- fix CVE-2020-27780: authentication bypass when the user doesn't exist
and root password is blank (#1901173)
* Wed Nov 11 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-28
- pam_unix: fix missing initialization of daysleft (#1887077)
- pam_motd: change privilege message prompt to default (#1861640)
* Mon Oct 26 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-27
- pam_motd: read motd files with target user credentials skipping unreadable ones (#1861640)
- Clarify upstreamed patches
* Wed Jun 24 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-26
- pam_faillock: change /run/faillock/$USER permissions to 0660 (#1661822)
* Mon Jun 22 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-25
- pam_unix and pam_usertype: avoid determining if user exists (#1629598)
* Mon Mar 9 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-24
- pam_selinux: check unknown object classes or permissions in current policy
* Tue Feb 4 2020 Pavel Březina <pbrezina@redhat.com> - 1.3.1-23
- Add pam_usertype.so
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.3.1-22
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild