2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/audit.h>
20 #define AUDIT_FAIL_AUTH 2
21 #define AUDIT_FAIL_ACCESS 3
22 #define AUDIT_FAIL_PRIV 4
23 #endif /* AFS_AIX32_ENV */
26 #include "afs/afsint.h"
31 #include "audit-api.h"
34 #include <afs/afsutil.h>
36 extern struct osi_audit_ops audit_file_ops
;
38 extern struct osi_audit_ops audit_sysvmq_ops
;
43 int (*islocal
)(void *rock
, char *name
, char *inst
, char *cell
);
44 } audit_user_check
= { NULL
, NULL
};
48 const struct osi_audit_ops
*ops
;
49 } audit_interfaces
[] = {
51 { "file", &audit_file_ops
},
53 { "sysvmq", &audit_sysvmq_ops
},
57 #define N_INTERFACES (sizeof(audit_interfaces) / sizeof(audit_interfaces[0]))
59 /* default to `file' audit interface */
60 static const struct osi_audit_ops
*audit_ops
= &audit_file_ops
;
62 static int osi_audit_all
= (-1); /* Not determined yet */
63 static int osi_echo_trail
= (-1);
65 static int auditout_open
= 0;
67 static int osi_audit_check(void);
70 static char *bufferPtr
;
74 audmakebuf(char *audEvent
, va_list vaList
)
83 vaEntry
= va_arg(vaList
, int);
84 while (vaEntry
!= AUD_END
) {
86 case AUD_STR
: /* String */
87 case AUD_NAME
: /* Name */
88 case AUD_ACL
: /* ACL */
89 vaStr
= (char *)va_arg(vaList
, char *);
91 strcpy(bufferPtr
, vaStr
);
92 bufferPtr
+= strlen(vaStr
) + 1;
94 strcpy(bufferPtr
, "");
98 case AUD_INT
: /* Integer */
99 case AUD_ID
: /* ViceId */
100 vaInt
= va_arg(vaList
, int);
101 *(int *)bufferPtr
= vaInt
;
102 bufferPtr
+= sizeof(vaInt
);
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
);
111 case AUD_FID
: /* AFSFid - contains 3 entries */
112 vaFid
= (struct AFSFid
*)va_arg(vaList
, struct AFSFid
*);
114 memcpy(bufferPtr
, vaFid
, sizeof(struct AFSFid
));
116 memset(bufferPtr
, 0, sizeof(struct AFSFid
));
118 bufferPtr
+= sizeof(struct AFSFid
);
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. */
126 struct AFSCBFids
*Fids
;
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
));
135 *((u_int
*) bufferPtr
) = 0;
136 bufferPtr
+= sizeof(u_int
);
137 memset(bufferPtr
, 0, sizeof(struct AFSFid
));
139 bufferPtr
+= sizeof(struct AFSFid
);
142 /* butc tape label */
145 struct tc_tapeLabel
*label
;
147 label
= (struct tc_tapeLabel
*)va_arg(vaList
,
148 struct tc_tapeLabel
*);
150 memcpy(bufferPtr
, label
, sizeof(*label
));
152 memset(bufferPtr
, 0, sizeof(*label
));
153 bufferPtr
+= sizeof(label
);
156 /* butc dump interface */
159 struct tc_dumpInterface
*di
;
161 di
= (struct tc_dumpInterface
*)
162 va_arg(vaList
, struct tc_dumpInterface
*);
164 memcpy(bufferPtr
, di
, sizeof(*di
));
166 memset(bufferPtr
, 0, sizeof(*di
));
167 bufferPtr
+= sizeof(*di
);
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.
177 struct tc_dumpArray
*da
;
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]));
187 memset(bufferPtr
, 0, sizeof(u_int
));
188 bufferPtr
+= sizeof(u_int
);
189 memset(bufferPtr
, 0, sizeof(da
->tc_dumpArray_val
[0]));
191 bufferPtr
+= sizeof(da
->tc_dumpArray_val
[0]);
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.
201 struct tc_restoreArray
*ra
;
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]));
211 memset(bufferPtr
, 0, sizeof(u_int
));
212 bufferPtr
+= sizeof(u_int
);
213 memset(bufferPtr
, 0, sizeof(ra
->tc_restoreArray_val
[0]));
215 bufferPtr
+= sizeof(ra
->tc_restoreArray_val
[0]);
218 /* butc tape controller status */
220 struct tciStatusS
*status
;
222 status
= (struct tciStatusS
*)va_arg(vaList
,
223 struct tciStatusS
*);
225 memcpy(bufferPtr
, status
, sizeof(*status
));
227 memset(bufferPtr
, 0, sizeof(*status
));
228 bufferPtr
+= sizeof(*status
);
234 auditlog("AFS_Aud_EINVAL", (-1), audEvent
,
235 (strlen(audEvent
) + 1));
241 vaEntry
= va_arg(vaList
, int);
247 printbuf(int rec
, char *audEvent
, char *afsName
, afs_int32 hostId
,
248 afs_int32 errCode
, va_list vaList
)
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
;
267 /* Don't print the timestamp or thread id if we recursed */
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
);
275 audit_ops
->append_msg("[%d] ", num
);
278 audit_ops
->append_msg("EVENT %s CODE %d ", audEvent
, errCode
);
281 hostAddr
.s_addr
= hostId
;
282 audit_ops
->append_msg("NAME %s HOST %s ", afsName
, inet_ntoa(hostAddr
));
285 vaEntry
= va_arg(vaList
, int);
286 while (vaEntry
!= AUD_END
) {
288 case AUD_STR
: /* String */
289 vaStr
= (char *)va_arg(vaList
, char *);
291 audit_ops
->append_msg("STR %s ", vaStr
);
293 audit_ops
->append_msg("STR <null>");
295 case AUD_NAME
: /* Name */
296 vaStr
= (char *)va_arg(vaList
, char *);
298 audit_ops
->append_msg("NAME %s ", vaStr
);
300 audit_ops
->append_msg("NAME <null>");
302 case AUD_ACL
: /* ACL */
303 vaStr
= (char *)va_arg(vaList
, char *);
305 audit_ops
->append_msg("ACL %s ", vaStr
);
307 audit_ops
->append_msg("ACL <null>");
309 case AUD_INT
: /* Integer */
310 vaInt
= va_arg(vaList
, int);
311 audit_ops
->append_msg("INT %d ", vaInt
);
313 case AUD_ID
: /* ViceId */
314 vaInt
= va_arg(vaList
, int);
315 audit_ops
->append_msg("ID %d ", vaInt
);
317 case AUD_DATE
: /* Date */
318 vaLong
= va_arg(vaList
, afs_int32
);
319 audit_ops
->append_msg("DATE %u ", vaLong
);
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
));
326 case AUD_LONG
: /* afs_int32 */
327 vaLong
= va_arg(vaList
, afs_int32
);
328 audit_ops
->append_msg("LONG %d ", vaLong
);
330 case AUD_FID
: /* AFSFid - contains 3 entries */
331 vaFid
= va_arg(vaList
, struct AFSFid
*);
333 audit_ops
->append_msg("FID %u:%u:%u ", vaFid
->Volume
, vaFid
->Vnode
,
336 audit_ops
->append_msg("FID %u:%u:%u ", 0, 0, 0);
338 case AUD_FIDS
: /* array of Fids */
339 vaFids
= va_arg(vaList
, struct AFSCBFids
*);
344 vaFid
= vaFids
->AFSCBFids_val
;
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
);
352 audit_ops
->append_msg("FIDS 0 FID 0:0:0 ");
356 case AUD_TLBL
: /* butc tape label */
357 vaLabel
= va_arg(vaList
, struct tc_tapeLabel
*);
360 audit_ops
->append_msg("TAPELABEL %d:%.*s:%.*s:%u ",
362 TC_MAXTAPELEN
, vaLabel
->afsname
,
363 TC_MAXTAPELEN
, vaLabel
->pname
,
366 audit_ops
->append_msg("TAPELABEL <null>");
370 vaDI
= va_arg(vaList
, struct tc_dumpInterface
*);
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
,
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
);
383 audit_ops
->append_msg("TCDUMPINTERFACE <null>");
387 vaDA
= va_arg(vaList
, struct tc_dumpArray
*);
391 struct tc_dumpDesc
*desc
;
392 struct in_addr hostAddr
;
394 desc
= vaDA
->tc_dumpArray_val
;
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
));
405 audit_ops
->append_msg("DUMPS 0 DUMP 0:0::0:0:0:0.0.0.0");
410 vaRA
= va_arg(vaList
, struct tc_restoreArray
*);
414 struct tc_restoreDesc
*desc
;
415 struct in_addr hostAddr
;
417 desc
= vaRA
->tc_restoreArray_val
;
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
);
433 audit_ops
->append_msg(
434 "RESTORES 0 RESTORE 0::0:0:0:0:0:0:0:0.0.0.0::: ");
439 vaTCstatus
= va_arg(vaList
, struct tciStatusS
*);
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
);
450 audit_ops
->append_msg("TCSTATUS <null>");
453 audit_ops
->append_msg("--badval-- ");
456 vaEntry
= va_arg(vaList
, int);
459 audit_ops
->send_msg();
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
;
468 osi_audit_init_lock(void)
470 MUTEX_INIT(&audit_lock
, "audit", MUTEX_DEFAULT
, 0);
471 audit_lock_initialized
= 1;
478 #ifdef AFS_PTHREAD_ENV
479 if (!audit_lock_initialized
) {
480 pthread_once(&audit_lock_once
, osi_audit_init_lock
);
482 #endif /* AFS_PTHREAD_ENV */
485 /* ************************************************************************** */
486 /* The routine that acually does the audit call.
487 * ************************************************************************** */
489 osi_audit_internal(char *audEvent
, /* Event name (15 chars or less) */
490 afs_int32 errCode
, /* The error code */
498 static char BUFFER
[32768];
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 */
509 if ((osi_audit_all
< 0) || (osi_echo_trail
< 0))
511 if (!osi_audit_all
&& !auditout_open
)
519 case KANOAUTH
: /* kautils.h */
520 case RXKADNOAUTH
: /* rxkad.h */
521 result
= AUDIT_FAIL_AUTH
;
523 case EPERM
: /* errno.h */
524 case EACCES
: /* errno.h */
525 case PRPERM
: /* pterror.h */
526 result
= AUDIT_FAIL_ACCESS
;
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
;
540 MUTEX_ENTER(&audit_lock
);
544 /* Put the error code into the buffer list */
545 *(int *)bufferPtr
= errCode
;
546 bufferPtr
+= sizeof(errCode
);
548 audmakebuf(audEvent
, vaList
);
552 bufferLen
= (int)((afs_int32
) bufferPtr
- (afs_int32
) & BUFFER
[0]);
553 code
= auditlog(audEvent
, result
, BUFFER
, bufferLen
);
556 printbuf(0, audEvent
, afsName
, hostId
, errCode
, vaList
);
559 MUTEX_EXIT(&audit_lock
);
564 osi_audit(char *audEvent
, /* Event name (15 chars or less) */
565 afs_int32 errCode
, /* The error code */
570 if ((osi_audit_all
< 0) || (osi_echo_trail
< 0))
572 if (!osi_audit_all
&& !auditout_open
)
575 va_start(vaList
, errCode
);
576 osi_audit_internal(audEvent
, errCode
, NULL
, 0, vaList
);
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 * ************************************************************************** */
587 osi_auditU(struct rx_call
*call
, char *audEvent
, int errCode
, ...)
589 struct rx_connection
*conn
;
590 struct rx_peer
*peer
;
593 char afsName
[MAXKTCNAMELEN
+ MAXKTCNAMELEN
+ MAXKTCREALMLEN
+ 3];
597 if (osi_audit_all
< 0)
599 if (!osi_audit_all
&& !auditout_open
)
602 strcpy(afsName
, "--Unknown--");
606 conn
= rx_ConnectionOf(call
); /* call -> 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
];
619 rxkad_GetServerInfo(conn
, NULL
, NULL
, name
, inst
, tcell
,
622 osi_audit("AFS_Aud_NoAFSId", (-1), AUD_STR
, audEvent
, AUD_END
);
623 strcpy(afsName
, "--NoName--");
625 afs_int32 islocal
= 0;
626 if (audit_user_check
.islocal
) {
628 audit_user_check
.islocal(audit_user_check
.rock
,
631 strlcpy(afsName
, name
, sizeof(afsName
));
633 strlcat(afsName
, ".", sizeof(afsName
));
634 strlcat(afsName
, inst
, sizeof(afsName
));
636 if (tcell
[0] && !islocal
) {
637 strlcat(afsName
, "@", sizeof(afsName
));
638 strlcat(afsName
, tcell
, sizeof(afsName
));
641 } else { /* Unauthenticated and/or unknown */
642 osi_audit("AFS_Aud_UnknSec", (-1), AUD_STR
, audEvent
, AUD_END
);
643 strcpy(afsName
, "--Unknown--");
645 peer
= rx_PeerOf(conn
); /* conn -> peer */
647 hostId
= rx_HostOf(peer
); /* peer -> host */
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
);
653 } else { /* null call */
654 osi_audit("AFS_Aud_NoCall", (-1), AUD_STR
, audEvent
, AUD_END
);
656 va_start(vaList
, errCode
);
657 osi_audit_internal(audEvent
, errCode
, afsName
, hostId
, vaList
);
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
666 * ************************************************************************** */
669 osi_audit_check(void)
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 */
680 fds
= fopen(AFSDIR_SERVER_AUDIT_FILEPATH
, "r");
682 while (fscanf(fds
, "%256s", event
) > 0) {
683 if (strcmp(event
, "AFS_AUDIT_AllEvents") == 0)
686 if (strcmp(event
, "Echo_Trail") == 0)
692 /* Audit this event all of the time */
694 osi_audit("AFS_Aud_On", 0, AUD_END
);
696 osi_audit("AFS_Aud_Off", 0, AUD_END
);
698 /* Now set whether we audit all events from here on out */
699 osi_audit_all
= onoff
;
705 osi_audit_file(const char *fileName
)
707 if(!audit_ops
->open_file(fileName
)) {
715 osi_audit_interface(const char *interface
)
718 for (i
= 0; i
< N_INTERFACES
; ++i
) {
719 if (strcmp(interface
, audit_interfaces
[i
].name
) == 0) {
720 audit_ops
= audit_interfaces
[i
].ops
;
729 osi_audit_set_user_check(void *rock
,
730 int (*islocal
) (void *rock
, char *name
, char *inst
,
733 audit_user_check
.rock
= rock
;
734 audit_user_check
.islocal
= islocal
;
738 audit_PrintStats(FILE *out
)
740 audit_ops
->print_interface_stats(out
);