From d89432f7266106f61532115ac0fcf25d8167afa1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 5 Dec 2007 20:08:57 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2007-12-05 Miloslav Trmac * 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. --- ChangeLog | 10 + NEWS | 2 + configure.in | 16 +- libpam/pam_static_modules.h | 6 + modules/Makefile.am | 4 +- modules/pam_tty_audit/Makefile.am | 30 +++ modules/pam_tty_audit/README.xml | 36 ++++ modules/pam_tty_audit/pam_tty_audit.8.xml | 120 +++++++++++ modules/pam_tty_audit/pam_tty_audit.c | 348 ++++++++++++++++++++++++++++++ 9 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 modules/pam_tty_audit/Makefile.am create mode 100644 modules/pam_tty_audit/README.xml create mode 100644 modules/pam_tty_audit/pam_tty_audit.8.xml create mode 100644 modules/pam_tty_audit/pam_tty_audit.c diff --git a/ChangeLog b/ChangeLog index 61b2e5e1..fcfb06ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-12-05 Miloslav Trmac + + * 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. + 2007-12-05 Tomas Mraz * modules/pam_unix/Makefile.am: Add passverify.h and passverify.c diff --git a/NEWS b/NEWS index acc6d0f2..87aaa6c7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ Linux-PAM NEWS -- history of user-visible changes. * New substack directive in config file syntax. +* New module pam_tty_audit.so for enabling and disabling tty + auditing. Release 0.99.9.0 * misc_conv no longer blocks SIGINT; applications that don't want diff --git a/configure.in b/configure.in index db00a62b..146e177a 100644 --- a/configure.in +++ b/configure.in @@ -331,15 +331,24 @@ AC_ARG_ENABLE([audit], WITH_LIBAUDIT=$enableval, WITH_LIBAUDIT=yes) if test x"$WITH_LIBAUDIT" != xno ; then AC_CHECK_HEADER([libaudit.h], - [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")] + [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="") + AC_CHECK_TYPE([struct audit_tty_status], + [HAVE_AUDIT_TTY_STATUS=yes], + [HAVE_AUDIT_TTY_STATUS=""], + [#include ])] ) if test ! -z "$LIBAUDIT" -a "ac_cv_header_libaudit_h" != "no" ; then - AC_DEFINE([HAVE_LIBAUDIT], 1, [Defined if audit support should be compiled in]) + AC_DEFINE([HAVE_LIBAUDIT], 1, [Define to 1 if audit support should be compiled in.]) + fi + if test ! -z "$HAVE_AUDIT_TTY_STATUS" ; then + AC_DEFINE([HAVE_AUDIT_TTY_STATUS], 1, [Define to 1 if struct audit_tty_status exists.]) fi else LIBAUDIT="" fi AC_SUBST(LIBAUDIT) +AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS], + [test "x$HAVE_AUDIT_TTY_STATUS" = xyes]) BACKUP_LIBS=$LIBS AC_SEARCH_LIBS([crypt],[xcrypt crypt], LIBCRYPT="-l$ac_lib", LIBCRYPT="") @@ -513,7 +522,8 @@ AC_OUTPUT(Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \ modules/pam_securetty/Makefile modules/pam_selinux/Makefile \ modules/pam_shells/Makefile modules/pam_stress/Makefile \ modules/pam_succeed_if/Makefile modules/pam_tally/Makefile \ - modules/pam_time/Makefile modules/pam_umask/Makefile \ + modules/pam_time/Makefile modules/pam_tty_audit/Makefile \ + modules/pam_umask/Makefile \ modules/pam_unix/Makefile modules/pam_userdb/Makefile \ modules/pam_warn/Makefile modules/pam_wheel/Makefile \ modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \ diff --git a/libpam/pam_static_modules.h b/libpam/pam_static_modules.h index 5445c5fe..42dcf8f0 100644 --- a/libpam/pam_static_modules.h +++ b/libpam/pam_static_modules.h @@ -73,6 +73,9 @@ extern struct pam_module _pam_stress_modstruct; extern struct pam_module _pam_succeed_if_modstruct; extern struct pam_module _pam_tally_modstruct; extern struct pam_module _pam_time_modstruct; +#ifdef HAVE_AUDIT_TTY_STATUS +extern struct pam_module _pam_tty_audit_modstruct; +#endif extern struct pam_module _pam_umask_modstruct; extern struct pam_module _pam_unix_acct_modstruct; extern struct pam_module _pam_unix_auth_modstruct; @@ -127,6 +130,9 @@ static struct pam_module *static_modules[] = { &_pam_succeed_if_modstruct, &_pam_tally_modstruct, &_pam_time_modstruct, +#ifdef HAVE_AUDIT_TTY_STATUS + &_pam_tty_audit_modstruct, +#endif &_pam_umask_modstruct, &_pam_unix_acct_modstruct, &_pam_unix_auth_modstruct, diff --git a/modules/Makefile.am b/modules/Makefile.am index 1272b0e8..88d7fe4e 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -7,8 +7,8 @@ SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ 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 pam_namespace pam_loginuid \ + pam_tally pam_time pam_tty_audit pam_umask pam_unix pam_userdb \ + pam_warn pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \ pam_faildelay CLEANFILES = *~ 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 +# + +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 @@ + + + +
+ + + + + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" + href="pam_tty_audit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tty_audit-name"]/*)'/> + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
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 @@ + + + + + + + pam_tty_audit + 8 + Linux-PAM Manual + + + + pam_tty_audit + Enable or disable TTY auditing for specified users + + + + + pam_tty_audit.so + + disable=usernames + + + enable=usernames + + + + + + DESCRIPTION + + 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. + + + + + OPTIONS + + + + + + + + For each user matching one of comma-separated + , disable + TTY auditing. This overrides any previous + option for the same user name on the command line. + + + + + + + + + + For each user matching one of comma-separated + , enable + TTY auditing. This overrides any previous + option for the same user name on the command line. + + + + + + + + MODULE SERVICES PROVIDED + + Only the session service is supported. + + + + + RETURN VALUES + + + PAM_SESSION_ERR + + + Error reading or modifying the TTY audit flag. See the system log + for more details. + + + + + + PAM_SUCCESS + + + Success. + + + + + + + + + EXAMPLES + + Audit all administrative actions. + +auth required pam_tty_audit.so enable=root + + + + + + AUTHOR + + pam_tty_audit was written by Miloslav Trmač + <mitr@redhat.com>. + + + + 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č + + 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PAM_SM_SESSION + +#include +#include +#include + +#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 -- cgit v1.2.3