diff --git a/doc/man-pages/pod8/butc.pod b/doc/man-pages/pod8/butc.pod index e836d39408..42c72daf25 100644 --- a/doc/man-pages/pod8/butc.pod +++ b/doc/man-pages/pod8/butc.pod @@ -9,11 +9,13 @@ butc - Initializes the Tape Coordinator process B S<<< [B<-port> >] >>> S<<< [B<-debuglevel> (0 | 1 | 2)] >>> S<<< [B<-cell> >] >>> [B<-noautoquery>] [B<-rxbind>] [B<-localauth>] - [B<-auditlog> > [B<-audit-interface> >]] [B<-help>] + [B<-auditlog> > [B<-audit-interface> >]] + [B<-allow_unauthenticated>] [B<-help>] B S<<< [B<-p> >] >>> S<<< [B<-d> (0 | 1 | 2)] >>> S<<< [B<-c> >] >>> [B<-n>] [B<-r>] [B<-l>] - [B<-auditl> > [-B<-audit-i> >]] [B<-h>] + [B<-auditl> > [-B<-audit-i> >]] + [B<-al>] [B<-h>] =for html @@ -201,6 +203,16 @@ succeeded or failed. Specifies what audit interface to use. Defaults to C. See L for an explanation of each interface. +=item B<-allow_unauthenticated> + +By default the B requires clients performing TC_ RPCs to authenticate +themselves, behavior introduced in the fix for OPENAFS-SA-2018-001. +This option reverts to the historical behavior of only using the rxnull +security class for incoming connections. Use of this option is strongly +disrecommended; it is provided only for backwards compatibility with older +clients in environments where B and B communicate over a secure +network that denies access to untrusted parties. + =item B<-help> Prints the online help for this command. All other valid options are diff --git a/src/butc/butc_prototypes.h b/src/butc/butc_prototypes.h index a1d7712e85..85a379963a 100644 --- a/src/butc/butc_prototypes.h +++ b/src/butc/butc_prototypes.h @@ -35,6 +35,7 @@ extern void *KeepAlive(void *); /* tcmain.c */ extern struct afsconf_dir *butc_confdir; +extern int allow_unauth; #endif diff --git a/src/butc/tcmain.c b/src/butc/tcmain.c index 7f79fa7516..c5399396ee 100644 --- a/src/butc/tcmain.c +++ b/src/butc/tcmain.c @@ -107,6 +107,7 @@ 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]; @@ -843,8 +844,8 @@ tc_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell) 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]; @@ -1070,6 +1071,13 @@ 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; @@ -1114,19 +1122,48 @@ WorkerBee(struct cmd_syndesc *as, void *arock) /* 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); @@ -1232,6 +1269,8 @@ main(int argc, char **argv) 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)) { diff --git a/src/butc/tcprocs.c b/src/butc/tcprocs.c index 7f0e40c86e..c51b1f14d2 100644 --- a/src/butc/tcprocs.c +++ b/src/butc/tcprocs.c @@ -62,12 +62,12 @@ int callPermitted(struct rx_call *call) { /* - * Before this code can be used, the rx connection, on the bucoord side, - * must be changed so that it will set up for token passing instead of - * using a simple rx connection that, below, returns a value of - * RX_SECIDX_NULL from rx_SecurityClassOf. + * If in backwards compat mode, allow anyone; otherwise, only + * superusers are allowed. */ - return 1; + if (allow_unauth) + return 1; + return afsconf_SuperIdentity(butc_confdir, call, NULL); } /* -----------------------------