audit: remove static local realms
[openafs.git] / src / audit / audit.c
index 440e423..a0a03b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
 #ifdef AFS_AIX32_ENV
 #include <sys/audit.h>
 #else
@@ -25,38 +21,71 @@ RCSID
 #define AUDIT_FAIL_ACCESS 3
 #define AUDIT_FAIL_PRIV 4
 #endif /* AFS_AIX32_ENV */
-#include <errno.h>
 
 #include "afs/afsint.h"
 #include <rx/rx.h>
 #include <rx/rxkad.h>
 #include "audit.h"
+#include "audit-api.h"
 #include "lock.h"
-#ifdef AFS_AIX32_ENV
-#include <sys/audit.h>
-#endif
+
 #include <afs/afsutil.h>
 
-char *bufferPtr;
-int bufferLen;
-int osi_audit_all = (-1);      /* Not determined yet */
-int osi_echo_trail = (-1);
+/* C99 requires va_copy.  Older versions of GCC provide __va_copy.  Per t
+   Autoconf manual, memcpy is a generally portable fallback. */
+#ifndef va_copy
+# ifdef __va_copy
+#  define va_copy(d, s)         __va_copy((d), (s))
+# else
+#  define va_copy(d, s)         memcpy(&(d), &(s), sizeof(va_list))
+# endif
+#endif
+
+extern struct osi_audit_ops audit_file_ops;
+#ifdef HAVE_SYS_IPC_H
+extern struct osi_audit_ops audit_sysvmq_ops;
+#endif
+
+static struct {
+    void *rock;
+    int (*islocal)(void *rock, char *name, char *inst, char *cell);
+} audit_user_check = { NULL, NULL };
+
+static struct {
+    const char *name;
+    const struct osi_audit_ops *ops;
+} audit_interfaces[] = {
+
+    { "file", &audit_file_ops },
+#ifdef HAVE_SYS_IPC_H
+    { "sysvmq", &audit_sysvmq_ops },
+#endif
+};
+
+#define N_INTERFACES (sizeof(audit_interfaces) / sizeof(audit_interfaces[0]))
+
+/* default to `file' audit interface */
+static const struct osi_audit_ops *audit_ops = &audit_file_ops;
+
+static int osi_audit_all = (-1);       /* Not determined yet */
+static int osi_echo_trail = (-1);
+
+static int auditout_open = 0;
 
-FILE *auditout = NULL;
+static int osi_audit_check(void);
 
-int osi_audit_check();
+#ifdef AFS_AIX32_ENV
+static char *bufferPtr;
+static int bufferLen;
 
 static void
 audmakebuf(char *audEvent, va_list vaList)
 {
-#ifdef AFS_AIX32_ENV
     int code;
-#endif
     int vaEntry;
     int vaInt;
     afs_int32 vaLong;
     char *vaStr;
-    va_list vaLst;
     struct AFSFid *vaFid;
 
     vaEntry = va_arg(vaList, int);
@@ -87,10 +116,6 @@ audmakebuf(char *audEvent, va_list vaList)
            *(afs_int32 *) bufferPtr = vaLong;
            bufferPtr += sizeof(vaLong);
            break;
-       case AUD_LST:           /* Ptr to another list */
-           vaLst = va_arg(vaList, va_list);
-           audmakebuf(audEvent, vaLst);
-           break;
        case AUD_FID:           /* AFSFid - contains 3 entries */
            vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
            if (vaFid) {
@@ -135,37 +160,41 @@ audmakebuf(char *audEvent, va_list vaList)
        vaEntry = va_arg(vaList, int);
     }                          /* end while */
 }
+#endif
 
 static void
-printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
+printbuf(int rec, char *audEvent, char *afsName, afs_int32 hostId,
+        afs_int32 errCode, va_list vaList)
 {
     int vaEntry;
     int vaInt;
     afs_int32 vaLong;
     char *vaStr;
-    va_list vaLst;
     struct AFSFid *vaFid;
     struct AFSCBFids *vaFids;
     int num = LogThreadNum();
     struct in_addr hostAddr;
     time_t currenttime;
-    char *timeStamp;
     char tbuffer[26];
-    
+    struct tm tm;
+
     /* Don't print the timestamp or thread id if we recursed */
     if (rec == 0) {
        currenttime = time(0);
-       timeStamp = afs_ctime(&currenttime, tbuffer,
-                             sizeof(tbuffer));
-       timeStamp[24] = ' ';   /* ts[24] is the newline, 25 is the null */
-       fprintf(out, timeStamp);
+       if (strftime(tbuffer, sizeof(tbuffer), "%a %b %d %H:%M:%S %Y ",
+                    localtime_r(&currenttime, &tm)) !=0)
+           audit_ops->append_msg(tbuffer);
 
        if (num > -1)
-           fprintf(out, "[%d] ", num);
+           audit_ops->append_msg("[%d] ", num);
+    }
+
+    audit_ops->append_msg("EVENT %s CODE %d ", audEvent, errCode);
+
+    if (afsName) {
+       hostAddr.s_addr = hostId;
+       audit_ops->append_msg("NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
     }
-    
-    if (strcmp(audEvent, "VALST") != 0)
-       fprintf(out,  "EVENT %s CODE %d ", audEvent, errCode);
 
     vaEntry = va_arg(vaList, int);
     while (vaEntry != AUD_END) {
@@ -173,88 +202,80 @@ printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
        case AUD_STR:           /* String */
            vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
-               fprintf(out,  "STR %s ", vaStr);
+               audit_ops->append_msg("STR %s ", vaStr);
            else
-               fprintf(out,  "STR <null>");
+               audit_ops->append_msg("STR <null>");
            break;
        case AUD_NAME:          /* Name */
            vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
-               fprintf(out,  "NAME %s ", vaStr);
+               audit_ops->append_msg("NAME %s ", vaStr);
            else
-               fprintf(out,  "NAME <null>");
+               audit_ops->append_msg("NAME <null>");
            break;
        case AUD_ACL:           /* ACL */
            vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
-               fprintf(out,  "ACL %s ", vaStr);
+               audit_ops->append_msg("ACL %s ", vaStr);
            else
-               fprintf(out,  "ACL <null>");
+               audit_ops->append_msg("ACL <null>");
            break;
        case AUD_INT:           /* Integer */
            vaInt = va_arg(vaList, int);
-           fprintf(out,  "INT %d ", vaInt);
+           audit_ops->append_msg("INT %d ", vaInt);
            break;
        case AUD_ID:            /* ViceId */
            vaInt = va_arg(vaList, int);
-           fprintf(out,  "ID %d ", vaInt);
+           audit_ops->append_msg("ID %d ", vaInt);
            break;
        case AUD_DATE:          /* Date    */
            vaLong = va_arg(vaList, afs_int32);
-           fprintf(out, "DATE %u ", vaLong);
+           audit_ops->append_msg("DATE %u ", vaLong);
            break;
        case AUD_HOST:          /* Host ID */
            vaLong = va_arg(vaList, afs_int32);
             hostAddr.s_addr = vaLong;
-           fprintf(out, "HOST %s ", inet_ntoa(hostAddr));
+           audit_ops->append_msg("HOST %s ", inet_ntoa(hostAddr));
            break;
        case AUD_LONG:          /* afs_int32    */
            vaLong = va_arg(vaList, afs_int32);
-           fprintf(out, "LONG %d ", vaLong);
-           break;
-       case AUD_LST:           /* Ptr to another list */
-           vaLst = va_arg(vaList, va_list);
-           printbuf(out, 1, "VALST", 0, vaLst);
+           audit_ops->append_msg("LONG %d ", vaLong);
            break;
        case AUD_FID:           /* AFSFid - contains 3 entries */
            vaFid = va_arg(vaList, struct AFSFid *);
            if (vaFid)
-               fprintf(out, "FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
+               audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
                       vaFid->Unique);
            else
-               fprintf(out, "FID %u:%u:%u ", 0, 0, 0);
+               audit_ops->append_msg("FID %u:%u:%u ", 0, 0, 0);
            break;
        case AUD_FIDS:          /* array of Fids */
            vaFids = va_arg(vaList, struct AFSCBFids *);
-           vaFid = NULL;
 
            if (vaFids) {
-                int i;
-                if (vaFid)
-                    fprintf(out, "FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
+                unsigned int i;
+
+                vaFid = vaFids->AFSCBFids_val;
+
+                if (vaFid) {
+                    audit_ops->append_msg("FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
                              vaFid->Vnode, vaFid->Unique);
-                else
-                    fprintf(out, "FIDS 0 FID 0:0:0 ");
-
-                for ( i = 1; i < vaFids->AFSCBFids_len; i++ ) {
-                    vaFid = vaFids->AFSCBFids_val;
-                    if (vaFid)
-                        fprintf(out, "FID %u:%u:%u ", vaFid->Volume,
-                                 vaFid->Vnode, vaFid->Unique);
-                    else
-                        fprintf(out, "FID 0:0:0 ");
-                }
+                    for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ )
+                        audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume,
+                                vaFid->Vnode, vaFid->Unique);
+                } else
+                    audit_ops->append_msg("FIDS 0 FID 0:0:0 ");
+
             }
            break;
        default:
-           fprintf(out, "--badval-- ");
+           audit_ops->append_msg("--badval-- ");
            break;
        }                       /* end switch */
        vaEntry = va_arg(vaList, int);
     }                          /* end while */
 
