4e33741b8b7acc9915f836418e925615c0d3b984
[openafs.git] / src / audit / audit.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #ifdef AFS_AIX32_ENV
16 #include <sys/audit.h>
17 #else
18 #define AUDIT_OK 0
19 #define AUDIT_FAIL 1
20 #define AUDIT_FAIL_AUTH 2
21 #define AUDIT_FAIL_ACCESS 3
22 #define AUDIT_FAIL_PRIV 4
23 #endif /* AFS_AIX32_ENV */
24
25 #include <afs/opr.h>
26 #include "afs/afsint.h"
27 #include "afs/butc.h"
28 #include <rx/rx.h>
29 #include <rx/rxkad.h>
30 #include "audit.h"
31 #include "audit-api.h"
32 #include "lock.h"
33
34 #include <afs/afsutil.h>
35
36 extern struct osi_audit_ops audit_file_ops;
37 #ifdef HAVE_SYS_IPC_H
38 extern struct osi_audit_ops audit_sysvmq_ops;
39 #endif
40
41 static struct {
42     void *rock;
43     int (*islocal)(void *rock, char *name, char *inst, char *cell);
44 } audit_user_check = { NULL, NULL };
45
46 static struct {
47     const char *name;
48     const struct osi_audit_ops *ops;
49 } audit_interfaces[] = {
50
51     { "file", &audit_file_ops },
52 #ifdef HAVE_SYS_IPC_H
53     { "sysvmq", &audit_sysvmq_ops },
54 #endif
55 };
56
57 #define N_INTERFACES (sizeof(audit_interfaces) / sizeof(audit_interfaces[0]))
58
59 /* default to `file' audit interface */
60 static const struct osi_audit_ops *audit_ops = &audit_file_ops;
61
62 static int osi_audit_all = (-1);        /* Not determined yet */
63 static int osi_echo_trail = (-1);
64
65 static int auditout_open = 0;
66
67 static int osi_audit_check(void);
68
69 #ifdef AFS_AIX32_ENV
70 static char *bufferPtr;
71 static int bufferLen;
72
73 static void
74 audmakebuf(char *audEvent, va_list vaList)
75 {
76     int code;
77     int vaEntry;
78     int vaInt;
79     afs_int32 vaLong;
80     char *vaStr;
81     struct AFSFid *vaFid;
82
83     vaEntry = va_arg(vaList, int);
84     while (vaEntry != AUD_END) {
85         switch (vaEntry) {
86         case AUD_STR:           /* String */
87         case AUD_NAME:          /* Name */
88         case AUD_ACL:           /* ACL */
89             vaStr = (char *)va_arg(vaList, char *);
90             if (vaStr) {
91                 strcpy(bufferPtr, vaStr);
92                 bufferPtr += strlen(vaStr) + 1;
93             } else {
94                 strcpy(bufferPtr, "");
95                 bufferPtr++;
96             }
97             break;
98         case AUD_INT:           /* Integer */
99         case AUD_ID:            /* ViceId */
100             vaInt = va_arg(vaList, int);
101             *(int *)bufferPtr = vaInt;
102             bufferPtr += sizeof(vaInt);
103             break;
104         case AUD_DATE:          /* Date    */
105         case AUD_HOST:          /* Host ID */
106         case AUD_LONG:          /* long    */
107             vaLong = va_arg(vaList, afs_int32);
108             *(afs_int32 *) bufferPtr = vaLong;
109             bufferPtr += sizeof(vaLong);
110             break;
111         case AUD_FID:           /* AFSFid - contains 3 entries */
112             vaFid = (struct AFSFid *)va_arg(vaList, struct AFSFid *);
113             if (vaFid) {
114                 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
115             } else {
116                 memset(bufferPtr, 0, sizeof(struct AFSFid));
117             }
118             bufferPtr += sizeof(struct AFSFid);
119             break;
120
121             /* Whole array of fids-- don't know how to handle variable length audit
122              * data with AIX audit package, so for now we just store the first fid.
123              * Better one than none. */
124         case AUD_FIDS:
125             {
126                 struct AFSCBFids *Fids;
127
128                 Fids = (struct AFSCBFids *)va_arg(vaList, struct AFSCBFids *);
129                 if (Fids && Fids->AFSCBFids_len) {
130                     *((u_int *) bufferPtr) = Fids->AFSCBFids_len;
131                     bufferPtr += sizeof(u_int);
132                     memcpy(bufferPtr, Fids->AFSCBFids_val,
133                            sizeof(struct AFSFid));
134                 } else {
135                     *((u_int *) bufferPtr) = 0;
136                     bufferPtr += sizeof(u_int);
137                     memset(bufferPtr, 0, sizeof(struct AFSFid));
138                 }
139                 bufferPtr += sizeof(struct AFSFid);
140                 break;
141             }
142         /* butc tape label */
143         case AUD_TLBL:
144             {
145                 struct tc_tapeLabel *label;
146
147                 label = (struct tc_tapeLabel *)va_arg(vaList,
148                                                       struct tc_tapeLabel *);
149                 if (label)
150                     memcpy(bufferPtr, label, sizeof(*label));
151                 else
152                     memset(bufferPtr, 0, sizeof(*label));
153                 bufferPtr += sizeof(label);
154                 break;
155             }
156         /* butc dump interface */
157         case AUD_TDI:
158             {
159                 struct tc_dumpInterface *di;
160
161                 di = (struct tc_dumpInterface *)
162                         va_arg(vaList, struct tc_dumpInterface *);
163                 if (di)
164                     memcpy(bufferPtr, di, sizeof(*di));
165                 else
166                     memset(bufferPtr, 0, sizeof(*di));
167                 bufferPtr += sizeof(*di);
168                 break;
169             }
170         /*
171          * butc dump array
172          * An array of dump descriptions, but the AIX audit package assumes fixed
173          * length, so we can only do the first one for now.
174          */
175         case AUD_TDA:
176             {
177                 struct tc_dumpArray *da;
178
179                 da = (struct tc_dumpArray *)
180                         va_arg(vaList, struct tc_dumpArray *);
181                 if (da && da->tc_dumpArray_len) {
182                     memcpy(bufferPtr, &da->tc_dumpArray_len, sizeof(u_int));
183                     bufferPtr += sizeof(u_int);
184                     memcpy(bufferPtr, da->tc_dumpArray_val,
185                            sizeof(da->tc_dumpArray_val[0]));
186                 } else {
187                     memset(bufferPtr, 0, sizeof(u_int));
188                     bufferPtr += sizeof(u_int);
189                     memset(bufferPtr, 0, sizeof(da->tc_dumpArray_val[0]));
190                 }
191                 bufferPtr += sizeof(da->tc_dumpArray_val[0]);
192                 break;
193             }
194         /*
195          * butc restore array
196          * An array of restore descriptions, but the AIX audit package assumes
197          * fixed length, so we can only do the first one for now.
198          */
199         case AUD_TRA:
200             {
201                 struct tc_restoreArray *ra;
202
203                 ra = (struct tc_restoreArray *)
204                         va_arg(vaList, struct tc_restoreArray *);
205                 if (ra && ra->tc_restoreArray_len) {
206                     memcpy(bufferPtr, &ra->tc_restoreArray_len, sizeof(u_int));
207                     bufferPtr += sizeof(u_int);
208                     memcpy(bufferPtr, ra->tc_restoreArray_val,
209                            sizeof(ra->tc_restoreArray_val[0]));
210                 } else {
211                     memset(bufferPtr, 0, sizeof(u_int));
212                     bufferPtr += sizeof(u_int);
213                     memset(bufferPtr, 0, sizeof(ra->tc_restoreArray_val[0]));
214                 }
215                 bufferPtr += sizeof(ra->tc_restoreArray_val[0]);
216                 break;
217             }
218         /* butc tape controller status */
219             {
220                 struct tciStatusS *status;
221
222                 status = (struct tciStatusS *)va_arg(vaList,
223                                                      struct tciStatusS *);
224                 if (status)
225                     memcpy(bufferPtr, status, sizeof(*status));
226                 else
227                     memset(bufferPtr, 0, sizeof(*status));
228                 bufferPtr += sizeof(*status);
229                 break;
230             }
231         default:
232 #ifdef AFS_AIX32_ENV
233             code =
234                 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
235                          (strlen(audEvent) + 1));
236 #endif
237             return;
238             break;
239         }                       /* end switch */
240
241         vaEntry = va_arg(vaList, int);
242     }                           /* end while */
243 }
244 #endif
245
246 static void
247 printbuf(int rec, char *audEvent, char *afsName, afs_int32 hostId,
248          afs_int32 errCode, va_list vaList)
249 {
250     int vaEntry;
251     int vaInt;
252     afs_int32 vaLong;
253     char *vaStr;
254     struct AFSFid *vaFid;
255     struct AFSCBFids *vaFids;
256     struct tc_tapeLabel *vaLabel;
257     struct tc_dumpInterface *vaDI;
258     struct tc_dumpArray *vaDA;
259     struct tc_restoreArray *vaRA;
260     struct tciStatusS *vaTCstatus;
261     int num = LogThreadNum();
262     struct in_addr hostAddr;
263     time_t currenttime;
264     char tbuffer[26];
265     struct tm tm;
266
267     /* Don't print the timestamp or thread id if we recursed */
268     if (rec == 0) {
269         currenttime = time(0);
270         if (strftime(tbuffer, sizeof(tbuffer), "%a %b %d %H:%M:%S %Y ",
271                      localtime_r(&currenttime, &tm)) !=0)
272             audit_ops->append_msg(tbuffer);
273
274         if (num > -1)
275             audit_ops->append_msg("[%d] ", num);
276     }
277
278     audit_ops->append_msg("EVENT %s CODE %d ", audEvent, errCode);
279
280     if (afsName) {
281         hostAddr.s_addr = hostId;
282         audit_ops->append_msg("NAME %s HOST %s ", afsName, inet_ntoa(hostAddr));
283     }
284
285     vaEntry = va_arg(vaList, int);
286     while (vaEntry != AUD_END) {
287         switch (vaEntry) {
288         case AUD_STR:           /* String */
289             vaStr = (char *)va_arg(vaList, char *);
290             if (vaStr)
291                 audit_ops->append_msg("STR %s ", vaStr);
292             else
293                 audit_ops->append_msg("STR <null>");
294             break;
295         case AUD_NAME:          /* Name */
296             vaStr = (char *)va_arg(vaList, char *);
297             if (vaStr)
298                 audit_ops->append_msg("NAME %s ", vaStr);
299             else
300                 audit_ops->append_msg("NAME <null>");
301             break;
302         case AUD_ACL:           /* ACL */
303             vaStr = (char *)va_arg(vaList, char *);
304             if (vaStr)
305                 audit_ops->append_msg("ACL %s ", vaStr);
306             else
307                 audit_ops->append_msg("ACL <null>");
308             break;
309         case AUD_INT:           /* Integer */
310             vaInt = va_arg(vaList, int);
311             audit_ops->append_msg("INT %d ", vaInt);
312             break;
313         case AUD_ID:            /* ViceId */
314             vaInt = va_arg(vaList, int);
315             audit_ops->append_msg("ID %d ", vaInt);
316             break;
317         case AUD_DATE:          /* Date    */
318             vaLong = va_arg(vaList, afs_int32);
319             audit_ops->append_msg("DATE %u ", vaLong);
320             break;
321         case AUD_HOST:          /* Host ID */
322             vaLong = va_arg(vaList, afs_int32);
323             hostAddr.s_addr = vaLong;
324             audit_ops->append_msg("HOST %s ", inet_ntoa(hostAddr));
325             break;
326         case AUD_LONG:          /* afs_int32    */
327             vaLong = va_arg(vaList, afs_int32);
328             audit_ops->append_msg("LONG %d ", vaLong);
329             break;
330         case AUD_FID:           /* AFSFid - contains 3 entries */
331             vaFid = va_arg(vaList, struct AFSFid *);
332             if (vaFid)
333                 audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume, vaFid->Vnode,
334                        vaFid->Unique);
335             else
336                 audit_ops->append_msg("FID %u:%u:%u ", 0, 0, 0);
337             break;
338         case AUD_FIDS:          /* array of Fids */
339             vaFids = va_arg(vaList, struct AFSCBFids *);
340
341             if (vaFids) {
342                 unsigned int i;
343
344                 vaFid = vaFids->AFSCBFids_val;
345
346                 if (vaFid) {
347                     audit_ops->append_msg("FIDS %u ", vaFids->AFSCBFids_len);
348                     for ( i = 1; i <= vaFids->AFSCBFids_len; i++, vaFid++ )
349                         audit_ops->append_msg("FID %u:%u:%u ", vaFid->Volume,
350                                 vaFid->Vnode, vaFid->Unique);
351                 } else
352                     audit_ops->append_msg("FIDS 0 FID 0:0:0 ");
353
354             }
355             break;
356         case AUD_TLBL:          /* butc tape label */
357             vaLabel = va_arg(vaList, struct tc_tapeLabel *);
358
359             if (vaLabel) {
360                 audit_ops->append_msg("TAPELABEL %d:%.*s:%.*s:%u ",
361                                       vaLabel->size,
362                                       TC_MAXTAPELEN, vaLabel->afsname,
363                                       TC_MAXTAPELEN, vaLabel->pname,
364                                       vaLabel->tapeId);
365             } else {
366                 audit_ops->append_msg("TAPELABEL <null>");
367             }
368             break;
369         case AUD_TDI:
370             vaDI = va_arg(vaList, struct tc_dumpInterface *);
371
372             if (vaDI) {
373                 audit_ops->append_msg(
374     "TCDUMPINTERFACE %.*s:%.*s:%.*s:%d:%d:%d:$d:%.*s:%.*s:%d:%d:%d:%d:%d ",
375     TC_MAXDUMPPATH, vaDI->dumpPath, TC_MAXNAMELEN, vaDI->volumeSetName,
376     TC_MAXNAMELEN, vaDI->dumpName, vaDI->parentDumpId, vaDI->dumpLevel,
377     vaDI->doAppend,
378     vaDI->tapeSet.id, TC_MAXHOSTLEN, vaDI->tapeSet.tapeServer,
379     TC_MAXFORMATLEN, vaDI->tapeSet.format, vaDI->tapeSet.maxTapes,
380     vaDI->tapeSet.a, vaDI->tapeSet.b, vaDI->tapeSet.expDate,
381     vaDI->tapeSet.expType);
382             } else {
383                 audit_ops->append_msg("TCDUMPINTERFACE <null>");
384             }
385             break;
386         case AUD_TDA:
387             vaDA = va_arg(vaList, struct tc_dumpArray *);
388
389             if (vaDA) {
390                 u_int i;
391                 struct tc_dumpDesc *desc;
392                 struct in_addr hostAddr;
393
394                 desc = vaDA->tc_dumpArray_val;
395                 if (desc) {
396                     audit_ops->append_msg("DUMPS %d ", vaDA->tc_dumpArray_len);
397                     for (i = 0; i < vaDA->tc_dumpArray_len; i++, desc++) {
398                         hostAddr.s_addr = desc->hostAddr;
399                         audit_ops->append_msg("DUMP %d:%d:%.*s:$d:%d:%d:%s ",
400                             desc->vid, desc->vtype, TC_MAXNAMELEN, desc->name,
401                             desc->partition, desc->date, desc->cloneDate,
402                             inet_ntoa(hostAddr));
403                     }
404                 } else {
405                     audit_ops->append_msg("DUMPS 0 DUMP 0:0::0:0:0:0.0.0.0");
406                 }
407             }
408             break;
409         case AUD_TRA:
410             vaRA = va_arg(vaList, struct tc_restoreArray *);
411
412             if (vaRA) {
413                 u_int i;
414                 struct tc_restoreDesc *desc;
415                 struct in_addr hostAddr;
416
417                 desc = vaRA->tc_restoreArray_val;
418                 if (desc) {
419                     audit_ops->append_msg("RESTORES %d ",
420                                           vaRA->tc_restoreArray_len);
421                     for(i = 0; i < vaRA->tc_restoreArray_len; i++, desc++) {
422                         hostAddr.s_addr = desc->hostAddr;
423                         audit_ops->append_msg(
424                             "RESTORE %d:%.*s:%d:%d:%d:%d:%d:%d:%d:%s:%.*s:%.*s ",
425                             desc->flags, TC_MAXTAPELEN, desc->tapeName,
426                             desc->dbDumpId, desc->initialDumpId,
427                             desc->position, desc->origVid, desc->vid,
428                             desc->partition, desc->dumpLevel,
429                             inet_ntoa(hostAddr), TC_MAXNAMELEN,
430                             desc->oldName, TC_MAXNAMELEN, desc->newName);
431                     }
432                 } else {
433                     audit_ops->append_msg(
434                         "RESTORES 0 RESTORE 0::0:0:0:0:0:0:0:0.0.0.0::: ");
435                 }
436             }
437             break;
438         case AUD_TSTT:
439             vaTCstatus = va_arg(vaList, struct tciStatusS *);
440
441             if (vaTCstatus)
442                 audit_ops->append_msg("TCSTATUS %.*s:%d:%d:%d:%d:%.*s:%d:%d ",
443                                       TC_MAXNAMELEN, vaTCstatus->taskName,
444                                       vaTCstatus->taskId, vaTCstatus->flags,
445                                       vaTCstatus->dbDumpId, vaTCstatus->nKBytes,
446                                       TC_MAXNAMELEN, vaTCstatus->volumeName,
447                                       vaTCstatus->volsFailed,
448                                       vaTCstatus->lastPolled);
449             else
450                 audit_ops->append_msg("TCSTATUS <null>");
451             break;
452         default:
453             audit_ops->append_msg("--badval-- ");
454             break;
455         }                       /* end switch */
456         vaEntry = va_arg(vaList, int);
457     }                           /* end while */
458
459     audit_ops->send_msg();
460 }
461
462 #ifdef AFS_PTHREAD_ENV
463 static pthread_mutex_t audit_lock;
464 static volatile afs_int32   audit_lock_initialized = 0;
465 static pthread_once_t audit_lock_once = PTHREAD_ONCE_INIT;
466
467 static void
468 osi_audit_init_lock(void)
469 {
470     MUTEX_INIT(&audit_lock, "audit", MUTEX_DEFAULT, 0);
471     audit_lock_initialized = 1;
472 }
473 #endif
474
475 void
476 osi_audit_init(void)
477 {
478 #ifdef AFS_PTHREAD_ENV
479     if (!audit_lock_initialized) {
480         pthread_once(&audit_lock_once, osi_audit_init_lock);
481     }
482 #endif /* AFS_PTHREAD_ENV */
483 }
484
485 /* ************************************************************************** */
486 /* The routine that acually does the audit call.
487  * ************************************************************************** */
488 static int
489 osi_audit_internal(char *audEvent,      /* Event name (15 chars or less) */
490                    afs_int32 errCode,   /* The error code */
491                    char *afsName,
492                    afs_int32 hostId,
493                    va_list vaList)
494 {
495 #ifdef AFS_AIX32_ENV
496     afs_int32 code;
497     afs_int32 err;
498     static char BUFFER[32768];
499     int result;
500 #endif
501
502 #ifdef AFS_PTHREAD_ENV
503     /* i'm pretty sure all the server apps now call osi_audit_init(),
504      * but to be extra careful we'll leave this assert in here for a
505      * while to make sure */
506     opr_Assert(audit_lock_initialized);
507 #endif /* AFS_PTHREAD_ENV */
508
509     if ((osi_audit_all < 0) || (osi_echo_trail < 0))
510         osi_audit_check();
511     if (!osi_audit_all && !auditout_open)
512         return 0;
513
514 #ifdef AFS_AIX32_ENV
515     switch (errCode) {
516     case 0:
517         result = AUDIT_OK;
518         break;
519     case KANOAUTH:              /* kautils.h   */
520     case RXKADNOAUTH:           /* rxkad.h     */
521         result = AUDIT_FAIL_AUTH;
522         break;
523     case EPERM:         /* errno.h     */
524     case EACCES:                /* errno.h     */
525     case PRPERM:                /* pterror.h   */
526         result = AUDIT_FAIL_ACCESS;
527         break;
528     case VL_PERM:               /* vlserver.h  */
529     case BUDB_NOTPERMITTED:     /* budb_errs.h */
530     case BZACCESS:              /* bnode.h     */
531     case VOLSERBAD_ACCESS:      /* volser.h    */
532         result = AUDIT_FAIL_PRIV;
533         break;
534     default:
535         result = AUDIT_FAIL;
536         break;
537     }
538 #endif
539
540     MUTEX_ENTER(&audit_lock);
541 #ifdef AFS_AIX32_ENV
542     bufferPtr = BUFFER;
543
544     /* Put the error code into the buffer list */
545     *(int *)bufferPtr = errCode;
546     bufferPtr += sizeof(errCode);
547
548     audmakebuf(audEvent, vaList);
549 #endif
550
551 #ifdef AFS_AIX32_ENV
552     bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
553     code = auditlog(audEvent, result, BUFFER, bufferLen);
554 #else
555     if (auditout_open) {
556         printbuf(0, audEvent, afsName, hostId, errCode, vaList);
557     }
558 #endif
559     MUTEX_EXIT(&audit_lock);
560
561     return 0;
562 }
563 int
564 osi_audit(char *audEvent,       /* Event name (15 chars or less) */
565           afs_int32 errCode,    /* The error code */
566           ...)
567 {
568     va_list vaList;
569
570     if ((osi_audit_all < 0) || (osi_echo_trail < 0))
571         osi_audit_check();
572     if (!osi_audit_all && !auditout_open)
573         return 0;
574
575     va_start(vaList, errCode);
576     osi_audit_internal(audEvent, errCode, NULL, 0, vaList);
577     va_end(vaList);
578
579     return 0;
580 }
581
582 /* ************************************************************************** */
583 /* Given a RPC call structure, this routine extracts the name and host id from the
584  * call and includes it within the audit information.
585  * ************************************************************************** */
586 int
587 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
588 {
589     struct rx_connection *conn;
590     struct rx_peer *peer;
591     afs_int32 secClass;
592     afs_int32 code;
593     char afsName[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
594     afs_int32 hostId;
595     va_list vaList;
596
597     if (osi_audit_all < 0)
598         osi_audit_check();
599     if (!osi_audit_all && !auditout_open)
600         return 0;
601
602     strcpy(afsName, "--Unknown--");
603     hostId = 0;
604
605     if (call) {
606         conn = rx_ConnectionOf(call);   /* call -> conn) */
607         if (conn) {
608             secClass = rx_SecurityClassOf(conn);        /* conn -> securityIndex */
609             if (secClass == RX_SECIDX_NULL) {   /* unauthenticated */
610                 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
611                 strcpy(afsName, "--UnAuth--");
612             } else if (secClass == RX_SECIDX_KAD || secClass == RX_SECIDX_KAE) {
613                 /* authenticated with rxkad */
614                 char tcell[MAXKTCREALMLEN];
615                 char name[MAXKTCNAMELEN];
616                 char inst[MAXKTCNAMELEN];
617
618                 code =
619                     rxkad_GetServerInfo(conn, NULL, NULL, name, inst, tcell,
620                                         NULL);
621                 if (code) {
622                     osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
623                     strcpy(afsName, "--NoName--");
624                 } else {
625                     afs_int32 islocal = 0;
626                     if (audit_user_check.islocal) {
627                         islocal =
628                             audit_user_check.islocal(audit_user_check.rock,
629                                                      name, inst, tcell);
630                     }
631                     strlcpy(afsName, name, sizeof(afsName));
632                     if (inst[0]) {
633                         strlcat(afsName, ".", sizeof(afsName));
634                         strlcat(afsName, inst, sizeof(afsName));
635                     }
636                     if (tcell[0] && !islocal) {
637                         strlcat(afsName, "@", sizeof(afsName));
638                         strlcat(afsName, tcell, sizeof(afsName));
639                     }
640                 }
641             } else {            /* Unauthenticated and/or unknown */
642                 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
643                 strcpy(afsName, "--Unknown--");
644             }
645             peer = rx_PeerOf(conn);     /* conn -> peer */
646             if (peer)
647                 hostId = rx_HostOf(peer);       /* peer -> host */
648             else
649                 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
650         } else {                /* null conn */
651             osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
652         }
653     } else {                    /* null call */
654         osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
655     }
656     va_start(vaList, errCode);
657     osi_audit_internal(audEvent, errCode, afsName, hostId, vaList);
658     va_end(vaList);
659     return 0;
660 }
661
662 /* ************************************************************************** */
663 /* Determines whether auditing is on or off by looking at the Audit file.
664  * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be
665  * enabled.
666  * ************************************************************************** */
667
668 int
669 osi_audit_check(void)
670 {
671     FILE *fds;
672     int onoff;
673     char event[257];
674
675     osi_audit_all = 1;          /* say we made check (>= 0) */
676     /* and assume audit all events (for now) */
677     onoff = 0;                  /* assume we will turn auditing off */
678     osi_echo_trail = 0;         /* assume no echoing   */
679
680     fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
681     if (fds) {
682         while (fscanf(fds, "%256s", event) > 0) {
683             if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
684                 onoff = 1;
685
686             if (strcmp(event, "Echo_Trail") == 0)
687                 osi_echo_trail = 1;
688         }
689         fclose(fds);
690     }
691
692     /* Audit this event all of the time */
693     if (onoff)
694         osi_audit("AFS_Aud_On", 0, AUD_END);
695     else
696         osi_audit("AFS_Aud_Off", 0, AUD_END);
697
698     /* Now set whether we audit all events from here on out */
699     osi_audit_all = onoff;
700
701     return 0;
702 }
703
704 int
705 osi_audit_file(const char *fileName)
706 {
707     if(!audit_ops->open_file(fileName)) {
708         auditout_open = 1;
709         return 0;
710     }
711     return 1;
712 }
713
714 int
715 osi_audit_interface(const char *interface)
716 {
717     int i;
718     for (i = 0; i < N_INTERFACES; ++i) {
719         if (strcmp(interface, audit_interfaces[i].name) == 0) {
720             audit_ops = audit_interfaces[i].ops;
721             return 0;
722         }
723     }
724
725     return 1;
726 }
727
728 void
729 osi_audit_set_user_check(void *rock,
730                          int (*islocal) (void *rock, char *name, char *inst,
731                                          char *cell))
732 {
733     audit_user_check.rock = rock;
734     audit_user_check.islocal = islocal;
735 }
736
737 void
738 audit_PrintStats(FILE *out)
739 {
740     audit_ops->print_interface_stats(out);
741 }