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
220XrdSysError *eDest;
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 }
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
911int 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
1006int 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
1071int 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
1120int 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
1155int 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
1193extern "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 EAUTH
#define DEBUG(x)
#define EPNAME(x)
#define TRACE_Debug
#define QTRACE(act)
#define TS_Xeq(x, m)
Definition XrdConfig.cc:155
static XrdSysError eDest(0,"crypto_")
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
#define open
Definition XrdPosix.hh:71
#define XrdSecPROTOIDSIZE
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)
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
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
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)
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)
XrdSysLogger * logger(XrdSysLogger *lp=0)
XrdCmsConfig Config
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.