Blame SOURCES/pam-1.1.8-audit-grantor.patch

c22a38
From 0d29e379601819c7f7ed8de18b54de803a9f4049 Mon Sep 17 00:00:00 2001
c22a38
From: Tomas Mraz <tmraz@fedoraproject.org>
c22a38
Date: Fri, 5 Sep 2014 09:09:37 +0200
c22a38
Subject: [PATCH] Add grantor field to audit records of libpam.
c22a38
c22a38
The grantor field gives audit trail of PAM modules which granted access
c22a38
for successful return from libpam calls. In case of failed return
c22a38
the grantor field is set to '?'.
c22a38
libpam/pam_account.c (pam_acct_mgmt): Remove _pam_auditlog() call.
c22a38
libpam/pam_auth.c (pam_authenticate, pam_setcred): Likewise.
c22a38
libpam/pam_password.c (pam_chauthtok): Likewise.
c22a38
libpam/pam_session.c (pam_open_session, pam_close_session): Likewise.
c22a38
libpam/pam_audit.c (_pam_audit_writelog): Add grantors parameter,
c22a38
add grantor= field to the message if grantors is set.
c22a38
(_pam_list_grantors): New function creating the string with grantors list.
c22a38
(_pam_auditlog): Add struct handler pointer parameter, call _pam_list_grantors()
c22a38
to list the grantors from the handler list.
c22a38
(_pam_audit_end): Add NULL handler parameter to _pam_auditlog() call.
c22a38
(pam_modutil_audit_write): Add NULL grantors parameter to _pam_audit_writelog().
c22a38
libpam/pam_dispatch.c (_pam_dispatch_aux): Set h->grantor where appropriate.
c22a38
(_pam_clear_grantors): New function to clear grantor field of handler.
c22a38
(_pam_dispatch): Call _pam_clear_grantors() before executing the stack.
c22a38
Call _pam_auditlog() when appropriate.
c22a38
libpam/pam_handlers.c (extract_modulename): Do not allow empty module name
c22a38
or just "?" to avoid confusing audit trail.
c22a38
(_pam_add_handler): Test for NULL return from extract_modulename().
c22a38
Clear grantor field of handler.
c22a38
libpam/pam_private.h: Add grantor field to struct handler, add handler pointer
c22a38
parameter to _pam_auditlog().
c22a38
---
c22a38
 libpam/pam_account.c  |  4 ---
c22a38
 libpam/pam_audit.c    | 84 +++++++++++++++++++++++++++++++++++++++++++--------
c22a38
 libpam/pam_auth.c     |  8 -----
c22a38
 libpam/pam_dispatch.c | 41 ++++++++++++++++++++-----
c22a38
 libpam/pam_handlers.c | 14 +++++++--
c22a38
 libpam/pam_password.c |  4 ---
c22a38
 libpam/pam_private.h  |  3 +-
c22a38
 libpam/pam_session.c  |  7 -----
c22a38
 8 files changed, 119 insertions(+), 46 deletions(-)
c22a38
c22a38
diff --git a/libpam/pam_account.c b/libpam/pam_account.c
c22a38
index 572acc4..3a4fb1f 100644
c22a38
--- a/libpam/pam_account.c
c22a38
+++ b/libpam/pam_account.c
c22a38
@@ -19,9 +19,5 @@ int pam_acct_mgmt(pam_handle_t *pamh, int flags)
c22a38
 
c22a38
     retval = _pam_dispatch(pamh, flags, PAM_ACCOUNT);
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_ACCOUNT, retval, flags);
c22a38
-#endif
c22a38
-
c22a38
     return retval;
c22a38
 }
c22a38
diff --git a/libpam/pam_audit.c b/libpam/pam_audit.c
c22a38
index 531746a..24fb799 100644
c22a38
--- a/libpam/pam_audit.c
c22a38
+++ b/libpam/pam_audit.c
c22a38
@@ -6,12 +6,12 @@
c22a38
    Authors:
c22a38
    Steve Grubb <sgrubb@redhat.com> */
c22a38
 
