XRootD
Loading...
Searching...
No Matches
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.
 
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.
 
virtual bool needTLS ()
 Check if this protocol requires TLS to properly function.
 

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).
 

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)
#define EPNAME(x)
#define QTRACE(act)
#define PRINT(y)
static const kXR_int32 Version
XrdOucString String
#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)
void insert(const int i, int start=-1)
int length() const
const char * c_str() const
XrdSecEntity Entity
XrdSecProtocol(const char *pName)
Constructor.

References XrdSecProtocol::XrdSecProtocol(), XrdOucString::c_str(), DEBUG, XrdSecProtocol::Entity, EPNAME, XrdNetAddrInfo::fmtName, XrdNetAddrInfo::Format(), gsiHSVars, XrdOucString::insert(), XrdNetAddrInfo::isHostName(), XrdOucString::length(), XrdNetAddrInfo::Name(), XrdNetAddrInfo::noPort, opts, PRINT, QTRACE, XrdNetAddr::Set(), 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;
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 = "";
2122 SafeFree(Entity.creds);
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 * ClientStepStr(int kclt)
static const char * ServerStepStr(int ksrv)
static bool AuthzFunCheck(XrdSutCacheEntry *e, void *a)
#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
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=':')
void ToString(XrdOucString &s)
int AddBucket(char *bp=0, int sz=0, int ty=0)
int Serialized(char **buffer, char opt='n')
const char * GetProtocol() const
void Dump(const char *stepstr=0, bool all=false)
int GetStep() const
XrdSutBucket * GetBucket(kXR_int32 type, const char *tag=0)
void Deactivate(kXR_int32 type)
void UnLock(bool reset=true)
void Set(XrdSysRWLock *lock)
XrdSutCacheEntryBuf buf2
XrdSutCacheEntryBuf buf1
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.

References XrdSutBuffer::AddBucket(), AuthzFunCheck(), XrdSutCacheEntryBuf::buf, XrdSutCacheEntry::buf1, XrdSutCacheEntry::buf2, XrdSecBuffer::buffer, XrdOucString::c_str(), ClientStepStr(), XrdSutCacheEntry::cnt, CryptList, XrdSutBuffer::Deactivate(), DEBUG, XrdSutBuffer::Dump(), XrdSecProtocol::Entity, EPNAME, XrdOucString::erase(), XrdOucString::find(), XrdOucString::form(), XrdSutBuffer::GetBucket(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), 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(), XrdSutCacheEntry::mtime, NOTIFY, PRINT, QTRACE, REL2, XrdSutCacheEntry::rwmtx, SafeDelArray, SafeDelete, SafeFree, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSutCERef::Set(), XrdSecBuffer::size, XrdSutCacheEntry::status, STR_NPOS, XrdOucString::tokenize(), XrdSutBucket::ToString(), XrdSutCERef::UnLock(), 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}

References DEBUG, EPNAME, and SafeFree.

◆ 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);
1067 SafeFree(Entity.endorsements);
1068 if (Entity.creds && Entity.credslen > 0) {
1069 SafeFree(Entity.creds);
1070 } else {
1071 Entity.creds = 0;
1072 }
1073 Entity.credslen = 0;
1074 SafeFree(Entity.moninfo);
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}

References XrdSecProtocol::Entity, SafeDelete, and SafeFree.

◆ 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}

Referenced by XrdSecProtocolgsiInit().

+ 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}

References DEBUG, EPNAME, and SafeFree.

◆ 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,
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 const char * SubjectHash(int)
virtual const char * IssuerHash(int)
kXR_int32 size
int UpdateBucket(const char *bp, int sz, int ty)
void SetStep(int s)
kXR_int32 MarshalBucket(kXR_int32 type, kXR_int32 code)

References XrdSutBuffer::AddBucket(), XrdSecBuffer::buffer, XrdSutBucket::buffer, XrdOucString::c_str(), ClientStepStr(), CryptoMod, DEBUG, XrdSutBuffer::Dump(), XrdSecProtocol::Entity, EPNAME, XrdOucString::form(), XrdOucEnv::Get(), XrdOucErrInfo::getEnv(), XrdSutBuffer::GetProtocol(), XrdSutBuffer::GetStep(), gNoPadTag, XrdCryptoX509::IssuerHash(), 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(), NOTIFY, QTRACE, REL2, XrdSutBuffer::Serialized(), ServerStepStr(), XrdSutBuffer::SetStep(), XrdSecBuffer::size, XrdSutBucket::size, XrdCryptoX509::SubjectHash(), XrdCryptoX509::type, XrdSutBuffer::UpdateBucket(), Version, 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}

References DEBUG, and EPNAME.

◆ 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
void XrdCryptoSetTrace(kXR_int32 trace)
#define cryptoTRACE_Notify
#define cryptoTRACE_Dump
#define cryptoTRACE_Debug
XrdOucGMap * XrdOucgetGMap(XrdOucGMapArgs)
Definition XrdOucGMap.cc:92
#define access(a, b)
Definition XrdPosix.hh:44
#define stat(a, b)
Definition XrdPosix.hh:101
static const char * gUsrPxyDef
@ kOptsSigReq
@ kOptsFwdPxy
@ kOptsPxCred
@ kOptsSrvReq
@ kOptsDlgPxy
@ kOptsCreatePxy
@ kOptsPxFile
#define XrdCryptoMax
@ kGSErrInit
#define TRACE_Authen
XrdOucTrace * gsiTrace
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
#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, gsiOptions::cert, gsiOptions::certdir, XrdCryptoFactory::Cipher(), gsiOptions::cipher, gsiOptions::clist, gsiOptions::createpxy, gsiOptions::crl, gsiOptions::crldir, gsiOptions::crlext, gsiOptions::crlrefresh, cryptoTRACE_Debug, cryptoTRACE_Dump, cryptoTRACE_Notify, DEBUG, gsiOptions::debug, gsiOptions::deplen, gsiOptions::dlgpxy, XrdOucString::endswith(), EPNAME, gsiOptions::exppxy, XrdCryptoFactory::GetCryptoFactory(), XrdOucErrInfo::getErrText(), gsiOptions::gmapfun, gsiOptions::gmapfunparms, gsiOptions::gmapto, gNoPadTag, gsiOptions::gridmap, gsiOptions, gsiTrace, gUsrPxyDef, gsiOptions::hashcomp, XrdCryptoFactory::HasPaddingSupport(), XrdCryptoFactory::ID(), gsiOptions::key, kGSErrError, kGSErrInit, kOptsCreatePxy, kOptsDlgPxy, kOptsFwdPxy, kOptsPxCred, kOptsPxFile, kOptsSigReq, kOptsSrvReq, XrdOucString::length(), gsiOptions::md, gsiOptions::mode, gsiOptions::moninfo, XrdCryptoFactory::Name(), NOTIFY, XrdCryptoFactory::Notify(), 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, 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 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}

References DEBUG, EPNAME, and SafeFree.

◆ 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}

References DEBUG, and EPNAME.

Friends And Related Symbol Documentation

◆ gsiHSVars

friend class gsiHSVars
friend

Definition at line 283 of file XrdSecProtocolgsi.hh.

References gsiHSVars, and opts.

Referenced by XrdSecProtocolgsi(), and gsiHSVars.

◆ gsiOptions

friend class gsiOptions
friend

Definition at line 282 of file XrdSecProtocolgsi.hh.

References gsiOptions.

Referenced by gsiOptions, and Init().


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