/*
* 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
#define AUDIT_FAIL_ACCESS 3
#define AUDIT_FAIL_PRIV 4
#endif /* AFS_AIX32_ENV */
-#include <errno.h>
+#include <afs/opr.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>
-/* 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 };
-char *bufferPtr;
-int bufferLen;
-int osi_audit_all = (-1); /* Not determined yet */
-int osi_echo_trail = (-1);
+static struct {
+ const char *name;
+ const struct osi_audit_ops *ops;
+} audit_interfaces[] = {
-FILE *auditout = NULL;
+ { "file", &audit_file_ops },
+#ifdef HAVE_SYS_IPC_H
+ { "sysvmq", &audit_sysvmq_ops },
+#endif
+};
-int osi_audit_check();
+#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;
+
+static int osi_audit_check(void);
+
+#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);
vaEntry = va_arg(vaList, int);
} /* end while */
}
+#endif
static void
-printbuf(FILE *out, int rec, char *audEvent, char *afsName, afs_int32 hostId,
+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(¤ttime, 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(¤ttime, &tm)) !=0)
+ audit_ops->append_msg(tbuffer);
if (num > -1)
- fprintf(out, "[%d] ", num);
+ audit_ops->append_msg("[%d] ", num);
}
-
- fprintf(out, "EVENT %s CODE %d ", audEvent, errCode);
+
+ audit_ops->append_msg("EVENT %s CODE %d ", audEvent, errCode);
if (afsName) {
hostAddr.s_addr = hostId;
- fprintf(out, "NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
+ audit_ops->append_msg("NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
}
vaEntry = va_arg(vaList, int);
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);
+ 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 *);
if (vaFids) {
- int i;
-
+ unsigned int i;
+
vaFid = vaFids->AFSCBFids_val;
-
+
if (vaFid) {
- fprintf(out, "FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
+ audit_ops->append_msg("FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
vaFid->Vnode, vaFid->Unique);
- for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ )
- fprintf(out, "FID %u:%u:%u ", vaFid->Volume,
+ for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ )
+ audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume,
vaFid->Vnode, vaFid->Unique);
} else
- fprintf(out, "FIDS 0 FID 0:0:0 ");
+ 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 */
- fprintf(out, "\n");
+ audit_ops->send_msg();
}
#ifdef AFS_PTHREAD_ENV
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
/* ************************************************************************** */
/* The routine that acually does the audit call.
* ************************************************************************** */
-int
+static int
osi_audit_internal(char *audEvent, /* Event name (15 chars or less) */
afs_int32 errCode, /* The error code */
char *afsName,
afs_int32 code;
afs_int32 err;
static char BUFFER[32768];
-#endif
int result;
- va_list vaCopy;
+#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);
+ opr_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;
- va_copy(vaCopy, vaList);
-
+#ifdef AFS_AIX32_ENV
switch (errCode) {
case 0:
result = AUDIT_OK;
result = AUDIT_FAIL;
break;
}
-
-#ifdef AFS_PTHREAD_ENV
- pthread_mutex_lock(&audit_lock);
#endif
+
+ MUTEX_ENTER(&audit_lock);
#ifdef AFS_AIX32_ENV
bufferPtr = BUFFER;
audmakebuf(audEvent, vaList);
#endif
- if (osi_echo_trail) {
- 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);
#else
- if (auditout) {
- printbuf(auditout, 0, audEvent, afsName, hostId, 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;
}
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;
va_start(vaList, errCode);
}
/* ************************************************************************** */
-/* 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
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--");
conn = rx_ConnectionOf(call); /* call -> conn) */
if (conn) {
secClass = rx_SecurityClassOf(conn); /* conn -> securityIndex */
- if (secClass == 0) { /* unauthenticated */
+ if (secClass == RX_SECIDX_NULL) { /* unauthenticated */
osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
strcpy(afsName, "--UnAuth--");
- } else if (secClass == 2) { /* authenticated */
+ } else if (secClass == RX_SECIDX_KAD || secClass == RX_SECIDX_KAE) {
+ /* authenticated with rxkad */
char tcell[MAXKTCREALMLEN];
char name[MAXKTCNAMELEN];
char inst[MAXKTCNAMELEN];
- char vname[256];
- int ilen, clen;
code =
rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
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);
- }
- } else { /* Unauthenticated & unknown */
+ 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 and/or 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 */
/* ************************************************************************** */
/* 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;
}
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);
}