XRootD
XrdSecProtocolgsi Class Reference

#include <XrdSecProtocolgsi.hh>

+ Inheritance diagram for XrdSecProtocolgsi:
+ Collaboration diagram for XrdSecProtocolgsi:

Public Member Functions

 XrdSecProtocolgsi (int opts, const char *hname, XrdNetAddrInfo &endPoint, const char *parms=0)
 
virtual ~XrdSecProtocolgsi ()
 
int Authenticate (XrdSecCredentials *cred, XrdSecParameters **parms, XrdOucErrInfo *einfo=0)
 
int Decrypt (const char *inbuf, int inlen, XrdSecBuffer **outbuf)
 
void Delete ()
 Delete the protocol object. DO NOT use C++ delete() on this object. More...
 
int Encrypt (const char *inbuf, int inlen, XrdSecBuffer **outbuf)
 
XrdSecCredentialsgetCredentials (XrdSecParameters *parm=0, XrdOucErrInfo *einfo=0)
 
int getKey (char *kbuf=0, int klen=0)
 
int setKey (char *kbuf, int klen)
 
int Sign (const char *inbuf, int inlen, XrdSecBuffer **outbuf)
 
int Verify (const char *inbuf, int inlen, const char *sigbuf, int siglen)
 
- Public Member Functions inherited from XrdSecProtocol
 XrdSecProtocol (const char *pName)
 Constructor. More...
 
virtual bool needTLS ()
 Check if this protocol requires TLS to properly function. More...
 

Static Public Member Functions

static XrdOucTraceEnableTracing ()
 
static char * Init (gsiOptions o, XrdOucErrInfo *erp)
 

Friends

class gsiHSVars
 
class gsiOptions
 

Additional Inherited Members

- Public Attributes inherited from XrdSecProtocol
XrdSecEntity Entity
 
- Protected Member Functions inherited from XrdSecProtocol
virtual ~XrdSecProtocol ()
 Destructor (prevents use of direct delete). More...
 

Detailed Description

Definition at line 280 of file XrdSecProtocolgsi.hh.

Constructor & Destructor Documentation

◆ XrdSecProtocolgsi()

XrdSecProtocolgsi::XrdSecProtocolgsi ( int  opts,
const char *  hname,
XrdNetAddrInfo endPoint,
const char *  parms = 0 
)

Definition at line 293 of file XrdSecProtocolgsi.cc.