c22a38
-#include <stdio.h>
c22a38
-#include <syslog.h>
c22a38
 #include "pam_private.h"
c22a38
 #include "pam_modutil_private.h"
c22a38
 
c22a38
 #ifdef HAVE_LIBAUDIT
c22a38
+#include <stdio.h>
c22a38
+#include <syslog.h>
c22a38
 #include <libaudit.h>
c22a38
 #include <pwd.h>
c22a38
 #include <netdb.h>
c22a38
@@ -25,17 +25,24 @@
c22a38
 
c22a38
 static int
c22a38
 _pam_audit_writelog(pam_handle_t *pamh, int audit_fd, int type,
c22a38
-	const char *message, int retval)
c22a38
+	const char *message, const char *grantors, int retval)
c22a38
 {
c22a38
   static int old_errno = -1;
c22a38
-  int rc;
c22a38
-  char buf[32];
c22a38
+  int rc = -ENOMEM;
c22a38
+  char *buf;
c22a38
+  const char *grantors_field = " grantors=";
c22a38
 
c22a38
-  snprintf(buf, sizeof(buf), "PAM:%s", message);
c22a38
+  if (grantors == NULL) {
c22a38
+      grantors = "";
c22a38
+      grantors_field = "";
c22a38
+  }
c22a38
 
c22a38
-  rc = audit_log_acct_message (audit_fd, type, NULL, buf,
c22a38
-       (retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
c22a38
-	-1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS );
c22a38
+  if (asprintf(&buf, "PAM:%s%s%s", message, grantors_field, grantors) >= 0) {
c22a38
+      rc = audit_log_acct_message(audit_fd, type, NULL, buf,
c22a38
+	(retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
c22a38
+	-1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS);
c22a38
+      free(buf);
c22a38
+  }
c22a38
 
c22a38
   /* libaudit sets errno to his own negative error code. This can be
c22a38
      an official errno number, but must not. It can also be a audit
c22a38
@@ -78,12 +85,54 @@ _pam_audit_open(pam_handle_t *pamh)
c22a38
   return audit_fd;
c22a38
 }
c22a38
 
c22a38
+static int
c22a38
+_pam_list_grantors(struct handler *hlist, int retval, char **list)
c22a38
+{
c22a38
+  *list = NULL;
c22a38
+
c22a38
+  if (retval == PAM_SUCCESS) {
c22a38
+    struct handler *h;
c22a38
+    char *p = NULL;
c22a38
+    size_t len = 0;
c22a38
+
c22a38
+    for (h = hlist; h != NULL; h = h->next) {
c22a38
+      if (h->grantor) {
c22a38
+        len += strlen(h->mod_name) + 1;
c22a38
+      }
c22a38
+    }
c22a38
+
c22a38
+    if (len == 0) {
c22a38
+      return 0;
c22a38
+    }
c22a38
+
c22a38
+    *list = malloc(len);
c22a38
+    if (*list == NULL) {
c22a38
+      return -1;
c22a38
+    }
c22a38
+
c22a38
+    for (h = hlist; h != NULL; h = h->next) {
c22a38
+      if (h->grantor) {
c22a38
+        if (p == NULL) {
c22a38
+          p = *list;
c22a38
+        } else {
c22a38
+          p = stpcpy(p, ",");
c22a38
+        }
c22a38
+
c22a38
+        p = stpcpy(p, h->mod_name);
c22a38
+      }
c22a38
+    }
c22a38
+  }
c22a38
+
c22a38
+  return 0;
c22a38
+}
c22a38
+
c22a38
 int
c22a38
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
c22a38
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h)
c22a38
 {
c22a38
   const char *message;
c22a38
   int type;
c22a38
   int audit_fd;
c22a38
+  char *grantors;
c22a38
 
c22a38
   if ((audit_fd=_pam_audit_open(pamh)) == -1) {
c22a38
     return PAM_SYSTEM_ERR;
c22a38
@@ -134,8 +183,17 @@ _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
c22a38
     retval = PAM_SYSTEM_ERR;
c22a38
   }
c22a38
 
c22a38
-  if (_pam_audit_writelog(pamh, audit_fd, type, message, retval) < 0)
c22a38
+  if (_pam_list_grantors(h, retval, &grantors) < 0) {
c22a38
+    /* allocation failure */
c22a38
+    pam_syslog(pamh, LOG_CRIT, "_pam_list_grantors() failed: %m");
c22a38
     retval = PAM_SYSTEM_ERR;
c22a38
+  }
c22a38
+
c22a38
+  if (_pam_audit_writelog(pamh, audit_fd, type, message,
c22a38
+      grantors ? grantors : "?", retval) < 0)
c22a38
+    retval = PAM_SYSTEM_ERR;
c22a38
+
c22a38
+  free(grantors);
c22a38
 
c22a38
   audit_close(audit_fd);
c22a38
   return retval;
c22a38
@@ -149,7 +207,7 @@ _pam_audit_end(pam_handle_t *pamh, int status UNUSED)
c22a38
      * stacks having been run. Assume that this is sshd faking
c22a38
      * things for an unknown user.
c22a38
      */
c22a38
-    _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0);
c22a38
+    _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0, NULL);
c22a38
   }
