Blame SOURCES/pam-1.3.1-pam-usertype.patch

4f62f7
diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype Linux-PAM-1.3.1/configure.ac
4f62f7
--- Linux-PAM-1.3.1/configure.ac.pam-usertype	2020-05-15 10:03:27.247468160 +0200
4f62f7
+++ Linux-PAM-1.3.1/configure.ac	2020-05-15 10:03:27.270468089 +0200
4f62f7
@@ -606,6 +606,27 @@ AC_SUBST([HAVE_KEY_MANAGEMENT], $HAVE_KE
8c7ed8
 
8c7ed8
 AM_CONDITIONAL([HAVE_KEY_MANAGEMENT], [test "$have_key_syscalls" = 1])
8c7ed8
 
8c7ed8
+dnl
8c7ed8
+dnl Get values for default uid ranges in login.defs used in pam_usertype
8c7ed8
+dnl
8c7ed8
+AC_ARG_WITH([uidmin], AS_HELP_STRING([--with-uidmin=<number>],[default value for regular user min uid (1000)]), opt_uidmin=$withval)
8c7ed8
+if test x"$opt_uidmin" == x; then
8c7ed8
+    opt_uidmin=1000
8c7ed8
+fi
8c7ed8
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
8c7ed8
+
8c7ed8
+AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
8c7ed8
+if test x"$opt_sysuidmin" == x; then
8c7ed8
+    opt_sysuidmin=101
8c7ed8
+fi
8c7ed8
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
8c7ed8
+
8c7ed8
+AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
8c7ed8
+if test x"$opt_kerneloverflowuid" == x; then
8c7ed8
+    opt_kerneloverflowuid=65534
8c7ed8
+fi
8c7ed8
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
8c7ed8
+
8c7ed8
 dnl Files to be created from when we run configure
8c7ed8
 AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
8c7ed8
 	libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
4f62f7
@@ -636,6 +657,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
8c7ed8
 	modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \
8c7ed8
 	modules/pam_umask/Makefile \
8c7ed8
 	modules/pam_unix/Makefile modules/pam_userdb/Makefile \
8c7ed8
+	modules/pam_usertype/Makefile \
8c7ed8
 	modules/pam_warn/Makefile modules/pam_wheel/Makefile \
8c7ed8
 	modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
8c7ed8
 	doc/man/Makefile doc/sag/Makefile doc/adg/Makefile \
4f62f7
diff -up Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/Makefile.am
4f62f7
--- Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype	2020-05-15 10:03:27.247468160 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/Makefile.am	2020-05-15 10:03:27.270468089 +0200
4f62f7
@@ -12,7 +12,7 @@ SUBDIRS = pam_access pam_cracklib pam_de
8c7ed8
 	pam_selinux pam_sepermit pam_shells pam_stress \
8c7ed8
 	pam_succeed_if pam_time pam_timestamp \
8c7ed8
 	pam_tty_audit pam_umask \
8c7ed8
-	pam_unix pam_userdb pam_warn pam_wheel pam_xauth
8c7ed8
+	pam_unix pam_userdb pam_usertype pam_warn pam_wheel pam_xauth
8c7ed8
 
8c7ed8
 CLEANFILES = *~
8c7ed8
 
4f62f7
diff -up Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am
4f62f7
--- Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype	2020-05-15 10:03:27.270468089 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am	2020-05-15 10:03:27.270468089 +0200
8c7ed8
@@ -0,0 +1,34 @@
8c7ed8
+#
8c7ed8
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
8c7ed8
+# Copyright (c) 2020 Red Hat, Inc.
8c7ed8
+#
8c7ed8
+
8c7ed8
+CLEANFILES = *~
8c7ed8
+MAINTAINERCLEANFILES = $(MANS) README
8c7ed8
+
8c7ed8
+EXTRA_DIST = README ${MANS} ${XMLS} tst-pam_usertype
8c7ed8
+
8c7ed8
+TESTS = tst-pam_usertype
8c7ed8
+
8c7ed8
+man_MANS = pam_usertype.8
8c7ed8
+
8c7ed8
+XMLS = README.xml pam_usertype.8.xml
8c7ed8
+
8c7ed8
+securelibdir = $(SECUREDIR)
8c7ed8
+secureconfdir = $(SCONFIGDIR)
8c7ed8
+
8c7ed8
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
8c7ed8
+	$(WARN_CFLAGS)
8c7ed8
+AM_LDFLAGS = -no-undefined -avoid-version -module
8c7ed8
+if HAVE_VERSIONING
8c7ed8
+  AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
8c7ed8
+endif
8c7ed8
+
8c7ed8
+securelib_LTLIBRARIES = pam_usertype.la
8c7ed8
+pam_usertype_la_LIBADD = $(top_builddir)/libpam/libpam.la
8c7ed8
+
8c7ed8
+if ENABLE_REGENERATE_MAN
8c7ed8
+noinst_DATA = README
8c7ed8
+README: pam_usertype.8.xml
8c7ed8
+-include $(top_srcdir)/Make.xml.rules
8c7ed8
+endif
4f62f7
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml
4f62f7
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype	2020-05-15 10:03:27.270468089 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml	2020-05-15 10:03:27.270468089 +0200
8c7ed8
@@ -0,0 +1,170 @@
8c7ed8
+
8c7ed8
+
8c7ed8
+        "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
8c7ed8
+
8c7ed8
+
8c7ed8
+<refentry id='pam_usertype'>
8c7ed8
+  <refmeta>
8c7ed8
+    <refentrytitle>pam_usertype</refentrytitle>
8c7ed8
+    <manvolnum>8</manvolnum>
8c7ed8
+    <refmiscinfo class='sectdesc'>Linux-PAM</refmiscinfo>
8c7ed8
+  </refmeta>
8c7ed8
+
8c7ed8
+  <refnamediv id='pam_usertype-name'>
8c7ed8
+    <refname>pam_usertype</refname>
8c7ed8
+    <refpurpose>check if the authenticated user is a system or regular account</refpurpose>
8c7ed8
+  </refnamediv>
8c7ed8
+
8c7ed8
+
8c7ed8
+  <refsynopsisdiv>
8c7ed8
+    <cmdsynopsis id='pam_usertype-cmdsynopsis'>
8c7ed8
+      <command>pam_usertype.so</command>
8c7ed8
+      <arg choice='opt' rep='repeat'><replaceable>flag</replaceable></arg>
8c7ed8
+      <arg choice='req'><replaceable>condition</replaceable></arg>
8c7ed8
+    </cmdsynopsis>
8c7ed8
+  </refsynopsisdiv>
8c7ed8
+
8c7ed8
+
8c7ed8
+  <refsect1 id='pam_usertype-description'>
8c7ed8
+    <title>DESCRIPTION</title>
8c7ed8
+    <para>
8c7ed8
+      pam_usertype.so is designed to succeed or fail authentication
8c7ed8
+      based on type of the account of the authenticated user.
8c7ed8
+      The type of the account is decided with help of
8c7ed8
+      <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
8c7ed8
+      settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
8c7ed8
+      whether to load other modules based on this test.
8c7ed8
+    </para>
8c7ed8
+
8c7ed8
+    <para>
8c7ed8
+      The module should be given only one condition as module argument.
8c7ed8
+      Authentication will succeed only if the condition is met.
8c7ed8
+    </para>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+  <refsect1 id="pam_usertype-options">
8c7ed8
+    <title>OPTIONS</title>
8c7ed8
+    <para>
8c7ed8
+      The following <emphasis>flag</emphasis>s are supported:
8c7ed8
+    </para>
8c7ed8
+
8c7ed8
+    <variablelist>
8c7ed8
+      <varlistentry>
8c7ed8
+        <term><option>use_uid</option></term>
8c7ed8
+        <listitem>
8c7ed8
+          <para>
8c7ed8
+            Evaluate conditions using the account of the user whose UID
8c7ed8
+            the application is running under instead of the user being
8c7ed8
+            authenticated.
8c7ed8
+          </para>
8c7ed8
+        </listitem>
8c7ed8
+      </varlistentry>
8c7ed8
+      <varlistentry>
8c7ed8
+        <term><option>audit</option></term>
8c7ed8
+        <listitem>
8c7ed8
+          <para>
8c7ed8
+            Log unknown users to the system log.
8c7ed8
+          </para>
8c7ed8
+        </listitem>
8c7ed8
+      </varlistentry>
8c7ed8
+    </variablelist>
8c7ed8
+
8c7ed8
+    <para>
8c7ed8
+      Available <emphasis>condition</emphasis>s are:
8c7ed8
+    </para>
8c7ed8
+
8c7ed8
+    <variablelist>
8c7ed8
+      <varlistentry>
8c7ed8
+        <term><option>issystem</option></term>
8c7ed8
+        <listitem>
8c7ed8
+          <para>Succeed if the user is a system user.</para>
8c7ed8
+        </listitem>
8c7ed8
+      </varlistentry>
8c7ed8
+      <varlistentry>
8c7ed8
+        <term><option>isregular</option></term>
8c7ed8
+        <listitem>
8c7ed8
+          <para>Succeed if the user is a regular user.</para>
8c7ed8
+        </listitem>
8c7ed8
+      </varlistentry>
8c7ed8
+    </variablelist>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+  <refsect1 id="pam_usertype-types">
8c7ed8
+    <title>MODULE TYPES PROVIDED</title>
8c7ed8
+    <para>
8c7ed8
+      All module types (<option>account</option>, <option>auth</option>,
8c7ed8
+      <option>password</option> and <option>session</option>) are provided.
8c7ed8
+    </para>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+  <refsect1 id='pam_usertype-return_values'>
8c7ed8
+    <title>RETURN VALUES</title>
8c7ed8
+     <variablelist>
8c7ed8
+
8c7ed8
+        <varlistentry>
8c7ed8
+          <term>PAM_SUCCESS</term>
8c7ed8
+          <listitem>
8c7ed8
+            <para>
8c7ed8
+              The condition was true.
8c7ed8
+            </para>
8c7ed8
+          </listitem>
8c7ed8
+        </varlistentry>
8c7ed8
+
8c7ed8
+        <varlistentry>
8c7ed8
+          <term>PAM_AUTH_ERR</term>
8c7ed8
+          <listitem>
8c7ed8
+            <para>
8c7ed8
+              The condition was false.
8c7ed8
+            </para>
8c7ed8
+          </listitem>
8c7ed8
+        </varlistentry>
8c7ed8
+
8c7ed8
+        <varlistentry>
8c7ed8
+          <term>PAM_SERVICE_ERR</term>
8c7ed8
+          <listitem>
8c7ed8
+            <para>
8c7ed8
+              A service error occurred or the arguments can't be
8c7ed8
+              parsed correctly.
8c7ed8
+            </para>
8c7ed8
+          </listitem>
8c7ed8
+        </varlistentry>
8c7ed8
+
8c7ed8
+        <varlistentry>
8c7ed8
+          <term>PAM_USER_UNKNOWN</term>
8c7ed8
+          <listitem>
8c7ed8
+            <para>
8c7ed8
+              User was not found.
8c7ed8
+            </para>
8c7ed8
+          </listitem>
8c7ed8
+        </varlistentry>
8c7ed8
+    </variablelist>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+
8c7ed8
+  <refsect1 id='pam_usertype-examples'>
8c7ed8
+    <title>EXAMPLES</title>
8c7ed8
+    <para>
8c7ed8
+      Skip remaining modules if the user is a system user:
8c7ed8
+    </para>
8c7ed8
+    <programlisting>
8c7ed8
+account sufficient pam_usertype.so issystem
8c7ed8
+    </programlisting>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+  <refsect1 id='pam_usertype-see_also'>
8c7ed8
+    <title>SEE ALSO</title>
8c7ed8
+    <para>
8c7ed8
+      <citerefentry>
8c7ed8
+        <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
8c7ed8
+      </citerefentry>,
8c7ed8
+      <citerefentry>
8c7ed8
+        <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
8c7ed8
+      </citerefentry>
8c7ed8
+    </para>
8c7ed8
+  </refsect1>
8c7ed8
+
8c7ed8
+  <refsect1 id='pam_usertype-author'>
8c7ed8
+    <title>AUTHOR</title>
8c7ed8
+    <para>Pavel Březina <pbrezina@redhat.com></para>
8c7ed8
+  </refsect1>
8c7ed8
+</refentry>
4f62f7
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
4f62f7
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype	2020-05-15 10:03:27.270468089 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c	2020-05-15 10:16:08.053198025 +0200
4f62f7
@@ -0,0 +1,394 @@
8c7ed8
+/******************************************************************************
8c7ed8
+ * Check user type based on login.defs.
8c7ed8
+ *
8c7ed8
+ * Copyright (c) 2020 Red Hat, Inc.
8c7ed8
+ * Written by Pavel Březina <pbrezina@redhat.com>
8c7ed8
+ *
8c7ed8
+ * Redistribution and use in source and binary forms, with or without
8c7ed8
+ * modification, are permitted provided that the following conditions
8c7ed8
+ * are met:
8c7ed8
+ * 1. Redistributions of source code must retain the above copyright
8c7ed8
+ *    notice, and the entire permission notice in its entirety,
8c7ed8
+ *    including the disclaimer of warranties.
8c7ed8
+ * 2. Redistributions in binary form must reproduce the above copyright
8c7ed8
+ *    notice, this list of conditions and the following disclaimer in the
8c7ed8
+ *    documentation and/or other materials provided with the distribution.
8c7ed8
+ * 3. The name of the author may not be used to endorse or promote
8c7ed8
+ *    products derived from this software without specific prior
8c7ed8
+ *    written permission.
8c7ed8
+ *
8c7ed8
+ * ALTERNATIVELY, this product may be distributed under the terms of
8c7ed8
+ * the GNU Public License, in which case the provisions of the GPL are
8c7ed8
+ * required INSTEAD OF the above restrictions.  (This clause is
8c7ed8
+ * necessary due to a potential bad interaction between the GPL and
8c7ed8
+ * the restrictions contained in a BSD-style copyright.)
8c7ed8
+ *
8c7ed8
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
8c7ed8
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8c7ed8
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
8c7ed8
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
8c7ed8
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
8c7ed8
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
8c7ed8
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8c7ed8
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
8c7ed8
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8c7ed8
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
8c7ed8
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
8c7ed8
+ *
8c7ed8
+ */
8c7ed8
+
8c7ed8
+#include "config.h"
8c7ed8
+
8c7ed8
+#include <sys/types.h>
8c7ed8
+#include <stdlib.h>
8c7ed8
+#include <string.h>
8c7ed8
+#include <syslog.h>
8c7ed8
+#include <unistd.h>
8c7ed8
+#include <pwd.h>
8c7ed8
+#include <ctype.h>
8c7ed8
+#include <errno.h>
8c7ed8
+#include <stdio.h>
8c7ed8
+
8c7ed8
+#define PAM_SM_AUTH
8c7ed8
+#define PAM_SM_ACCOUNT
8c7ed8
+#define PAM_SM_SESSION
8c7ed8
+#define PAM_SM_PASSWORD
8c7ed8
+
8c7ed8
+#include <security/pam_modules.h>
8c7ed8
+#include <security/pam_modutil.h>
8c7ed8
+#include <security/pam_ext.h>
8c7ed8
+
8c7ed8
+#define LOGIN_DEFS "/etc/login.defs"
8c7ed8
+
8c7ed8
+enum pam_usertype_op {
8c7ed8
+    OP_IS_SYSTEM,
8c7ed8
+    OP_IS_REGULAR,
8c7ed8
+
8c7ed8
+    OP_SENTINEL
8c7ed8
+};
8c7ed8
+
8c7ed8
+struct pam_usertype_opts {
8c7ed8
+    enum pam_usertype_op op;
8c7ed8
+    int use_uid;
8c7ed8
+    int audit;
8c7ed8
+};
8c7ed8
+
8c7ed8
+static int
8c7ed8
+pam_usertype_parse_args(struct pam_usertype_opts *opts,
8c7ed8
+                        pam_handle_t *pamh,
8c7ed8
+                        int argc,
8c7ed8
+                        const char **argv)
8c7ed8
+{
8c7ed8
+    int i;
8c7ed8
+
8c7ed8
+    memset(opts, 0, sizeof(struct pam_usertype_opts));
8c7ed8
+    opts->op = OP_SENTINEL;
8c7ed8
+
8c7ed8
+    for (i = 0; i < argc; i++) {
8c7ed8
+        if (strcmp(argv[i], "use_uid") == 0) {
8c7ed8
+            opts->use_uid = 1;
8c7ed8
+        } else if (strcmp(argv[i], "audit") == 0) {
8c7ed8
+            opts->audit = 1;
8c7ed8
+        } else if (strcmp(argv[i], "issystem") == 0) {
8c7ed8
+            opts->op = OP_IS_SYSTEM;
8c7ed8
+        } else if (strcmp(argv[i], "isregular") == 0) {
8c7ed8
+            opts->op = OP_IS_REGULAR;
8c7ed8
+        } else {
8c7ed8
+            pam_syslog(pamh, LOG_WARNING, "Unknown argument: %s", argv[i]);
8c7ed8
+            /* Just continue. */
8c7ed8
+        }
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    if (opts->op == OP_SENTINEL) {
8c7ed8
+        pam_syslog(pamh, LOG_ERR, "Operation not specified");
8c7ed8
+        return PAM_SERVICE_ERR;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    return PAM_SUCCESS;
8c7ed8
+}
8c7ed8
+
8c7ed8
+static int
8c7ed8
+pam_usertype_get_uid(struct pam_usertype_opts *opts,
8c7ed8
+                     pam_handle_t *pamh,
8c7ed8
+                     uid_t *_uid)
8c7ed8
+{
8c7ed8
+    struct passwd *pwd;
8c7ed8
+    const void *prompt;
8c7ed8
+    const char *username;
8c7ed8
+    int ret;
8c7ed8
+
8c7ed8
+    /* Get uid of user that runs the application. */
8c7ed8
+    if (opts->use_uid) {
8c7ed8
+        pwd = pam_modutil_getpwuid(pamh, getuid());
8c7ed8
+        if (pwd == NULL) {
8c7ed8
+            pam_syslog(pamh, LOG_ERR,
8c7ed8
+                       "error retrieving information about user %lu",
8c7ed8
+                       (unsigned long)getuid());
8c7ed8
+            return PAM_USER_UNKNOWN;
8c7ed8
+        }
8c7ed8
+
8c7ed8
+        *_uid = pwd->pw_uid;
8c7ed8
+        return PAM_SUCCESS;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    /* Get uid of user that is being authenticated. */
8c7ed8
+    ret = pam_get_item(pamh, PAM_USER_PROMPT, &prompt);
8c7ed8
+    if (ret != PAM_SUCCESS || prompt == NULL || strlen(prompt) == 0) {
8c7ed8
+        prompt = "login: ";
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    ret = pam_get_user(pamh, &username, prompt);
8c7ed8
+    if (ret != PAM_SUCCESS || username == NULL) {
8c7ed8
+        pam_syslog(pamh, LOG_ERR, "error retrieving user name: %s",
8c7ed8
+                   pam_strerror(pamh, ret));
8c7ed8
+        return ret;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    pwd = pam_modutil_getpwnam(pamh, username);
8c7ed8
+    if (pwd == NULL) {
8c7ed8
+        if (opts->audit) {
8c7ed8
+            pam_syslog(pamh, LOG_NOTICE,
8c7ed8
+                       "error retrieving information about user %s", username);
8c7ed8
+        }
8c7ed8
+
8c7ed8
+        return PAM_USER_UNKNOWN;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    *_uid = pwd->pw_uid;
8c7ed8
+
8c7ed8
+    return PAM_SUCCESS;
8c7ed8
+}
8c7ed8
+
8c7ed8
+#define MAX_UID_VALUE 0xFFFFFFFFUL
8c7ed8
+
8c7ed8
+/* lookup a value for key in login.defs file or similar key value format */
8c7ed8
+char *
8c7ed8
+pam_usertype_search_key(pam_handle_t *pamh UNUSED,
8c7ed8
+		       const char *file_name,
8c7ed8
+		       const char *key)
8c7ed8
+{
8c7ed8
+	FILE *fp;
8c7ed8
+	char *buf = NULL;
8c7ed8
+	size_t buflen = 0;
8c7ed8
+	char *retval = NULL;
8c7ed8
+
8c7ed8
+	fp = fopen(file_name, "r");
8c7ed8
+	if (NULL == fp)
8c7ed8
+		return NULL;
8c7ed8
+
8c7ed8
+	while (!feof(fp)) {
8c7ed8
+		char *tmp, *cp;
8c7ed8
+#if defined(HAVE_GETLINE)
8c7ed8
+		ssize_t n = getline(&buf, &buflen, fp);
8c7ed8
+#elif defined (HAVE_GETDELIM)
8c7ed8
+		ssize_t n = getdelim(&buf, &buflen, '\n', fp);
8c7ed8
+#else
8c7ed8
+		ssize_t n;
8c7ed8
+
8c7ed8
+		if (buf == NULL) {
8c7ed8
+			buflen = BUF_SIZE;
8c7ed8
+			buf = malloc(buflen);
8c7ed8
+			if (buf == NULL) {
8c7ed8
+				fclose(fp);
8c7ed8
+				return NULL;
8c7ed8
+			}
8c7ed8
+		}
8c7ed8
+		buf[0] = '\0';
8c7ed8
+		if (fgets(buf, buflen - 1, fp) == NULL)
8c7ed8
+			break;
8c7ed8
+		else if (buf != NULL)
8c7ed8
+			n = strlen(buf);
8c7ed8
+		else
8c7ed8
+			n = 0;
8c7ed8
+#endif /* HAVE_GETLINE / HAVE_GETDELIM */
8c7ed8
+		cp = buf;
8c7ed8
+
8c7ed8
+		if (n < 1)
8c7ed8
+			break;
8c7ed8
+		if (cp[n - 1] == '\n')
8c7ed8
+			cp[n - 1] = '\0';
8c7ed8
+
8c7ed8
+		tmp = strchr(cp, '#');  /* remove comments */
8c7ed8
+		if (tmp)
8c7ed8
+			*tmp = '\0';
8c7ed8
+		while (isspace((int)*cp))    /* remove spaces and tabs */
8c7ed8
+			++cp;
8c7ed8
+		if (*cp == '\0')        /* ignore empty lines */
8c7ed8
+			continue;
8c7ed8
+
8c7ed8
+		tmp = strsep (&cp, " \t=");
8c7ed8
+		if (cp != NULL)
8c7ed8
+			while (isspace((int)*cp) || *cp == '=')
8c7ed8
+				++cp;
8c7ed8
+		else
8c7ed8
+			cp = "";
8c7ed8
+
8c7ed8
+		if (strcasecmp(tmp, key) == 0) {
8c7ed8
+			retval = strdup(cp);
8c7ed8
+			break;
8c7ed8
+		}
8c7ed8
+	}
8c7ed8
+	fclose(fp);
8c7ed8
+
8c7ed8
+	free(buf);
8c7ed8
+
8c7ed8
+	return retval;
8c7ed8
+}
8c7ed8
+
8c7ed8
+static uid_t
8c7ed8
+pam_usertype_get_id(pam_handle_t *pamh,
8c7ed8
+                    const char *key,
8c7ed8
+                    uid_t default_value)
8c7ed8
+{
8c7ed8
+    unsigned long ul;
8c7ed8
+    char *value;
8c7ed8
+    char *ep;
8c7ed8
+    uid_t uid;
8c7ed8
+
8c7ed8
+    value = pam_usertype_search_key(pamh, LOGIN_DEFS, key);
8c7ed8
+    if (value == NULL) {
8c7ed8
+        return default_value;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    /* taken from get_lastlog_uid_max() */
8c7ed8
+    ep = value + strlen(value);
8c7ed8
+    while (ep > value && isspace(*(--ep))) {
8c7ed8
+        *ep = '\0';
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    errno = 0;
8c7ed8
+    ul = strtoul(value, &ep, 10);
8c7ed8
+    if (!(ul >= MAX_UID_VALUE
8c7ed8
+        || (uid_t)ul >= MAX_UID_VALUE
8c7ed8
+        || (errno != 0 && ul == 0)
8c7ed8
+        || value == ep
8c7ed8
+        || *ep != '\0')) {
8c7ed8
+        uid = (uid_t)ul;
8c7ed8
+    } else {
8c7ed8
+        uid = default_value;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    free(value);
8c7ed8
+
8c7ed8
+    return uid;
8c7ed8
+}
8c7ed8
+
8c7ed8
+static int
8c7ed8
+pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
8c7ed8
+{
8c7ed8
+    uid_t uid_min;
8c7ed8
+    uid_t sys_min;
8c7ed8
+    uid_t sys_max;
8c7ed8
+
8c7ed8
+    if (uid == (uid_t)-1) {
8c7ed8
+        pam_syslog(pamh, LOG_WARNING, "invalid uid");
8c7ed8
+        return PAM_USER_UNKNOWN;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    if (uid <= 99) {
8c7ed8
+        /* Reserved. */
8c7ed8
+        return PAM_SUCCESS;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    if (uid == PAM_USERTYPE_OVERFLOW_UID) {
8c7ed8
+        /* nobody */
8c7ed8
+        return PAM_SUCCESS;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
8c7ed8
+    sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
8c7ed8
+    sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
8c7ed8
+
8c7ed8
+    return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
8c7ed8
+}
8c7ed8
+
8c7ed8
+static int
8c7ed8
+pam_usertype_is_regular(pam_handle_t *pamh, uid_t uid)
8c7ed8
+{
8c7ed8
+    int ret;
8c7ed8
+
8c7ed8
+    ret = pam_usertype_is_system(pamh, uid);
8c7ed8
+    switch (ret) {
8c7ed8
+    case PAM_SUCCESS:
8c7ed8
+        return PAM_AUTH_ERR;
8c7ed8
+    case PAM_USER_UNKNOWN:
8c7ed8
+        return PAM_USER_UNKNOWN;
8c7ed8
+    default:
8c7ed8
+        return PAM_SUCCESS;
8c7ed8
+    }
8c7ed8
+}
8c7ed8
+
8c7ed8
+static int
8c7ed8
+pam_usertype_evaluate(struct pam_usertype_opts *opts,
8c7ed8
+                      pam_handle_t *pamh,
8c7ed8
+                      uid_t uid)
8c7ed8
+{
8c7ed8
+    switch (opts->op) {
8c7ed8
+    case OP_IS_SYSTEM:
8c7ed8
+        return pam_usertype_is_system(pamh, uid);
8c7ed8
+    case OP_IS_REGULAR:
8c7ed8
+        return pam_usertype_is_regular(pamh, uid);
8c7ed8
+    default:
8c7ed8
+        pam_syslog(pamh, LOG_ERR, "Unknown operation: %d", opts->op);
8c7ed8
+        return PAM_SERVICE_ERR;
8c7ed8
+    }
8c7ed8
+}
8c7ed8
+
8c7ed8
+/**
8c7ed8
+ * Arguments:
8c7ed8
+ * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
8c7ed8
+ * - isregular: not issystem
8c7ed8
+ * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
8c7ed8
+ * - audit: log unknown users to syslog
8c7ed8
+ */
8c7ed8
+int
8c7ed8
+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
8c7ed8
+                    int argc, const char **argv)
8c7ed8
+{
8c7ed8
+    struct pam_usertype_opts opts;
8c7ed8
+    uid_t uid;
8c7ed8
+    int ret;
8c7ed8
+
8c7ed8
+    ret = pam_usertype_parse_args(&opts, pamh, argc, argv);
8c7ed8
+    if (ret != PAM_SUCCESS) {
8c7ed8
+        return ret;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    ret = pam_usertype_get_uid(&opts, pamh, &uid);
8c7ed8
+    if (ret != PAM_SUCCESS) {
8c7ed8
+        return ret;
8c7ed8
+    }
8c7ed8
+
8c7ed8
+    return pam_usertype_evaluate(&opts, pamh, uid);
8c7ed8
+}
8c7ed8
+
8c7ed8
+int
8c7ed8
+pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
8c7ed8
+               int argc UNUSED, const char **argv UNUSED)
8c7ed8
+{
8c7ed8
+	return PAM_IGNORE;
8c7ed8
+}
8c7ed8
+
8c7ed8
+int
8c7ed8
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
8c7ed8
+{
8c7ed8
+	return pam_sm_authenticate(pamh, flags, argc, argv);
8c7ed8
+}
8c7ed8
+
8c7ed8
+int
8c7ed8
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
8c7ed8
+{
8c7ed8
+	return pam_sm_authenticate(pamh, flags, argc, argv);
8c7ed8
+}
8c7ed8
+
8c7ed8
+int
8c7ed8
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
8c7ed8
+{
8c7ed8
+	return pam_sm_authenticate(pamh, flags, argc, argv);
8c7ed8
+}
8c7ed8
+
8c7ed8
+int
8c7ed8
+pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
8c7ed8
+{
8c7ed8
+	return pam_sm_authenticate(pamh, flags, argc, argv);
8c7ed8
+}
4f62f7
diff -up Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/README.xml
4f62f7
--- Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype	2020-05-15 10:03:27.270468089 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/pam_usertype/README.xml	2020-05-15 10:03:27.270468089 +0200
4f62f7
@@ -0,0 +1,41 @@
4f62f7
+
4f62f7
+
4f62f7
+"http://www.docbook.org/xml/4.3/docbookx.dtd"
4f62f7
+[
4f62f7
+
4f62f7
+
4f62f7
+-->
4f62f7
+]>
4f62f7
+
4f62f7
+<article>
4f62f7
+
4f62f7
+  <articleinfo>
4f62f7
+
4f62f7
+    <title>
4f62f7
+      
4f62f7
+      href="pam_usertype.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_usertype-name"]/*)'/>
4f62f7
+    </title>
4f62f7
+
4f62f7
+  </articleinfo>
4f62f7
+
4f62f7
+  <section>
4f62f7
+    
4f62f7
+      href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-description"]/*)'/>
4f62f7
+  </section>
4f62f7
+
4f62f7
+  <section>
4f62f7
+    
4f62f7
+      href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-options"]/*)'/>
4f62f7
+  </section>
4f62f7
+
4f62f7
+  <section>
4f62f7
+    
4f62f7
+      href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-examples"]/*)'/>
4f62f7
+  </section>
4f62f7
+
4f62f7
+  <section>
4f62f7
+    
4f62f7
+      href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-author"]/*)'/>
4f62f7
+  </section>
4f62f7
+
4f62f7
+</article>
4f62f7
diff -up Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype
4f62f7
--- Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype	2020-05-15 10:03:27.270468089 +0200
4f62f7
+++ Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype	2020-05-15 10:03:27.270468089 +0200
8c7ed8
@@ -0,0 +1,2 @@
8c7ed8
+#!/bin/sh
8c7ed8
+../../tests/tst-dlopen .libs/pam_usertype.so