295  : XrdSecProtocol("gsi")
296 {
297  // Default constructor
298  EPNAME("XrdSecProtocolgsi");
299 
300  if (QTRACE(Authen)) { PRINT("constructing: "<<this); }
301 
302  // Create instance of the handshake vars
303  if ((hs = new gsiHSVars())) {
304  // Update time stamp
305  hs->TimeStamp = time(0);
306  // Local handshake variables
307  hs->Tty = (isatty(0) == 0 || isatty(1) == 0) ? 0 : 1;
308  } else {
309  PRINT("could not create handshake vars object");
310  }
311 
312  // Set host name and address
313  // The hostname is critical for the GSI protocol; it must match the potential
314  // names on the remote EEC. We default to the hostname requested by the user to
315  // the client (or proxy). However, as we may have been redirected to an IP
316  // address instead of an actual hostname, we must fallback to a reverse DNS lookup.
317  // As of time of testing (June 2018), EOS will redirect to an IP address to handle
318  // metadata commands and rely on the reverse DNS lookup for GSI security to function.
319  // Hence, this fallback likely needs to be kept for some time.
320  //
321  // We provide servers a switch and clients an environment variable to override all
322  // usage of DNS (processed on XrdSecProtocolgsiInit).
323  // Default is to fallback to DNS lookups in limited
324  // cases for backward compatibility.
325  expectedHost = NULL;
326  if (TrustDNS) {
327  if (!hname || !XrdNetAddrInfo::isHostName(hname)) {
328  Entity.host = strdup(endPoint.Name(""));
329  } else {
330  // At this point, hname still may possibly be a non-qualified domain name.
331  // If there is a '.' character, then we assume it is a qualified domain name --
332  // otherwise, we use DNS.
333  //
334  // NOTE: We can definitively test whether this is a qualified domain name by
335  // simply appending a '.' to `hname` and performing a lookup. However, this
336  // causes DNS to be used by every lookup - meaning we rely on the security
337  // of DNS for all cases; we want to avoid this.
338  if (strchr(hname, '.')) {
339  // We have a valid hostname; proceed.
340  Entity.host = strdup(hname);
341  } else {
342  XrdNetAddr xrd_addr;
343  char canonname[256];
344  if (!xrd_addr.Set(hname) || (xrd_addr.Format(canonname, 256, XrdNetAddrInfo::fmtName, XrdNetAddrInfo::noPort) <= 0)) {
345  Entity.host = strdup(hname);
346  } else {
347  Entity.host = strdup(canonname);
348  }
349  }
350  }
351  } else {
352  // We have been told via environment variable to not trust DNS; use the exact
353  // hostname provided by the user.
354 // char dnBuff[256];
355 // getdomainname(dnBuff, sizeof(dnBuff));
356  Entity.host = strdup(hname);
357  expectedHost = strdup(hname);
358  }
359  epAddr = endPoint;
360  Entity.addrInfo = &epAddr;
361 
362  // Init session variables
363  sessionCF = 0;
364  sessionKey = 0;
365  bucketKey = 0;
366  sessionMD = 0;
367  sessionKsig = 0;
368  sessionKver = 0;
369  sessionKver = 0;
370  proxyChain = 0;
371  useIV = false;
372 
373  //
374  // Notify, if required
375  DEBUG("constructing: host: "<< Entity.host);
376  DEBUG("p: "<<XrdSecPROTOIDENT<<", plen: "<<XrdSecPROTOIDLEN);
377  //
378  // basic settings
379  options = opts;
380  srvMode = 0;
381 
382  //
383  // Mode specific initializations
384  if (Server) {
385  srvMode = 1;
386  DEBUG("mode: server");
387  } else {
388  DEBUG("mode: client");
389  //
390  // Decode received buffer
391  if (parms) {
392  XrdOucString p("&P=gsi,");
393  p += parms;
394  hs->Parms = new XrdSutBuffer(p.c_str(), p.length());
395  }
396  }
397 
398  // We are done
399  String vers = Version;
400  vers.insert('.',vers.length()-2);
401  vers.insert('.',vers.length()-5);
402  DEBUG("object created: v"<<vers.c_str());
403 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
#define PRINT(y)
static const kXR_int32 Version
#define XrdSecPROTOIDLEN
#define XrdSecPROTOIDENT
struct myOpts opts
static const int noPort
Do not add port number.
static bool isHostName(const char *name)
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtName
Hostname if it is resolvable o/w use fmtAddr.
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
void insert(const int i, int start=-1)
const char * c_str() const
int length() const
XrdNetAddrInfo * addrInfo
Entity's connection details.
Definition: XrdSecEntity.hh:80
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70
XrdSecEntity Entity
XrdSecProtocol(const char *pName)
Constructor.
XrdSutBuffer * Parms

References XrdSecEntity::addrInfo, XrdOucString::c_str(), DEBUG, XrdSecProtocol::Entity, EPNAME, XrdNetAddrInfo::fmtName, XrdNetAddrInfo::Format(), gsiHSVars, XrdSecEntity::host, XrdOucString::insert(), XrdNetAddrInfo::isHostName(), XrdOucString::length(), XrdNetAddrInfo::Name(), XrdNetAddrInfo::noPort, opts, gsiHSVars::Parms, PRINT, QTRACE, XrdNetAddr::Set(), gsiHSVars::TimeStamp, gsiHSVars::Tty, Version, XrdSecPROTOIDENT, and XrdSecPROTOIDLEN.

+ Here is the call graph for this function:

◆ ~XrdSecProtocolgsi()

virtual XrdSecProtocolgsi::~XrdSecProtocolgsi ( )
inlinevirtual

Definition at line 294 of file XrdSecProtocolgsi.hh.

294 {} // Delete() does it all

Member Function Documentation

◆ Authenticate()

int XrdSecProtocolgsi::Authenticate ( XrdSecCredentials cred,
XrdSecParameters **  parms,
XrdOucErrInfo einfo = 0 
)
virtual

Authenticate a client.

Parameters
credCredentials supplied by the client.
parmsPlace where the address of additional authentication data is to be placed for another autrhentication handshake.
einfoThe error information object where error messages should be placed. The messages are returned to the client. Should einfo be null, messages should be written to stderr.
Returns
> 0 -> parms present (more authentication needed) = 0 -> Entity present (authentication suceeded) < 0 -> einfo present (error has occurred)

Implements XrdSecProtocol.

Definition at line 1748 of file XrdSecProtocolgsi.cc.

1751 {
1752  //
1753  // Check if we have any credentials or if no credentials really needed.
1754  // In either case, use host name as client name
1755  EPNAME("Authenticate");
1756 
1757  //
1758  // If cred buffer is two small or empty assume host protocol
1759  if (cred->size <= (int)XrdSecPROTOIDLEN || !cred->buffer) {
1760  strncpy(Entity.prot, "host", sizeof(Entity.prot));
1761  return 0;
1762  }
1763 
1764  // Handshake vars conatiner must be initialized at this point
1765  if (!hs)
1766  return ErrS(Entity.tident,ei,0,0,0,kGSErrError,
1767  "handshake var container missing",
1768  "protocol initialization problems");
1769 
1770  // Update time stamp
1771  hs->TimeStamp = time(0);
1772 
1773  //
1774  // ID of this handshaking
1775  if (hs->ID.length() <= 0)
1776  hs->ID = Entity.tident;
1777  DEBUG("handshaking ID: " << hs->ID);
1778 
1779  // Local vars
1780  int kS_rc = kgST_more;
1781  int step = 0;
1782  int nextstep = 0;
1783  char *bpub = 0;
1784  int lpub = 0;
1785  bool vomsFailed = false;
1786  const char *stepstr = 0;
1787  String Message;
1788  String CryptList;
1789  String Ciphers;
1790  String Host;
1791  String SrvPuKExp;
1792  String Salt;
1793  String RndmTag;
1794  String ClntMsg(256);
1795  // Buffer related
1796  XrdSutBuffer *bpar = 0; // Global buffer
1797  XrdSutBuffer *bmai = 0; // Main buffer
1798  XrdSutBucket *bck = 0; // Generic bucket
1799  // Proxy export related
1800  XrdOucString spxy;
1801  XrdSutBucket *bpxy = 0;
1802 
1803  //
1804  // Decode received buffer
1805  if (!(bpar = new XrdSutBuffer((const char *)cred->buffer,cred->size)))
1806  return ErrS(hs->ID,ei,0,0,0,kGSErrDecodeBuffer,"global",stepstr);
1807  //
1808  // Check protocol ID name
1809  if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
1810  return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrBadProtocol,stepstr);
1811  //
1812  // The step indicates what we are supposed to do
1813  step = bpar->GetStep();
1814  stepstr = ClientStepStr(step);
1815  // Dump, if requested
1816  XrdOucString bmsg;
1817  if (QTRACE(Dump)) {
1818  bmsg.form("IN: bpar: %s", stepstr);
1819  bpar->Dump(bmsg.c_str());
1820  }
1821  //
1822  // Parse input buffer
1823  if (ParseServerInput(bpar, &bmai, ClntMsg) == -1) {
1824  DEBUG(ClntMsg);
1825  return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrParseBuffer,ClntMsg.c_str(),stepstr);
1826  }
1827  //
1828  // Version
1829  DEBUG("version run by client: "<< hs->RemVers);
1830  DEBUG("options req by client: "<< hs->Options);
1831  //
1832  // Dump, if requested
1833  if (QTRACE(Dump)) {
1834  if (bmai) {
1835  bmsg.form("IN: bmai: %s", stepstr);
1836  bmai->Dump(bmsg.c_str());
1837  }
1838  }
1839  //
1840  // Check random challenge
1841  if (!CheckRtag(bmai, ClntMsg))
1842  return ErrS(hs->ID,ei,bpar,bmai,0,kGSErrBadRndmTag,stepstr,ClntMsg.c_str());
1843 
1844  // Extract the VOMS attrbutes, if required
1845  XrdCryptoX509ExportChain_t X509ExportChain = (sessionCF) ? sessionCF->X509ExportChain() : 0;
1846  if (!X509ExportChain) {
1847  // Error
1848  return ErrS(hs->ID,ei,0,0,0,kGSErrError,
1849  "crypto factory function for chain export not found");
1850  }
1851 
1852  //
1853  // Now action depens on the step
1854  switch (step) {
1855 
1856  case kXGC_certreq:
1857  //
1858  // Client required us to send our certificate and cipher DH public parameters:
1859  // add first this last one.
1860  // Extract buffer with public info for the cipher agreement
1861  if (!(bpub = hs->Rcip->Public(lpub)))
1862  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrNoPublic,
1863  "session",stepstr);
1864 
1865  // If client supports decoding of signed DH, do sign them
1866  if (hs->RemVers >= XrdSecgsiVersDHsigned) {
1867  bck = new XrdSutBucket(bpub,lpub,kXRS_cipher);
1868  if (sessionKsig) {
1869  //
1870  // Encrypt server DH public parameters with server key
1871  if (sessionKsig->EncryptPrivate(*bck) <= 0)
1872  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrExportPuK,
1873  "encrypting server DH public parameters",stepstr);
1874  } else {
1875  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrExportPuK,
1876  "server signing key undefined!",stepstr);
1877  }
1878  } else {
1879  // Previous naming
1880  bck = new XrdSutBucket(bpub,lpub,kXRS_puk);
1881  }
1882 
1883  //
1884  // Add it to the global list
1885  if (bpar->AddBucket(bck) != 0)
1886  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrAddBucket,
1887  "main",stepstr);
1888 
1889  //
1890  // Add bucket with list of supported ciphers
1891  if (bpar->AddBucket(DefCipher,kXRS_cipher_alg) != 0)
1892  return ErrS(hs->ID,ei,bpar,bmai,0,
1894  //
1895  // Add bucket with list of supported MDs
1896  if (bpar->AddBucket(DefMD,kXRS_md_alg) != 0)
1897  return ErrS(hs->ID,ei,bpar,bmai,0,
1899  //
1900  // Add the server certificate
1901  bpar->AddBucket(hs->Cbck);
1902 
1903  // We are done for the moment
1904  nextstep = kXGS_cert;
1905  break;
1906 
1907  case kXGC_cert:
1908  //
1909  // Client sent its own credentials: their are checked in
1910  // ParseServerInput, so if we are here they are OK
1911  kS_rc = kgST_ok;
1912  nextstep = kXGS_none;
1913 
1914  if (GMAPOpt > 0) {
1915  // Get name from gridmap
1916  String name;
1917  QueryGMAP(hs->Chain, hs->TimeStamp, name);
1918  DEBUG("username(s) associated with this DN: "<<name);
1919  if (name.length() <= 0) {
1920  // Grid map lookup failure
1921  if (GMAPOpt == 2) {
1922  // It was required, so we fail
1923  kS_rc = kgST_error;
1924  PRINT("ERROR: user mapping required, but lookup failed - failure");
1925  break;
1926  } else {
1927  NOTIFY("WARNING: user mapping lookup failed - use DN or DN-hash as name");
1928  }
1929  } else {
1930  //
1931  // Extract user login name, if any
1932  XrdSutBucket *bck = 0;
1933  String user;
1934  if ((bck = bmai->GetBucket(kXRS_user))) {
1935  bck->ToString(user);
1936  bmai->Deactivate(kXRS_user);
1937  }
1938  DEBUG("target user: "<<user);
1939  if (user.length() > 0) {
1940  // Check if the wanted username is authorized
1941  String u;
1942  int from = 0;
1943  bool ok = 0;
1944  while ((from = name.tokenize(u, from, ',')) != -1) {
1945  if (user == u) { ok = 1; break; }
1946  }
1947  if (ok) {
1948  name = u;
1949  DEBUG("DN mapping: requested user is authorized: name is '"<<name<<"'");
1950  } else {
1951  // The requested username is not in the list; we warn and default to the first
1952  // found (to be Globus compliant)
1953  if (name.find(',') != STR_NPOS) name.erase(name.find(','));
1954  PRINT("WARNING: user mapping lookup ok, but the requested user is not"
1955  " authorized ("<<user<<"). Instead, mapped as " << name << ".");
1956  }
1957  } else {
1958  // No username requested: we default to the first found (to be Globus compliant)
1959  if (name.find(',') != STR_NPOS) name.erase(name.find(','));
1960  DEBUG("user mapping lookup successful: name is '"<<name<<"'");
1961  }
1962  Entity.name = strdup(name.c_str());
1963  Entity.eaAPI->Add("gridmap.name", "1", true);
1964  }
1965  }
1966  // If not set, use DN
1967  if (!Entity.name || (strlen(Entity.name) <= 0)) {
1968  // No grid map: set the hash of the client DN as name
1969  if (!GMAPuseDNname && hs->Chain->EEChash()) {
1970  Entity.name = strdup(hs->Chain->EEChash());
1971  } else if (GMAPuseDNname && hs->Chain->EECname()) {
1972  Entity.name = strdup(hs->Chain->EECname());
1973  } else {
1974  PRINT("WARNING: DN missing: corruption? ");
1975  }
1976  }
1977 
1978  // Add the DN as default moninfo if requested (the authz plugin may change this)
1979  if (MonInfoOpt > 0 || ShowDN) {
1980  const char *theDN = hs->Chain->EECname();
1981  if (theDN) {
1982  if (ShowDN && !GMAPuseDNname) {
1983  PRINT(Entity.name<<" Subject DN='"<<theDN<<"'");
1984  }
1985  if (MonInfoOpt > 0) Entity.moninfo = strdup(theDN);
1986  }
1987  }
1988 
1989  if (VOMSAttrOpt > vatIgnore && VOMSFun) {
1990  // Fill the information needed by the external function
1991  if (VOMSCertFmt == 1) {
1992  // PEM base64
1993  bpxy = (*X509ExportChain)(hs->Chain, true);
1994  bpxy->ToString(spxy);
1995  delete bpxy;
1996  Entity.creds = strdup(spxy.c_str());
1997  Entity.credslen = spxy.length();
1998  } else {
1999  // Raw (opaque) format, to be used with XrdCrypto
2000  Entity.creds = (char *) hs->Chain;
2001  Entity.credslen = 0;
2002  }
2003  if ((*VOMSFun)(Entity) != 0) {
2004  vomsFailed = true;
2005  if (VOMSAttrOpt == vatRequire) {
2006  // Error
2007  kS_rc = kgST_error;
2008  PRINT("ERROR: the VOMS extraction plug-in reported "
2009  "authentication failure");
2010  break;
2011  }
2012  }
2013  NOTIFY("VOMS: Entity.vorg: "<< (Entity.vorg ? Entity.vorg : "<none>"));
2014  NOTIFY("VOMS: Entity.grps: "<< (Entity.grps ? Entity.grps : "<none>"));
2015  NOTIFY("VOMS: Entity.role: "<< (Entity.role ? Entity.role : "<none>"));
2016  NOTIFY("VOMS: Entity.endorsements: "<< (Entity.endorsements ? Entity.endorsements : "<none>"));
2017  }
2018 
2019  // Here prepare/extract the information for authorization
2020  spxy = "";
2021  bpxy = 0;
2022  if (AuthzFun && AuthzKey && (AuthzAlways || vomsFailed)) {
2023  // Fill the information needed by the external function
2024  if (AuthzCertFmt == 1) {
2025  // May have been already done
2026  if (!Entity.creds || (Entity.creds && Entity.credslen == 0)) {
2027  // PEM base64
2028  bpxy = (*X509ExportChain)(hs->Chain, true);
2029  bpxy->ToString(spxy);
2030  Entity.creds = strdup(spxy.c_str());
2031  Entity.credslen = spxy.length();
2032  // If not empty Entity.creds is a pointer to hs->Chain and
2033  // we need not to free it
2034  }
2035  } else {
2036  // May have been already done
2037  if (Entity.creds && Entity.credslen > 0) {
2038  // Entity.creds is in PEM form, we need to free it
2039  free(Entity.creds);
2040  // Raw (opaque) format, to be used with XrdCrypto
2041  Entity.creds = (char *) hs->Chain;
2042  Entity.credslen = 0;
2043  }
2044  }
2045  // Get the key
2046  char *key = 0;
2047  int lkey = 0;
2048  if ((lkey = (*AuthzKey)(Entity, &key)) < 0) {
2049  // Fatal error
2050  kS_rc = kgST_error;
2051  PRINT("ERROR: unable to get the key associated to this user");
2052  break;
2053  }
2054  const char *dn = (const char *)key;
2055  time_t now = hs->TimeStamp;
2056  // We may have it in the cache
2057  XrdSutCERef ceref;
2058  bool rdlock = false;
2059  XrdSutCacheArg_t arg = {kCE_ok, now, AuthzCacheTimeOut, kCE_disabled};
2060  XrdSutCacheEntry *cent = cacheAuthzFun.Get(dn, rdlock, AuthzFunCheck, (void *) &arg);
2061  if (!cent) {
2062  // Fatal error
2063  kS_rc = kgST_error;
2064  PRINT("ERROR: unable to get cache entry for dn: "<<dn);
2065  break;
2066  }
2067  ceref.Set(&(cent->rwmtx));
2068  if (!rdlock) {
2069  if (cent->buf1.buf)
2070  FreeEntity((XrdSecEntity *) cent->buf1.buf);
2071  SafeDelete(cent->buf1.buf);
2072  SafeDelete(cent->buf2.buf);
2073  }
2074  if (cent->status != kCE_ok) {
2075  int authzrc = 0;
2076  if ((authzrc = (*AuthzFun)(Entity)) != 0) {
2077  // Error
2078  kS_rc = kgST_error;
2079  PRINT("ERROR: the authz plug-in reported failure");
2080  SafeDelete(key);
2081  ceref.UnLock();
2082  break;
2083  } else {
2084  cent->status = kCE_ok;
2085  // Save a copy of the relevant Entity fields
2086  XrdSecEntity *se = new XrdSecEntity();
2087  int slen = 0;
2088  CopyEntity(&Entity, se, &slen);
2089  FreeEntity((XrdSecEntity *) cent->buf1.buf);
2090  SafeDelete(cent->buf1.buf);
2091  cent->buf1.buf = (char *) se;
2092  cent->buf1.len = slen;
2093  // Proxy expiration time
2094  int notafter = hs->Chain->End() ? hs->Chain->End()->NotAfter() : -1;
2095  cent->buf2.buf = (char *) new int(notafter);
2096  cent->buf2.len = sizeof(int);
2097  // Fill up the rest
2098  cent->cnt = 0;
2099  cent->mtime = now; // creation time
2100  // Notify
2101  DEBUG("Saved Entity to cacheAuthzFun ("<<slen<<" bytes)");
2102  }
2103  } else {
2104  // Fetch a copy of the saved entity
2105  int slen = 0;
2106  FreeEntity(&Entity);
2107  CopyEntity((XrdSecEntity *) cent->buf1.buf, &Entity, &slen);
2108  // Notify
2109  DEBUG("Got Entity from cacheAuthzFun ("<<slen<<" bytes)");
2110  }
2111  // Release lock
2112  ceref.UnLock();
2113  // Cleanup
2114  SafeDelArray(key);
2115  }
2116 
2117  // Export proxy for authorization, if required
2118  if (AuthzPxyWhat >= azFull) {
2119  if (bpxy && AuthzPxyWhat == azLast) {
2120  SafeDelete(bpxy); spxy = "";
2122  Entity.credslen = 0;
2123  }
2124  if (!bpxy) {
2125  if (AuthzPxyWhat == 1 && hs->Chain->End()) {
2126  bpxy = hs->Chain->End()->Export();
2127  } else {
2128  bpxy = (*X509ExportChain)(hs->Chain, true);
2129  }
2130  bpxy->ToString(spxy);
2131  }
2132  if (AuthzPxyWhere == azCred) {
2133  Entity.creds = strdup(spxy.c_str());
2134  Entity.credslen = spxy.length();
2135  } else {
2136  // This should be deprecated
2137  Entity.endorsements = strdup(spxy.c_str());
2138  }
2139  delete bpxy;
2140  NOTIFY("Entity.endorsements: "<<(void *)Entity.endorsements);
2141  NOTIFY("Entity.creds: "<<(void *)Entity.creds);
2142  NOTIFY("Entity.credslen: "<<Entity.credslen);
2143 
2144  } else if (bpxy) {
2145  // Cleanup
2146  SafeDelete(bpxy); spxy = "";
2147  }
2148 
2149  if (hs->RemVers >= 10100) {
2150  if (hs->PxyChain) {
2151  // The client is going to send over info for delegation
2152  kS_rc = kgST_more;
2153  nextstep = kXGS_pxyreq;
2154  }
2155  }
2156 
2157  break;
2158 
2159  case kXGC_sigpxy:
2160  //
2161  // Nothing to do after this
2162  kS_rc = kgST_ok;
2163  nextstep = kXGS_none;
2164  //
2165  // If something went wrong, print explanation
2166  if (ClntMsg.length() > 0) {
2167  PRINT(ClntMsg);
2168  }
2169  break;
2170 
2171  default:
2172  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrBadOpt, stepstr);
2173  }
2174 
2175  if (kS_rc == kgST_more) {
2176  //
2177  // Add message to client
2178  if (ClntMsg.length() > 0)
2179  if (bmai->AddBucket(ClntMsg,kXRS_message) != 0) {
2180  NOTIFY("problems adding bucket with message for client");
2181  }
2182  //
2183  // Serialize, encrypt and add to the global list
2184  if (AddSerialized('s', nextstep, hs->ID,
2185  bpar, bmai, kXRS_main, sessionKey) != 0) {
2186  return ErrS(hs->ID,ei,bpar,bmai,0, kGSErrSerialBuffer,
2187  "main / session cipher",stepstr);
2188  }
2189  //
2190  // Serialize the global buffer
2191  char *bser = 0;
2192  int nser = bpar->Serialized(&bser,'f');
2193  //
2194  // Dump, if requested
2195  if (QTRACE(Authen)) {
2196  bmsg.form("OUT: bpar: %s", ServerStepStr(bpar->GetStep()));
2197  bpar->Dump(bmsg.c_str());
2198  bmsg.form("OUT: bmai: %s", ServerStepStr(bpar->GetStep()));
2199  bmai->Dump(bmsg.c_str());
2200  }
2201  //
2202  // Create buffer for client
2203  *parms = new XrdSecParameters(bser,nser);
2204 
2205  } else {
2206  //
2207  // Cleanup handshake vars
2208  SafeDelete(hs);
2209  }
2210  //
2211  // We may release the buffers now
2212  REL2(bpar,bmai);
2213  //
2214  // All done
2215  return kS_rc;
2216 }
XrdSutBucket *(* XrdCryptoX509ExportChain_t)(XrdCryptoX509Chain *, bool)
#define STR_NPOS
XrdSecBuffer XrdSecParameters
static const char * ServerStepStr(int ksrv)
static bool AuthzFunCheck(XrdSutCacheEntry *e, void *a)
static const char * ClientStepStr(int kclt)
#define SafeDelete(x)
#define REL2(x, y)
@ kXGS_cert
@ kXGS_none
@ kXGS_pxyreq
#define XrdSecgsiVersDHsigned
@ kgST_ok
@ kgST_error
@ kgST_more
#define SafeFree(x)
#define SafeDelArray(x)
@ kXGC_sigpxy
@ kXGC_cert
@ kXGC_certreq
@ kGSErrExportPuK
@ kGSErrBadRndmTag
@ kGSErrParseBuffer
@ kGSErrBadProtocol
@ kGSErrNoPublic
@ kGSErrSerialBuffer
@ kGSErrDecodeBuffer
@ kGSErrBadOpt
@ kGSErrAddBucket
@ kGSErrError
#define NOTIFY(y)
XrdOucString CryptList
const char * XrdSutBuckStr(int kbck)
Definition: XrdSutAux.cc:121
@ kXRS_user
Definition: XrdSutAux.hh:65
@ kXRS_cipher_alg
Definition: XrdSutAux.hh:82
@ kXRS_message
Definition: XrdSutAux.hh:68
@ kXRS_puk
Definition: XrdSutAux.hh:61
@ kXRS_cipher
Definition: XrdSutAux.hh:62
@ kXRS_main
Definition: XrdSutAux.hh:58
@ kXRS_md_alg
Definition: XrdSutAux.hh:83
@ kCE_ok
@ kCE_disabled
virtual char * Public(int &lpub)
virtual XrdCryptoX509ExportChain_t X509ExportChain()
virtual int EncryptPrivate(const char *in, int lin, char *out, int lout)
XrdCryptoX509 * End() const
virtual XrdSutBucket * Export()
virtual time_t NotAfter()
int erase(int start=0, int size=0)
int find(const char c, int start=0, bool forward=1)
int form(const char *fmt,...)
int tokenize(XrdOucString &tok, int from, char del=':')
bool Add(XrdSecAttr &attr)
char * vorg
Entity's virtual organization(s)
Definition: XrdSecEntity.hh:71
int credslen
Length of the 'creds' data.
Definition: XrdSecEntity.hh:78
XrdSecEntityAttr * eaAPI
non-const API to attributes
Definition: XrdSecEntity.hh:92
const char * tident
Trace identifier always preset.
Definition: XrdSecEntity.hh:81
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
Definition: XrdSecEntity.hh:67
char * creds
Raw entity credentials or cert.
Definition: XrdSecEntity.hh:77
char * grps
Entity's group name(s)
Definition: XrdSecEntity.hh:73
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
char * role
Entity's role(s)
Definition: XrdSecEntity.hh:72
char * endorsements
Protocol specific endorsements.
Definition: XrdSecEntity.hh:75
char * moninfo
Information for monitoring.
Definition: XrdSecEntity.hh:76
void ToString(XrdOucString &s)
int AddBucket(char *bp=0, int sz=0, int ty=0)
Definition: XrdSutBuffer.hh:59
int Serialized(char **buffer, char opt='n')
void Dump(const char *stepstr=0, bool all=false)
int GetStep() const
Definition: XrdSutBuffer.hh:89
XrdSutBucket * GetBucket(kXR_int32 type, const char *tag=0)
const char * GetProtocol() const
Definition: XrdSutBuffer.hh:88
void Deactivate(kXR_int32 type)
void UnLock(bool reset=true)
void Set(XrdSysRWLock *lock)
XrdSysRWLock rwmtx
XrdSutCacheEntryBuf buf2
XrdSutCacheEntryBuf buf1
XrdSutCacheEntry * Get(const char *tag)
Definition: XrdSutCache.hh:54
X509Chain * PxyChain
XrdSutBucket * Cbck
X509Chain * Chain
XrdCryptoCipher * Rcip
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.