c22a38
 
c22a38
   return 0;
c22a38
@@ -168,7 +226,7 @@ pam_modutil_audit_write(pam_handle_t *pamh, int type,
c22a38
     return retval;
c22a38
   }
c22a38
 
c22a38
-  rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
c22a38
+  rc = _pam_audit_writelog(pamh, audit_fd, type, message, NULL, retval);
c22a38
 
c22a38
   audit_close(audit_fd);
c22a38
 
c22a38
diff --git a/libpam/pam_auth.c b/libpam/pam_auth.c
c22a38
index 5984fa5..1e7bc6e 100644
c22a38
--- a/libpam/pam_auth.c
c22a38
+++ b/libpam/pam_auth.c
c22a38
@@ -45,10 +45,6 @@ int pam_authenticate(pam_handle_t *pamh, int flags)
c22a38
     prelude_send_alert(pamh, retval);
c22a38
 #endif
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_AUTHENTICATE, retval, flags);
c22a38
-#endif
c22a38
-
c22a38
     return retval;
c22a38
 }
c22a38
 
c22a38
@@ -71,10 +67,6 @@ int pam_setcred(pam_handle_t *pamh, int flags)
c22a38
 
c22a38
     retval = _pam_dispatch(pamh, flags, PAM_SETCRED);
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_SETCRED, retval, flags);
c22a38
-#endif
c22a38
-
c22a38
     D(("pam_setcred exit"));
c22a38
 
c22a38
     return retval;
c22a38
diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c
c22a38
index eb52c82..cf632e8 100644
c22a38
--- a/libpam/pam_dispatch.c
c22a38
+++ b/libpam/pam_dispatch.c
c22a38
@@ -217,8 +217,14 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
c22a38
                     status = retval;
c22a38
                 }
c22a38
 	    }
c22a38
-	    if ( impression == _PAM_POSITIVE && action == _PAM_ACTION_DONE ) {
c22a38
-		goto decision_made;
c22a38
+	    if ( impression == _PAM_POSITIVE ) {
c22a38
+		if ( retval == PAM_SUCCESS ) {
c22a38
+		    h->grantor = 1;
c22a38
+		}
c22a38
+
c22a38
+		if ( action == _PAM_ACTION_DONE ) {
c22a38
+		    goto decision_made;
c22a38
+		}
c22a38
 	    }
c22a38
 	    break;
c22a38
 
c22a38
@@ -262,6 +268,9 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
c22a38
 			|| (impression == _PAM_POSITIVE
c22a38
 			    && status == PAM_SUCCESS) ) {
c22a38
 			if ( retval != PAM_IGNORE || cached_retval == retval ) {
c22a38
+			    if ( impression == _PAM_UNDEF && retval == PAM_SUCCESS ) {
c22a38
+				h->grantor = 1;
c22a38
+			    }
c22a38
 			    impression = _PAM_POSITIVE;
c22a38
 			    status = retval;
c22a38
 			}
c22a38
@@ -308,6 +317,13 @@ decision_made:     /* by getting  here we have made a decision */
c22a38
     return status;
c22a38
 }