-    if (strcmp(audEvent, "VALST") != 0)
-       fprintf(out, "\n");
+    audit_ops->send_msg();
 }
 
 #ifdef AFS_PTHREAD_ENV
@@ -265,7 +286,7 @@ static pthread_once_t audit_lock_once = PTHREAD_ONCE_INIT;
 static void
 osi_audit_init_lock(void)
 {
-    pthread_mutex_init(&audit_lock, NULL);
+    MUTEX_INIT(&audit_lock, "audit", MUTEX_DEFAULT, 0);
     audit_lock_initialized = 1;
 }
 #endif
@@ -283,31 +304,33 @@ osi_audit_init(void)
 /* ************************************************************************** */
 /* The routine that acually does the audit call.
  * ************************************************************************** */
-int
-osi_audit(char *audEvent,      /* Event name (15 chars or less) */
-         afs_int32 errCode,    /* The error code */
-         ...)
+static int
+osi_audit_internal(char *audEvent,     /* Event name (15 chars or less) */
+                  afs_int32 errCode,   /* The error code */
+                  char *afsName,
+                  afs_int32 hostId,
+                  va_list vaList)
 {
 #ifdef AFS_AIX32_ENV
     afs_int32 code;
     afs_int32 err;
     static char BUFFER[32768];
-#endif
     int result;
-    va_list vaList;
+#endif
 
 #ifdef AFS_PTHREAD_ENV
     /* i'm pretty sure all the server apps now call osi_audit_init(),
-     * but to be extra careful we'll leave this assert in here for a 
+     * but to be extra careful we'll leave this assert in here for a
      * while to make sure */
-    assert(audit_lock_initialized);
+    osi_Assert(audit_lock_initialized);
 #endif /* AFS_PTHREAD_ENV */
 
     if ((osi_audit_all < 0) || (osi_echo_trail < 0))
        osi_audit_check();
-    if (!osi_audit_all && !auditout)
+    if (!osi_audit_all && !auditout_open)
        return 0;
 
+#ifdef AFS_AIX32_ENV
     switch (errCode) {
     case 0:
        result = AUDIT_OK;
@@ -331,10 +354,9 @@ osi_audit(char *audEvent,  /* Event name (15 chars or less) */
        result = AUDIT_FAIL;
        break;
     }
-
-#ifdef AFS_PTHREAD_ENV
-    pthread_mutex_lock(&audit_lock);
 #endif
+
+    MUTEX_ENTER(&audit_lock);
 #ifdef AFS_AIX32_ENV
     bufferPtr = BUFFER;
 
@@ -342,42 +364,42 @@ osi_audit(char *audEvent, /* Event name (15 chars or less) */
     *(int *)bufferPtr = errCode;
     bufferPtr += sizeof(errCode);
 
-    va_start(vaList, errCode);
     audmakebuf(audEvent, vaList);
 #endif
 
-    if (osi_echo_trail) {
-       va_start(vaList, errCode);
-       printbuf(stdout, 0, audEvent, errCode, vaList);
-    }
-
 #ifdef AFS_AIX32_ENV
     bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
     code = auditlog(audEvent, result, BUFFER, bufferLen);
-#ifdef notdef
-    if (code) {
-       err = errno;
-       code = auditlog("AFS_Aud_Fail", result, &err, sizeof(err));
-       if (code)
-           printf("Error while writing audit entry: %d.\n", errno);
-    }
-#endif /* notdef */
 #else
-    if (auditout) {
-       va_start(vaList, errCode);
-       printbuf(auditout, 0, audEvent, errCode, vaList);
-       fflush(auditout);
+    if (auditout_open) {
+       printbuf(0, audEvent, afsName, hostId, errCode, vaList);
     }
 #endif
-#ifdef AFS_PTHREAD_ENV
-    pthread_mutex_unlock(&audit_lock);
-#endif
+    MUTEX_EXIT(&audit_lock);
+
+    return 0;
+}
+int
+osi_audit(char *audEvent,      /* Event name (15 chars or less) */
+         afs_int32 errCode,    /* The error code */
+         ...)
+{
+    va_list vaList;
+
+    if ((osi_audit_all < 0) || (osi_echo_trail < 0))
+       osi_audit_check();
+    if (!osi_audit_all && !auditout_open)
+       return 0;
+
+    va_start(vaList, errCode);
+    osi_audit_internal(audEvent, errCode, NULL, 0, vaList);
+    va_end(vaList);
 
     return 0;
 }
 
 /* ************************************************************************** */
-/* Given a RPC call structure, this routine extracts the name and host id from the 
+/* Given a RPC call structure, this routine extracts the name and host id from the
  * call and includes it within the audit information.
  * ************************************************************************** */
 int
@@ -387,13 +409,13 @@ osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
     struct rx_peer *peer;
     afs_int32 secClass;
     afs_int32 code;
-    char afsName[MAXKTCNAMELEN];
+    char afsName[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
     afs_int32 hostId;
     va_list vaList;
 
     if (osi_audit_all < 0)
        osi_audit_check();
-    if (!osi_audit_all && !auditout)
+    if (!osi_audit_all && !auditout_open)
        return 0;
 
     strcpy(afsName, "--Unknown--");
@@ -410,8 +432,6 @@ osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
                 char tcell[MAXKTCREALMLEN];
                 char name[MAXKTCNAMELEN];
                 char inst[MAXKTCNAMELEN];
-                char vname[256];
-                int  ilen, clen;
 
                 code =
                    rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
@@ -420,66 +440,26 @@ osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
                    osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
                    strcpy(afsName, "--NoName--");
                } else {
-                    strncpy(vname, name, sizeof(vname));
-                    if ((ilen = strlen(inst))) {
-                        if (strlen(vname) + 1 + ilen >= sizeof(vname))
-                            goto done;
-                        strcat(vname, ".");
-                        strcat(vname, inst);
-                    }
-                    if ((clen = strlen(tcell))) {
-#if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
-                        static char local_realms[AFS_NUM_LREALMS][AFS_REALM_SZ];
-                       static int  num_lrealms = -1;
-                       int i, lrealm_match;
-
-                       if (num_lrealms == -1) {
-                           for (i=0; i<AFS_NUM_LREALMS; i++) {
-                               if (afs_krb_get_lrealm(local_realms[i], i) != 0 /*KSUCCESS*/)
-                                   break;
-                           }
-
-                           if (i=0)
-                               strncpy(local_realms[0], "UNKNOWN.LOCAL.REALM", AFS_REALM_SZ);
-                           num_lrealms = i;
-                        }
-
-                       /* Check to see if the ticket cell matches one of the local realms */
-                       lrealm_match = 0;
-                       for ( i=0;i<num_lrealms;i++ ) {
-                           if (!strcasecmp(local_realms[i], tcell)) {
-                               lrealm_match = 1;
-                               break;
-                           }
-                       }
-                       /* If yes, then make sure that the name is not present in 
-                        * an exclusion list */
-                       if (lrealm_match) {
-                           char uname[256];
-                           if (inst[0])
-                               snprintf(uname,sizeof(uname),"%s.%s@%s",name,inst,tcell);
-                           else
-                               snprintf(uname,sizeof(uname),"%s@%s",name,tcell);
-
-                           if (afs_krb_exclusion(uname))
-                               lrealm_match = 0;
-                       }
-
-                       if (!lrealm_match) {    
-                            if (strlen(vname) + 1 + clen >= sizeof(vname))
-                                goto done;
-                            strcat(vname, "@");
-                            strcat(vname, tcell);
-                        }
-#endif
-                    }
-                    strcpy(afsName, vname);
-                }
+                   afs_int32 islocal = 0;
+                   if (audit_user_check.islocal) {
+                       islocal =
+                           audit_user_check.islocal(audit_user_check.rock,
+                                                    name, inst, tcell);
+                   }
+                   strlcpy(afsName, name, sizeof(afsName));
+                   if (inst[0]) {
+                       strlcat(afsName, ".", sizeof(afsName));
+                       strlcat(afsName, inst, sizeof(afsName));
+                   }
+                   if (tcell[0] && !islocal) {
+                       strlcat(afsName, "@", sizeof(afsName));
+                       strlcat(afsName, tcell, sizeof(afsName));
+                   }
+               }
            } else {            /* Unauthenticated & unknown */
                osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
                 strcpy(afsName, "--Unknown--");
            }
-       done:
            peer = rx_PeerOf(conn);     /* conn -> peer */
            if (peer)
                hostId = rx_HostOf(peer);       /* peer -> host */
@@ -492,20 +472,19 @@ osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
        osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
     }
     va_start(vaList, errCode);
