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

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