XRootD
Loading...
Searching...
No Matches
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
45#include "XrdSys/XrdSysError.hh"
46#include "XrdOuc/XrdOucEnv.hh"
49#include "XrdNet/XrdNetAddr.hh"
50
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
65namespace
66{
67XrdSecProtectParms lclParms;
68XrdSecProtectParms rmtParms;
69
70XrdVERSIONINFODEF(myVer, XrdSec, XrdVNUMBER, XrdVERSION);
71}
72
73/******************************************************************************/
74/* X r d S e c P i n I n f o */
75/******************************************************************************/
76
78{
79public:
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{
98public:
100char *thost;
106
107XrdSecProtBind *Find(const char *hname);
108
109int 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
159int 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{
187public:
188
189 void Add() {Next = First; First = this;}
190
191 int Cat(char *token);
192
193static 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);}
218private:
219
221int bsize;
222char *buff;
223char *bp;
224const char *who;
225};
226
228
229/******************************************************************************/
230/* C a t */
231/******************************************************************************/
232
233int 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
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
282XrdSecPManager 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
317const 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
441int 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
534int 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
611int 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
644int 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
705int XrdSecServer::xlevel(XrdOucStream &Config, XrdSysError &Eroute)
706{
707 struct lvltab {const char *lname; XrdSecProtectParms::secLevel lvl;} ltab[] =
709 {"compatible", XrdSecProtectParms::secCompatible},
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
796int 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 } else if (!strcmp("=localhost", thost) || !strcmp("loopback", thost))
872 {free(thost);
873 thost = strdup("localhost");
874 }
875
876// Create new bind object
877//
878 bnow = new XrdSecProtBind(thost,(noprot ? 0:sectoken),(only ? PMask:0));
879
880// Push the entry onto our bindings
881//
882 if (isdflt) bpDefault = bnow;
883 else {if (bpLast) bpLast->next = bnow;
884 else bpFirst = bnow;
885 bpLast = bnow;
886 }
887
888// All done
889//
890 return 0;
891}
892
893/******************************************************************************/
894/* x p r o t */
895/******************************************************************************/
896
897/* Function: xprot
898
899 Purpose: To parse the directive: protocol [<path>] <pid> [ <opts> ]
900
901 <path> is the absolute path where the protocol library resides
902 <pid> is the 1-to-8 character protocol id.
903 <opts> are the associated protocol specific options such as:
904 noipcheck - don't check ip address origin
905 keyfile <kfn> - the key file associated with protocol
906 args <args> - associated non-blank arguments
907 Additional arguments may be passed to the protocol using the
908 protargs directive. ALl protargs directives must appear
909 prior to the protocol directive for the given protocol.
910
911 Output: 0 upon success or !0 upon failure.
912*/
913
914int XrdSecServer::xprot(XrdOucStream &Config, XrdSysError &Eroute)
915{
916 XrdSecProtParm *pp, myParms(&Eroute, "protocol");
917 char *pap, *val, pid[XrdSecPROTOIDSIZE+1], *args = 0;
918 char pathbuff[1024], *path = 0;
919 int psize;
920 XrdOucErrInfo erp;
921 XrdSecPMask_t mymask = 0;
922
923// Get the protocol id
924//
925 val = Config.GetWord();
926 if (val && *val == '/')
927 {strlcpy(pathbuff, val, sizeof(pathbuff)); path = pathbuff;
928 val = Config.GetWord();
929 }
930 if (!val || !val[0])
931 {Eroute.Emsg("Config","protocol id not specified"); return 1;}
932
933// Verify that we don't have this protocol
934//
935 if (strlen(val) > XrdSecPROTOIDSIZE)
936 {Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
937
938 if (PManager.Find(val))
939 {Eroute.Say("Config warning: protocol ",val," previously defined.");
940 strcpy(pid, val);
941 return add2token(Eroute, pid, &STBuff, STBlen, mymask);
942 }
943
944// Add this protocol to the list of protocols that have been defined
945//
946 char pName[XrdSecPROTOIDSIZE+2];
947 *pName = ':';
948 strcpy(pName+1, val);
949 if (!pidList) pidList = strdup(pName);
950 else {std::string pids = pidList;
951 pids.append(pName);
952 free(pidList);
953 pidList = strdup(pids.c_str());
954 }
955
956// The builtin host protocol does not accept any parameters. Additionally, the
957// host protocol negates any other protocols we may have in the default set.
958//
959 if (!strcmp("host", val))
960 {if (Config.GetWord())
961 {Eroute.Emsg("Config", "Builtin host protocol does not accept parms.");
962 return 1;
963 }
964 implauth = true;
965 return 0;
966 }
967
968// Grab additional parameters that we here and that we have accumulated
969//
970 strcpy(pid, val);
971 while((args = Config.GetWord())) if (!myParms.Cat(args)) return 1;
972 if ((pp = myParms.Find(pid, 1)))
973 {if ((*myParms.Result(psize) && !myParms.Insert('\n'))
974 || !myParms.Cat(pp->Result(psize))) return 1;
975 else delete pp;
976 }
977
978// Load this protocol
979//
980 pap = myParms.Result(psize);
981 if (!PManager.Load(&erp, 's', pid, (psize ? pap : 0), path))
982 {if (*(erp.getErrText())) Eroute.Say(erp.getErrText());
983 Eroute.Say("Config Failed to load ", pid, " authentication protocol!");
984 return 1;
985 }
986
987// Add this protocol to the default security token
988//
989 return add2token(Eroute, pid, &STBuff, STBlen, mymask);
990}
991
992/******************************************************************************/
993/* x p p a r m */
994/******************************************************************************/
995
996/* Function: xpparm
997
998 Purpose: To parse the directive: protparm <prot> <args>
999
1000 <prot> is the name of the protocol to which these args apply.
1001 <args> are the protocol specific parameters. The remaing tokens
1002 on the line will be passed to the protocol at during
1003 protocol initialization. Each such line is separated by
1004 a new line character.
1005
1006 Output: 0 upon success or !0 upon failure.
1007*/
1008
1009int XrdSecServer::xpparm(XrdOucStream &Config, XrdSysError &Eroute)
1010{
1011 XrdSecProtParm *pp;
1012 char *val, pid[XrdSecPROTOIDSIZE+1];
1013
1014// Get the protocol name
1015//
1016 val = Config.GetWord();
1017 if (!val || !val[0])
1018 {Eroute.Emsg("Config","protparm protocol not specified"); return 1;}
1019
1020// The builtin host protocol does not accept any parameters
1021//
1022 if (!strcmp("host", val))
1023 {Eroute.Emsg("Config", "Builtin host protocol does not accept protparms.");
1024 return 1;
1025 }
1026
1027// Verify that we don't have this protocol
1028//
1029 if (strlen(val) > XrdSecPROTOIDSIZE)
1030 {Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
1031
1032 if (PManager.Find(val))
1033 {Eroute.Emsg("Config warning: protparm protocol ",val," already defined.");
1034 return 0;
1035 }
1036
1037 strcpy(pid, val);
1038
1039// Make sure we have at least one parameter here
1040//
1041 if (!(val = Config.GetWord()))
1042 {Eroute.Emsg("Config","protparm", pid, "parameter not specified");
1043 return 1;
1044 }
1045
1046// Try to find a previous incarnation of this parm
1047//
1048 if ((pp = XrdSecProtParm::Find(pid))) {if (!pp->Insert('\n')) return 1;}
1049 else {pp = new XrdSecProtParm(&Eroute, "protparm");
1050 pp->setProt(pid);
1051 pp->Add();
1052 }
1053
1054// Grab the options for the protocol. They are pretty much opaque to us here
1055//
1056 do {if (!pp->Cat(val)) return 1;} while((val = Config.GetWord()));
1057 return 0;
1058}
1059
1060/******************************************************************************/
1061/* x t r a c e */
1062/******************************************************************************/
1063
1064/* Function: xtrace
1065
1066 Purpose: To parse the directive: trace <events>
1067
1068 <events> the blank separated list of events to trace. Trace
1069 directives are cummalative.
1070
1071 Output: 0 upon success or !0 upon failure.
1072*/
1073
1074int XrdSecServer::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
1075{
1076 static struct traceopts {const char *opname; int opval;} tropts[] =
1077 {
1078 {"all", TRACE_ALL},
1079 {"debug", TRACE_Debug},
1080 {"auth", TRACE_Authen},
1081 {"authentication", TRACE_Authen}
1082 };
1083 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
1084 char *val;
1085
1086 val = Config.GetWord();
1087 if (!val || !val[0])
1088 {Eroute.Emsg("Config", "trace option not specified"); return 1;}
1089 while (val && val[0])
1090 {if (!strcmp(val, "off")) trval = 0;
1091 else {if ((neg = (val[0] == '-' && val[1]))) val++;
1092 for (i = 0; i < numopts; i++)
1093 {if (!strcmp(val, tropts[i].opname))
1094 {if (neg) trval &= ~tropts[i].opval;
1095 else trval |= tropts[i].opval;
1096 break;
1097 }
1098 }
1099 if (i >= numopts)
1100 Eroute.Say("Config warning: ignoring invalid trace option '", val, "'.");
1101 }
1102 val = Config.GetWord();
1103 }
1104
1105 SecTrace->What = (SecTrace->What & ~TRACE_Authenxx) | trval;
1106
1107// Propogate the debug option
1108//
1109#ifndef NODEBUG
1110 if (QTRACE(Debug)) PManager.setDebug(1);
1111 else PManager.setDebug(0);
1112#endif
1113 return 0;
1114}
1115
1116/******************************************************************************/
1117/* M i s c e l l a n e o u s */
1118/******************************************************************************/
1119/******************************************************************************/
1120/* a d d 2 t o k e n */
1121/******************************************************************************/
1122
1123int XrdSecServer::add2token(XrdSysError &Eroute, char *pid,
1124 char **tokbuff, int &toklen, XrdSecPMask_t &pmask)
1125{
1126 int i;
1127 char *pargs;
1128 XrdSecPMask_t protnum;
1129
1130// Find the protocol argument string
1131//
1132 if (!(protnum = PManager.Find(pid, &pargs)))
1133 {Eroute.Emsg("Config","Protocol",pid,"not found after being added!");
1134 return 1;
1135 }
1136
1137// Make sure we have enough room to add
1138//
1139 i = 4+strlen(pid)+strlen(pargs);
1140 if (i >= toklen)
1141 {Eroute.Emsg("Config","Protocol",pid,"parms exceed overall maximum!");
1142 return 1;
1143 }
1144
1145// Insert protocol specification (we already checked for an overflow)
1146//
1147 i = sprintf(*tokbuff, "&P=%s%s%s", pid, (*pargs ? "," : ""), pargs);
1148 toklen -= i;
1149 *tokbuff += i;
1150 pmask |= protnum;
1151 return 0;
1152}
1153
1154/******************************************************************************/
1155/* P r o t B i n d _ C o m p l e t e */
1156/******************************************************************************/
1157
1158int XrdSecServer::ProtBind_Complete(XrdSysError &Eroute)
1159{
1160 EPNAME("ProtBind_Complete")
1161 XrdOucErrInfo erp;
1162
1163// Check if we have a default token, create one otherwise
1164//
1165 if (!bpDefault)
1166 {if (!*SToken) {Eroute.Say("Config warning: No protocols defined; "
1167 "only host authentication available.");
1168 implauth = true;
1169 }
1170 else if (implauth)
1171 {Eroute.Say("Config warning: enabled builtin host "
1172 "protocol negates default use of any other protocols.");
1173 *SToken = '\0';
1174 }
1175 bpDefault = new XrdSecProtBind(strdup("*"), SToken);
1176 DEBUG("Default sectoken built: '" <<SToken <<"'");
1177 }
1178
1179// Add the host protocol to the set at this point to allow clients to
1180// actually give use "host" as a protocol id if it's allowed. We do this so
1181// that the right error message is generated. Otherwise, it ignored.
1182//
1183 if (implauth && !PManager.Load(&erp, 's', "host", 0, 0))
1184 {Eroute.Emsg("Config", erp.getErrText()); return 1;}
1185
1186// Free up the constructed default sectoken
1187//
1188 free(SToken); SToken = STBuff = 0; STBlen = 0;
1189 return 0;
1190}
1191
1192/******************************************************************************/
1193/* X r d S e c g e t S e r v i c e */
1194/******************************************************************************/
1195
1196extern "C"
1197{
1199{
1200 XrdSecServer *SecServer = new XrdSecServer(lp);
1201
1202// Configure the server object
1203//
1204 if (SecServer->Configure(cfn)) return 0;
1205
1206// Return the server object
1207//
1208 return (XrdSecService *)SecServer;
1209}
1210}
#define EAUTH
#define DEBUG(x)
#define EPNAME(x)
#define TRACE_Debug
#define QTRACE(act)
#define TS_Xeq(x, m)
Definition XrdConfig.cc:160
XrdSysError eDest(0, "HttpMon")
#define open
Definition XrdPosix.hh:78
#define XrdSecPROTOIDSIZE
XrdSecBuffer XrdSecParameters
XrdSecBuffer XrdSecCredentials
XrdSecProtector * XrdSecLoadProtection(XrdSysError &erP)
int XrdSecPMask_t
XrdSecService * XrdSecgetService(XrdSysLogger *lp, const char *cfn)
#define TRACE_Authen
bool Debug
if(ec< 0) ec
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:170
void Put(const char *varname, const char *value)
Definition XrdOucEnv.hh:85
const char * getErrText()
int setErrInfo(int code, const char *emsg)
XrdOucTrace(XrdSysError *erp)
XrdOucEnv theEnv
XrdSecPinInfo(const char *drctv, const char *cfn, XrdSysError &errR)
XrdOucPinKing< XrdSecEntityPin > KingPin
int Match(const char *hname)
XrdSecProtBind * next
XrdSecPMask_t ValidProts
XrdSecProtBind(char *th, char *st, XrdSecPMask_t pmask=0)
XrdSecProtBind * Find(const char *hname)
XrdSecParameters SecToken
char * Result(int &size)
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)
void setProt(char *pid)
static const int relax
relax old clients
static const int force
Allow unencryted hash.
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)
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)
XrdCmsConfig Config
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.