References XrdSecEntityAttr::Add(), XrdSutBuffer::AddBucket(), AuthzFunCheck(), XrdSutCacheEntryBuf::buf, XrdSutCacheEntry::buf1, XrdSutCacheEntry::buf2, XrdSecBuffer::buffer, XrdOucString::c_str(), gsiHSVars::Cbck, gsiHSVars::Chain, ClientStepStr(), XrdSutCacheEntry::cnt, XrdSecEntity::creds, XrdSecEntity::credslen, CryptList, XrdSutBuffer::Deactivate(), DEBUG, XrdSutBuffer::Dump(), XrdSecEntity::eaAPI, XrdCryptoX509Chain::EEChash(), XrdCryptoX509Chain::EECname(), XrdCryptoRSA::EncryptPrivate(), XrdCryptoX509Chain::End(), XrdSecEntity::endorsements, XrdSecProtocol::Entity, EPNAME, XrdOucString::erase(), XrdCryptoX509::Export(), XrdOucString::find(), XrdOucString::form(), XrdSutCache::Get(), XrdSutBuffer::GetBucket(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), XrdSecEntity::grps, gsiHSVars::ID, kCE_disabled, kCE_ok, kGSErrAddBucket, kGSErrBadOpt, kGSErrBadProtocol, kGSErrBadRndmTag, kGSErrDecodeBuffer, kGSErrError, kGSErrExportPuK, kGSErrNoPublic, kGSErrParseBuffer, kGSErrSerialBuffer, kgST_error, kgST_more, kgST_ok, kXGC_cert, kXGC_certreq, kXGC_sigpxy, kXGS_cert, kXGS_none, kXGS_pxyreq, kXRS_cipher, kXRS_cipher_alg, kXRS_main, kXRS_md_alg, kXRS_message, kXRS_puk, kXRS_user, XrdSutCacheEntryBuf::len, XrdOucString::length(), XrdSecEntity::moninfo, XrdSutCacheEntry::mtime, XrdSecEntity::name, XrdCryptoX509::NotAfter(), NOTIFY, gsiHSVars::Options, PRINT, XrdSecEntity::prot, XrdCryptoCipher::Public(), gsiHSVars::PxyChain, QTRACE, gsiHSVars::Rcip, REL2, gsiHSVars::RemVers, XrdSecEntity::role, XrdSutCacheEntry::rwmtx, SafeDelArray, SafeDelete, SafeFree, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSutCERef::Set(), XrdSecBuffer::size, XrdSutCacheEntry::status, STR_NPOS, XrdSecEntity::tident, gsiHSVars::TimeStamp, XrdOucString::tokenize(), XrdSutBucket::ToString(), XrdSutCERef::UnLock(), XrdSecEntity::vorg, XrdCryptoFactory::X509ExportChain(), XrdSecgsiVersDHsigned, XrdSecPROTOIDENT, XrdSecPROTOIDLEN, and XrdSutBuckStr().

+ Here is the call graph for this function:

◆ Decrypt()

int XrdSecProtocolgsi::Decrypt ( const char *  inbuff,
int  inlen,
XrdSecBuffer **  outbuff 
)
virtual

Decrypt data in inbuff using the session key.

Parameters
inbuffbuffer holding data to be decrypted.
inlenlength of the data.
outbuffplace where a pointer to the decrypted data is placed.
Returns
< 0 Failed,the return value is -errno (see Encrypt). = 0 Success, outbuff contains a pointer to the decrypted data. The caller is responsible for deleting the returned object.

Reimplemented from XrdSecProtocol.

Definition at line 1151 of file XrdSecProtocolgsi.cc.

1154 {
1155  // Decrypt data in inbuff and place it in outbuff.
1156  //
1157  // Returns: < 0 Failed,the return value is -errno (see Encrypt).
1158  // = 0 Success, outbuff contains a pointer to the encrypted data.
1159  EPNAME("Decrypt");
1160 
1161  // We must have a key
1162  if (!sessionKey)
1163  return -ENOENT;
1164 
1165  // And something to decrypt
1166  if (!inbuf || inlen <= 0 || !outbuf)
1167  return -EINVAL;
1168 
1169  // Size
1170  int liv = (useIV) ? sessionKey->MaxIVLength() : 0;
1171  int sz = inlen - liv;
1172  // Get output buffer
1173  char *buf = (char *)malloc(sessionKey->DecOutLength(sz) + liv);
1174  if (!buf)
1175  return -ENOMEM;
1176 
1177  // Get and set IV
1178  if (useIV) {
1179  char *iv = new char[liv];
1180  memcpy(iv, inbuf, liv);
1181  sessionKey->SetIV(liv, iv);
1182  delete[] iv;
1183  }
1184 
1185  // Decrypt
1186  int len = sessionKey->Decrypt(inbuf + liv, sz, buf);
1187  if (len <= 0) {
1188  SafeFree(buf);
1189  return -EINVAL;
1190  }
1191 
1192  // Create and fill output buffer
1193  *outbuf = new XrdSecBuffer(buf, len);
1194 
1195  // We are done
1196  DEBUG("decrypted buffer has "<<len<<" bytes");
1197  return 0;
1198 }
virtual void SetIV(int l, const char *iv)
virtual int Decrypt(const char *in, int lin, char *out)
virtual int DecOutLength(int l)
virtual int MaxIVLength() const
Generic structure to pass security information back and forth.

References DEBUG, XrdCryptoCipher::DecOutLength(), XrdCryptoCipher::Decrypt(), EPNAME, XrdCryptoCipher::MaxIVLength(), SafeFree, and XrdCryptoCipher::SetIV().

+ Here is the call graph for this function:

◆ Delete()

void XrdSecProtocolgsi::Delete ( )
virtual

Delete the protocol object. DO NOT use C++ delete() on this object.

Implements XrdSecProtocol.

Definition at line 1058 of file XrdSecProtocolgsi.cc.

