#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];
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];
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)
{
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;
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);
else if (!strcmp(cmd, "BUFFERSIZE")) {
afs_int32 size;
- afs_int32 tapeblocks;
+ afs_int32 numTapeblocks;
if (!CONF_XBSA) {
if (atocl(value, 'K', &size)) {
/* 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)) {
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));
+ 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[1]);
+ afs_int32 code, numClasses;
+ struct rx_securityClass *(nullObjects[1]), **secObjs, **allObjs;
struct rx_service *service;
time_t tokenExpires;
char cellName[64];
#else
PROCESS dbWatcherPid;
#endif
+ char hoststr[16];
afs_uint32 host = htonl(INADDR_ANY);
char *auditFileName = NULL;
char *auditInterface = NULL;
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) {
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;
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",
/* 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[RX_SECIDX_NULL] = rxnull_NewServerSecurityObject();
- if (!securityObjects[RX_SECIDX_NULL]) {
- 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, 1, TC_ExecuteRequest);
+ rx_NewServiceHost(host, 0, 1, "BUTC", secObjs, numClasses, TC_ExecuteRequest);
if (!service) {
TLog(0, "rx_NewService");
exit(1);
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)) {