b5e1084d796fc47faba4f5a4ecde61ec5a118afb
[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 RCSID
14     ("$Header$");
15
16 #include <fcntl.h>
17 #include <stdarg.h>
18 #ifdef AFS_AIX32_ENV
19 #include <sys/audit.h>
20 #endif /* AFS_AIX32_ENV */
21 #include <errno.h>
22
23 #include "afs/afsint.h"
24 #include <rx/rx.h>
25 #include <rx/rxkad.h>
26 #include "audit.h"
27 #include "lock.h"
28 #ifdef AFS_AIX32_ENV
29 #include <sys/audit.h>
30 #endif
31 #include <afs/afsutil.h>
32
33 char *bufferPtr;
34 int bufferLen;
35 int osi_audit_all = (-1);       /* Not determined yet */
36 int osi_echo_trail = (-1);
37
38 #ifdef AFS_AIX_ENV /** all these functions are only defined for AIX */
39
40 #ifndef AFS_OSF_ENV
41 /*
42  * These variadic functions work under AIX, and not all systems (osf1)
43  */
44 /* ************************************************************************** */
45 /* AIX requires a buffer filled with values to record with each audit event.
46  * aixmakebuf creates that buffer from the variable list of values we are given.
47  * ************************************************************************** */
48 static
49 aixmakebuf(audEvent, vaList)
50      char *audEvent;
51      char *vaList;
52 {
53     int code;
54     int vaEntry;
55     int vaInt;
56     afs_int32 vaLong;
57     char *vaStr;
58     char *vaLst;
59     char hname[20];
60     struct AFSFid *vaFid;
61
62     vaEntry = va_arg(vaList, int);
63     while (vaEntry != AUD_END) {
64         switch (vaEntry) {
65         case AUD_STR:           /* String */
66             vaStr = (char *)va_arg(vaList, int);
67             if (vaStr) {
68                 strcpy(bufferPtr, vaStr);
69                 bufferPtr += strlen(vaStr) + 1;
70             } else {
71                 strcpy(bufferPtr, "");
72                 bufferPtr++;
73             }
74             break;
75         case AUD_INT:           /* Integer */
76             vaInt = va_arg(vaList, int);
77             *(int *)bufferPtr = vaInt;
78             bufferPtr += sizeof(vaInt);
79             break;
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);
86             break;
87         case AUD_LST:           /* Ptr to another list */
88             vaLst = (char *)va_arg(vaList, int);
89             aixmakebuf(audEvent, vaLst);
90             break;
91         case AUD_FID:           /* AFSFid - contains 3 entries */
92             vaFid = (struct AFSFid *)va_arg(vaList, int);
93             if (vaFid) {
94                 memcpy(bufferPtr, vaFid, sizeof(struct AFSFid));
95             } else {
96                 memset(bufferPtr, 0, sizeof(struct AFSFid));
97             }
98             bufferPtr += sizeof(struct AFSFid);
99             break;
100
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. */
104         case AUD_FIDS:
105             {
106                 struct AFSCBFids *Fids;
107
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));
114                 } else {
115                     struct AFSFid dummy;
116                     *((u_int *) bufferPtr) = 0;
117                     bufferPtr += sizeof(u_int);
118                     memset(bufferPtr, 0, sizeof(struct AFSFid));
119                 }
120                 bufferPtr += sizeof(struct AFSFid);
121                 break;
122             }
123         default:
124 #ifdef AFS_AIX32_ENV
125             code =
126                 auditlog("AFS_Aud_EINVAL", (-1), audEvent,
127                          (strlen(audEvent) + 1));
128 #endif
129             return;
130             break;
131         }                       /* end switch */
132
133         vaEntry = va_arg(vaList, int);
134     }                           /* end while */
135 }
136
137 static
138 printbuf(audEvent, errCode, vaList)
139      char *audEvent;
140      afs_int32 errCode;
141      char *vaList;
142 {
143     int vaEntry;
144     int vaInt;
145     afs_int32 vaLong;
146     char *vaStr;
147     char *vaLst;
148     char hname[20];
149     struct AFSFid *vaFid;
150     struct AFSCBFids *vaFids;
151
152     if (osi_echo_trail < 0)
153         osi_audit_check();
154     if (!osi_echo_trail)
155         return;
156
157     if (strcmp(audEvent, "VALST") != 0)
158         printf("%s %d ", audEvent, errCode);
159
160     vaEntry = va_arg(vaList, int);
161     while (vaEntry != AUD_END) {
162         switch (vaEntry) {
163         case AUD_STR:           /* String */
164             vaStr = (char *)va_arg(vaList, int);
165             if (vaStr)
166                 printf("%s ", vaStr);
167             else
168                 printf("<null>", vaStr);
169             break;
170         case AUD_INT:           /* Integer */
171             vaInt = va_arg(vaList, int);
172             printf("%d ", vaInt);
173             break;
174         case AUD_DATE:          /* Date    */
175         case AUD_HOST:          /* Host ID */
176             vaLong = va_arg(vaList, afs_int32);
177             printf("%u ", vaLong);
178             break;
179         case AUD_LONG:          /* afs_int32    */
180             vaLong = va_arg(vaList, afs_int32);
181             printf("%d ", vaLong);
182             break;
183         case AUD_LST:           /* Ptr to another list */
184             vaLst = (char *)va_arg(vaList, int);
185             printbuf("VALST", 0, vaLst);
186             break;
187         case AUD_FID:           /* AFSFid - contains 3 entries */
188             vaFid = (struct AFSFid *)va_arg(vaList, int);
189             if (vaFid)
190                 printf("%u:%u:%u ", vaFid->Volume, vaFid->Vnode,
191                        vaFid->Unique);
192             else
193                 printf("%u:%u:%u ", 0, 0, 0);
194             break;
195         case AUD_FIDS:          /* array of Fids */
196             vaFids = (struct AFSCBFids *)va_arg(vaList, int);
197             vaFid = NULL;
198
199             if (vaFids)
200                 vaFid = vaFids->AFSCBFids_val;
201             if (vaFid)
202                 printf("%u %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
203                        vaFid->Vnode, vaFid->Unique);
204             else
205                 printf("0 0:0:0 ");
206             break;
207         default:
208             printf("--badval-- ");
209             break;
210         }                       /* end switch */
211         vaEntry = va_arg(vaList, int);
212     }                           /* end while */
213
214     if (strcmp(audEvent, "VALST") != 0)
215         printf("\n");
216 }
217 #else
218 static
219 aixmakebuf(audEvent, vaList)
220      char *audEvent;
221      va_list vaList;
222 {
223     return;
224 }
225
226 static
227 printbuf(audEvent, errCode, vaList)
228      char *audEvent;
229      long errCode;
230      va_list vaList;
231 {
232     return;
233 }
234
235 #endif
236
237
238 /* ************************************************************************** */
239 /* The routine that acually does the audit call.
240  * ************************************************************************** */
241 int
242 osi_audit(char *audEvent,       /* Event name (15 chars or less) */
243           afs_int32 errCode,    /* The error code */
244           ...)
245 {
246 #ifdef AFS_AIX32_ENV
247     afs_int32 code;
248     afs_int32 err;
249     int result;
250
251     va_list vaList;
252     static struct Lock audbuflock = { 0, 0, 0, 0,
253 #ifdef AFS_PTHREAD_ENV
254         PTHREAD_MUTEX_INITIALIZER,
255         PTHREAD_COND_INITIALIZER,
256         PTHREAD_COND_INITIALIZER
257 #endif /* AFS_PTHREAD_ENV */
258     };
259     static char BUFFER[32768];
260
261     if (osi_audit_all < 0)
262         osi_audit_check();
263     if (!osi_audit_all)
264         return;
265
266     switch (errCode) {
267     case 0:
268         result = AUDIT_OK;
269         break;
270     case KANOAUTH:              /* kautils.h   */
271     case RXKADNOAUTH:           /* rxkad.h     */
272         result = AUDIT_FAIL_AUTH;
273         break;
274     case EPERM:         /* errno.h     */
275     case EACCES:                /* errno.h     */
276     case PRPERM:                /* pterror.h   */
277         result = AUDIT_FAIL_ACCESS;
278         break;
279     case VL_PERM:               /* vlserver.h  */
280     case BUDB_NOTPERMITTED:     /* budb_errs.h */
281 /*  case KRB_RD_AP_UNAUTHOR : */
282     case BZACCESS:              /* bnode.h     */
283     case VOLSERBAD_ACCESS:      /* volser.h    */
284         result = AUDIT_FAIL_PRIV;
285         break;
286     default:
287         result = AUDIT_FAIL;
288         break;
289     }
290
291     ObtainWriteLock(&audbuflock);
292     bufferPtr = BUFFER;
293
294     /* Put the error code into the buffer list */
295     *(int *)bufferPtr = errCode;
296     bufferPtr += sizeof(errCode);
297
298     va_start(vaList, errCode);
299     aixmakebuf(audEvent, vaList);
300
301     va_start(vaList, errCode);
302     printbuf(audEvent, errCode, vaList);
303
304     bufferLen = (int)((afs_int32) bufferPtr - (afs_int32) & BUFFER[0]);
305     code = auditlog(audEvent, result, BUFFER, bufferLen);
306 #ifdef notdef
307     if (code) {
308         err = errno;
309         code = auditlog("AFS_Aud_Fail", result, &err, sizeof(err));
310         if (code)
311             printf("Error while writing audit entry: %d.\n", errno);
312     }
313 #endif /* notdef */
314     ReleaseWriteLock(&audbuflock);
315 #endif
316 }
317
318 /* ************************************************************************** */
319 /* Given a RPC call structure, this routine extracts the name and host id from the 
320  * call and includes it within the audit information.
321  * ************************************************************************** */
322 int
323 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
324 {
325     struct rx_connection *conn;
326     struct rx_peer *peer;
327     afs_int32 secClass;
328     afs_int32 code;
329     char afsName[MAXKTCNAMELEN];
330     afs_int32 hostId;
331     va_list vaList;
332
333
334     if (osi_audit_all < 0)
335         osi_audit_check();
336     if (!osi_audit_all)
337         return;
338
339     strcpy(afsName, "--Unknown--");
340     hostId = 0;
341
342     if (call) {
343         conn = rx_ConnectionOf(call);   /* call -> conn) */
344         if (conn) {
345             secClass = rx_SecurityClassOf(conn);        /* conn -> securityIndex */
346             if (secClass == 0) {        /* unauthenticated */
347                 osi_audit("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
348                 strcpy(afsName, "--UnAuth--");
349             } else if (secClass == 2) { /* authenticated */
350                 code =
351                     rxkad_GetServerInfo(conn, NULL, NULL, afsName, NULL, NULL,
352                                         NULL);
353                 if (code) {
354                     osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent,
355                               AUD_END);
356                     strcpy(afsName, "--NoName--");
357                 }
358             } else {            /* Unauthenticated & unknown */
359
360                 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent,
361                           AUD_END);
362             }
363
364             peer = rx_PeerOf(conn);     /* conn -> peer */
365             if (peer)
366                 hostId = rx_HostOf(peer);       /* peer -> host */
367             else
368                 osi_audit("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
369         } else {                /* null conn */
370
371             osi_audit("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
372         }
373     } else {                    /* null call */
374
375         osi_audit("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
376     }
377
378     va_start(vaList, errCode);
379     osi_audit(audEvent, errCode, AUD_STR, afsName, AUD_HOST, hostId, AUD_LST,
380               vaList, AUD_END);
381 }
382
383 /* ************************************************************************** */
384 /* Determines whether auditing is on or off by looking at the Audit file.
385  * If the string AFS_AUDIT_AllEvents is defined in the file, then auditing will be 
386  * enabled.
387  * ************************************************************************** */
388
389 int
390 osi_audit_check()
391 {
392     FILE *fds;
393     int onoff;
394     char event[257];
395
396     osi_audit_all = 1;          /* say we made check (>= 0) */
397     /* and assume audit all events (for now) */
398     onoff = 0;                  /* assume we will turn auditing off */
399     osi_echo_trail = 0;         /* assume no echoing   */
400
401     fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
402     if (fds) {
403         while (fscanf(fds, "%256s", event) > 0) {
404             if (strcmp(event, "AFS_AUDIT_AllEvents") == 0)
405                 onoff = 1;
406
407             if (strcmp(event, "Echo_Trail") == 0)
408                 osi_echo_trail = 1;
409         }
410         fclose(fds);
411     }
412
413     /* Audit this event all of the time */
414     if (onoff)
415         osi_audit("AFS_Aud_On", 0, AUD_END);
416     else
417         osi_audit("AFS_Aud_Off", 0, AUD_END);
418
419     /* Now set whether we audit all events from here on out */
420     osi_audit_all = onoff;
421 }
422
423
424 #else /* ! AFS_AIX_ENV */
425
426 int
427 osi_audit(char *audEvent, afs_int32 errCode, ...)
428 {
429     return 0;
430 }
431
432 int
433 osi_auditU(struct rx_call *call, char *audEvent, int errCode, ...)
434 {
435     return 0;
436 }
437
438 #endif