1059 {
1060  // Deletes the protocol
1061  SafeFree(Entity.name);
1062  SafeFree(Entity.host);
1063  SafeFree(Entity.vorg);
1064  SafeFree(Entity.role);
1065  SafeFree(Entity.grps);
1066  SafeFree(Entity.caps);
1068  if (Entity.creds && Entity.credslen > 0) {
1070  } else {
1071  Entity.creds = 0;
1072  }
1073  Entity.credslen = 0;
1075  // Cleanup the handshake variables, if still there
1076  SafeDelete(hs);
1077  // Cleanup any other instance specific to this protocol
1078  SafeDelete(sessionKey); // Session Key (result of the handshake)
1079  SafeDelete(bucketKey); // Bucket with the key in export form
1080  SafeDelete(sessionMD); // Message Digest instance
1081  SafeDelete(sessionKsig); // RSA key to sign
1082  SafeDelete(sessionKver); // RSA key to verify
1083  if (proxyChain) proxyChain->Cleanup();
1084  SafeDelete(proxyChain); // Chain with delegated proxies
1085  SafeFree(expectedHost);
1086 
1087  delete this;
1088 }
void Cleanup(bool keepCA=0)
char * caps
Entity's capabilities.
Definition: XrdSecEntity.hh:74

References XrdSecEntity::caps, XrdCryptoX509Chain::Cleanup(), XrdSecEntity::creds, XrdSecEntity::credslen, XrdSecEntity::endorsements, XrdSecProtocol::Entity, XrdSecEntity::grps, XrdSecEntity::host, XrdSecEntity::moninfo, XrdSecEntity::name, XrdSecEntity::role, SafeDelete, SafeFree, and XrdSecEntity::vorg.

+ Here is the call graph for this function:

◆ EnableTracing()

XrdOucTrace * XrdSecProtocolgsi::EnableTracing ( )
static

Definition at line 2276 of file XrdSecProtocolgsi.cc.

2277 {
2278  // Initiate error logging and tracing
2279 
2280  eDest.logger(&Logger);
2281  GSITrace = new XrdOucTrace(&eDest);
2282  return GSITrace;
2283 }
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141

References eDest, XrdGlobal::Logger, and XrdSysError::logger().

Referenced by XrdSecProtocolgsiInit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Encrypt()

int XrdSecProtocolgsi::Encrypt ( const char *  inbuff,
int  inlen,
XrdSecBuffer **  outbuff 
)
virtual

Encrypt data in inbuff using the session key.

Parameters
inbuffbuffer holding data to be encrypted.
inlenlength of the data.
outbuffplace where a pointer to the encrypted data is placed.
Returns
< 0 Failed, the return value is -errno of the reason. Typically, -EINVAL - one or more arguments are invalid. -NOTSUP - encryption not supported by the protocol -ENOENT - Context not innitialized = 0 Success, outbuff contains a pointer to the encrypted data. The caller is responsible for deleting the returned object.

Reimplemented from XrdSecProtocol.

Definition at line 1096 of file XrdSecProtocolgsi.cc.

1099 {
1100  // Encrypt data in inbuff and place it in outbuff.
1101  //
1102  // Returns: < 0 Failed, the return value is -errno of the reason. Typically,
1103  // -EINVAL - one or more arguments are invalid.
1104  // -ENOTSUP - encryption not supported by the protocol
1105  // -EOVERFLOW - outbuff is too small to hold result
1106  // -ENOENT - Context not initialized
1107  // = 0 Success, outbuff contains a pointer to the encrypted data.
1108  //
1109  EPNAME("Encrypt");
1110 
1111  // We must have a key
1112  if (!sessionKey)
1113  return -ENOENT;
1114 
1115  // And something to encrypt
1116  if (!inbuf || inlen <= 0 || !outbuf)
1117  return -EINVAL;
1118 
1119  // Regenerate IV
1120  int liv = 0;
1121  char *iv = 0;
1122  if (useIV) {
1123  iv = sessionKey->RefreshIV(liv); // no need to call sessionKeySetIV as
1124  // RefreshIV will set the internal value
1125  }
1126 
1127  // Get output buffer
1128  char *buf = (char *)malloc(sessionKey->EncOutLength(inlen) + liv);
1129  if (!buf)
1130  return -ENOMEM;
1131  // IV at beginning
1132  memcpy(buf, iv, liv);
1133 
1134  // Encrypt
1135  int len = sessionKey->Encrypt(inbuf, inlen, buf + liv) + liv; // the size of initialization vector which is being appended at
1136  // the beginning of the output buffer has to be taken into account
1137  if (len <= 0) {
1138  SafeFree(buf);
1139  return -EINVAL;
1140  }
1141 
1142  // Create and fill output buffer
1143  *outbuf = new XrdSecBuffer(buf, len);
1144 
1145  // We are done
1146  DEBUG("encrypted buffer has "<<len<<" bytes");
1147  return 0;
1148 }
virtual char * RefreshIV(int &l)
virtual int Encrypt(const char *in, int lin, char *out)
virtual int EncOutLength(int l)

References DEBUG, XrdCryptoCipher::EncOutLength(), XrdCryptoCipher::Encrypt(), EPNAME, XrdCryptoCipher::RefreshIV(), and SafeFree.

+ Here is the call graph for this function:

◆ getCredentials()

XrdSecCredentials * XrdSecProtocolgsi::getCredentials ( XrdSecParameters parm = 0,
XrdOucErrInfo einfo = 0 
)
virtual

Generate client credentials to be used in the authentication process.

Parameters
parmPointer to the information returned by the server either in the initial login response or the authmore response.
einfoThe error information object where error messages should be placed. The messages are returned to the client. Should einfo be null, messages should be written to stderr.
Returns
Success: Pointer to credentials to sent to the server. The caller is responsible for deleting the object. Failure: Null pointer with einfo, if supplied, containing the reason for the failure.

Implements XrdSecProtocol.

Definition at line 1411 of file XrdSecProtocolgsi.cc.

