]> granicus.if.org Git - linux-pam/commitdiff
Add grantor field to audit records of libpam.
authorTomas Mraz <tmraz@fedoraproject.org>
Fri, 5 Sep 2014 07:09:37 +0000 (09:09 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Fri, 5 Sep 2014 07:09:37 +0000 (09:09 +0200)
The grantor field gives audit trail of PAM modules which granted access
for successful return from libpam calls. In case of failed return
the grantor field is set to '?'.
libpam/pam_account.c (pam_acct_mgmt): Remove _pam_auditlog() call.
libpam/pam_auth.c (pam_authenticate, pam_setcred): Likewise.
libpam/pam_password.c (pam_chauthtok): Likewise.
libpam/pam_session.c (pam_open_session, pam_close_session): Likewise.
libpam/pam_audit.c (_pam_audit_writelog): Add grantors parameter,
add grantor= field to the message if grantors is set.
(_pam_list_grantors): New function creating the string with grantors list.
(_pam_auditlog): Add struct handler pointer parameter, call _pam_list_grantors()
to list the grantors from the handler list.
(_pam_audit_end): Add NULL handler parameter to _pam_auditlog() call.
(pam_modutil_audit_write): Add NULL grantors parameter to _pam_audit_writelog().
libpam/pam_dispatch.c (_pam_dispatch_aux): Set h->grantor where appropriate.
(_pam_clear_grantors): New function to clear grantor field of handler.
(_pam_dispatch): Call _pam_clear_grantors() before executing the stack.
Call _pam_auditlog() when appropriate.
libpam/pam_handlers.c (extract_modulename): Do not allow empty module name
or just "?" to avoid confusing audit trail.
(_pam_add_handler): Test for NULL return from extract_modulename().
Clear grantor field of handler.
libpam/pam_private.h: Add grantor field to struct handler, add handler pointer
parameter to _pam_auditlog().

libpam/pam_account.c
libpam/pam_audit.c
libpam/pam_auth.c
libpam/pam_dispatch.c
libpam/pam_handlers.c
libpam/pam_password.c
libpam/pam_private.h
libpam/pam_session.c

index 572acc473db653a12f6c65fe71bc94f9f2b8d5a5..3a4fb1fc8c049783346a185c0bcfc7af4b4c1b39 100644 (file)
@@ -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;
 }
index 531746ab67fb11129178b47327484e01376e617d..24fb799a75e1bd3672239361ec1efabfc1ea5949 100644 (file)
@@ -6,12 +6,12 @@
    Authors:
    Steve Grubb <sgrubb@redhat.com> */
 
-#include <stdio.h>
-#include <syslog.h>
 #include "pam_private.h"
 #include "pam_modutil_private.h"
 
 #ifdef HAVE_LIBAUDIT
+#include <stdio.h>
+#include <syslog.h>
 #include <libaudit.h>
 #include <pwd.h>
 #include <netdb.h>
 
 static int
 _pam_audit_writelog(pam_handle_t *pamh, int audit_fd, int type,
-       const char *message, int retval)
+       const char *message, const char *grantors, int retval)
 {
   static int old_errno = -1;
-  int rc;
-  char buf[32];
+  int rc = -ENOMEM;
+  char *buf;
+  const char *grantors_field = " grantors=";
 
-  snprintf(buf, sizeof(buf), "PAM:%s", message);
+  if (grantors == NULL) {
+      grantors = "";
+      grantors_field = "";
+  }
 
-  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 );
+  if (asprintf(&buf, "PAM:%s%s%s", message, grantors_field, grantors) >= 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 +85,54 @@ _pam_audit_open(pam_handle_t *pamh)
   return audit_fd;
 }
 
