XRootD
XrdSecServer.cc
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* X r d S e c S e r v e r . c c */
4 /* */
5 /* (c) 2005 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 <cerrno>
34 #include <fcntl.h>
35 #include <netdb.h>
36 #include <cstdlib>
37 #include <strings.h>
38 #include <cstdio>
39 #include <sys/param.h>
40 
41 #include "XrdVersion.hh"
42 
43 #include "XrdSys/XrdSysLogger.hh"
44 #include "XrdSys/XrdSysHeaders.hh"
45 #include "XrdSys/XrdSysError.hh"
46 #include "XrdOuc/XrdOucEnv.hh"
47 #include "XrdOuc/XrdOucErrInfo.hh"
48 #include "XrdOuc/XrdOucPinKing.hh"
49 #include "XrdNet/XrdNetAddr.hh"
50 
54 #include "XrdSec/XrdSecServer.hh"
55 #include "XrdSec/XrdSecTrace.hh"
56 
57 #ifndef EAUTH
58 #define EAUTH EBADE
59 #endif
60 
61 /******************************************************************************/
62 /* S e c u r i t y L e v e l s */
63 /******************************************************************************/
64 
65 namespace
66 {
67 XrdSecProtectParms lclParms;
68 XrdSecProtectParms rmtParms;
69 
70 XrdVERSIONINFODEF(myVer, XrdSec, XrdVNUMBER, XrdVERSION);
71 }
72 
73 /******************************************************************************/
74 /* X r d S e c P i n I n f o */
75 /******************************************************************************/
76 
78 {
79 public:
80 
82 
83  XrdSecPinInfo(const char *drctv, const char *cfn, XrdSysError &errR)
84  : KingPin(drctv, theEnv, errR, &myVer)
85  {theEnv.Put("configFN", cfn);}
86 
88 
90 };
91 
92 /******************************************************************************/
93 /* X r d S e c P r o t B i n d */
94 /******************************************************************************/
95 
97 {
98 public:
100 char *thost;
102 char *thostsfx;
106 
107 XrdSecProtBind *Find(const char *hname);
108 
109 int Match(const char *hname);
110 
111  XrdSecProtBind(char *th, char *st, XrdSecPMask_t pmask=0);
113  {free(thost);
114  if (SecToken.buffer) free(SecToken.buffer);
115  }
116 };
117 
118 /******************************************************************************/
119 /* C o n s t r u c t o r */
120 /******************************************************************************/
121 
123 {
124  char *starp;
125  next = 0;
126  thost = th;
127  if (!(starp = index(thost, '*')))
128  {tsfxlen = -1;
129  thostsfx = (char *)0;
130  tpfxlen = 0;
131  } else {
132  *starp = '\0';
133  tpfxlen = strlen(thost);
134  thostsfx = starp+1;
135  tsfxlen = strlen(thostsfx);
136  }
137  if (st) {SecToken.buffer = strdup(st); SecToken.size = strlen(st);}
138  else {SecToken.buffer = 0; SecToken.size = 0;}
139  ValidProts = (pmask ? pmask : ~(XrdSecPMask_t)0);
140 }
141 
142 /******************************************************************************/
143 /* F i n d */
144 /******************************************************************************/
145 
147 {
148  XrdSecProtBind *bp = this;
149 
150  while(bp && !bp->Match(hname)) bp = bp->next;
151 
152  return bp;
153 }
154 
155 /******************************************************************************/
156 /* M a t c h */
157 /******************************************************************************/
158 
159 int XrdSecProtBind::Match(const char *hname)
160 {
161  int i;
162 
163 // If an exact match wanted, return the result
164 //
165  if (tsfxlen < 0) return !strcmp(thost, hname);
166 
167 // Try to match the prefix
168 //
169  if (tpfxlen && strncmp(thost, hname, tpfxlen)) return 0;
170 
171 // If no suffix matching is wanted, then we have succeeded
172 //
173  if (!(thostsfx)) return 1;
174 
175 // Try to match the suffix
176 //
177  if ((i = (strlen(hname) - tsfxlen)) < 0) return 0;
178  return !strcmp(&hname[i], thostsfx);
179 }
180 
181 /******************************************************************************/
182 /* X r d S e c P r o t P a r m */
183 /******************************************************************************/
184 
186 {
187 public:
188 
189  void Add() {Next = First; First = this;}
190 
191  int Cat(char *token);
192 
193 static XrdSecProtParm *Find(char *pid, int remove=0);
194 
195  int Insert(char oct);
196 
197  int isProto(char *proto) {return !strcmp(ProtoID, proto);}
198 
199  char *Result(int &size) {size = bp-buff; return buff;}
200 
201  void setProt(char *pid) {strcpy(ProtoID, pid);}
202 
205 
207 
208  XrdSecProtParm(XrdSysError *erp, const char *cid) : who(cid)
209  {*ProtoID = '\0';
210  bsize = 4096;
211  buff = (char *)malloc(bsize);
212  *buff = '\0';
213  bp = buff;
214  eDest = erp;
215  Next = 0;
216  }
217  ~XrdSecProtParm() {free(buff);}
218 private:
219 
220 XrdSysError *eDest;
221 int bsize;
222 char *buff;
223 char *bp;
224 const char *who;
225 };
226 
228 
229 /******************************************************************************/
230 /* C a t */
231 /******************************************************************************/
232 
233 int XrdSecProtParm::Cat(char *token)
234 {
235  int alen;
236  alen = strlen(token);
237  if (alen+1 > bsize-(bp-buff))
238  {eDest->Emsg("Config",who,ProtoID,"argument string too long");
239  return 0;
240  }
241  *bp++ = ' ';
242  strcpy(bp, token);
243  bp += alen;
244  return 1;
245 }
246 
247 /******************************************************************************/
248 /* F i n d */
249 /******************************************************************************/
250 
251 XrdSecProtParm *XrdSecProtParm::Find(char *pid, int remove)
252 {
253  XrdSecProtParm *mp, *pp;
254 
255  mp = 0; pp = First;
256  while(pp && !pp->isProto(pid)){mp = pp; pp = pp->Next;}
257  if (pp && remove)
258  {if (mp) mp->Next = pp->Next;
259  else First = pp->Next;
260  }
261  return pp;
262 }
263 
264 /******************************************************************************/
265 /* I n s e r t */
266 /******************************************************************************/
267 
269 {
270  if (bsize-(bp-buff) < 1)
271  {eDest->Emsg("Config",who,ProtoID,"argument string too long");
272  return 0;
273  }
274  *bp++ = oct;
275  return 1;
276 }
277 
278 /******************************************************************************/
279 /* X r d S e c S e r v e r */
280 /******************************************************************************/
281 
282 XrdSecPManager XrdSecServer::PManager;
283 
284 /******************************************************************************/
285 /* C o n s t r u c t o r */
286 /******************************************************************************/
287 
289 {
290 
291 // Set default values
292 //
293  PManager.setErrP(&eDest);
294  configFN = "";
295  bpFirst = 0;
296  bpLast = 0;
297  bpDefault = 0;
298  pinInfo = 0;
299  pidList = 0;
300  STBlen = 4096;
301  STBuff = (char *)malloc(STBlen);
302  *STBuff = '\0';
303  SToken = STBuff;
304  SecTrace = new XrdOucTrace(&eDest);
305  if (getenv("XRDDEBUG") || getenv("XrdSecDEBUG"))
306  {SecTrace->What = TRACE_ALL;
307  PManager.setDebug(1);
308  }
309  Enforce = false;
310  implauth = false;
311 }
312 
313 /******************************************************************************/
314 /* g e t P a r m s */
315 /******************************************************************************/
316 
317 const char *XrdSecServer::getParms(int &size, XrdNetAddrInfo *endPoint)
318 {
319  EPNAME("getParms")
320  XrdSecProtBind *bp;
321  char buff[256];
322 
323 // Try to find a specific token binding for a host or return default binding
324 //
325  if (!endPoint || !bpFirst) bp = 0;
326  else {const char *hname = endPoint->Name("*unknown*");
327  bp = bpFirst;
328  do {if (bp->Match(hname)) break;} while((bp = bp->next));
329  }
330 
331 // Get endpoint info if we are debugging
332 //
333  if (endPoint && QTRACE(Debug))
334  endPoint->Format(buff, sizeof(buff), XrdNetAddrInfo::fmtAuto,
336  else *buff = 0;
337 
338 // If we have a binding, return that else return the default
339 //
340  if (!bp) bp = bpDefault;
341  if (bp->SecToken.buffer)
342  {DEBUG(buff <<" sectoken=" <<bp->SecToken.buffer);
343  size = bp->SecToken.size;
344  return bp->SecToken.buffer;
345  }
346 
347  DEBUG(buff <<" sectoken=''");
348  size = 0;
349  return (const char *)0;
350 }
351 
352 /******************************************************************************/
353 /* g e t P r o t o c o l */
354 /******************************************************************************/
355 
357  XrdNetAddrInfo &endPoint,
358  const XrdSecCredentials *cred,
359  XrdOucErrInfo &einfo)
360 {
361  XrdSecProtBind *bp;
362  XrdSecPMask_t pnum;
363  XrdSecCredentials myCreds;
364  const char *msgv[8];
365 
366 // If null credentials supplied, default to host protocol otherwise make sure
367 // credentials data is actually supplied.
368 //
369  if (!cred) {myCreds.buffer=(char *)"host"; myCreds.size = 4; cred=&myCreds;}
370  else if (cred->size < 1 || !(cred->buffer))
371  {einfo.setErrInfo(EACCES,"No authentication credentials supplied.");
372  return 0;
373  }
374 
375 // If protocol binding must be enforced, make sure the host is not using a
376 // disallowed protocol.
377 //
378  if (Enforce)
379  {if ((pnum = PManager.Find(cred->buffer)))
380  {if (bpFirst && (bp = bpFirst->Find(host))
381  && !(bp->ValidProts & pnum))
382  {msgv[0] = host;
383  msgv[1] = " not allowed to authenticate using ";
384  msgv[2] = cred->buffer;
385  msgv[3] = " protocol.";
386  einfo.setErrInfo(EACCES, msgv, 4);
387  return 0;
388  }
389  }
390  else {msgv[0] = cred->buffer;
391  msgv[1] = " security protocol is not supported.";
392  einfo.setErrInfo(EPROTONOSUPPORT, msgv, 2);
393  return 0;
394  }
395  }
396 
397 // If we passed the protocol binding check, try to get an instance of the
398 // protocol the host is using
399 //
400  return PManager.Get(host, endPoint, cred->buffer, &einfo);
401 }
402 
403 /******************************************************************************/
404 /* P o s t P r o c e s s */
405 /******************************************************************************/
406 
408 {
409 // Return correct result. Make sure there is some kind of message returned.
410 //
411  if (secEntityPin && !secEntityPin->Process(entity, einfo))
412  {if (*einfo.getErrText() == '\0')
413  einfo.setErrInfo(EAUTH, "rejected by auth post processing");
414  return false;
415  }
416 
417  return true;
418 }
419 
420 /******************************************************************************/
421 /* C o n f i g F i l e P r o c e s s i n g M e t h o d s */
422 /******************************************************************************/
423 /******************************************************************************/
424 /* d e f i n e s */
425 /******************************************************************************/
426 
427 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config,Eroute);
428 
429 #define TS_Str(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
430 
431 #define TS_Chr(x,m) if (!strcmp(x,var)) {m = val[0]; return 0;}
432 
433 #define TS_Bit(x,m,v) if (!strcmp(x,var)) {m = v; return 0;}
434 
435 #define Max(x,y) (x > y ? x : y)
436 
437 /******************************************************************************/
438 /* C o n f i g u r e */
439 /******************************************************************************/
440 
441 int XrdSecServer::Configure(const char *cfn)
442 /*
443  Function: Establish default values using a configuration file.
444 
445  Input: None.
446 
447  Output: 0 upon success or !0 otherwise.
448 */
449 {
451  static const int isRlx = XrdSecProtectParms::relax;
452  static const int isFrc = XrdSecProtectParms::force;
453  XrdSecProtector *protObj;
454  const char *lName = "none", *rName = "none";
455  char *var;
456  int NoGo;
457 
458 // Print warm-up message
459 //
460  eDest.Say("++++++ Authentication system initialization started.");
461 
462 // Perform initialization
463 //
464  NoGo = ConfigFile(cfn);
465 
466 // Load the entity post processing plugin if we have one
467 //
468  if (pinInfo && !NoGo)
469  {XrdSecEntityPin *secPin = pinInfo->KingPin.Load("SecEntityPin");
470  delete pinInfo;
471  secEntityPin = secPin;
472  if (!secPin) return 1;
473  }
474 
475 // Export the list of security protocols that are available
476 //
477  if (pidList) XrdOucEnv::Export("XRDSECPROTOCOLS", pidList);
478 
479 // Almost done
480 //
481  var = (NoGo > 0 ? (char *)"failed." : (char *)"completed.");
482  eDest.Say("------ Authentication system initialization ", var);
483 
484 // No need to configure protect system if authentication failed
485 //
486  if (NoGo) return 1;
487 
488 // Put out another banner
489 //
490  eDest.Say("++++++ Protection system initialization started.");
491 
492 // If local level if greater than remote level, issue a warning
493 //
494  if (lclParms.level > rmtParms.level)
495  eDest.Say("Config warning: local protection level greater than "
496  "remote level; are you sure?");
497 
498 // Check if we need to initialize protection services
499 //
500  if (lclParms.level == XrdSecProtectParms::secNone
501  && rmtParms.level == XrdSecProtectParms::secNone)
502  {eDest.Say("Config warning: Security level is set to none; "
503  "request protection disabled!");
504  } else {
505  if (!(protObj = XrdSecLoadProtection(eDest))
506  || !(protObj->Config(lclParms, rmtParms, *eDest.logger()))) NoGo = 1;
507  else {lName = protObj->LName(lclParms.level);
508  rName = protObj->LName(rmtParms.level);
509  }
510  }
511 
512 // Blurt out what we have
513 //
514  if (!NoGo)
515  {eDest.Say("Config ","Local protection level: ",
516  (lclParms.opts & isRlx ? "relaxed " : 0), lName,
517  (lclParms.opts & isFrc ? " force" : 0));
518  eDest.Say("Config ","Remote protection level: ",
519  (rmtParms.opts & isRlx ? "relaxed " : 0), rName,
520  (rmtParms.opts & isFrc ? " force" : 0));
521  }
522 
523 // Now we are done
524 //
525  var = (NoGo > 0 ? (char *)"failed." : (char *)"completed.");
526  eDest.Say("------ Protection system initialization ", var);
527  return (NoGo > 0);
528 }
529 
530 /******************************************************************************/
531 /* C o n f i g F i l e */
532 /******************************************************************************/
533 
534 int XrdSecServer::ConfigFile(const char *ConfigFN)
535 /*
536  Function: Establish default values using a configuration file.
537 
538  Input: None.
539 
540  Output: 1 - Initialization failed.
541  0 - Initialization succeeded.
542 */
543 {
544  char *var;
545  int cfgFD, retc, NoGo = 0, recs = 0;
546  XrdOucEnv myEnv;
547  XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
548  XrdSecProtParm *pp;
549 
550 // If there is no config file, return with the defaults sets.
551 //
552  if (!ConfigFN || !*ConfigFN)
553  {eDest.Emsg("Config", "Authentication configuration file not specified.");
554  return 1;
555  }
556  configFN = ConfigFN;
557 
558 // Try to open the configuration file.
559 //
560  if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
561  {eDest.Emsg("Config", errno, "opening config file", ConfigFN);
562  return 1;
563  }
564 
565 // Now start reading records until eof.
566 //
567  Config.Attach(cfgFD); Config.Tabs(0);
568  static const char *cvec[] = { "*** sec plugin config:", 0 };
569  Config.Capture(cvec);
570  while((var = Config.GetMyFirstWord()))
571  {if (!strncmp(var, "sec.", 4))
572  {recs++;
573  if (ConfigXeq(var+4, Config, eDest)) {Config.Echo(); NoGo = 1;}
574  }
575  }
576 
577 // Now check if any errors occurred during file i/o
578 //
579  if ((retc = Config.LastError()))
580  NoGo = eDest.Emsg("Config",-retc,"reading config file", ConfigFN);
581  else {char buff[128];
582  snprintf(buff, sizeof(buff),
583  " %d authentication directives processed in ", recs);
584  eDest.Say("Config", buff, ConfigFN);
585  }
586  Config.Close();
587 
588 // Determine whether we should initialize security
589 //
590  if (NoGo || ProtBind_Complete(eDest) ) NoGo = 1;
591  else if ((pp = XrdSecProtParm::First))
592  {NoGo = 1;
593  while(pp) {eDest.Emsg("Config", "protparm", pp->ProtoID,
594  "does not have a matching protocol.");
595  pp = pp->Next;
596  }
597  }
598 
599 // All done
600 //
601  return NoGo;
602 }
603 
604 /******************************************************************************/
605 /* P r i v a t e M e t h o d s */
606 /******************************************************************************/
607 /******************************************************************************/
608 /* C o n f i g X e q */
609 /******************************************************************************/
610 
611 int XrdSecServer::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError &Eroute)
612 {
613 
614  // Fan out based on the variable
615  //
616  TS_Xeq("entitylib", xenlib);
617  TS_Xeq("level", xlevel);
618  TS_Xeq("protbind", xpbind);
619  TS_Xeq("protocol", xprot);
620  TS_Xeq("protparm", xpparm);
621  TS_Xeq("trace", xtrace);
622 
623  // No match found, complain.
624  //
625  Eroute.Say("Config warning: ignoring unknown directive '",var,"'.");
626  Config.Echo();
627  return 0;
628 }
629 
630 /******************************************************************************/
631 /* x e n l i b */
632 /******************************************************************************/
633 
634 /* Function: xenlib
635 
636  Purpose: To parse the directive: entitylib [++] <path> [<parms>]
637 
638  <path> absolute path to the entity plugin.
639  <parms> optional parameters passed to the plugin.
640 
641  Output: 0 upon success or !0 upon failure.
642 */
643 
644 int XrdSecServer::xenlib(XrdOucStream &Config, XrdSysError &Eroute)
645 {
646  std::string path;
647  char *val, parms[2048];
648  bool push = false;
649 
650 // Get the path or the push token
651 //
652  if ((val = Config.GetWord()))
653  {if (!strcmp(val, "++"))
654  {push = true;
655  val = Config.GetWord();
656  }
657  }
658 
659 // Make sure a path was specified
660 //
661  if (!val || !*val)
662  {Eroute.Emsg("Config", "entitylib not specified"); return 1;}
663 
664 // Make sure the path is absolute
665 //
666  if (*val != '/')
667  {Eroute.Emsg("Config", "entitylib path is not absolute"); return 1;}
668 
669 // Sequester the path as we will get additional tokens
670 //
671  path = val;
672 
673 // Record any parms
674 //
675  if (!Config.GetRest(parms, sizeof(parms)))
676  {Eroute.Emsg("Config", "entitylib parameters too long"); return 1;}
677 
678 // Check if we have a plugin info object (we will need one for this)
679 //
680  if (!pinInfo) pinInfo = new XrdSecPinInfo("sec.entitylib",configFN,Eroute);
681 
682 // Add the plugin
683 //
684  pinInfo->KingPin.Add(path.c_str(), (*parms ? parms : 0), push);
685 
686 // All done
687 //
688  return 0;
689 }
690 
691 /******************************************************************************/
692 /* x l e v e l */
693 /******************************************************************************/
694 
695 /* Function: xlevel
696 
697  Purpose: To parse the directive: level [<type>] [relaxed] <level> [force]
698 
699  <type> all | local | remote
700  <level> none | compatible | standard | intense | pedantic
701 
702  Output: 0 upon success or !0 upon failure.
703 */
704 
705 int XrdSecServer::xlevel(XrdOucStream &Config, XrdSysError &Eroute)
706 {
707  struct lvltab {const char *lname; XrdSecProtectParms::secLevel lvl;} ltab[] =
708  {{"none", XrdSecProtectParms::secNone},
709  {"compatible", XrdSecProtectParms::secCompatible},
710  {"standard", XrdSecProtectParms::secStandard},
711  {"intense", XrdSecProtectParms::secIntense},
712  {"pedantic", XrdSecProtectParms::secPedantic}
713  };
714  int i, numopts = sizeof(ltab)/sizeof(struct lvltab);
715  bool isLcl = true, isRmt = true, isSpec = false, isRlx = false, isFRC=false;
716  char *val;
717 
718 // Get the template host
719 //
720  val = Config.GetWord();
721  if (!val || !val[0])
722  {Eroute.Emsg("Config","level not specified"); return 1;}
723 
724 // Check for optional keyword
725 //
726  if (!strcmp(val, "all")) isSpec = true;
727  else if (!strcmp(val, "local")) {isSpec = true; isRmt = false;}
728  else if (!strcmp(val, "remote")){isSpec = true; isLcl = false;}
729 
730 // Check if we need another token
731 //
732  if (isSpec)
733  {val = Config.GetWord();
734  if (!val || !val[0])
735  {Eroute.Emsg("Config","level not specified"); return 1;}
736  }
737 
738 // Check for optional relaxed keyword
739 //
740  if (!strcmp(val, "relaxed"))
741  {isRlx = true;
742  val = Config.GetWord();
743  if (!val || !val[0])
744  {Eroute.Emsg("Config","level not specified"); return 1;}
745  }
746 
747 // Get the level
748 //
749  for (i = 0; i < numopts; i++) if (!strcmp(ltab[i].lname, val)) break;
750  if (i >= numopts)
751  {Eroute.Emsg("Config", "invalid level option -", val); return 1;}
752 
753 // Check for final keyword
754 //
755  val = Config.GetWord();
756  if (val && val[0])
757  {if (strcmp(val, "force"))
758  {Eroute.Emsg("Config","invalid level modifier - ", val); return 1;}
759  isFRC = true;
760  }
761 
762 // Set appropriate levels
763 //
764  if (isLcl)
765  {lclParms.level = ltab[i].lvl;
766  if (isRlx) lclParms.opts |= XrdSecProtectParms::relax;
767  else lclParms.opts &= ~XrdSecProtectParms::relax;
768  if (isFRC) lclParms.opts |= XrdSecProtectParms::force;
769  else lclParms.opts &= ~XrdSecProtectParms::force;
770  }
771  if (isRmt)
772  {rmtParms.level = ltab[i].lvl;
773  if (isRlx) rmtParms.opts |= XrdSecProtectParms::relax;
774  else rmtParms.opts &= ~XrdSecProtectParms::relax;
775  if (isFRC) rmtParms.opts |= XrdSecProtectParms::force;
776  else rmtParms.opts &= ~XrdSecProtectParms::force;
777  }
778  return 0;
779 }
780 
781 /******************************************************************************/
782 /* x p b i n d */
783 /******************************************************************************/
784 
785 /* Function: xpbind
786 
787  Purpose: To parse the directive: protbind <thost> [none | [only] <plist>]
788 
789  <thost> is a templated host name (e.g., bronco*.slac.stanford.edu)
790  <plist> are the protocols to be bound to the <thost>. A special
791  protocol, none, indicates that no token is to be passed.
792 
793  Output: 0 upon success or !0 upon failure.
794 */
795 
796 int XrdSecServer::xpbind(XrdOucStream &Config, XrdSysError &Eroute)
797 {
798  EPNAME("xpbind")
799  char *val, *thost;
800  XrdSecProtBind *bnow;
801  char sectoken[4096], *secbuff = sectoken;
802  int isdflt = 0, only = 0, anyprot = 0, noprot = 0, phost = 0;
803  int sectlen = sizeof(sectoken)-1;
804  XrdSecPMask_t PMask = 0;
805  *secbuff = '\0';
806 
807 // Get the template host
808 //
809  val = Config.GetWord();
810  if (!val || !val[0])
811  {Eroute.Emsg("Config","protbind host not specified"); return 1;}
812 
813 // Verify that this host has not been bound before
814 //
815  if ((isdflt = !strcmp("*", val))) bnow = bpDefault;
816  else {bnow = bpFirst;
817  while(bnow) if (!strcmp(bnow->thost, val)) break;
818  else bnow = bnow->next;
819  }
820  if (bnow) {Eroute.Emsg("Config","duplicate protbind definition - ", val);
821  return 1;
822  }
823  thost = strdup(val);
824 
825 // Now get each protocol to be used (there must be one).
826 //
827  while((val = Config.GetWord()))
828  {if (!strcmp(val, "none")) {noprot = 1; break;}
829  if (!strcmp(val, "only")) {only = 1; Enforce = true;}
830  else if (!strcmp(val, "host")) {phost = 1; anyprot = 1;}
831  else if (!PManager.Find(val))
832  {Eroute.Emsg("Config","protbind", val,
833  "protocol not previously defined.");
834  return 1;
835  }
836  else if (add2token(Eroute, val, &secbuff, sectlen, PMask))
837  {Eroute.Emsg("Config","Unable to bind protocols to",thost);
838  return 1;
839  } else anyprot = 1;
840  }
841 
842 // Verify that no conflicts arose
843 //
844  if (val && (val = Config.GetWord()))
845  {Eroute.Emsg("Config","conflicting protbind:", thost, val);
846  return 1;
847  }
848 
849 // Make sure we have some protocols bound to this host
850 //
851  if (!(anyprot || noprot))
852  {Eroute.Emsg("Config","no protocols bound to", thost); return 1;}
853  DEBUG("XrdSecConfig: Bound "<< thost<< " to "
854  << (noprot ? "none" : (phost ? "host" : sectoken)));
855 
856 // Issue warning if the host protocol was bound to this host but other
857 // protocols were also bound, making them rather useless.
858 //
859  if (phost && *sectoken)
860  {Eroute.Say("Config warning: 'protbind", thost,
861  "host' negates all other bound protocols.");
862  *sectoken = '\0';
863  }
864 
865 // Translate "localhost" to our local hostname, if possible.
866 //
867  if (!strcmp("localhost", thost))
868  {XrdNetAddr myIPAddr(0);
869  free(thost);
870  thost = strdup(myIPAddr.Name("localhost"));
871  }
872 
873 // Create new bind object
874 //
875  bnow = new XrdSecProtBind(thost,(noprot ? 0:sectoken),(only ? PMask:0));
876 
877 // Push the entry onto our bindings
878 //
879  if (isdflt) bpDefault = bnow;
880  else {if (bpLast) bpLast->next = bnow;
881  else bpFirst = bnow;
882  bpLast = bnow;
883  }
884 
885 // All done
886 //
887  return 0;
888 }
889 
890 /******************************************************************************/
891 /* x p r o t */
892 /******************************************************************************/
893 
894 /* Function: xprot
895 
896  Purpose: To parse the directive: protocol [<path>] <pid> [ <opts> ]
897 
898  <path> is the absolute path where the protocol library resides
899  <pid> is the 1-to-8 character protocol id.
900  <opts> are the associated protocol specific options such as:
901  noipcheck - don't check ip address origin
902  keyfile <kfn> - the key file associated with protocol
903  args <args> - associated non-blank arguments
904  Additional arguments may be passed to the protocol using the
905  protargs directive. ALl protargs directives must appear
906  prior to the protocol directive for the given protocol.
907 
908  Output: 0 upon success or !0 upon failure.
909 */
910 
911 int XrdSecServer::xprot(XrdOucStream &Config, XrdSysError &Eroute)
912 {
913  XrdSecProtParm *pp, myParms(&Eroute, "protocol");
914  char *pap, *val, pid[XrdSecPROTOIDSIZE+1], *args = 0;
915  char pathbuff[1024], *path = 0;
916  int psize;
917  XrdOucErrInfo erp;
918  XrdSecPMask_t mymask = 0;
919 
920 // Get the protocol id
921 //
922  val = Config.GetWord();
923  if (val && *val == '/')
924  {strlcpy(pathbuff, val, sizeof(pathbuff)); path = pathbuff;
925  val = Config.GetWord();
926  }
927  if (!val || !val[0])
928  {Eroute.Emsg("Config","protocol id not specified"); return 1;}
929 
930 // Verify that we don't have this protocol
931 //
932  if (strlen(val) > XrdSecPROTOIDSIZE)
933  {Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
934 
935  if (PManager.Find(val))
936  {Eroute.Say("Config warning: protocol ",val," previously defined.");
937  strcpy(pid, val);
938  return add2token(Eroute, pid, &STBuff, STBlen, mymask);
939  }
940 
941 // Add this protocol to the list of protocols that have been defined
942 //
943  char pName[XrdSecPROTOIDSIZE+2];
944  *pName = ':';
945  strcpy(pName+1, val);
946  if (!pidList) pidList = strdup(pName);
947  else {std::string pids = pidList;
948  pids.append(pName);
949  free(pidList);
950  pidList = strdup(pids.c_str());
951  }
952 
953 // The builtin host protocol does not accept any parameters. Additionally, the
954 // host protocol negates any other protocols we may have in the default set.
955 //
956  if (!strcmp("host", val))
957  {if (Config.GetWord())
958  {Eroute.Emsg("Config", "Builtin host protocol does not accept parms.");
959  return 1;
960  }
961  implauth = true;
962  return 0;
963  }
964 
965 // Grab additional parameters that we here and that we have accumulated
966 //
967  strcpy(pid, val);
968  while((args = Config.GetWord())) if (!myParms.Cat(args)) return 1;
969  if ((pp = myParms.Find(pid, 1)))
970  {if ((*myParms.Result(psize) && !myParms.Insert('\n'))
971  || !myParms.Cat(pp->Result(psize))) return 1;
972  else delete pp;
973  }
974 
975 // Load this protocol
976 //
977  pap = myParms.Result(psize);
978  if (!PManager.Load(&erp, 's', pid, (psize ? pap : 0), path))
979  {if (*(erp.getErrText())) Eroute.Say(erp.getErrText());
980  Eroute.Say("Config Failed to load ", pid, " authentication protocol!");
981  return 1;
982  }
983 
984 // Add this protocol to the default security token
985 //
986  return add2token(Eroute, pid, &STBuff, STBlen, mymask);
987 }
988 
989 /******************************************************************************/
990 /* x p p a r m */
991 /******************************************************************************/
992 
993 /* Function: xpparm
994 
995  Purpose: To parse the directive: protparm <prot> <args>
996 
997  <prot> is the name of the protocol to which these args apply.
998  <args> are the protocol specific parameters. The remaing tokens
999  on the line will be passed to the protocol at during
1000  protocol initialization. Each such line is separated by
1001  a new line character.
1002 
1003  Output: 0 upon success or !0 upon failure.
1004 */
1005 
1006 int XrdSecServer::xpparm(XrdOucStream &Config, XrdSysError &Eroute)
1007 {
1008  XrdSecProtParm *pp;
1009  char *val, pid[XrdSecPROTOIDSIZE+1];
1010 
1011 // Get the protocol name
1012 //
1013  val = Config.GetWord();
1014  if (!val || !val[0])
1015  {Eroute.Emsg("Config","protparm protocol not specified"); return 1;}
1016 
1017 // The builtin host protocol does not accept any parameters
1018 //
1019  if (!strcmp("host", val))
1020  {Eroute.Emsg("Config", "Builtin host protocol does not accept protparms.");
1021  return 1;
1022  }
1023 
1024 // Verify that we don't have this protocol
1025 //
1026  if (strlen(val) > XrdSecPROTOIDSIZE)
1027  {Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
1028 
1029  if (PManager.Find(val))
1030  {Eroute.Emsg("Config warning: protparm protocol ",val," already defined.");
1031  return 0;
1032  }
1033 
1034  strcpy(pid, val);
1035 
1036 // Make sure we have at least one parameter here
1037 //
1038  if (!(val = Config.GetWord()))
1039  {Eroute.Emsg("Config","protparm", pid, "parameter not specified");
1040  return 1;
1041  }
1042 
1043 // Try to find a previous incarnation of this parm
1044 //
1045  if ((pp = XrdSecProtParm::Find(pid))) {if (!pp->Insert('\n')) return 1;}
1046  else {pp = new XrdSecProtParm(&Eroute, "protparm");
1047  pp->setProt(pid);
1048  pp->Add();
1049  }
1050 
1051 // Grab the options for the protocol. They are pretty much opaque to us here
1052 //
1053  do {if (!pp->Cat(val)) return 1;} while((val = Config.GetWord()));
1054  return 0;
1055 }
1056 
1057 /******************************************************************************/
1058 /* x t r a c e */
1059 /******************************************************************************/
1060 
1061 /* Function: xtrace
1062 
1063  Purpose: To parse the directive: trace <events>
1064 
1065  <events> the blank separated list of events to trace. Trace
1066  directives are cummalative.
1067 
1068  Output: 0 upon success or !0 upon failure.
1069 */
1070 
1071 int XrdSecServer::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
1072 {
1073  static struct traceopts {const char *opname; int opval;} tropts[] =
1074  {
1075  {"all", TRACE_ALL},
1076  {"debug", TRACE_Debug},
1077  {"auth", TRACE_Authen},
1078  {"authentication", TRACE_Authen}
1079  };
1080  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
1081  char *val;
1082 
1083  val = Config.GetWord();
1084  if (!val || !val[0])
1085  {Eroute.Emsg("Config", "trace option not specified"); return 1;}
1086  while (val && val[0])
1087  {if (!strcmp(val, "off")) trval = 0;
1088  else {if ((neg = (val[0] == '-' && val[1]))) val++;
1089  for (i = 0; i < numopts; i++)
1090  {if (!strcmp(val, tropts[i].opname))
1091  {if (neg) trval &= ~tropts[i].opval;
1092  else trval |= tropts[i].opval;
1093  break;
1094  }
1095  }
1096  if (i >= numopts)
1097  Eroute.Say("Config warning: ignoring invalid trace option '", val, "'.");
1098  }
1099  val = Config.GetWord();
1100  }
1101 
1102  SecTrace->What = (SecTrace->What & ~TRACE_Authenxx) | trval;
1103 
1104 // Propogate the debug option
1105 //
1106 #ifndef NODEBUG
1107  if (QTRACE(Debug)) PManager.setDebug(1);
1108  else PManager.setDebug(0);
1109 #endif
1110  return 0;
1111 }
1112 
1113 /******************************************************************************/
1114 /* M i s c e l l a n e o u s */
1115 /******************************************************************************/
1116 /******************************************************************************/
1117 /* a d d 2 t o k e n */
1118 /******************************************************************************/
1119 
1120 int XrdSecServer::add2token(XrdSysError &Eroute, char *pid,
1121  char **tokbuff, int &toklen, XrdSecPMask_t &pmask)
1122 {
1123  int i;
1124  char *pargs;
1125  XrdSecPMask_t protnum;
1126 
1127 // Find the protocol argument string
1128 //
1129  if (!(protnum = PManager.Find(pid, &pargs)))
1130  {Eroute.Emsg("Config","Protocol",pid,"not found after being added!");
1131  return 1;
1132  }
1133 
1134 // Make sure we have enough room to add
1135 //
1136  i = 4+strlen(pid)+strlen(pargs);
1137  if (i >= toklen)
1138  {Eroute.Emsg("Config","Protocol",pid,"parms exceed overall maximum!");
1139  return 1;
1140  }
1141 
1142 // Insert protocol specification (we already checked for an overflow)
1143 //
1144  i = sprintf(*tokbuff, "&P=%s%s%s", pid, (*pargs ? "," : ""), pargs);
1145  toklen -= i;
1146  *tokbuff += i;
1147  pmask |= protnum;
1148  return 0;
1149 }
1150 
1151 /******************************************************************************/
1152 /* P r o t B i n d _ C o m p l e t e */
1153 /******************************************************************************/
1154 
1155 int XrdSecServer::ProtBind_Complete(XrdSysError &Eroute)
1156 {
1157  EPNAME("ProtBind_Complete")
1158  XrdOucErrInfo erp;
1159 
1160 // Check if we have a default token, create one otherwise
1161 //
1162  if (!bpDefault)
1163  {if (!*SToken) {Eroute.Say("Config warning: No protocols defined; "
1164  "only host authentication available.");
1165  implauth = true;
1166  }
1167  else if (implauth)
1168  {Eroute.Say("Config warning: enabled builtin host "
1169  "protocol negates default use of any other protocols.");
1170  *SToken = '\0';
1171  }
1172  bpDefault = new XrdSecProtBind(strdup("*"), SToken);
1173  DEBUG("Default sectoken built: '" <<SToken <<"'");
1174  }
1175 
1176 // Add the host protocol to the set at this point to allow clients to
1177 // actually give use "host" as a protocol id if it's allowed. We do this so
1178 // that the right error message is generated. Otherwise, it ignored.
1179 //
1180  if (implauth && !PManager.Load(&erp, 's', "host", 0, 0))
1181  {Eroute.Emsg("Config", erp.getErrText()); return 1;}
1182 
1183 // Free up the constructed default sectoken
1184 //
1185  free(SToken); SToken = STBuff = 0; STBlen = 0;
1186  return 0;
1187 }
1188 
1189 /******************************************************************************/
1190 /* X r d S e c g e t S e r v i c e */
1191 /******************************************************************************/
1192 
1193 extern "C"
1194 {
1196 {
1197  XrdSecServer *SecServer = new XrdSecServer(lp);
1198 
1199 // Configure the server object
1200 //
1201  if (SecServer->Configure(cfn)) return 0;
1202 
1203 // Return the server object
1204 //
1205  return (XrdSecService *)SecServer;
1206 }
1207 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define TRACE_Debug
Definition: XrdCmsTrace.hh:37
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
static XrdSysError eDest(0,"crypto_")
int open(const char *path, int oflag,...)
#define XrdSecPROTOIDSIZE
Definition: XrdSecEntity.hh:47
XrdSecProtector * XrdSecLoadProtection(XrdSysError &erP)
int XrdSecPMask_t
#define EAUTH
Definition: XrdSecServer.cc:58
#define TS_Xeq(x, m)
XrdSecService * XrdSecgetService(XrdSysLogger *lp, const char *cfn)
#define TRACE_Authen
Definition: XrdSecTrace.hh:62
#define TRACE_Authenxx
Definition: XrdSecTrace.hh:61
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE_ALL
Definition: XrdTrace.hh:35
static const int noPort
Do not add port number.
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtAuto
Hostname if already resolved o/w use fmtAddr.
const char * Name(const char *eName=0, const char **eText=0)
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
const char * getErrText()
int setErrInfo(int code, const char *emsg)
XrdSecPMask_t Find(const char *pid, char **parg=0)
XrdSecProtocol * Get(const char *hname, XrdNetAddrInfo &endPoint, const char *pname, XrdOucErrInfo *erp)
int Load(XrdOucErrInfo *eMsg, const char pmode, const char *pid, const char *parg, const char *path)
void setErrP(XrdSysError *eP)
void setDebug(int dbg)
XrdOucEnv theEnv
Definition: XrdSecServer.cc:89
XrdSecPinInfo(const char *drctv, const char *cfn, XrdSysError &errR)
Definition: XrdSecServer.cc:83
XrdOucPinKing< XrdSecEntityPin > KingPin
Definition: XrdSecServer.cc:81
int Match(const char *hname)
XrdSecProtBind * next
Definition: XrdSecServer.cc:99
XrdSecPMask_t ValidProts
XrdSecProtBind(char *th, char *st, XrdSecPMask_t pmask=0)
XrdSecProtBind * Find(const char *hname)
XrdSecParameters SecToken
char ProtoID[XrdSecPROTOIDSIZE+1]
static XrdSecProtParm * Find(char *pid, int remove=0)
XrdSecProtParm(XrdSysError *erp, const char *cid)
XrdSecProtParm * Next
int Insert(char oct)
int Cat(char *token)
static XrdSecProtParm * First
int isProto(char *proto)
char * Result(int &size)
void setProt(char *pid)
static const int relax
relax old clients
secLevel level
In: The desired level.
static const int force
Allow unencryted hash.
int opts
In: Options:
virtual bool Config(const XrdSecProtectParms &lclParms, const XrdSecProtectParms &rmtParms, XrdSysLogger &logr)
virtual const char * LName(XrdSecProtectParms::secLevel level)
XrdSecProtocol * getProtocol(const char *host, XrdNetAddrInfo &endPoint, const XrdSecCredentials *cred, XrdOucErrInfo &einfo)
const char * getParms(int &size, XrdNetAddrInfo *endPoint=0)
XrdSecServer(XrdSysLogger *lp)
int Configure(const char *cfn)
bool PostProcess(XrdSecEntity &entity, XrdOucErrInfo &einfo)
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
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdCmsConfig Config
@ oct
Definition: XrdSysTrace.hh:42
Generic structure to pass security information back and forth.
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.