OPENAFS-SA-2018-001 Add auditing to butc server RPC implementations
authorBenjamin Kaduk <kaduk@mit.edu>
Sun, 9 Sep 2018 16:49:03 +0000 (11:49 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Sun, 9 Sep 2018 22:35:26 +0000 (17:35 -0500)
Make the actual implementations into helper functions, with the RPC
stubs calling the helpers and doing the auditing on the results, akin
to most other server programs in the tree.  This relies on support for
some additional types having been added to the audit framework.

Change-Id: Ic872d6dfc7854fa28bd3dc2277e92c7919d0d0c0

doc/man-pages/pod8/butc.pod
src/audit/audit.h
src/butc/Makefile.in
src/butc/butc_prototypes.h
src/butc/tcmain.c
src/butc/tcprocs.c
src/butc/tcstatus.c

index 730ce83..e836d39 100644 (file)
@@ -8,10 +8,12 @@ butc - Initializes the Tape Coordinator process
 <div class="synopsis">
 
 B<butc> S<<< [B<-port> <I<port offset>>] >>> S<<< [B<-debuglevel> (0 | 1 | 2)] >>>
-    S<<< [B<-cell> <I<cell name>>] >>> [B<-noautoquery>] [B<-rxbind>] [B<-localauth>] [B<-help>]
+    S<<< [B<-cell> <I<cell name>>] >>> [B<-noautoquery>] [B<-rxbind>] [B<-localauth>]
+    [B<-auditlog> <I<file | sysvmq>> [B<-audit-interface> <I<interface>>]] [B<-help>]
 
 B<butc> S<<< [B<-p> <I<port offset>>] >>> S<<< [B<-d> (0 | 1 | 2)] >>>
-    S<<< [B<-c> <I<cell name>>] >>> [B<-n>] [B<-r>] [B<-l>] [B<-h>]
+    S<<< [B<-c> <I<cell name>>] >>> [B<-n>] [B<-r>] [B<-l>]
+    [B<-auditl> <I<file | sysvmq>> [-B<-audit-i> <I<interface>>]] [B<-h>]
 
 =for html
 </div>
@@ -186,6 +188,19 @@ logged on to a server machine as the local superuser C<root>; client
 machines do not have F</usr/afs/etc/KeyFile> or F</usr/afs/etc/KeyFileExt>
 files.
 
+=item B<-auditlog> <I<log path>>
+
+Turns on audit logging, and sets the path for the audit log.  The audit
+log records information about RPC calls, including the name of the RPC
+call, the host that submitted the call, the authenticated entity (user)
+that issued the call, the parameters for the call, and if the call
+succeeded or failed.
+
+=item B<-audit-interface> <(file | sysvmq)>
+
+Specifies what audit interface to use. Defaults to C<file>. See
+L<fileserver(8)> for an explanation of each interface.
+
 =item B<-help>
 
 Prints the online help for this command. All other valid options are
index 599620a..6188cf6 100644 (file)
 #define SREMIORemoteGetHSMdata  "AFS_RE_HSMdata"
 #define SREMIOPrefetch          "AFS_RE_Prefetch"
 
+#define TC_StartEvent           "AFS_TC_Start"
+#define TC_LabelTapeEvent       "AFS_TC_LabelTape"
+#define TC_PerformDumpEvent     "AFS_TC_PerformDump"
+#define TC_PerformRestoreEvent  "AFS_TC_PerformRestore"
+#define TC_ReadLabelEvent       "AFS_TC_ReadLabel"
+#define TC_RestoreDbEvent       "AFS_TC_RestoreDb"
+#define TC_SaveDbEvent          "AFS_TC_SaveDb"
+#define TC_ScanDumpsEvent       "AFS_TC_ScanDumps"
+#define TC_TCInfoEvent          "AFS_TC_TCInfo"
+#define TC_DeleteDumpEvent      "AFS_TC_DeleteDump"
+#define TC_GetStatusEvent       "AFS_TC_GetStatus"
+#define TC_EndStatusEvent       "AFS_TC_EndStatus"
+#define TC_RequestAbortEvent    "AFS_TC_RequestAbort"
+#define TC_ScanStatusEvent      "AFS_TC_ScanStatus"
+
 
 /* prototypes for audit functions */
 int osi_audit(char *audEvent, afs_int32 errCode, ...);
index 4648f96..5d94222 100644 (file)
@@ -38,6 +38,7 @@ LIBS=${TOP_LIBDIR}/libbudb.a \
         ${TOP_LIBDIR}/libsys.a  \
        ${TOP_LIBDIR}/librx.a \
         ${TOP_LIBDIR}/libsys.a  \
+       ${TOP_LIBDIR}/libaudit.a \
        ${TOP_LIBDIR}/liblwp.a \
         ${TOP_LIBDIR}/libcmd.a \
        ${TOP_LIBDIR}/libafscom_err.a \
index 1c62c34..a1d7712 100644 (file)
@@ -32,5 +32,9 @@ extern void *saveDbToTape(void *);
 extern void *restoreDbFromTape(void *);
 extern void *KeepAlive(void *);
 
+/* tcmain.c */
+
+extern struct afsconf_dir *butc_confdir;
+
 #endif
 
index 89b711a..7f79fa7 100644 (file)
@@ -41,6 +41,7 @@
 #include <afs/keys.h>
 #include <afs/volser.h>
 #include <ubik.h>
+#include <afs/audit.h>
 #include <afs/com_err.h>
 #include <afs/cmd.h>
 #include <afs/tcdata.h>
@@ -105,6 +106,7 @@ afs_int32 BufferSize;               /* Size in B stored for data */
 char *centralLogFile;
 afs_int32 lastLog;             /* Log last pass info */
 int rxBind = 0;
+struct afsconf_dir *butc_confdir;
 
 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
 afs_uint32 SHostAddrs[ADDRSPERSITE];
@@ -824,6 +826,21 @@ xbsa_shutdown(int x)
 #endif
 
 static int
+tc_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell)
+{
+    struct afsconf_dir *dir = (struct afsconf_dir *)rock;
+    afs_int32 islocal = 0;     /* default to no */
+    int code;
+
+    code = afsconf_IsLocalRealmMatch(dir, &islocal, name, inst, cell);
+    if (code) {
+       TLog(0, ("Failed local realm check; code=%d, name=%s, inst=%s, cell=%s\n",
+                code, name, inst, cell));
+    }
+    return islocal;
+}
+
+static int
 WorkerBee(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
@@ -842,6 +859,8 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
     PROCESS dbWatcherPid;
 #endif
     afs_uint32 host = htonl(INADDR_ANY);
+    char *auditFileName = NULL;
+    char *auditInterface = NULL;
 
     debugLevel = 0;
 
@@ -987,6 +1006,30 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
        }
     }
 
