diff -up Linux-PAM-1.1.6/modules/pam_rootok/Makefile.am.audit Linux-PAM-1.1.6/modules/pam_rootok/Makefile.am --- Linux-PAM-1.1.6/modules/pam_rootok/Makefile.am.audit 2012-08-15 13:08:43.000000000 +0200 +++ Linux-PAM-1.1.6/modules/pam_rootok/Makefile.am 2013-07-04 10:30:21.000000000 +0200 @@ -25,7 +25,7 @@ if HAVE_VERSIONING endif securelib_LTLIBRARIES = pam_rootok.la -pam_rootok_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBSELINUX@ +pam_rootok_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBSELINUX@ @LIBAUDIT@ if ENABLE_REGENERATE_MAN noinst_DATA = README diff -up Linux-PAM-1.1.6/modules/pam_rootok/pam_rootok.c.audit Linux-PAM-1.1.6/modules/pam_rootok/pam_rootok.c --- Linux-PAM-1.1.6/modules/pam_rootok/pam_rootok.c.audit 2012-08-15 13:08:43.000000000 +0200 +++ Linux-PAM-1.1.6/modules/pam_rootok/pam_rootok.c 2013-03-22 09:41:48.000000000 +0100 @@ -28,7 +28,11 @@ #ifdef WITH_SELINUX #include -#include +#include +#endif + +#ifdef HAVE_LIBAUDIT +#include #endif /* argument parsing */ @@ -55,6 +59,61 @@ _pam_parse (const pam_handle_t *pamh, in return ctrl; } +#ifdef WITH_SELINUX +static int +log_callback (int type, const char *fmt, ...) +{ + int audit_fd; + va_list ap; + + va_start(ap, fmt); +#ifdef HAVE_LIBAUDIT + audit_fd = audit_open(); + + if (audit_fd >= 0) { + char *buf; + + if (vasprintf (&buf, fmt, ap) < 0) + return 0; + audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, + NULL, 0); + audit_close(audit_fd); + free(buf); + return 0; + } + +#endif + vsyslog (LOG_USER | LOG_INFO, fmt, ap); + va_end(ap); + return 0; +} + +static int +selinux_check_root (void) +{ + int status = -1; + security_context_t user_context; + union selinux_callback old_callback; + + if (is_selinux_enabled() < 1) + return 0; + + old_callback = selinux_get_callback(SELINUX_CB_LOG); + /* setup callbacks */ + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); + if ((status = getprevcon(&user_context)) < 0) { + selinux_set_callback(SELINUX_CB_LOG, old_callback); + return status; + } + + status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); + + selinux_set_callback(SELINUX_CB_LOG, old_callback); + freecon(user_context); + return status; +} +#endif + static int check_for_root (pam_handle_t *pamh, int ctrl) { @@ -62,7 +121,7 @@ check_for_root (pam_handle_t *pamh, int if (getuid() == 0) #ifdef WITH_SELINUX - if (is_selinux_enabled()<1 || checkPasswdAccess(PASSWD__ROOTOK)==0) + if (selinux_check_root() == 0 || security_getenforce() == 0) #endif retval = PAM_SUCCESS;