butc: fix int to float conversion warning
[openafs.git] / src / butc / tcmain.c
index e632092..8402963 100644 (file)
 #include <afsconfig.h>
 #include <afs/param.h>
 
+#include <afs/procmgmt.h>
+
+#include <roken.h>
+#include <afs/opr.h>
+
 #ifdef IGNORE_SOME_GCC_WARNINGS
 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
 #endif
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <WINNT/afsevent.h>
-#else
-#include <netinet/in.h>
-#include <sys/time.h>
 #endif
-#include <afs/procmgmt.h>
+
+#include <ctype.h>
+
+#include <rx/rx.h>
+#include <rx/rx_globals.h>
+#include <rx/rxkad.h>
 #include <rx/xdr.h>
+
 #include <afs/afsint.h>
-#include <stdio.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else
-#include <afs/afs_assert.h>
-#endif
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
-#include <string.h>
 #include <afs/vlserver.h>
 #include <lwp.h>
 #include <lock.h>
 #include <afs/afsutil.h>
-#include <rx/rx.h>
-#include <rx/rx_globals.h>
-#include <rx/rxkad.h>
 #include <afs/cellconfig.h>
 #include <afs/keys.h>
 #include <afs/volser.h>
 #include <ubik.h>
+#include <afs/audit.h>
 #include <afs/com_err.h>
-#include <errno.h>
 #include <afs/cmd.h>
 #include <afs/tcdata.h>
 #include <afs/bubasics.h>
-#include <ctype.h>
-#include "error_macros.h"
 #include <afs/budb_errs.h>
 #include <afs/budb_client.h>
 #include <afs/bucoord_prototypes.h>
-#include "afs/butx.h"
+#include <afs/butx.h>
+#include <afs/kautils.h>
+#include <afs/bc.h>
+
+#include "error_macros.h"
 #define XBSA_TCMAIN
 #include "butc_xbsa.h"
 #include "butc_prototypes.h"
-#include <afs/kautils.h>
-#include <afs/bc.h>
+#include "butc_internal.h"
 
 #define N_SECURITY_OBJECTS 3
 #define ERRCODE_RANGE 8                /* from error_table.h */
 #define TL_PREFIX  "TL"
 #define CFG_PREFIX "CFG"
 
-struct ubik_client *cstruct;
+extern struct ubik_client *cstruct;
 FILE *logIO, *ErrorlogIO, *centralLogIO, *lastLogIO;
 char lFile[AFSDIR_PATH_MAX];
-char logFile[256];
-char ErrorlogFile[256];
-char lastLogFile[256];
+char logFile[AFSDIR_PATH_MAX + 256];
+char ErrorlogFile[AFSDIR_PATH_MAX + 256];
+char lastLogFile[AFSDIR_PATH_MAX + 256];
 char eFile[AFSDIR_PATH_MAX];
 char tapeConfigFile[AFSDIR_PATH_MAX];
 char pFile[AFSDIR_PATH_MAX];
@@ -110,18 +106,12 @@ 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;
+int allow_unauth = 0;
 
 #define ADDRSPERSITE 16         /* Same global is in rx/rx_user.c */
 afs_uint32 SHostAddrs[ADDRSPERSITE];
 
-/* dummy routine for the audit work.  It should do nothing since audits */
-/* occur at the server level and bos is not a server. */
-int
-osi_audit(void)
-{
-    return 0;
-}
-
 static afs_int32
 SafeATOL(char *anum)
 {
@@ -247,31 +237,14 @@ atocl(char *numstring, char crunit, afs_int32 *number)
        total *= 1024.0;
 
     total += 0.5;              /* Round up */
-    if ((total > 0x7fffffff) || (total < 0))   /* Don't go over 2G */
-       total = 0x7fffffff;
+    if ((total >= 2147483648.0) || (total < 0))        /* Don't go over 2G */
+       *number = 2147483647;
+    else
+       *number = total;
 
-    *number = total;
     return (0);
 }
 
