Blob Blame History Raw
diff --git a/libpam/pam_account.c b/libpam/pam_account.c
index 572acc4..3a4fb1f 100644
--- a/libpam/pam_account.c
+++ b/libpam/pam_account.c
@@ -19,9 +19,5 @@ int pam_acct_mgmt(pam_handle_t *pamh, int flags)
 
     retval = _pam_dispatch(pamh, flags, PAM_ACCOUNT);
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_ACCOUNT, retval, flags);
-#endif
-
     return retval;
 }
diff --git a/libpam/pam_audit.c b/libpam/pam_audit.c
index 531746a..63a4ea5 100644
--- a/libpam/pam_audit.c
+++ b/libpam/pam_audit.c
@@ -28,14 +28,15 @@ _pam_audit_writelog(pam_handle_t *pamh, int audit_fd, int type,
 	const char *message, int retval)
 {
   static int old_errno = -1;
-  int rc;
-  char buf[32];
-
-  snprintf(buf, sizeof(buf), "PAM:%s", message);
-
-  rc = audit_log_acct_message (audit_fd, type, NULL, buf,
-       (retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
-	-1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS );
+  int rc = -ENOMEM;
+  char *buf = NULL;
+
+  if (asprintf(&buf, "PAM:%s", message) >= 0) {
+      rc = audit_log_acct_message(audit_fd, type, NULL, buf,
+	(retval != PAM_USER_UNKNOWN && pamh->user) ? pamh->user : "?",
+	-1, pamh->rhost, NULL, pamh->tty, retval == PAM_SUCCESS);
+      free(buf);
+  }
 
   /* libaudit sets errno to his own negative error code. This can be
      an official errno number, but must not. It can also be a audit
@@ -78,12 +79,65 @@ _pam_audit_open(pam_handle_t *pamh)
   return audit_fd;
 }
 
+static char *
+_pam_list_grantors(struct handler *hlist, const char *message, int retval)
+{
+  char *buf;
+  char *list = NULL;
+
+  if (retval == PAM_SUCCESS) {
+    struct handler *h;
+    char *p = NULL;
+    size_t len = 0;
+
+    h = hlist;
+
+    while (h != NULL) {
+      if (h->grantor) {
+        len += strlen(h->mod_name) + 1;
+      }
+
+      h = h->next;
+    }
+
+    list = malloc(len);
+    if (list == NULL) {
+      return NULL;
+    }
+
+    h = hlist;
+
+    while (h != NULL) {
+      if (h->grantor) {
+        if (p == NULL) {
+          p = list;
+        } else {
+          p = stpcpy(p, ",");
+        }
+
+        p = stpcpy(p, h->mod_name);
+      }
+
+      h = h->next;
+    }
+  }
+
+  if (asprintf(&buf, "%s grantor=%s", message, list ? list : "?") < 0) {
+    free(list);
+    return NULL;
+  }
+
+  free(list);
+  return buf;
+}
+
 int
-_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h)
 {
   const char *message;
   int type;
   int audit_fd;
+  char *buf = NULL;
 
   if ((audit_fd=_pam_audit_open(pamh)) == -1) {
     return PAM_SYSTEM_ERR;
@@ -134,9 +188,18 @@ _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
     retval = PAM_SYSTEM_ERR;
   }
 
-  if (_pam_audit_writelog(pamh, audit_fd, type, message, retval) < 0)
+  buf = _pam_list_grantors(h, message, retval);
+  if (buf == NULL) {
+    /* allocation failure */
+    pam_syslog(pamh, LOG_CRIT, "_pam_list_grantors() failed: %m");
+    retval = PAM_SYSTEM_ERR;
+  }
+
+  if (_pam_audit_writelog(pamh, audit_fd, type, buf ? buf : message, retval) < 0)
     retval = PAM_SYSTEM_ERR;
 
+  free(buf);
+
   audit_close(audit_fd);
   return retval;
 }
@@ -149,7 +212,7 @@ _pam_audit_end(pam_handle_t *pamh, int status UNUSED)
      * stacks having been run. Assume that this is sshd faking
      * things for an unknown user.
      */
-    _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0);
+    _pam_auditlog(pamh, _PAM_ACTION_DONE, PAM_USER_UNKNOWN, 0, NULL);
   }
 
   return 0;
diff --git a/libpam/pam_auth.c b/libpam/pam_auth.c
index 5984fa5..1e7bc6e 100644
--- a/libpam/pam_auth.c
+++ b/libpam/pam_auth.c
@@ -45,10 +45,6 @@ int pam_authenticate(pam_handle_t *pamh, int flags)
     prelude_send_alert(pamh, retval);
 #endif
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_AUTHENTICATE, retval, flags);
-#endif
-
     return retval;
 }
 
@@ -71,10 +67,6 @@ int pam_setcred(pam_handle_t *pamh, int flags)
 
     retval = _pam_dispatch(pamh, flags, PAM_SETCRED);
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_SETCRED, retval, flags);
-#endif
-
     D(("pam_setcred exit"));
 
     return retval;
diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c
index eb52c82..ccfc372 100644
--- a/libpam/pam_dispatch.c
+++ b/libpam/pam_dispatch.c
@@ -217,8 +217,14 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
                     status = retval;
                 }
 	    }
