2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/audit.h>
20 #define AUDIT_FAIL_AUTH 2
21 #define AUDIT_FAIL_ACCESS 3
22 #define AUDIT_FAIL_PRIV 4
23 #endif /* AFS_AIX32_ENV */
26 #include "afs/afsint.h"
30 #include "audit-api.h"
33 #include <afs/afsutil.h>
35 /* C99 requires va_copy. Older versions of GCC provide __va_copy. Per t
36 Autoconf manual, memcpy is a generally portable fallback. */
39 # define va_copy(d, s) __va_copy((d), (s))
41 # define va_copy(d, s) memcpy(&(d), &(s), sizeof(va_list))
45 extern struct osi_audit_ops audit_file_ops;
47 extern struct osi_audit_ops audit_sysvmq_ops;
52 int (*islocal)(void *rock, char *name, char *inst, char *cell);
53 } audit_user_check = { NULL, NULL };
57 const struct osi_audit_ops *ops;
58 } audit_interfaces[] = {
60 { "file", &audit_file_ops },
62 { "sysvmq", &audit_sysvmq_ops },
66 #define N_INTERFACES (sizeof(audit_interfaces) / sizeof(audit_interfaces[0]))
68 /* default to `file' audit interface */
69 static const struct osi_audit_ops *audit_ops = &audit_file_ops;
71 static int osi_audit_all = (-1); /* Not determined yet */
72 static int osi_echo_trail = (-1);
74 static int auditout_open = 0;
76 static int osi_audit_check(void);
79 static char *bufferPtr;
83 audmakebuf(char *audEvent, va_list vaList)
92 vaEntry = va_arg(vaList, int);
93 while (vaEntry != AUD_END) {
95 case AUD_STR: /* String */
96 case AUD_NAME: /* Name */
97 case AUD_ACL: /* ACL */
98 vaStr = (char *)va_arg(vaList, char *);
100 strcpy(bufferPtr, vaStr);
101 bufferPtr += strlen(vaStr) + 1;
103 strcpy(bufferPtr, "");
107 case AUD_INT: /* Integer */
108 case AUD_ID: /* ViceId */
109 vaInt = va_arg(vaList, int);
110 *(int *)bufferPtr = vaInt;
111 bufferPtr += sizeof(vaInt);
113 case AUD_DATE: /* Date */
114 case AUD_HOST: /* Host ID */
115 case AUD_LONG: /* long */
116 vaLong = va_arg(vaList, afs_int32);
117 *(afs_int32 *) bufferPtr = vaLong;
118 bufferPtr += sizeof(vaLong);
120 case AUD_FID: /* AFSFid - contains 3 entries */
121 vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
123 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
125 memset(bufferPtr, 0, sizeof(struct AFSFid));
127 bufferPtr += sizeof(struct AFSFid);
130 /* Whole array of fids-- don't know how to handle variable length audit
131 * data with AIX audit package, so for now we just store the first fid.
132 * Better one than none. */
135 struct AFSCBFids *Fids;
137 Fids = (struct AFSCBFids *)va_arg(vaList, struct AFSCBFids *);
138 if (Fids && Fids->AFSCBFids_len) {
139 *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
140 bufferPtr += sizeof(u_int);
141 memcpy(bufferPtr, Fids->AFSCBFids_val,
142 sizeof(struct AFSFid));
144 *((u_int *) bufferPtr) = 0;
145 bufferPtr += sizeof(u_int);
146 memset(bufferPtr, 0, sizeof(struct AFSFid));
148 bufferPtr += sizeof(struct AFSFid);
154 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
155 (strlen(audEvent) + 1));
161 vaEntry = va_arg(vaList, int);
167 printbuf(int rec, char *audEvent, char *afsName, afs_int32 hostId,
168 afs_int32 errCode, va_list vaList)
174 struct AFSFid *vaFid;
175 struct AFSCBFids *vaFids;
176 int num = LogThreadNum();
177 struct in_addr hostAddr;
182 /* Don't print the timestamp or thread id if we recursed */
184 currenttime = time(0);
185 if (strftime(tbuffer, sizeof(tbuffer), "%a %b %d %H:%M:%S %Y ",
186 localtime_r(¤ttime, &tm)) !=0)
187 audit_ops->append_msg(tbuffer);
190 audit_ops->append_msg("[%d] ", num);
193 audit_ops->append_msg("EVENT %s CODE %d ", audEvent, errCode);
196 hostAddr.s_addr = hostId;
197 audit_ops->append_msg("NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
200 vaEntry = va_arg(vaList, int);
201 while (vaEntry != AUD_END) {
203 case AUD_STR: /* String */
204 vaStr = (char *)va_arg(vaList, char *);
206 audit_ops->append_msg("STR %s ", vaStr);
208 audit_ops->append_msg("STR <null>");
210 case AUD_NAME: /* Name */
211 vaStr = (char *)va_arg(vaList, char *);
213 audit_ops->append_msg("NAME %s ", vaStr);
215 audit_ops->append_msg("NAME <null>");
217 case AUD_ACL: /* ACL */
218 vaStr = (char *)va_arg(vaList, char *);
220 audit_ops->append_msg("ACL %s ", vaStr);
222 audit_ops->append_msg("ACL <null>");
224 case AUD_INT: /* Integer */
225 vaInt = va_arg(vaList, int);
226 audit_ops->append_msg("INT %d ", vaInt);
228 case AUD_ID: /* ViceId */
229 vaInt = va_arg(vaList, int);
230 audit_ops->append_msg("ID %d ", vaInt);
232 case AUD_DATE: /* Date */
233 vaLong = va_arg(vaList, afs_int32);
234 audit_ops->append_msg("DATE %u ", vaLong);
236 case AUD_HOST: /* Host ID */
237 vaLong = va_arg(vaList, afs_int32);
238 hostAddr.s_addr = vaLong;
239 audit_ops->append_msg("HOST %s ", inet_ntoa(hostAddr));
241 case AUD_LONG: /* afs_int32 */
242 vaLong = va_arg(vaList, afs_int32);
243 audit_ops->append_msg("LONG %d ", vaLong);
245 case AUD_FID: /* AFSFid - contains 3 entries */
246 vaFid = va_arg(vaList, struct AFSFid *);
248 audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
251 audit_ops->append_msg("FID %u:%u:%u ", 0, 0, 0);
253 case AUD_FIDS: /* array of Fids */
254 vaFids = va_arg(vaList, struct AFSCBFids *);
259 vaFid = vaFids->AFSCBFids_val;
262 audit_ops->append_msg("FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
263 vaFid->Vnode, vaFid->Unique);
264 for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ )
265 audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume,
266 vaFid->Vnode, vaFid->Unique);
268 audit_ops->append_msg("FIDS 0 FID 0:0:0 ");
273 audit_ops->append_msg("--badval-- ");
276 vaEntry = va_arg(vaList, int);
279 audit_ops->send_msg();
282 #ifdef AFS_PTHREAD_ENV
283 static pthread_mutex_t audit_lock;
284 static volatile afs_int32 audit_lock_initialized = 0;
285 static pthread_once_t audit_lock_once = PTHREAD_ONCE_INIT;
288 osi_audit_init_lock(void)
290 MUTEX_INIT(&audit_lock, "audit", MUTEX_DEFAULT, 0);
291 audit_lock_initialized = 1;
298 #ifdef AFS_PTHREAD_ENV
299 if (!audit_lock_initialized) {
300 pthread_once(&audit_lock_once, osi_audit_init_lock);
302 #endif /* AFS_PTHREAD_ENV */
305 /* ************************************************************************** */
306 /* The routine that acually does the audit call.
307 * ************************************************************************** */
309 osi_audit_internal(char *audEvent, /* Event name (15 chars or less) */
310 afs_int32 errCode, /* The error code */
318 static char BUFFER[32768];
322 #ifdef AFS_PTHREAD_ENV
323 /* i'm pretty sure all the server apps now call osi_audit_init(),
324 * but to be extra careful we'll leave this assert in here for a
325 * while to make sure */
326 opr_Assert(audit_lock_initialized);
327 #endif /* AFS_PTHREAD_ENV */
329 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
331 if (!osi_audit_all && !auditout_open)
339 case KANOAUTH: /* kautils.h */
340 case RXKADNOAUTH: /* rxkad.h */
341 result = AUDIT_FAIL_AUTH;
343 case EPERM: /* errno.h */
344 case EACCES: /* errno.h */
345 case PRPERM: /* pterror.h */
346 result = AUDIT_FAIL_ACCESS;
348 case VL_PERM: /* vlserver.h */
349 case BUDB_NOTPERMITTED: /* budb_errs.h */
350 case BZACCESS: /* bnode.h */
351 case VOLSERBAD_ACCESS: /* volser.h */
352 result = AUDIT_FAIL_PRIV;
360 MUTEX_ENTER(&audit_lock);
364 /* Put the error code into the buffer list */
365 *(int *)bufferPtr = errCode;
366 bufferPtr += sizeof(errCode);
368 audmakebuf(audEvent, vaList);
372 bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
373 code = auditlog(audEvent, result, BUFFER, bufferLen);
376 printbuf(0, audEvent, afsName, hostId, errCode, vaList);
379 MUTEX_EXIT(&audit_lock);
384 osi_audit(char *audEvent, /* Event name (15 chars or less) */
385 afs_int32 errCode, /* The error code */
390 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
392 if (!osi_audit_all && !auditout_open)
395 va_start(vaList, errCode);
396 osi_audit_internal(audEvent, errCode, NULL, 0, vaList);
402 /* ************************************************************************** */
403 /* Given a RPC call structure, this routine extracts the name and host id from the
404 * call and includes it within the audit information.
405 * ************************************************************************** */
407 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
409 struct rx_connection *conn;
410 struct rx_peer *peer;
413 char afsName[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
417 if (osi_audit_all < 0)
419 if (!osi_audit_all && !auditout_open)
422 strcpy(afsName, "--Unknown--");
426 conn = rx_ConnectionOf(call); /* call -> conn) */
428 secClass = rx_SecurityClassOf(conn); /* conn -> securityIndex */
429 if (secClass == 0) { /* unauthenticated */
430 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
431 strcpy(afsName, "--UnAuth--");
432 } else if (secClass == 2) { /* authenticated */
433 char tcell[MAXKTCREALMLEN];
434 char name[MAXKTCNAMELEN];
435 char inst[MAXKTCNAMELEN];
438 rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
441 osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
442 strcpy(afsName, "--NoName--");
444 afs_int32 islocal = 0;
445 if (audit_user_check.islocal) {
447 audit_user_check.islocal(audit_user_check.rock,
450 strlcpy(afsName, name, sizeof(afsName));
452 strlcat(afsName, ".", sizeof(afsName));
453 strlcat(afsName, inst, sizeof(afsName));
455 if (tcell[0] && !islocal) {
456 strlcat(afsName, "@", sizeof(afsName));
457 strlcat(afsName, tcell, sizeof(afsName));
460 } else { /* Unauthenticated & unknown */
461 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
462 strcpy(afsName, "--Unknown--");
464 peer = rx_PeerOf(conn); /* conn -> peer */
466 hostId = rx_HostOf(peer); /* peer -> host */
468 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
469 } else { /* null conn */
470 osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
472 } else { /* null call */
473 osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
475 va_start(vaList, errCode);
476 osi_audit_internal(audEvent, errCode, afsName, hostId, vaList);
481 /* ************************************************************************** */
482 /* Determines whether auditing is on or off by looking at the Audit file.
483 * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
485 * ************************************************************************** */
488 osi_audit_check(void)
494 osi_audit_all = 1; /* say we made check (>= 0) */
495 /* and assume audit all events (for now) */
496 onoff = 0; /* assume we will turn auditing off */
497 osi_echo_trail = 0; /* assume no echoing */
499 fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
501 while (fscanf(fds, "%256s", event) > 0) {
502 if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
505 if (strcmp(event, "Echo_Trail") == 0)
511 /* Audit this event all of the time */
513 osi_audit("AFS_Aud_On", 0, AUD_END);
515 osi_audit("AFS_Aud_Off", 0, AUD_END);
517 /* Now set whether we audit all events from here on out */
518 osi_audit_all = onoff;
524 osi_audit_file(const char *fileName)
526 if(!audit_ops->open_file(fileName)) {
534 osi_audit_interface(const char *interface)
537 for (i = 0; i < N_INTERFACES; ++i) {
538 if (strcmp(interface, audit_interfaces[i].name) == 0) {
539 audit_ops = audit_interfaces[i].ops;
548 osi_audit_set_user_check(void *rock,
549 int (*islocal) (void *rock, char *name, char *inst,
552 audit_user_check.rock = rock;
553 audit_user_check.islocal = islocal;
557 audit_PrintStats(FILE *out)
559 audit_ops->print_interface_stats(out);