-/* replace last two ocurrences of / by _ */
-#if 0
-static int
-stringReplace(char *name)
-{
-    char *pos;
-    char buffer[256];
-
-    pos = strrchr(name, '/');
-    *pos = '_';
-    strcpy(buffer, pos);
-    pos = strrchr(name, '/');
-    *pos = '\0';
-    strcat(name, buffer);
-    return 0;
-}
-#endif
-
 static int
 stringNowReplace(char *logFile, char *deviceName)
 {
@@ -294,10 +267,9 @@ stringNowReplace(char *logFile, char *deviceName)
        *pos = '_';
     strcat(logFile, deviceName);
     /* now put back deviceName to the way it was */
-    if (mvFlag) {
-       mvFlag = 0;
+    if (mvFlag)
        deviceName -= devPrefLen;
-    }
+
     strcpy(deviceName, storeDevice);
 
     return (0);
@@ -414,7 +386,7 @@ GetDeviceConfig(char *filename, struct tapeConfig *config, afs_int32 portOffset)
 static afs_int32
 GetConfigParams(char *filename, afs_int32 port)
 {
-    char paramFile[256];
+    char paramFile[AFSDIR_PATH_MAX + 257];
     FILE *devFile = 0;
     char line[LINESIZE], cmd[LINESIZE], value[LINESIZE];
     afs_int32 code = 0;
@@ -448,13 +420,13 @@ GetConfigParams(char *filename, afs_int32 port)
     groupId = 0;               /* Group id for multiple dumps */
 
     /* Try opening the CFG_<port> file */
-    sprintf(paramFile, "%s_%d", filename, port);
+    snprintf(paramFile, sizeof(paramFile), "%s_%d", filename, port);
     devFile = fopen(paramFile, "r");
     if (devFile) {
        /* Set log names to TL_<port>, TL_<port>.lp and TE_<port> */
-       sprintf(logFile, "%s_%d", lFile, port);
-       sprintf(lastLogFile, "%s_%d.lp", lFile, port);
-       sprintf(ErrorlogFile, "%s_%d", eFile, port);
+       snprintf(logFile, sizeof(logFile), "%s_%d", lFile, port);
+       snprintf(lastLogFile, sizeof(lastLogFile), "%s_%d.lp", lFile, port);
+       snprintf(ErrorlogFile, sizeof(ErrorlogFile), "%s_%d", eFile, port);
     } else if (CONF_XBSA) {
        /* If configured as XBSA, a configuration file CFG_<port> must exist */
        printf("Cannot open configuration file %s", paramFile);
@@ -520,8 +492,7 @@ GetConfigParams(char *filename, afs_int32 port)
                continue;
            }
 
-           opencallout = (char *)malloc(strlen(value) + 1);
-           strcpy(opencallout, value);
+           opencallout = strdup(value);
            printf("Tape mount callout routine is %s\n", opencallout);
        }
 
@@ -533,8 +504,7 @@ GetConfigParams(char *filename, afs_int32 port)
                continue;
            }
 
-           closecallout = (char *)malloc(strlen(value) + 1);
-           strcpy(closecallout, value);
+           closecallout = strdup(value);
            printf("Tape unmount callout routine is %s\n", closecallout);
        }
 
@@ -596,7 +566,7 @@ GetConfigParams(char *filename, afs_int32 port)
 
        else if (!strcmp(cmd, "BUFFERSIZE")) {
            afs_int32 size;
-           afs_int32 tapeblocks;
+           afs_int32 numTapeblocks;
 
            if (!CONF_XBSA) {
                if (atocl(value, 'K', &size)) {
@@ -607,11 +577,11 @@ GetConfigParams(char *filename, afs_int32 port)
                /* A tapeblock is 16KB. Determine # of tapeblocks. Then
                 * determine BufferSize needed for that many tapeblocks.
                 */
-               tapeblocks = size / 16;
-               if (tapeblocks <= 0)
-                   tapeblocks = 1;
-               printf("BUFFERSIZE is %u KBytes\n", (tapeblocks * 16));
-               BufferSize = tapeblocks * BUTM_BLOCKSIZE;
+               numTapeblocks = size / 16;
+               if (numTapeblocks <= 0)
+                   numTapeblocks = 1;
+               printf("BUFFERSIZE is %u KBytes\n", (numTapeblocks * 16));
+               BufferSize = numTapeblocks * BUTM_BLOCKSIZE;
            } else {
 #ifdef xbsa
                if (atocl(value, 'B', &size)) {
@@ -667,8 +637,7 @@ GetConfigParams(char *filename, afs_int32 port)
                     cmd);
                continue;
            }
-           xbsaObjectOwner = malloc(strlen(value) + 1);
-           strcpy(xbsaObjectOwner, value);
+           xbsaObjectOwner = strdup(value);
            printf("XBSA node is %s\n", xbsaObjectOwner);
        }
 
@@ -679,8 +648,7 @@ GetConfigParams(char *filename, afs_int32 port)
                     cmd);
                continue;
            }