1413 {
1414  // Query client for the password; remote username and host
1415  // are specified in 'parm'. File '.rootnetrc' is checked.
1416  EPNAME("getCredentials");
1417 
1418  // If we are a server the only reason to be here is to get the forwarded
1419  // or saved client credentials
1420  if (srvMode) {
1421  XrdSecCredentials *creds = 0;
1422  if (proxyChain) {
1423  // Export the proxy chain into a bucket
1424  XrdCryptoX509ExportChain_t ExportChain = sessionCF->X509ExportChain();
1425  if (ExportChain) {
1426  XrdSutBucket *bck = (*ExportChain)(proxyChain, 1);
1427  if (bck) {
1428  // We need to duplicate it because XrdSecCredentials uses
1429  // {malloc, free} instead of {new, delete}
1430  char *nbuf = (char *) malloc(bck->size);
1431  if (nbuf) {
1432  memcpy(nbuf, bck->buffer, bck->size);
1433  // Import the buffer in a XrdSecCredentials object
1434  creds = new XrdSecCredentials(nbuf, bck->size);
1435  }
1436  delete bck;
1437  }
1438  }
1439  }
1440  return creds;
1441  }
1442 
1443  // Handshake vars container must be initialized at this point
1444  if (!hs)
1445  return ErrC(ei,0,0,0,kGSErrError,
1446  "handshake var container missing","getCredentials");
1447  //
1448  // Nothing to do if buffer is empty
1449  if ((!parm && !hs->Parms) || (parm && (!(parm->buffer) || parm->size <= 0))) {
1450  if (hs->Iter == 0)
1451  return ErrC(ei,0,0,0,kGSErrNoBuffer,"missing parameters","getCredentials");
1452  else
1453  return (XrdSecCredentials *)0;
1454  }
1455 
1456  // We support passing the user {proxy, cert, key} paths via Url parameter
1457  char *upp = (ei && ei->getEnv()) ? ei->getEnv()->Get("xrd.gsiusrpxy") : 0;
1458  if (upp) urlUsrProxy = upp;
1459  upp = (ei && ei->getEnv()) ? ei->getEnv()->Get("xrd.gsiusrcrt") : 0;
1460  if (upp) urlUsrCert = upp;
1461  upp = (ei && ei->getEnv()) ? ei->getEnv()->Get("xrd.gsiusrkey") : 0;
1462  if (upp) urlUsrKey = upp;
1463 
1464  // Count interations
1465  (hs->Iter)++;
1466 
1467  // Update time stamp
1468  hs->TimeStamp = time(0);
1469 
1470  // Local vars
1471  int step = 0;
1472  int nextstep = 0;
1473  const char *stepstr = 0;
1474  char *bpub = 0;
1475  int lpub = 0;
1476  String CryptoMod = "";
1477  String Host = "";
1478  String RemID = "";
1479  String Emsg;
1480  String specID = "";
1481  String issuerHash = "";
1482  // Buffer / Bucket related
1483  XrdSutBuffer *bpar = 0; // Global buffer
1484  XrdSutBuffer *bmai = 0; // Main buffer
1485  XrdSutBucket *bck = 0; // Generic bucket
1486 
1487  //
1488  // Decode received buffer
1489  bpar = hs->Parms;
1490  if (!bpar && !(bpar = new XrdSutBuffer((const char *)parm->buffer,parm->size)))
1491  return ErrC(ei,0,0,0,kGSErrDecodeBuffer,"global",stepstr);
1492  // Ownership has been transferred
1493  hs->Parms = 0;
1494  //
1495  // Check protocol ID name
1496  if (strcmp(bpar->GetProtocol(),XrdSecPROTOIDENT))
1497  return ErrC(ei,bpar,bmai,0,kGSErrBadProtocol,stepstr);
1498  //
1499  // The step indicates what we are supposed to do
1500  if (!(step = bpar->GetStep())) {
1501  // The first, fake, step
1502  step = kXGS_init;
1503  bpar->SetStep(step);
1504  }
1505  stepstr = ServerStepStr(step);
1506  // Dump, if requested
1507  XrdOucString bmsg;
1508  if (QTRACE(Dump)) {
1509  bmsg.form("IN: bpar: %s", stepstr);
1510  bpar->Dump(bmsg.c_str());
1511  }
1512  //
1513  // Parse input buffer
1514  if (ParseClientInput(bpar, &bmai, Emsg) == -1) {
1515  DEBUG(Emsg<<" CF: "<<sessionCF);
1516  return ErrC(ei,bpar,bmai,0,kGSErrParseBuffer,Emsg.c_str(),stepstr);
1517  }
1518  // Dump, if requested
1519  if (QTRACE(Dump)) {
1520  if (bmai) {
1521  bmsg.form("IN: bmai: %s", stepstr);
1522  bmai->Dump(bmsg.c_str());
1523  }
1524  }
1525  //
1526  // Version
1527  DEBUG("version run by server: "<< hs->RemVers);
1528  //
1529  // Check random challenge
1530  if (!CheckRtag(bmai, Emsg))
1531  return ErrC(ei,bpar,bmai,0,kGSErrBadRndmTag,Emsg.c_str(),stepstr);
1532  //
1533  // Login name if any
1534  String user(Entity.name);
1535  if (user.length() <= 0) user = getenv("XrdSecUSER");
1536  //
1537  // Now action depens on the step
1538  nextstep = kXGC_none;
1539 
1540  XrdCryptoX509 *c = 0;
1541 
1542  switch (step) {
1543 
1544  case kXGS_init:
1545  //
1546  // Add bucket with cryptomod to the global list
1547  // (This must be always visible from now on)
1548  CryptoMod = hs->CryptoMod;
1549  if (hs->RemVers >= XrdSecgsiVersDHsigned && !(hs->HasPad)) CryptoMod += gNoPadTag;
1550  if (bpar->AddBucket(CryptoMod,kXRS_cryptomod) != 0)
1551  return ErrC(ei,bpar,bmai,0,
1553  //
1554  // Add bucket with our version to the main list
1555  if (bpar->MarshalBucket(kXRS_version,(kXR_int32)(Version)) != 0)
1556  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1557  XrdSutBuckStr(kXRS_version),"global",stepstr);
1558  //
1559  // Add our issuer hash
1560  c = hs->PxyChain->Begin();
1561  if (c->type == XrdCryptoX509::kCA) {
1562  issuerHash = c->SubjectHash();
1563  if (HashCompatibility && c->SubjectHash(1)) {
1564  issuerHash += "|"; issuerHash += c->SubjectHash(1); }
1565  } else {
1566  issuerHash = c->IssuerHash();
1567  if (HashCompatibility && c->IssuerHash(1)
1568  && strcmp(c->IssuerHash(1),c->IssuerHash())) {
1569  issuerHash += "|"; issuerHash += c->IssuerHash(1); }
1570  }
1571  while ((c = hs->PxyChain->Next()) != 0) {
1572  if (c->type != XrdCryptoX509::kCA)
1573  break;
1574  issuerHash = c->SubjectHash();
1575  if (HashCompatibility && c->SubjectHash(1)
1576  && strcmp(c->IssuerHash(1),c->IssuerHash())) {
1577  issuerHash += "|"; issuerHash += c->SubjectHash(1); }
1578  }
1579 
1580  DEBUG("Client issuer hash: " << issuerHash);
1581  if (bpar->AddBucket(issuerHash,kXRS_issuer_hash) != 0)
1582  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1583  XrdSutBuckStr(kXRS_issuer_hash),stepstr);
1584  //
1585  // Add bucket with our delegate proxy options
1586  if (hs->RemVers >= 10100) {
1587  if (bpar->MarshalBucket(kXRS_clnt_opts,(kXR_int32)(hs->Options)) != 0)
1588  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1589  XrdSutBuckStr(kXRS_clnt_opts),"global",stepstr);
1590  }
1591 
1592  //
1593  nextstep = kXGC_certreq;
1594  break;
1595 
1596  case kXGS_cert:
1597  //
1598  // We must have a session cipher at this point
1599  if (!(sessionKey))
1600  return ErrC(ei,bpar,bmai,0,
1601  kGSErrNoCipher,"session cipher",stepstr);
1602 
1603  //
1604  // Extract buffer with public info for the cipher agreement
1605  if (!(bpub = sessionKey->Public(lpub)))
1606  return ErrC(ei,bpar,bmai,0,
1607  kGSErrNoPublic,"session",stepstr);
1608 
1609  //
1610  // If server supports decoding of signed DH, do sign them
1611  if (hs->RemVers >= XrdSecgsiVersDHsigned) {
1612  bck = new XrdSutBucket(bpub,lpub,kXRS_cipher);
1613  if (sessionKsig) {
1614  // Encrypt client DH public parameters with client private key
1615  if (sessionKsig->EncryptPrivate(*bck) <= 0)
1616  return ErrC(ei,bpar,bmai,0, kGSErrExportPuK,
1617  "encrypting client DH public parameters",stepstr);
1618  } else {
1619  return ErrC(ei,bpar,bmai,0, kGSErrExportPuK,
1620  "client signing key undefined!",stepstr);
1621  }
1622  //
1623  // Add it to the global list
1624  if (bpar->AddBucket(bck) != 0)
1625  return ErrC(ei,bpar,bmai,0, kGSErrAddBucket, "main",stepstr);
1626  //
1627  // Export client public key
1628  XrdOucString cpub;
1629  if (sessionKsig->ExportPublic(cpub) < 0)
1630  return ErrC(ei,bpar,bmai,0, kGSErrExportPuK,
1631  "exporting client public key",stepstr);
1632  // Add it to the global list
1633  if (bpar->UpdateBucket(cpub.c_str(),cpub.length(),kXRS_puk) != 0)
1634  return ErrC(ei,bpar,bmai,0, kGSErrAddBucket,
1635  XrdSutBuckStr(kXRS_puk),"global",stepstr);
1636  } else {
1637  //
1638  // Add it to the global list
1639  if (bpar->UpdateBucket(bpub,lpub,kXRS_puk) != 0)
1640  return ErrC(ei,bpar,bmai,0, kGSErrAddBucket,
1641  XrdSutBuckStr(kXRS_puk),"global",stepstr);
1642  delete[] bpub; // bpub is being duplicated inside of 'UpdateBucket'
1643  }
1644 
1645  //
1646  // Add the proxy certificate
1647  bmai->AddBucket(hs->Cbck);
1648  //
1649  // Add login name if any, needed while chosing where to export the proxies
1650  if (user.length() > 0) {
1651  if (bmai->AddBucket(user, kXRS_user) != 0)
1652  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1653  XrdSutBuckStr(kXRS_user),stepstr);
1654  }
1655  //
1656  nextstep = kXGC_cert;
1657  break;
1658 
1659  case kXGS_pxyreq:
1660  //
1661  // If something went wrong, send explanation
1662  if (Emsg.length() > 0) {
1663  if (bmai->AddBucket(Emsg,kXRS_message) != 0)
1664  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1665  XrdSutBuckStr(kXRS_message),stepstr);
1666  }
1667  //
1668  // Add login name if any, needed while chosing where to export the proxies
1669  if (user.length() > 0) {
1670  if (bmai->AddBucket(user, kXRS_user) != 0)
1671  return ErrC(ei,bpar,bmai,0, kGSErrCreateBucket,
1672  XrdSutBuckStr(kXRS_user),stepstr);
1673  }
1674  //
1675  // The relevant buckets should already be in the buffers
1676  nextstep = kXGC_sigpxy;
1677  break;
1678 
1679  default:
1680  return ErrC(ei,bpar,bmai,0, kGSErrBadOpt,stepstr);
1681  }
1682 
1683  //
1684  // Serialize and encrypt
1685  if (AddSerialized('c', nextstep, hs->ID,
1686  bpar, bmai, kXRS_main, sessionKey) != 0) {
1687  return ErrC(ei,bpar,bmai,0,
1688  kGSErrSerialBuffer,"main",stepstr);
1689  }
1690  //
1691  // Serialize the global buffer
1692  char *bser = 0;
1693  int nser = bpar->Serialized(&bser,'f');
1694 
1695  if (QTRACE(Authen)) {
1696  bmsg.form("OUT: bpar: %s", ClientStepStr(bpar->GetStep()));
1697  bpar->Dump(bmsg.c_str());
1698  bmsg.form("OUT: bmai: %s", ClientStepStr(bpar->GetStep()));
1699  bmai->Dump(bmsg.c_str());
1700  }
1701  //
1702  // We may release the buffers now
1703  REL2(bpar,bmai);
1704  //
1705  // Return serialized buffer
1706  if (nser > 0) {
1707  DEBUG("returned " << nser <<" bytes of credentials");
1708  return new XrdSecCredentials(bser, nser);
1709  } else {
1710  NOTIFY("problems with final serialization");
1711  return (XrdSecCredentials *)0;
1712  }
1713 }
int kXR_int32
Definition: XPtypes.hh:89
XrdSecBuffer XrdSecCredentials
static const char * gNoPadTag
@ kXGS_init
@ kXGC_none
@ kGSErrNoCipher
@ kGSErrCreateBucket
@ kGSErrNoBuffer
XrdOucString CryptoMod
@ kXRS_issuer_hash
Definition: XrdSutAux.hh:80
@ kXRS_version
Definition: XrdSutAux.hh:71
@ kXRS_cryptomod
Definition: XrdSutAux.hh:57
@ kXRS_clnt_opts
Definition: XrdSutAux.hh:76
virtual int ExportPublic(char *out, int lout)
Definition: XrdCryptoRSA.cc:91
XrdCryptoX509 * Next()
XrdCryptoX509 * Begin()
virtual const char * SubjectHash(int)
virtual const char * IssuerHash(int)
EX509Type type
kXR_int32 size
Definition: XrdSutBucket.hh:47
int UpdateBucket(const char *bp, int sz, int ty)
void SetStep(int s)
Definition: XrdSutBuffer.hh:90
kXR_int32 MarshalBucket(kXR_int32 type, kXR_int32 code)

References XrdSutBuffer::AddBucket(), XrdCryptoX509Chain::Begin(), XrdSecBuffer::buffer, XrdSutBucket::buffer, XrdOucString::c_str(), gsiHSVars::Cbck, ClientStepStr(), CryptoMod, gsiHSVars::CryptoMod, DEBUG, XrdSutBuffer::Dump(), XrdCryptoRSA::EncryptPrivate(), XrdSecProtocol::Entity, EPNAME, XrdCryptoRSA::ExportPublic(), XrdOucString::form(), XrdOucEnv::Get(), XrdOucErrInfo::getEnv(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), gNoPadTag, gsiHSVars::HasPad, gsiHSVars::ID, XrdCryptoX509::IssuerHash(), gsiHSVars::Iter, XrdCryptoX509::kCA, kGSErrAddBucket, kGSErrBadOpt, kGSErrBadProtocol, kGSErrBadRndmTag, kGSErrCreateBucket, kGSErrDecodeBuffer, kGSErrError, kGSErrExportPuK, kGSErrNoBuffer, kGSErrNoCipher, kGSErrNoPublic, kGSErrParseBuffer, kGSErrSerialBuffer, kXGC_cert, kXGC_certreq, kXGC_none, kXGC_sigpxy, kXGS_cert, kXGS_init, kXGS_pxyreq, kXRS_cipher, kXRS_clnt_opts, kXRS_cryptomod, kXRS_issuer_hash, kXRS_main, kXRS_message, kXRS_puk, kXRS_user, kXRS_version, XrdOucString::length(), XrdSutBuffer::MarshalBucket(), XrdSecEntity::name, XrdCryptoX509Chain::Next(), NOTIFY, gsiHSVars::Options, gsiHSVars::Parms, XrdCryptoCipher::Public(), gsiHSVars::PxyChain, QTRACE, REL2, gsiHSVars::RemVers, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSutBuffer::SetStep(), XrdSecBuffer::size, XrdSutBucket::size, XrdCryptoX509::SubjectHash(), gsiHSVars::TimeStamp, XrdCryptoX509::type, XrdSutBuffer::UpdateBucket(), Version, XrdCryptoFactory::X509ExportChain(), XrdSecgsiVersDHsigned, XrdSecPROTOIDENT, and XrdSutBuckStr().

+ Here is the call graph for this function:

◆ getKey()

int XrdSecProtocolgsi::getKey ( char *  buff = 0,
int  size = 0 
)
virtual

Get the current encryption key (i.e. session key)

Parameters
buffbuffer to hold the key, and may be null.
sizesize of the buffer.
Returns
< 0 Failed, returned value if -errno (see Encrypt) >= 0 The size of the encyption key. The supplied buffer of length size hold the key. If the buffer address is supplied, the key is placed in the buffer.

Reimplemented from XrdSecProtocol.

Definition at line 1311 of file XrdSecProtocolgsi.cc.

1312 {
1313  // Get the current encryption key
1314  //
1315  // Returns: < 0 Failed, returned value if -errno (see Encrypt)
1316  // >= 0 The size of the encyption key. The supplied buffer of length
1317  // size hold the key. If the buffer address is 0, only the
1318  // size of the key is returned.
1319  //
1320  EPNAME("getKey");
1321 
1322  // Check if we have to serialize the key
1323  if (!bucketKey) {
1324 
1325  // We must have a key for that
1326  if (!sessionKey)
1327  // Invalid call
1328  return -ENOENT;
1329  // Create bucket
1330  bucketKey = sessionKey->AsBucket();
1331  }
1332 
1333  // Prepare output now, if we have any
1334  if (bucketKey) {
1335  // If are asked only the size, we are done
1336  if (kbuf == 0)
1337  return bucketKey->size;
1338 
1339  // Check the size of the buffer
1340  if (klen < bucketKey->size)
1341  // Too small
1342  return -EOVERFLOW;
1343 
1344  // Copy the buffer
1345  memcpy(kbuf, bucketKey->buffer, bucketKey->size);
1346 
1347  // We are done
1348  DEBUG("session key exported");
1349  return bucketKey->size;
1350  }
1351 
1352  // Key exists but we could export it in bucket format
1353  return -ENOMEM;
1354 }
virtual XrdSutBucket * AsBucket()

References XrdCryptoCipher::AsBucket(), XrdSutBucket::buffer, DEBUG, EPNAME, and XrdSutBucket::size.

+ Here is the call graph for this function:

◆ Init()

char * XrdSecProtocolgsi::Init ( gsiOptions  o,
XrdOucErrInfo erp 
)
static

Definition at line 406 of file XrdSecProtocolgsi.cc.