-	    if ( impression == _PAM_POSITIVE && action == _PAM_ACTION_DONE ) {
-		goto decision_made;
+	    if ( impression == _PAM_POSITIVE ) {
+		if ( retval == PAM_SUCCESS ) {
+		    h->grantor = 1;
+		}
+
+		if ( action == _PAM_ACTION_DONE ) {
+		    goto decision_made;
+		}
 	    }
 	    break;
 
@@ -308,6 +314,14 @@ decision_made:     /* by getting  here we have made a decision */
     return status;
 }
 
+static void _pam_clear_grantors(struct handler *h)
+{
+    while (h != NULL) {
+	h->grantor = 0;
+	h = h->next;
+    }
+}
+
 /*
  * This function translates the module dispatch request into a pointer
  * to the stack of modules that will actually be run.  the
@@ -318,21 +332,21 @@ decision_made:     /* by getting  here we have made a decision */
 int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
 {
     struct handler *h = NULL;
-    int retval, use_cached_chain;
+    int retval = PAM_SYSTEM_ERR, use_cached_chain;
     _pam_boolean resumed;
 
     IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR);
 
     if (__PAM_FROM_MODULE(pamh)) {
 	D(("called from a module!?"));
-	return PAM_SYSTEM_ERR;
+	goto end;
     }
 
     /* Load all modules, resolve all symbols */
 
     if ((retval = _pam_init_handlers(pamh)) != PAM_SUCCESS) {
 	pam_syslog(pamh, LOG_ERR, "unable to dispatch function");
-	return retval;
+	goto end;
     }
 
     use_cached_chain = _PAM_PLEASE_FREEZE;
@@ -360,7 +374,8 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
 	break;
     default:
 	pam_syslog(pamh, LOG_ERR, "undefined fn choice; %d", choice);
-	return PAM_ABORT;
+	retval = PAM_ABORT;
+	goto end;
     }
 
     if (h == NULL) {     /* there was no handlers.conf... entry; will use
@@ -393,11 +408,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
 	    pam_syslog(pamh, LOG_ERR,
 			    "application failed to re-exec stack [%d:%d]",
 			    pamh->former.choice, choice);
-	    return PAM_ABORT;
+	    retval = PAM_ABORT;
+	    goto end;
 	}
 	resumed = PAM_TRUE;
     } else {
 	resumed = PAM_FALSE;
+	_pam_clear_grantors(h);
     }
 
     __PAM_TO_MODULE(pamh);
@@ -417,5 +434,13 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice)
 	pamh->former.choice = PAM_NOT_STACKED;
     }
 
+end:
+
+#ifdef HAVE_LIBAUDIT
+    if (choice != PAM_CHAUTHTOK || flags & PAM_UPDATE_AUTHTOK || retval != PAM_SUCCESS) {
+	retval = _pam_auditlog(pamh, choice, retval, flags, h);
+    }
+#endif
+
     return retval;
 }
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 02714f7..e3f8ff6 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -889,6 +889,7 @@ int _pam_add_handler(pam_handle_t *pamh
     (*handler_p)->argc = argc;
     (*handler_p)->argv = argv;                       /* not a copy */
     (*handler_p)->mod_name = extract_modulename(mod_path);
+    (*handler_p)->grantor = 0;
     (*handler_p)->next = NULL;
 
     /* some of the modules have a second calling function */
@@ -921,6 +922,7 @@ int _pam_add_handler(pam_handle_t *pamh
 	    (*handler_p2)->argv = NULL;              /* no arguments */
 	}
 	(*handler_p2)->mod_name = extract_modulename(mod_path);
+	(*handler_p2)->grantor = 0;
 	(*handler_p2)->next = NULL;
     }
 
diff --git a/libpam/pam_password.c b/libpam/pam_password.c
index 75db5e5..592e01f 100644
--- a/libpam/pam_password.c
+++ b/libpam/pam_password.c
@@ -57,9 +57,5 @@ int pam_chauthtok(pam_handle_t *pamh, int flags)
 	D(("will resume when ready", retval));
     }
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_CHAUTHTOK, retval, flags);
-#endif
-
     return retval;
 }
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
index 134dc72..d93283c 100644
--- a/libpam/pam_private.h
+++ b/libpam/pam_private.h
@@ -55,6 +55,7 @@ struct handler {
     struct handler *next;
     char *mod_name;
     int stack_level;
+    int grantor;
 };
 
 #define PAM_HT_MODULE       0
@@ -316,7 +317,7 @@ if ((pamh) == NULL) {                             \
         do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0)
 
 #ifdef HAVE_LIBAUDIT
-extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags);
+extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags, struct handler *h);
 extern int _pam_audit_end(pam_handle_t *pamh, int pam_status);
 #endif
 
diff --git a/libpam/pam_session.c b/libpam/pam_session.c
index 512153f..cb393c1 100644
--- a/libpam/pam_session.c
+++ b/libpam/pam_session.c
@@ -22,9 +22,6 @@ int pam_open_session(pam_handle_t *pamh, int flags)
     }
     retval = _pam_dispatch(pamh, flags, PAM_OPEN_SESSION);
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_OPEN_SESSION, retval, flags);
-#endif
     return retval;
 }
 
@@ -43,10 +40,6 @@ int pam_close_session(pam_handle_t *pamh, int flags)
 
     retval = _pam_dispatch(pamh, flags, PAM_CLOSE_SESSION);
 
-#ifdef HAVE_LIBAUDIT
-    retval = _pam_auditlog(pamh, PAM_CLOSE_SESSION, retval, flags);
-#endif
-
     return retval;
 
 }