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