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>
20 #include <sys/audit.h>
24 #define AUDIT_FAIL_AUTH 2
25 #define AUDIT_FAIL_ACCESS 3
26 #define AUDIT_FAIL_PRIV 4
27 #endif /* AFS_AIX32_ENV */
30 #include "afs/afsint.h"
36 #include <sys/audit.h>
38 #include <afs/afsutil.h>
42 int osi_audit_all = (-1); /* Not determined yet */
43 int osi_echo_trail = (-1);
45 FILE *auditout = NULL;
47 int osi_audit_check();
50 audmakebuf(char *audEvent, va_list vaList)
62 vaEntry = va_arg(vaList, int);
63 while (vaEntry != AUD_END) {
65 case AUD_STR: /* String */
66 case AUD_NAME: /* Name */
67 case AUD_ACL: /* ACL */
68 vaStr = (char *)va_arg(vaList, char *);
70 strcpy(bufferPtr, vaStr);
71 bufferPtr += strlen(vaStr) + 1;
73 strcpy(bufferPtr, "");
77 case AUD_INT: /* Integer */
78 case AUD_ID: /* ViceId */
79 vaInt = va_arg(vaList, int);
80 *(int *)bufferPtr = vaInt;
81 bufferPtr += sizeof(vaInt);
83 case AUD_DATE: /* Date */
84 case AUD_HOST: /* Host ID */
85 case AUD_LONG: /* long */
86 vaLong = va_arg(vaList, afs_int32);
87 *(afs_int32 *) bufferPtr = vaLong;
88 bufferPtr += sizeof(vaLong);
90 case AUD_LST: /* Ptr to another list */
91 vaLst = va_arg(vaList, va_list);
92 audmakebuf(audEvent, vaLst);
94 case AUD_FID: /* AFSFid - contains 3 entries */
95 vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
97 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
99 memset(bufferPtr, 0, sizeof(struct AFSFid));
101 bufferPtr += sizeof(struct AFSFid);
104 /* Whole array of fids-- don't know how to handle variable length audit
105 * data with AIX audit package, so for now we just store the first fid.
106 * Better one than none. */
109 struct AFSCBFids *Fids;
111 Fids = (struct AFSCBFids *)va_arg(vaList, struct AFSCBFids *);
112 if (Fids && Fids->AFSCBFids_len) {
113 *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
114 bufferPtr += sizeof(u_int);
115 memcpy(bufferPtr, Fids->AFSCBFids_val,
116 sizeof(struct AFSFid));
118 *((u_int *) bufferPtr) = 0;
119 bufferPtr += sizeof(u_int);
120 memset(bufferPtr, 0, sizeof(struct AFSFid));
122 bufferPtr += sizeof(struct AFSFid);
128 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
129 (strlen(audEvent) + 1));
135 vaEntry = va_arg(vaList, int);
140 printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
147 struct AFSFid *vaFid;
148 struct AFSCBFids *vaFids;
149 int num = LogThreadNum();
150 struct in_addr hostAddr;
155 /* Don't print the timestamp or thread id if we recursed */
157 currenttime = time(0);
158 timeStamp = afs_ctime(¤ttime, tbuffer,
160 timeStamp[24] = ' '; /* ts[24] is the newline, 25 is the null */
161 fprintf(out, timeStamp);
164 fprintf(out, "[%d] ", num);
167 if (strcmp(audEvent, "VALST") != 0)
168 fprintf(out, "EVENT %s CODE %d ", audEvent, errCode);
170 vaEntry = va_arg(vaList, int);
171 while (vaEntry != AUD_END) {
173 case AUD_STR: /* String */
174 vaStr = (char *)va_arg(vaList, char *);
176 fprintf(out, "STR %s ", vaStr);
178 fprintf(out, "STR <null>");
180 case AUD_NAME: /* Name */
181 vaStr = (char *)va_arg(vaList, char *);
183 fprintf(out, "NAME %s ", vaStr);
185 fprintf(out, "NAME <null>");
187 case AUD_ACL: /* ACL */
188 vaStr = (char *)va_arg(vaList, char *);
190 fprintf(out, "ACL %s ", vaStr);
192 fprintf(out, "ACL <null>");
194 case AUD_INT: /* Integer */
195 vaInt = va_arg(vaList, int);
196 fprintf(out, "INT %d ", vaInt);
198 case AUD_ID: /* ViceId */
199 vaInt = va_arg(vaList, int);
200 fprintf(out, "ID %d ", vaInt);
202 case AUD_DATE: /* Date */
203 vaLong = va_arg(vaList, afs_int32);
204 fprintf(out, "DATE %u ", vaLong);
206 case AUD_HOST: /* Host ID */
207 vaLong = va_arg(vaList, afs_int32);
208 hostAddr.s_addr = vaLong;
209 fprintf(out, "HOST %s ", inet_ntoa(hostAddr));
211 case AUD_LONG: /* afs_int32 */
212 vaLong = va_arg(vaList, afs_int32);
213 fprintf(out, "LONG %d ", vaLong);
215 case AUD_LST: /* Ptr to another list */
216 vaLst = va_arg(vaList, va_list);
217 printbuf(out, 1, "VALST", 0, vaLst);
219 case AUD_FID: /* AFSFid - contains 3 entries */
220 vaFid = va_arg(vaList, struct AFSFid *);
222 fprintf(out, "FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
225 fprintf(out, "FID %u:%u:%u ", 0, 0, 0);
227 case AUD_FIDS: /* array of Fids */
228 vaFids = va_arg(vaList, struct AFSCBFids *);
234 fprintf(out, "FIDS %u FID %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
235 vaFid->Vnode, vaFid->Unique);
237 fprintf(out, "FIDS 0 FID 0:0:0 ");
239 for ( i = 1; i < vaFids->AFSCBFids_len; i++ ) {
240 vaFid = vaFids->AFSCBFids_val;
242 fprintf(out, "FID %u:%u:%u ", vaFid->Volume,
243 vaFid->Vnode, vaFid->Unique);
245 fprintf(out, "FID 0:0:0 ");
250 fprintf(out, "--badval-- ");
253 vaEntry = va_arg(vaList, int);
256 if (strcmp(audEvent, "VALST") != 0)
260 static struct Lock audlock;
261 static afs_int32 lock_init = 0;
265 #ifdef AFS_PTHREAD_ENV
270 #endif /* AFS_PTHREAD_ENV */
273 /* ************************************************************************** */
274 /* The routine that acually does the audit call.
275 * ************************************************************************** */
277 osi_audit(char *audEvent, /* Event name (15 chars or less) */
278 afs_int32 errCode, /* The error code */
284 static char BUFFER[32768];
289 #ifdef AFS_PTHREAD_ENV
290 /* This is not thread safe. Lock initialization should
291 * be done in a server initialization phase
295 #endif /* AFS_PTHREAD_ENV */
297 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
299 if (!osi_audit_all && !auditout)
306 case KANOAUTH: /* kautils.h */
307 case RXKADNOAUTH: /* rxkad.h */
308 result = AUDIT_FAIL_AUTH;
310 case EPERM: /* errno.h */
311 case EACCES: /* errno.h */
312 case PRPERM: /* pterror.h */
313 result = AUDIT_FAIL_ACCESS;
315 case VL_PERM: /* vlserver.h */
316 case BUDB_NOTPERMITTED: /* budb_errs.h */
317 case BZACCESS: /* bnode.h */
318 case VOLSERBAD_ACCESS: /* volser.h */
319 result = AUDIT_FAIL_PRIV;
326 #ifdef AFS_PTHREAD_ENV
327 ObtainWriteLock(&audlock);
332 /* Put the error code into the buffer list */
333 *(int *)bufferPtr = errCode;
334 bufferPtr += sizeof(errCode);
336 va_start(vaList, errCode);
337 audmakebuf(audEvent, vaList);
340 if (osi_echo_trail) {
341 va_start(vaList, errCode);
342 printbuf(stdout, 0, audEvent, errCode, vaList);
346 bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
347 code = auditlog(audEvent, result, BUFFER, bufferLen);
351 code = auditlog("AFS_Aud_Fail", result, &err, sizeof(err));
353 printf("Error while writing audit entry: %d.\n", errno);
358 va_start(vaList, errCode);
359 printbuf(auditout, 0, audEvent, errCode, vaList);
363 #ifdef AFS_PTHREAD_ENV
364 ReleaseWriteLock(&audlock);
370 /* ************************************************************************** */
371 /* Given a RPC call structure, this routine extracts the name and host id from the
372 * call and includes it within the audit information.
373 * ************************************************************************** */
375 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
377 struct rx_connection *conn;
378 struct rx_peer *peer;
381 char afsName[MAXKTCNAMELEN];
385 if (osi_audit_all < 0)
387 if (!osi_audit_all && !auditout)
390 strcpy(afsName, "--Unknown--");
394 conn = rx_ConnectionOf(call); /* call -> conn) */
396 secClass = rx_SecurityClassOf(conn); /* conn -> securityIndex */
397 if (secClass == 0) { /* unauthenticated */
398 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
399 strcpy(afsName, "--UnAuth--");
400 } else if (secClass == 2) { /* authenticated */
401 char tcell[MAXKTCREALMLEN];
402 char name[MAXKTCNAMELEN];
403 char inst[MAXKTCNAMELEN];
408 rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
411 osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
412 strcpy(afsName, "--NoName--");
414 strncpy(vname, name, sizeof(vname));
415 if ((ilen = strlen(inst))) {
416 if (strlen(vname) + 1 + ilen >= sizeof(vname))
421 if ((clen = strlen(tcell))) {
422 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
423 static char local_realms[AFS_NUM_LREALMS][AFS_REALM_SZ];
424 static int num_lrealms = -1;
427 if (num_lrealms == -1) {
428 for (i=0; i<AFS_NUM_LREALMS; i++) {
429 if (afs_krb_get_lrealm(local_realms[i], i) != 0 /*KSUCCESS*/)
434 strncpy(local_realms[0], "UNKNOWN.LOCAL.REALM", AFS_REALM_SZ);
438 /* Check to see if the ticket cell matches one of the local realms */
440 for ( i=0;i<num_lrealms;i++ ) {
441 if (!strcasecmp(local_realms[i], tcell)) {
446 /* If yes, then make sure that the name is not present in
447 * an exclusion list */
451 snprintf(uname,sizeof(uname),"%s.%s@%s",name,inst,tcell);
453 snprintf(uname,sizeof(uname),"%s@%s",name,tcell);
455 if (afs_krb_exclusion(uname))
460 if (strlen(vname) + 1 + clen >= sizeof(vname))
463 strcat(vname, tcell);
467 strcpy(afsName, vname);
469 } else { /* Unauthenticated & unknown */
470 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
471 strcpy(afsName, "--Unknown--");
474 peer = rx_PeerOf(conn); /* conn -> peer */
476 hostId = rx_HostOf(peer); /* peer -> host */
478 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
479 } else { /* null conn */
480 osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
482 } else { /* null call */
483 osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
485 va_start(vaList, errCode);
486 osi_audit(audEvent, errCode, AUD_NAME, afsName, AUD_HOST, hostId,
487 AUD_LST, vaList, AUD_END);
492 /* ************************************************************************** */
493 /* Determines whether auditing is on or off by looking at the Audit file.
494 * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
496 * ************************************************************************** */
505 osi_audit_all = 1; /* say we made check (>= 0) */
506 /* and assume audit all events (for now) */
507 onoff = 0; /* assume we will turn auditing off */
508 osi_echo_trail = 0; /* assume no echoing */
510 fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
512 while (fscanf(fds, "%256s", event) > 0) {
513 if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
516 if (strcmp(event, "Echo_Trail") == 0)
522 /* Audit this event all of the time */
524 osi_audit("AFS_Aud_On", 0, AUD_END);
526 osi_audit("AFS_Aud_Off", 0, AUD_END);
528 /* Now set whether we audit all events from here on out */
529 osi_audit_all = onoff;
535 osi_audit_file(FILE *out)