407 {
408  // Static method to the configure the static part of the protocol
409  // Called once by XrdSecProtocolgsiInit
410  EPNAME("Init");
411  char *Failure = 0, *Parms = 0;
412 
413  //
414  // Debug an tracing
415  Debug = (opt.debug > -1) ? opt.debug : Debug;
416 
417  // We must have the tracing object at this point
418  // (initialized in XrdSecProtocolgsiInit)
419  if (!gsiTrace) {
420  ErrF(erp,kGSErrInit,"tracing object (gsiTrace) not initialized! cannot continue");
421  return Failure;
422  }
423  // Set debug mask ... also for auxilliary libs
424  int trace = 0, traceSut = 0, traceCrypto = 0;
425  if (Debug >= 3) {
426  trace = cryptoTRACE_Dump;
427  traceSut = sutTRACE_Dump;
428  traceCrypto = cryptoTRACE_Dump;
429  GSITrace->What = TRACE_ALL;
430  } else if (Debug >= 2) {
431  trace = cryptoTRACE_Debug;
432  traceSut = sutTRACE_Debug;
433  traceCrypto = cryptoTRACE_Debug;
434  GSITrace->What = TRACE_Debug;
435  GSITrace->What |= TRACE_Authen;
436  } else if (Debug >= 1) {
437  trace = cryptoTRACE_Debug;
438  traceSut = sutTRACE_Notify;
439  traceCrypto = cryptoTRACE_Notify;
440  GSITrace->What = TRACE_Debug;
441  }
442 
443  // ... also for auxilliary libs
444  XrdSutSetTrace(traceSut);
445  XrdCryptoSetTrace(traceCrypto);
446 
447  // Name hashing algorithm compatibility
448  if (opt.hashcomp == 0) HashCompatibility = 0;
449 
450  //
451  // Operation mode
452  Server = (opt.mode == 's');
453 
454  //
455  // CA verification level
456  //
457  // 0 do not verify
458  // 1 verify if self-signed; warn if not
459  // 2 verify in all cases; fail if not possible
460  //
461  if (opt.ca >= caNoVerify && opt.ca <= caVerify)
462  CACheck = opt.ca;
463  DEBUG("option CACheck: "<<getOptName(caVerOpts,CACheck));
464 
465  //
466  // Check existence of CA directory
467  struct stat st;
468  if (opt.certdir) {
469  DEBUG("testing CA dir(s): "<<opt.certdir);
470  String CAtmp;
471  String tmp = opt.certdir;
472  String dp;
473  int from = 0;
474  while ((from = tmp.tokenize(dp, from, ',')) != -1) {
475  if (dp.length() > 0) {
476  if (XrdSutExpand(dp) == 0) {
477  if (stat(dp.c_str(),&st) == -1) {
478  if (errno == ENOENT) {
479  ErrF(erp,kGSErrError,"CA directory non existing",dp.c_str());
480  PRINT(erp->getErrText());
481  } else {
482  ErrF(erp,kGSErrError,"cannot stat CA directory",dp.c_str());
483  PRINT(erp->getErrText());
484  }
485  } else {
486  if (!(dp.endswith('/'))) dp += '/';
487  if (!(CAtmp.endswith(','))) CAtmp += ',';
488  CAtmp += dp;
489  }
490  } else {
491  PRINT("Warning: could not expand: "<<dp);
492  }
493  }
494  }
495  if (CAtmp.length() > 0)
496  CAdir = CAtmp;
497  }
498  DEBUG("using CA dir(s): "<<CAdir);
499 
500  //
501  // CRL check level
502  //
503  // 0 do not care
504  // 1 use if available
505  // 2 require
506  // 3 require not expired
507  // 12 require; try download if missing
508  // 13 require not expired; try download if missing
509  //
510  const char *cocrl[] = { "do-not-care", "use-if-available", "require", "require-not-expired" };
511  const char *codwld[] = { "no", "yes"};
512  if (opt.crl >= crlUpdate) {
513  CRLDownload = 1;
514  opt.crl %= 10;
515  }
516  if (opt.crl >= crlIgnore && opt.crl <= crlRequire)
517  CRLCheck = opt.crl;
518  DEBUG("option CRLCheck: "<<CRLCheck<<" ('"<<cocrl[CRLCheck]<<"'; download? "<<
519  codwld[CRLDownload]<<")");
520 
521  //
522  // Check existence of CRL directory
523  if (opt.crldir) {
524 
525  DEBUG("testing CRL dir(s): "<<opt.crldir);
526  String CRLtmp;
527  String tmp = opt.crldir;
528  String dp;
529  int from = 0;
530  while ((from = tmp.tokenize(dp, from, ',')) != -1) {
531  if (dp.length() > 0) {
532  if (XrdSutExpand(dp) == 0) {
533  if (stat(dp.c_str(),&st) == -1) {
534  if (errno == ENOENT) {
535  ErrF(erp,kGSErrError,"CRL directory non existing:",dp.c_str());
536  PRINT(erp->getErrText());
537  } else {
538  ErrF(erp,kGSErrError,"cannot stat CRL directory:",dp.c_str());
539  PRINT(erp->getErrText());
540  }
541  } else {
542  if (!(dp.endswith('/'))) dp += '/';
543  if (!(CRLtmp.endswith(','))) CRLtmp += ',';
544  CRLtmp += dp;
545  }
546  } else {
547  PRINT("Warning: could not expand: "<<dp);
548  }
549  }
550  }
551  if (CRLtmp.length() > 0)
552  CRLdir = CRLtmp;
553 
554  } else {
555  // Use CAdir
556  CRLdir = CAdir;
557  }
558  if (CRLCheck > 0)
559  DEBUG("using CRL dir(s): "<<CRLdir);
560 
561  //
562  // Default extension for CRL files
563  if (opt.crlext)
564  DefCRLext = opt.crlext;
565 
566  //
567  // Refresh or expiration time for CRLs
568  if (opt.crlrefresh)
569  CRLRefresh = opt.crlrefresh;
570  DEBUG("CRL information refreshed every "<<CRLRefresh<<" secs");
571 
572  //
573  // Honour trust / unstrust DNS settings (switch or env)
574  TrustDNS = opt.trustdns;
575  DEBUG("trust DNS option: "<<TrustDNS);
576 
577  //
578  // Enable/disable displaying the DN
579  ShowDN = opt.showDN;
580  DEBUG("show DN option: "<<ShowDN);
581 
582  //
583  // Server specific options
584  if (Server) {
585  //
586  // List of supported / wanted crypto modules
587  if (opt.clist)
588  DefCrypto = opt.clist;
589  //
590  // List of crypto modules
591  String cryptlist;
592  String crypts(DefCrypto,0,-1,64);
593  //
594  // Load crypto modules
595  XrdSutPFEntry ent;
596  XrdCryptoFactory *cf = 0;
597  if (crypts.length()) {
598  String ncpt = "";
599  int from = 0;
600  while ((from = crypts.tokenize(ncpt, from, '|')) != -1) {
601  if (ncpt.length() > 0 && ncpt[0] != '-') {
602  // Try loading
603  if ((cf = XrdCryptoFactory::GetCryptoFactory(ncpt.c_str()))) {
604  // Add it to the list
605  cryptF[ncrypt] = cf;
606  cryptID[ncrypt] = cf->ID();
607  cryptName[ncrypt].insert(cf->Name(),0,strlen(cf->Name())+1);
608  cf->SetTrace(trace);
609  cf->Notify();
610  // Ref cipher
611  if (!(refcip[ncrypt] = cf->Cipher(0,0,0))) {
612  PRINT("ref cipher for module "<<ncpt<<
613  " cannot be instantiated : disable");
614  from -= ncpt.length();
615  } else {
616  ncrypt++;
617  if (ncrypt >= XrdCryptoMax) {
618  PRINT("max number of crypto modules ("
619  << XrdCryptoMax <<") reached ");
620  break;
621  }
622  if (cryptlist.length()) cryptlist += ":";
623  cryptlist += ncpt;
624  if (!cf->HasPaddingSupport()) cryptlist += gNoPadTag;
625  }
626  } else {
627  PRINT("cannot instantiate crypto factory "<<ncpt<<
628  ": disable");
629  from -= ncpt.length();
630  }
631  }
632  }
633  }
634  //
635  // We need at least one valid crypto module
636  if (ncrypt <= 0) {
637  ErrF(erp,kGSErrInit,"could not find any valid crypto module");
638  PRINT(erp->getErrText());
639  return Failure;
640  }
641  //
642  // List of supported / wanted ciphers
643  if (opt.cipher)
644  DefCipher = opt.cipher;
645  // make sure we support all of them
646  String cip = "";
647  int from = 0;
648  while ((from = DefCipher.tokenize(cip, from, ':')) != -1) {
649  if (cip.length() > 0) {
650  int i = 0;
651  for (; i < ncrypt; i++) {
652  if (!(cryptF[i]->SupportedCipher(cip.c_str()))) {
653  // Not supported: drop from the list
654  DEBUG("cipher type not supported ("<<cip<<") - disabling");
655  from -= cip.length();
656  DefCipher.erase(cip);
657  }
658  }
659  }
660  }
661 
662  //
663  // List of supported / wanted Message Digest
664  if (opt.md)
665  DefMD = opt.md;
666  // make sure we support all of them
667  String md = "";
668  from = 0;
669  while ((from = DefMD.tokenize(md, from, ':')) != -1) {
670  if (md.length() > 0) {
671  int i = 0;
672  for (; i < ncrypt; i++) {
673  if (!(cryptF[i]->SupportedMsgDigest(md.c_str()))) {
674  // Not supported: drop from the list
675  PRINT("MD type not supported ("<<md<<") - disabling");
676  from -= md.length();
677  DefMD.erase(md);
678  }
679  }
680  }
681  }
682 
683  //
684  // Load server certificate and key
685  if (opt.cert) {
686  String TmpCert = opt.cert;
687  if (XrdSutExpand(TmpCert) == 0) {
688  SrvCert = TmpCert;
689  } else {
690  PRINT("Could not expand: "<<opt.cert<<": use default");
691  }
692  }
693  if (opt.key) {
694  String TmpKey = opt.key;
695  if (XrdSutExpand(TmpKey) == 0) {
696  SrvKey = TmpKey;
697  } else {
698  PRINT("Could not expand: "<<opt.key<<": use default");
699  }
700  }
701  //
702  // Check if we can read the certificate key
703  if (access(SrvKey.c_str(), R_OK)) {
704  PRINT("WARNING: process has no permission to read the certificate key file: "<<SrvKey);
705  }
706  int i = 0;
707  String certcalist = ""; // list of CA for server certificates
708  XrdSutCERef ceref;
709  for (; i<ncrypt; i++) {
710  if (!GetSrvCertEnt(ceref, cryptF[i], time(0), certcalist)) {
711  PRINT("problems loading srv cert");
712  ceref.UnLock();
713  continue;
714  }
715  }
716  // Rehash cache
717  ceref.UnLock();
718  //
719  // We must have got at least one valid certificate
720  if (cacheCert.Num() <= 0) {
721  ErrF(erp,kGSErrError,"no valid server certificate found");
722  PRINT(erp->getErrText());
723  return Failure;
724  }
725 
726  DEBUG("CA list: "<<certcalist);
727 
728  //
729  // GRID map check option
730  //
731  // 0 do not use (DN hash will be used as identifier)
732  // 1 use if available; otherwise as 0
733  // 2 require
734  // 10 do not use (DN name will be used as identifier)
735  // 11 use if available; otherwise as 10
736  const char *cogmap[] = { "do-not-use", "use-if-available", "require" };
737  const char *codnnm[] = { "DN hash", "DN name"};
738  if (opt.ogmap >= 10) {
739  GMAPuseDNname = 1;
740  opt.ogmap %= 10;
741  }
742  if (opt.ogmap >= 0 && opt.ogmap <= 2)
743  GMAPOpt = opt.ogmap;
744  DEBUG("user mapping file option: "<<cogmap[GMAPOpt]);
745  if (GMAPOpt < 2)
746  DEBUG("default option for entity name if no mapping available: "<<codnnm[(int)GMAPuseDNname]);
747 
748  //
749  // Check existence of GRID map file
750  if (opt.gridmap) {
751  String GMAPTmp = opt.gridmap;
752  if (XrdSutExpand(GMAPTmp) == 0) {
753  GMAPFile = GMAPTmp;
754  } else {
755  PRINT("Could not expand: "<<opt.gridmap<<": use default");
756  }
757  }
758  bool hasgmap = 0;
759  if (GMAPOpt > 0) {
760  // Initialize the GMap service
761  //
762  String pars;
763  if (Debug) pars += "dbg|";
764  if (opt.gmapto > 0) { pars += "to="; pars += (int)opt.gmapto; }
765  if (!(servGMap = XrdOucgetGMap(&eDest, GMAPFile.c_str(), pars.c_str()))) {
766  if (GMAPOpt > 1) {
767  ErrF(erp,kGSErrError,"error loading grid map file",GMAPFile.c_str());
768  PRINT(erp->getErrText());
769  return Failure;
770  } else {
771  NOTIFY("Grid map file: "<<GMAPFile<<" cannot be 'access'ed: do not use");
772  }
773  } else {
774  DEBUG("using grid map file: "<<GMAPFile);
775  hasgmap = 1;
776  }
777  }
778  //
779  // Load function be used to map DN to usernames, if specified
780  bool hasgmapfun = 0;
781  if (opt.gmapfun && GMAPOpt > 0) {
782  if (!(GMAPFun = LoadGMAPFun((const char *) opt.gmapfun,
783  (const char *) opt.gmapfunparms))) {
784  ErrF(erp, kGSErrError, "GMAP plug-in could not be loaded", opt.gmapfun);
785  PRINT(erp->getErrText());
786  return Failure;
787  } else {
788  hasgmapfun = 1;
789  }
790  }
791  //
792  // Disable GMAP if neither a grid mapfile nor a GMAP function are available
793  if (!hasgmap && !hasgmapfun) {
794  if (GMAPOpt > 1) {
795  ErrF(erp,kGSErrError,"User mapping required, but neither a grid mapfile"
796  " nor a mapping function are available");
797  PRINT(erp->getErrText());
798  return Failure;
799  }
800  GMAPOpt = 0;
801  }
802  //
803  // Authentication function
804  bool hasauthzfun = 0;
805  AuthzAlways = opt.authzcall;
806  if (opt.authzfun) {
807  if (!(AuthzFun = LoadAuthzFun((const char *) opt.authzfun,
808  (const char *) opt.authzfunparms, AuthzCertFmt))) {
809  ErrF(erp, kGSErrError, "Authz plug-in could not be loaded", opt.authzfun);
810  PRINT(erp->getErrText());
811  return Failure;
812  } else {
813  hasauthzfun = 1;
814  // Notify certificate format
815  if (AuthzCertFmt >= 0 && AuthzCertFmt <= 1) {
816  const char *ccfmt[] = { "raw", "PEM base64" };
817  DEBUG("authzfun: proxy certificate format: "<<ccfmt[AuthzCertFmt]);
818  } else {
819  NOTIFY("authzfun: proxy certificate format: unknown (code: "<<AuthzCertFmt<<")");
820  }
821  // Expiration of Authz related cache entries
822  if (opt.authzto > 0) {
823  AuthzCacheTimeOut = opt.authzto;
824  DEBUG("grid-map cache entries expire after "<<AuthzCacheTimeOut<<" secs");
825  }
826  }
827  }
828  //
829  // Expiration of GRIDMAP related cache entries
830  if (GMAPOpt > 0 && !hasauthzfun && opt.gmapto > 0) {
831  GMAPCacheTimeOut = opt.gmapto;
832  DEBUG("grid-map cache entries expire after "<<GMAPCacheTimeOut<<" secs");
833  }
834 
835  //
836  // Request for proxy export for authorization
837  // authzpxy = opt_what*10 + opt_where
838  // opt_what = 0 full chain
839  // 1 last proxy only
840  // opt_where = 1 Entity.creds
841  // 2 Entity.endorsements
842  if (opt.authzpxy) {
843  AuthzPxyWhat = opt.authzpxy / 10;
844  AuthzPxyWhere = opt.authzpxy % 10;
845  // Some notification
846  const char *capxy_what = (AuthzPxyWhat == 1) ? "'last proxy only'"
847  : "'full proxy chain'";
848  const char *capxy_where = (AuthzPxyWhere == 1) ? "XrdSecEntity.creds"
849  : "XrdSecEntity.endorsements";
850  DEBUG("Export proxy for authorization in '"<<capxy_where<<"': "<<capxy_what);
851  if (hasauthzfun) {
852  // Warn user about possible overwriting of Entity.creds or Entity.endorsements
853  PRINT("WARNING: proxy export for authz enabled: be aware that any setting of '"<<capxy_what<<
854  "' done by '"<<opt.authzfun<<"' will get overwritten with "<<capxy_what);
855  }
856  }
857 
858  //
859  // Handle delegated proxies options
860  if (opt.dlgpxy == -1) {
861  // Will not accept any delegated proxies
862  DEBUG("Will not accept delegated proxies");
863  } else {
864  // Ask the client to sign a delegated proxy; client may decide to forward its proxy
865  if (opt.dlgpxy == dlgReqSign)
866  PxyReqOpts |= kOptsSrvReq;
867 
868  // Exporting options (default none: delegated proxy kept in memory, in proxyChain)
869  if (opt.exppxy) {
870  if (!strcmp(opt.exppxy, "=creds")) {
871  // register the delegated proxy in Entity.creds (in HEX format)
872  PxyReqOpts |= kOptsPxCred;
873  DEBUG("Delegated proxy saved in Entity.creds ");
874  } else {
875  String TmpProxy = gUsrPxyDef;
876  if (strcmp(opt.exppxy, "=default"))
877  TmpProxy = opt.exppxy;
878  if (XrdSutExpand(TmpProxy) == 0) {
879  UsrProxy = TmpProxy;
880  } else {
881  UsrProxy = gUsrPxyDef;
882  UsrProxy += "u<uid>";
883  }
884  PxyReqOpts |= kOptsPxFile;
885  DEBUG("File template for delegated proxy: "<<UsrProxy);
886  }
887  }
888  DEBUG("Delegated proxies options: "<<PxyReqOpts);
889  }
890 
891  //
892  // VOMS attributes switch
893  // vomsat = 0 do not look for
894  // 1 extract if any (fill 'vorg', 'role'; the full string in 'endorsements');
895  // 2 require (fill 'vorg', 'role'; the full string in 'endorsements');
896  VOMSAttrOpt = (opt.vomsat <= vatRequire && opt.vomsat >= vatIgnore)
897  ? opt.vomsat : VOMSAttrOpt;
898 
899  //
900  // Alternative VOMS extraction function
901  if (opt.vomsfun) {
902  if (!(VOMSFun = LoadVOMSFun((const char *) opt.vomsfun,
903  (const char *) opt.vomsfunparms, VOMSCertFmt))) {
904  ErrF(erp, kGSErrError, "VOMS plug-in loading failed", opt.vomsfun);
905  PRINT(erp->getErrText());
906  return Failure;
907  } else {
908  // Notify certificate format
909  if (VOMSCertFmt >= 0 && VOMSCertFmt <= 1) {
910  const char *ccfmt[] = { "raw", "PEM base64" };
911  DEBUG("vomsfun: proxy certificate format: "<<ccfmt[VOMSCertFmt]);
912  } else {
913  char fbuff[64];
914  snprintf(fbuff, sizeof(fbuff), "%d", VOMSCertFmt);
915  ErrF(erp, kGSErrError, "VOMS plug-in returned invalid cert "
916  "format", fbuff);
917  PRINT(erp->getErrText());
918  return Failure;
919  }
920  }
921  } else opt.authzcall = AuthzAlways = 1;
922  DEBUG("VOMS attributes options: "<<getOptName(vomsatOpts, VOMSAttrOpt));
923 
924  //
925  // Default moninfo option
926  // 0 nothing
927  // 1 DN
928  MonInfoOpt = opt.moninfo;
929  const char *cmoninfo = (MonInfoOpt == 1) ? "DN" : "none";
930  DEBUG("Monitor information options: "<<cmoninfo);
931 
932  // Make sure we have a calist as the client can't do anything without it.
933  // If the cryptlist is empty the client will use the default one.
934  //
935  if (certcalist.length() == 0)
936  {ErrF(erp,kGSErrInit,"unable to generate ca cert hash list!");
937  PRINT(erp->getErrText());
938  return Failure;
939  }
940 
941  //
942  // Parms in the form:
943  // &P=gsi,v:<version>,c:<cryptomod>,ca:<list_of_srv_cert_ca>
944  Parms = new char[cryptlist.length()+3+12+certcalist.length()+5];
945  if (Parms) {
946  sprintf(Parms,"v:%d,c:%s,ca:%s",
947  Version,cryptlist.c_str(),certcalist.c_str());
948  } else {
949  ErrF(erp,kGSErrInit,"no system resources for 'Parms'");
950  PRINT(erp->getErrText());
951  return Failure;
952  }
953 
954  // Some notification
955  DEBUG("available crypto modules: "<<cryptlist);
956  DEBUG("issuer CAs of server certs (hashes): "<<certcalist);
957  }
958 
959  //
960  // Client specific options
961  if (!Server) {
962  // use default dir $(HOME)/.<prefix>
963  struct passwd *pw = getpwuid(getuid());
964  if (!pw) {
965  NOTIFY("WARNING: cannot get user information (uid:"<<getuid()<<")");
966  }
967  //
968  // Define user proxy file
969  UsrProxy = gUsrPxyDef;
970  if (opt.proxy) {
971  String TmpProxy = opt.proxy;
972  if (XrdSutExpand(TmpProxy) == 0) {
973  UsrProxy = TmpProxy;
974  } else {
975  PRINT("Could not expand: "<<opt.proxy<<": use default");
976  }
977  } else {
978  if (pw)
979  UsrProxy += (int)(pw->pw_uid);
980  }
981  // Define user certificate file
982  if (opt.cert) {
983  String TmpCert = opt.cert;
984  if (XrdSutExpand(TmpCert) == 0) {
985  UsrCert = TmpCert;
986  } else {
987  PRINT("Could not expand: "<<opt.cert<<": use default");
988  }
989  } else {
990  if (pw)
991  UsrCert.insert(XrdSutHome(),0);
992  }
993  // Define user private key file
994  if (opt.key) {
995  String TmpKey = opt.key;
996  if (XrdSutExpand(TmpKey) == 0) {
997  UsrKey = TmpKey;
998  } else {
999  PRINT("Could not expand: "<<opt.key<<": use default");
1000  }
1001  } else {
1002  if (pw)
1003  UsrKey.insert(XrdSutHome(),0);
1004  }
1005  // Define proxy validity at renewal
1006  if (opt.valid)
1007  PxyValid = opt.valid;
1008  // Set depth of signature path
1009  if (opt.deplen != DepLength)
1010  DepLength = opt.deplen;
1011  // Set number of bits for proxy key
1012  if (opt.bits > DefBits)
1013  DefBits = opt.bits;
1014  //
1015  // Delegate proxy options
1016  if (opt.dlgpxy > dlgIgnore) {
1017  PxyReqOpts |= kOptsSigReq;
1018  if (opt.dlgpxy == dlgSendpxy) {
1019  PxyReqOpts |= kOptsFwdPxy;
1020  } else {
1021  PxyReqOpts |= kOptsDlgPxy;
1022  }
1023  }
1024  //
1025  // No proxy options
1026  if (opt.createpxy) {
1027  PxyReqOpts |= kOptsCreatePxy;
1028  }
1029  //
1030  // Define valid CNs for the server certificates; default is null, which means that
1031  // the server CN must be in the form "*/<hostname>"
1032  if (opt.srvnames)
1033  SrvAllowedNames = opt.srvnames;
1034  //
1035  // Notify
1036  TRACE(Authen, "using certificate file: "<<UsrCert);
1037  TRACE(Authen, "using private key file: "<<UsrKey);
1038  TRACE(Authen, "proxy: file: "<<UsrProxy);
1039  TRACE(Authen, "proxy: validity: "<<PxyValid);
1040  TRACE(Authen, "proxy: depth of signature path: "<<DepLength);
1041  TRACE(Authen, "proxy: bits in key: "<<DefBits);
1042  TRACE(Authen, "server cert: allowed names: "<<SrvAllowedNames);
1043  if (!(PxyReqOpts & kOptsCreatePxy)) {
1044  TRACE(Authen, "allowing for pure cert/key authentication (no proxy) ");
1045  }
1046 
1047  // We are done
1048  Parms = (char *)"";
1049  }
1050 
1051  // We are done
1052  return Parms;
1053 }
#define TRACE_Debug
Definition: XrdCmsTrace.hh:37
void XrdCryptoSetTrace(kXR_int32 trace)
Definition: XrdCryptoAux.cc:49
static XrdSysError eDest(0,"crypto_")
#define cryptoTRACE_Notify
Definition: XrdCryptoAux.hh:49
#define cryptoTRACE_Dump
Definition: XrdCryptoAux.hh:47
#define cryptoTRACE_Debug
Definition: XrdCryptoAux.hh:48
XrdOucGMap * XrdOucgetGMap(XrdOucGMapArgs)
Definition: XrdOucGMap.cc:92
int stat(const char *path, struct stat *buf)
int access(const char *path, int amode)
static const char * gUsrPxyDef
XrdOucTrace * gsiTrace
@ kOptsSigReq
@ kOptsFwdPxy
@ kOptsPxCred
@ kOptsSrvReq
@ kOptsDlgPxy
@ kOptsCreatePxy
@ kOptsPxFile
#define XrdCryptoMax
@ kGSErrInit
#define TRACE_Authen
Definition: XrdSecTrace.hh:62
XrdOucString CAdir
XrdOucString CRLdir
int ncrypt
XrdOucString DefCrypto
int XrdSutExpand(XrdOucString &path)
Definition: XrdSutAux.cc:366
const char * XrdSutHome()
Definition: XrdSutAux.cc:465
void XrdSutSetTrace(kXR_int32 trace)
Definition: XrdSutAux.cc:93
#define sutTRACE_Notify
Definition: XrdSutAux.hh:100
#define sutTRACE_Debug
Definition: XrdSutAux.hh:99
#define sutTRACE_Dump
Definition: XrdSutAux.hh:98
if(Avsz)
#define TRACE(act, x)
Definition: XrdTrace.hh:63
#define TRACE_ALL
Definition: XrdTrace.hh:35
virtual bool HasPaddingSupport()
virtual void SetTrace(kXR_int32 trace)
char * Name() const
virtual XrdCryptoCipher * Cipher(const char *t, int l=0)
static XrdCryptoFactory * GetCryptoFactory(const char *factoryname)
virtual void Notify()
const char * getErrText()
bool endswith(char c)

