afsconfig-and-rcsid-all-around-20010705
[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 <afs/param.h>
11 #include <afsconfig.h>
12
13 RCSID("$Header$");
14
15 #include <fcntl.h>
16 #include <stdarg.h>
17 #ifdef AFS_AIX32_ENV
18 #include <sys/audit.h>
19 #endif /* AFS_AIX32_ENV */
20 #include <errno.h>
21
22 #include "afs/afsint.h"
23 #include <rx/rx.h>
24 #include <rx/rxkad.h>
25 #include "audit.h"
26 #include "lock.h"
27 #ifdef AFS_AIX32_ENV
28 #include <sys/audit.h>
29 #endif
30 #include <afs/afsutil.h>
31
32 char            *bufferPtr;
33 int             bufferLen;
34 int             osi_audit_all  = (-1);        /* Not determined yet */
35 int             osi_echo_trail = (-1);
36
37 #ifdef AFS_AIX_ENV /** all these functions are only defined for AIX */
38
39 #ifndef AFS_OSF_ENV
40 /*
41  * These variadic functions work under AIX, and not all systems (osf1)
42  */
43 /* ************************************************************************** */
44 /* AIX requires a buffer filled with values to record with each audit event.
45  * aixmakebuf creates that buffer from the variable list of values we are given.
46  * ************************************************************************** */
47 static aixmakebuf (audEvent, vaList)
48      char *audEvent;
49      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   {
63     switch (vaEntry)
64     {
65       case AUD_STR :                                     /* String */
66         vaStr = (char *) va_arg(vaList, int);
67         if ( vaStr )
68         {
69           strcpy (bufferPtr, vaStr);
70           bufferPtr += strlen(vaStr) + 1;
71         }
72         else
73         {
74           strcpy (bufferPtr, "");
75           bufferPtr++;
76         }
77         break;
78       case AUD_INT :                                     /* Integer */
79         vaInt = va_arg(vaList, int);
80         *(int *)bufferPtr = vaInt;
81         bufferPtr += sizeof(vaInt);
82         break;
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);
89         break;
90       case AUD_LST :                                     /* Ptr to another list */
91         vaLst = (char *) va_arg(vaList, int);
92         aixmakebuf(audEvent, vaLst);
93         break;
94       case AUD_FID :                             /* AFSFid - contains 3 entries */
95         vaFid = (struct AFSFid *) va_arg(vaList, int);
96         if (vaFid) {
97           bcopy(vaFid, bufferPtr, sizeof(struct AFSFid));
98         }
99         else {
100           bzero (bufferPtr, sizeof(struct AFSFid));
101         }
102         bufferPtr += sizeof(struct AFSFid);
103         break;
104
105         /* Whole array of fids-- don't know how to handle variable length audit
106          * data with AIX audit package, so for now we just store the first fid.
107          * Better one than none. */
108       case AUD_FIDS :
109         {
110           struct AFSCBFids *Fids;
111         
112           Fids = (struct AFSCBFids *) va_arg(vaList, int);
113           if (Fids && Fids->AFSCBFids_len) {
114             *((u_int *)bufferPtr) = Fids->AFSCBFids_len;
115             bufferPtr += sizeof(u_int);
116             bcopy(Fids->AFSCBFids_val, bufferPtr, sizeof(struct AFSFid));
117           }
118           else {
119             struct AFSFid dummy;
120             *((u_int *)bufferPtr) = 0;
121             bufferPtr += sizeof(u_int);
122             bzero (bufferPtr, sizeof(struct AFSFid));
123           }
124           bufferPtr += sizeof(struct AFSFid);
125           break;
126         }
127       default:
128 #ifdef AFS_AIX32_ENV
129         code = auditlog("AFS_Aud_EINVAL", (-1), audEvent, (strlen(audEvent)+1));
130 #endif
131         return;
132         break;
133     }                                         /* end switch */
134
135     vaEntry = va_arg(vaList, int); 
136   }                                           /* end while */
137 }
138
139 static printbuf (audEvent, errCode, vaList)
140      char *audEvent;
141      afs_int32 errCode;
142      char *vaList;
143 {
144   int            vaEntry;
145   int            vaInt;
146   afs_int32           vaLong;
147   char           *vaStr;
148   char           *vaLst;
149   char           hname[20];
150   struct AFSFid  *vaFid;
151   struct AFSCBFids  *vaFids;
152
153   if ( osi_echo_trail < 0 ) osi_audit_check();
154   if ( ! osi_echo_trail ) return;
155
156   if ( strcmp(audEvent,"VALST") != 0 ) 
157     printf ("%s %d ", audEvent, errCode);
158
159   vaEntry = va_arg(vaList, int); 
160   while ( vaEntry != AUD_END )
161   {
162     switch (vaEntry)
163     {
164       case AUD_STR :                                     /* String */
165         vaStr = (char *) va_arg(vaList, int);
166         if ( vaStr ) printf("%s ", vaStr);
167         else         printf("<null>", vaStr);
168         break;
169       case AUD_INT :                                     /* Integer */
170         vaInt = va_arg(vaList, int);
171         printf("%d ", vaInt);
172         break;
173       case AUD_DATE :                                    /* Date    */
174       case AUD_HOST :                                    /* Host ID */
175         vaLong = va_arg(vaList, afs_int32);
176         printf("%u ", vaLong);
177         break;
178       case AUD_LONG :                                    /* afs_int32    */
179         vaLong = va_arg(vaList, afs_int32);
180         printf("%d ", vaLong);
181         break;
182       case AUD_LST :                                     /* Ptr to another list */
183         vaLst = (char *) va_arg(vaList, int);
184         printbuf("VALST", 0, vaLst);
185         break;
186       case AUD_FID :                                     /* AFSFid - contains 3 entries */
187         vaFid = (struct AFSFid *) va_arg(vaList, int);
188         if (vaFid) printf ("%u:%u:%u ", vaFid->Volume, vaFid->Vnode, vaFid->Unique);
189         else       printf ("%u:%u:%u ", 0, 0, 0);
190         break;
191       case AUD_FIDS :                                    /* array of Fids */
192         vaFids = (struct AFSCBFids *) va_arg(vaList, int);
193         vaFid = NULL;
194
195         if (vaFids) 
196           vaFid = vaFids->AFSCBFids_val;
197         if (vaFid) 
198           printf ("%u %u:%u:%u ", vaFids->AFSCBFids_len, vaFid->Volume,
199                   vaFid->Vnode, vaFid->Unique);
200         else 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 aixmakebuf (audEvent, vaList)
214      char *audEvent;
215      va_list vaList;
216 {
217     return;
218 }
219
220 static printbuf (audEvent, errCode, vaList)
221      char *audEvent;
222      long errCode;
223      va_list vaList;
224 {
225     return;
226 }
227
228 #endif
229
230
231 /* ************************************************************************** */
232 /* The routine that acually does the audit call.
233  * ************************************************************************** */
234 int 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 ) osi_audit_check();
254   if ( ! osi_audit_all ) return;
255
256   switch (errCode) 
257   {
258     case 0 :
259       result = AUDIT_OK;
260       break;
261     case KANOAUTH           :                /* kautils.h   */
262     case RXKADNOAUTH        :                /* rxkad.h     */
263       result = AUDIT_FAIL_AUTH;
264       break;
265     case EPERM              :                /* errno.h     */
266     case EACCES             :                /* errno.h     */
267     case PRPERM             :                /* pterror.h   */
268       result = AUDIT_FAIL_ACCESS;
269       break;
270     case VL_PERM            :                /* vlserver.h  */
271     case BUDB_NOTPERMITTED  :                /* budb_errs.h */
272 /*  case KRB_RD_AP_UNAUTHOR : */
273     case BZACCESS           :                /* bnode.h     */
274     case VOLSERBAD_ACCESS   :                /* volser.h    */
275       result = AUDIT_FAIL_PRIV;
276       break;
277     default:
278       result = AUDIT_FAIL;
279       break;
280   }
281
282   ObtainWriteLock(&audbuflock);
283   bufferPtr = BUFFER;
284
285   /* Put the error code into the buffer list */
286   *(int *)bufferPtr = errCode;
287   bufferPtr += sizeof(errCode);
288
289   va_start(vaList, errCode);
290   aixmakebuf(audEvent, vaList);
291
292   va_start(vaList, errCode);
293   printbuf(audEvent, errCode, vaList);
294         
295   bufferLen = (int)((afs_int32)bufferPtr - (afs_int32)&BUFFER[0]);
296   code = auditlog (audEvent, result, BUFFER, bufferLen);
297 #ifdef notdef
298   if (code) 
299   {
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 osi_auditU (struct rx_call *call,
315             char           *audEvent,
316             int            errCode,
317             ...)
318 {
319   struct rx_connection        *conn;
320   struct rx_peer              *peer;
321   afs_int32                        secClass;
322   afs_int32                        code;
323   char                        afsName[MAXKTCNAMELEN];
324   afs_int32                        hostId;
325   va_list                     vaList;
326
327
328   if ( osi_audit_all < 0 ) osi_audit_check();
329   if ( !osi_audit_all ) return;
330
331   strcpy (afsName,  "--Unknown--");
332   hostId = 0;
333
334   if ( call ) 
335   {
336     conn = rx_ConnectionOf(call);                       /* call -> conn) */
337     if (conn)
338     {
339       secClass  = rx_SecurityClassOf(conn);             /* conn -> securityIndex */
340       if (secClass == 0)                                /* unauthenticated */
341       {
342         osi_audit ("AFS_Aud_Unauth", (-1), AUD_STR, audEvent, AUD_END);
343         strcpy (afsName,  "--UnAuth--");
344       }
345       else if (secClass == 2)                           /* authenticated */
346       {
347         code = rxkad_GetServerInfo(conn, (char *)0, (char *)0, afsName, 
348                                    (char *)0, (char *)0, (char *)0);
349         if (code)
350         {
351           osi_audit ("AFS_Aud_NoAFSId", (-1), AUD_STR, audEvent, AUD_END);
352           strcpy (afsName,  "--NoName--");
353         }
354       }
355       else                                               /* Unauthenticated & unknown */
356       {
357         osi_audit ("AFS_Aud_UnknSec", (-1), AUD_STR, audEvent, AUD_END);
358       }
359
360       peer = rx_PeerOf(conn);                            /* conn -> peer */
361       if ( peer )
362         hostId = rx_HostOf(peer);                        /* peer -> host */
363       else
364         osi_audit ("AFS_Aud_NoHost", (-1), AUD_STR, audEvent, AUD_END);
365     }
366     else /* null conn */
367     {
368       osi_audit ("AFS_Aud_NoConn", (-1), AUD_STR, audEvent, AUD_END);
369     }
370   }
371   else  /* null call */
372   {
373     osi_audit ("AFS_Aud_NoCall", (-1), AUD_STR, audEvent, AUD_END);
374   }
375
376   va_start(vaList, errCode);
377   osi_audit (audEvent, errCode, AUD_STR,  afsName, 
378                                 AUD_HOST, hostId, 
379                                 AUD_LST,  vaList, 
380                                 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 osi_audit_check ()
390 {
391   FILE        *fds;
392   int         onoff;
393   char        event[257];
394   
395   osi_audit_all  = 1;                 /* say we made check (>= 0) */
396                                       /* and assume audit all events (for now) */
397   onoff          = 0;                 /* assume we will turn auditing off */
398   osi_echo_trail = 0;                 /* assume no echoing   */
399
400   fds = fopen(AFSDIR_SERVER_AUDIT_FILEPATH, "r");
401   if (fds)
402   {
403     while ( fscanf(fds, "%256s", event) > 0)
404     {
405       if ( strcmp(event,"AFS_AUDIT_AllEvents") == 0 ) 
406         onoff = 1;
407
408       if ( strcmp(event,"Echo_Trail") == 0 ) 
409         osi_echo_trail = 1;
410     }    
411     fclose(fds);
412   }
413
414   /* Audit this event all of the time */
415   if (onoff) osi_audit("AFS_Aud_On",  0, AUD_END);
416   else       osi_audit("AFS_Aud_Off", 0, AUD_END);
417
418   /* Now set whether we audit all events from here on out */
419   osi_audit_all = onoff;
420 }
421
422
423 #else /* ! AFS_AIX_ENV */
424
425 int osi_audit (char *audEvent, afs_int32 errCode, ...)
426 { return 0; }
427
428 int osi_auditU (struct rx_call *call, char *audEvent, int errCode, ...)
429 { return 0; }
430
431 #endif
432