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>
17 #include <sys/types.h>
23 #include <sys/audit.h>
27 #define AUDIT_FAIL_AUTH 2
28 #define AUDIT_FAIL_ACCESS 3
29 #define AUDIT_FAIL_PRIV 4
30 #endif /* AFS_AIX32_ENV */
33 #include "afs/afsint.h"
37 #include "audit-api.h"
40 #include <sys/audit.h>
42 #include <afs/afsutil.h>
44 /* C99 requires va_copy. Older versions of GCC provide __va_copy. Per t
45 Autoconf manual, memcpy is a generally portable fallback. */
48 # define va_copy(d, s) __va_copy((d), (s))
50 # define va_copy(d, s) memcpy(&(d), &(s), sizeof(va_list))
54 extern struct osi_audit_ops audit_file_ops;
56 extern struct osi_audit_ops audit_sysvmq_ops;
61 const struct osi_audit_ops *ops;
62 } audit_interfaces[] = {
64 { "file", &audit_file_ops },
66 { "sysvmq", &audit_sysvmq_ops },
70 #define N_INTERFACES (sizeof(audit_interfaces) / sizeof(audit_interfaces[0]))
72 /* default to `file' audit interface */
73 static const struct osi_audit_ops *audit_ops = &audit_file_ops;
75 static int osi_audit_all = (-1); /* Not determined yet */
76 static int osi_echo_trail = (-1);
78 static int auditout_open = 0;
80 static int osi_audit_check(void);
83 static char *bufferPtr;
87 audmakebuf(char *audEvent, va_list vaList)
96 vaEntry = va_arg(vaList, int);
97 while (vaEntry != AUD_END) {
99 case AUD_STR: /* String */
100 case AUD_NAME: /* Name */
101 case AUD_ACL: /* ACL */
102 vaStr = (char *)va_arg(vaList, char *);
104 strcpy(bufferPtr, vaStr);
105 bufferPtr += strlen(vaStr) + 1;
107 strcpy(bufferPtr, "");
111 case AUD_INT: /* Integer */
112 case AUD_ID: /* ViceId */
113 vaInt = va_arg(vaList, int);
114 *(int *)bufferPtr = vaInt;
115 bufferPtr += sizeof(vaInt);
117 case AUD_DATE: /* Date */
118 case AUD_HOST: /* Host ID */
119 case AUD_LONG: /* long */
120 vaLong = va_arg(vaList, afs_int32);
121 *(afs_int32 *) bufferPtr = vaLong;
122 bufferPtr += sizeof(vaLong);
124 case AUD_FID: /* AFSFid - contains 3 entries */
125 vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
127 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
129 memset(bufferPtr, 0, sizeof(struct AFSFid));
131 bufferPtr += sizeof(struct AFSFid);
134 /* Whole array of fids-- don't know how to handle variable length audit
135 * data with AIX audit package, so for now we just store the first fid.
136 * Better one than none. */
139 struct AFSCBFids *Fids;
141 Fids = (struct AFSCBFids *)va_arg(vaList, struct AFSCBFids *);
142 if (Fids && Fids->AFSCBFids_len) {
143 *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
144 bufferPtr += sizeof(u_int);
145 memcpy(bufferPtr, Fids->AFSCBFids_val,
146 sizeof(struct AFSFid));
148 *((u_int *) bufferPtr) = 0;
149 bufferPtr += sizeof(u_int);
150 memset(bufferPtr, 0, sizeof(struct AFSFid));
152 bufferPtr += sizeof(struct AFSFid);
158 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
159 (strlen(audEvent) + 1));
165 vaEntry = va_arg(vaList, int);
171 printbuf(int rec, char *audEvent, char *afsName, afs_int32 hostId,
172 afs_int32 errCode, va_list vaList)
178 struct AFSFid *vaFid;
179 struct AFSCBFids *vaFids;
180 int num = LogThreadNum();
181 struct in_addr hostAddr;
186 /* Don't print the timestamp or thread id if we recursed */
188 currenttime = time(0);
189 timeStamp = afs_ctime(¤ttime, tbuffer,
191 timeStamp[24] = ' '; /* ts[24] is the newline, 25 is the null */
192 audit_ops->append_msg(timeStamp);
195 audit_ops->append_msg("[%d] ", num);
198 audit_ops->append_msg("EVENT %s CODE %d ", audEvent, errCode);
201 hostAddr.s_addr = hostId;
202 audit_ops->append_msg("NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
205 vaEntry = va_arg(vaList, int);
206 while (vaEntry != AUD_END) {
208 case AUD_STR: /* String */
209 vaStr = (char *)va_arg(vaList, char *);
211 audit_ops->append_msg("STR %s ", vaStr);
213 audit_ops->append_msg("STR <null>");
215 case AUD_NAME: /* Name */
216 vaStr = (char *)va_arg(vaList, char *);
218 audit_ops->append_msg("NAME %s ", vaStr);
220 audit_ops->append_msg("NAME <null>");
222 case AUD_ACL: /* ACL */
223 vaStr = (char *)va_arg(vaList, char *);
225 audit_ops->append_msg("ACL %s ", vaStr);
227 audit_ops->append_msg("ACL <null>");
229 case AUD_INT: /* Integer */
230 vaInt = va_arg(vaList, int);
231 audit_ops->append_msg("INT %d ", vaInt);
233 case AUD_ID: /* ViceId */
234 vaInt = va_arg(vaList, int);
235 audit_ops->append_msg("ID %d ", vaInt);
237 case AUD_DATE: /* Date */
238 vaLong = va_arg(vaList, afs_int32);
239 audit_ops->append_msg("DATE %u ", vaLong);
241 case AUD_HOST: /* Host ID */
242 vaLong = va_arg(vaList, afs_int32);
243 hostAddr.s_addr = vaLong;
244 audit_ops->append_msg("HOST %s ", inet_ntoa(hostAddr));
246 case AUD_LONG: /* afs_int32 */
247 vaLong = va_arg(vaList, afs_int32);
248 audit_ops->append_msg("LONG %d ", vaLong);
250 case AUD_FID: /* AFSFid - contains 3 entries */
251 vaFid = va_arg(vaList, struct AFSFid *);
253 audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
256 audit_ops->append_msg("FID %u:%u:%u ", 0, 0, 0);
258 case AUD_FIDS: /* array of Fids */
259 vaFids = va_arg(vaList, struct AFSCBFids *);
264 vaFid = vaFids->AFSCBFids_val;
267 audit_ops->append_msg("FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
268 vaFid->Vnode, vaFid->Unique);
269 for ( i = 1; i < vaFids->AFSCBFids_len; i++, vaFid++ )
270 audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume,
271 vaFid->Vnode, vaFid->Unique);
273 audit_ops->append_msg("FIDS 0 FID 0:0:0 ");
278 audit_ops->append_msg("--badval-- ");
281 vaEntry = va_arg(vaList, int);
284 audit_ops->send_msg();
287 #ifdef AFS_PTHREAD_ENV
288 static pthread_mutex_t audit_lock;
289 static volatile afs_int32 audit_lock_initialized = 0;
290 static pthread_once_t audit_lock_once = PTHREAD_ONCE_INIT;
293 osi_audit_init_lock(void)
295 MUTEX_INIT(&audit_lock, "audit", MUTEX_DEFAULT, 0);
296 audit_lock_initialized = 1;
303 #ifdef AFS_PTHREAD_ENV
304 if (!audit_lock_initialized) {
305 pthread_once(&audit_lock_once, osi_audit_init_lock);
307 #endif /* AFS_PTHREAD_ENV */
310 /* ************************************************************************** */
311 /* The routine that acually does the audit call.
312 * ************************************************************************** */
314 osi_audit_internal(char *audEvent, /* Event name (15 chars or less) */
315 afs_int32 errCode, /* The error code */
323 static char BUFFER[32768];
327 #ifdef AFS_PTHREAD_ENV
328 /* i'm pretty sure all the server apps now call osi_audit_init(),
329 * but to be extra careful we'll leave this assert in here for a
330 * while to make sure */
331 osi_Assert(audit_lock_initialized);
332 #endif /* AFS_PTHREAD_ENV */
334 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
336 if (!osi_audit_all && !auditout_open)
344 case KANOAUTH: /* kautils.h */
345 case RXKADNOAUTH: /* rxkad.h */
346 result = AUDIT_FAIL_AUTH;
348 case EPERM: /* errno.h */
349 case EACCES: /* errno.h */
350 case PRPERM: /* pterror.h */
351 result = AUDIT_FAIL_ACCESS;
353 case VL_PERM: /* vlserver.h */
354 case BUDB_NOTPERMITTED: /* budb_errs.h */
355 case BZACCESS: /* bnode.h */
356 case VOLSERBAD_ACCESS: /* volser.h */
357 result = AUDIT_FAIL_PRIV;
365 MUTEX_ENTER(&audit_lock);
369 /* Put the error code into the buffer list */
370 *(int *)bufferPtr = errCode;
371 bufferPtr += sizeof(errCode);
373 audmakebuf(audEvent, vaList);
377 bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
378 code = auditlog(audEvent, result, BUFFER, bufferLen);
381 printbuf(0, audEvent, afsName, hostId, errCode, vaList);
384 MUTEX_EXIT(&audit_lock);
389 osi_audit(char *audEvent, /* Event name (15 chars or less) */
390 afs_int32 errCode, /* The error code */
395 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
397 if (!osi_audit_all && !auditout_open)
400 va_start(vaList, errCode);
401 osi_audit_internal(audEvent, errCode, NULL, 0, vaList);
407 /* ************************************************************************** */
408 /* Given a RPC call structure, this routine extracts the name and host id from the
409 * call and includes it within the audit information.
410 * ************************************************************************** */
412 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
414 struct rx_connection *conn;
415 struct rx_peer *peer;
418 char afsName[MAXKTCNAMELEN];
422 if (osi_audit_all < 0)
424 if (!osi_audit_all && !auditout_open)
427 strcpy(afsName, "--Unknown--");
431 conn = rx_ConnectionOf(call); /* call -> conn) */
433 secClass = rx_SecurityClassOf(conn); /* conn -> securityIndex */
434 if (secClass == 0) { /* unauthenticated */
435 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
436 strcpy(afsName, "--UnAuth--");
437 } else if (secClass == 2) { /* authenticated */
438 char tcell[MAXKTCREALMLEN];
439 char name[MAXKTCNAMELEN];
440 char inst[MAXKTCNAMELEN];
445 rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
448 osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
449 strcpy(afsName, "--NoName--");
451 strncpy(vname, name, sizeof(vname));
452 if ((ilen = strlen(inst))) {
453 if (strlen(vname) + 1 + ilen >= sizeof(vname))
458 if ((clen = strlen(tcell))) {
459 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
460 static char local_realms[AFS_NUM_LREALMS][AFS_REALM_SZ];
461 static int num_lrealms = -1;
464 if (num_lrealms == -1) {
465 for (i = 0; i < AFS_NUM_LREALMS; i++) {
466 if (afs_krb_get_lrealm(local_realms[i], i) != 0 /*KSUCCESS*/)
471 strncpy(local_realms[0], "UNKNOWN.LOCAL.REALM", AFS_REALM_SZ);
475 /* Check to see if the ticket cell matches one of the local realms */
477 for (i = 0; i < num_lrealms ; i++ ) {
478 if (!strcasecmp(local_realms[i], tcell)) {
483 /* If yes, then make sure that the name is not present in
484 * an exclusion list */
488 snprintf(uname,sizeof(uname),"%s.%s@%s",name,inst,tcell);
490 snprintf(uname,sizeof(uname),"%s@%s",name,tcell);
492 if (afs_krb_exclusion(uname))
497 if (strlen(vname) + 1 + clen >= sizeof(vname))
500 strcat(vname, tcell);
504 strcpy(afsName, vname);
506 } else { /* Unauthenticated & unknown */
507 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
508 strcpy(afsName, "--Unknown--");
511 peer = rx_PeerOf(conn); /* conn -> peer */
513 hostId = rx_HostOf(peer); /* peer -> host */
515 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
516 } else { /* null conn */
517 osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
519 } else { /* null call */
520 osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
522 va_start(vaList, errCode);
523 osi_audit_internal(audEvent, errCode, afsName, hostId, vaList);
528 /* ************************************************************************** */
529 /* Determines whether auditing is on or off by looking at the Audit file.
530 * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
532 * ************************************************************************** */
535 osi_audit_check(void)
541 osi_audit_all = 1; /* say we made check (>= 0) */
542 /* and assume audit all events (for now) */
543 onoff = 0; /* assume we will turn auditing off */
544 osi_echo_trail = 0; /* assume no echoing */
546 fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
548 while (fscanf(fds, "%256s", event) > 0) {
549 if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
552 if (strcmp(event, "Echo_Trail") == 0)
558 /* Audit this event all of the time */
560 osi_audit("AFS_Aud_On", 0, AUD_END);
562 osi_audit("AFS_Aud_Off", 0, AUD_END);
564 /* Now set whether we audit all events from here on out */
565 osi_audit_all = onoff;
571 osi_audit_file(const char *fileName)
573 if(!audit_ops->open_file(fileName)) {
581 osi_audit_interface(const char *interface)
584 for (i = 0; i < N_INTERFACES; ++i) {
585 if (strcmp(interface, audit_interfaces[i].name) == 0) {
586 audit_ops = audit_interfaces[i].ops;
595 audit_PrintStats(FILE *out)
597 audit_ops->print_interface_stats(out);