summaryrefslogtreecommitdiff
path: root/modules/pam_tty_audit
diff options
context:
space:
mode:
authorTomas Mraz <tm@t8m.info>2007-12-05 20:08:57 +0000
committerTomas Mraz <tm@t8m.info>2007-12-05 20:08:57 +0000
commitd89432f7266106f61532115ac0fcf25d8167afa1 (patch)
treec0a8bfac842a17ce91a4b16cde91eafe3bb52cf0 /modules/pam_tty_audit
parent39483af547d33022ff9e18b741165f0551bdc090 (diff)
Relevant BUGIDs:
Purpose of commit: new feature Commit summary: --------------- 2007-12-05 Miloslav Trmac <mitr@redhat.com> * configure.in: Add test for audit_tty_status struct. Add pam_tty_audit module. * libpam/pam_static_modules.h: Add pam_tty_audit module. * modules/pam_tty_audit/Makefile.am: New file. * modules/pam_tty_audit/README.xml: Likewise. * modules/pam_tty_audit/pam_tty_audit.8.xml: Likewise. * modules/pam_tty_audit/pam_tty_audit.c: Likewise.
Diffstat (limited to 'modules/pam_tty_audit')
-rw-r--r--modules/pam_tty_audit/Makefile.am30
-rw-r--r--modules/pam_tty_audit/README.xml36
-rw-r--r--modules/pam_tty_audit/pam_tty_audit.8.xml120
-rw-r--r--modules/pam_tty_audit/pam_tty_audit.c348
4 files changed, 534 insertions, 0 deletions
diff --git a/modules/pam_tty_audit/Makefile.am b/modules/pam_tty_audit/Makefile.am
new file mode 100644
index 00000000..5bb64585
--- /dev/null
+++ b/modules/pam_tty_audit/Makefile.am
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
+#
+
+CLEANFILES = *~
+
+EXTRA_DIST = README $(MANS) $(XMLS)
+
+man_MANS = pam_tty_audit.8
+XMLS = README.xml pam_tty_audit.8.xml
+
+securelibdir = $(SECUREDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+if HAVE_AUDIT_TTY_STATUS
+ pam_tty_audit_la_LIBADD = -L$(top_builddir)/libpam -lpam
+ securelib_LTLIBRARIES = pam_tty_audit.la
+endif
+
+if ENABLE_REGENERATE_MAN
+noinst_DATA = README
+README: pam_tty_audit.8.xml
+-include $(top_srcdir)/Make.xml.rules
+endif
+
diff --git a/modules/pam_tty_audit/README.xml b/modules/pam_tty_audit/README.xml
new file mode 100644
index 00000000..85b27733
--- /dev/null
+++ b/modules/pam_tty_audit/README.xml
@@ -0,0 +1,36 @@
+<?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">
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tty_audit-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-options"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-examples"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refsect1[@id = "pam_tty_audit-author"]/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml
new file mode 100644
index 00000000..7842ac66
--- /dev/null
+++ b/modules/pam_tty_audit/pam_tty_audit.8.xml
@@ -0,0 +1,120 @@
+<?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_tty_audit">
+
+ <refmeta>
+ <refentrytitle>pam_tty_audit</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="pam_tty_audit-name">
+ <refname>pam_tty_audit</refname>
+ <refpurpose>Enable or disable TTY auditing for specified users</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pam_tty_audit-cmdsynopsis">
+ <command>pam_tty_audit.so</command>
+ <arg choice="opt">
+ disable=<replaceable>usernames</replaceable>
+ </arg>
+ <arg choice="opt">
+ enable=<replaceable>usernames</replaceable>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="pam_tty_audit-description">
+ <title>DESCRIPTION</title>
+ <para>
+ The pam_tty_audit PAM module is used to enable or disable TTY auditing.
+ By default, the kernel does not audit input on any TTY.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_tty_audit-options">
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term>
+ <option>disable=<replaceable>usernames</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ For each user matching one of comma-separated
+ <option><replaceable>usernames</replaceable></option>, disable
+ TTY auditing. This overrides any previous <option>enable</option>
+ option for the same user name on the command line.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>enable=<replaceable>usernames</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ For each user matching one of comma-separated
+ <option><replaceable>usernames</replaceable></option>, enable
+ TTY auditing. This overrides any previous <option>disable</option>
+ option for the same user name on the command line.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_tty_audit-services">
+ <title>MODULE SERVICES PROVIDED</title>
+ <para>
+ Only the <emphasis remap='B'>session</emphasis> service is supported.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_tty_audit-return_values'>
+ <title>RETURN VALUES</title>
+ <variablelist>
+ <varlistentry>
+ <term>PAM_SESSION_ERR</term>
+ <listitem>
+ <para>
+ Error reading or modifying the TTY audit flag. See the system log
+ for more details.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ Success.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='pam_tty_audit-examples'>
+ <title>EXAMPLES</title>
+ <para>
+ Audit all administrative actions.
+ <programlisting>
+auth required pam_tty_audit.so enable=root
+ </programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_tty_audit-author'>
+ <title>AUTHOR</title>
+ <para>
+ pam_tty_audit was written by Miloslav Trma&ccaron;
+ &lt;mitr@redhat.com&gt;.
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c
new file mode 100644
index 00000000..5e6211bc
--- /dev/null
+++ b/modules/pam_tty_audit/pam_tty_audit.c
@@ -0,0 +1,348 @@
+/* Copyright © 2007 Red Hat, Inc. All rights reserved.
+ Red Hat author: Miloslav Trmač <mitr@redhat.com>
+
+ Redistribution and use in source and binary forms of Linux-PAM, with
+ or without modification, are permitted provided that the following
+ conditions are met:
+
+ 1. Redistributions of source code must retain any existing copyright
+ notice, and this entire permission notice in its entirety,
+ including the disclaimer of warranties.
+
+ 2. Redistributions in binary form must reproduce all prior and current
+ copyright notices, this list of conditions, and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ 3. The name of any author may not be used to endorse or promote
+ products derived from this software without their specific prior
+ written permission.
+
+ ALTERNATIVELY, this product may be distributed under the terms of the
+ GNU General Public License, in which case the provisions of the GNU
+ GPL are required INSTEAD OF the above restrictions. (This clause is
+ necessary due to a potential conflict between the GNU 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(S) 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 <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <libaudit.h>
+#include <linux/netlink.h>
+
+#define PAM_SM_SESSION
+
+#include <security/pam_ext.h>
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+
+#define DATANAME "pam_tty_audit_last_state"
+
+/* Open an audit netlink socket */
+static int
+nl_open (void)
+{
+ return socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+}
+
+static int
+nl_send (int fd, unsigned type, unsigned flags, const void *data, size_t size)
+{
+ struct sockaddr_nl addr;
+ struct msghdr msg;
+ struct nlmsghdr nlm;
+ struct iovec iov[2];
+ ssize_t res;
+
+ nlm.nlmsg_len = NLMSG_LENGTH (size);
+ nlm.nlmsg_type = type;
+ nlm.nlmsg_flags = NLM_F_REQUEST | flags;
+ nlm.nlmsg_seq = 0;
+ nlm.nlmsg_pid = 0;
+ iov[0].iov_base = &nlm;
+ iov[0].iov_len = sizeof (nlm);
+ iov[1].iov_base = (void *)data;
+ iov[1].iov_len = size;
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = 0;
+ addr.nl_groups = 0;
+ msg.msg_name = &addr;
+ msg.msg_namelen = sizeof (addr);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+ res = sendmsg (fd, &msg, 0);
+ if (res == -1)
+ return -1;
+ if ((size_t)res != nlm.nlmsg_len)
+ {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+nl_recv (int fd, unsigned type, void *buf, size_t size)
+{
+ struct sockaddr_nl addr;
+ struct msghdr msg;
+ struct nlmsghdr nlm;
+ struct iovec iov[2];
+ ssize_t res;
+
+ again:
+ iov[0].iov_base = &nlm;
+ iov[0].iov_len = sizeof (nlm);
+ msg.msg_name = &addr;
+ msg.msg_namelen = sizeof (addr);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ if (type != NLMSG_ERROR)
+ {
+ res = recvmsg (fd, &msg, MSG_PEEK);
+ if (res == -1)
+ return -1;
+ if (res != NLMSG_LENGTH (0))
+ {
+ errno = EIO;
+ return -1;
+ }
+ if (nlm.nlmsg_type == NLMSG_ERROR)
+ {
+ struct nlmsgerr err;
+
+ iov[1].iov_base = &err;
+ iov[1].iov_len = sizeof (err);
+ msg.msg_iovlen = 2;
+ res = recvmsg (fd, &msg, 0);
+ if (res == -1)
+ return -1;
+ if ((size_t)res != NLMSG_LENGTH (sizeof (err))
+ || nlm.nlmsg_type != NLMSG_ERROR)
+ {
+ errno = EIO;
+ return -1;
+ }
+ if (err.error == 0)
+ goto again;
+ errno = -err.error;
+ return -1;
+ }
+ }
+ if (size != 0)
+ {
+ iov[1].iov_base = buf;
+ iov[1].iov_len = size;
+ msg.msg_iovlen = 2;
+ }
+ res = recvmsg (fd, &msg, 0);
+ if (res == -1)
+ return -1;
+ if ((size_t)res != NLMSG_LENGTH (size)
+ || nlm.nlmsg_type != type)
+ {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+nl_recv_ack (int fd)
+{
+ struct nlmsgerr err;
+
+ if (nl_recv (fd, NLMSG_ERROR, &err, sizeof (err)) != 0)
+ return -1;
+ if (err.error != 0)
+ {
+ errno = -err.error;
+ return -1;
+ }
+ return 0;
+}
+
+static void
+cleanup_old_status (pam_handle_t *pamh, void *data, int error_status)
+{
+ (void)pamh;
+ (void)error_status;
+ free (data);
+}
+
+int
+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ enum command { CMD_NONE, CMD_ENABLE, CMD_DISABLE };
+
+ enum command command;
+ struct audit_tty_status *old_status, new_status;
+ const char *user;
+ uid_t user_uid;
+ struct passwd *pwd;
+ int i, fd;
+
+ (void)flags;
+
+ if (pam_get_user (pamh, &user, NULL) != PAM_SUCCESS)
+ {
+ pam_syslog (pamh, LOG_ERR, "error determining target user's name");
+ return PAM_SESSION_ERR;
+ }
+ pwd = pam_modutil_getpwnam (pamh, user);
+ if (pwd == NULL)
+ {
+ pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
+ return PAM_SESSION_ERR;
+ }
+ user_uid = pwd->pw_uid;
+
+ command = CMD_NONE;
+ for (i = 0; i < argc; i++)
+ {
+ if (strncmp (argv[i], "enable=", 7) == 0
+ || strncmp (argv[i], "disable=", 8) == 0)
+ {
+ enum command this_command;
+ char *copy, *tok_data, *tok;
+
+ this_command = *argv[i] == 'e' ? CMD_ENABLE : CMD_DISABLE;
+ copy = strdup (strchr (argv[i], '=') + 1);
+ if (copy == NULL)
+ return PAM_SESSION_ERR;
+ for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
+ tok = strtok_r (NULL, ",", &tok_data))
+ {
+ pwd = pam_modutil_getpwnam (pamh, tok);
+ if (pwd == NULL)
+ {
+ pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
+ continue;
+ }
+ if (pwd->pw_uid == user_uid)
+ {
+ command = this_command;
+ break;
+ }
+ }
+ free (copy);
+ }
+ }
+ if (command == CMD_NONE)
+ return PAM_SUCCESS;
+
+ old_status = malloc (sizeof (*old_status));
+ if (old_status == NULL)
+ return PAM_SESSION_ERR;
+
+ fd = nl_open ();
+ if (fd == -1
+ || nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
+ || nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
+ {
+ pam_syslog (pamh, LOG_ERR, "error reading current audit status: %m");
+ if (fd != -1)
+ close (fd);
+ free (old_status);
+ return PAM_SESSION_ERR;
+ }
+
+ if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
+ {
+ free (old_status);
+ goto ok_fd;
+ }
+
+ if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
+ != PAM_SUCCESS)
+ {
+ pam_syslog (pamh, LOG_ERR, "error saving old audit status");
+ close (fd);
+ free (old_status);
+ return PAM_SESSION_ERR;
+ }
+
+ new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
+ if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
+ sizeof (new_status)) != 0
+ || nl_recv_ack (fd) != 0)
+ {
+ pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
+ close (fd);
+ return PAM_SESSION_ERR;
+ }
+ /* Fall through */
+ ok_fd:
+ close (fd);
+ pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
+ old_status->enabled, new_status.enabled);
+ return PAM_SUCCESS;
+}
+
+int
+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ const void *status_;
+
+ (void)flags;
+ (void)argc;
+ (void)argv;
+ if (pam_get_data (pamh, DATANAME, &status_) == PAM_SUCCESS)
+ {
+ const struct audit_tty_status *status;
+ int fd;
+
+ status = status_;
+
+ fd = nl_open ();
+ if (fd == -1
+ || nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, status,
+ sizeof (*status)) != 0
+ || nl_recv_ack (fd) != 0)
+ {
+ pam_syslog (pamh, LOG_ERR, "error restoring audit status: %m");
+ if (fd != -1)
+ close (fd);
+ return PAM_SESSION_ERR;
+ }
+ close (fd);
+ pam_syslog (pamh, LOG_ERR, "restored status to %d", status->enabled);
+ }
+ return PAM_SUCCESS;
+}
+
+/* static module data */
+#ifdef PAM_STATIC
+struct pam_module _pam_tty_audit_modstruct = {
+ "pam_tty_audit",
+ NULL,
+ NULL,
+ NULL,
+ pam_sm_open_session,
+ pam_sm_close_session,
+ NULL
+};
+#endif