c22a38
 
c22a38
+static void _pam_clear_grantors(struct handler *h)
c22a38
+{
c22a38
+    for (; h != NULL; h = h->next) {
c22a38
+	h->grantor = 0;
c22a38
+    }
c22a38
+}
c22a38
+
c22a38
 /*
c22a38
  * This function translates the module dispatch request into a pointer
c22a38
  * to the stack of modules that will actually be run.  the
c22a38
@@ -318,21 +334,21 @@ decision_made:     /* by getting  here we have made a decision */
c22a38
 int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
c22a38
 {
c22a38
     struct handler *h = NULL;
c22a38
-    int retval, use_cached_chain;
c22a38
+    int retval = PAM_SYSTEM_ERR, use_cached_chain;
c22a38
     _pam_boolean resumed;
c22a38
 
c22a38
     IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR);
c22a38
 
c22a38
     if (__PAM_FROM_MODULE(pamh)) {
c22a38
 	D(("called from a module!?"));
c22a38
-	return PAM_SYSTEM_ERR;
c22a38
+	goto end;
c22a38
     }
c22a38
 
c22a38
     /* Load all modules, resolve all symbols */
c22a38
 
c22a38
     if ((retval = _pam_init_handlers(pamh)) != PAM_SUCCESS) {
c22a38
 	pam_syslog(pamh, LOG_ERR, "unable to dispatch function");
c22a38
-	return retval;
c22a38
+	goto end;
c22a38
     }
c22a38
 
c22a38
     use_cached_chain = _PAM_PLEASE_FREEZE;
c22a38
@@ -360,7 +376,8 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
c22a38
 	break;
c22a38
     default:
c22a38
 	pam_syslog(pamh, LOG_ERR, "undefined fn choice; %d", choice);
c22a38
-	return PAM_ABORT;
c22a38
+	retval = PAM_ABORT;
c22a38
+	goto end;
c22a38
     }
c22a38
 
c22a38
     if (h == NULL) {     /* there was no handlers.conf... entry; will use
c22a38
@@ -393,11 +410,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
c22a38
 	    pam_syslog(pamh, LOG_ERR,
c22a38
 			    "application failed to re-exec stack [%d:%d]",
c22a38
 			    pamh->former.choice, choice);
c22a38
-	    return PAM_ABORT;
c22a38
+	    retval = PAM_ABORT;
c22a38
+	    goto end;
c22a38
 	}
c22a38
 	resumed = PAM_TRUE;
c22a38
     } else {
c22a38
 	resumed = PAM_FALSE;
c22a38
+	_pam_clear_grantors(h);
c22a38
     }
c22a38
 
c22a38
     __PAM_TO_MODULE(pamh);
c22a38
@@ -417,5 +436,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
c22a38
 	pamh->former.choice = PAM_NOT_STACKED;
c22a38
     }
c22a38
 
c22a38
+end:
c22a38
+
c22a38
+#ifdef HAVE_LIBAUDIT
c22a38
+    if (choice != PAM_CHAUTHTOK || flags & PAM_UPDATE_AUTHTOK || retval != PAM_SUCCESS) {
c22a38
+	retval = _pam_auditlog(pamh, choice, retval, flags, h);
c22a38
+    }
c22a38
+#endif
c22a38
+
c22a38
     return retval;
c22a38
 }
c22a38
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
c22a38
index 02714f7..df3a1d9 100644
c22a38
--- a/libpam/pam_handlers.c
c22a38
+++ b/libpam/pam_handlers.c
c22a38
@@ -611,6 +611,12 @@ extract_modulename(const char *mod_path)
c22a38
   if (dot)
c22a38
     *dot = '\0';
c22a38
 
c22a38
+  if (*retval == '\0' || strcmp(retval, "?") == 0) {
c22a38
+    /* do not allow empty module name or "?" to avoid confusing audit trail */
c22a38
+    _pam_drop(retval);
c22a38
+    return NULL;
c22a38
+  }
c22a38
+
c22a38
   return retval;
