/***************************************************************************/
/* */
/* X r d S e c S e r v e r . c c */
/* */
/* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "XrdVersion.hh"
#include "XrdSys/XrdSysLogger.hh"
#include "XrdSys/XrdSysHeaders.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucErrInfo.hh"
#include "XrdNet/XrdNetAddr.hh"
#include "XrdSec/XrdSecInterface.hh"
#include "XrdSec/XrdSecProtector.hh"
#include "XrdSec/XrdSecServer.hh"
#include "XrdSec/XrdSecTrace.hh"
/******************************************************************************/
/* S e c u r i t y L e v e l s */
/******************************************************************************/
namespace
{
XrdSecProtectParms lclParms;
XrdSecProtectParms rmtParms;
}
/******************************************************************************/
/* X r d S e c P r o t B i n d */
/******************************************************************************/
class XrdSecProtBind
{
public:
XrdSecProtBind *next;
char *thost;
int tpfxlen;
char *thostsfx;
int tsfxlen;
XrdSecParameters SecToken;
XrdSecPMask_t ValidProts;
XrdSecProtBind *Find(const char *hname);
int Match(const char *hname);
XrdSecProtBind(char *th, char *st, XrdSecPMask_t pmask=0);
~XrdSecProtBind()
{free(thost);
if (SecToken.buffer) free(SecToken.buffer);
}
};
/******************************************************************************/
/* C o n s t r u c t o r */
/******************************************************************************/
XrdSecProtBind::XrdSecProtBind(char *th, char *st, XrdSecPMask_t pmask)
{
char *starp;
next = 0;
thost = th;
if (!(starp = index(thost, '*')))
{tsfxlen = -1;
thostsfx = (char *)0;
tpfxlen = 0;
} else {
*starp = '\0';
tpfxlen = strlen(thost);
thostsfx = starp+1;
tsfxlen = strlen(thostsfx);
}
if (st) {SecToken.buffer = strdup(st); SecToken.size = strlen(st);}
else {SecToken.buffer = 0; SecToken.size = 0;}
ValidProts = (pmask ? pmask : ~(XrdSecPMask_t)0);
}
/******************************************************************************/
/* F i n d */
/******************************************************************************/
XrdSecProtBind *XrdSecProtBind::Find(const char *hname)
{
XrdSecProtBind *bp = this;
while(bp && !bp->Match(hname)) bp = bp->next;
return bp;
}
/******************************************************************************/
/* M a t c h */
/******************************************************************************/
int XrdSecProtBind::Match(const char *hname)
{
int i;
// If an exact match wanted, return the result
//
if (tsfxlen < 0) return !strcmp(thost, hname);
// Try to match the prefix
//
if (tpfxlen && strncmp(thost, hname, tpfxlen)) return 0;
// If no suffix matching is wanted, then we have succeeded
//
if (!(thostsfx)) return 1;
// Try to match the suffix
//
if ((i = (strlen(hname) - tsfxlen)) < 0) return 0;
return !strcmp(&hname[i], thostsfx);
}
/******************************************************************************/
/* X r d S e c P r o t P a r m */
/******************************************************************************/
class XrdSecProtParm
{
public:
void Add() {Next = First; First = this;}
int Cat(char *token);
static XrdSecProtParm *Find(char *pid, int remove=0);
int Insert(char oct);
int isProto(char *proto) {return !strcmp(ProtoID, proto);}
char *Result(int &size) {size = bp-buff; return buff;}
void setProt(char *pid) {strcpy(ProtoID, pid);}
static XrdSecProtParm *First;
XrdSecProtParm *Next;
char ProtoID[XrdSecPROTOIDSIZE+1];
XrdSecProtParm(XrdSysError *erp, const char *cid) : who(cid)
{*ProtoID = '\0';
bsize = 4096;
buff = (char *)malloc(bsize);
*buff = '\0';
bp = buff;
eDest = erp;
Next = 0;
}
~XrdSecProtParm() {free(buff);}
private:
XrdSysError *eDest;
int bsize;
char *buff;
char *bp;
const char *who;
};
XrdSecProtParm *XrdSecProtParm::First = 0;
/******************************************************************************/
/* C a t */
/******************************************************************************/
int XrdSecProtParm::Cat(char *token)
{
int alen;
alen = strlen(token);
if (alen+1 > bsize-(bp-buff))
{eDest->Emsg("Config",who,ProtoID,"argument string too long");
return 0;
}
*bp++ = ' ';
strcpy(bp, token);
bp += alen;
return 1;
}
/******************************************************************************/
/* F i n d */
/******************************************************************************/
XrdSecProtParm *XrdSecProtParm::Find(char *pid, int remove)
{
XrdSecProtParm *mp, *pp;
mp = 0; pp = First;
while(pp && !pp->isProto(pid)){mp = pp; pp = pp->Next;}
if (pp && remove)
{if (mp) mp->Next = pp->Next;
else First = pp->Next;
}
return pp;
}
/******************************************************************************/
/* I n s e r t */
/******************************************************************************/
int XrdSecProtParm::Insert(char oct)
{
if (bsize-(bp-buff) < 1)
{eDest->Emsg("Config",who,ProtoID,"argument string too long");
return 0;
}
*bp++ = oct;
return 1;
}
/******************************************************************************/
/* X r d S e c S e r v e r */
/******************************************************************************/
XrdSecPManager XrdSecServer::PManager;
/******************************************************************************/
/* C o n s t r u c t o r */
/******************************************************************************/
XrdSecServer::XrdSecServer(XrdSysLogger *lp) : eDest(lp, "sec_")
{
// Set default values
//
PManager.setErrP(&eDest);
bpFirst = 0;
bpLast = 0;
bpDefault = 0;
STBlen = 4096;
STBuff = (char *)malloc(STBlen);
*STBuff = '\0';
SToken = STBuff;
SecTrace = new XrdOucTrace(&eDest);
if (getenv("XRDDEBUG") || getenv("XrdSecDEBUG"))
{SecTrace->What = TRACE_ALL;
PManager.setDebug(1);
}
Enforce = 0;
implauth = 0;
}
/******************************************************************************/
/* g e t P a r m s */
/******************************************************************************/
const char *XrdSecServer::getParms(int &size, XrdNetAddrInfo *endPoint)
{
EPNAME("getParms")
XrdSecProtBind *bp;
char buff[256];
// Try to find a specific token binding for a host or return default binding
//
if (!endPoint || !bpFirst) bp = 0;
else {const char *hname = endPoint->Name("*unknown*");
bp = bpFirst;
do {if (bp->Match(hname)) break;} while((bp = bp->next));
}
// Get endpoint info if we are debugging
//
if (endPoint && QTRACE(Debug))
endPoint->Format(buff, sizeof(buff), XrdNetAddrInfo::fmtAuto,
XrdNetAddrInfo::noPort);
else *buff = 0;
// If we have a binding, return that else return the default
//
if (!bp) bp = bpDefault;
if (bp->SecToken.buffer)
{DEBUG(buff <<" sectoken=" <SecToken.buffer);
size = bp->SecToken.size;
return bp->SecToken.buffer;
}
DEBUG(buff <<" sectoken=''");
size = 0;
return (const char *)0;
}
/******************************************************************************/
/* g e t P r o t o c o l */
/******************************************************************************/
XrdSecProtocol *XrdSecServer::getProtocol(const char *host,
XrdNetAddrInfo &endPoint,
const XrdSecCredentials *cred,
XrdOucErrInfo *einfo)
{
XrdSecProtBind *bp;
XrdSecPMask_t pnum;
XrdSecCredentials myCreds;
const char *msgv[8];
// If null credentials supplied, default to host protocol otherwise make sure
// credentials data is actually supplied.
//
if (!cred) {myCreds.buffer=(char *)"host"; myCreds.size = 4; cred=&myCreds;}
else if (cred->size < 1 || !(cred->buffer))
{einfo->setErrInfo(EACCES,
(char *)"No authentication credentials supplied.");
return 0;
}
// If protocol binding must be enforced, make sure the host is not using a
// disallowed protocol.
//
if (Enforce)
{if ((pnum = PManager.Find(cred->buffer)))
{if (bpFirst && (bp = bpFirst->Find(host))
&& !(bp->ValidProts & pnum))
{msgv[0] = host;
msgv[1] = " not allowed to authenticate using ";
msgv[2] = cred->buffer;
msgv[3] = " protocol.";
einfo->setErrInfo(EACCES, msgv, 4);
return 0;
}
}
else {msgv[0] = cred->buffer;
msgv[1] = " security protocol is not supported.";
einfo->setErrInfo(EPROTONOSUPPORT, msgv, 2);
return 0;
}
}
// If we passed the protocol binding check, try to get an instance of the
// protocol the host is using
//
return PManager.Get(host, endPoint, cred->buffer, einfo);
}
/******************************************************************************/
/* 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 */
/******************************************************************************/
/******************************************************************************/
/* d e f i n e s */
/******************************************************************************/
#define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config,Eroute);
#define TS_Str(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
#define TS_Chr(x,m) if (!strcmp(x,var)) {m = val[0]; return 0;}
#define TS_Bit(x,m,v) if (!strcmp(x,var)) {m = v; return 0;}
#define Max(x,y) (x > y ? x : y)
/******************************************************************************/
/* C o n f i g u r e */
/******************************************************************************/
int XrdSecServer::Configure(const char *cfn)
/*
Function: Establish default values using a configuration file.
Input: None.
Output: 0 upon success or !0 otherwise.
*/
{
extern XrdSecProtector *XrdSecLoadProtection(XrdSysError &erP);
static const int isRlx = XrdSecProtectParms::relax;
static const int isFrc = XrdSecProtectParms::force;
XrdSecProtector *protObj;
const char *lName = "none", *rName = "none";
char *var;
int NoGo;
// Print warm-up message
//
eDest.Say("++++++ Authentication system initialization started.");
// Perform initialization
//
NoGo = ConfigFile(cfn);
// Almost done
//
var = (NoGo > 0 ? (char *)"failed." : (char *)"completed.");
eDest.Say("------ Authentication system initialization ", var);
// No need to configure protect system if authentication failed
//
if (NoGo) return 1;
// Put out another banner
//
eDest.Say("++++++ Protection system initialization started.");
// If local level if greater than remote level, issue a warning
//
if (lclParms.level > rmtParms.level)
eDest.Say("Config warning: local protection level greater than "
"remote level; are you sure?");
// Check if we need to initialize protection services
//
if (lclParms.level == XrdSecProtectParms::secNone
&& rmtParms.level == XrdSecProtectParms::secNone)
{eDest.Say("Config warning: Security level is set to none; "
"request protection disabled!");
} else {
if (!(protObj = XrdSecLoadProtection(eDest))
|| !(protObj->Config(lclParms, rmtParms, *eDest.logger()))) NoGo = 1;
else {lName = protObj->LName(lclParms.level);
rName = protObj->LName(rmtParms.level);
}
}
// Blurt out what we have
//
if (!NoGo)
{eDest.Say("Config ","Local protection level: ",
(lclParms.opts & isRlx ? "relaxed " : 0), lName,
(lclParms.opts & isFrc ? " force" : 0));
eDest.Say("Config ","Remote protection level: ",
(rmtParms.opts & isRlx ? "relaxed " : 0), rName,
(rmtParms.opts & isFrc ? " force" : 0));
}
// Now we are done
//
var = (NoGo > 0 ? (char *)"failed." : (char *)"completed.");
eDest.Say("------ Protection system initialization ", var);
return (NoGo > 0);
}
/******************************************************************************/
/* C o n f i g F i l e */
/******************************************************************************/
int XrdSecServer::ConfigFile(const char *ConfigFN)
/*
Function: Establish default values using a configuration file.
Input: None.
Output: 1 - Initialization failed.
0 - Initialization succeeded.
*/
{
char *var;
int cfgFD, retc, NoGo = 0, recs = 0;
XrdOucEnv myEnv;
XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
XrdSecProtParm *pp;
// If there is no config file, return with the defaults sets.
//
if (!ConfigFN || !*ConfigFN)
{eDest.Emsg("Config", "Authentication configuration file not specified.");
return 1;
}
// Try to open the configuration file.
//
if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
{eDest.Emsg("Config", errno, "opening config file", ConfigFN);
return 1;
}
// Now start reading records until eof.
//
Config.Attach(cfgFD); Config.Tabs(0);
while((var = Config.GetMyFirstWord()))
{if (!strncmp(var, "sec.", 4))
{recs++;
if (ConfigXeq(var+4, Config, eDest)) {Config.Echo(); NoGo = 1;}
}
}
// Now check if any errors occured during file i/o
//
if ((retc = Config.LastError()))
NoGo = eDest.Emsg("Config",-retc,"reading config file", ConfigFN);
else {char buff[128];
snprintf(buff, sizeof(buff),
" %d authentication directives processed in ", recs);
eDest.Say("Config", buff, ConfigFN);
}
Config.Close();
// Determine whether we should initialize security
//
if (NoGo || ProtBind_Complete(eDest) ) NoGo = 1;
else if ((pp = XrdSecProtParm::First))
{NoGo = 1;
while(pp) {eDest.Emsg("Config", "protparm", pp->ProtoID,
"does not have a matching protocol.");
pp = pp->Next;
}
}
// All done
//
return NoGo;
}
/******************************************************************************/
/* P r i v a t e M e t h o d s */
/******************************************************************************/
/******************************************************************************/
/* C o n f i g X e q */
/******************************************************************************/
int XrdSecServer::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError &Eroute)
{
// Fan out based on the variable
//
TS_Xeq("level", xlevel);
TS_Xeq("protbind", xpbind);
TS_Xeq("protocol", xprot);
TS_Xeq("protparm", xpparm);
TS_Xeq("trace", xtrace);
// No match found, complain.
//
Eroute.Say("Config warning: ignoring unknown directive '",var,"'.");
Config.Echo();
return 0;
}
/******************************************************************************/
/* x l e v e l */
/******************************************************************************/
/* Function: xlevel
Purpose: To parse the directive: level [] [relaxed] [force]
all | local | remote
none | compatible | standard | intense | pedantic
Output: 0 upon success or !0 upon failure.
*/
int XrdSecServer::xlevel(XrdOucStream &Config, XrdSysError &Eroute)
{
struct lvltab {const char *lname; XrdSecProtectParms::secLevel lvl;} ltab[] =
{{"none", XrdSecProtectParms::secNone},
{"compatible", XrdSecProtectParms::secCompatible},
{"standard", XrdSecProtectParms::secStandard},
{"intense", XrdSecProtectParms::secIntense},
{"pedantic", XrdSecProtectParms::secPedantic}
};
int i, numopts = sizeof(ltab)/sizeof(struct lvltab);
bool isLcl = true, isRmt = true, isSpec = false, isRlx = false, isFRC=false;
char *val;
// Get the template host
//
val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config","level not specified"); return 1;}
// Check for optional keyword
//
if (!strcmp(val, "all")) isSpec = true;
else if (!strcmp(val, "local")) {isSpec = true; isRmt = false;}
else if (!strcmp(val, "remote")){isSpec = true; isLcl = false;}
// Check if we need another token
//
if (isSpec)
{val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config","level not specified"); return 1;}
}
// Check for optional relaxed keyword
//
if (!strcmp(val, "relaxed"))
{isRlx = true;
val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config","level not specified"); return 1;}
}
// Get the level
//
for (i = 0; i < numopts; i++) if (!strcmp(ltab[i].lname, val)) break;
if (i >= numopts)
{Eroute.Emsg("Config", "invalid level option -", val); return 1;}
// Check for final keyword
//
val = Config.GetWord();
if (val && val[0])
{if (strcmp(val, "force"))
{Eroute.Emsg("Config","invalid level modifier - ", val); return 1;}
isFRC = true;
}
// Set appropriate levels
//
if (isLcl)
{lclParms.level = ltab[i].lvl;
if (isRlx) lclParms.opts |= XrdSecProtectParms::relax;
else lclParms.opts &= ~XrdSecProtectParms::relax;
if (isFRC) lclParms.opts |= XrdSecProtectParms::force;
else lclParms.opts &= ~XrdSecProtectParms::force;
}
if (isRmt)
{rmtParms.level = ltab[i].lvl;
if (isRlx) rmtParms.opts |= XrdSecProtectParms::relax;
else rmtParms.opts &= ~XrdSecProtectParms::relax;
if (isFRC) rmtParms.opts |= XrdSecProtectParms::force;
else rmtParms.opts &= ~XrdSecProtectParms::force;
}
return 0;
}
/******************************************************************************/
/* x p b i n d */
/******************************************************************************/
/* Function: xpbind
Purpose: To parse the directive: protbind [none | [only] ]
is a templated host name (e.g., bronco*.slac.stanford.edu)
are the protocols to be bound to the . A special
protocol, none, indicates that no token is to be passed.
Output: 0 upon success or !0 upon failure.
*/
int XrdSecServer::xpbind(XrdOucStream &Config, XrdSysError &Eroute)
{
EPNAME("xpbind")
char *val, *thost;
XrdSecProtBind *bnow;
char sectoken[4096], *secbuff = sectoken;
int isdflt = 0, only = 0, anyprot = 0, noprot = 0, phost = 0;
int sectlen = sizeof(sectoken)-1;
XrdSecPMask_t PMask = 0;
*secbuff = '\0';
// Get the template host
//
val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config","protbind host not specified"); return 1;}
// Verify that this host has not been bound before
//
if ((isdflt = !strcmp("*", val))) bnow = bpDefault;
else {bnow = bpFirst;
while(bnow) if (!strcmp(bnow->thost, val)) break;
else bnow = bnow->next;
}
if (bnow) {Eroute.Emsg("Config","duplicate protbind definition - ", val);
return 1;
}
thost = strdup(val);
// Now get each protocol to be used (there must be one).
//
while((val = Config.GetWord()))
{if (!strcmp(val, "none")) {noprot = 1; break;}
if (!strcmp(val, "only")) {only = 1; Enforce = 1;}
else if (!strcmp(val, "host")) {phost = 1; anyprot = 1;}
else if (!PManager.Find(val))
{Eroute.Emsg("Config","protbind", val,
"protocol not previously defined.");
return 1;
}
else if (add2token(Eroute, val, &secbuff, sectlen, PMask))
{Eroute.Emsg("Config","Unable to bind protocols to",thost);
return 1;
} else anyprot = 1;
}
// Verify that no conflicts arose
//
if (val && (val = Config.GetWord()))
{Eroute.Emsg("Config","conflicting protbind:", thost, val);
return 1;
}
// Make sure we have some protocols bound to this host
//
if (!(anyprot || noprot))
{Eroute.Emsg("Config","no protocols bound to", thost); return 1;}
DEBUG("XrdSecConfig: Bound "<< thost<< " to "
<< (noprot ? "none" : (phost ? "host" : sectoken)));
// Issue warning if the host protocol was bound to this host but other
// protocols were also bound, making them rather useless.
//
if (phost && *sectoken)
{Eroute.Say("Config warning: 'protbind", thost,
"host' negates all other bound protocols.");
*sectoken = '\0';
}
// Translate "localhost" to our local hostname, if possible.
//
if (!strcmp("localhost", thost))
{XrdNetAddr myIPAddr(0);
free(thost);
thost = strdup(myIPAddr.Name("localhost"));
}
// Create new bind object
//
bnow = new XrdSecProtBind(thost,(noprot ? 0:sectoken),(only ? PMask:0));
// Push the entry onto our bindings
//
if (isdflt) bpDefault = bnow;
else {if (bpLast) bpLast->next = bnow;
else bpFirst = bnow;
bpLast = bnow;
}
// All done
//
return 0;
}
/******************************************************************************/
/* x p r o t */
/******************************************************************************/
/* Function: xprot
Purpose: To parse the directive: protocol [] [ ]
is the absolute path where the protocol library resides
is the 1-to-8 character protocol id.
are the associated protocol specific options such as:
noipcheck - don't check ip address origin
keyfile - the key file associated with protocol
args - associated non-blank arguments
Additional arguments may be passed to the protocol using the
protargs directive. ALl protargs directives must appear
prior to the protocol directive for the given protocol.
Output: 0 upon success or !0 upon failure.
*/
int XrdSecServer::xprot(XrdOucStream &Config, XrdSysError &Eroute)
{
XrdSecProtParm *pp, myParms(&Eroute, "protocol");
char *pap, *val, pid[XrdSecPROTOIDSIZE+1], *args = 0;
char pathbuff[1024], *path = 0;
int psize;
XrdOucErrInfo erp;
XrdSecPMask_t mymask = 0;
// Get the protocol id
//
val = Config.GetWord();
if (val && *val == '/')
{strlcpy(pathbuff, val, sizeof(pathbuff)); path = pathbuff;
val = Config.GetWord();
}
if (!val || !val[0])
{Eroute.Emsg("Config","protocol id not specified"); return 1;}
// Verify that we don't have this protocol
//
if (strlen(val) > XrdSecPROTOIDSIZE)
{Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
if (PManager.Find(val))
{Eroute.Say("Config warning: protocol ",val," previously defined.");
strcpy(pid, val);
return add2token(Eroute, pid, &STBuff, STBlen, mymask);}
// The builtin host protocol does not accept any parameters. Additionally, the
// host protocol negates any other protocols we may have in the default set.
//
if (!strcmp("host", val))
{if (Config.GetWord())
{Eroute.Emsg("Config", "Builtin host protocol does not accept parms.");
return 1;
}
implauth = 1;
return 0;
}
// Grab additional parameters that we here and that we have accumulated
//
strcpy(pid, val);
while((args = Config.GetWord())) if (!myParms.Cat(args)) return 1;
if ((pp = myParms.Find(pid, 1)))
{if ((*myParms.Result(psize) && !myParms.Insert('\n'))
|| !myParms.Cat(pp->Result(psize))) return 1;
else delete pp;
}
// Load this protocol
//
pap = myParms.Result(psize);
if (!PManager.Load(&erp, 's', pid, (psize ? pap : 0), path))
{if (*(erp.getErrText())) Eroute.Say(erp.getErrText());
return 1;
}
// Add this protocol to the default security token
//
return add2token(Eroute, pid, &STBuff, STBlen, mymask);
}
/******************************************************************************/
/* x p p a r m */
/******************************************************************************/
/* Function: xpparm
Purpose: To parse the directive: protparm
is the name of the protocol to which these args apply.
are the protocol specific parameters. The remaing tokens
on the line will be passed to the protocol at during
protocol initialization. Each such line is separated by
a new line character.
Output: 0 upon success or !0 upon failure.
*/
int XrdSecServer::xpparm(XrdOucStream &Config, XrdSysError &Eroute)
{
XrdSecProtParm *pp;
char *val, pid[XrdSecPROTOIDSIZE+1];
// Get the protocol name
//
val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config","protparm protocol not specified"); return 1;}
// The builtin host protocol does not accept any parameters
//
if (!strcmp("host", val))
{Eroute.Emsg("Config", "Builtin host protocol does not accept protparms.");
return 1;
}
// Verify that we don't have this protocol
//
if (strlen(val) > XrdSecPROTOIDSIZE)
{Eroute.Emsg("Config","protocol id too long - ", val); return 1;}
if (PManager.Find(val))
{Eroute.Emsg("Config warning: protparm protocol ",val," already defined.");
return 0;
}
strcpy(pid, val);
// Make sure we have at least one parameter here
//
if (!(val = Config.GetWord()))
{Eroute.Emsg("Config","protparm", pid, "parameter not specified");
return 1;
}
// Try to find a previous incarnation of this parm
//
if ((pp = XrdSecProtParm::Find(pid))) {if (!pp->Insert('\n')) return 1;}
else {pp = new XrdSecProtParm(&Eroute, "protparm");
pp->setProt(pid);
pp->Add();
}
// Grab the options for the protocol. They are pretty much opaque to us here
//
do {if (!pp->Cat(val)) return 1;} while((val = Config.GetWord()));
return 0;
}
/******************************************************************************/
/* x t r a c e */
/******************************************************************************/
/* Function: xtrace
Purpose: To parse the directive: trace
the blank separated list of events to trace. Trace
directives are cummalative.
Output: 0 upon success or !0 upon failure.
*/
int XrdSecServer::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
{
static struct traceopts {const char *opname; int opval;} tropts[] =
{
{"all", TRACE_ALL},
{"debug", TRACE_Debug},
{"auth", TRACE_Authen},
{"authentication", TRACE_Authen}
};
int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
char *val;
val = Config.GetWord();
if (!val || !val[0])
{Eroute.Emsg("Config", "trace option not specified"); return 1;}
while (val && val[0])
{if (!strcmp(val, "off")) trval = 0;
else {if ((neg = (val[0] == '-' && val[1]))) val++;
for (i = 0; i < numopts; i++)
{if (!strcmp(val, tropts[i].opname))
{if (neg) trval &= ~tropts[i].opval;
else trval |= tropts[i].opval;
break;
}
}
if (i >= numopts)
Eroute.Say("Config warning: ignoring invalid trace option '", val, "'.");
}
val = Config.GetWord();
}
SecTrace->What = (SecTrace->What & ~TRACE_Authenxx) | trval;
// Propogate the debug option
//
#ifndef NODEBUG
if (QTRACE(Debug)) PManager.setDebug(1);
else PManager.setDebug(0);
#endif
return 0;
}
/******************************************************************************/
/* M i s c e l l a n e o u s */
/******************************************************************************/
/******************************************************************************/
/* a d d 2 t o k e n */
/******************************************************************************/
int XrdSecServer::add2token(XrdSysError &Eroute, char *pid,
char **tokbuff, int &toklen, XrdSecPMask_t &pmask)
{
int i;
char *pargs;
XrdSecPMask_t protnum;
// Find the protocol argument string
//
if (!(protnum = PManager.Find(pid, &pargs)))
{Eroute.Emsg("Config","Protocol",pid,"not found after being added!");
return 1;
}
// Make sure we have enough room to add
//
i = 4+strlen(pid)+strlen(pargs);
if (i >= toklen)
{Eroute.Emsg("Config","Protocol",pid,"parms exceed overall maximum!");
return 1;
}
// Insert protocol specification (we already checked for an overflow)
//
i = sprintf(*tokbuff, "&P=%s%s%s", pid, (*pargs ? "," : ""), pargs);
toklen -= i;
*tokbuff += i;
pmask |= protnum;
return 0;
}
/******************************************************************************/
/* P r o t B i n d _ C o m p l e t e */
/******************************************************************************/
int XrdSecServer::ProtBind_Complete(XrdSysError &Eroute)
{
EPNAME("ProtBind_Complete")
XrdOucErrInfo erp;
// Check if we have a default token, create one otherwise
//
if (!bpDefault)
{if (!*SToken) {Eroute.Say("Config warning: No protocols defined; "
"only host authentication available.");
implauth = 1;
}
else if (implauth)
{Eroute.Say("Config warning: enabled builtin host "
"protocol negates default use of any other protocols.");
*SToken = '\0';
}
bpDefault = new XrdSecProtBind(strdup("*"), SToken);
DEBUG("Default sectoken built: '" <Configure(cfn)) return 0;
// Return the server object
//
return (XrdSecService *)SecServer;
}
}