-    osi_audit(audEvent, errCode, AUD_NAME, afsName, AUD_HOST, hostId, 
-              AUD_LST, vaList, AUD_END);
-
+    osi_audit_internal(audEvent, errCode, afsName, hostId, vaList);
+    va_end(vaList);
     return 0;
 }
 
 /* ************************************************************************** */
 /* Determines whether auditing is on or off by looking at the Audit file.
- * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be 
+ * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
  * enabled.
  * ************************************************************************** */
 
 int
-osi_audit_check()
+osi_audit_check(void)
 {
     FILE *fds;
     int onoff;
@@ -541,8 +520,40 @@ osi_audit_check()
 }
 
 int
-osi_audit_file(FILE *out)
+osi_audit_file(const char *fileName)
 {
-    auditout = out;
-    return 0;
+    if(!audit_ops->open_file(fileName)) {
+        auditout_open = 1;
+        return 0;
+    }
+    return 1;
+}
+
+int
+osi_audit_interface(const char *interface)
+{
+    int i;
+    for (i = 0; i < N_INTERFACES; ++i) {
+       if (strcmp(interface, audit_interfaces[i].name) == 0) {
+           audit_ops = audit_interfaces[i].ops;
+           return 0;
+       }
+    }
+
+    return 1;
+}
+
+void
+osi_audit_set_user_check(void *rock,
+                        int (*islocal) (void *rock, char *name, char *inst,
+                                        char *cell))
+{
+    audit_user_check.rock = rock;
+    audit_user_check.islocal = islocal;
+}
+
+void
+audit_PrintStats(FILE *out)
+{
+    audit_ops->print_interface_stats(out);
 }