XRootD
XrdPssConfig.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d P s s C o n f i g . c c */
4 /* */
5 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <unistd.h>
32 #include <cctype>
33 #include <cstdio>
34 #include <cstring>
35 #include <strings.h>
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 
41 #include "XrdVersion.hh"
42 
43 #include "XrdNet/XrdNetAddr.hh"
44 #include "XrdNet/XrdNetUtils.hh"
45 #include "XrdNet/XrdNetSecurity.hh"
46 
47 #include "XrdPss/XrdPss.hh"
48 #include "XrdPss/XrdPssTrace.hh"
49 #include "XrdPss/XrdPssUrlInfo.hh"
50 #include "XrdPss/XrdPssUtils.hh"
51 
52 #include "XrdSys/XrdSysError.hh"
53 #include "XrdSys/XrdSysFD.hh"
54 #include "XrdSys/XrdSysHeaders.hh"
55 #include "XrdSys/XrdSysPlatform.hh"
56 #include "XrdSys/XrdSysPthread.hh"
57 
58 #include "XrdOuc/XrdOuca2x.hh"
59 #include "XrdOuc/XrdOucCache.hh"
60 #include "XrdOuc/XrdOucEnv.hh"
61 #include "XrdOuc/XrdOucExport.hh"
63 #include "XrdOuc/XrdOucPsx.hh"
64 #include "XrdOuc/XrdOucStream.hh"
65 #include "XrdOuc/XrdOucTList.hh"
66 #include "XrdOuc/XrdOucUtils.hh"
67 
71 
72 #include "XrdSecsss/XrdSecsssID.hh"
73 
75 
76 /******************************************************************************/
77 /* d e f i n e s */
78 /******************************************************************************/
79 
80 #define Duplicate(x,y) if (y) free(y); y = strdup(x)
81 
82 #define TS_String(x,m) if (!strcmp(x,var)) {Duplicate(val,m); return 0;}
83 
84 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(&eDest, Config);
85 
86 #define TS_PSX(x,m) if (!strcmp(x,var)) \
87  return (psxConfig->m(&eDest, Config) ? 0 : 1);
88 
89 #define TS_DBG(x,m) if (!strcmp(x,var)) {SysTrace.What |= m; return 0;}
90 
91 /******************************************************************************/
92 /* G l o b a l s */
93 /******************************************************************************/
94 
95 const char *XrdPssSys::ConfigFN; // -> Pointer to the config file name
96 const char *XrdPssSys::myHost;
97 const char *XrdPssSys::myName;
98 
100 
102 
104  char *XrdPssSys::fileOrgn = 0;
105 const char *XrdPssSys::protName = "root:";
106 const char *XrdPssSys::hdrData = "";
107 int XrdPssSys::hdrLen = 0;
108 int XrdPssSys::Streams =512;
109 int XrdPssSys::Workers = 16;
110 int XrdPssSys::Trace = 0;
111 int XrdPssSys::dcaCTime = 0;
112 
113 bool XrdPssSys::xLfn2Pfn = false;
114 bool XrdPssSys::dcaCheck = false;
115 bool XrdPssSys::dcaWorld = false;
116 bool XrdPssSys::deferID = false;
117 bool XrdPssSys::reProxy = false;
118 
119 namespace XrdProxy
120 {
122 
124 
125 extern XrdOucSid *sidP;
126 
127 extern XrdOucEnv *envP;
128 
129 extern XrdSecsssID *idMapper; // -> Auth ID mapper
130 
131 extern int rpFD;
132 
133 extern bool idMapAll;
134 
135 extern bool outProxy; // True means outgoing proxy
136 
137 extern bool xrdProxy; // True means dest using xroot protocol
138 
139 extern XrdSysTrace SysTrace;
140 
141 static const int maxHLen = 1024;
142 }
143 
144 namespace
145 {
146 XrdOucPsx *psxConfig;
147 
148 XrdSecsssID::authType sssMap; // persona setting
149 
150 std::vector<const char *> protVec; // Additional wanted protocols
151 }
152 
153 using namespace XrdProxy;
154 
155 /******************************************************************************/
156 /* C o n f i g u r e */
157 /******************************************************************************/
158 
159 int XrdPssSys::Configure(const char *cfn, XrdOucEnv *envP)
160 {
161 /*
162  Function: Establish configuration at start up time.
163 
164  Input: None.
165 
166  Output: 0 upon success or !0 otherwise.
167 */
168  char theRdr[maxHLen];
169  int NoGo = 0;
170 
171 // Get environmental values
172 //
173  myHost = getenv("XRDHOST");
174  myName = XrdOucUtils::InstName(1);
175  ConfigFN = cfn;
176 
177 // Thell xrootd to disable POSC mode as this is meaningless here
178 //
179  XrdOucEnv::Export("XRDXROOTD_NOPOSC", "1");
180 
181 // Create a configurator. It will be deleted when we are done.
182 //
183  psxConfig = new XrdOucPsx(myVersion, cfn, eDest.logger(), envP);
184 
185 // Set debug level if so wanted
186 //
187  if (getenv("XRDDEBUG"))
188  {psxConfig->traceLvl = 4;
190  }
191 
192 // Set the defaault number of worker threads for the client
193 //
194  XrdPosixConfig::SetEnv("WorkerThreads", 64);
195 
196 // Set client IP mode based on what the server is set to
197 //
198  if (XrdNetAddr::IPV4Set()) psxConfig->useV4 = true;
199 
200 // Set default number of event loops
201 //
202  XrdPosixConfig::SetEnv("ParallelEvtLoop", 10);
203 
204 // Turn off the fork handler as we always exec after forking.
205 //
206  XrdPosixConfig::SetEnv("RunForkHandler", 0);
207 
208 // Process the configuration file
209 //
210  if ((NoGo = ConfigProc(cfn))) return NoGo;
211 
212 // Make sure we have some kind of origin
213 //
214  if (!ManList && !outProxy && !fileOrgn)
215  {eDest.Emsg("Config", "Origin for proxy service not specified.");
216  return 1;
217  }
218 
219 // Check if we should configure authentication security mapping
220 //
221  if (sssMap && !ConfigMapID()) return 1;
222 
223 // Handle the local root here
224 //
225  if (LocalRoot) psxConfig->SetRoot(LocalRoot);
226 
227 // Pre-screen any n2n library parameters
228 //
229  if (outProxy && psxConfig->xLfn2Pfn)
230  {const char *txt;
231  if (!(psxConfig->xNameLib)) txt = "localroot directive";
232  else if (psxConfig->xPfn2Lfn) txt = "namelib -lfn2pfn option";
233  else txt = "namelib directive";
234  eDest.Say("Config warning: ignoring ",txt,"; this is forwarding proxy!");
235  psxConfig->xLfn2Pfn = false;
236  }
237 
238 // If we have a cache, indicate so in the feature set
239 //
240  if(psxConfig->hasCache()) myFeatures |= XRDOSS_HASCACH;
241 
242 // If we need to reproxy, then open the directory where the reproxy information
243 // will ne placed. The path is in the Env.
244 //
245  if (reProxy)
246  {char *rPath;
247  if (!envP || !(rPath = envP->Get("tpc.rpdir")))
248  {eDest.Say("Config warning: ignoring 'pss.reproxy'; TPC is not enabled!");
249  reProxy = false;
250  myFeatures &= ~XRDOSS_HASRPXY;
251  } else {
252  rpFD = XrdSysFD_Open(rPath, O_DIRECTORY);
253  if (rpFD < 0)
254  {eDest.Emsg("Config", "to open reproxy directory", rPath);
255  return 1;
256  }
257  }
258  }
259 
260 // Finalize the configuration
261 //
262  if (!(psxConfig->ConfigSetup(eDest))) return 1;
263 
264 // Complete initialization (we would set the env pointer here)
265 //
266  if (!XrdPosixConfig::SetConfig(*psxConfig)) return 1;
267 
268 // Save the N2N library pointer if we will be using it
269 //
270  if (psxConfig->xLfn2Pfn) xLfn2Pfn = (theN2N = psxConfig->theN2N) != 0;
271 
272 // If we have a cache then save it and check if we need to tell
273 // xrootd we allow a redirect on a read (this is complicated).
274 // ??? Why are we doing this
275 // if (psxConfig->theCache2 && dcaCTime)
276 // {char buff[32];
277 // sprintf(buff, "%d", dcaCTime);
278 // XrdOucEnv::Export("XRDXROOTD_CACHERDRDR", buff);
279 // }
280 
281 // All done with the configurator
282 //
283  delete psxConfig;
284 
285 // Allocate an Xroot proxy object (only one needed here). Tell it to not
286 // shadow open files with real file descriptors (we will be honest).
287 //
288  Xroot = new XrdPosixXrootd(-32768, 16384);
289 
290 // Allocate an streaim ID object if need be
291 //
292  if (Streams) sidP = new XrdOucSid((Streams > 8192 ? 8192 : Streams));
293 
294 // Tell any security manager we are a proxy as this will force it to use our
295 // credentials. We don't support credential forwarding, yet. If we did we would
296 // also set XrdSecPROXYCREDS to accomplish that feat.
297 //
298  XrdOucEnv::Export("XrdSecPROXY", "1");
299 
300 // Add the origin protocl to the recognized list of protocol names
301 //
302  if (!XrdPosixXrootPath::AddProto(protName))
303  {eDest.Emsg("Config", "Unable to add origin protocol to protocol list.");
304  return 1;
305  }
306 
307 // Add any other protocols to the recognized list of protocol names
308 //
309  if (protVec.size())
310  {for (int i = 0; i < (int)protVec.size(); i++)
311  {if (!XrdPosixXrootPath::AddProto(protVec[i]))
312  {eDest.Emsg("Config", "Unable to add", protVec[i],
313  "protocol to protocol list.");
314  return 1;
315  }
316  }
317  protVec.clear();
318  }
319 
320 // Construct the redirector name:port (we might not have one) export it
321 //
322  const char *outeq = (outProxy ? "= " : "");
323  if (ManList) sprintf(theRdr, "%s%s:%d", outeq, ManList->text, ManList->val);
324  else if (fileOrgn) sprintf(theRdr, "%s%s", outeq, fileOrgn);
325  else strcpy(theRdr, outeq);
326  XrdOucEnv::Export("XRDXROOTD_PROXY", theRdr);
327  XrdOucEnv::Export("XRDXROOTD_ORIGIN", theRdr); // Backward compatibility
328  if (HostArena) XrdOucEnv::Export("XRDXROOTD_PROXYARENA", HostArena);
329 
330 // Construct the contact URL header
331 //
332  if (ManList) //<prot><id>@<host>:<port>/<path>
333  {hdrLen = sprintf(theRdr, "%s%%s%s:%d/%s%%s",
334  protName, ManList->text, ManList->val,
335  (HostArena ? HostArena : ""));
336  hdrData = strdup(theRdr);
337  } else {
338  if (fileOrgn)
339 //?? {if (!(myFeatures & XRDOSS_HASCACH))
340 // {eDest.Emsg("Config", "File origins only supported for caching proxies.");
341 // return 1;
342 // }
343  {hdrLen = sprintf(theRdr, "%s%s%%s", protName, fileOrgn);
344  hdrData = strdup(theRdr);
345  }
346  }
347 
348 // Export the URL
349 //
350  if (hdrData && *hdrData)
351  {snprintf(theRdr, sizeof(theRdr), hdrData, "", "");
352  XrdOucEnv::Export("XRDXROOTD_PROXYURL", theRdr);
353  }
354 
355 // Check if we have any r/w exports as this will determine whether or not we
356 // need to initialize any r/w cache. Currently, we don't support this so we
357 // have no particular initialization to do.
358 //
359 // XrdOucPList *fP = XPList.First();
360 // while(fP && !(fP->Flag() & XRDEXP_NOTRW)) fP = fP->Next();
361 // if (!fP) . . .
362 
363 // All done
364 //
365  return 0;
366 }
367 
368 /******************************************************************************/
369 /* P r i v a t e F u n c t i o n s */
370 /******************************************************************************/
371 /******************************************************************************/
372 /* C o n f i g M a p I D */
373 /******************************************************************************/
374 
376 {
377  XrdSecsssCon *conTracker;
378  bool isOK, Debug = (SysTrace.What & TRACEPSS_Debug) != 0;
379 
380 // If this is a generic static ID mapping, we are done
381 //
382  if (sssMap == XrdSecsssID::idStatic) return true;
383 
384 // For optimzation we also note if we have a cache in he way of the map
385 //
386  deferID = psxConfig->hasCache();
387 
388 // Now that we did the cache thing, currently we don't support client personas
389 // with a cache because aren't able to tell which client will be used.
390 //
391  if (deferID)
392  {eDest.Emsg("Config", "Client personas are not supported for "
393  "caching proxy servers.");
394  return false;
395  }
396 
397 // If this server is only a forwarding proxy server, we can't support client
398 // personas either because we don't control the URL. However, if we have an
399 // origin then simply warn that the client persona applies to the origin.
400 //
401  if (outProxy)
402  {if (!ManList)
403  {eDest.Emsg("Config", "Client personas are not supported for "
404  "strictly forwarding proxy servers.");
405  return false;
406  }
407  eDest.Say("Config warning: client personas only apply to "
408  "the origin server!");
409  }
410 
411 // We need to get a connection tracker object from the posix interface.
412 // However, we only need it if we are actually mapping id's.
413 //
414  if (sssMap == XrdSecsssID::idStaticM) conTracker = 0;
415  else conTracker = XrdPosixConfig::conTracker(Debug);
416 
417 // Get an mapper object
418 //
419  idMapper = new XrdSecsssID(sssMap, 0, conTracker, &isOK);
420  if (!isOK)
421  {eDest.Emsg("Config", "Unable to render persona; persona mapper failed!");
422  return false;
423  }
424 
425 // If ths is a server persona then we don't need the mapper; abandon it.
426 //
427  if (sssMap == XrdSecsssID::idStaticM) idMapper = 0;
428  else XrdPssUrlInfo::setMapID(true);
429 
430 // We are all done
431 //
432  return true;
433 }
434 
435 /******************************************************************************/
436 /* C o n f i g P r o c */
437 /******************************************************************************/
438 
439 int XrdPssSys::ConfigProc(const char *Cfn)
440 {
441  char *var;
442  int cfgFD, retc, NoGo = 0;
443  XrdOucEnv myEnv;
444  XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
445 
446 // Make sure we have a config file
447 //
448  if (!Cfn || !*Cfn)
449  {eDest.Emsg("Config", "pss configuration file not specified.");
450  return 1;
451  }
452 
453 // Try to open the configuration file.
454 //
455  if ( (cfgFD = open(Cfn, O_RDONLY, 0)) < 0)
456  {eDest.Emsg("Config", errno, "open config file", Cfn);
457  return 1;
458  }
459  Config.Attach(cfgFD);
460  static const char *cvec[] = { "*** pss (oss) plugin config:", 0 };
461  Config.Capture(cvec);
462 
463 // Now start reading records until eof.
464 //
465  while((var = Config.GetMyFirstWord()))
466  {if (!strncmp(var, "pss.", 4)
467  || !strcmp(var, "oss.defaults")
468  || !strcmp(var, "all.export"))
469  if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
470  }
471 
472 // Now check if any errors occurred during file i/o
473 //
474  if ((retc = Config.LastError()))
475  NoGo = eDest.Emsg("Config", retc, "read config file", Cfn);
476  Config.Close();
477 
478 // Set the defaults for the export list
479 //
480  XPList.Set(DirFlags);
481 
482 // Return final return code
483 //
484  return NoGo;
485 }
486 
487 /******************************************************************************/
488 /* C o n f i g X e q */
489 /******************************************************************************/
490 
491 int XrdPssSys::ConfigXeq(char *var, XrdOucStream &Config)
492 {
493  char myVar[80], *val;
494 
495  // Process items. for either a local or a remote configuration
496  //
497  TS_PSX("namelib", ParseNLib);
498  TS_PSX("memcache", ParseCache); // Backward compatibility
499  TS_PSX("cache", ParseCache);
500  TS_PSX("cachelib", ParseCLib);
501  TS_PSX("ccmlib", ParseMLib);
502  TS_PSX("ciosync", ParseCio);
503  TS_Xeq("config", xconf);
504  TS_Xeq("dca", xdca);
505  TS_Xeq("defaults", xdef);
506  TS_DBG("debug", TRACEPSS_Debug);
507  TS_Xeq("export", xexp);
508  TS_PSX("inetmode", ParseINet);
509  TS_Xeq("origin", xorig);
510  TS_Xeq("permit", xperm);
511  TS_Xeq("persona", xpers);
512  TS_PSX("setopt", ParseSet);
513  TS_PSX("trace", ParseTrace);
514 
515  if (!strcmp("reproxy", var))
516  {myFeatures |= XRDOSS_HASRPXY;
517  reProxy = true;
518  Config.GetWord(); // Force echo
519  return 0;
520  }
521 
522  // Copy the variable name as this may change because it points to an
523  // internal buffer in Config. The vagaries of effeciency. Then get value.
524  //
525  strlcpy(myVar, var, sizeof(myVar)); var = myVar;
526  if (!(val = Config.GetWord()))
527  {eDest.Emsg("Config", "no value for directive", var);
528  return 1;
529  }
530 
531  // Match directives that take a single argument
532  //
533  TS_String("hostarena", HostArena);
534  TS_String("localroot", LocalRoot);
535 
536  // No match found, complain.
537  //
538  eDest.Say("Config warning: ignoring unknown directive '",var,"'.");
539  Config.Echo();
540  return 0;
541 }
542 
543 /******************************************************************************/
544 /* x c o n f */
545 /******************************************************************************/
546 
547 /* Function: xconf
548 
549  Purpose: To parse the directive: config <keyword> <value>
550 
551  <keyword> is one of the following:
552  streams number of i/o streams
553  workers number of queue workers
554 
555  Output: 0 upon success or 1 upon failure.
556 */
557 
558 int XrdPssSys::xconf(XrdSysError *Eroute, XrdOucStream &Config)
559 {
560  char *val, *kvp;
561  int kval;
562  struct Xtab {const char *Key; int *Val;} Xopts[] =
563  {{"streams", &Streams},
564  {"workers", &Workers}};
565  int i, numopts = sizeof(Xopts)/sizeof(struct Xtab);
566 
567  if (!(val = Config.GetWord()))
568  {Eroute->Emsg("Config", "options argument not specified."); return 1;}
569 
570 do{for (i = 0; i < numopts; i++) if (!strcmp(Xopts[i].Key, val)) break;
571 
572  if (i >= numopts)
573  Eroute->Say("Config warning: ignoring unknown config option '",val,"'.");
574  else {if (!(val = Config.GetWord()))
575  {Eroute->Emsg("Config","config",Xopts[i].Key,"value not specified.");
576  return 1;
577  }
578 
579  kval = strtol(val, &kvp, 10);
580  if (*kvp || !kval)
581  {Eroute->Emsg("Config", Xopts[i].Key,
582  "config value is invalid -", val);
583  return 1;
584  }
585  *(Xopts[i].Val) = kval;
586  }
587  val = Config.GetWord();
588  } while(val && *val);
589 
590  return 0;
591 }
592 
593 /******************************************************************************/
594 /* x d c a */
595 /******************************************************************************/
596 
597 /* Function: xdca
598 
599  Purpose: To parse the directive: dca [group|world] [recheck {<tm> | off}]
600 
601  <tm> recheck for applicability every <tm> interval
602  world When specified, files are made world deadable.
603  Otherwise, they are only made group readable.
604 
605  Output: 0 upon success or 1 upon failure.
606 */
607 
608 int XrdPssSys::xdca(XrdSysError *errp, XrdOucStream &Config)
609 {
610  static const int maxsz = 0x7fffffff;
611  char *val;
612 
613 // Preset the defaults
614 //
615  dcaCheck = true;
616  dcaCTime = 0;
617  dcaWorld = false;
618 
619 // If no options then we are done
620 //
621  while((val = Config.GetWord()))
622  { if (!strcmp(val, "world")) dcaWorld = true;
623  else if (!strcmp(val, "group")) dcaWorld = false;
624  else if (!strcmp(val, "recheck"))
625  {if (!strcmp(val, "off")) dcaCTime = 0;
626  else {if (!(val = Config.GetWord()))
627  {errp->Emsg("Config",
628  "dca recheck value not specified");
629  return 1;
630  }
631  if (XrdOuca2x::a2tm(*errp,"dca recheck",val,
632  &dcaCTime,10,maxsz)) return 1;
633  }
634  }
635  else {errp->Emsg("Config","invalid dca option -", val); return 1;}
636  }
637 
638 // All done
639 //
640  return 0;
641 }
642 
643 /******************************************************************************/
644 /* x d e f */
645 /******************************************************************************/
646 
647 /* Function: xdef
648 
649  Purpose: Parse: defaults <default options>
650 
651  Notes: See the oss configuration manual for the meaning of each option.
652  The actual implementation is defined in XrdOucExport.
653 
654  Output: 0 upon success or !0 upon failure.
655 */
656 
657 int XrdPssSys::xdef(XrdSysError *Eroute, XrdOucStream &Config)
658 {
659  DirFlags = XrdOucExport::ParseDefs(Config, *Eroute, DirFlags);
660  return 0;
661 }
662 
663 /******************************************************************************/
664 /* x e x p */
665 /******************************************************************************/
666 
667 /* Function: xrcp
668 
669  Purpose: To parse the directive: {export | path} <path> [<options>]
670 
671  <path> the full path that resides in a remote system.
672  <options> a blank separated list of options (see XrdOucExport)
673 
674  Output: 0 upon success or !0 upon failure.
675 */
676 
677 int XrdPssSys::xexp(XrdSysError *Eroute, XrdOucStream &Config)
678 {
679  XrdOucPList *pP;
680 
681 // Parse the arguments
682 //
683  if (!(pP = XrdOucExport::ParsePath(Config, *Eroute, XPList, DirFlags)))
684  return 1;
685 
686 // Check if we are allowing object id's
687 //
688  if (*(pP->Path()) == '*') XrdPosixConfig::setOids(true);
689  return 0;
690 }
691 
692 /******************************************************************************/
693 /* x o r i g */
694 /******************************************************************************/
695 
696 /* Function: xorig
697 
698  Purpose: Parse: origin {=[<prot>,<prot>,...] [<dest>] | <dest>}
699 
700  where: <dest> <host>[+][:<port>|<port>] or a URL of the form
701  <prot>://<dest>[:<port>] where <prot> is one
702  http, https, root, xroot
703 
704  Output: 0 upon success or !0 upon failure.
705 */
706 
707 int XrdPssSys::xorig(XrdSysError *errp, XrdOucStream &Config)
708 {
709  XrdOucTList *tp = 0;
710  char *val, *colon, *slash, *mval = 0;
711  int i, port = 0;
712  bool isURL;
713 
714 // We are looking for regular managers. These are our points of contact
715 //
716  if (!(val = Config.GetWord()))
717  {errp->Emsg("Config","origin host name not specified"); return 1;}
718 
719 // Check for outgoing proxy
720 //
721  if (*val == '=')
722  {outProxy = true;
723  if (*(val+1))
724  {std::vector<char *> pVec;
725  char *pData = strdup(val+1);
726  const char *pName;
727  protVec.clear();
728  if (!XrdPssUtils::Vectorize(pData, pVec, ','))
729  {errp->Emsg("Config", "Malformed forwarding specification");
730  free(pData);
731  return 1;
732  }
733  protVec.reserve(pVec.size());
734  for (int i = 0; i < (int)pVec.size(); i++)
735  {int n = strlen(pVec[i]);
736  if (!(pName = XrdPssUtils::valProt(pVec[i], n, 3)))
737  {errp->Emsg("Config","Unsupported forwarding protocol -",pVec[i]);
738  free(pData);
739  return 1;
740  }
741  protVec.push_back(pName);
742  }
743  free(pData);
744  }
745  if (!(val = Config.GetWord())) return 0;
746  }
747  else outProxy = false;
748 
749 // We must always cleanup the file origin if it exists
750 //
751  if (fileOrgn) {free(fileOrgn); fileOrgn = 0;}
752 
753 // Check if dest is some local filesystem
754 //
755  if (*val == '/')
756  {char *vP = val +strlen(val) - 1;
757  while(*vP == '/'&& vP != val) {*vP-- = 0;}
758  if (ManList) {delete ManList; ManList = 0;}
759  protName = "file://";
760  fileOrgn = strdup(val);
761  return 0;
762  }
763 
764 
765 // Check if the <dest> is a url, if so, the protocol, must be supported
766 //
767  if ((colon = index(val, ':')) && *(colon+1) == '/' && *(colon+2) == '/')
768  {int pnlen;
769  protName = XrdPssUtils::valProt(val, pnlen);
770  if (!protName)
771  {errp->Emsg("Config", "Unsupported origin protocol -", val);
772  return 1;
773  }
774  if (*val == 'x') protName++;
775  xrdProxy = (*val == 'r');
776  val += pnlen;
777  if ((slash = index(val, '/')))
778  {if (*(slash+1))
779  {errp->Emsg("Config","badly formed origin URL"); return 1;}
780  *slash = 0;
781  }
782  mval = strdup(val);
783  isURL = true;
784  } else {
785  protName = "root://";
786  mval = strdup(val);
787  isURL = false;
788  xrdProxy = true;
789  }
790 
791 // Check if there is a port number. This could be as ':port' or ' port'.
792 //
793  if (!(val = index(mval,':')) && !isURL) val = Config.GetWord();
794  else if (val) {*val = '\0'; val++;}
795 
796 // At this point, make sure we actually have a host name
797 //
798  if (!(*mval))
799  {errp->Emsg("Config","origin host name not specified"); return 1;}
800 
801 // Validate the port number
802 //
803  if (val)
804  {if (isdigit(*val))
805  {if (XrdOuca2x::a2i(*errp,"origin port",val,&port,1,65535))
806  port = 0;
807  }
808  else if (!(port = XrdNetUtils::ServPort(val)))
809  {errp->Emsg("Config", "unable to find tcp service", val);
810  port = 0;
811  }
812  } else {
813  if (protName) {
814  // use default port for protocol
815  port = *protName == 'h' ? (strncmp(protName, "https", 5) == 0 ? 443 : 80) : 1094;
816  } else {
817  // assume protocol is root(s)://
818  port = 1094;
819  }
820  errp->Say("Config warning: origin port not specified, using port ",
821  std::to_string(port).c_str(), " as default for ", protName);
822  }
823 
824 // If port is invalid or missing, fail this
825 //
826  if (!port) {free(mval); return 1;}
827 
828 // For proxies we need not expand 'host+' spec but need to supress the plus
829 //
830  if ((i = strlen(mval)) > 1 && mval[i-1] == '+') mval[i-1] = 0;
831 
832 // We used to support multiple destinations in the URL but the new client
833 // does not support this. So, we only provide a single destination here. The
834 // original code is left commented out just in case we actually revert to this.
835 //
836 // tp = ManList;
837 // while(tp && (strcmp(tp->text, mval) || tp->val != port)) tp = tp->next;
838 // if (tp) errp->Emsg("Config","Duplicate origin",mval);
839 // else ManList = new XrdOucTList(mval, port, ManList);
840 
841  if (ManList) delete ManList;
842  ManList = new XrdOucTList(mval, port);
843 
844 // We now set the default dirlist flag based on whether the origin is in or out
845 // of domain. Composite listings are normally disabled for out of domain nodes.
846 //
847  if (!index(mval, '.')
848  || (!strcmp(XrdPssUtils::getDomain(mval), XrdPssUtils::getDomain(myHost))
849  && !strcmp(protName, "http://") && !strcmp(protName, "https://")))
850  XrdPosixConfig::SetEnv("DirlistDflt", 1);
851 
852 // All done
853 //
854  free(mval);
855  return tp != 0;
856 }
857 
858 /******************************************************************************/
859 /* x p e r m */
860 /******************************************************************************/
861 
862 /* Function: xperm
863 
864  Purpose: To parse the directive: permit [/] [*] <name>
865 
866  netgroup name the host must be a member of. For DNS names,
867  A single asterisk may be specified anywhere in the name.
868 
869  Output: 0 upon success or !0 upon failure.
870 */
871 
872 int XrdPssSys::xperm(XrdSysError *Eroute, XrdOucStream &Config)
873 { char *val;
874  bool pType[PolNum] = {false, false};
875  int i;
876 
877 do {if (!(val = Config.GetWord()))
878  {Eroute->Emsg("Config", "permit target not specified"); return 1;}
879  if (!strcmp(val, "/")) pType[PolPath] = true;
880  else if (!strcmp(val, "*")) pType[PolObj ] = true;
881  else break;
882  } while(1);
883 
884  if (!pType[PolPath] && !pType[PolObj])
885  pType[PolPath] = pType[PolObj] = true;
886 
887  for (i = 0; i < PolNum; i++)
888  {if (pType[i])
889  {if (!Police[i]){Police[i] = new XrdNetSecurity();}
890  Police[i]->AddHost(val);
891  }
892  }
893 
894  return 0;
895 }
896 
897 /******************************************************************************/
898 /* x p e r s */
899 /******************************************************************************/
900 
901 /* Function: xpers
902 
903  Purpose: To parse the directive: persona {client | server} [options]
904 
905  options: [[non]strict] [[no]verify]
906 
907  client proxy client's identity via sss authentication
908  server use server's identity at end point
909  strict all requests must use the client persona
910  nonstrict certain requests can use a server persona
911  noverify do not verify endpoint
912  verify verify endpoint
913 
914  Output: 0 upon success or !0 upon failure.
915 */
916 
917 int XrdPssSys::xpers(XrdSysError *Eroute, XrdOucStream &Config)
918 { char *val;
919  bool isClient = false, strict = false;
920  int doVer = -1;
921 
922 // Make sure a parameter was specified
923 //
924  if (!(val = Config.GetWord()))
925  {Eroute->Emsg("Config", "persona not specified"); return 1;}
926 
927 // Check for persona
928 //
929  if (!strcmp(val, "client")) isClient = true;
930  else if (!strcmp(val, "server")) isClient = false;
931  else {Eroute->Emsg("Config", "Invalid persona - ", val); return 1;}
932 
933 // Process the subsequent options
934 //
935  while ((val = Config.GetWord()))
936  { if (!strcmp(val, "strict" )) strict = true;
937  else if (!strcmp(val, "nonstrict" )) strict = false;
938  else if (!strcmp(val, "verify" )) doVer = 1;
939  else if (!strcmp(val, "noverify" )) doVer = 0;
940  else {Eroute->Emsg("Config", "Invalid persona option - ", val);
941  return 1;
942  }
943  }
944 
945 // Resolve options vs persona
946 //
947  if (isClient)
948  {idMapAll = (strict ? true : false);
949  if (doVer < 0) doVer = 1;
950  }
951 
952 // Now record the information for future processin
953 //
954  if (isClient) sssMap = (doVer ? XrdSecsssID::idMappedM
956  else sssMap = (doVer ? XrdSecsssID::idStaticM
958 
959 // All done
960 //
961  return 0;
962 }
#define XRDOSS_HASRPXY
Definition: XrdOss.hh:481
#define XRDOSS_HASCACH
Definition: XrdOss.hh:479
int open(const char *path, int oflag,...)
#define TS_String(x, m)
Definition: XrdPssConfig.cc:82
#define TS_DBG(x, m)
Definition: XrdPssConfig.cc:89
#define TS_Xeq(x, m)
Definition: XrdPssConfig.cc:84
#define TS_PSX(x, m)
Definition: XrdPssConfig.cc:86
#define TRACEPSS_Debug
Definition: XrdPssTrace.hh:34
size_t strlcpy(char *dst, const char *src, size_t sz)
static bool IPV4Set()
Definition: XrdNetAddr.hh:61
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
Definition: XrdNetUtils.cc:839
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
static unsigned long long ParseDefs(XrdOucStream &Config, XrdSysError &Eroute, unsigned long long Flags)
Definition: XrdOucExport.cc:60
static XrdOucPList * ParsePath(XrdOucStream &Config, XrdSysError &Eroute, XrdOucPListAnchor &Export, unsigned long long Defopts)
char * Path()
Definition: XrdOucPList.hh:45
static const char * InstName(int TranOpt=0)
Definition: XrdOucUtils.cc:732
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
static void SetEnv(const char *kword, int kval)
static void setOids(bool isok)
static XrdSecsssCon * conTracker(bool debug=false)
static bool SetConfig(XrdOucPsx &parms)
static bool AddProto(const char *proto)
POSIX interface to XRootD with some extensions, as noted.
static const int PolNum
Definition: XrdPss.hh:177
static int dcaCTime
Definition: XrdPss.hh:202
static int Streams
Definition: XrdPss.hh:199
static bool deferID
Definition: XrdPss.hh:207
static const char * ConfigFN
Definition: XrdPss.hh:187
static int hdrLen
Definition: XrdPss.hh:198
static const char * hdrData
Definition: XrdPss.hh:197
static XrdOucTList * ManList
Definition: XrdPss.hh:194
static char * fileOrgn
Definition: XrdPss.hh:195
static bool dcaCheck
Definition: XrdPss.hh:205
static bool reProxy
Definition: XrdPss.hh:208
static int Workers
Definition: XrdPss.hh:200
static XrdNetSecurity * Police[PolNum]
Definition: XrdPss.hh:193
static const char * myName
Definition: XrdPss.hh:189
static int Trace
Definition: XrdPss.hh:201
bool ConfigMapID()
static XrdOucPListAnchor XPList
Definition: XrdPss.hh:191
static const char * myHost
Definition: XrdPss.hh:188
static bool xLfn2Pfn
Definition: XrdPss.hh:204
static bool dcaWorld
Definition: XrdPss.hh:206
static const char * protName
Definition: XrdPss.hh:196
static void setMapID(bool onoff)
static const char * getDomain(const char *hName)
Definition: XrdPssUtils.cc:56
static const char * valProt(const char *pname, int &plen, int adj=0)
Definition: XrdPssUtils.cc:82
static bool Vectorize(char *str, std::vector< char * > &vec, char sep)
Definition: XrdPssUtils.cc:99
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
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:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
XrdVersionInfo myVersion
XrdCmsConfig Config
XrdOucName2Name * theN2N
Definition: XrdPosixFile.cc:62
XrdSecsssID * idMapper
Definition: XrdPss.cc:113
XrdSysTrace SysTrace("Pss", 0)
Definition: XrdPssCks.cc:55
bool xrdProxy
Definition: XrdPss.cc:127
XrdOucSid * sidP
Definition: XrdPss.cc:107
XrdSysError eDest(0, "pss_")
static const int maxHLen
bool outProxy
Definition: XrdPss.cc:125
bool idMapAll
Definition: XrdPss.cc:123
int rpFD
Definition: XrdPss.cc:121
static XrdPosixXrootd * Xroot
XrdOucEnv * envP
Definition: XrdPss.cc:109