XRootD
XrdXrootdConfig.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d C o n f i g . c c */
4 /* */
5 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <unistd.h>
31 #include <cctype>
32 #include <fcntl.h>
33 #include <string>
34 #include <cstring>
35 #include <cstdio>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <vector>
40 
41 #ifdef __solaris__
42 #include <sys/isa_defs.h>
43 #endif
44 
45 #include "XrdVersion.hh"
46 
47 #include "XProtocol/XProtocol.hh"
48 
49 #include "XrdSfs/XrdSfsFlags.hh"
51 #include "XrdNet/XrdNetOpts.hh"
52 #include "XrdNet/XrdNetPMarkCfg.hh"
53 #include "XrdNet/XrdNetSocket.hh"
54 #include "XrdOuc/XrdOuca2x.hh"
55 #include "XrdOuc/XrdOucEnv.hh"
56 #include "XrdOuc/XrdOucProg.hh"
57 #include "XrdOuc/XrdOucReqID.hh"
58 #include "XrdOuc/XrdOucString.hh"
59 #include "XrdOuc/XrdOucStream.hh"
60 #include "XrdOuc/XrdOucUtils.hh"
62 #include "XrdSys/XrdSysError.hh"
63 #include "XrdSys/XrdSysHeaders.hh"
64 #include "XrdSys/XrdSysLogger.hh"
65 
66 #include "XrdTls/XrdTlsContext.hh"
67 
82 
83 #include "Xrd/XrdBuffer.hh"
84 #include "Xrd/XrdInet.hh"
85 #include "Xrd/XrdLink.hh"
86 
87 /******************************************************************************/
88 /* P r o t o c o l C o m m a n d L i n e O p t i o n s */
89 /******************************************************************************/
90 
91 /* This is the XRootd server. The syntax is:
92 
93  xrootd [options]
94 
95  options: [<xopt>] [-r] [-t] [-y] [path]
96 
97 Where:
98  xopt are xrd specified options that are screened out.
99 
100  -r This is a redirecting server.
101 
102  -t This server is a redirection target.
103 
104  -y This server is a proxy server.
105 
106  path Export path. Any number of paths may be specified.
107  By default, only '/tmp' is exported.
108 
109 */
110 /******************************************************************************/
111 /* G l o b a l s */
112 /******************************************************************************/
113 
115 
117 
119 
120  const char *XrdXrootdInstance;
121 
123 
126  const char *,
127  const char *, XrdOucEnv *);
128 
131  const char *, const char *,
132  const char *, XrdOucEnv *);
133 
135  (XrdSfsFileSystem *nativeFS,
137  const char *configFn,
138  XrdOucEnv *EnvInfo);
139 
140 /******************************************************************************/
141 /* G l o b a l S t a t i c s */
142 /******************************************************************************/
143 
144 namespace XrdXrootd
145 {
146 extern XrdBuffManager *BPool;
147 extern XrdScheduler *Sched;
148 extern XrdXrootdStats *SI;
149 }
150 
151 /******************************************************************************/
152 /* L o c a l S t a t i c s */
153 /******************************************************************************/
154 
155 namespace
156 {
157 char *digParm = 0;
158 char *FSLib[2] = {0,0};
159 std::vector<std::string> FSLPath; // fslib
160 std::vector<std::string> RDLPath; // redirlib
161 std::vector<std::string> RDLParm; // redirlib
162 char *gpfLib = 0;// Normally zero for default
163 char *gpfParm = 0;
164 char *SecLib;
166 int asyncFlags = 0;
167 
168 static const int asDebug = 0x01;
169 static const int asNoCache = 0x02;
170 }
171 
172 /******************************************************************************/
173 /* C o n f i g u r e */
174 /******************************************************************************/
175 
177 {
178 /*
179  Function: Establish configuration at load time.
180 
181  Input: None.
182 
183  Output: 0 upon success or !0 otherwise.
184 */
185 
187  (XrdSfsFileSystem *nativeFS,
189  const char *configFn,
190  const char *theParms);
191 
192  XrdOucEnv xrootdEnv;
193  XrdXrootdXPath *xp;
194  char *adminp, *rdf, *bP, *tmp, buff[1024];
195  int i, n;
196 
197 // Copy out the special info we want to use at top level
198 //
199  eDest.logger(pi->eDest->logger());
201  SI = new XrdXrootdStats(pi->Stats);
202  XrdXrootd::SI= SI;
203  Sched = pi->Sched; XrdXrootd::Sched = pi->Sched;
204  BPool = pi->BPool; XrdXrootd::BPool = pi->BPool;
205  hailWait = pi->hailWait;
206  readWait = pi->readWait;
207  Port = pi->Port;
208  myInst = pi->myInst;
209  Window = pi->WSize;
210  tlsPort = pi->tlsPort;
211  tlsCtx = pi->tlsCtx;
212  XrdXrootdCF = pi->totalCF;
213 
214 // Record globally accessible values
215 //
217  XrdXrootdPort = pi->Port;
218 
219 // Set the callback object static areas now!
220 //
222 
223 // Pick up exported paths from the command line
224 //
225  for (i = 1; i < pi->argc; i++) xexpdo(pi->argv[i]);
226 
227 // Pre-initialize some i/o values. Note that we now set maximum readv element
228 // transfer size to the buffer size (before it was a reasonable 256K).
229 //
230  n = (pi->theEnv ? pi->theEnv->GetInt("MaxBuffSize") : 0);
231  maxTransz = maxBuffsz = (n ? n : BPool->MaxSize());
232  maxReadv_ior = maxTransz-(int)sizeof(readahead_list);
233 
234 // Export the readv_ior_max and readv_iov_max values
235 //
236  {char buff[256];
237  snprintf(buff, sizeof(buff), "%d,%d", maxReadv_ior, XrdProto::maxRvecsz);
238  XrdOucEnv::Export("XRD_READV_LIMITS", buff);
239  }
240 
241  memset(Route, 0, sizeof(Route));
242 
243 // Now process and configuration parameters
244 //
245  rdf = (parms && *parms ? parms : pi->ConfigFN);
246  if (rdf && Config(rdf)) return 0;
248 
249 // Initialize the packet marking framework if configured. We do that here as
250 // nothing else following this code can fail but we can so be consistent.
251 //
252  bool bad = false;
254  if (PMark)
255  {if (pi->theEnv) pi->theEnv->PutPtr("XrdNetPMark*", PMark);
256  xrootdEnv.PutPtr("XrdNetPMark*", PMark);
257  }
258  else if (bad) return 0;
259 
260 // Check if we are exporting a generic object name
261 //
262  if (XPList.Opts() & XROOTDXP_NOSLASH)
263  {eDest.Say("Config exporting ", XPList.Path(n)); n += 2;}
264  else n = 0;
265 
266 // Check if we are exporting anything
267 //
268  if (!(xp = XPList.Next()) && !n)
269  {XPList.Insert("/tmp"); n = 8;
270  eDest.Say("Config warning: only '/tmp' will be exported.");
271  } else {
272  while(xp) {eDest.Say("Config exporting ", xp->Path(i));
273  n += i+2; xp = xp->Next();
274  }
275  }
276 
277 // Export the exports
278 //
279  bP = tmp = (char *)malloc(n);
280  if (XPList.Opts() & XROOTDXP_NOSLASH)
281  {strcpy(bP, XPList.Path(i)); bP += i, *bP++ = ' ';}
282  xp = XPList.Next();
283  while(xp) {strcpy(bP, xp->Path(i)); bP += i; *bP++ = ' '; xp = xp->Next();}
284  *(bP-1) = '\0';
285  XrdOucEnv::Export("XRDEXPORTS", tmp); free(tmp);
286 
287 // Initialize the security system if this is wanted
288 //
289  if (!ConfigSecurity(xrootdEnv, pi->ConfigFN)) return 0;
290 
291 // Set up the network for self-identification and display it
292 //
293  pi->NetTCP->netIF.Port(Port);
294  pi->NetTCP->netIF.Display("Config ");
295 
296 // Establish our specific environment that will be passed along
297 //
298  xrootdEnv.PutPtr("XrdInet*", (void *)(pi->NetTCP));
299  xrootdEnv.PutPtr("XrdNetIF*", (void *)(&(pi->NetTCP->netIF)));
300  xrootdEnv.PutPtr("XrdScheduler*", Sched);
301 
302 // Copy over the xrd environment which contains plugin argv's and re-export
303 // the monitoring registration object into out own env for simplicity
304 //
305  if (pi->theEnv)
306  {xrootdEnv.PutPtr("xrdEnv*", pi->theEnv);
307  void* theMon = pi->theEnv->GetPtr("XrdMonRoll*");
308  if (theMon) xrootdEnv.PutPtr("XrdMonRoll*", theMon);
309  }
310 
311 // Initialize monitoring (it won't do anything if it wasn't enabled). This
312 // needs to be done before we load any plugins as plugins may need monitoring.
313 //
314  if (!ConfigMon(pi, xrootdEnv)) return 0;
315 
316 // Get the filesystem to be used and its features.
317 //
318  if (!ConfigFS(xrootdEnv, pi->ConfigFN)) return 0;
319  fsFeatures = osFS->Features();
321  if (pi->theEnv) pi->theEnv->PutPtr("XrdSfsFileSystem*", osFS);
322 
323 // Check if the file system includes a custom prepare handler as this will
324 // affect how we handle prepare requests.
325 //
326  if (fsFeatures & XrdSfs::hasPRP2 || xrootdEnv.Get("XRD_PrepHandler"))
327  PrepareAlt = true;
328 
329 // Check if the diglib should be loaded. We only support the builtin one. In
330 // the future we will have to change this code to be like the above.
331 //
332  if (digParm)
333  {TRACE(DEBUG, "Loading dig filesystem builtin");
334  digFS = XrdDigGetFS(osFS, eDest.logger(), pi->ConfigFN, digParm);
335  if (!digFS) eDest.Emsg("Config","Unable to load digFS; "
336  "remote debugging disabled!");
337  }
338 
339 // Check if we are going to be processing checksums locally
340 //
341  if (JobCKT) {
342  XrdOucString csList(1024);
343  XrdOucErrInfo myError("Config");
344  XrdOucTList *tP = JobCKTLST;
345  int csNum = 0;
346  do {
347  if(JobLCL) {
348  // Check natively supported checksum
349  if (osFS->chksum(XrdSfsFileSystem::csSize, tP->text, 0, myError)) {
350  eDest.Emsg("Config", tP->text, "checksum is not natively supported.");
351  return 0;
352  }
353  }
354  tP->ival[1] = myError.getErrInfo();
355  if (csNum) csList += ',';
356  csList.append(csNum);
357  csList.append(':');
358  csList.append(tP->text);
359  csNum++;
360  tP = tP->next;
361  } while (tP);
362  if (csNum) XrdOucEnv::Export("XRD_CSLIST", csList.c_str());
363  }
364 
365 // Configure the redirect plugins. After loading the chain we publish the
366 // final pointer in two places: the protocol environment (so external
367 // plugins can fetch the raw pointer of the plugin via the
368 // "XrdXrootdRedirPI*" key) and XrdXrootdRedirHelper, the in-tree adapter
369 // that fsRedirPI() and the HTTP TPC handler both call to apply plugin-
370 // driven routing (issue #2767).
371 //
372  if (!RDLPath.empty())
373  {for (int i = 0; i < (int)RDLPath.size(); i++)
374  {const char* parm = (RDLParm[i].length() ? RDLParm[i].c_str() : 0);
375  if (!ConfigRedirPI(RDLPath[i].c_str(),xrootdEnv,pi->ConfigFN,parm))
376  return 0;
377  if (pi->theEnv)
378  pi->theEnv->PutPtr("XrdXrootdRedirPI*", RedirPI);
379  }
381  }
382 
383 // Initialiaze for AIO. If we are not in debug mode and aio is enabled then we
384 // turn off async I/O if tghe filesystem requests it or if this is a caching
385 // proxy and we were asked not to use aio in such a cacse.
386 //
387  if (!(asyncFlags & asDebug) && as_aioOK)
388  {if (fsFeatures & XrdSfs::hasNAIO) as_aioOK = false;
389  else if (asyncFlags & asNoCache && fsFeatures & XrdSfs::hasCACH)
390  as_aioOK = false;
391  if (!as_aioOK) eDest.Say("Config asynchronous I/O has been disabled!");
392  }
393 
394 // Compute the maximum stutter allowed during async I/O (one per 64k)
395 //
396  if (as_segsize > 65536) as_okstutter = as_segsize/65536;
397 
398 // Establish final sendfile processing mode. This may be turned off by the
399 // link or by the SFS plugin usually because it's a proxy.
400 //
401  const char *why = 0;
402  if (!as_nosf)
403  {if (fsFeatures & XrdSfs::hasNOSF) why = "file system plugin.";
404  else if (!XrdLink::sfOK) why = "OS kernel.";
405  if (why)
406  {as_nosf = true;
407  eDest.Say("Config sendfile has been disabled by ", why);
408  }
409  }
410 
411 // Create the file lock manager and initialize file handling
412 //
415 
416 // Schedule protocol object cleanup (also advise the transit protocol)
417 //
418  ProtStack.Set(pi->Sched, &XrdXrootdTrace, TRACE_MEM);
419  n = (pi->ConnMax/3 ? pi->ConnMax/3 : 30);
420  ProtStack.Set(n, 60*60);
421  XrdXrootdTransit::Init(pi->Sched, n, 60*60);
422 
423 // Initialize the request ID generation object
424 //
425  PrepID = new XrdOucReqID(pi->urAddr, (int)Port);
426 
427 // Initialize for prepare processing
428 //
430  sprintf(buff, "%%s://%s:%d/&L=%%d&U=%%s", pi->myName, pi->Port);
431  Notify = strdup(buff);
432 
433 // Set the redirect flag if we are a pure redirector
434 //
435  int tlsFlags = myRole & kXR_tlsAny;
437  if ((rdf = getenv("XRDREDIRECT"))
438  && (!strcmp(rdf, "R") || !strcmp(rdf, "M")))
439  {isRedir = *rdf;
441  if (!strcmp(rdf, "M")) myRole |=kXR_attrMeta;
442  }
445  myRole |= tlsFlags;
446 
447 // Turn off client redirects if we are neither a redirector nor a proxy server
448 //
449  if (CL_Redir && !isRedir && !isProxy)
450  {CL_Redir = false;
451  eDest.Say("Config warning: 'redirect client' ignored; "
452  "not a redirector nor a proxy server");
453  }
454 
455 // Check if we are redirecting anything
456 //
457  if ((xp = RPList.Next()))
458  {int k;
459  char buff[2048], puff[1024];
460  do {k = xp->Opts();
461  if (Route[k].Host[0] == Route[k].Host[1]
462  && Route[k].Port[0] == Route[k].Port[1]) *puff = 0;
463  else sprintf(puff, "%%%s:%d", Route[k].Host[1], Route[k].Port[1]);
464  sprintf(buff," to %s:%d%s",Route[k].Host[0],Route[k].Port[0],puff);
465  eDest.Say("Config redirect static ", xp->Path(), buff);
466  xp = xp->Next();
467  } while(xp);
468  }
469 
470  if ((xp = RQList.Next()))
471  {int k;
472  const char *cgi1, *cgi2;
473  char buff[2048], puff[1024], xCgi[RD_Num] = {0};
474  if (isRedir) {cgi1 = "+"; cgi2 = getenv("XRDCMSCLUSTERID");}
475  else {cgi1 = ""; cgi2 = pi->myName;}
476  myCNlen = snprintf(buff, sizeof(buff), "%s%s", cgi1, cgi2);
477  myCName = strdup(buff);
478  do {k = xp->Opts();
479  if (Route[k].Host[0] == Route[k].Host[1]
480  && Route[k].Port[0] == Route[k].Port[1]) *puff = 0;
481  else sprintf(puff, "%%%s:%d", Route[k].Host[1], Route[k].Port[1]);
482  sprintf(buff," to %s:%d%s",Route[k].Host[0],Route[k].Port[0],puff);
483  eDest.Say("Config redirect enoent ", xp->Path(), buff);
484  if (!xCgi[k] && cgi2)
485  {bool isdup = Route[k].Host[0] == Route[k].Host[1]
486  && Route[k].Port[0] == Route[k].Port[1];
487  for (i = 0; i < 2; i++)
488  {n = snprintf(buff,sizeof(buff), "%s?tried=%s%s",
489  Route[k].Host[i], cgi1, cgi2);
490  free(Route[k].Host[i]); Route[k].Host[i] = strdup(buff);
491  Route[k].RDSz[i] = n;
492  if (isdup) {Route[k].Host[1] = Route[k].Host[0];
493  Route[k].RDSz[1] = n; break;
494  }
495  }
496  }
497  xCgi[k] = 1;
498  xp = xp->Next();
499  } while(xp);
500  }
501 
502 // Add all jobs that we can run to the admin object
503 //
504  if (JobCKS) XrdXrootdAdmin::addJob("chksum", JobCKS);
505 
506 // Establish the path to be used for admin functions. We will loose this
507 // storage upon an error but we don't care because we'll just exit.
508 //
509  adminp = XrdOucUtils::genPath(pi->AdmPath, 0, ".xrootd");
510 
511 // Setup the admin path (used in all roles).
512 //
513  if (!(AdminSock = XrdNetSocket::Create(&eDest, adminp, "admin", pi->AdmMode))
514  || !XrdXrootdAdmin::Init(&eDest, AdminSock)) return 0;
515 
516 // Indicate whether or not we support extended attributes
517 //
518  {XrdOucEnv myEnv;
519  XrdOucErrInfo eInfo("", &myEnv);
520  char buff[128];
521  if (osFS->FAttr(0, eInfo, 0) == SFS_OK)
522  {usxMaxNsz = myEnv.GetInt("usxMaxNsz");
523  if (usxMaxNsz < 0) usxMaxNsz = 0;
524  usxMaxVsz = myEnv.GetInt("usxMaxVsz");
525  if (usxMaxVsz < 0) usxMaxVsz = 0;
526  snprintf(buff, sizeof(buff), "%d %d", usxMaxNsz, usxMaxVsz);
527  usxParms = strdup(buff);
528  } else {
529  usxMaxNsz = 0;
530  usxMaxVsz = 0;
531  usxParms = strdup("0 0");
532  }
533  }
534 
535 // Finally, check if we really need to be in bypass mode if it is set
536 //
537  if (OD_Bypass)
538  {const char *penv = getenv("XRDXROOTD_PROXY");
539  if (!penv || *penv != '=')
540  {OD_Bypass = false;
541  eDest.Say("Config warning: 'fsoverload bypass' ignored; "
542  "not a forwarding proxy.");
543  }
544  }
545 
546 // Add any additional features
547 //
552  myRole |= kXR_anongpf;
553 
554 // Finally note whether or not we have TLS enabled
555 //
556  if (tlsCtx) myRole |= kXR_haveTLS;
557 
558 // Return success
559 //
560  free(adminp);
561  return 1;
562 }
563 
564 /******************************************************************************/
565 /* C o n f i g */
566 /******************************************************************************/
567 
568 #define TS_Xeq(x,m) (!strcmp(x,var)) GoNo = m(Config)
569 #define TS_Zeq(x,m) (!strcmp(x,var)) GoNo = m(&eDest, Config)
570 
571 int XrdXrootdProtocol::Config(const char *ConfigFN)
572 {
573  XrdOucEnv myEnv;
574  XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
575  char *var;
576  int cfgFD, GoNo, NoGo = 0, ismine;
577 
578  // Open and attach the config file
579  //
580  if ((cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
581  return eDest.Emsg("Config", errno, "open config file", ConfigFN);
582  Config.Attach(cfgFD);
583 
584  // Indicate what we are about to do in the capture stream
585  //
586  static const char *cvec[] = { "*** xroot protocol config:", 0 };
587  Config.Capture(cvec);
588 
589  // Process items
590  //
591  while((var = Config.GetMyFirstWord()))
592  { if ((ismine = !strncmp("xrootd.", var, 7)) && var[7]) var += 7;
593  else if ((ismine = !strcmp("all.export", var))) var += 4;
594  else if ((ismine = !strcmp("all.seclib", var))) var += 4;
595 
596  if (ismine)
597  { if TS_Xeq("async", xasync);
598  else if TS_Xeq("bindif", xbif);
599  else if TS_Xeq("chksum", xcksum);
600  else if TS_Xeq("diglib", xdig);
601  else if TS_Xeq("export", xexp);
602  else if TS_Xeq("fslib", xfsl);
603  else if TS_Xeq("fsoverload", xfso);
604  else if TS_Xeq("gpflib", xgpf);
605  else if TS_Xeq("log", xlog);
606  else if TS_Xeq("mongstream", xmongs);
607  else if TS_Xeq("monitor", xmon);
608  else if TS_Zeq("pmark", XrdNetPMarkCfg::Parse);
609  else if TS_Xeq("prep", xprep);
610  else if TS_Xeq("redirect", xred);
611  else if TS_Xeq("redirlib", xrdl);
612  else if TS_Xeq("seclib", xsecl);
613  else if TS_Xeq("tls", xtls);
614  else if TS_Xeq("tlsreuse", xtlsr);
615  else if TS_Xeq("trace", xtrace);
616  else if TS_Xeq("limit", xlimit);
617  else {if (!strcmp(var, "pidpath"))
618  {eDest.Say("Config warning: 'xrootd.pidpath' no longer "
619  "supported; use 'all.pidpath'.");
620  } else {
621  eDest.Say("Config warning: ignoring unknown "
622  "directive '", var, "'.");
623  }
624  Config.Echo(false);
625  continue;
626  }
627  if (GoNo) {Config.Echo(); NoGo = 1;}
628  }
629  }
630 
631 // We now have to generate the correct TLS context if one was specified. Our
632 // context must be of the non-verified kind as we don't accept certs.
633 //
634  if (!NoGo && tlsCtx)
635  {tlsCtx = tlsCtx->Clone(false,true);
636  if (!tlsCtx)
637  {eDest.Say("Config failure: unable to setup TLS for protocol!");
638  NoGo = 1;
639  } else {
640  static const char *sessID = "xroots";
641  tlsCtx->SessionCache(tlsCache, sessID, 6);
642  }
643  }
644 
645 // Add our config to our environment and return
646 //
647  return NoGo;
648 }
649 
650 /******************************************************************************/
651 /* P r i v a t e F u n c t i o n s */
652 /******************************************************************************/
653 /******************************************************************************/
654 /* C h e c k T L S */
655 /******************************************************************************/
656 
657 int XrdXrootdProtocol::CheckTLS(const char *tlsProt)
658 {
659 
660 // If login specified, turn off session as it doesn't make sense together.
661 //
665 
666 // Turn off TPC TLS requirement if login or session is required to have TLS
667 // However, that flag must remain to be set in the protocol response.
668 //
671 
672 // If some authnetication protocols need TLS then we must requie that login
673 // uses TLS. For incapable clients, we leave this alone as we will skip
674 // TLS authnetication based protocols should the login phase not have TLS.
675 //
676  if (tlsProt && !(tlsCap & Req_TLSLogin))
677  {eDest.Say("Config Authentication protocol(s)", tlsProt,
678  " require TLS; login now requires TLS.");
679  myRole |= kXR_tlsLogin;
680  tlsCap |= Req_TLSLogin;
681  }
682 
683 // If there are any TLS requirements then TLS must have been configured.
684 //
685  if (myRole & kXR_tlsAny && !tlsCtx)
686  {eDest.Say("Config failure: unable to honor TLS requirement; "
687  "TLS not configured!");
688  return 0;
689  }
690 
691 // All done
692 //
693  return 1;
694 }
695 
696 /******************************************************************************/
697 /* C o n f i g F S */
698 /******************************************************************************/
699 
700 bool XrdXrootdProtocol::ConfigFS(XrdOucEnv &xEnv, const char *cfn)
701 {
702  const char *fsLoc;
703  int n;
704 
705 // The filesystem may need access to the list of valid checksums. We construct
706 // here and place it in the local env.
707 //
708  if (JobCKT) {
709  XrdOucString csList(1024);
710  XrdOucTList *tP = JobCKTLST;
711  do {
712  if (csList.length()) csList += ' ';
713  csList.append(tP->text);
714  tP = tP->next;
715  } while (tP);
716  if (csList.length()) xEnv.Put("csList", csList.c_str());
717  }
718 
719 // Get the filesystem to be used
720 //
721  if (FSLib[0])
722  {TRACE(DEBUG, "Loading base filesystem library " <<FSLib[0]);
723  osFS = XrdXrootdloadFileSystem(&eDest, 0, FSLib[0], cfn, &xEnv);
724  fsLoc = FSLib[0];
725  } else {
726  osFS = XrdSfsGetDefaultFileSystem(0, eDest.logger(), cfn, &xEnv);
727  fsLoc = "default";
728  }
729 
730 // Make sure we have loaded something
731 //
732  if (!osFS)
733  {eDest.Emsg("Config", "Unable to load base file system using", fsLoc);
734  return false;
735  }
736  if (FSLib[0]) osFS->EnvInfo(&xEnv);
737 
738 // If there is an old style wrapper, load it now.
739 //
740  if (FSLib[1] && !ConfigFS(FSLib[1], xEnv, cfn)) return false;
741 
742 // Run through any other pushdowns
743 //
744  if ((n = FSLPath.size()))
745  for (int i = 0; i < n; i++)
746  {if (!ConfigFS(FSLPath[i].c_str(), xEnv, cfn)) return false;}
747 
748 // Inform the statistics object which filesystem to use
749 //
750  SI->setFS(osFS);
751 
752 // All done here
753 //
754  return true;
755 }
756 
757 /******************************************************************************/
758 
759 bool XrdXrootdProtocol::ConfigFS(const char *path, XrdOucEnv &xEnv,
760  const char *cfn)
761 {
762 
763 // Try to load this wrapper library
764 //
765  TRACE(DEBUG, "Loading wrapper filesystem library " <<path);
766  osFS = XrdXrootdloadFileSystem(&eDest, osFS, path, cfn, &xEnv);
767  if (!osFS)
768  {eDest.Emsg("Config", "Unable to load file system wrapper from", path);
769  return false;
770  }
771  osFS->EnvInfo(&xEnv);
772  return true;
773 }
774 
775 /******************************************************************************/
776 /* C o n f i g R e d i r P I */
777 /******************************************************************************/
778 
779 bool XrdXrootdProtocol::ConfigRedirPI(const char *path, XrdOucEnv &xEnv,
780  const char *cfn, const char *parms)
781 {
782 
783 // Try to load this wrapper library
784 //
785  TRACE(DEBUG, "Loading redirect plugin library " <<path);
786  RedirPI = XrdXrootdloadRedirLib(&eDest, RedirPI, path, parms, cfn, &xEnv);
787  return RedirPI != 0;
788 }
789 
790 /******************************************************************************/
791 /* C o n f i g S e c u r i t y */
792 /******************************************************************************/
793 
794 int XrdXrootdProtocol::ConfigSecurity(XrdOucEnv &xEnv, const char *cfn)
795 {
796  XrdSecGetProt_t secGetProt = 0;
797  char idBuff[256];
798  int n;
799 
800 // Obtain our uid and username
801 //
802  myUID = geteuid();
803  if ((n = XrdOucUtils::UidName(myUID, idBuff, sizeof(idBuff))))
804  {myUName = strdup(idBuff);
805  myUNLen = n;
806  }
807 
808 // Obtain our gid and groupname
809 //
810  myGID = getegid();
811  if ((n = XrdOucUtils::GidName(myGID, idBuff, sizeof(idBuff))))
812  {myGName = strdup(idBuff);
813  myGNLen = n;
814  }
815 
816 // TLS support is independent of security per se. Record context, if any.
817 //
818  if (tlsCtx) xEnv.PutPtr("XrdTLSContext*", (void *)tlsCtx);
819 
820 // Check if we need to load anything
821 //
822  if (!SecLib)
823  {eDest.Say("Config warning: 'xrootd.seclib' not specified;"
824  " strong authentication disabled!");
825  xEnv.PutPtr("XrdSecGetProtocol*", (void *)0);
826  xEnv.PutPtr("XrdSecProtector*" , (void *)0);
827  return 1;
828  }
829 
830 // Blad some debugging info
831 //
832  TRACE(DEBUG, "Loading security library " <<SecLib);
833 
834 // Load the security server
835 //
836  if (!(CIA = XrdSecLoadSecService(&eDest, cfn,
837  (strcmp(SecLib,"default") ? SecLib : 0),
838  &secGetProt, &DHS)))
839  {eDest.Emsg("Config", "Unable to load security system.");
840  return 0;
841  }
842 
843 // Set environmental pointers
844 //
845  xEnv.PutPtr("XrdSecGetProtocol*", (void *)secGetProt);
846  xEnv.PutPtr("XrdSecProtector*" , (void *)DHS);
847 
848 // If any protocol needs TLS then all logins must use TLS, ufortunately.
849 //
850  const char *tlsProt = CIA->protTLS();
851  if (tlsProt) return CheckTLS(tlsProt);
852  return 1;
853 }
854 
855 /******************************************************************************/
856 /* x a s y n c */
857 /******************************************************************************/
858 
859 /* Function: xasync
860 
861  Purpose: To parse directive: async [limit <aiopl>] [maxsegs <msegs>]
862  [maxtot <mtot>] [segsize <segsize>]
863  [minsize <iosz>] [maxstalls <cnt>]
864  [timeout <tos>]
865  [Debug] [force] [syncw] [off]
866  [nocache] [nosf]
867 
868  <aiopl> maximum number of async req per link. Default 8.
869  <msegs> maximum number of async ops per request. Default 8.
870  <mtot> maximum number of async ops per server. Default is 4096.
871  of maximum connection times aiopl divided by two.
872  <segsz> The aio segment size. This is the maximum size that data
873  will be read or written. The defaults to 64K but is
874  adjusted for each request to minimize latency.
875  <iosz> the minimum number of bytes that must be read or written
876  to allow async processing to occur (default is maxbsz/2
877  typically 1M).
878  <tos> second timeout for async I/O.
879  <cnt> Maximum number of client stalls before synchronous i/o is
880  used. Async mode is tried after <cnt> requests.
881  Debug Turns on async I/O for everything. This an internal
882  undocumented option used for testing purposes.
883  force Uses async i/o for all requests, even when not explicitly
884  requested (this is compatible with synchronous clients).
885  syncw Use synchronous i/o for write requests.
886  off Disables async i/o
887  nocache Disables async I/O is this is a caching proxy.
888  nosf Disables use of sendfile to send data to the client.
889 
890  Output: 0 upon success or 1 upon failure.
891 */
892 
893 int XrdXrootdProtocol::xasync(XrdOucStream &Config)
894 {
895  char *val;
896  int i, ppp;
897  int V_force=-1, V_syncw = -1, V_off = -1, V_mstall = -1, V_nosf = -1;
898  int V_limit=-1, V_msegs=-1, V_mtot=-1, V_minsz=-1, V_segsz=-1;
899  int V_minsf=-1, V_debug=-1, V_noca=-1, V_tmo=-1;
900  long long llp;
901  struct asyncopts {const char *opname; int minv; int *oploc;
902  const char *opmsg;} asopts[] =
903  {
904  {"Debug", -1, &V_debug, ""},
905  {"force", -1, &V_force, ""},
906  {"off", -1, &V_off, ""},
907  {"nocache", -1, &V_noca, ""},
908  {"nosf", -1, &V_nosf, ""},
909  {"syncw", -1, &V_syncw, ""},
910  {"limit", 0, &V_limit, "async limit"},
911  {"segsize", 4096, &V_segsz, "async segsize"},
912  {"timeout", 0, &V_tmo, "async timeout"},
913  {"maxsegs", 0, &V_msegs, "async maxsegs"},
914  {"maxstalls", 0, &V_mstall,"async maxstalls"},
915  {"maxtot", 0, &V_mtot, "async maxtot"},
916  {"minsfsz", 1, &V_minsf, "async minsfsz"},
917  {"minsize", 4096, &V_minsz, "async minsize"}};
918  int numopts = sizeof(asopts)/sizeof(struct asyncopts);
919 
920  if (!(val = Config.GetWord()))
921  {eDest.Emsg("Config", "async option not specified"); return 1;}
922 
923  while (val)
924  {for (i = 0; i < numopts; i++)
925  if (!strcmp(val, asopts[i].opname))
926  {if (asopts[i].minv >= 0 && !(val = Config.GetWord()))
927  {eDest.Emsg("Config","async",(char *)asopts[i].opname,
928  "value not specified");
929  return 1;
930  }
931  if (asopts[i].minv > 0)
932  if (XrdOuca2x::a2sz(eDest,asopts[i].opmsg, val, &llp,
933  (long long)asopts[i].minv)) return 1;
934  else *asopts[i].oploc = (int)llp;
935  else if (asopts[i].minv == 0)
936  if (XrdOuca2x::a2i(eDest,asopts[i].opmsg,val,&ppp,1))
937  return 1;
938  else *asopts[i].oploc = ppp;
939  else *asopts[i].oploc = 1;
940  break;
941  }
942  if (i >= numopts)
943  eDest.Emsg("Config", "Warning, invalid async option", val);
944  val = Config.GetWord();
945  }
946 
947 // Make sure max values are consistent
948 //
949  if (V_limit > 0 && V_mtot > 0 && V_limit > V_mtot)
950  {eDest.Emsg("Config", "async limit may not be greater than maxtot");
951  return 1;
952  }
953 
954 // Calculate the actual segment size
955 //
956  if (V_segsz > 0)
957  {i = BPool->Recalc(V_segsz);
958  if (!i) {eDest.Emsg("Config", "async segsize is too large"); return 1;}
959  if (i != V_segsz)
960  {char buff[64];
961  sprintf(buff, "%d readjusted to %d", V_segsz, i);
962  eDest.Emsg("Config", "async segsize", buff);
963  V_segsz = i;
964  }
965  }
966 
967 // Calculate actual timeout
968 //
969  if (V_tmo >= 0)
970  {i = V_tmo;
971  if (V_tmo < 1) i = 1;
972  else if (V_tmo > 360) i = 360;
973  if (i != V_tmo)
974  {char buff[64];
975  sprintf(buff, "%d readjusted to %d", V_tmo, i);
976  eDest.Emsg("Config", "async timeout", buff);
977  V_tmo = i;
978  }
979  }
980 
981 // Establish async options
982 //
983  if (V_limit > 0) as_maxperlnk = V_limit;
984  if (V_msegs > 0) as_maxperreq = V_msegs;
985  if (V_mtot > 0) as_maxpersrv = V_mtot;
986  if (V_minsz > 0) as_miniosz = V_minsz;
987  if (V_segsz > 0){as_segsize = V_segsz; as_seghalf = V_segsz/2;}
988  if (V_tmo >= 0) as_timeout = V_tmo;
989  if (V_mstall> 0) as_maxstalls = V_mstall;
990  if (V_debug > 0) asyncFlags |= asDebug;
991  if (V_force > 0) as_force = true;
992  if (V_off > 0) as_aioOK = false;
993  if (V_syncw > 0) as_syncw = true;
994  if (V_noca > 0) asyncFlags |= asNoCache;
995  if (V_nosf > 0) as_nosf = true;
996  if (V_minsf > 0) as_minsfsz = V_minsf;
997 
998  return 0;
999 }
1000 
1001 /******************************************************************************/
1002 /* x b i f */
1003 /******************************************************************************/
1004 
1005 /* Function: xbif
1006 
1007  Purpose: To parse the directive: bindif <trg>
1008 
1009  <trg>: <host>:<port>[%<prvhost>:<port>]] [<trg>]
1010 */
1011 
1012 namespace XrdXrootd
1013 {
1014 char *bifResp[2] = {0,0};
1015 int bifRLen[2] = {0,0};
1016 }
1017 
1018 int XrdXrootdProtocol::xbif(XrdOucStream &Config)
1019 {
1020  static const int brSize = sizeof(XrdProto::bifReqs);
1021  using XrdXrootd::bifResp;
1022  using XrdXrootd::bifRLen;
1023 
1024  XrdOucString bSpec[2];
1025  char *bHost[2], *val, buff[512];
1026  int bPort[2], thePort;
1027 
1028 // Cleanup any previous bif specification
1029 //
1030  if (bifResp[1])
1031  {if (bifResp[1] != bifResp[0]) free(bifResp[1]);
1032  bifResp[1] = 0; bifRLen[1] = 0;
1033  }
1034  if (bifResp[0])
1035  {free(bifResp[0]);
1036  bifResp[0] = 0; bifRLen[0] = 0;
1037  }
1038 
1039 // Process all of the options
1040 //
1041  while((val = Config.GetWord()) && *val)
1042  {if (!xred_php(val, bHost, bPort, "bindif", true)) return 1;
1043  for (int i = 0; i < 2 && bHost[i] != 0; i++)
1044  {thePort = (bPort[i] ? bPort[i] : XrdXrootdPort);
1045  snprintf(buff, sizeof(buff), "%s%s:%d",
1046  (bSpec[i].length() ? "," : ""), bHost[i], thePort);
1047  bSpec[i] += buff;
1048  }
1049  }
1050 
1051 // Generate the "b" record for each type of interface
1052 //
1053  for (int i = 0; i < 2 && bSpec[i].length(); i++)
1054  {int n = brSize + bSpec[i].length() + 1;
1055  n = (n + 7) & ~7;
1056  XrdProto::bifReqs *bifRec = (XrdProto::bifReqs *)malloc(n);
1057  memset(bifRec, 0, n);
1058  bifRec->theTag = 'B';
1059  bifRec->bifILen = htons(static_cast<kXR_unt16>(n-brSize));
1060  strcpy(((char *)bifRec)+brSize, bSpec[i].c_str());
1061  bifResp[i] = (char *)bifRec;
1062  bifRLen[i] = n;
1063  }
1064 
1065 // Now complete the definition
1066 //
1067  if (bifResp[0] && bifResp[1] == 0)
1068  {bifResp[1] = bifResp[0];
1069  bifRLen[1] = bifRLen[0];
1070  }
1071 
1072 // All done
1073 //
1074  return 0;
1075 }
1076 
1077 /******************************************************************************/
1078 /* x c k s u m */
1079 /******************************************************************************/
1080 
1081 /* Function: xcksum
1082 
1083  Purpose: To parse the directive: chksum [chkcgi] [max <n>] <type> [<path>]
1084 
1085  max maximum number of simultaneous jobs
1086  chkcgi Always check for checksum type in cgo info.
1087  <type> algorithm of checksum (e.g., md5). If more than one
1088  checksum is supported then they should be listed with
1089  each separated by a space.
1090  <path> the path of the program performing the checksum
1091  If no path is given, the checksum is local.
1092 
1093  Output: 0 upon success or !0 upon failure.
1094 */
1095 
1096 int XrdXrootdProtocol::xcksum(XrdOucStream &Config)
1097 {
1098  static XrdOucProg *theProg = 0;
1099  int (*Proc)(XrdOucStream *, char **, int) = 0;
1100  XrdOucTList *tP, *algFirst = 0, *algLast = 0;
1101  char *palg, prog[2048];
1102  int jmax = 4, anum[2] = {0,0};
1103 
1104 // Get the algorithm name and the program implementing it
1105 //
1106  JobCKCGI = 0;
1107  while ((palg = Config.GetWord()) && *palg != '/')
1108  {if (!strcmp(palg,"chkcgi")) {JobCKCGI = 1; continue;}
1109  if (strcmp(palg, "max"))
1110  {XrdOucUtils::toLower(palg);
1111  XrdOucTList *xalg = new XrdOucTList(palg, anum); anum[0]++;
1112  if (algLast) algLast->next = xalg;
1113  else algFirst = xalg;
1114  algLast = xalg;
1115  continue;
1116  }
1117  if (!(palg = Config.GetWord()))
1118  {eDest.Emsg("Config", "chksum max not specified"); return 1;}
1119  if (XrdOuca2x::a2i(eDest, "chksum max", palg, &jmax, 0)) return 1;
1120  }
1121 
1122 // Verify we have an algoritm
1123 //
1124  if (!algFirst)
1125  {eDest.Emsg("Config", "chksum algorithm not specified"); return 1;}
1126  if (JobCKT) free(JobCKT);
1127  JobCKT = strdup(algFirst->text);
1128 
1129 // Handle alternate checksums
1130 //
1131  while((tP = JobCKTLST)) {JobCKTLST = tP->next; delete tP;}
1132  JobCKTLST = algFirst;
1133  if (algFirst->next) JobCKCGI = 2;
1134 
1135 // Handle program if we have one
1136 //
1137  if (palg)
1138  {int n = strlen(palg);
1139  if (n+2 >= (int)sizeof(prog))
1140  {eDest.Emsg("Config", "cksum program too long"); return 1;}
1141  strcpy(prog, palg); palg = prog+n; *palg++ = ' '; n = sizeof(prog)-n-1;
1142  if (!Config.GetRest(palg, n))
1143  {eDest.Emsg("Config", "cksum parameters too long"); return 1;}
1144  } else *prog = 0;
1145 
1146 // Check if we have a program. If not, then this will be a local checksum and
1147 // the algorithm will be verified after we load the filesystem.
1148 //
1149  if (*prog) JobLCL = 0;
1150  else { JobLCL = 1; Proc = &CheckSum; strcpy(prog, "chksum");}
1151 
1152 // Set up the program and job
1153 //
1154  if (!theProg) theProg = new XrdOucProg(0);
1155  if (theProg->Setup(prog, &eDest, Proc)) return 1;
1156  if (JobCKS) delete JobCKS;
1157  if (jmax) JobCKS = new XrdXrootdJob(Sched, theProg, "chksum", jmax);
1158  else JobCKS = 0;
1159  return 0;
1160 }
1161 
1162 /******************************************************************************/
1163 /* x d i g */
1164 /******************************************************************************/
1165 
1166 /* Function: xdig
1167 
1168  Purpose: To parse the directive: diglib * <parms>
1169 
1170  * use builtin digfs library (only one supported now).
1171  parms parameters for digfs.
1172 
1173  Output: 0 upon success or !0 upon failure.
1174 */
1175 
1176 int XrdXrootdProtocol::xdig(XrdOucStream &Config)
1177 {
1178  char parms[4096], *val;
1179 
1180 // Get the path
1181 //
1182  if (!(val = Config.GetWord()))
1183  {eDest.Emsg("Config", "diglib not specified"); return 1;}
1184 
1185 // Make sure it refers to an internal one
1186 //
1187  if (strcmp(val, "*"))
1188  {eDest.Emsg("Config", "builtin diglib not specified"); return 1;}
1189 
1190 // Grab the parameters
1191 //
1192  if (!Config.GetRest(parms, sizeof(parms)))
1193  {eDest.Emsg("Config", "diglib parameters too long"); return 1;}
1194  if (digParm) free(digParm);
1195  digParm = strdup(parms);
1196 
1197 // All done
1198 //
1199  return 0;
1200 }
1201 
1202 /******************************************************************************/
1203 /* x e x p */
1204 /******************************************************************************/
1205 
1206 /* Function: xexp
1207 
1208  Purpose: To parse the directive: export <path> [lock|nolock] [mwfiles]
1209 
1210  <path> the path to be exported.
1211 
1212  Output: 0 upon success or !0 upon failure.
1213 */
1214 
1215 int XrdXrootdProtocol::xexp(XrdOucStream &Config)
1216 {
1217  char *val, pbuff[1024];
1218  int popt = 0;
1219 
1220 // Get the path
1221 //
1222  val = Config.GetWord();
1223  if (!val || !val[0])
1224  {eDest.Emsg("Config", "export path not specified"); return 1;}
1225  strlcpy(pbuff, val, sizeof(pbuff));
1226 
1227 // Get export lock option
1228 //
1229  while((val = Config.GetWord()))
1230  { if (!strcmp( "nolock", val)) popt |= XROOTDXP_NOLK;
1231  else if (!strcmp( "lock", val)) popt &= ~XROOTDXP_NOLK;
1232  else if (!strcmp("mwfiles", val)) popt |= XROOTDXP_NOMWCHK;
1233  else {Config.RetToken(); break;}
1234  }
1235 
1236 // Add path to configuration
1237 //
1238  return xexpdo(pbuff, popt);
1239 }
1240 
1241 /******************************************************************************/
1242 
1243 int XrdXrootdProtocol::xexpdo(char *path, int popt)
1244 {
1245  char *opaque;
1246  int xopt;
1247 
1248 // Check if we are exporting a generic name
1249 //
1250  if (*path == '*')
1251  {popt |= XROOTDXP_NOSLASH | XROOTDXP_NOCGI;
1252  if (*(path+1))
1253  {if (*(path+1) == '?') popt &= ~XROOTDXP_NOCGI;
1254  else {eDest.Emsg("Config","invalid export path -",path);return 1;}
1255  }
1256  XPList.Set(popt, path);
1257  return 0;
1258  }
1259 
1260 // Make sure path start with a slash
1261 //
1262  if (rpCheck(path, &opaque))
1263  {eDest.Emsg("Config", "non-absolute export path -", path); return 1;}
1264 
1265 // Record the path
1266 //
1267  if (!(xopt = Squash(path)) || xopt != (popt|XROOTDXP_OK))
1268  XPList.Insert(path, popt);
1269  return 0;
1270 }
1271 
1272 /******************************************************************************/
1273 /* x f s l */
1274 /******************************************************************************/
1275 
1276 /* Function: xfsl
1277 
1278  Purpose: To parse the directive: fslib [throttle | [-2] <fspath2>]
1279  {default | [-2] <fspath1>}
1280  | ++ <fspath2>
1281 
1282  -2 Uses version2 of the plugin initializer.
1283  This is ignored now because it's always done.
1284  ++ Pushes a wrapper onto the library stack.
1285  throttle load libXrdThrottle.so as the head interface.
1286  <fspath2> load the named library as the head interface.
1287  default load libXrdOfs.so ro libXrdPss.so as the tail
1288  interface. This is the default.
1289  <fspath1> load the named library as the tail interface.
1290 
1291  Output: 0 upon success or !0 upon failure.
1292 */
1293 
1294 int XrdXrootdProtocol::xfsl(XrdOucStream &Config)
1295 {
1296  char *val;
1297 
1298 // Get the path
1299 //
1300  if (!(val = Config.GetWord()))
1301  {eDest.Emsg("Config", "fslib not specified"); return 1;}
1302 
1303 // First check for a psuhdown
1304 //
1305  if (!strcmp("++", val))
1306  {if (!(val = Config.GetWord()))
1307  {eDest.Emsg("Config", "fslib wrapper not specified"); return 1;}
1308  if (strcmp("throttle", val)) FSLPath.push_back((std::string)val);
1309  else FSLPath.push_back("libXrdThrottle.so");
1310  return 0;
1311  }
1312 
1313 // Clear storage pointers
1314 //
1315  if (FSLib[0]) {free(FSLib[0]); FSLib[0] = 0;}
1316  if (FSLib[1]) {free(FSLib[1]); FSLib[1] = 0;}
1317 
1318 // Check if this is "thottle"
1319 //
1320  if (!strcmp("throttle", val))
1321  {FSLib[1] = strdup("libXrdThrottle.so");
1322  if (!(val = Config.GetWord()))
1323  {eDest.Emsg("Config","fslib throttle target library not specified");
1324  return 1;
1325  }
1326  return xfsL(Config, val, 0);
1327  }
1328 
1329 // Check for default or default library, the common case
1330 //
1331  if (xfsL(Config, val, 1)) return 1;
1332  if (!FSLib[1]) return 0;
1333 
1334 // If we dont have another token, then demote the previous library
1335 //
1336  if (!(val = Config.GetWord()))
1337  {FSLib[0] = FSLib[1]; FSLib[1] = 0;
1338  return 0;
1339  }
1340 
1341 // Check for default or default library, the common case
1342 //
1343  return xfsL(Config, val, 0);
1344 }
1345 
1346 /******************************************************************************/
1347 
1348 int XrdXrootdProtocol::xfsL(XrdOucStream &Config, char *val, int lix)
1349 {
1350  char *Slash;
1351 
1352 // Check if this is a version token
1353 //
1354  if (!strcmp(val, "-2"))
1355  {if (!(val = Config.GetWord()))
1356  {eDest.Emsg("Config", "fslib not specified"); return 1;}
1357  }
1358 
1359 // We will play fast and furious with the syntax as "default" should not be
1360 // prefixed with a version number but will let that pass.
1361 //
1362  if (!strcmp("default", val)) return 0;
1363 
1364 // If this is the "standard" name tell the user that we are ignoring this lib.
1365 // Otherwise, record the path and return.
1366 //
1367  if (!(Slash = rindex(val, '/'))) Slash = val;
1368  else Slash++;
1369  if (!strcmp(Slash, "libXrdOfs.so"))
1370  eDest.Say("Config warning: 'fslib libXrdOfs.so' is actually built-in.");
1371  else FSLib[lix] = strdup(val);
1372  return 0;
1373 }
1374 
1375 /******************************************************************************/
1376 /* x f s o */
1377 /******************************************************************************/
1378 
1379 /* Function: xfso
1380 
1381  Purpose: To parse the directive: fsoverload [options]
1382 
1383  options: [[no]bypass] [redirect <host>:<port>[%<prvhost>:<port>]]
1384  [stall <sec>]
1385 
1386  bypass If path is a forwarding path, redirect client to the
1387  location specified in the path to bypass this server.
1388  The default is nobypass.
1389  redirect Redirect the request to the specified destination.
1390  stall Stall the client <sec> seconds. The default is 33.
1391 */
1392 
1393 int XrdXrootdProtocol::xfso(XrdOucStream &Config)
1394 {
1395  static const int rHLen = 264;
1396  char rHost[2][rHLen], *hP[2] = {0,0}, *val;
1397  int rPort[2], bypass = -1, stall = -1;
1398 
1399 // Process all of the options
1400 //
1401  while((val = Config.GetWord()) && *val)
1402  { if (!strcmp(val, "bypass")) bypass = 1;
1403  else if (!strcmp(val, "nobypass")) bypass = 0;
1404  else if (!strcmp(val, "redirect"))
1405  {val = Config.GetWord();
1406  if (!xred_php(val, hP, rPort, "redirect")) return 1;
1407  for (int i = 0; i < 2; i++)
1408  {if (!hP[i]) rHost[i][0] = 0;
1409  else {strlcpy(rHost[i], hP[i], rHLen);
1410  hP[i] = rHost[i];
1411  }
1412  }
1413  }
1414  else if (!strcmp(val, "stall"))
1415  {if (!(val = Config.GetWord()) || !(*val))
1416  {eDest.Emsg("Config", "stall value not specified");
1417  return 1;
1418  }
1419  if (XrdOuca2x::a2tm(eDest,"stall",val,&stall,0,32767))
1420  return 1;
1421  }
1422  else {eDest.Emsg("config","invalid fsoverload option",val); return 1;}
1423  }
1424 
1425 // Set all specified values
1426 //
1427  if (bypass >= 0) OD_Bypass = (bypass ? true : false);
1428  if (stall >= 0) OD_Stall = stall;
1429  if (hP[0])
1430  {if (Route[RD_ovld].Host[0]) free(Route[RD_ovld].Host[0]);
1431  if (Route[RD_ovld].Host[1]) free(Route[RD_ovld].Host[1]);
1432  Route[RD_ovld].Host[0] = strdup(hP[0]);
1433  Route[RD_ovld].Port[0] = rPort[0];
1434  Route[RD_ovld].RDSz[0] = strlen(hP[0]);
1435  if (hP[1])
1436  {Route[RD_ovld].Host[1] = strdup(hP[1]);
1437  Route[RD_ovld].Port[1] = rPort[1];
1438  Route[RD_ovld].RDSz[1] = strlen(hP[1]);
1439  } else {
1440  Route[RD_ovld].Host[1] = Route[RD_ovld].Host[0];
1441  Route[RD_ovld].Port[1] = Route[RD_ovld].Port[0];
1442  Route[RD_ovld].RDSz[1] = Route[RD_ovld].RDSz[0];
1443  }
1444  OD_Redir = true;
1445  } else OD_Redir = false;
1446 
1447  return 0;
1448 }
1449 
1450 /******************************************************************************/
1451 /* x g p f */
1452 /******************************************************************************/
1453 
1454 /* Function: xgpf
1455 
1456  Purpose: To parse the directive: gpflib <path> <parms>
1457 
1458  <path> library path to use or default to use the builtin one.
1459  parms optional parameters.
1460 
1461  Output: 0 upon success or !0 upon failure.
1462 */
1463 
1464 int XrdXrootdProtocol::xgpf(XrdOucStream &Config)
1465 {
1466  char parms[4096], *val;
1467 
1468 // Remove any previous parameters
1469 //
1470  if (gpfLib) {free(gpfLib); gpfLib = 0;}
1471  if (gpfParm) {free(gpfParm); gpfParm = 0;}
1472 
1473 // Get the path
1474 //
1475  if (!(val = Config.GetWord()))
1476  {eDest.Emsg("Config", "gpflib not specified"); return 1;}
1477 
1478 // If this refers to out default, then keep the library pointer nil
1479 //
1480  if (strcmp(val, "default")) gpfLib = strdup(val);
1481 
1482 // Grab the parameters
1483 //
1484  if (!Config.GetRest(parms, sizeof(parms)))
1485  {eDest.Emsg("Config", "gpflib parameters too long"); return 1;}
1486  gpfParm = strdup(parms);
1487 
1488 // All done
1489 //
1490  return 0;
1491 }
1492 
1493 /******************************************************************************/
1494 /* x l o g */
1495 /******************************************************************************/
1496 
1497 /* Function: xlog
1498 
1499  Purpose: To parse the directive: log <events>
1500 
1501  <events> the blank separated list of events to log.
1502 
1503  Output: 0 upon success or 1 upon failure.
1504 */
1505 
1506 int XrdXrootdProtocol::xlog(XrdOucStream &Config)
1507 {
1508  char *val;
1509  static struct logopts {const char *opname; int opval;} lgopts[] =
1510  {
1511  {"all", -1},
1512  {"disc", SYS_LOG_02},
1513  {"login", SYS_LOG_01}
1514  };
1515  int i, neg, lgval = -1, numopts = sizeof(lgopts)/sizeof(struct logopts);
1516 
1517  if (!(val = Config.GetWord()))
1518  {eDest.Emsg("config", "log option not specified"); return 1;}
1519  while (val)
1520  {if ((neg = (val[0] == '-' && val[1]))) val++;
1521  for (i = 0; i < numopts; i++)
1522  {if (!strcmp(val, lgopts[i].opname))
1523  {if (neg) lgval &= ~lgopts[i].opval;
1524  else lgval |= lgopts[i].opval;
1525  break;
1526  }
1527  }
1528  if (i >= numopts) eDest.Emsg("config","invalid log option",val);
1529  val = Config.GetWord();
1530  }
1531  eDest.setMsgMask(lgval);
1532  return 0;
1533 }
1534 
1535 /******************************************************************************/
1536 /* x p r e p */
1537 /******************************************************************************/
1538 
1539 /* Function: xprep
1540 
1541  Purpose: To parse the directive: prep [keep <sec>] [scrub <sec>]
1542  [logdir <path>]
1543  keep <sec> time (seconds, M, H) to keep logdir entries.
1544  scrub <sec> time (seconds, M, H) between logdir scrubs.
1545  logdir <path> the absolute path to the prepare log directory.
1546 
1547  Output: 0 upon success or !0 upon failure. Ignored by master.
1548 */
1549 int XrdXrootdProtocol::xprep(XrdOucStream &Config)
1550 { int rc, keep = 0, scrub=0;
1551  char *ldir=0,*val,buff[1024];
1552 
1553  if (!(val = Config.GetWord()))
1554  {eDest.Emsg("Config", "prep options not specified"); return 1;}
1555 
1556  do { if (!strcmp("keep", val))
1557  {if (!(val = Config.GetWord()))
1558  {eDest.Emsg("Config", "prep keep value not specified");
1559  return 1;
1560  }
1561  if (XrdOuca2x::a2tm(eDest,"prep keep int",val,&keep,1)) return 1;
1562  }
1563  else if (!strcmp("scrub", val))
1564  {if (!(val = Config.GetWord()))
1565  {eDest.Emsg("Config", "prep scrub value not specified");
1566  return 1;
1567  }
1568  if (XrdOuca2x::a2tm(eDest,"prep scrub",val,&scrub,0)) return 1;
1569  }
1570  else if (!strcmp("logdir", val))
1571  {if (!(ldir = Config.GetWord()))
1572  {eDest.Emsg("Config", "prep logdir value not specified");
1573  return 1;
1574  }
1575  }
1576  else eDest.Emsg("Config", "Warning, invalid prep option", val);
1577  } while((val = Config.GetWord()));
1578 
1579 // Set the values
1580 //
1581  if (scrub || keep) XrdXrootdPrepare::setParms(scrub, keep);
1582  if (ldir)
1583  if ((rc = XrdOucUtils::genPath(buff, sizeof(buff), ldir, myInst)) < 0
1584  || (rc = XrdOucUtils::makePath(buff, XrdOucUtils::pathMode)) < 0
1585  || (rc = XrdXrootdPrepare::setParms(buff)) < 0)
1586  {eDest.Emsg("Config", rc, "process logdir", ldir);
1587  return 1;
1588  }
1589  return 0;
1590 }
1591 
1592 /******************************************************************************/
1593 /* x r d l */
1594 /******************************************************************************/
1595 
1596 /* Function: xrdl
1597 
1598  Purpose: To parse the directive: redirlib [++] [<opts>] <libpath> [<parm>]
1599 
1600  ++ Pushes a wrapper onto the library stack.
1601  <opts> Options:
1602  +iphold <time>
1603  <libpath> load the named library as the head interface.
1604  <parms> optional parameters
1605 
1606  Output: 0 upon success or !0 upon failure.
1607 */
1608 
1609 int XrdXrootdProtocol::xrdl(XrdOucStream &Config)
1610 {
1611  char *val;
1612  char pbuff[4096];
1613 
1614 // Get the path
1615 //
1616  if (!(val = Config.GetWord()))
1617  {eDest.Emsg("Config", "redirlib path not specified"); return 1;}
1618 
1619 // First check for a psuhdown
1620 //
1621  if (!strcmp("++", val))
1622  {if (!(val = Config.GetWord()))
1623  {eDest.Emsg("Config", "redrilib wrapper not specified"); return 1;}
1624  if (RDLPath.empty())
1625  {eDest.Emsg("Config", "base redrilib not specified"); return 1;}
1626  if (*val == '+' && !(val = xrdlopt(Config, val))) return 1;
1627  RDLPath.push_back((std::string)val);
1628  if (!Config.GetRest(pbuff, sizeof(pbuff)))
1629  {eDest.Emsg("Config", "redirlib parameters too long"); return 1;}
1630  RDLParm.push_back((std::string)pbuff);
1631  return 0;
1632  } else if (*val == '+' && !(val = xrdlopt(Config, val))) return 1;
1633 
1634 // This is either a base library specification or a replacement
1635 //
1636  if (RDLPath.empty()) RDLPath.push_back((std::string)val);
1637  else RDLPath[0] = val;
1638 
1639 // Get the optional parameters
1640 //
1641  if (!Config.GetRest(pbuff, sizeof(pbuff)))
1642  {eDest.Emsg("Config", "redirlib parameters too long"); return 1;}
1643  if (RDLParm.empty()) RDLParm.push_back((std::string)pbuff);
1644  else RDLParm[0] = pbuff;
1645 
1646 // All done
1647 //
1648  return 0;
1649 }
1650 
1651 /******************************************************************************/
1652 /* x r d r o p t */
1653 /******************************************************************************/
1654 
1655 char* XrdXrootdProtocol::xrdlopt(XrdOucStream &Config, char* val)
1656 {
1657  int num;
1658 
1659 // Check for valid options
1660 //
1661 do{if (!strcmp(val, "+iphold"))
1662  {if (!(val = Config.GetWord()))
1663  {eDest.Emsg("Config", "+iphold value not specified"); return 0;}
1664  if (XrdOuca2x::a2tm(eDest,"redirlib iphold",val,&num,0)) return 0;
1665  redirIPHold = num;
1666  }
1667  } while((val = Config.GetWord()) && *val == '+');
1668 
1669 // All done
1670 //
1671  return val;
1672 }
1673 
1674 /******************************************************************************/
1675 /* x r e d */
1676 /******************************************************************************/
1677 
1678 /* Function: xred
1679 
1680  Purpose: To parse the directive: redirect <host>:<port>[%<prvhost>:<port>]
1681  {<funcs>|[?]<path>} |
1682  client <domlist>
1683 
1684  <funcs> are one or more of the following functions that will
1685  be immediately redirected to <host>:<port>. Each function
1686  may be prefixed by a minus sign to disable redirection.
1687 
1688  chmod dirlist locate mkdir mv prepare rm rmdir stat
1689 
1690  <paths> redirects the client when an attempt is made to open
1691  one of absolute <paths>. Up to 4 different redirect
1692  combinations may be specified. When prefixed by "?"
1693  then the redirect applies to any operation on the path
1694  that results in an ENOENT error.
1695 
1696  <domlist> {private | local | .<domain>} [<domlist>]
1697 
1698  Output: 0 upon success or !0 upon failure.
1699 */
1700 
1701 int XrdXrootdProtocol::xred(XrdOucStream &Config)
1702 {
1703  static struct rediropts {const char *opname; RD_func opval;} rdopts[] =
1704  {
1705  {"chmod", RD_chmod},
1706  {"chksum", RD_chksum},
1707  {"dirlist", RD_dirlist},
1708  {"locate", RD_locate},
1709  {"mkdir", RD_mkdir},
1710  {"mv", RD_mv},
1711  {"openw", RD_openw},
1712  {"prepare", RD_prepare},
1713  {"prepstage",RD_prepstg},
1714  {"rm", RD_rm},
1715  {"rmdir", RD_rmdir},
1716  {"stat", RD_stat},
1717  {"trunc", RD_trunc}
1718  };
1719  static const int rHLen = 264;
1720  char rHost[2][rHLen], *hP[2], *val;
1721  int i, k, neg, numopts = sizeof(rdopts)/sizeof(struct rediropts);
1722  int rPort[2], isQ = 0;
1723 
1724 // Get the host and port
1725 //
1726  val = Config.GetWord();
1727  if (!xred_php(val, hP, rPort, "redirect")) return 1;
1728 
1729 // Copy out he values as the target variable will be lost
1730 //
1731  for (i = 0; i < 2; i++)
1732  {if (!hP[i]) rHost[i][0] = 0;
1733  else {strlcpy(rHost[i], hP[i], rHLen);
1734  hP[i] = rHost[i];
1735  }
1736  }
1737 
1738 // Set all redirect target functions
1739 //
1740  if (!(val = Config.GetWord()))
1741  {eDest.Emsg("config", "redirect option not specified"); return 1;}
1742 
1743 // Handle the client option
1744 //
1745  if (!strcmp("client", val)) return xred_clnt(Config, hP, rPort);
1746 
1747  if (*val == '/' || (isQ = ((*val == '?') || !strcmp(val,"enoent"))))
1748  {if (isQ)
1749  {RQLxist = 1;
1750  if (!(val = Config.GetWord()))
1751  {eDest.Emsg("Config", "redirect path not specified.");
1752  return 1;
1753  }
1754  if (*val != '/')
1755  {eDest.Emsg("Config", "non-absolute redirect path -", val);
1756  return 1;
1757  }
1758  }
1759  for (k = static_cast<int>(RD_open1); k < RD_Num; k++)
1760  if (xred_xok(k, hP, rPort)) break;
1761  if (k >= RD_Num)
1762  {eDest.Emsg("Config", "too many different path redirects"); return 1;}
1763  xred_set(RD_func(k), hP, rPort);
1764  do {if (isQ) RQList.Insert(val, k, 0);
1765  else RPList.Insert(val, k, 0);
1766  if ((val = Config.GetWord()) && *val != '/')
1767  {eDest.Emsg("Config", "non-absolute redirect path -", val);
1768  return 1;
1769  }
1770  } while(val);
1771  return 0;
1772  }
1773 
1774  while (val)
1775  {if (!strcmp(val, "all"))
1776  {for (i = 0; i < numopts; i++)
1777  xred_set(rdopts[i].opval, hP, rPort);
1778  }
1779  else {if ((neg = (val[0] == '-' && val[1]))) val++;
1780  for (i = 0; i < numopts; i++)
1781  {if (!strcmp(val, rdopts[i].opname))
1782  {if (neg) xred_set(rdopts[i].opval, 0, 0);
1783  else xred_set(rdopts[i].opval, hP, rPort);
1784  break;
1785  }
1786  }
1787  if (i >= numopts)
1788  eDest.Emsg("config", "invalid redirect option", val);
1789  }
1790  val = Config.GetWord();
1791  }
1792  return 0;
1793 }
1794 
1795 /******************************************************************************/
1796 
1797 int XrdXrootdProtocol::xred_clnt(XrdOucStream &Config,char *hP[2],int rPort[2])
1798 {
1799  static const int maxDom = sizeof(RouteClient.Domain)/sizeof(char*);
1800  char *val;
1801 
1802 // Reset values
1803 //
1804  if (CL_Redir)
1805  {for (int i = 0; i < RouteClient.DomCnt; i++)
1806  {if (RouteClient.Domain[i]) free(RouteClient.Domain[i]);}
1807  }
1808  for (int i = 0; i < maxDom; i++) RouteClient.Domain[i] = 0;
1809  RouteClient.DomCnt = 0;
1810  RouteClient.pvtIP = false;
1811  RouteClient.lclDom = false;
1812  CL_Redir = true;
1813 
1814 // Process arguments
1815 //
1816  if (!(val = Config.GetWord()))
1817  {eDest.Emsg("Config", "redirect client argument not specified.");
1818  return 1;
1819  }
1820 
1821  while(val)
1822  { if (!strcmp("private", val)) RouteClient.pvtIP = true;
1823  else if (!strcmp("local", val)) RouteClient.lclDom = true;
1824  else if (*val == '.')
1825  {if (RouteClient.DomCnt >= maxDom)
1826  {eDest.Emsg("Config",
1827  "Too many redirect client domains specified.");
1828  return 1;
1829  }
1830  RouteClient.Domain[RouteClient.DomCnt++] = strdup(val);
1831  }
1832  else {eDest.Emsg("Config", "Invalid redirect client domain -", val);
1833  return 1;
1834  }
1835  val = Config.GetWord();
1836  }
1837 
1838 // Set the host parameters
1839 //
1840  xred_set(RD_client, hP, rPort);
1841  return 0;
1842 }
1843 
1844 /******************************************************************************/
1845 
1846 bool XrdXrootdProtocol::xred_php(char *val, char *hP[2], int rPort[2],
1847  const char *what, bool optport)
1848 {
1849  XrdNetAddr testAddr;
1850  char *pp;
1851 
1852 // Make sure we have a value
1853 //
1854  if (!val || !(*val))
1855  {eDest.Emsg("config", what, "argument not specified"); return false;}
1856 
1857 // Check if we have two hosts here
1858 //
1859  hP[0] = val;
1860  if (!(pp = index(val, '%'))) hP[1] = 0;
1861  else {hP[1] = pp+1; *pp = 0;}
1862 
1863 // Verify corectness here
1864 //
1865  if (!(*val) || (hP[1] && !*hP[1]))
1866  {eDest.Emsg("Config", "malformed", what, "host specification");
1867  return false;
1868  }
1869 
1870 // Process the hosts
1871 //
1872  for (int i = 0; i < 2; i++)
1873  {if (!(val = hP[i])) break;
1874  if (!val || !val[0] || val[0] == ':')
1875  {eDest.Emsg("Config", what, "host not specified"); return false;}
1876  if ((pp = rindex(val, ':')))
1877  {if ((rPort[i] = XrdOuca2x::a2p(eDest, "tcp", pp+1, false)) <= 0)
1878  return false;
1879  *pp = '\0';
1880  } else {
1881  if (optport) rPort[i] = 0;
1882  else {eDest.Emsg("Config", what, "port not specified");
1883  return false;
1884  }
1885  }
1886  const char *eText = testAddr.Set(val, 0);
1887  if (eText)
1888  {if (XrdNetAddrInfo::isHostName(val) && !strncmp(eText,"Dynamic",7))
1889  eDest.Say("Config warning: ", eText, " as ", val);
1890  else {eDest.Say("Config failure: ", what, " target ", val,
1891  " is invalid; ", eText);
1892  return false;
1893  }
1894  }
1895  }
1896 
1897 // All done
1898 //
1899  return true;
1900 }
1901 
1902 void XrdXrootdProtocol::xred_set(RD_func func, char *rHost[2], int rPort[2])
1903 {
1904 
1905 // Reset static redirection
1906 //
1907  if (Route[func].Host[0]) free(Route[func].Host[0]);
1908  if (Route[func].Host[0] != Route[func].Host[1]) free(Route[func].Host[1]);
1909 
1910  if (rHost)
1911  {Route[func].Host[0] = strdup(rHost[0]);
1912  Route[func].Port[0] = rPort[0];
1913  } else {
1914  Route[func].Host[0] = Route[func].Host[1] = 0;
1915  Route[func].Port[0] = Route[func].Port[1] = 0;
1916  return;
1917  }
1918 
1919  if (!rHost[1])
1920  {Route[func].Host[1] = Route[func].Host[0];
1921  Route[func].Port[1] = Route[func].Port[0];
1922  } else {
1923  Route[func].Host[1] = strdup(rHost[1]);
1924  Route[func].Port[1] = rPort[1];
1925  }
1926 }
1927 
1928 bool XrdXrootdProtocol::xred_xok(int func, char *rHost[2], int rPort[2])
1929 {
1930  if (!Route[func].Host[0]) return true;
1931 
1932  if (strcmp(Route[func].Host[0], rHost[0])
1933  || Route[func].Port[0] != rPort[0]) return false;
1934 
1935  if (!rHost[1]) return Route[func].Host[0] == Route[func].Host[1];
1936 
1937  if (strcmp(Route[func].Host[1], rHost[1])
1938  || Route[func].Port[1] != rPort[1]) return false;
1939 
1940  return true;
1941 }
1942 
1943 /******************************************************************************/
1944 /* x s e c l */
1945 /******************************************************************************/
1946 
1947 /* Function: xsecl
1948 
1949  Purpose: To parse the directive: seclib {default | <path>}
1950 
1951  <path> the path of the security library to be used.
1952  "default" uses the default security library.
1953 
1954  Output: 0 upon success or !0 upon failure.
1955 */
1956 
1957 int XrdXrootdProtocol::xsecl(XrdOucStream &Config)
1958 {
1959  char *val;
1960 
1961 // Get the path
1962 //
1963  val = Config.GetWord();
1964  if (!val || !val[0])
1965  {eDest.Emsg("Config", "seclib argument not specified"); return 1;}
1966 
1967 // Record the path
1968 //
1969  if (SecLib) free(SecLib);
1970  SecLib = strdup(val);
1971  return 0;
1972 }
1973 
1974 /******************************************************************************/
1975 /* x t l s */
1976 /******************************************************************************/
1977 
1978 /* Function: xtls
1979 
1980 topPurpose: To parse the directive: tls [capable] <reqs>
1981 
1982  capable Enforce TLS requirements only for TLS capable clients.
1983  Otherwise, TLS is enforced for all clients.
1984  <reqs> are one or more of the following tls requirements. Each
1985  may be prefixed by a minus sign to disable it. Note
1986  this directive is cummalitive.
1987 
1988  all Requires all of the below.
1989  data All bound sockets must use TLS. When specified,
1990  session is implied unless login is specified.
1991  gpfile getile and putfile requests must use TLS
1992  login Logins and all subsequent requests must use TLS
1993  none Turns all requirements off (default).
1994  off Synonym for none.
1995  session All requests after login must use TLS
1996  tpc Third party copy requests must use TLS
1997 
1998  Output: 0 upon success or !0 upon failure.
1999 */
2000 
2001 int XrdXrootdProtocol::xtls(XrdOucStream &Config)
2002 {
2003  static const int Req_TLSAll = Req_TLSData|Req_TLSLogin|Req_TLSTPC;
2004  static struct enforceopts {const char *opname; int opval; int enval;}
2005  enfopts[] =
2006  {
2007  {"all", kXR_tlsAny, Req_TLSAll},
2008  {"data", kXR_tlsData, Req_TLSData},
2009  {"gpfile", kXR_tlsGPF, Req_TLSGPFile},
2010  {"login", kXR_tlsLogin, Req_TLSLogin},
2011  {"session", kXR_tlsSess, Req_TLSSess},
2012  {"tpc", kXR_tlsTPC, Req_TLSTPC}
2013  };
2014  char *val;
2015  int i, numopts = sizeof(enfopts)/sizeof(struct enforceopts);
2016  bool neg, forall = true;
2017 
2018  if (!(val = Config.GetWord()))
2019  {eDest.Emsg("config", "tls parameter not specified"); return 1;}
2020 
2021  if (!strcmp("capable", val))
2022  {forall = false;
2023  if (!(val = Config.GetWord()))
2024  {eDest.Emsg("config", "tls requirement not specified"); return 1;}
2025  }
2026 
2027  while (val)
2028  {if (!strcmp(val, "off") || !strcmp(val, "none"))
2029  {myRole &= ~kXR_tlsAny;
2030  if (forall) tlsCap = tlsNot = 0;
2031  else tlsCap = 0;
2032  } else {
2033  if ((neg = (val[0] == '-' && val[1]))) val++;
2034  for (i = 0; i < numopts; i++)
2035  {if (!strcmp(val, enfopts[i].opname))
2036  {if (neg) myRole &= ~enfopts[i].opval;
2037  else myRole |= enfopts[i].opval;
2038  if (neg) tlsCap &= ~enfopts[i].enval;
2039  else tlsCap |= enfopts[i].enval;
2040  if (forall)
2041  {if (neg) tlsNot &= ~enfopts[i].enval;
2042  else tlsNot |= enfopts[i].enval;
2043  }
2044  break;
2045  }
2046  }
2047  if (i >= numopts)
2048  {eDest.Emsg("config", "Invalid tls requirement -", val);
2049  return 1;
2050  }
2051  }
2052  val = Config.GetWord();
2053  }
2054 
2055 // If data needs TLS but the session does not, then force session TLS
2056 //
2057  if ((myRole & kXR_tlsData) && !(myRole & (kXR_tlsLogin | kXR_tlsSess)))
2058  myRole |= kXR_tlsSess;
2059  if ((tlsCap & kXR_tlsData) && !(tlsCap & (Req_TLSLogin | Req_TLSSess)))
2060  tlsCap |= Req_TLSSess;
2061  if ((tlsNot & kXR_tlsData) && !(tlsNot & (Req_TLSLogin | Req_TLSSess)))
2062  tlsNot |= Req_TLSSess;
2063 
2064 // Do final resolution on the settins
2065 //
2066  return (CheckTLS(0) ? 0 : 1);
2067 }
2068 
2069 /******************************************************************************/
2070 /* x t l s r */
2071 /******************************************************************************/
2072 
2073 /* Function: xtlsr
2074 
2075  Purpose: To parse the directive: tlsreuse off | on [flush <ft>[h|m|s]]
2076 
2077  off turns off the TLS session reuse cache.
2078  on turns on the TLS session reuse cache.
2079  <ft> sets the cache flush frequency. the default is set
2080  by the TLS libraries and is typically connection count.
2081 
2082  Output: 0 upon success or !0 upon failure.
2083 */
2084 
2085 int XrdXrootdProtocol::xtlsr(XrdOucStream &Config)
2086 {
2087  char *val;
2088  int num;
2089 
2090 // Get the argument
2091 //
2092  val = Config.GetWord();
2093  if (!val || !val[0])
2094  {eDest.Emsg("Config", "tlsreuse argument not specified"); return 1;}
2095 
2096 // If it's off, we set it off
2097 //
2098  if (!strcmp(val, "off"))
2100  return 0;
2101  }
2102 
2103 // If it's on we may need more to do
2104 //
2105  if (!strcmp(val, "on"))
2106  {if (!tlsCtx) {eDest.Emsg("Config warning:", "Ignoring "
2107  "'tlsreuse on'; TLS not configured!");
2108  return 0;
2109  }
2111  if (!(val = Config.GetWord())) return 0;
2112  if (!strcmp(val, "flush" ))
2113  {if (!(val = Config.GetWord()))
2114  {eDest.Emsg("Config", "tlsreuse flush value not specified");
2115  return 1;
2116  }
2117  if (XrdOuca2x::a2tm(eDest,"tlsreuse flush",val,&num,1)) return 1;
2118  if (num < 60) num = 60;
2119  else if (num > XrdTlsContext::scFMax)
2120  num = XrdTlsContext::scFMax;
2121  tlsCache |= num;
2122  }
2123  }
2124 
2125 // We have a bad keyword
2126 //
2127  eDest.Emsg("config", "Invalid tlsreuse option -", val);
2128  return 1;
2129 }
2130 
2131 /******************************************************************************/
2132 /* x t r a c e */
2133 /******************************************************************************/
2134 
2135 /* Function: xtrace
2136 
2137  Purpose: To parse the directive: trace <events>
2138 
2139  <events> the blank separated list of events to trace. Trace
2140  directives are cummalative.
2141 
2142  Output: 0 upon success or 1 upon failure.
2143 */
2144 
2145 int XrdXrootdProtocol::xtrace(XrdOucStream &Config)
2146 {
2147  char *val;
2148  static struct traceopts {const char *opname; int opval;} tropts[] =
2149  {
2150  {"all", TRACE_ALL},
2151  {"auth", TRACE_AUTH},
2152  {"debug", TRACE_DEBUG},
2153  {"emsg", TRACE_EMSG},
2154  {"fs", TRACE_FS},
2155  {"fsaio", TRACE_FSAIO},
2156  {"fsio", TRACE_FSIO},
2157  {"login", TRACE_LOGIN},
2158  {"mem", TRACE_MEM},
2159  {"pgcserr", TRACE_PGCS},
2160  {"redirect", TRACE_REDIR},
2161  {"request", TRACE_REQ},
2162  {"response", TRACE_RSP},
2163  {"stall", TRACE_STALL}
2164  };
2165  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
2166 
2167  if (!(val = Config.GetWord()))
2168  {eDest.Emsg("config", "trace option not specified"); return 1;}
2169  while (val)
2170  {if (!strcmp(val, "off")) trval = 0;
2171  else {if ((neg = (val[0] == '-' && val[1]))) val++;
2172  for (i = 0; i < numopts; i++)
2173  {if (!strcmp(val, tropts[i].opname))
2174  {if (neg) trval &= ~tropts[i].opval;
2175  else trval |= tropts[i].opval;
2176  break;
2177  }
2178  }
2179  if (i >= numopts)
2180  eDest.Emsg("config", "invalid trace option", val);
2181  }
2182  val = Config.GetWord();
2183  }
2184  XrdXrootdTrace.What = trval;
2185  return 0;
2186 }
2187 
2188 /******************************************************************************/
2189 /* x l i m i t */
2190 /******************************************************************************/
2191 
2192 /* Function: xlimit
2193 
2194  Purpose: To parse the directive: limit [prepare <count>] [noerror]
2195 
2196  prepare <count> The maximum number of prepares that are allowed
2197  during the course of a single connection
2198 
2199  noerror When possible, do not issue an error when a limit
2200  is hit.
2201 
2202  Output: 0 upon success or 1 upon failure.
2203 */
2204 int XrdXrootdProtocol::xlimit(XrdOucStream &Config)
2205 {
2206  int plimit = -1;
2207  const char *word;
2208 
2209 // Look for various limits set
2210 //
2211  while ( (word = Config.GetWord()) ) {
2212  if (!strcmp(word, "prepare")) {
2213  if (!(word = Config.GetWord()))
2214  {
2215  eDest.Emsg("Config", "'limit prepare' value not specified");
2216  return 1;
2217  }
2218  if (XrdOuca2x::a2i(eDest, "limit prepare", word, &plimit, 0)) { return 1; }
2219  } else if (!strcmp(word, "noerror")) {
2220  LimitError = false;
2221  }
2222  }
2223  if (plimit >= 0) {PrepareLimit = plimit;}
2224  return 0;
2225 }
#define kXR_isManager
Definition: XProtocol.hh:1198
#define kXR_tlsLogin
Definition: XProtocol.hh:1226
#define kXR_suppgrw
Definition: XProtocol.hh:1216
#define kXR_attrMeta
Definition: XProtocol.hh:1201
#define kXR_haveTLS
Definition: XProtocol.hh:1221
#define kXR_anongpf
Definition: XProtocol.hh:1214
#define kXR_tlsAny
Definition: XProtocol.hh:1223
#define kXR_tlsTPC
Definition: XProtocol.hh:1228
#define kXR_isServer
Definition: XProtocol.hh:1199
#define kXR_attrCache
Definition: XProtocol.hh:1200
#define kXR_attrProxy
Definition: XProtocol.hh:1202
#define kXR_LBalServer
Definition: XProtocol.hh:1193
#define kXR_tlsGPF
Definition: XProtocol.hh:1225
#define kXR_supposc
Definition: XProtocol.hh:1217
#define kXR_tlsSess
Definition: XProtocol.hh:1227
#define kXR_DataServer
Definition: XProtocol.hh:1192
#define kXR_supgpf
Definition: XProtocol.hh:1215
#define kXR_tlsData
Definition: XProtocol.hh:1224
unsigned short kXR_unt16
Definition: XPtypes.hh:67
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
XrdSfsFileSystem * XrdDigGetFS(XrdSfsFileSystem *native_fs, XrdSysLogger *lp, const char *cFN, const char *parms)
Definition: XrdDigFS.cc:105
#define TRACE_AUTH
Definition: XrdHttpTrace.hh:48
#define TRACE_REQ
Definition: XrdHttpTrace.hh:51
#define TRACE_RSP
Definition: XrdHttpTrace.hh:53
#define TRACE_REDIR
Definition: XrdHttpTrace.hh:52
#define open
Definition: XrdPosix.hh:78
XrdSecProtocol *(* XrdSecGetProt_t)(const char *hostname, XrdNetAddrInfo &endPoint, XrdSecParameters &sectoken, XrdOucErrInfo *einfo)
Typedef to simplify the encoding of methods returning XrdSecProtocol.
XrdSecService * XrdSecLoadSecService(XrdSysError *eDest, const char *cfn, const char *seclib, XrdSecGetProt_t *getP, XrdSecProtector **proP)
#define SFS_OK
const int SYS_LOG_02
Definition: XrdSysError.hh:101
const int SYS_LOG_01
Definition: XrdSysError.hh:100
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE_DEBUG
Definition: XrdTrace.hh:36
#define TRACE_MEM
Definition: XrdTrace.hh:38
#define TRACE(act, x)
Definition: XrdTrace.hh:63
#define TRACE_ALL
Definition: XrdTrace.hh:35
const char * XrdXrootdInstance
XrdSysTrace XrdXrootdTrace
XrdSfsFileSystem * XrdSfsGetDefaultFileSystem(XrdSfsFileSystem *nativeFS, XrdSysLogger *Logger, const char *configFn, XrdOucEnv *EnvInfo)
Definition: XrdOfsFS.cc:49
XrdXrootdPrepare * XrdXrootdPrepQ
XrdXrootdRedirPI * XrdXrootdloadRedirLib(XrdSysError *, XrdXrootdRedirPI *, const char *, const char *, const char *, XrdOucEnv *)
#define TS_Zeq(x, m)
XrdOucString * XrdXrootdCF
#define TS_Xeq(x, m)
XrdSfsFileSystem * XrdXrootdloadFileSystem(XrdSysError *, XrdSfsFileSystem *, const char *, const char *, XrdOucEnv *)
int XrdXrootdPort
#define TRACE_FS
#define TRACE_FSAIO
#define TRACE_FSIO
#define TRACE_PGCS
#define TRACE_LOGIN
#define TRACE_EMSG
#define TRACE_STALL
#define XROOTDXP_OK
#define XROOTDXP_NOLK
#define XROOTDXP_NOSLASH
#define XROOTDXP_NOMWCHK
#define XROOTDXP_NOCGI
int Recalc(int bsz)
Definition: XrdBuffer.cc:195
static XrdNetIF netIF
Definition: XrdInet.hh:68
static bool isHostName(const char *name)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
void Display(const char *pfx="=====> ")
Definition: XrdNetIF.cc:142
int Port()
Definition: XrdNetIF.hh:322
static int Parse(XrdSysError *eLog, XrdOucStream &Config)
static XrdNetPMark * Config(XrdSysError *eLog, XrdScheduler *sched, XrdSysTrace *trc, bool &fatal)
static XrdNetSocket * Create(XrdSysError *Say, const char *path, const char *fn, mode_t mode, int isudp=0)
void Set(int inQMax, time_t agemax=1800)
Definition: XrdObject.icc:90
long GetInt(const char *varname)
Definition: XrdOucEnv.cc:253
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
void PutPtr(const char *varname, void *value)
Definition: XrdOucEnv.cc:316
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
int Setup(const char *prog, XrdSysError *errP=0, int(*Proc)(XrdOucStream *, char **, int)=0)
Definition: XrdOucProg.cc:296
const char * c_str() const
int length() const
void append(const int i)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static const mode_t pathMode
Definition: XrdOucUtils.hh:48
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:506
static int GidName(gid_t gID, char *gName, int gNsz, time_t keepT=0)
Definition: XrdOucUtils.cc:636
static int UidName(uid_t uID, char *uName, int uNsz, time_t keepT=0)
static int makePath(char *path, mode_t mode, bool reset=false)
static void toLower(char *str)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
static int a2p(XrdSysError &, const char *ptype, const char *val, bool anyOK=true)
Definition: XrdOuca2x.cc:140
const char * myName
Definition: XrdProtocol.hh:82
XrdBuffManager * BPool
Definition: XrdProtocol.hh:63
XrdScheduler * Sched
Definition: XrdProtocol.hh:64
XrdTlsContext * tlsCtx
Definition: XrdProtocol.hh:99
const char * AdmPath
Definition: XrdProtocol.hh:76
XrdSysError * eDest
Definition: XrdProtocol.hh:61
XrdOucString * totalCF
Definition: XrdProtocol.hh:100
XrdOucEnv * theEnv
Definition: XrdProtocol.hh:66
const char * myInst
Definition: XrdProtocol.hh:81
XrdStats * Stats
Definition: XrdProtocol.hh:65
virtual const char * protTLS()=0
virtual void EnvInfo(XrdOucEnv *envP)
virtual int chksum(csFunc Func, const char *csName, const char *path, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0, const char *opaque=0)
virtual int FAttr(XrdSfsFACtl *faReq, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:162
void setMsgMask(int mask)
Definition: XrdSysError.hh:188
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:175
void SetLogger(XrdSysLogger *logp)
Definition: XrdSysTrace.cc:65
XrdTlsContext * Clone(bool full=true, bool startCRLRefresh=false)
int SessionCache(int opts=scNone, const char *id=0, int idlen=0)
static const int scNone
Do not change any option settings.
static const int scOff
Turn off cache.
static const int scFMax
static const int scSrvr
Turn on cache server mode (default)
static int Init(XrdSysError *erp, XrdNetSocket *asock)
static void addJob(const char *jname, XrdXrootdJob *jp)
static void setVals(XrdSysError *erp, XrdXrootdStats *SIp, XrdScheduler *schp, int port)
static void Init(XrdXrootdFileLock *lp, XrdSysError *erP, bool sfok)
static int setParms(int stime, int skeep)
static XrdXrootdStats * SI
static const char * myInst
static XrdSfsFileSystem * digFS
static XrdNetPMark * PMark
static short as_okstutter
static XrdXrootdXPath RPList
static XrdNetSocket * AdminSock
static const char Req_TLSGPFile
static const char Req_TLSSess
static XrdXrootdJob * JobCKS
static XrdSysError & eDest
static char * usxParms
static XrdXrootdRedirPI * RedirPI
static const char * myCName
static const char Req_TLSData
static XrdXrootdFileLock * Locker
static const char Req_TLSTPC
static XrdTlsContext * tlsCtx
static XrdXrootdXPath XPList
static XrdScheduler * Sched
static struct XrdXrootdProtocol::RC_Table RouteClient
static const char * myUName
static const char Req_TLSLogin
static int Configure(char *parms, XrdProtocol_Config *pi)
static XrdOucTList * JobCKTLST
static XrdXrootdXPath RQList
static XrdSecProtector * DHS
static XrdBuffManager * BPool
static XrdSecService * CIA
static const char * myGName
static uint64_t fsFeatures
static XrdOucReqID * PrepID
static struct XrdXrootdProtocol::RD_Table Route[RD_Num]
static XrdSfsFileSystem * osFS
static void Init(XrdXrootdRedirPI *pi, XrdSysError *eDest, int ipHold)
void setFS(XrdSfsFileSystem *fsp)
static void Init(XrdScheduler *schedP, int qMax, int qTTL)
Perform one-time initialization.
void Insert(const char *pd, int popt=0, int flags=XROOTDXP_OK)
XrdXrootdXPath * Next()
void Set(int opts, const char *pathdata=0)
XrdCmsConfig Config
XrdSysLogger Logger
Definition: XrdGlobals.cc:47
struct ServerResponseBifs_Protocol bifReqs
Definition: XProtocol.hh:1162
static const int maxRvecsz
Definition: XProtocol.hh:722
static const uint64_t hasPGRW
Feature: pgRead and pgWrite.
Definition: XrdSfsFlags.hh:56
static const uint64_t hasPRP2
Feature: Prepare Handler Version 2 (different calling conventions)
Definition: XrdSfsFlags.hh:62
static const uint64_t hasGPFA
Feature: gpFile anonymous.
Definition: XrdSfsFlags.hh:53
static const uint64_t hasCACH
Feature: Implements a data cache.
Definition: XrdSfsFlags.hh:74
static const uint64_t hasNOSF
Feature: Supports no sendfile.
Definition: XrdSfsFlags.hh:71
static const uint64_t hasPOSC
Feature: Persist On Successful Close.
Definition: XrdSfsFlags.hh:59
static const uint64_t hasGPF
Feature: gpFile.
Definition: XrdSfsFlags.hh:50
static const uint64_t hasNAIO
Feature: Supports no async I/O.
Definition: XrdSfsFlags.hh:77
static const uint64_t hasPRXY
Feature: Proxy Server.
Definition: XrdSfsFlags.hh:65
XrdXrootdStats * SI
XrdScheduler * Sched
char * bifResp[2]
XrdBuffManager * BPool