c22a38
 }
c22a38
 
c22a38
@@ -888,7 +894,9 @@ int _pam_add_handler(pam_handle_t *pamh
c22a38
     (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
c22a38
     (*handler_p)->argc = argc;
c22a38
     (*handler_p)->argv = argv;                       /* not a copy */
c22a38
-    (*handler_p)->mod_name = extract_modulename(mod_path);
c22a38
+    if (((*handler_p)->mod_name = extract_modulename(mod_path)) == NULL)
c22a38
+	return PAM_ABORT;
c22a38
+    (*handler_p)->grantor = 0;
c22a38
     (*handler_p)->next = NULL;
c22a38
 
c22a38
     /* some of the modules have a second calling function */
c22a38
@@ -920,7 +928,9 @@ int _pam_add_handler(pam_handle_t *pamh
c22a38
 	} else {
c22a38
 	    (*handler_p2)->argv = NULL;              /* no arguments */
c22a38
 	}
c22a38
-	(*handler_p2)->mod_name = extract_modulename(mod_path);
c22a38
+	if (((*handler_p2)->mod_name = extract_modulename(mod_path)) == NULL)
c22a38
+	    return PAM_ABORT;
c22a38
+	(*handler_p2)->grantor = 0;
c22a38
 	(*handler_p2)->next = NULL;
c22a38
     }
c22a38
 
c22a38
diff --git a/libpam/pam_password.c b/libpam/pam_password.c
c22a38
index 75db5e5..592e01f 100644
c22a38
--- a/libpam/pam_password.c
c22a38
+++ b/libpam/pam_password.c
c22a38
@@ -57,9 +57,5 @@ int pam_chauthtok(pam_handle_t *pamh, int flags)
c22a38
 	D(("will resume when ready", retval));
c22a38
     }
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_CHAUTHTOK, retval, flags);
c22a38
-#endif
c22a38
-
c22a38
     return retval;
c22a38
 }
c22a38
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
c22a38
index 134dc72..d93283c 100644
c22a38
--- a/libpam/pam_private.h
c22a38
+++ b/libpam/pam_private.h
c22a38
@@ -55,6 +55,7 @@ struct handler {
c22a38
     struct handler *next;
c22a38
     char *mod_name;
c22a38
     int stack_level;
c22a38
+    int grantor;
c22a38
 };
c22a38
 
c22a38
 #define PAM_HT_MODULE       0
c22a38
@@ -316,7 +317,7 @@ if ((pamh) == NULL) {                             \
c22a38
         do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0)
c22a38
 
c22a38
 #ifdef HAVE_LIBAUDIT
c22a38
-extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags);
c22a38
+extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h);
c22a38
 extern int _pam_audit_end(pam_handle_t *pamh, int pam_status);
c22a38
 #endif
c22a38
 
c22a38
diff --git a/libpam/pam_session.c b/libpam/pam_session.c
c22a38
index 512153f..cb393c1 100644
c22a38
--- a/libpam/pam_session.c
c22a38
+++ b/libpam/pam_session.c
c22a38
@@ -22,9 +22,6 @@ int pam_open_session(pam_handle_t *pamh, int flags)
c22a38
     }
c22a38
     retval = _pam_dispatch(pamh, flags, PAM_OPEN_SESSION);
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_OPEN_SESSION, retval, flags);
c22a38
-#endif
c22a38
     return retval;
c22a38
 }
c22a38
 
c22a38
@@ -43,10 +40,6 @@ int pam_close_session(pam_handle_t *pamh, int flags)
c22a38
 
c22a38
     retval = _pam_dispatch(pamh, flags, PAM_CLOSE_SESSION);
c22a38
 
c22a38
-#ifdef HAVE_LIBAUDIT
c22a38
-    retval = _pam_auditlog(pamh, PAM_CLOSE_SESSION, retval, flags);
c22a38
-#endif
c22a38
-
c22a38
     return retval;
c22a38
 
c22a38
 }
c22a38
-- 
c22a38
1.8.3.1
c22a38