+static int
+_pam_list_grantors(struct handler *hlist, int retval, char **list)
+{
+  *list = NULL;
+
+  if (retval == PAM_SUCCESS) {
+    struct handler *h;
+    char *p = NULL;
+    size_t len = 0;
+
+    for (h = hlist; h != NULL; h = h->next) {
+      if (h->grantor) {
+        len += strlen(h->mod_name) + 1;
+      }
+    }
+
+    if (len == 0) {
+      return 0;
+    }
+
+    *list = malloc(len);
+    if (*list == NULL) {
+      return -1;
+    }
+
+    for (h = hlist; h != NULL; h = h->next) {
+      if (h->grantor) {
+        if (p == NULL) {
+          p = *list;
+        } else {
+          p = stpcpy(p, ",");
+        }
+
+        p = stpcpy(p, h->mod_name);
+      }
+    }
+  }
+
+  return 0;
+}
+
 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 *grantors;
 
   if ((audit_fd=_pam_audit_open(pamh)) == -1) {
     return PAM_SYSTEM_ERR;
@@ -134,8 +183,17 @@ _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)
+  if (_pam_list_grantors(h, retval, &grantors) < 0) {
+    /* allocation failure */
+    pam_syslog(pamh, LOG_CRIT, "_pam_list_grantors() failed: %m");
     retval = PAM_SYSTEM_ERR;
+  }
+
+  if (_pam_audit_writelog(pamh, audit_fd, type, message,
+      grantors ? grantors : "?", retval) < 0)
+    retval = PAM_SYSTEM_ERR;
+
+  free(grantors);
 
   audit_close(audit_fd);
   return retval;
@@ -149,7 +207,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;
@@ -168,7 +226,7 @@ pam_modutil_audit_write(pam_handle_t *pamh, int type,
     return retval;
   }
 
-  rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
+  rc = _pam_audit_writelog(pamh, audit_fd, type, message, NULL, retval);
 
   audit_close(audit_fd);
 
index 5984fa59c24f18d09cae34ba89c32ba255531db9..1e7bc6e7df898235b2240f9ccbdb7cb2737f9890 100644 (file)
@@ -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;
index eb52c824ec312d7ef801200691ac2b3012bbe2f9..cf632e8ea9f485bb25a32131a7d32da1a0148041 100644 (file)
@@ -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;
 
@@ -262,6 +268,9 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
                        || (impression == _PAM_POSITIVE
                            && status == PAM_SUCCESS) ) {
                        if ( retval != PAM_IGNORE || cached_retval == retval ) {
+                           if ( impression == _PAM_UNDEF && retval == PAM_SUCCESS ) {
+                               h->grantor = 1;
+                           }
                            impression = _PAM_POSITIVE;
                            status = retval;
                        }
@@ -308,6 +317,13 @@ decision_made:     /* by getting  here we have made a decision */
     return status;
 }
 
+static void _pam_clear_grantors(struct handler *h)
+{
+    for (; h != NULL; h = h->next) {
+       h->grantor = 0;
+    }
+}
+
 /*
  * This function translates the module dispatch request into a pointer
  * to the stack of modules that will actually be run.  the
@@ -318,21 +334,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 +376,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 +410,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 +436,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;
 }
index 02714f781bb9c437dc6432aaaf20ce2b87201c2d..df3a1d912e494a468ed5a3ec4fb8e34ca4d573c3 100644 (file)
@@ -611,6 +611,12 @@ extract_modulename(const char *mod_path)
   if (dot)
     *dot = '\0';
 
+  if (*retval == '\0' || strcmp(retval, "?") == 0) {
+    /* do not allow empty module name or "?" to avoid confusing audit trail */
+    _pam_drop(retval);
+    return NULL;
+  }
+
   return retval;
 }
 
@@ -888,7 +894,9 @@ int _pam_add_handler(pam_handle_t *pamh
     (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
     (*handler_p)->argc = argc;
     (*handler_p)->argv = argv;                       /* not a copy */
-    (*handler_p)->mod_name = extract_modulename(mod_path);
+    if (((*handler_p)->mod_name = extract_modulename(mod_path)) == NULL)
+       return PAM_ABORT;
+    (*handler_p)->grantor = 0;
     (*handler_p)->next = NULL;
 
     /* some of the modules have a second calling function */
@@ -920,7 +928,9 @@ int _pam_add_handler(pam_handle_t *pamh
        } else {
            (*handler_p2)->argv = NULL;              /* no arguments */
        }
-       (*handler_p2)->mod_name = extract_modulename(mod_path);
+       if (((*handler_p2)->mod_name = extract_modulename(mod_path)) == NULL)
+           return PAM_ABORT;
+       (*handler_p2)->grantor = 0;
        (*handler_p2)->next = NULL;
     }
 
index 75db5e50999338579cd71de7e70e5fe96f0a9d51..592e01fb850314357e8a22ab09633ec286c4e648 100644 (file)
@@ -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;
 }
index 134dc7267aca250f0fc313e41968ea4633813b9a..d93283ce3a8ad64582531b1650efec3d3ca59b09 100644 (file)
@@ -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
 
index 512153f2dd25d01f55a6728278f25882699e1b20..cb393c1ae800250536720783207a0e1cad406c9b 100644 (file)
@@ -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;
 
 }