audit-consolidate-open-20081217
[openafs.git] / src / audit / audit.c
index 93c4ba6..2cd5d5b 100644 (file)
@@ -16,6 +16,9 @@ RCSID
 #include <fcntl.h>
 #include <stdarg.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #ifdef AFS_AIX32_ENV
 #include <sys/audit.h>
 #else
@@ -37,6 +40,16 @@ RCSID
 #endif
 #include <afs/afsutil.h>
 
+/* 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      
+
 char *bufferPtr;
 int bufferLen;
 int osi_audit_all = (-1);      /* Not determined yet */
@@ -56,7 +69,7 @@ audmakebuf(char *audEvent, va_list vaList)
     int vaInt;
     afs_int32 vaLong;
     char *vaStr;
-    char *vaLst;
+    va_list vaLst;
     struct AFSFid *vaFid;
 
     vaEntry = va_arg(vaList, int);
@@ -65,7 +78,7 @@ audmakebuf(char *audEvent, va_list vaList)
        case AUD_STR:           /* String */
         case AUD_NAME:          /* Name */
         case AUD_ACL:           /* ACL */
-           vaStr = (char *)va_arg(vaList, int);
+           vaStr = (char *)va_arg(vaList, char *);
            if (vaStr) {
                strcpy(bufferPtr, vaStr);
                bufferPtr += strlen(vaStr) + 1;
@@ -87,12 +100,8 @@ audmakebuf(char *audEvent, va_list vaList)
            *(afs_int32 *) bufferPtr = vaLong;
            bufferPtr += sizeof(vaLong);
            break;
-       case AUD_LST:           /* Ptr to another list */
-           vaLst = (char *)va_arg(vaList, int);
-           audmakebuf(audEvent, vaLst);
-           break;
        case AUD_FID:           /* AFSFid - contains 3 entries */
-           vaFid = (struct AFSFid *)va_arg(vaList, int);
+           vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
            if (vaFid) {
                memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
            } else {
@@ -108,7 +117,7 @@ audmakebuf(char *audEvent, va_list vaList)
            {
                struct AFSCBFids *Fids;
 
-               Fids = (struct AFSCBFids *)va_arg(vaList, int);
+               Fids = (struct AFSCBFids *)va_arg(vaList, struct AFSCBFids *);
                if (Fids && Fids->AFSCBFids_len) {
                    *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
                    bufferPtr += sizeof(u_int);
@@ -137,13 +146,14 @@ audmakebuf(char *audEvent, va_list vaList)
 }
 
 static void
-printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
+printbuf(FILE *out, int rec, char *audEvent, char *afsName, afs_int32 hostId, 
+        afs_int32 errCode, va_list vaList)
 {
     int vaEntry;
     int vaInt;
     afs_int32 vaLong;
     char *vaStr;
-    char *vaLst;
+    va_list vaLst;
     struct AFSFid *vaFid;
     struct AFSCBFids *vaFids;
     int num = LogThreadNum();
@@ -164,28 +174,32 @@ printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
            fprintf(out, "[%d] ", num);
     }
     
-    if (strcmp(audEvent, "VALST") != 0)
-       fprintf(out,  "EVENT %s CODE %d ", audEvent, errCode);
+    fprintf(out,  "EVENT %s CODE %d ", audEvent, errCode);
+
+    if (afsName) {
+       hostAddr.s_addr = hostId;
+       fprintf(out,  "NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
+    }
 
     vaEntry = va_arg(vaList, int);
     while (vaEntry != AUD_END) {
        switch (vaEntry) {
        case AUD_STR:           /* String */
-           vaStr = (char *)va_arg(vaList, int);
+           vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
                fprintf(out,  "STR %s ", vaStr);
            else
                fprintf(out,  "STR <null>");
            break;
        case AUD_NAME:          /* Name */
-           vaStr = (char *)va_arg(vaList, int);
+           vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
                fprintf(out,  "NAME %s ", vaStr);
            else
                fprintf(out,  "NAME <null>");
            break;
        case AUD_ACL:           /* ACL */
-           vaStr = (char *)va_arg(vaList, int);
+           vaStr = (char *)va_arg(vaList, char *);
            if (vaStr)
                fprintf(out,  "ACL %s ", vaStr);
            else
@@ -212,12 +226,8 @@ printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
            vaLong = va_arg(vaList, afs_int32);
            fprintf(out, "LONG %d ", vaLong);
            break;
-       case AUD_LST:           /* Ptr to another list */
-           vaLst = (char *)va_arg(vaList, int);
-           printbuf(out, 1, "VALST", 0, vaLst);
-           break;
        case AUD_FID:           /* AFSFid - contains 3 entries */
-           vaFid = (struct AFSFid *)va_arg(vaList, int);
+           vaFid = va_arg(vaList, struct AFSFid *);
            if (vaFid)
                fprintf(out, "FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
                       vaFid->Unique);
@@ -225,25 +235,22 @@ printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
                fprintf(out, "FID %u:%u:%u ", 0, 0, 0);
            break;
        case AUD_FIDS:          /* array of Fids */
-           vaFids = (struct AFSCBFids *)va_arg(vaList, int);
-           vaFid = NULL;
+           vaFids = va_arg(vaList, struct AFSCBFids *);
 
            if (vaFids) {
                 int i;
-                if (vaFid)
+                
+                vaFid = vaFids->AFSCBFids_val;
+                
+                if (vaFid) {
                     fprintf(out, "FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
                              vaFid->Vnode, vaFid->Unique);
-                else
+                    for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ ) 
+                        fprintf(out, "FID %u:%u:%u ", 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 ");
-                }
             }
            break;
        default:
@@ -253,41 +260,64 @@ printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
        vaEntry = va_arg(vaList, int);
     }                          /* end while */
 
-    if (strcmp(audEvent, "VALST") != 0)
-       fprintf(out, "\n");
+    fprintf(out, "\n");
+}
+
+#ifdef AFS_PTHREAD_ENV
+static pthread_mutex_t audit_lock;
+static volatile afs_int32   audit_lock_initialized = 0;
+static pthread_once_t audit_lock_once = PTHREAD_ONCE_INIT;
+
+static void
+osi_audit_init_lock(void)
+{
+    pthread_mutex_init(&audit_lock, NULL);
+    audit_lock_initialized = 1;
+}
+#endif
+
+void
+osi_audit_init(void)
+{
+#ifdef AFS_PTHREAD_ENV
+    if (!audit_lock_initialized) {
+       pthread_once(&audit_lock_once, osi_audit_init_lock);
+    }
+#endif /* AFS_PTHREAD_ENV */
 }
 
 /* ************************************************************************** */
 /* 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 */
-         ...)
+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 vaCopy;
 
-    va_list vaList;
-#ifdef AFS_AIX32_ENV
-    static struct Lock audbuflock = { 0, 0, 0, 0,
 #ifdef AFS_PTHREAD_ENV
-       PTHREAD_MUTEX_INITIALIZER,
-       PTHREAD_COND_INITIALIZER,
-       PTHREAD_COND_INITIALIZER
+    /* 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 
+     * while to make sure */
+    assert(audit_lock_initialized);
 #endif /* AFS_PTHREAD_ENV */
-    };
-    static char BUFFER[32768];
-#endif
 
     if ((osi_audit_all < 0) || (osi_echo_trail < 0))
        osi_audit_check();
     if (!osi_audit_all && !auditout)
        return 0;
 
+    va_copy(vaCopy, vaList);
+
     switch (errCode) {
     case 0:
        result = AUDIT_OK;
@@ -312,42 +342,54 @@ osi_audit(char *audEvent, /* Event name (15 chars or less) */
        break;
     }
 
+#ifdef AFS_PTHREAD_ENV
+    pthread_mutex_lock(&audit_lock);
+#endif
 #ifdef AFS_AIX32_ENV
-    ObtainWriteLock(&audbuflock);
     bufferPtr = BUFFER;
 
     /* Put the error code into the buffer list */
     *(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);
+       printbuf(stdout, 0, audEvent, afsName, hostId, errCode, vaList);
     }
+    va_end(vaCopy);
 
 #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 */
-    ReleaseWriteLock(&audbuflock);
 #else
     if (auditout) {
-       va_start(vaList, errCode);
-       printbuf(auditout, 0, audEvent, errCode, vaList);
+       printbuf(auditout, 0, audEvent, afsName, hostId, errCode, vaList);
        fflush(auditout);
     }
 #endif
+#ifdef AFS_PTHREAD_ENV
+    pthread_mutex_unlock(&audit_lock);
+#endif
+
+    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)
+       return 0;
+
+    va_start(vaList, errCode);
+    osi_audit_internal(audEvent, errCode, NULL, 0, vaList);
+    va_end(vaList);
 
     return 0;
 }
@@ -405,12 +447,43 @@ osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
                     }
                     if ((clen = strlen(tcell))) {
 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
-                        static char local_realm[AFS_REALM_SZ] = "";
-                        if (!local_realm[0]) {
-                            if (afs_krb_get_lrealm(local_realm, 0) != 0 /*KSUCCESS*/)
-                                strncpy(local_realm, "UNKNOWN.LOCAL.REALM", AFS_REALM_SZ);
+                        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;
                         }
-                        if (strcasecmp(local_realm, tcell)) {
+
+                       /* 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, "@");
@@ -437,9 +510,8 @@ 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;
 }
 
@@ -486,8 +558,35 @@ osi_audit_check()
 }
 
 int
-osi_audit_file(FILE *out)
+osi_audit_file(char *fileName)
 {
-    auditout = out;
+    int tempfd, flags;
+    char oldName[MAXPATHLEN];
+    
+#ifndef AFS_NT40_ENV
+    struct stat statbuf;
+    
+    if ((lstat(fileName, &statbuf) == 0)
+        && (S_ISFIFO(statbuf.st_mode))) {
+        flags = O_WRONLY | O_NONBLOCK;
+    } else 
+#endif
+    {
+        strcpy(oldName, fileName);
+        strcat(oldName, ".old");
+        renamefile(fileName, oldName);
+        flags = O_WRONLY | O_TRUNC | O_CREAT;
+    }
+    tempfd = open(fileName, flags, 0666);
+    if (tempfd > -1) {
+        auditout = fdopen(tempfd, "a");
+        if (!auditout) {
+            printf("Warning: auditlog %s not writable, ignored.\n", fileName);
+            return 1;
+        }
+    } else { 
+        printf("Warning: auditlog %s not writable, ignored.\n", fileName);
+        return 1;
+    }
     return 0;
 }