-           adsmServerName = malloc(strlen(value) + 1);
-           strcpy(adsmServerName, value);
+           adsmServerName = strdup(value);
            printf("XBSA server is %s\n", adsmServerName);
        }
 
@@ -698,8 +666,7 @@ GetConfigParams(char *filename, afs_int32 port)
                continue;
            }
 
-           xbsaSecToken = malloc(strlen(value) + 1);
-           strcpy(xbsaSecToken, value);
+           xbsaSecToken = strdup(value);
            printf("XBSA Password has been read\n");
        }
 
@@ -742,8 +709,7 @@ GetConfigParams(char *filename, afs_int32 port)
                     cmd);
                continue;
            }
-           xbsalGName = malloc(strlen(value) + 1);
-           strcpy(xbsalGName, value);
+           xbsalGName = strdup(value);
            printf("XBSA management class is %s\n", xbsalGName);
        }
 #endif
@@ -777,8 +743,7 @@ GetConfigParams(char *filename, afs_int32 port)
        }
 
        else if (!strcmp(cmd, "CENTRALLOG")) {
-           centralLogFile = malloc(strlen(value) + 1);
-           strcpy(centralLogFile, value);
+           centralLogFile = strdup(value);
            printf("Central log file is %s\n", centralLogFile);
        }
 
@@ -835,11 +800,35 @@ GetConfigParams(char *filename, afs_int32 port)
     return (code);
 }
 
+#ifdef xbsa
+static void
+xbsa_shutdown(int x)
+{
+    xbsa_Finalize(&butxInfo);
+    exit(0);
+}
+#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;
-    struct rx_securityClass *(securityObjects[3]);
+    afs_int32 code, numClasses;
+    struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs;
     struct rx_service *service;
     time_t tokenExpires;
     char cellName[64];
@@ -853,7 +842,10 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
 #else
     PROCESS dbWatcherPid;
 #endif
+    char hoststr[16];
     afs_uint32 host = htonl(INADDR_ANY);
+    char *auditFileName = NULL;
+    char *auditInterface = NULL;
 
     debugLevel = 0;
 
@@ -909,9 +901,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
     }
 
     if (as->parms[6].items) {  /* -restoretofile */
-       int s = strlen(as->parms[6].items->data);
-       restoretofile = malloc(s + 1);
-       strncpy(restoretofile, as->parms[6].items->data, s + 1);
+       restoretofile = strdup(as->parms[6].items->data);
        printf("Restore to file '%s'\n", restoretofile);
     }
 
@@ -961,7 +951,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
        struct stat sbuf;
        afs_int32 statcode;
 #ifndef AFS_NT40_ENV
-       char path[AFSDIR_PATH_MAX];
+       char *path;
 #endif
 
        statcode = stat(centralLogFile, &sbuf);
@@ -973,7 +963,8 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
        }
 #ifndef AFS_NT40_ENV
        /* Make sure it is not in AFS, has to have been created first */
-       if (!realpath(centralLogFile, path)) {
+       path = malloc(AFSDIR_PATH_MAX);
+       if (path == NULL || !realpath(centralLogFile, path)) {
            fprintf(stderr,
                    "Warning: can't determine real path of '%s' (%d)\n",
                    centralLogFile, errno);
@@ -984,6 +975,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
                exit(1);
            }
        }
