diff --git a/src/XrdSecgsi.cmake b/src/XrdSecgsi.cmake index 3c7ce427f60..80038082899 100644 --- a/src/XrdSecgsi.cmake +++ b/src/XrdSecgsi.cmake @@ -15,6 +15,7 @@ add_library( ${LIB_XRD_SEC_GSI} MODULE XrdSecgsi/XrdSecProtocolgsi.cc XrdSecgsi/XrdSecProtocolgsi.hh + XrdSecgsi/XrdSecgsiOpts.hh XrdSecgsi/XrdSecgsiTrace.hh ) target_link_libraries( diff --git a/src/XrdSecgsi/XrdSecProtocolgsi.cc b/src/XrdSecgsi/XrdSecProtocolgsi.cc index d6f0698ad57..b059b6496a6 100644 --- a/src/XrdSecgsi/XrdSecProtocolgsi.cc +++ b/src/XrdSecgsi/XrdSecProtocolgsi.cc @@ -57,12 +57,14 @@ #include "XrdCrypto/XrdCryptoX509Req.hh" #include "XrdSecgsi/XrdSecProtocolgsi.hh" +#include "XrdSecgsi/XrdSecgsiOpts.hh" /******************************************************************************/ /* T r a c i n g I n i t O p t i o n s */ /******************************************************************************/ #ifndef NODEBUG -#define POPTS(t,y) {if (t) {t->Beg(epname); cerr <End();}} +//#define POPTS(t,y) {if (t) {t->Beg(epname); cerr <End();}} +#define POPTS(t,y) {if (t) {cerr <<"Secgsi" <= 0 && opt.ca <= 2) + if (opt.ca >= caNoVerify && opt.ca <= caVerify) CACheck = opt.ca; - DEBUG("option CACheck: "<getErrText()); } else { - ErrF(erp,kGSErrError,"cannot stat CA directory:",dp.c_str()); + ErrF(erp,kGSErrError,"cannot stat CA directory",dp.c_str()); PRINT(erp->getErrText()); } } else { @@ -504,11 +507,11 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) // const char *cocrl[] = { "do-not-care", "use-if-available", "require", "require-not-expired" }; const char *codwld[] = { "no", "yes"}; - if (opt.crl >= 10) { + if (opt.crl >= crlUpdate) { CRLDownload = 1; opt.crl %= 10; } - if (opt.crl >= 0 && opt.crl <= 3) + if (opt.crl >= crlIgnore && opt.crl <= crlRequire) CRLCheck = opt.crl; DEBUG("option CRLCheck: "<getErrText()); - return Parms; + return Failure; } // // List of supported / wanted ciphers @@ -710,7 +713,7 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) if (cacheCert.Num() <= 0) { ErrF(erp,kGSErrError,"no valid server certificate found"); PRINT(erp->getErrText()); - return Parms; + return Failure; } DEBUG("CA list: "< 0) { pars += "to="; pars += (int)opt.gmapto; } if (!(servGMap = XrdOucgetGMap(&eDest, GMAPFile.c_str(), pars.c_str()))) { if (GMAPOpt > 1) { - ErrF(erp,kGSErrError,"error loading grid map file:",GMAPFile.c_str()); + ErrF(erp,kGSErrError,"error loading grid map file",GMAPFile.c_str()); PRINT(erp->getErrText()); - return Parms; + return Failure; } else { NOTIFY("Grid map file: "<getErrText()); - return Parms; + return Failure; } else { hasgmapfun = 1; } @@ -785,19 +788,20 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) ErrF(erp,kGSErrError,"User mapping required, but neither a grid mapfile" " nor a mapping function are available"); PRINT(erp->getErrText()); - return Parms; + return Failure; } GMAPOpt = 0; } // - // Authorization function + // Authentication function bool hasauthzfun = 0; + AuthzAlways = opt.authzcall; if (opt.authzfun) { if (!(AuthzFun = LoadAuthzFun((const char *) opt.authzfun, (const char *) opt.authzfunparms, AuthzCertFmt))) { ErrF(erp, kGSErrError, "Authz plug-in could not be loaded", opt.authzfun); PRINT(erp->getErrText()); - return Parms; + return Failure; } else { hasauthzfun = 1; // Notify certificate format @@ -828,7 +832,7 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) // 1 last proxy only // opt_where = 1 Entity.creds // 2 Entity.endorsements - if (opt.authzpxy > 0) { + if (opt.authzpxy) { AuthzPxyWhat = opt.authzpxy / 10; AuthzPxyWhere = opt.authzpxy % 10; // Some notification @@ -851,7 +855,7 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) DEBUG("Will not accept delegated proxies"); } else { // Ask the client to sign a delegated proxy; client may decide to forward its proxy - if (opt.dlgpxy == 1) + if (opt.dlgpxy == dlgReqSign) PxyReqOpts |= kOptsSrvReq; // Exporting options (default none: delegated proxy kept in memory, in proxyChain) @@ -882,30 +886,33 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) // vomsat = 0 do not look for // 1 extract if any (fill 'vorg', 'role'; the full string in 'endorsements'); // 2 require (fill 'vorg', 'role'; the full string in 'endorsements'); - VOMSAttrOpt = (opt.vomsat <= 2 && opt.vomsat >= 0) ? opt.vomsat : VOMSAttrOpt; + VOMSAttrOpt = (opt.vomsat <= vatRequire && opt.vomsat >= vatIgnore) + ? opt.vomsat : VOMSAttrOpt; // // Alternative VOMS extraction function if (opt.vomsfun) { if (!(VOMSFun = LoadVOMSFun((const char *) opt.vomsfun, (const char *) opt.vomsfunparms, VOMSCertFmt))) { - ErrF(erp, kGSErrError, "VOMS plug-in could not be loaded", opt.vomsfun); + ErrF(erp, kGSErrError, "VOMS plug-in loading failed", opt.vomsfun); PRINT(erp->getErrText()); - return Parms; + return Failure; } else { - // We at least check VOMS attributes if we have a function ... - if (VOMSAttrOpt < 1) VOMSAttrOpt = 1; // Notify certificate format if (VOMSCertFmt >= 0 && VOMSCertFmt <= 1) { const char *ccfmt[] = { "raw", "PEM base64" }; DEBUG("vomsfun: proxy certificate format: "<getErrText()); + return Failure; } } - } - const char *cvomsat[3] = { "ignore", "extract", "require" }; - DEBUG("VOMS attributes options: "<getErrText()); + return Failure; + } + // // Parms in the form: // &P=gsi,v:,c:,ca: @@ -925,6 +941,7 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) } else { ErrF(erp,kGSErrInit,"no system resources for 'Parms'"); PRINT(erp->getErrText()); + return Failure; } // Some notification @@ -989,9 +1006,9 @@ char *XrdSecProtocolgsi::Init(gsiOptions opt, XrdOucErrInfo *erp) DefBits = opt.bits; // // Delegate proxy options - if (opt.dlgpxy > 0) { + if (opt.dlgpxy > dlgIgnore) { PxyReqOpts |= kOptsSigReq; - if (opt.dlgpxy == 2) { + if (opt.dlgpxy == dlgSendpxy) { PxyReqOpts |= kOptsFwdPxy; } else { PxyReqOpts |= kOptsDlgPxy; @@ -1750,6 +1767,7 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, int nextstep = 0; char *bpub = 0; int lpub = 0; + bool vomsFailed = false; const char *stepstr = 0; String Message; String CryptList; @@ -1946,35 +1964,29 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, Entity.moninfo = strdup(hs->Chain->EECname()); } - if (VOMSAttrOpt > 0) { - if (VOMSFun) { - // Fill the information needed by the external function - if (VOMSCertFmt == 1) { - // PEM base64 - bpxy = (*X509ExportChain)(hs->Chain, true); - bpxy->ToString(spxy); - delete bpxy; - Entity.creds = strdup(spxy.c_str()); - Entity.credslen = spxy.length(); - } else { - // Raw (opaque) format, to be used with XrdCrypto - Entity.creds = (char *) hs->Chain; - Entity.credslen = 0; - } - if ((*VOMSFun)(Entity) != 0 && VOMSAttrOpt == 2) { - // Error - kS_rc = kgST_error; - PRINT("ERROR: the VOMS extraction plug-in reported a failure for this handshake"); - break; - } + if (VOMSAttrOpt > vatIgnore && VOMSFun) { + // Fill the information needed by the external function + if (VOMSCertFmt == 1) { + // PEM base64 + bpxy = (*X509ExportChain)(hs->Chain, true); + bpxy->ToString(spxy); + delete bpxy; + Entity.creds = strdup(spxy.c_str()); + Entity.credslen = spxy.length(); } else { - // Lite version (no validations whatsover) - if (ExtractVOMS(hs->Chain, Entity) != 0 && VOMSAttrOpt == 2) { + // Raw (opaque) format, to be used with XrdCrypto + Entity.creds = (char *) hs->Chain; + Entity.credslen = 0; + } + if ((*VOMSFun)(Entity) != 0) { + vomsFailed = true; + if (VOMSAttrOpt == vatRequire) { // Error kS_rc = kgST_error; - PRINT("ERROR: VOMS attributes required but not found (default lite-extraction technology)"); + PRINT("ERROR: the VOMS extraction plug-in reported " + "authentication failure"); break; - } + } } NOTIFY("VOMS: Entity.vorg: "<< (Entity.vorg ? Entity.vorg : "")); NOTIFY("VOMS: Entity.grps: "<< (Entity.grps ? Entity.grps : "")); @@ -1985,7 +1997,7 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, // Here prepare/extract the information for authorization spxy = ""; bpxy = 0; - if (AuthzFun && AuthzKey) { + if (AuthzFun && AuthzKey && (AuthzAlways || vomsFailed)) { // Fill the information needed by the external function if (AuthzCertFmt == 1) { // May have been already done @@ -2042,7 +2054,7 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, if ((authzrc = (*AuthzFun)(Entity)) != 0) { // Error kS_rc = kgST_error; - PRINT("ERROR: the authorization plug-in reported a failure for this handshake"); + PRINT("ERROR: the authz plug-in reported failure"); SafeDelete(key); ceref.UnLock(); break; @@ -2081,8 +2093,8 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, } // Export proxy for authorization, if required - if (AuthzPxyWhat >= 0) { - if (bpxy && AuthzPxyWhat == 1) { + if (AuthzPxyWhat >= azFull) { + if (bpxy && AuthzPxyWhat == azLast) { SafeDelete(bpxy); spxy = ""; SafeFree(Entity.creds); Entity.credslen = 0; @@ -2095,7 +2107,7 @@ int XrdSecProtocolgsi::Authenticate(XrdSecCredentials *cred, } bpxy->ToString(spxy); } - if (AuthzPxyWhere == 1) { + if (AuthzPxyWhere == azCred) { Entity.creds = strdup(spxy.c_str()); Entity.credslen = spxy.length(); } else { @@ -2235,91 +2247,6 @@ void XrdSecProtocolgsi::FreeEntity(XrdSecEntity *in) return; } -/******************************************************************************/ -/* E x t r a c t V O M S */ -/******************************************************************************/ - -int XrdSecProtocolgsi::ExtractVOMS(X509Chain *c, XrdSecEntity &ent) -{ - // Get the VOMS attributes from proxy file(s) in chain 'c' (either the proxy - // or the limited proxy) and fill the relevant fields in 'ent' - EPNAME("ExtractVOMS"); - - if (!c) return -1; - - XrdCryptoX509 *xp = c->End(); - if (!xp) return -1; - - // Extractor - XrdCryptoX509GetVOMSAttr_t X509GetVOMSAttr = sessionCF->X509GetVOMSAttr(); - if (!X509GetVOMSAttr) return -1; - - // Extract the information - XrdOucString vatts; - int rc = 0; - if ((rc = (*X509GetVOMSAttr)(xp, vatts)) != 0) { - if (strstr(xp->Subject(), "CN=limited proxy")) { - xp = c->SearchBySubject(xp->Issuer()); - rc = (*X509GetVOMSAttr)(xp, vatts); - } - if (rc != 0) { - if (rc > 0) { - NOTIFY("No VOMS attributes in proxy chain"); - } else { - PRINT("ERROR: problem extracting VOMS attributes"); - } - return -1; - } - } - - int from = 0; - XrdOucString vat; - while ((from = vatts.tokenize(vat, from, ',')) != -1) { - XrdOucString vo, role, grp; - if (vat.length() > 0) { - // The attribute is in the form - // /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap] - int isl = vat.find('/', 1); - if (isl != STR_NPOS) vo.assign(vat, 1, isl - 1); - int igr = vat.find("/Role=", 1); - if (igr != STR_NPOS) grp.assign(vat, 0, igr - 1); - int irl = vat.find("Role="); - if (irl != STR_NPOS) { - role.assign(vat, irl + 5); - isl = role.find('/'); - role.erase(isl); - } - if (ent.vorg) { - if (vo != (const char *) ent.vorg) { - DEBUG("WARNING: found a second VO ('"< 0) ent.vorg = strdup(vo.c_str()); - } - if (grp.length() > 0 - && (!ent.grps || grp.length() > int(strlen(ent.grps)))) { - SafeFree(ent.grps); - ent.grps = strdup(grp.c_str()); - } - if (role.length() > 0 && role != "NULL" && !ent.role) { - ent.role = strdup(role.c_str()); - } - } - } - - // Save the whole string in endorsements - SafeFree(ent.endorsements); - if (vatts.length() > 0) ent.endorsements = strdup(vatts.c_str()); - - // Notify if did not find the main info (the VO ...) - if (!ent.vorg) PRINT("WARNING: no VO found! (VOMS attributes: '"< 0) POPTS(t, " CRL refresh time: "<< crlrefresh); if (mode == 'c') { POPTS(t, " Certificate: " << (cert ? cert : XrdSecProtocolgsi::UsrCert)); @@ -2368,11 +2295,11 @@ void gsiOptions::Print(XrdOucTrace *t) } else { POPTS(t, " Certificate: " << (cert ? cert : XrdSecProtocolgsi::SrvCert)); POPTS(t, " Key: " << (key ? key : XrdSecProtocolgsi::SrvKey)); - POPTS(t, " Proxy delegation option: "<< dlgpxy); - if (dlgpxy > 1) + POPTS(t, " Proxy delegation option: "<< getOptName(sDlgOpts,dlgpxy)); + if (exppxy) POPTS(t, " Template for exported proxy: "<< (exppxy ? exppxy : gUsrPxyDef)); POPTS(t, " GRIDmap file: " << (gridmap ? gridmap : XrdSecProtocolgsi::GMAPFile)); - POPTS(t, " GRIDmap option: "<< ogmap); + POPTS(t, " GRIDmap option: "<< getOptName(gmoOpts,ogmap)); POPTS(t, " GRIDmap cache entries expiration (secs): "<< gmapto); if (gmapfun) { POPTS(t, " DN mapping function: " << gmapfun); @@ -2381,14 +2308,16 @@ void gsiOptions::Print(XrdOucTrace *t) if (gmapfunparms) POPTS(t, " DN mapping function parms: ignored (no mapping function defined)"); } if (authzfun) { - POPTS(t, " Authorization function: " << authzfun); - if (authzfunparms) POPTS(t, " Authorization function parms: " << authzfunparms); - POPTS(t, " Authorization cache entries expiration (secs): " << authzto); + POPTS(t, " Authz function: " << authzfun); + if (authzfunparms) POPTS(t, " Authz function parms: " << authzfunparms); + POPTS(t, " Authz call: " <] // [-gmapfun:] // [-gmapfunparms:] + // [-authzcall:] // [-authzfun:] // [-authzfunparms:] // [-authzto:] @@ -2669,12 +2599,13 @@ char *XrdSecProtocolgsiInit(const char mode, int ogmap = 1; int gmapto = 600; int authzto = -1; - int dlgpxy = 0; + int authzcall = 1; + int dlgpxy = dlgIgnore; int authzpxy = 0; - int vomsat = 1; + int vomsat = vatIgnore; // Was 1 or extract int moninfo = 0; int hashcomp = 1; - int trustdns = 1; + int trustdns = false; char *op = 0; while (inParms.GetLine()) { while ((op = inParms.GetToken())) { @@ -2697,19 +2628,22 @@ char *XrdSecProtocolgsiInit(const char mode, } else if (!strncmp(op, "-md:",4)) { md = (const char *)(op+4); } else if (!strncmp(op, "-ca:",4)) { + ca = getOptVal(caVerOpts, op+4); ca = atoi(op+4); } else if (!strncmp(op, "-crl:",5)) { - crl = atoi(op+5); + crl = getOptVal(crlOpts, op+5); } else if (!strncmp(op, "-crlrefresh:",12)) { crlrefresh = atoi(op+12); } else if (!strncmp(op, "-gmapopt:",9)) { - ogmap = atoi(op+9); + ogmap = getOptVal(gmoOpts, op+9); } else if (!strncmp(op, "-gridmap:",9)) { gridmap = (const char *)(op+9); } else if (!strncmp(op, "-gmapfun:",9)) { gmapfun = (const char *)(op+9); } else if (!strncmp(op, "-gmapfunparms:",14)) { gmapfunparms = (const char *)(op+14); + } else if (!strncmp(op, "-authzcall:",11)) { + authzcall = getOptVal(azCallOpts, op+11); } else if (!strncmp(op, "-authzfun:",10)) { authzfun = (const char *)(op+10); } else if (!strncmp(op, "-authzfunparms:",15)) { @@ -2719,15 +2653,15 @@ char *XrdSecProtocolgsiInit(const char mode, } else if (!strncmp(op, "-gmapto:",8)) { gmapto = atoi(op+8); } else if (!strncmp(op, "-dlgpxy:",8)) { - dlgpxy = atoi(op+8); + opts.dlgpxy = getOptVal(sDlgOpts, op+8); } else if (!strncmp(op, "-exppxy:",8)) { exppxy = (const char *)(op+8); } else if (!strncmp(op, "-authzpxy:",10)) { - authzpxy = atoi(op+10); + opts.authzpxy = getOptVal(azPxyOpts, op+10); } else if (!strncmp(op, "-authzpxy",9)) { authzpxy = 11; } else if (!strncmp(op, "-vomsat:",8)) { - vomsat = atoi(op+8); + vomsat = getOptVal(vomsatOpts, op+8); } else if (!strncmp(op, "-vomsfun:",9)) { vomsfun = (const char *)(op+9); } else if (!strncmp(op, "-vomsfunparms:",14)) { @@ -2739,13 +2673,23 @@ char *XrdSecProtocolgsiInit(const char mode, } else if (!strcmp(op, "-defaulthash")) { hashcomp = 0; } else if (!strncmp(op, "-trustdns:",10)) { - trustdns = atoi(op+10); + trustdns = getOptVal(tdnsOpts, op+10); } else { PRINT("ignoring unknown switch: "< 0) + {if (vomsat == vatIgnore) vomsat = vatExtract; + if (vomsfun == "default") vomsfun = LIB_XRDVOMS; + } else authzcall = azAlways; + // // Build the option object opts.debug = (debug > -1) ? debug : opts.debug; @@ -2755,8 +2699,9 @@ char *XrdSecProtocolgsiInit(const char mode, opts.crlrefresh = crlrefresh; opts.ogmap = ogmap; opts.gmapto = gmapto; + opts.authzcall = authzcall; opts.authzto = authzto; - opts.dlgpxy = (dlgpxy >= 0 && dlgpxy <= 1) ? dlgpxy : 0; + opts.dlgpxy = (dlgpxy >= dlgIgnore && dlgpxy <= dlgReqSign) ? dlgpxy : 0; opts.authzpxy = authzpxy; opts.vomsat = vomsat; opts.moninfo = moninfo; @@ -4566,7 +4511,7 @@ bool XrdSecProtocolgsi::VerifyCA(int opt, X509Chain *cca, XrdCryptoFactory *CF) } } } else { - if (CACheck > 0) { + if (CACheck > caNoVerify) { // Check self-signature if (!(verified = cca->CheckCA())) PRINT("CA certificate self-signed: integrity check failed ("<SubjectHash()<<")"); @@ -5145,7 +5090,7 @@ int XrdSecProtocolgsi::QueryProxy(bool checkcache, XrdSutCache *cache, continue; } // Check if any CA was in the file - bool checkselfsigned = (CACheck > 1) ? 1 : 0; + bool checkselfsigned = (CACheck > caVerifyss) ? true : false; po->chain->CheckCA(checkselfsigned); exportbucket = 1; } diff --git a/src/XrdSecgsi/XrdSecProtocolgsi.hh b/src/XrdSecgsi/XrdSecProtocolgsi.hh index fc258a642ea..b6efb399d83 100644 --- a/src/XrdSecgsi/XrdSecProtocolgsi.hh +++ b/src/XrdSecgsi/XrdSecProtocolgsi.hh @@ -190,6 +190,7 @@ public: char *gmapfunparms;// [s] parameters for the function to map DN to usernames [0] char *authzfun;// [s] file with the function to fill entities [0] char *authzfunparms;// [s] parameters for the function to fill entities [0] + int authzcall; // [s] when to call authz function [1 -> always] int authzto; // [s] validity in secs of authz cache entries [-1 => unlimited] int ogmap; // [s] gridmap file checking option int dlgpxy; // [c] explicitely ask the creation of a delegated proxy; default 0 @@ -212,10 +213,12 @@ public: cipher = 0; md = 0; ca = 1 ; crl = 1; crlrefresh = 86400; proxy = 0; valid = 0; deplen = 0; bits = 512; gridmap = 0; gmapto = 600; - gmapfun = 0; gmapfunparms = 0; authzfun = 0; authzfunparms = 0; authzto = -1; + gmapfun = 0; gmapfunparms = 0; authzfun = 0; authzfunparms = 0; + authzto = -1; authzcall = 1; ogmap = 1; dlgpxy = 0; sigpxy = 1; srvnames = 0; exppxy = 0; authzpxy = 0; - vomsat = 1; vomsfun = 0; vomsfunparms = 0; moninfo = 0; hashcomp = 1; trustdns = true; } + vomsat = 1; vomsfun = 0; vomsfunparms = 0; moninfo = 0; + hashcomp = 1; trustdns = true;} virtual ~gsiOptions() { } // Cleanup inside XrdSecProtocolgsiInit void Print(XrdOucTrace *t); // Print summary of gsi option status }; @@ -342,6 +345,7 @@ private: static int PxyReqOpts; static int AuthzPxyWhat; static int AuthzPxyWhere; + static int AuthzAlways; static String SrvAllowedNames; static int VOMSAttrOpt; static XrdSecgsiVOMS_t VOMSFun; @@ -483,9 +487,6 @@ private: // Entity handling void CopyEntity(XrdSecEntity *in, XrdSecEntity *out, int *lout = 0); void FreeEntity(XrdSecEntity *in); - - // VOMS parsing - int ExtractVOMS(X509Chain *c, XrdSecEntity &ent); }; class gsiHSVars { diff --git a/src/XrdSecgsi/XrdSecgsiOpts.hh b/src/XrdSecgsi/XrdSecgsiOpts.hh new file mode 100644 index 00000000000..c8f1982548b --- /dev/null +++ b/src/XrdSecgsi/XrdSecgsiOpts.hh @@ -0,0 +1,236 @@ +#ifndef __XRD_GSIOPTS_H__ +#define __XRD_GSIOPTS_H__ +/******************************************************************************/ +/* */ +/* X r d S e c g s i O p t s . h h */ +/* */ +/* (c) 2020 by the Board of Trustees of the Leland Stanford, Jr., University */ +/* 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. */ +/******************************************************************************/ + +namespace +{ +/******************************************************************************/ +/* D e f i n e s a n d S t r u c t s */ +/******************************************************************************/ + +#define WARN(x) std::cerr <<"Secgsi warning: " << x <<'\n' <= 0) + {WARN("invalid " <. */ -/* */ -/* 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. */ -/* */ -/******************************************************************************/ - -/* ************************************************************************** */ -/* */ -/* Example of fucntion extracting VOMS attributes */ -/* */ -/* To get it build as libXrdSecgsiVOMSLite.so, add the following to */ -/* src/XrdSecgsi.cmake */ -/* */ -/* #------------------------------------------------------------------------------- -/* # The XrdSecgsiVOMSLite library -/* #------------------------------------------------------------------------------- -/* -/* set( XRD_SEC_GSI_VOMSLITE_VERSION 1.0.0 ) -/* set( XRD_SEC_GSI_VOMSLITE_SOVERSION 0 ) -/* -/* add_library( -/* XrdSecgsiVOMSLite -/* SHARED -/* XrdSecgsi/XrdSecgsiVOMSFunLite.cc ) -/* -/* target_link_libraries( -/* XrdSecgsiVOMSLite -/* XrdSecgsi -/* XrdCryptossl -/* XrdCrypto -/* XrdUtils ) -/* -/* set_target_properties( -/* XrdSecgsiVOMSLite -/* PROPERTIES -/* VERSION ${XRD_SEC_GSI_VOMSLITE_VERSION} -/* SOVERSION ${XRD_SEC_GSI_VOMSLITE_SOVERSION} -/* LINK_INTERFACE_LIBRARIES "" ) -/* */ -/* and make sure that XrdSecgsiVOMSLite is added to TARGETS in 'install' */ -/* */ -/* ************************************************************************** */ - -#include -#include -#include -#include - -#include "XrdVersion.hh" - -#include "XrdCrypto/XrdCryptosslAux.hh" -#include "XrdCrypto/XrdCryptosslgsiAux.hh" -#include "XrdCrypto/XrdCryptoX509.hh" -#include "XrdCrypto/XrdCryptoX509Chain.hh" -#include "XrdOuc/XrdOucString.hh" -#include "XrdSec/XrdSecEntity.hh" -#include "XrdSecgsi/XrdSecgsiTrace.hh" -#include "XrdSut/XrdSutBucket.hh" - - -/******************************************************************************/ -/* V e r s i o n I n f o r m a t i o n */ -/******************************************************************************/ - -XrdVERSIONINFO(XrdSecgsiVOMSFun,secgsivoms); - -XrdVERSIONINFO(XrdSecgsiVOMSInit,secgsivoms); - -/******************************************************************************/ -/* G l o b a l s */ -/******************************************************************************/ - -extern XrdOucTrace *gsiTrace; - -#ifndef SafeFree -#define SafeFree(x) { if (x) free(x) ; x = 0; } -#endif - -/******************************************************************************/ -/* X r d S e c g s i V O M S F u n */ -/******************************************************************************/ - -// -// Main function -// -extern "C" -{ -int XrdSecgsiVOMSFun(XrdSecEntity &ent) -{ - // Implementation of XrdSecgsiAuthzFun extracting the information from the - // proxy chain in entity.creds - EPNAME("VOMSFunLite"); - - XrdCryptoX509Chain *c = (XrdCryptoX509Chain *) ent.creds; - if (!c) { - PRINT("ERROR: no proxy chain found!"); - return -1; - } - - XrdCryptoX509 *xp = c->End(); - if (!xp) { - PRINT("ERROR: no proxy certificate in chain!"); - return -1; - } - - // Extract the information - XrdOucString vatts; - int rc = 0; - if ((rc = XrdSslgsiX509GetVOMSAttr(xp, vatts)) != 0) { - if (strstr(xp->Subject(), "CN=limited proxy")) { - xp = c->SearchBySubject(xp->Issuer()); - rc = XrdSslgsiX509GetVOMSAttr(xp, vatts); - } - if (rc != 0) { - if (rc > 0) { - DEBUG("No VOMS attributes in proxy chain"); - } else { - PRINT("ERROR: problem extracting VOMS attributes"); - } - return -1; - } - } - - int from = 0; - XrdOucString vat; - while ((from = vatts.tokenize(vat, from, ',')) != -1) { - XrdOucString vo, role, grp; - if (vat.length() > 0) { - // The attribute is in the form - // /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap] - int isl = vat.find('/', 1); - if (isl != STR_NPOS) vo.assign(vat, 1, isl - 1); - int igr = vat.find("/Role=", 1); - if (igr != STR_NPOS) grp.assign(vat, 0, igr - 1); - int irl = vat.find("Role="); - if (irl != STR_NPOS) { - role.assign(vat, irl + 5); - isl = role.find('/'); - role.erase(isl); - } - if (ent.vorg) { - if (vo != (const char *) ent.vorg) { - DEBUG("WARNING: found a second VO ('"< 0) ent.vorg = strdup(vo.c_str()); - } - if (grp.length() > 0 && (!ent.grps || grp.length() > strlen(ent.grps))) { - SafeFree(ent.grps); - ent.grps = strdup(grp.c_str()); - } - if (role.length() > 0 && role != "NULL" && !ent.role) { - ent.role = strdup(role.c_str()); - } - } - } - - // Save the whole string in endorsements - SafeFree(ent.endorsements); - if (vatts.length() > 0) ent.endorsements = strdup(vatts.c_str()); - - // Notify if did not find the main info (the VO ...) - if (!ent.vorg) { - PRINT("WARNING: no VO found! (VOMS attributes: '"<