Commit | Line | Data |
---|---|---|
805e021f CE |
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(¤ttime, &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 | } |