+       free(path);
 #endif
 
        /* Write header if created it */
@@ -999,6 +991,36 @@ 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);
+    }
+
+    if (afsconf_CountKeys(butc_confdir) == 0) {
+       TLog(0, "WARNING: No encryption keys found! "
+               "All authenticated accesses will fail. "
+               "Run akeyconvert or asetkey to import encryption keys.\n");
+    }
+
+    /* 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) {
@@ -1023,6 +1045,8 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
        rc = InitToServer(0 /*taskid */ , &butxInfo, adsmServerName);
        if (rc != XBSA_SUCCESS)
            return (1);
+       (void)signal(SIGINT, xbsa_shutdown);
+       (void)signal(SIGHUP, xbsa_shutdown);
     }
 #endif /*xbsa */
 
@@ -1037,16 +1061,23 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
 
     localauth = (as->parms[5].items ? 1 : 0);
     rxBind = (as->parms[8].items ? 1 : 0);
+    allow_unauth = (as->parms[11].items ? 1 : 0);
+
+    if (!allow_unauth && !localauth) {
+       const char *errstr = "Neither -localauth nor -allow_unauthenticated was provided; refusing to start in unintended insecure configuration\n";
+       TLog(0, "%s", (char *)errstr);
+       exit(1);
+    }
 
     if (rxBind) {
         afs_int32 ccode;
         if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
             AFSDIR_SERVER_NETINFO_FILEPATH) {
             char reason[1024];
-            ccode = parseNetFiles(SHostAddrs, NULL, NULL,
-                                           ADDRSPERSITE, reason,
-                                           AFSDIR_SERVER_NETINFO_FILEPATH,
-                                           AFSDIR_SERVER_NETRESTRICT_FILEPATH);
+            ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL,
+                                          ADDRSPERSITE, reason,
+                                          AFSDIR_SERVER_NETINFO_FILEPATH,
+                                          AFSDIR_SERVER_NETRESTRICT_FILEPATH);
         } else
        {
             ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
@@ -1055,6 +1086,8 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
             host = SHostAddrs[0];
     }
 
