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