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