+    TLog(0, "butc binding rx to %s:%d\n",
+         afs_inet_ntoa_r(host, hoststr), BC_TAPEPORT + portOffset);
     code = rx_InitHost(host, htons(BC_TAPEPORT + portOffset));
     if (code) {
        TapeLog(0, 0, code, 0, "rx init failed on port %u\n",
@@ -1075,27 +1108,54 @@ WorkerBee(struct cmd_syndesc *as, void *arock)
     /*initialize the dumpNode list */
     InitNodeList(portOffset);
 
-    deviceLatch =
-       (struct deviceSyncNode *)(malloc(sizeof(struct deviceSyncNode)));
+    deviceLatch = malloc(sizeof(struct deviceSyncNode));
     Lock_Init(&(deviceLatch->lock));
     deviceLatch->flags = 0;
 
     /* initialize database support, volume support, and logs */
 
-    /* Create a single security object, in this case the null security
-     * object, for unauthenticated connections, which will be used to control
-     * security on connections made to this server
+    /*
+     * Create security objects for the Rx server functionality.  Historically
+     * this was a single rxnull security object, since the tape controller was
+     * run by an operator that had local access to the tape device and some
+     * administrative privilege in the cell (to be able to perform volume-level
+     * accesses), but on a machine that was not necessarily trusted to hold the
+     * cell-wide key.
+     *
+     * Such a configuration is, of course, insecure because anyone can make
+     * inbound RPCs and manipulate the database, including creating bogus
+     * dumps and restoring them!  Additionally, in modern usage, butc is
+     * frequently run with -localauth to authenticate its outbound connections
+     * to the volservers and budb with the cell-wide key, in which case the
+     * cell-wide key is present and could be used to authenticate incoming
+     * connections as well.
+     *
+     * If -localauth is in use, create the full barrage of server security
+     * objects, including rxkad, so that inbound connections can be verified
+     * to only be made by authenticated clients.  Otherwise, only the rxnull
+     * class is in use with a single server security object.  Note that butc
+     * will refuse to start in this configuration unless the
+     * "-allow_unauthenticated" flag is provided, indicating that the operator
+     * has ensured that incoming connections are appropriately restricted by
+     * firewall configuration or network topology.
      */
 
-    securityObjects[0] = rxnull_NewServerSecurityObject();
-    securityObjects[1] = (struct rx_securityClass *)0; /* don't bother with rxvab */
-    if (!securityObjects[0]) {
-       TLog(0, "rxnull_NewServerSecurityObject");
-       exit(1);
+    if (allow_unauth) {
+       nullObjects[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
+       if (!nullObjects[RX_SECIDX_NULL]) {
+           TLog(0, "rxnull_NewServerSecurityObject");
+           exit(1);
+       }
+       numClasses = 1;
+       secObjs = nullObjects;
+    } else {
+       /* Must be -localauth, so the cell keys are available. */
+       afsconf_BuildServerSecurityObjects(butc_confdir, &allObjs, &numClasses);
+       secObjs = allObjs;
     }
 
     service =
-       rx_NewServiceHost(host, 0, 1, "BUTC", securityObjects, 3, TC_ExecuteRequest);
+       rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest);
     if (!service) {
        TLog(0, "rx_NewService");
        exit(1);
@@ -1182,7 +1242,7 @@ main(int argc, char **argv)
 
     setlinebuf(stdout);
 
-    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, "tape coordinator");
+    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, 0, "tape coordinator");
     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "port offset");
     cmd_AddParm(ts, "-debuglevel", CMD_SINGLE, CMD_OPTIONAL, "0 | 1 | 2");
     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
@@ -1198,6 +1258,11 @@ 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");
+    cmd_AddParm(ts, "-allow_unauthenticated", CMD_FLAG, CMD_OPTIONAL,
+               "allow unauthenticated inbound RPCs (requires firewalling)");
 
     /* Initialize dirpaths */
     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
@@ -1210,32 +1275,31 @@ main(int argc, char **argv)
 
     /* setup the file paths */
     strcompose(eFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
-              TE_PREFIX, NULL);
+              TE_PREFIX, (char *)NULL);
     strcompose(lFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
-              TL_PREFIX, NULL);
+              TL_PREFIX, (char *)NULL);
     strcompose(pFile, AFSDIR_PATH_MAX, AFSDIR_SERVER_BACKUP_DIRPATH, "/",
-              CFG_PREFIX, NULL);
+              CFG_PREFIX, (char *)NULL);
     strcpy(tapeConfigFile, AFSDIR_SERVER_TAPECONFIG_FILEPATH);
 
     /* special case "no args" case since cmd_dispatch gives help message
      * instead
      */
     if (argc == 1) {
-       ts = (struct cmd_syndesc *)malloc(sizeof(struct cmd_syndesc));
-       memset(ts, 0, sizeof(*ts));
+       ts = calloc(1, sizeof(struct cmd_syndesc));
 
-       ti = (struct cmd_item *)malloc(sizeof(struct cmd_item));
+       ti = malloc(sizeof(struct cmd_item));
        ti->next = 0;
        ti->data = "0";
        ts->parms[0].items = ti;
-       ti = (struct cmd_item *)malloc(sizeof(struct cmd_item));
+       ti = malloc(sizeof(struct cmd_item));
        ti->next = 0;
        ti->data = "0";
        ts->parms[1].items = ti;
-       ts->parms[2].items = (struct cmd_item *)NULL;
-       ts->parms[3].items = (struct cmd_item *)NULL;
-       ts->parms[4].items = (struct cmd_item *)NULL;
-       ts->parms[5].items = (struct cmd_item *)NULL;
+       ts->parms[2].items = NULL;
+       ts->parms[3].items = NULL;
+       ts->parms[4].items = NULL;
+       ts->parms[5].items = NULL;
        return WorkerBee(ts, NULL);
     } else
        return cmd_Dispatch(argc, argv);