add pam_usertype
This commit is contained in:
parent
966d010ebd
commit
a346ac13e2
126
pam-1.3.1-add-pam_usertype-fix-backport.patch
Normal file
126
pam-1.3.1-add-pam_usertype-fix-backport.patch
Normal 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
|
||||
|
684
pam-1.3.1-add-pam_usertype.patch
Normal file
684
pam-1.3.1-add-pam_usertype.patch
Normal 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 <pbrezina@redhat.com></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
|
||||
|
10
pam.spec
10
pam.spec
@ -3,7 +3,7 @@
|
||||
Summary: An extensible library which provides authentication for applications
|
||||
Name: pam
|
||||
Version: 1.3.1
|
||||
Release: 22%{?dist}
|
||||
Release: 23%{?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,8 @@ 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
|
||||
|
||||
%global _pamlibdir %{_libdir}
|
||||
%global _moduledir %{_libdir}/security
|
||||
@ -150,6 +152,8 @@ 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
|
||||
|
||||
autoreconf -i
|
||||
|
||||
@ -354,6 +358,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 +404,9 @@ done
|
||||
%doc doc/specs/rfc86.0.txt
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user