+    /* Open the configuration directory */
+    butc_confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
+    if (butc_confdir == NULL) {
+       TLog(0, "Failed to open server configuration directory");
+       exit(1);
+    }
+
+    /* Start auditing */
+    osi_audit_init();
+    if (as->parms[9].items) {
+       auditFileName = as->parms[9].items->data;
+    }
+    if (auditFileName != NULL)
+       osi_audit_file(auditFileName);
+    if (as->parms[10].items) {
+       auditInterface = as->parms[10].items->data;
+       if (osi_audit_interface(auditInterface)) {
+           TLog(0, "Invalid audit interface '%s'\n", auditInterface);
+           exit(1);
+       }
+    }
+    osi_audit(TC_StartEvent, 0, AUD_END);
+    osi_audit_set_user_check(butc_confdir, tc_IsLocalRealmMatch);
+
     if (as->parms[1].items) {
        debugLevel = SafeATOL(as->parms[1].items->data);
        if (debugLevel == -1) {
@@ -1186,6 +1229,9 @@ main(int argc, char **argv)
                "Force multiple XBSA server support");
     cmd_AddParm(ts, "-rxbind", CMD_FLAG, CMD_OPTIONAL,
                "bind Rx socket");
+    cmd_AddParm(ts, "-auditlog", CMD_SINGLE, CMD_OPTIONAL, "location of audit log");
+    cmd_AddParm(ts, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL,
+               "interface to use for audit logging");
 
     /* Initialize dirpaths */
     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
index cc19e53..7f0e40c 100644 (file)
 #include "butc_xbsa.h"
 #include "butc_prototypes.h"
 #include "butc_internal.h"
+#include "afs/audit.h"
 
 static int CopyDumpDesc(struct tc_dumpDesc *, tc_dumpArray *);
 static int CopyRestoreDesc(struct tc_restoreDesc *, tc_restoreArray *);
 static int CopyTapeSetDesc(struct tc_tapeSet *, struct tc_tapeSet *);
 
+/* Helpers implementing RPC backends */
+static afs_int32 SLabelTape(struct rx_call *acid, struct tc_tapeLabel *label,
+                           afs_uint32 *taskId);
+static afs_int32 SPerformDump(struct rx_call *rxCallId,
+                             struct tc_dumpInterface *tcdiPtr,
+                             tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId);
+static afs_int32 SPerformRestore(struct rx_call *acid, char *dumpSetName,
+                                tc_restoreArray *arestores, afs_int32 *taskId);
+static afs_int32 SReadLabel(struct rx_call *acid, struct tc_tapeLabel *label,
+                           afs_uint32 *taskId);
+static afs_int32 SRestoreDb(struct rx_call *rxCall, afs_uint32 *taskId);
+static afs_int32 SSaveDb(struct rx_call *rxCall, Date archiveTime,
+                        afs_uint32 *taskId);
+static afs_int32 SScanDumps(struct rx_call *acid, afs_int32 addDbFlag,
+                           afs_uint32 *taskId);
+static afs_int32 STCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr);
+static afs_int32 SDeleteDump(struct rx_call *acid, afs_uint32 dumpID,
+                            afs_uint32 *taskId);
+
 int
 callPermitted(struct rx_call *call)
 {
@@ -130,6 +150,17 @@ CopyTapeSetDesc(struct tc_tapeSet *toPtr, struct tc_tapeSet *fromPtr)
 afs_int32
 STC_LabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
 {
+    afs_int32 code;
+
+    code = SLabelTape(acid, label, taskId);
+    osi_auditU(acid, TC_LabelTapeEvent, code,
+              AUD_TLBL, label, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SLabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
+{
 #ifdef AFS_PTHREAD_ENV
     pthread_t pid;
     pthread_attr_t tattr;
@@ -204,7 +235,20 @@ STC_LabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *task
  */
 
 afs_int32
-STC_PerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr, tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId)
+STC_PerformDump(struct rx_call *call, struct tc_dumpInterface *di,
+               tc_dumpArray *da, afs_int32 *taskId)
+{
+    afs_int32 code;
+
+    code = SPerformDump(call, di, da, taskId);
+    osi_auditU(call, TC_PerformDumpEvent, code,
+              AUD_TDI, di, AUD_TDA, da, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SPerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr,
+            tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId)
 {
     struct dumpNode *newNode = 0;
     statusP statusPtr = 0;
@@ -295,7 +339,20 @@ STC_PerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr, tc_d
 }
 
 afs_int32
-STC_PerformRestore(struct rx_call *acid, char *dumpSetName, tc_restoreArray *arestores, afs_int32 *taskID)
+STC_PerformRestore(struct rx_call *call, char *dumpSetName,
+                  tc_restoreArray *ra, afs_int32 *taskId)
+{
+    afs_int32 code;
+
+    code = SPerformRestore(call, dumpSetName, ra, taskId);
+    osi_auditU(call, TC_PerformRestoreEvent, code,
+              AUD_STR, dumpSetName, AUD_TRA, ra, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SPerformRestore(struct rx_call *acid, char *dumpSetName,
+               tc_restoreArray *arestores, afs_int32 *taskID)
 {
     struct dumpNode *newNode;
     statusP statusPtr;
@@ -368,7 +425,18 @@ STC_PerformRestore(struct rx_call *acid, char *dumpSetName, tc_restoreArray *are
 }
 
 afs_int32
-STC_ReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
+STC_ReadLabel(struct rx_call *call, struct tc_tapeLabel *label, afs_uint32 *taskId)
+{
+    afs_int32 code;
+
+    code = SReadLabel(call, label, taskId);
+    osi_auditU(call, TC_ReadLabelEvent, code,
+              AUD_TLBL, label, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
 {
     afs_int32 code;
 
@@ -392,7 +460,17 @@ STC_ReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *task
  */
 
 afs_int32
-STC_RestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
+STC_RestoreDb(struct rx_call *call, afs_uint32 *taskId)
+{
+    afs_int32 code;
+
+    code = SRestoreDb(call, taskId);
+    osi_auditU(call, TC_RestoreDbEvent, code, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SRestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
 {
 #ifdef AFS_PTHREAD_ENV
     pthread_t pid;
@@ -458,7 +536,18 @@ STC_RestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
  */
 
 afs_int32
-STC_SaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
+STC_SaveDb(struct rx_call *call, Date archiveTime, afs_uint32 *taskId)
+{
+    afs_int32 code;
+
+    code = SSaveDb(call, archiveTime, taskId);
+    osi_auditU(call, TC_SaveDbEvent, code,
+              AUD_DATE, archiveTime, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SSaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
 {
 #ifdef AFS_PTHREAD_ENV
     pthread_t pid;
@@ -537,7 +626,18 @@ STC_SaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
  */
 
 afs_int32
-STC_ScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
+STC_ScanDumps(struct rx_call *call, afs_int32 addDbFlag, afs_uint32 *taskId)
+{
+    afs_int32 code;
+
+    code = SScanDumps(call, addDbFlag, taskId);
+    osi_auditU(call, TC_ScanDumpsEvent, code,
+              AUD_INT, addDbFlag, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
 {
 #ifdef AFS_PTHREAD_ENV
     pthread_t pid;
@@ -612,7 +712,17 @@ STC_ScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
  */
 
 afs_int32
-STC_TCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
+STC_TCInfo(struct rx_call *call, struct tc_tcInfo *ti)
+{
+    afs_int32 code;
+
+    code = STCInfo(call, ti);
+    osi_auditU(call, TC_TCInfoEvent, code, AUD_INT, ti->tcVersion, AUD_END);
+    return code;
+}
+
+static afs_int32
+STCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
 {
     if (callPermitted(acid) == 0)
        return (TC_NOTPERMITTED);
@@ -624,7 +734,18 @@ STC_TCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
 /* STC_DeleteDump
  */
 afs_int32
-STC_DeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId)
+STC_DeleteDump(struct rx_call *call, afs_uint32 dumpID, afs_uint32 *taskId)
+{
+    afs_int32 code;
+
+    code = SDeleteDump(call, dumpID, taskId);
+    osi_auditU(call, TC_DeleteDumpEvent, code,
+              AUD_DATE, dumpID, AUD_INT, *taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SDeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId)
 {
     afs_int32 code = TC_BADTASK;       /* If not compiled -Dxbsa then fail */
 #ifdef xbsa
index db06b51..b67ae1e 100644 (file)
@@ -23,6 +23,7 @@
 #include "butc_internal.h"
 #include "error_macros.h"
 #include "butc_xbsa.h"
+#include "afs/audit.h"
 
 /* tape coordinator - task status management */
 extern afs_int32 xbsaType;
@@ -31,6 +32,13 @@ dlqlinkT statusHead;
 struct Lock statusQueueLock;
 struct Lock cmdLineLock;
 
+static afs_int32 SGetStatus(struct rx_call *call, afs_uint32 taskId,
+                           struct tciStatusS *statusPtr);
+static afs_int32 SEndStatus(struct rx_call *call, afs_uint32 taskId);
+static afs_int32 SRequestAbort(struct rx_call *call, afs_uint32 taskId);
+static afs_int32 SScanStatus(struct rx_call *call, afs_uint32 *taskId,
+                            struct tciStatusS *statusPtr, afs_uint32 *flags);
+
 /* STC_GetStatus
  *     get the status of a task
  * entry:
@@ -41,7 +49,19 @@ struct Lock cmdLineLock;
 
 afs_int32
 STC_GetStatus(struct rx_call *call, afs_uint32 taskId,
-             struct tciStatusS *statusPtr)
+             struct tciStatusS *status)
+{
+    afs_int32 code;
+
+    code = SGetStatus(call, taskId, status);
+    osi_auditU(call, TC_GetStatusEvent, code,
+              AUD_INT, taskId, AUD_TSTT, status, AUD_END);
+    return code;
+}
+
+static afs_int32
+SGetStatus(struct rx_call *call, afs_uint32 taskId,
+          struct tciStatusS *statusPtr)
 {
     statusP ptr;
     int retval = 0;
@@ -72,6 +92,16 @@ STC_GetStatus(struct rx_call *call, afs_uint32 taskId,
 afs_int32
 STC_EndStatus(struct rx_call *call, afs_uint32 taskId)
 {
+    afs_int32 code;
+
+    code = SEndStatus(call, taskId);
+    osi_auditU(call, TC_EndStatusEvent, code, AUD_INT, taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SEndStatus(struct rx_call *call, afs_uint32 taskId)
+{
     statusP ptr;
     int retval = 0;
 
@@ -93,6 +123,16 @@ STC_EndStatus(struct rx_call *call, afs_uint32 taskId)
 afs_int32
 STC_RequestAbort(struct rx_call *call, afs_uint32 taskId)
 {
+    afs_int32 code;
+
+    code = SRequestAbort(call, taskId);
+    osi_auditU(call, TC_RequestAbortEvent, code, AUD_INT, taskId, AUD_END);
+    return code;
+}
+
+static afs_int32
+SRequestAbort(struct rx_call *call, afs_uint32 taskId)
+{
     statusP ptr;
     int retval = 0;
 
@@ -127,7 +167,19 @@ STC_RequestAbort(struct rx_call *call, afs_uint32 taskId)
 
 afs_int32
 STC_ScanStatus(struct rx_call *call, afs_uint32 *taskId,
-              struct tciStatusS *statusPtr, afs_uint32 *flags)
+              struct tciStatusS *status, afs_uint32 *flags)
+{
+    afs_int32 code;
+
+    code = SScanStatus(call, taskId, status, flags);
+    osi_auditU(call, TC_ScanStatusEvent, code,
+              AUD_INT, *taskId, AUD_TSTT, status, AUD_INT, *flags, AUD_END);
+    return code;
+}
+
+static afs_int32
+SScanStatus(struct rx_call *call, afs_uint32 *taskId,
+           struct tciStatusS *statusPtr, afs_uint32 *flags)
 {
     statusP ptr = 0;
     dlqlinkP dlqPtr;