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 vaStr = (char *)va_arg(vaList, int);
68 strcpy(bufferPtr, vaStr);
69 bufferPtr += strlen(vaStr) + 1;
71 strcpy(bufferPtr, "");
75 case AUD_INT: /* Integer */
76 vaInt = va_arg(vaList, int);
77 *(int *)bufferPtr = vaInt;
78 bufferPtr += sizeof(vaInt);
80 case AUD_DATE: /* Date */
81 case AUD_HOST: /* Host ID */
82 case AUD_LONG: /* long */
83 vaLong = va_arg(vaList, afs_int32);
84 *(afs_int32 *) bufferPtr = vaLong;
85 bufferPtr += sizeof(vaLong);
87 case AUD_LST: /* Ptr to another list */
88 vaLst = (char *)va_arg(vaList, int);
89 audmakebuf(audEvent, vaLst);
91 case AUD_FID: /* AFSFid - contains 3 entries */
92 vaFid = (struct AFSFid *)va_arg(vaList, int);
94 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
96 memset(bufferPtr, 0, sizeof(struct AFSFid));
98 bufferPtr += sizeof(struct AFSFid);
101 /* Whole array of fids-- don't know how to handle variable length audit
102 * data with AIX audit package, so for now we just store the first fid.
103 * Better one than none. */
106 struct AFSCBFids *Fids;
108 Fids = (struct AFSCBFids *)va_arg(vaList, int);
109 if (Fids && Fids->AFSCBFids_len) {
110 *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
111 bufferPtr += sizeof(u_int);
112 memcpy(bufferPtr, Fids->AFSCBFids_val,
113 sizeof(struct AFSFid));
115 *((u_int *) bufferPtr) = 0;
116 bufferPtr += sizeof(u_int);
117 memset(bufferPtr, 0, sizeof(struct AFSFid));
119 bufferPtr += sizeof(struct AFSFid);
125 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
126 (strlen(audEvent) + 1));
132 vaEntry = va_arg(vaList, int);
137 printbuf(FILE *out, int rec, char *audEvent, afs_int32 errCode, va_list vaList)
144 struct AFSFid *vaFid;
145 struct AFSCBFids *vaFids;
146 int num = LogThreadNum();
148 /* Don't print the thread id if we recursed */
149 if ((num > -1) && (rec == 0))
150 fprintf(out, "[%d]:", num);
152 if (strcmp(audEvent, "VALST") != 0)
153 fprintf(out, "%s %d ", audEvent, errCode);
155 vaEntry = va_arg(vaList, int);
156 while (vaEntry != AUD_END) {
158 case AUD_STR: /* String */
159 vaStr = (char *)va_arg(vaList, int);
161 fprintf(out, "%s ", vaStr);
163 fprintf(out, "<null>");
165 case AUD_INT: /* Integer */
166 vaInt = va_arg(vaList, int);
167 fprintf(out, "%d ", vaInt);
169 case AUD_DATE: /* Date */
170 case AUD_HOST: /* Host ID */
171 vaLong = va_arg(vaList, afs_int32);
172 fprintf(out, "%u ", vaLong);
174 case AUD_LONG: /* afs_int32 */
175 vaLong = va_arg(vaList, afs_int32);
176 fprintf(out, "%d ", vaLong);
178 case AUD_LST: /* Ptr to another list */
179 vaLst = (char *)va_arg(vaList, int);
180 printbuf(out, 1, "VALST", 0, vaLst);
182 case AUD_FID: /* AFSFid - contains 3 entries */
183 vaFid = (struct AFSFid *)va_arg(vaList, int);
185 fprintf(out, "%u:%u:%u ", vaFid->Volume, vaFid->Vnode,
188 fprintf(out, "%u:%u:%u ", 0, 0, 0);
190 case AUD_FIDS: /* array of Fids */
191 vaFids = (struct AFSCBFids *)va_arg(vaList, int);
195 vaFid = vaFids->AFSCBFids_val;
197 fprintf(out, "%u %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
198 vaFid->Vnode, vaFid->Unique);
200 fprintf(out, "0 0:0:0 ");
203 fprintf(out, "--badval-- ");
206 vaEntry = va_arg(vaList, int);
209 if (strcmp(audEvent, "VALST") != 0)
213 /* ************************************************************************** */
214 /* The routine that acually does the audit call.
215 * ************************************************************************** */
217 osi_audit(char *audEvent, /* Event name (15 chars or less) */
218 afs_int32 errCode, /* The error code */
229 static struct Lock audbuflock = { 0, 0, 0, 0,
230 #ifdef AFS_PTHREAD_ENV
231 PTHREAD_MUTEX_INITIALIZER,
232 PTHREAD_COND_INITIALIZER,
233 PTHREAD_COND_INITIALIZER
234 #endif /* AFS_PTHREAD_ENV */
236 static char BUFFER[32768];
239 if ((osi_audit_all < 0) || (osi_echo_trail < 0))
241 if (!osi_audit_all && !auditout)
248 case KANOAUTH: /* kautils.h */
249 case RXKADNOAUTH: /* rxkad.h */
250 result = AUDIT_FAIL_AUTH;
252 case EPERM: /* errno.h */
253 case EACCES: /* errno.h */
254 case PRPERM: /* pterror.h */
255 result = AUDIT_FAIL_ACCESS;
257 case VL_PERM: /* vlserver.h */
258 case BUDB_NOTPERMITTED: /* budb_errs.h */
259 case BZACCESS: /* bnode.h */
260 case VOLSERBAD_ACCESS: /* volser.h */
261 result = AUDIT_FAIL_PRIV;
269 ObtainWriteLock(&audbuflock);
272 /* Put the error code into the buffer list */
273 *(int *)bufferPtr = errCode;
274 bufferPtr += sizeof(errCode);
276 va_start(vaList, errCode);
277 audmakebuf(audEvent, vaList);
280 if (osi_echo_trail) {
281 va_start(vaList, errCode);
282 printbuf(stdout, 0, audEvent, errCode, vaList);
286 bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
287 code = auditlog(audEvent, result, BUFFER, bufferLen);
291 code = auditlog("AFS_Aud_Fail", result, &err, sizeof(err));
293 printf("Error while writing audit entry: %d.\n", errno);
296 ReleaseWriteLock(&audbuflock);
299 va_start(vaList, errCode);
300 printbuf(auditout, 0, audEvent, errCode, vaList);
308 /* ************************************************************************** */
309 /* Given a RPC call structure, this routine extracts the name and host id from the
310 * call and includes it within the audit information.
311 * ************************************************************************** */
313 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
315 struct rx_connection *conn;
316 struct rx_peer *peer;
319 char afsName[MAXKTCNAMELEN];
323 if (osi_audit_all < 0)
325 if (!osi_audit_all && !auditout)
328 strcpy(afsName, "--Unknown--");
332 conn = rx_ConnectionOf(call); /* call -> conn) */
334 secClass = rx_SecurityClassOf(conn); /* conn -> securityIndex */
335 if (secClass == 0) { /* unauthenticated */
336 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
337 strcpy(afsName, "--UnAuth--");
338 } else if (secClass == 2) { /* authenticated */
339 char tcell[MAXKTCREALMLEN];
340 char name[MAXKTCNAMELEN];
341 char inst[MAXKTCNAMELEN];
346 rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
349 osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent,
351 strcpy(afsName, "--NoName--");
353 strncpy(vname, name, sizeof(vname));
354 if ((ilen = strlen(inst))) {
355 if (strlen(vname) + 1 + ilen >= sizeof(vname))
360 if ((clen = strlen(tcell))) {
361 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
362 static char local_realm[AFS_REALM_SZ] = "";
363 if (!local_realm[0]) {
364 if (afs_krb_get_lrealm(local_realm, 0) != 0 /*KSUCCESS*/)
365 strncpy(local_realm, "UNKNOWN.LOCAL.REALM", AFS_REALM_SZ);
367 if (strcasecmp(local_realm, tcell)) {
368 if (strlen(vname) + 1 + clen >= sizeof(vname))
371 strcat(vname, tcell);
374 strcpy(afsName, vname);
377 } else { /* Unauthenticated & unknown */
379 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent,
383 peer = rx_PeerOf(conn); /* conn -> peer */
385 hostId = rx_HostOf(peer); /* peer -> host */
387 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
388 } else { /* null conn */
390 osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
392 } else { /* null call */
394 osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
397 va_start(vaList, errCode);
398 osi_audit(audEvent, errCode, AUD_STR, afsName, AUD_HOST, hostId, AUD_LST,
404 /* ************************************************************************** */
405 /* Determines whether auditing is on or off by looking at the Audit file.
406 * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
408 * ************************************************************************** */
417 osi_audit_all = 1; /* say we made check (>= 0) */
418 /* and assume audit all events (for now) */
419 onoff = 0; /* assume we will turn auditing off */
420 osi_echo_trail = 0; /* assume no echoing */
422 fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
424 while (fscanf(fds, "%256s", event) > 0) {
425 if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
428 if (strcmp(event, "Echo_Trail") == 0)
434 /* Audit this event all of the time */
436 osi_audit("AFS_Aud_On", 0, AUD_END);
438 osi_audit("AFS_Aud_Off", 0, AUD_END);
440 /* Now set whether we audit all events from here on out */
441 osi_audit_all = onoff;
447 osi_audit_file(FILE *out)