References access(), gsiOptions::authzcall, gsiOptions::authzfun, gsiOptions::authzfunparms, gsiOptions::authzpxy, gsiOptions::authzto, gsiOptions::bits, XrdOucString::c_str(), gsiOptions::ca, CAdir, gsiOptions::cert, gsiOptions::certdir, XrdCryptoFactory::Cipher(), gsiOptions::cipher, gsiOptions::clist, gsiOptions::createpxy, gsiOptions::crl, CRLdir, gsiOptions::crldir, gsiOptions::crlext, gsiOptions::crlrefresh, cryptoTRACE_Debug, cryptoTRACE_Dump, cryptoTRACE_Notify, DEBUG, Macaroons::Debug, gsiOptions::debug, DefCrypto, gsiOptions::deplen, gsiOptions::dlgpxy, eDest, XrdOucString::endswith(), EPNAME, XrdOucString::erase(), gsiOptions::exppxy, XrdCryptoFactory::GetCryptoFactory(), XrdOucErrInfo::getErrText(), gsiOptions::gmapfun, gsiOptions::gmapfunparms, gsiOptions::gmapto, gNoPadTag, gsiOptions::gridmap, gsiTrace, gUsrPxyDef, gsiOptions::hashcomp, XrdCryptoFactory::HasPaddingSupport(), XrdCryptoFactory::ID(), if(), XrdOucString::insert(), gsiOptions::key, kGSErrError, kGSErrInit, kOptsCreatePxy, kOptsDlgPxy, kOptsFwdPxy, kOptsPxCred, kOptsPxFile, kOptsSigReq, kOptsSrvReq, XrdOucString::length(), gsiOptions::md, gsiOptions::mode, gsiOptions::moninfo, XrdCryptoFactory::Name(), ncrypt, XrdCryptoFactory::Notify(), NOTIFY, XrdSutCache::Num(), gsiOptions::ogmap, PRINT, gsiOptions::proxy, XrdCryptoFactory::SetTrace(), gsiOptions::showDN, gsiOptions::srvnames, stat(), sutTRACE_Debug, sutTRACE_Dump, sutTRACE_Notify, XrdOucString::tokenize(), TRACE, TRACE_ALL, TRACE_Authen, TRACE_Debug, gsiOptions::trustdns, XrdSutCERef::UnLock(), gsiOptions::valid, Version, gsiOptions::vomsat, gsiOptions::vomsfun, gsiOptions::vomsfunparms, XrdOucTrace::What, XrdCryptoMax, XrdCryptoSetTrace(), XrdOucgetGMap(), XrdSutExpand(), XrdSutHome(), and XrdSutSetTrace().

