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 succeeded) < 0 -> einfo present (error has occurred)

Implements XrdSecProtocol.

Definition at line 1749 of file XrdSecProtocolgsi.cc.

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

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

2278 {
2279  // Initiate error logging and tracing
2280 
2281  eDest.logger(&Logger);
2282  GSITrace = new XrdOucTrace(&eDest);
2283  return GSITrace;
2284 }
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  if (liv > 0 && iv)
1133  memcpy(buf, iv, liv);
1134 
1135  // Encrypt
1136  int len = sessionKey->Encrypt(inbuf, inlen, buf + liv) + liv; // the size of initialization vector which is being appended at
1137  // the beginning of the output buffer has to be taken into account
1138  if (len <= 0) {
1139  SafeFree(buf);
1140  return -EINVAL;
1141  }
1142 
1143  // Create and fill output buffer
1144  *outbuf = new XrdSecBuffer(buf, len);
1145 
1146  // We are done
1147  DEBUG("encrypted buffer has "<<len<<" bytes");
1148  return 0;
1149 }
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 1412 of file XrdSecProtocolgsi.cc.

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

1313 {
1314  // Get the current encryption key
1315  //
1316  // Returns: < 0 Failed, returned value if -errno (see Encrypt)
1317  // >= 0 The size of the encyption key. The supplied buffer of length
1318  // size hold the key. If the buffer address is 0, only the
1319  // size of the key is returned.
1320  //
1321  EPNAME("getKey");
1322 
1323  // Check if we have to serialize the key
1324  if (!bucketKey) {
1325 
1326  // We must have a key for that
1327  if (!sessionKey)
1328  // Invalid call
1329  return -ENOENT;
1330  // Create bucket
1331  bucketKey = sessionKey->AsBucket();
1332  }
1333 
1334  // Prepare output now, if we have any
1335  if (bucketKey) {
1336  // If are asked only the size, we are done
1337  if (kbuf == 0)
1338  return bucketKey->size;
1339 
1340  // Check the size of the buffer
1341  if (klen < bucketKey->size)
1342  // Too small
1343  return -EOVERFLOW;
1344 
1345  // Copy the buffer
1346  memcpy(kbuf, bucketKey->buffer, bucketKey->size);
1347 
1348  // We are done
1349  DEBUG("session key exported");
1350  return bucketKey->size;
1351  }
1352 
1353  // Key exists but we could export it in bucket format
1354  return -ENOMEM;
1355 }
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 access(const char *path, int amode)
#define stat(a, b)
Definition: XrdPosix.hh:101
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
bool Debug
int ncrypt
XrdOucString DefCrypto
int XrdSutExpand(XrdOucString &path)
Definition: XrdSutAux.cc:360
const char * XrdSutHome()
Definition: XrdSutAux.cc:459
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, 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 1358 of file XrdSecProtocolgsi.cc.

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

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

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