summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorTomas Mraz <tm@t8m.info>2006-06-27 12:34:07 +0000
committerTomas Mraz <tm@t8m.info>2006-06-27 12:34:07 +0000
commitabf8754ad5c98462b2134aa339271b52960569c0 (patch)
tree09db681c2ee192a738ec34c6b3bc9aba1e12ecd3 /modules
parentc001cd28e81640b755bc9b6ec56b9005bf40e3c4 (diff)
Relevant BUGIDs:
Purpose of commit: new feature Commit summary: --------------- * modules/pam_keyinit/pam_keyinit.c: New module. * modules/pam_keyinit/pam_keyinit.8: New. * modules/pam_keyinit/pam_keyinit.8.xml: New. * modules/pam_keyinit/README: New. * modules/pam_keyinit/README.xml: New. * modules/pam_keyinit/Makefile.am: New. * modules/pam_keyinit/tst_pam_keyinit: New. * modules/Makefile.am: Added pam_keyinit. * configure.in: Added test for the key mgmt syscall.
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile.am7
-rw-r--r--modules/pam_keyinit/Makefile.am33
-rw-r--r--modules/pam_keyinit/README24
-rw-r--r--modules/pam_keyinit/README.xml41
-rw-r--r--modules/pam_keyinit/pam_keyinit.8133
-rw-r--r--modules/pam_keyinit/pam_keyinit.8.xml241
-rw-r--r--modules/pam_keyinit/pam_keyinit.c209
-rwxr-xr-xmodules/pam_keyinit/tst-pam_keyinit2
8 files changed, 686 insertions, 4 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 075eb58d..9d7a6fcb 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -3,14 +3,13 @@
#
SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \
- pam_env pam_filter pam_ftp pam_group pam_issue pam_lastlog \
- pam_limits pam_listfile pam_localuser pam_mail pam_mkhomedir \
- pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \
+ pam_env pam_filter pam_ftp pam_group pam_issue pam_keyinit \
+ pam_lastlog pam_limits pam_listfile pam_localuser pam_mail \
+ pam_mkhomedir pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \
pam_securetty pam_selinux pam_shells pam_stress pam_succeed_if \
pam_tally pam_time pam_umask pam_unix pam_userdb pam_warn \
pam_wheel pam_xauth pam_exec
-
CLEANFILES = *~
EXTRA_DIST = modules.map
diff --git a/modules/pam_keyinit/Makefile.am b/modules/pam_keyinit/Makefile.am
new file mode 100644
index 00000000..e75106f6
--- /dev/null
+++ b/modules/pam_keyinit/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2006 David Howells <dhowells@redhat.com>
+#
+
+CLEANFILES = *~
+
+EXTRA_DIST = README tst-pam_keyinit
+XMLS = README.xml pam_keyinit.8.xml
+
+if HAVE_KEY_MANAGEMENT
+ man_MANS = pam_keyinit.8
+ TESTS = tst-pam_keyinit
+endif
+
+if ENABLE_REGENERATE_MAN
+noinst_DATA = README
+README: pam_keyinit.8.xml
+-include $(top_srcdir)/Make.xml.rules
+endif
+
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+AM_LDFLAGS = -no-undefined -avoid-version -module \
+ -L$(top_builddir)/libpam -lpam
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+if HAVE_KEY_MANAGEMENT
+ securelib_LTLIBRARIES = pam_keyinit.la
+endif \ No newline at end of file
diff --git a/modules/pam_keyinit/README b/modules/pam_keyinit/README
new file mode 100644
index 00000000..a27077b3
--- /dev/null
+++ b/modules/pam_keyinit/README
@@ -0,0 +1,24 @@
+# $Id$ -*- text -*-
+#
+
+This module makes sure the calling process has its own session keyring rather
+than using the default per-user session keyring.
+
+The following words may be supplied as arguments to the module through the PAM
+configuration scripts:
+
+ (*) "force"
+
+ This will cause the process's current session keyring to be replaced with
+ a new one. If this isn't supplied, a session keyring will only be created
+ if the process doesn't already have its own.
+
+ (*) "revoke"
+
+ If the module actually created a keyring, this will cause that keyring to
+ be revoked on session closure.
+
+ (*) "debug"
+
+ This will cause the module to write some debugging information to the
+ syslog.
diff --git a/modules/pam_keyinit/README.xml b/modules/pam_keyinit/README.xml
new file mode 100644
index 00000000..47659e89
--- /dev/null
+++ b/modules/pam_keyinit/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_keyinit.8.xml">
+-->
+]>
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_keyinit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_keyinit-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_keyinit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_keyinit-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_keyinit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_keyinit-options"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_keyinit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_keyinit-examples"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_keyinit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_keyinit-author"]/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_keyinit/pam_keyinit.8 b/modules/pam_keyinit/pam_keyinit.8
new file mode 100644
index 00000000..40b1e125
--- /dev/null
+++ b/modules/pam_keyinit/pam_keyinit.8
@@ -0,0 +1,133 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "PAM_KEYINIT" 8 "" "" ""
+.SH NAME
+pam_keyinit \- Kernel session keyring initialiser module
+.SH "SYNOPSIS"
+.ad l
+.hy 0
+.HP 15
+\fBpam_keyinit\&.so\fR [debug] [force] [revoke]
+.ad
+.hy
+
+.SH "DESCRIPTION"
+
+.PP
+The pam_keyinit PAM module ensures that the invoking process has a session keyring other than the user default session keyring\&.
+
+.PP
+The session component of the module checks to see if the process's session keyring is the user default, and, if it is, creates a new anonymous session keyring with which to replace it\&.
+
+.PP
+If a new session keyring is created, it will install a link to the user common keyring in the session keyring so that keys common to the user will be automatically accessible through it\&.
+
+.PP
+The session keyring of the invoking process will thenceforth be inherited by all its children unless they override it\&.
+
+.PP
+This module is intended primarily for use by login processes\&. Be aware that after the session keyring has been replaced, the old session keyring and the keys it contains will no longer be accessible\&.
+
+.PP
+This module should not, generally, be invoked by programs like \fIsu\fR, since it is usually desirable for the key set to percolate through to the alternate context\&. The keys have their own permissions system to manage this\&.
+
+.PP
+This module should be included as early as possible in a PAM configuration, so that other PAM modules can attach tokens to the keyring\&.
+
+.PP
+The keyutils package is used to manipulate keys more directly\&. This included in the Fedora Extras 5+ and Red Hat Enterprise Linux 4 U2+ and can also be obtained from:
+
+.PP
+ Keyutils : \fIhttp://people.redhat.com/~dhowells/keyutils/\fR
+
+.SH "OPTIONS"
+
+.TP
+\fBdebug\fR
+Log debug information with \fBsyslog\fR(3)\&.
+
+.TP
+\fBforce\fR
+Causes the session keyring of the invoking process to be replaced unconditionally\&.
+
+.TP
+\fBrevoke\fR
+Causes the session keyring of the invoking process to be revoked when the invoking process exits if the session keyring was created for this process in the first place\&.
+
+.SH "MODULE SERVICES PROVIDED"
+
+.PP
+Only the \fIsession\fR service is supported\&.
+
+.SH "RETURN VALUES"
+
+.TP
+PAM_SUCCESS
+This module will usually return this value
+
+.TP
+PAM_AUTH_ERR
+Authentication failure\&.
+
+.TP
+PAM_BUF_ERR
+Memory buffer error\&.
+
+.TP
+PAM_IGNORE
+The return value should be ignored by PAM dispatch\&.
+
+.TP
+PAM_SERVICE_ERR
+Cannot determine the user name\&.
+
+.TP
+PAM_SESSION_ERR
+This module will return this value if its arguments are invalid or if a system error such as ENOMEM occurs\&.
+
+.TP
+PAM_USER_UNKNOWN
+User not known\&.
+
+.SH "EXAMPLES"
+
+.PP
+Add this line to your login entries to start each login session with its own session keyring:
+
+.nf
+
+session required pam_keyinit\&.so
+
+.fi
+
+
+.PP
+This will prevent keys from one session leaking into another session for the same user\&.
+
+.SH "SEE ALSO"
+
+.PP
+ \fBpam\&.conf\fR(5), \fBpam\&.d\fR(8), \fBpam\fR(8) \fBkeyctl\fR(1)
+
+.SH "AUTHOR"
+
+.PP
+pam_keyinit was written by David Howells, <dhowells@redhat\&.com>\&.
+
diff --git a/modules/pam_keyinit/pam_keyinit.8.xml b/modules/pam_keyinit/pam_keyinit.8.xml
new file mode 100644
index 00000000..c7dddf54
--- /dev/null
+++ b/modules/pam_keyinit/pam_keyinit.8.xml
@@ -0,0 +1,241 @@
+<?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_keyinit">
+
+ <refmeta>
+ <refentrytitle>pam_keyinit</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="pam_keyinit-name">
+ <refname>pam_keyinit</refname>
+ <refpurpose>Kernel session keyring initialiser module</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pam_keyinit-cmdsynopsis">
+ <command>pam_keyinit.so</command>
+ <arg choice="opt">
+ debug
+ </arg>
+ <arg choice="opt">
+ force
+ </arg>
+ <arg choice="opt">
+ revoke
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="pam_keyinit-description">
+ <title>DESCRIPTION</title>
+ <para>
+ The pam_keyinit PAM module ensures that the invoking process has a
+ session keyring other than the user default session keyring.
+ </para>
+ <para>
+ The session component of the module checks to see if the process's
+ session keyring is the user default, and, if it is, creates a new
+ anonymous session keyring with which to replace it.
+ </para>
+ <para>
+ If a new session keyring is created, it will install a link to the user
+ common keyring in the session keyring so that keys common to the user
+ will be automatically accessible through it.
+ </para>
+ <para>
+ The session keyring of the invoking process will thenceforth be inherited
+ by all its children unless they override it.
+ </para>
+ <para>
+ This module is intended primarily for use by login processes. Be aware
+ that after the session keyring has been replaced, the old session keyring
+ and the keys it contains will no longer be accessible.
+ </para>
+ <para>
+ This module should not, generally, be invoked by programs like
+ <emphasis remap='B'>su</emphasis>, since it is usually desirable for the
+ key set to percolate through to the alternate context. The keys have
+ their own permissions system to manage this.
+ </para>
+ <para>
+ This module should be included as early as possible in a PAM
+ configuration, so that other PAM modules can attach tokens to the
+ keyring.
+ </para>
+ <para>
+ The keyutils package is used to manipulate keys more directly. This
+ can be obtained from:
+ </para>
+ <para>
+ <ulink url="http://people.redhat.com/~dhowells/keyutils/">
+ Keyutils
+ </ulink>
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_keyinit-options">
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>debug</option>
+ </term>
+ <listitem>
+ <para>
+ Log debug information with <citerefentry>
+ <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>force</option>
+ </term>
+ <listitem>
+ <para>
+ Causes the session keyring of the invoking process to be replaced
+ unconditionally.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>revoke</option>
+ </term>
+ <listitem>
+ <para>
+ Causes the session keyring of the invoking process to be revoked
+ when the invoking process exits if the session keyring was created
+ for this process in the first place.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_keyinit-services">
+ <title>MODULE SERVICES PROVIDED</title>
+ <para>
+ Only the <emphasis remap='B'>session</emphasis> service is supported.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_keyinit-return_values'>
+ <title>RETURN VALUES</title>
+ <variablelist>
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ This module will usually return this value
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_AUTH_ERR</term>
+ <listitem>
+ <para>
+ Authentication failure.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_BUF_ERR</term>
+ <listitem>
+ <para>
+ Memory buffer error.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_IGNORE</term>
+ <listitem>
+ <para>
+ The return value should be ignored by PAM dispatch.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SERVICE_ERR</term>
+ <listitem>
+ <para>
+ Cannot determine the user name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SESSION_ERR</term>
+ <listitem>
+ <para>
+ This module will return this value if its arguments are invalid or
+ if a system error such as ENOMEM occurs.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_USER_UNKNOWN</term>
+ <listitem>
+ <para>
+ User not known.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='pam_keyinit-examples'>
+ <title>EXAMPLES</title>
+ <para>
+ Add this line to your login entries to start each login session with its
+ own session keyring:
+ <programlisting>
+session required pam_keyinit.so
+ </programlisting>
+ </para>
+ <para>
+ This will prevent keys from one session leaking into another session for
+ the same user.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_keyinit-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_keyinit-author'>
+ <title>AUTHOR</title>
+ <para>
+ pam_keyinit was written by David Howells, &lt;dhowells@redhat.com&gt;.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c
new file mode 100644
index 00000000..363adb58
--- /dev/null
+++ b/modules/pam_keyinit/pam_keyinit.c
@@ -0,0 +1,209 @@
+/* pam_keyinit.c: Initialise the session keyring on login through a PAM module
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "config.h"
+#include <stdarg.h>
+#include <string.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <errno.h>
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+#include <sys/syscall.h>
+
+#define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */
+#define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */
+#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
+
+#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
+#define KEYCTL_JOIN_SESSION_KEYRING 1 /* start named session keyring */
+#define KEYCTL_REVOKE 3 /* revoke a key */
+#define KEYCTL_LINK 8 /* link a key into a keyring */
+
+static int my_session_keyring;
+static int do_revoke;
+static int xdebug = 1;
+
+static void debug(pam_handle_t *pamh, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+static void debug(pam_handle_t *pamh, const char *fmt, ...)
+{
+ va_list va;
+
+ if (xdebug) {
+ va_start(va, fmt);
+ pam_vsyslog(pamh, LOG_DEBUG, fmt, va);
+ va_end(va);
+ }
+}
+
+static int error(pam_handle_t *pamh, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+static int error(pam_handle_t *pamh, const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ pam_vsyslog(pamh, LOG_ERR, fmt, va);
+ va_end(va);
+
+ return PAM_SESSION_ERR;
+}
+
+/*
+ * initialise the session keyring for this process
+ */
+static int init_keyrings(pam_handle_t *pamh, int force)
+{
+ int session, usession, ret;
+
+ if (!force) {
+ /* get the IDs of the session keyring and the user session
+ * keyring */
+ session = syscall(__NR_keyctl,
+ KEYCTL_GET_KEYRING_ID,
+ KEY_SPEC_SESSION_KEYRING,
+ 0);
+ debug(pamh, "GET SESSION = %d", session);
+ if (session < 0) {
+ /* don't worry about keyrings if facility not
+ * installed */
+ if (errno == ENOSYS)
+ return PAM_SUCCESS;
+ return PAM_SESSION_ERR;
+ }
+
+ usession = syscall(__NR_keyctl,
+ KEYCTL_GET_KEYRING_ID,
+ KEY_SPEC_USER_SESSION_KEYRING,
+ 0);
+ debug(pamh, "GET SESSION = %d", usession);
+ if (usession < 0)
+ return PAM_SESSION_ERR;
+
+ /* if the user session keyring is our keyring, then we don't
+ * need to do anything if we're not forcing */
+ if (session != usession) {
+ do_revoke = 0;
+ return PAM_SUCCESS;
+ }
+ }
+
+ /* create a session keyring, discarding the old one */
+ ret = syscall(__NR_keyctl,
+ KEYCTL_JOIN_SESSION_KEYRING,
+ NULL);
+ debug(pamh, "JOIN = %d", ret);
+ if (ret < 0)
+ return PAM_SESSION_ERR;
+
+ my_session_keyring = ret;
+
+ /* make a link from the session keyring to the user keyring */
+ ret = syscall(__NR_keyctl,
+ KEYCTL_LINK,
+ KEY_SPEC_USER_KEYRING,
+ KEY_SPEC_SESSION_KEYRING);
+
+ return ret < 0 ? PAM_SESSION_ERR : PAM_SUCCESS;
+}
+
+/*
+ * revoke the session keyring for this process
+ */
+static void kill_keyrings(pam_handle_t *pamh)
+{
+ /* revoke the session keyring we created earlier */
+ if (my_session_keyring > 0) {
+ debug(pamh, "REVOKE %d", my_session_keyring);
+
+ syscall(__NR_keyctl,
+ KEYCTL_REVOKE,
+ my_session_keyring);
+ }
+}
+
+/*
+ * open a PAM session by making sure there's a session keyring
+ */
+PAM_EXTERN
+int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
+ int argc, const char **argv)
+{
+ struct passwd *pw;
+ const char *username;
+ int ret, old_uid, uid, old_gid, gid, loop, force = 0;
+
+ for (loop = 0; loop < argc; loop++) {
+ if (strcmp(argv[loop], "force") == 0)
+ force = 1;
+ else if (strcmp(argv[loop], "debug") == 0)
+ xdebug = 1;
+ else if (strcmp(argv[loop], "revoke") == 0)
+ do_revoke = 1;
+ }
+
+ /* look up the target UID */
+ ret = pam_get_user(pamh, &username, "key user");
+ if (ret != PAM_SUCCESS)
+ return ret;
+
+ pw = pam_modutil_getpwnam(pamh, username);
+ if (!pw) {
+ error(pamh, "Unable to look up user \"%s\"\n", username);
+ return PAM_USER_UNKNOWN;
+ }
+
+ uid = pw->pw_uid;
+ old_uid = getuid();
+ gid = pw->pw_gid;
+ old_gid = getgid();
+ debug(pamh, "UID:%d [%d] GID:%d [%d]", uid, old_uid, gid, old_gid);
+
+ /* switch to the real UID and GID so that the keyring ends up owned by
+ * the right user */
+ if (uid != old_uid && setreuid(uid, -1) < 0)
+ return error(pamh, "Unable to change UID to %d temporarily\n", uid);
+
+ if (gid != old_gid && setregid(gid, -1) < 0) {
+ error(pamh, "Unable to change GID to %d temporarily\n", gid);
+ setreuid(old_uid, -1);
+ return PAM_SESSION_ERR;
+ }
+
+ ret = init_keyrings(pamh, force);
+
+ /* return to the orignal UID and GID (probably root) */
+ if (uid != old_uid && setreuid(old_uid, -1) < 0)
+ ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
+
+ if (gid != old_gid && setregid(old_gid, -1) < 0)
+ ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
+
+ return ret;
+}
+
+/*
+ * close a PAM session by revoking the session keyring if requested
+ */
+PAM_EXTERN
+int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
+{
+ if (do_revoke)
+ kill_keyrings(pamh);
+
+ return PAM_SUCCESS;
+}
diff --git a/modules/pam_keyinit/tst-pam_keyinit b/modules/pam_keyinit/tst-pam_keyinit
new file mode 100755
index 00000000..f0a7b9bc
--- /dev/null
+++ b/modules/pam_keyinit/tst-pam_keyinit
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_keyinit.so