Referenced by XrdSecProtocolgsiInit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setKey()

int XrdSecProtocolgsi::setKey ( char *  buff,
int  size 
)
virtual

Set the current encryption key

Parameters
buffbuffer that holds the key.
sizesize of the key.
Returns
: < 0 Failed, returned value if -errno (see Encrypt) = 0 The new key has been set.

Reimplemented from XrdSecProtocol.

Definition at line 1357 of file XrdSecProtocolgsi.cc.

1358 {
1359  // Set the current encryption key
1360  //
1361  // Returns: < 0 Failed, returned value if -errno (see Encrypt)
1362  // 0 The new key has been set.
1363  //
1364  EPNAME("setKey");
1365 
1366  // Make sur that we can initialize the new key
1367  if (!kbuf || klen <= 0)
1368  // Invalid inputs
1369  return -EINVAL;
1370 
1371  if (!sessionCF)
1372  // Invalid context
1373  return -ENOENT;
1374 
1375  // Put the buffer key into a bucket
1376  XrdSutBucket *bck = new XrdSutBucket();
1377  if (!bck)
1378  // Cannot get buffer: out-of-resources?
1379  return -ENOMEM;
1380  // Set key buffer
1381  bck->SetBuf(kbuf, klen);
1382 
1383  // Init a new cipher from the bucket
1384  XrdCryptoCipher *newKey = sessionCF->Cipher(bck);
1385  if (!newKey) {
1386  SafeDelete(bck);
1387  return -ENOMEM;
1388  }
1389 
1390  // Delete current key
1391  SafeDelete(sessionKey);
1392 
1393  // Set the new key
1394  sessionKey = newKey;
1395 
1396  // Cleanup
1397  SafeDelete(bck);
1398 
1399  // Ok
1400  DEBUG("session key update");
1401  return 0;
1402 }
int SetBuf(const char *nb=0, int ns=0)

References XrdCryptoFactory::Cipher(), DEBUG, EPNAME, SafeDelete, and XrdSutBucket::SetBuf().

+ Here is the call graph for this function:

◆ Sign()

int XrdSecProtocolgsi::Sign ( const char *  inbuff,
int  inlen,
XrdSecBuffer **  outbuff 
)
virtual

Sign data in inbuff using the session key.

Parameters
inbuffbuffer holding data to be signed.
inlenlength of the data.
outbuffplace where a pointer to the signature is placed.
Returns
< 0 Failed,the return value is -errno (see Encrypt). = 0 Success, outbuff contains a pointer to the signature. The caller is responsible for deleting the returned object.

Reimplemented from XrdSecProtocol.

Definition at line 1201 of file XrdSecProtocolgsi.cc.

1204 {
1205  // Sign data in inbuff and place the signature in outbuf.
1206  //
1207  // Returns: < 0 Failed, returned value is -errno (see Encrypt).
1208  // = 0 Success, the return value is the length of the signature
1209  // placed in outbuf.
1210  //
1211  EPNAME("Sign");
1212 
1213  // We must have a PKI and a digest
1214  if (!sessionKsig || !sessionMD)
1215  return -ENOENT;
1216 
1217  // And something to sign
1218  if (!inbuf || inlen <= 0 || !outbuf)
1219  return -EINVAL;
1220 
1221  // Reset digest
1222  sessionMD->Reset(0);
1223 
1224  // Calculate digest
1225  sessionMD->Update(inbuf, inlen);
1226  sessionMD->Final();
1227 
1228  // Output length
1229  int lmax = sessionKsig->GetOutlen(sessionMD->Length());
1230  char *buf = (char *)malloc(lmax);
1231  if (!buf)
1232  return -ENOMEM;
1233 
1234  // Sign
1235  int len = sessionKsig->EncryptPrivate(sessionMD->Buffer(),
1236  sessionMD->Length(),
1237  buf, lmax);
1238  if (len <= 0) {
1239  SafeFree(buf);
1240  return -EINVAL;
1241  }
1242 
1243  // Create and fill output buffer
1244  *outbuf = new XrdSecBuffer(buf, len);
1245 
1246  // We are done
1247  DEBUG("signature has "<<len<<" bytes");
1248  return 0;
1249 }
virtual int Length() const
virtual char * Buffer() const
virtual int Update(const char *b, int l)
virtual int Reset(const char *dgst)
virtual int GetOutlen(int lin)
Definition: XrdCryptoRSA.cc:59

References XrdCryptoBasic::Buffer(), DEBUG, XrdCryptoRSA::EncryptPrivate(), EPNAME, XrdCryptoMsgDigest::Final(), XrdCryptoRSA::GetOutlen(), XrdCryptoBasic::Length(), XrdCryptoMsgDigest::Reset(), SafeFree, and XrdCryptoMsgDigest::Update().

+ Here is the call graph for this function:

◆ Verify()

int XrdSecProtocolgsi::Verify ( const char *  inbuff,
int  inlen,
const char *  sigbuff,
int  siglen 
)
virtual

Verify a signature using the session key.

Parameters
inbuffbuffer holding data to be verified.
inlenlength of the data.
sigbuffpointer to the signature data.
siglenlength of the signature data.
Returns
< 0 Failed,the return value is -errno (see Encrypt). = 0 Success, signature is correct. > 0 Failed to verify, signature does not match inbuff data.

Reimplemented from XrdSecProtocol.

Definition at line 1252 of file XrdSecProtocolgsi.cc.

1256 {
1257  // Verify a signature
1258  //
1259  // Returns: < 0 Failed, returned value is -errno (see Encrypt).
1260  // = 0 Signature matches the value in inbuff.
1261  // > 0 Failed to verify, signature does not match inbuff data.
1262  //
1263  EPNAME("Verify");
1264 
1265  // We must have a PKI and a digest
1266  if (!sessionKver || !sessionMD)
1267  return -ENOENT;
1268 
1269  // And something to verify
1270  if (!inbuf || inlen <= 0 || !sigbuf || siglen <= 0)
1271  return -EINVAL;
1272 
1273  // Reset digest
1274  sessionMD->Reset(0);
1275 
1276  // Calculate digest
1277  sessionMD->Update(inbuf, inlen);
1278  sessionMD->Final();
1279 
1280  // Output length
1281  int lmax = sessionKver->GetOutlen(siglen);
1282  char *buf = new char[lmax];
1283  if (!buf)
1284  return -ENOMEM;
1285 
1286  // Decrypt signature
1287  int len = sessionKver->DecryptPublic(sigbuf, siglen, buf, lmax);
1288  if (len <= 0) {
1289  delete[] buf;
1290  return -EINVAL;
1291  }
1292 
1293  // Verify signature
1294  bool bad = 1;
1295  if (len == sessionMD->Length()) {
1296  if (!strncmp(buf, sessionMD->Buffer(), len)) {
1297  // Signature matches
1298  bad = 0;
1299  DEBUG("signature successfully verified");
1300  }
1301  }
1302 
1303  // Cleanup
1304  if (buf) delete[] buf;
1305 
1306  // We are done
1307  return ((bad) ? 1 : 0);
1308 }
virtual int DecryptPublic(const char *in, int lin, char *out, int lout)

References XrdCryptoBasic::Buffer(), DEBUG, XrdCryptoRSA::DecryptPublic(), EPNAME, XrdCryptoMsgDigest::Final(), XrdCryptoRSA::GetOutlen(), XrdCryptoBasic::Length(), XrdCryptoMsgDigest::Reset(), and XrdCryptoMsgDigest::Update().

+ Here is the call graph for this function:

Friends And Related Function Documentation

◆ gsiHSVars

friend class gsiHSVars
friend

Definition at line 283 of file XrdSecProtocolgsi.hh.

Referenced by XrdSecProtocolgsi().

◆ gsiOptions

friend class gsiOptions
friend

Definition at line 282 of file XrdSecProtocolgsi.hh.


The documentation for this class was generated from the following files: