XRootD
Loading...
Searching...
No Matches
XrdHttpProtocol Class Reference

#include <XrdHttpProtocol.hh>

+ Inheritance diagram for XrdHttpProtocol:
+ Collaboration diagram for XrdHttpProtocol:

Classes

struct  StaticPreloadInfo
 

Public Member Functions

 XrdHttpProtocol (bool imhttps)
 
 XrdHttpProtocol (const XrdHttpProtocol &)=default
 Ctor, dtors and copy ctor.
 
 ~XrdHttpProtocol ()
 
int doChksum (const XrdOucString &fname)
 Perform a checksum request.
 
void DoIt ()
 Override from the base class.
 
int doStat (char *fname)
 Perform a Stat request.
 
bool isHTTPS ()
 called via https
 
XrdProtocolMatch (XrdLink *lp)
 Tells if the oustanding bytes on the socket match this protocol implementation.
 
XrdHttpProtocol operator= (const XrdHttpProtocol &rhs)
 
int Process (XrdLink *lp)
 Process data incoming from the socket.
 
void Recycle (XrdLink *lp, int consec, const char *reason)
 Recycle this instance.
 
int Stats (char *buff, int blen, int do_sync=0)
 Get activity stats.
 
- Public Member Functions inherited from XrdProtocol
 XrdProtocol (const char *jname)
 
virtual ~XrdProtocol ()
 
- Public Member Functions inherited from XrdJob
 XrdJob (const char *desc="")
 
virtual ~XrdJob ()
 

Static Public Member Functions

static int Configure (char *parms, XrdProtocol_Config *pi)
 Read and apply the configuration.
 
static int parseHeader2CGI (XrdOucStream &Config, XrdSysError &err, std::map< std::string, std::string > &header2cgi)
 Use this function to parse header2cgi configurations.
 

Public Attributes

XrdObject< XrdHttpProtocolProtLink
 
XrdSecEntity SecEntity
 Authentication area.
 
- Public Attributes inherited from XrdJob
const char * Comment
 
XrdJobNextJob
 

Static Public Attributes

static XrdHttpChecksumHandler cksumHandler = XrdHttpChecksumHandler()
 
static XrdObjectQ< XrdHttpProtocolProtStack
 
static XrdHttpReadRangeHandler::Configuration ReadRangeConfig
 configuration for the read range handler
 

Protected Attributes

char * Addr_str
 
XrdXrootd::BridgeBridge
 The Bridge that we use to exercise the xrootd internals.
 
XrdHttpReq CurrentReq
 
XrdLinkLink
 The link we are bound to.
 

Static Protected Attributes

static XrdBuffManagerBPool = 0
 
static XrdSecServiceCIA = 0
 
static bool compatNameGeneration = false
 
static int crlRefIntervalSec = XrdTlsContext::DEFAULT_CRL_REF_INT_SEC
 CRL thread refresh interval.
 
static XrdSysError eDest = 0
 
static bool embeddedstatic = true
 If true, use the embedded css and icons.
 
static char * gridmap = 0
 Gridmap file location. The same used by XrdSecGsi.
 
static int hailWait = 60000
 Timeout for reading the handshake.
 
static std::map< std::string, std::string > hdr2cgimap
 Rules that turn HTTP headers to cgi tokens in the URL, for internal comsumption.
 
static bool isdesthttps = false
 True if the redirections must be towards https targets.
 
static bool isRequiredGridmap = false
 
static bool listdeny = false
 If true, any form of listing is denied.
 
static char * listredir = 0
 Url to redirect to in the case a listing is requested.
 
static BIO_METHOD * m_bio_method = NULL
 C-style vptr table for our custom BIO objects.
 
static int m_bio_type = 0
 Type identifier for our custom BIO objects.
 
static kXR_int32 myRole = kXR_isManager
 Our role.
 
static XrdNetPMarkpmarkHandle = nullptr
 Packet marking handler pointer (assigned from the environment during the Config() call)
 
static int Port = 1094
 Our port.
 
static char * Port_str = 0
 Our port, as a string.
 
static int readWait = 300000
 Timeout for reading data.
 
static XrdSchedulerSched = 0
 
static char * secretkey = 0
 The key used to calculate the url hashes.
 
static bool selfhttps2http = false
 If client is HTTPS, self-redirect with HTTP+token.
 
static XrdOucGMapservGMap = 0
 The instance of the DN mapper. Created only when a valid path is given.
 
static char * sslcadir = 0
 
static char * sslcafile = 0
 
static char * sslcert = 0
 OpenSSL stuff.
 
static char * sslcipherfilter = 0
 
static char * sslkey = 0
 
static int sslverifydepth = 9
 Depth of verification of a certificate chain.
 
static XrdOucHash< StaticPreloadInfo > * staticpreload = 0
 
static char * staticredir = 0
 
static bool tpcForwardCreds = false
 If set to true, the HTTP TPC transfers will forward the credentials to redirected hosts.
 
static char * xrd_cslist = nullptr
 The list of checksums that were configured via the xrd.cksum parameter on the server config file.
 

Friends

class XrdHttpExtReq
 
class XrdHttpReq
 

Detailed Description

Definition at line 79 of file XrdHttpProtocol.hh.


Class Documentation

◆ XrdHttpProtocol::StaticPreloadInfo

struct XrdHttpProtocol::StaticPreloadInfo

Definition at line 427 of file XrdHttpProtocol.hh.

+ Collaboration diagram for XrdHttpProtocol::StaticPreloadInfo:
Class Members
char * data
int len

Constructor & Destructor Documentation

◆ XrdHttpProtocol() [1/2]

XrdHttpProtocol::XrdHttpProtocol ( const XrdHttpProtocol & )
default

Ctor, dtors and copy ctor.

References XrdHttpProtocol().

Referenced by XrdHttpProtocol(), Match(), and operator=().

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

◆ XrdHttpProtocol() [2/2]

XrdHttpProtocol::XrdHttpProtocol ( bool imhttps)

Definition at line 192 of file XrdHttpProtocol.cc.

193: XrdProtocol("HTTP protocol handler"), ProtLink(this),
195 myBuff = 0;
196 Addr_str = 0;
197 Reset();
198 ishttps = imhttps;
199
200}
XrdObject< XrdHttpProtocol > ProtLink
static XrdHttpReadRangeHandler::Configuration ReadRangeConfig
configuration for the read range handler
XrdSecEntity SecEntity
Authentication area.
XrdProtocol(const char *jname)

References XrdProtocol::XrdProtocol(), Addr_str, CurrentReq, ProtLink, ReadRangeConfig, and SecEntity.

+ Here is the call graph for this function:

◆ ~XrdHttpProtocol()

XrdHttpProtocol::~XrdHttpProtocol ( )
inline

Definition at line 123 of file XrdHttpProtocol.hh.

123 {
124 Cleanup();
125 }

Member Function Documentation

◆ Configure()

int XrdHttpProtocol::Configure ( char * parms,
XrdProtocol_Config * pi )
static

Read and apply the configuration.

Definition at line 1695 of file XrdHttpProtocol.cc.

1695 {
1696 /*
1697 Function: Establish configuration at load time.
1698
1699 Input: None.
1700
1701 Output: 0 upon success or !0 otherwise.
1702 */
1703
1704 char *rdf;
1705
1706 // Copy out the special info we want to use at top level
1707 //
1708 eDest.logger(pi->eDest->logger());
1710 // SI = new XrdXrootdStats(pi->Stats);
1711 Sched = pi->Sched;
1712 BPool = pi->BPool;
1713 xrd_cslist = getenv("XRD_CSLIST");
1714
1715 Port = pi->Port;
1716
1717 // Copy out the current TLS context
1718 //
1719 xrdctx = pi->tlsCtx;
1720
1721 {
1722 char buf[16];
1723 sprintf(buf, "%d", Port);
1724 Port_str = strdup(buf);
1725 }
1726
1727 // Now process and configuration parameters
1728 //
1729 rdf = (parms && *parms ? parms : pi->ConfigFN);
1730 if (rdf && Config(rdf, pi->theEnv)) return 0;
1732
1733 // Set the redirect flag if we are a pure redirector
1735 if ((rdf = getenv("XRDROLE"))) {
1736 eDest.Emsg("Config", "XRDROLE: ", rdf);
1737
1738 if (!strcasecmp(rdf, "manager") || !strcasecmp(rdf, "supervisor")) {
1740 eDest.Emsg("Config", "Configured as HTTP(s) redirector.");
1741 } else {
1742
1743 eDest.Emsg("Config", "Configured as HTTP(s) data server.");
1744 }
1745
1746 } else {
1747 eDest.Emsg("Config", "No XRDROLE specified.");
1748 }
1749
1750 // Schedule protocol object cleanup
1751 //
1752 ProtStack.Set(pi->Sched, &XrdHttpTrace,
1754 ProtStack.Set((pi->ConnMax / 3 ? pi->ConnMax / 3 : 30), 60 * 60);
1755
1756 // Return success
1757 //
1758
1759 return 1;
1760}
#define kXR_isManager
#define kXR_isServer
XrdSysTrace XrdHttpTrace("http")
#define TRACE_MEM
Definition XrdTrace.hh:38
#define TRACE_ALL
Definition XrdTrace.hh:35
static XrdScheduler * Sched
static kXR_int32 myRole
Our role.
static char * Port_str
Our port, as a string.
static XrdSysError eDest
static char * xrd_cslist
The list of checksums that were configured via the xrd.cksum parameter on the server config file.
static XrdObjectQ< XrdHttpProtocol > ProtStack
static int Port
Our port.
static XrdBuffManager * BPool
XrdBuffManager * BPool
XrdScheduler * Sched
XrdTlsContext * tlsCtx
XrdSysError * eDest
XrdOucEnv * theEnv
XrdSysLogger * logger(XrdSysLogger *lp=0)
void SetLogger(XrdSysLogger *logp)
XrdTlsContext * xrdctx

References BPool, XrdProtocol_Config::BPool, XrdProtocol_Config::ConfigFN, XrdProtocol_Config::ConnMax, XrdProtocol_Config::DebugON, eDest, XrdProtocol_Config::eDest, kXR_isManager, kXR_isServer, XrdSysError::logger(), myRole, Port, XrdProtocol_Config::Port, Port_str, ProtStack, Sched, XrdProtocol_Config::Sched, XrdProtocol_Config::theEnv, XrdProtocol_Config::tlsCtx, TRACE_ALL, TRACE_MEM, xrd_cslist, XrdHttpProtoInfo::xrdctx, and XrdHttpTrace.

Referenced by XrdgetProtocol().

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

◆ doChksum()

int XrdHttpProtocol::doChksum ( const XrdOucString & fname)

Perform a checksum request.

Definition at line 2952 of file XrdHttpProtocol.cc.

2952 {
2953 size_t length;
2954 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2955 CurrentReq.xrdreq.query.requestid = htons(kXR_query);
2956 CurrentReq.xrdreq.query.infotype = htons(kXR_Qcksum);
2957 memset(CurrentReq.xrdreq.query.reserved1, '\0', sizeof(CurrentReq.xrdreq.query.reserved1));
2958 memset(CurrentReq.xrdreq.query.fhandle, '\0', sizeof(CurrentReq.xrdreq.query.fhandle));
2959 memset(CurrentReq.xrdreq.query.reserved2, '\0', sizeof(CurrentReq.xrdreq.query.reserved2));
2960 length = fname.length() + 1;
2961 CurrentReq.xrdreq.query.dlen = htonl(length);
2962
2963 if (!Bridge) return -1;
2964
2965 return Bridge->Run(reinterpret_cast<char *>(&CurrentReq.xrdreq), const_cast<char *>(fname.c_str()), length) ? 0 : -1;
2966}
@ kXR_query
Definition XProtocol.hh:113
@ kXR_Qcksum
Definition XProtocol.hh:617
XrdXrootd::Bridge * Bridge
The Bridge that we use to exercise the xrootd internals.
int length() const
const char * c_str() const

References Bridge, XrdOucString::c_str(), CurrentReq, kXR_Qcksum, kXR_query, and XrdOucString::length().

+ Here is the call graph for this function:

◆ DoIt()

void XrdHttpProtocol::DoIt ( )
inlinevirtual

Override from the base class.

Implements XrdJob.

Definition at line 90 of file XrdHttpProtocol.hh.

90 {
91 if (Resume) (*this.*Resume)();
92 }

◆ doStat()

int XrdHttpProtocol::doStat ( char * fname)

Perform a Stat request.

Definition at line 2924 of file XrdHttpProtocol.cc.

2924 {
2925 int l;
2926 bool b;
2927 CurrentReq.filesize = 0;
2928 CurrentReq.fileflags = 0;
2929 CurrentReq.filemodtime = 0;
2930
2931 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2932 CurrentReq.xrdreq.stat.requestid = htons(kXR_stat);
2933 memset(CurrentReq.xrdreq.stat.reserved, 0,
2934 sizeof (CurrentReq.xrdreq.stat.reserved));
2935 l = strlen(fname) + 1;
2936 CurrentReq.xrdreq.stat.dlen = htonl(l);
2937
2938 if (!Bridge) return -1;
2939 b = Bridge->Run((char *) &CurrentReq.xrdreq, fname, l);
2940 if (!b) {
2941 return -1;
2942 }
2943
2944
2945 return 0;
2946}
@ kXR_stat
Definition XProtocol.hh:129

References Bridge, CurrentReq, and kXR_stat.

◆ isHTTPS()

bool XrdHttpProtocol::isHTTPS ( )
inline

called via https

Definition at line 141 of file XrdHttpProtocol.hh.

141{ return ishttps; }

◆ Match()

XrdProtocol * XrdHttpProtocol::Match ( XrdLink * lp)
virtual

Tells if the oustanding bytes on the socket match this protocol implementation.

Implements XrdProtocol.

Definition at line 218 of file XrdHttpProtocol.cc.

218 {
219 char mybuf[16], mybuf2[1024];
220 XrdHttpProtocol *hp;
221 int dlen;
222 bool myishttps = false;
223
224 // Peek at the first 20 bytes of data
225 //
226 if ((dlen = lp->Peek(mybuf, (int) sizeof (mybuf), hailWait)) < (int) sizeof (mybuf)) {
227 if (dlen <= 0) lp->setEtext("handshake not received");
228 return (XrdProtocol *) 0;
229 }
230 mybuf[dlen - 1] = '\0';
231
232 // Trace the data
233 //
234
235 TRACEI(DEBUG, "received dlen: " << dlen);
236 //TRACEI(REQ, "received buf: " << mybuf);
237 mybuf2[0] = '\0';
238 for (int i = 0; i < dlen; i++) {
239 char mybuf3[16];
240 sprintf(mybuf3, "%.02d ", mybuf[i]);
241 strcat(mybuf2, mybuf3);
242
243 }
244 TRACEI(DEBUG, "received dump: " << mybuf2);
245
246 // Decide if it looks http or not. For now we are happy if all the received characters are alphanumeric
247 bool ismine = true;
248 for (int i = 0; i < dlen - 1; i++)
249 if (!isprint(mybuf[i]) && (mybuf[i] != '\r') && (mybuf[i] != '\n')) {
250 ismine = false;
251 TRACEI(DEBUG, "This does not look like http at pos " << i);
252 break;
253 }
254
255 // If it does not look http then look if it looks like https
256 if ((!ismine) && (dlen >= 4)) {
257 char check[4] = {00, 00, 00, 00};
258 if (memcmp(mybuf, check, 4)) {
259
260 if (httpsmode) {
261 ismine = true;
262 myishttps = true;
263 TRACEI(DEBUG, "This may look like https");
264 } else {
265 TRACEI(ALL, "This may look like https, but https is not configured");
266 }
267
268 }
269 }
270
271 if (!ismine) {
272 TRACEI(DEBUG, "This does not look like https. Protocol not matched.");
273 return (XrdProtocol *) 0;
274 }
275
276 // It does look http or https...
277 // Get a protocol object off the stack (if none, allocate a new one)
278 //
279
280 TRACEI(REQ, "Protocol matched. https: " << myishttps);
281 if (!(hp = ProtStack.Pop())) hp = new XrdHttpProtocol(myishttps);
282 else
283 hp->ishttps = myishttps;
284
285 // We now have to do some work arounds to tell the underlying framework
286 // that is is https without invoking TLS on the actual link. Eventually,
287 // we should just use the link's TLS native implementation.
288 //
289 hp->SecEntity.addrInfo = lp->AddrInfo();
290 XrdNetAddr *netP = const_cast<XrdNetAddr*>(lp->NetAddr());
291 netP->SetDialect("https");
292 netP->SetTLS(true);
293
294 // Allocate 1MB buffer from pool
295 if (!hp->myBuff) {
296 hp->myBuff = BPool->Obtain(1024 * 1024);
297 }
298 hp->myBuffStart = hp->myBuffEnd = hp->myBuff->buff;
299
300 // Bind the protocol to the link and return the protocol
301 //
302 hp->Link = lp;
303 return (XrdProtocol *) hp;
304}
#define DEBUG(x)
#define TRACEI(act, x)
Definition XrdTrace.hh:66
char * buff
Definition XrdBuffer.hh:45
static int hailWait
Timeout for reading the handshake.
XrdLink * Link
The link we are bound to.
XrdHttpProtocol(const XrdHttpProtocol &)=default
Ctor, dtors and copy ctor.
void SetDialect(const char *dP)
void SetTLS(bool val)
XrdNetAddrInfo * addrInfo
Entity's connection details.

References XrdHttpProtocol(), XrdProtocol::XrdProtocol(), XrdLink::AddrInfo(), XrdSecEntity::addrInfo, BPool, XrdBuffer::buff, DEBUG, hailWait, XrdHttpProtoInfo::httpsmode, Link, XrdLink::NetAddr(), XrdLink::Peek(), ProtStack, SecEntity, XrdNetAddr::SetDialect(), XrdLink::setEtext(), XrdNetAddr::SetTLS(), and TRACEI.

+ Here is the call graph for this function:

◆ operator=()

XrdHttpProtocol XrdHttpProtocol::operator= ( const XrdHttpProtocol & rhs)

Definition at line 207 of file XrdHttpProtocol.cc.

207 {
208
209 return *this;
210}

References XrdHttpProtocol().

+ Here is the call graph for this function:

◆ parseHeader2CGI()

int XrdHttpProtocol::parseHeader2CGI ( XrdOucStream & Config,
XrdSysError & err,
std::map< std::string, std::string > & header2cgi )
static

Use this function to parse header2cgi configurations.

Definition at line 1765 of file XrdHttpProtocol.cc.

1765 {
1766 char *val, keybuf[1024], parmbuf[1024];
1767 char *parm;
1768
1769 // Get the header key
1770 val = Config.GetWord();
1771 if (!val || !val[0]) {
1772 err.Emsg("Config", "No headerkey specified.");
1773 return 1;
1774 } else {
1775
1776 // Trim the beginning, in place
1777 while ( *val && !isalnum(*val) ) val++;
1778 strcpy(keybuf, val);
1779
1780 // Trim the end, in place
1781 char *pp;
1782 pp = keybuf + strlen(keybuf) - 1;
1783 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1784 *pp = '\0';
1785 pp--;
1786 }
1787
1788 parm = Config.GetWord();
1789
1790 // Avoids segfault in case a key is given without value
1791 if(!parm || !parm[0]) {
1792 err.Emsg("Config", "No header2cgi value specified. key: '", keybuf, "'");
1793 return 1;
1794 }
1795
1796 // Trim the beginning, in place
1797 while ( *parm && !isalnum(*parm) ) parm++;
1798 strcpy(parmbuf, parm);
1799
1800 // Trim the end, in place
1801 pp = parmbuf + strlen(parmbuf) - 1;
1802 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1803 *pp = '\0';
1804 pp--;
1805 }
1806
1807 // Add this mapping to the map that will be used
1808 try {
1809 header2cgi[keybuf] = parmbuf;
1810 } catch ( ... ) {
1811 err.Emsg("Config", "Can't insert new header2cgi rule. key: '", keybuf, "'");
1812 return 1;
1813 }
1814
1815 }
1816 return 0;
1817}
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)

References XrdSysError::Emsg().

+ Here is the call graph for this function:

◆ Process()

int XrdHttpProtocol::Process ( XrdLink * lp)
virtual

Process data incoming from the socket.

Implements XrdProtocol.

Definition at line 480 of file XrdHttpProtocol.cc.

481{
482 int rc = 0;
483
484 TRACEI(DEBUG, " Process. lp:"<<(void *)lp<<" reqstate: "<<CurrentReq.reqstate);
485
486 if (!myBuff || !myBuff->buff || !myBuff->bsize) {
487 TRACE(ALL, " Process. No buffer available. Internal error.");
488 return -1;
489 }
490
491
492 if (!SecEntity.host) {
493 char *nfo = GetClientIPStr();
494 if (nfo) {
495 TRACEI(REQ, " Setting host: " << nfo);
496 SecEntity.host = nfo;
497 strcpy(SecEntity.prot, "http");
498 }
499 }
500
501
502
503 // If https then check independently for the ssl handshake
504 if (ishttps && !ssldone) {
505
506 if (!ssl) {
507 sbio = CreateBIO(Link);
508 BIO_set_nbio(sbio, 1);
509 ssl = (SSL*)xrdctx->Session();
510 }
511
512 if (!ssl) {
513 TRACEI(DEBUG, " SSL_new returned NULL");
514 ERR_print_errors(sslbio_err);
515 return -1;
516 }
517
518 // If a secxtractor has been loaded
519 // maybe it wants to add its own initialization bits
520 if (secxtractor)
521 secxtractor->InitSSL(ssl, sslcadir);
522
523 SSL_set_bio(ssl, sbio, sbio);
524 //SSL_set_connect_state(ssl);
525
526 //SSL_set_fd(ssl, Link->FDnum());
527 struct timeval tv;
528 tv.tv_sec = 10;
529 tv.tv_usec = 0;
530 setsockopt(Link->FDnum(), SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
531 setsockopt(Link->FDnum(), SOL_SOCKET, SO_SNDTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
532
533 TRACEI(DEBUG, " Entering SSL_accept...");
534 int res = SSL_accept(ssl);
535 TRACEI(DEBUG, " SSL_accept returned :" << res);
536 if ((res == -1) && (SSL_get_error(ssl, res) == SSL_ERROR_WANT_READ)) {
537 TRACEI(DEBUG, " SSL_accept wants to read more bytes... err:" << SSL_get_error(ssl, res));
538 return 1;
539 }
540
541 if(res <= 0) {
542 ERR_print_errors(sslbio_err);
543 if (res < 0) {
544
545 SSL_free(ssl);
546 ssl = 0;
547 return -1;
548 }
549 }
550
551 BIO_set_nbio(sbio, 0);
552
553 strcpy(SecEntity.prot, "https");
554
555 // Get the voms string and auth information
556 if (HandleAuthentication(Link)) {
557 SSL_free(ssl);
558 ssl = 0;
559 return -1;
560 }
561
562 ssldone = true;
563 if (TRACING(TRACE_AUTH)) {
564 SecEntity.Display(eDest);
565 }
566 }
567
568
569
570 if (!DoingLogin) {
571 // Re-invocations triggered by the bridge have lp==0
572 // In this case we keep track of a different request state
573 if (lp) {
574
575 // This is an invocation that was triggered by a socket event
576 // Read all the data that is available, throw it into the buffer
577 if ((rc = getDataOneShot(BuffAvailable())) < 0) {
578 // Error -> exit
579 return -1;
580 }
581
582 // If we need more bytes, let's wait for another invokation
583 if (BuffUsed() < ResumeBytes) return 1;
584
585
586 } else
587 CurrentReq.reqstate++;
588 } else if (!DoneSetInfo && !CurrentReq.userAgent().empty()) { // DoingLogin is true, meaning the login finished.
589 std::string mon_info = "monitor info " + CurrentReq.userAgent();
590 DoneSetInfo = true;
591 if (mon_info.size() >= 1024) {
592 TRACEI(ALL, "User agent string too long");
593 } else if (!Bridge) {
594 TRACEI(ALL, "Internal logic error: Bridge is null after login");
595 } else {
596 TRACEI(DEBUG, "Setting " << mon_info);
597 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
598 CurrentReq.xrdreq.set.requestid = htons(kXR_set);
599 CurrentReq.xrdreq.set.modifier = '\0';
600 memset(CurrentReq.xrdreq.set.reserved, '\0', sizeof(CurrentReq.xrdreq.set.reserved));
601 CurrentReq.xrdreq.set.dlen = htonl(mon_info.size());
602 if (!Bridge->Run((char *) &CurrentReq.xrdreq, (char *) mon_info.c_str(), mon_info.size())) {
603 SendSimpleResp(500, nullptr, nullptr, "Could not set user agent.", 0, false);
604 return -1;
605 }
606 return 0;
607 }
608 } else {
609 DoingLogin = false;
610 }
611
612 // Read the next request header, that is, read until a double CRLF is found
613
614
615 if (!CurrentReq.headerok) {
616
617 // Read as many lines as possible into the buffer. An empty line breaks
618 while ((rc = BuffgetLine(tmpline)) > 0) {
619 std::string traceLine = tmpline.c_str();
620 if (TRACING(TRACE_DEBUG)) {
621 traceLine = obfuscateAuth(traceLine);
622 }
623 TRACE(DEBUG, " rc:" << rc << " got hdr line: " << traceLine);
624 if ((rc == 2) && (tmpline.length() > 1) && (tmpline[rc - 1] == '\n')) {
625 CurrentReq.headerok = true;
626 TRACE(DEBUG, " rc:" << rc << " detected header end.");
627 break;
628 }
629
630
631 if (CurrentReq.request == CurrentReq.rtUnset) {
632 TRACE(DEBUG, " Parsing first line: " << traceLine.c_str());
633 int result = CurrentReq.parseFirstLine((char *)tmpline.c_str(), rc);
634 if (result < 0) {
635 TRACE(DEBUG, " Parsing of first line failed with " << result);
636 return -1;
637 }
638 } else {
639 int result = CurrentReq.parseLine((char *) tmpline.c_str(), rc);
640 if(result < 0) {
641 TRACE(DEBUG, " Parsing of header line failed with " << result)
642 SendSimpleResp(400,NULL,NULL,"Malformed header line. Hint: ensure the line finishes with \"\\r\\n\"", 0, false);
643 return -1;
644 }
645 }
646
647
648 }
649
650 // Here we have CurrentReq loaded with the header, or its relevant fields
651
652 if (!CurrentReq.headerok) {
653 TRACEI(REQ, " rc:" << rc << "Header not yet complete.");
654
655 // Here a subtle error condition. IF we failed reading a line AND the buffer
656 // has a reasonable amount of data available THEN we consider the header
657 // as corrupted and shutdown the client
658 if ((rc <= 0) && (BuffUsed() >= 16384)) {
659 TRACEI(ALL, "Corrupted header detected, or line too long. Disconnecting client.");
660 return -1;
661 }
662
663
664 if (CurrentReq.reqstate > 0)
665 CurrentReq.reqstate--;
666 // Waiting for more data
667 return 1;
668 }
669
670 }
671
672 // If we are in self-redirect mode, then let's do it
673 // Do selfredirect only with 'simple' requests, otherwise poor clients may misbehave
674 if (ishttps && ssldone && selfhttps2http &&
675 ( (CurrentReq.request == XrdHttpReq::rtGET) || (CurrentReq.request == XrdHttpReq::rtPUT) ||
676 (CurrentReq.request == XrdHttpReq::rtPROPFIND)) ) {
677 char hash[512];
678 time_t timenow = time(0);
679
680
681 calcHashes(hash, CurrentReq.resource.c_str(), (kXR_int16) CurrentReq.request,
682 &SecEntity,
683 timenow,
684 secretkey);
685
686
687
688 if (hash[0]) {
689
690 // Workaround... delete the previous opaque information
691 if (CurrentReq.opaque) {
692 delete CurrentReq.opaque;
693 CurrentReq.opaque = 0;
694 }
695
696 TRACEI(REQ, " rc:" << rc << " self-redirecting to http with security token.");
697
698 XrdOucString dest = "Location: http://";
699 // Here I should put the IP addr of the server
700
701 // We have to recompute it here because we don't know to which
702 // interface the client had connected to
703 struct sockaddr_storage sa;
704 socklen_t sl = sizeof(sa);
705 getsockname(this->Link->AddrInfo()->SockFD(), (struct sockaddr*)&sa, &sl);
706
707 // now get it back and print it
708 char buf[256];
709 bool ok = false;
710
711 switch (sa.ss_family) {
712 case AF_INET:
713 if (inet_ntop(AF_INET, &(((sockaddr_in*)&sa)->sin_addr), buf, INET_ADDRSTRLEN)) {
714 if (Addr_str) free(Addr_str);
715 Addr_str = strdup(buf);
716 ok = true;
717 }
718 break;
719 case AF_INET6:
720 if (inet_ntop(AF_INET6, &(((sockaddr_in6*)&sa)->sin6_addr), buf, INET6_ADDRSTRLEN)) {
721 if (Addr_str) free(Addr_str);
722 Addr_str = (char *)malloc(strlen(buf)+3);
723 strcpy(Addr_str, "[");
724 strcat(Addr_str, buf);
725 strcat(Addr_str, "]");
726 ok = true;
727 }
728 break;
729 default:
730 TRACEI(REQ, " Can't recognize the address family of the local host.");
731 }
732
733 if (ok) {
734 dest += Addr_str;
735 dest += ":";
736 dest += Port_str;
737 dest += CurrentReq.resource.c_str();
738 TRACEI(REQ," rc:"<<rc<<" self-redirecting to http with security token: '"
739 << dest.c_str() << "'");
740
741
742 CurrentReq.appendOpaque(dest, &SecEntity, hash, timenow);
743 SendSimpleResp(302, NULL, (char *) dest.c_str(), 0, 0, true);
744 CurrentReq.reset();
745 return -1;
746 }
747
748 TRACEI(REQ, " rc:" << rc << " Can't perform self-redirection.");
749
750 }
751 else {
752 TRACEI(ALL, " Could not calculate self-redirection hash");
753 }
754 }
755
756 // If this is not https, then extract the signed information from the url
757 // and fill the SecEntity structure as if we were using https
758 if (!ishttps && !ssldone) {
759
760
761 if (CurrentReq.opaque) {
762 char * tk = CurrentReq.opaque->Get("xrdhttptk");
763 // If there is a hash then we use it as authn info
764 if (tk) {
765
766 time_t tim = 0;
767 char * t = CurrentReq.opaque->Get("xrdhttptime");
768 if (t) tim = atoi(t);
769 if (!t) {
770 TRACEI(REQ, " xrdhttptime not specified. Authentication failed.");
771 return -1;
772 }
773 if (abs(time(0) - tim) > XRHTTP_TK_GRACETIME) {
774 TRACEI(REQ, " Token expired. Authentication failed.");
775 return -1;
776 }
777
778 // Fill the Secentity from the fields in the URL:name, vo, host
779 char *nfo;
780
781 nfo = CurrentReq.opaque->Get("xrdhttpvorg");
782 if (nfo) {
783 TRACEI(DEBUG, " Setting vorg: " << nfo);
784 SecEntity.vorg = strdup(nfo);
785 TRACEI(REQ, " Setting vorg: " << SecEntity.vorg);
786 }
787
788 nfo = CurrentReq.opaque->Get("xrdhttpname");
789 if (nfo) {
790 TRACEI(DEBUG, " Setting name: " << nfo);
791 SecEntity.name = unquote(nfo);
792 TRACEI(REQ, " Setting name: " << SecEntity.name);
793 }
794
795 nfo = CurrentReq.opaque->Get("xrdhttphost");
796 if (nfo) {
797 TRACEI(DEBUG, " Setting host: " << nfo);
798 if (SecEntity.host) free(SecEntity.host);
799 SecEntity.host = unquote(nfo);
800 TRACEI(REQ, " Setting host: " << SecEntity.host);
801 }
802
803 nfo = CurrentReq.opaque->Get("xrdhttpdn");
804 if (nfo) {
805 TRACEI(DEBUG, " Setting dn: " << nfo);
806 SecEntity.moninfo = unquote(nfo);
807 TRACEI(REQ, " Setting dn: " << SecEntity.moninfo);
808 }
809
810 nfo = CurrentReq.opaque->Get("xrdhttprole");
811 if (nfo) {
812 TRACEI(DEBUG, " Setting role: " << nfo);
813 SecEntity.role = unquote(nfo);
814 TRACEI(REQ, " Setting role: " << SecEntity.role);
815 }
816
817 nfo = CurrentReq.opaque->Get("xrdhttpgrps");
818 if (nfo) {
819 TRACEI(DEBUG, " Setting grps: " << nfo);
820 SecEntity.grps = unquote(nfo);
821 TRACEI(REQ, " Setting grps: " << SecEntity.grps);
822 }
823
824 nfo = CurrentReq.opaque->Get("xrdhttpendorsements");
825 if (nfo) {
826 TRACEI(DEBUG, " Setting endorsements: " << nfo);
827 SecEntity.endorsements = unquote(nfo);
828 TRACEI(REQ, " Setting endorsements: " << SecEntity.endorsements);
829 }
830
831 nfo = CurrentReq.opaque->Get("xrdhttpcredslen");
832 if (nfo) {
833 TRACEI(DEBUG, " Setting credslen: " << nfo);
834 char *s1 = unquote(nfo);
835 if (s1 && s1[0]) {
836 SecEntity.credslen = atoi(s1);
837 TRACEI(REQ, " Setting credslen: " << SecEntity.credslen);
838 }
839 if (s1) free(s1);
840 }
841
842 if (SecEntity.credslen) {
843 nfo = CurrentReq.opaque->Get("xrdhttpcreds");
844 if (nfo) {
845 TRACEI(DEBUG, " Setting creds: " << nfo);
846 SecEntity.creds = unquote(nfo);
847 TRACEI(REQ, " Setting creds: " << SecEntity.creds);
848 }
849 }
850
851 char hash[512];
852
853 calcHashes(hash, CurrentReq.resource.c_str(), (kXR_int16) CurrentReq.request,
854 &SecEntity,
855 tim,
856 secretkey);
857
858 if (compareHash(hash, tk)) {
859 TRACEI(REQ, " Invalid tk '" << tk << "' != '" << hash << "'(calculated). Authentication failed.");
860 return -1;
861 }
862
863 } else {
864 // Client is plain http. If we have a secret key then we reject it
865 if (secretkey) {
866 TRACEI(ALL, " Rejecting plain http with no valid token as we have a secretkey.");
867 return -1;
868 }
869 }
870
871 } else {
872 // Client is plain http. If we have a secret key then we reject it
873 if (secretkey) {
874 TRACEI(ALL, " Rejecting plain http with no valid token as we have a secretkey.");
875 return -1;
876 }
877 }
878
879 ssldone = true;
880 }
881
882
883
884 // Now we have everything that is needed to try the login
885 // Remember that if there is an exthandler then it has the responsibility
886 // for authorization in the paths that it manages
887 if (!Bridge && !FindMatchingExtHandler(CurrentReq)) {
888 if (SecEntity.name)
889 Bridge = XrdXrootd::Bridge::Login(&CurrentReq, Link, &SecEntity, SecEntity.name, ishttps ? "https" : "http");
890 else
891 Bridge = XrdXrootd::Bridge::Login(&CurrentReq, Link, &SecEntity, "unknown", ishttps ? "https" : "http");
892
893 if (!Bridge) {
894 TRACEI(REQ, " Authorization failed.");
895 return -1;
896 }
897
898 // Let the bridge process the login, and then reinvoke us
899 DoingLogin = true;
900 return 0;
901 }
902
903 // Compute and send the response. This may involve further reading from the socket
904 rc = CurrentReq.ProcessHTTPReq();
905 if (rc < 0)
906 CurrentReq.reset();
907
908
909
910 TRACEI(REQ, "Process is exiting rc:" << rc);
911 return rc;
912}
@ kXR_set
Definition XProtocol.hh:130
short kXR_int16
Definition XPtypes.hh:66
#define XRHTTP_TK_GRACETIME
#define TRACE_AUTH
int compareHash(const char *h1, const char *h2)
char * unquote(char *str)
void calcHashes(char *hash, const char *fn, kXR_int16 request, XrdSecEntity *secent, time_t tim, const char *key)
std::string obfuscateAuth(const std::string &input)
#define TRACE_DEBUG
Definition XrdTrace.hh:36
#define TRACE(act, x)
Definition XrdTrace.hh:63
#define TRACING(x)
Definition XrdTrace.hh:70
static char * secretkey
The key used to calculate the url hashes.
static bool selfhttps2http
If client is HTTPS, self-redirect with HTTP+token.
static char * sslcadir
static Bridge * Login(Result *rsltP, XrdLink *linkP, XrdSecEntity *seceP, const char *nameP, const char *protP)

References Addr_str, Bridge, XrdOucString::c_str(), calcHashes(), compareHash(), CurrentReq, DEBUG, eDest, kXR_set, Link, XrdXrootd::Bridge::Login(), obfuscateAuth(), Port_str, XrdHttpReq::rtGET, XrdHttpReq::rtPROPFIND, XrdHttpReq::rtPUT, SecEntity, secretkey, selfhttps2http, sslcadir, TRACE, TRACE_AUTH, TRACE_DEBUG, TRACEI, TRACING, unquote(), XrdHttpProtoInfo::xrdctx, and XRHTTP_TK_GRACETIME.

+ Here is the call graph for this function:

◆ Recycle()

void XrdHttpProtocol::Recycle ( XrdLink * lp,
int consec,
const char * reason )
virtual

Recycle this instance.

Implements XrdProtocol.

Definition at line 920 of file XrdHttpProtocol.cc.

920 {
921
922 // Release all appendages
923 //
924
925 Cleanup();
926
927
928 // Set fields to starting point (debugging mostly)
929 //
930 Reset();
931
932 // Push ourselves on the stack
933 //
934 ProtStack.Push(&ProtLink);
935}

References ProtLink, and ProtStack.

◆ Stats()

int XrdHttpProtocol::Stats ( char * buff,
int blen,
int do_sync = 0 )
virtual

Get activity stats.

Implements XrdProtocol.

Definition at line 937 of file XrdHttpProtocol.cc.

937 {
938 // Synchronize statistics if need be
939 //
940 // if (do_sync) {
941 //
942 // SI->statsMutex.Lock();
943 // SI->readCnt += numReads;
944 // cumReads += numReads;
945 // numReads = 0;
946 // SI->prerCnt += numReadP;
947 // cumReadP += numReadP;
948 // numReadP = 0;
949 // SI->rvecCnt += numReadV;
950 // cumReadV += numReadV;
951 // numReadV = 0;
952 // SI->rsegCnt += numSegsV;
953 // cumSegsV += numSegsV;
954 // numSegsV = 0;
955 // SI->writeCnt += numWrites;
956 // cumWrites += numWrites;
957 // numWrites = 0;
958 // SI->statsMutex.UnLock();
959 // }
960 //
961 // // Now return the statistics
962 // //
963 // return SI->Stats(buff, blen, do_sync);
964
965 return 0;
966}

Friends And Related Symbol Documentation

◆ XrdHttpExtReq

friend class XrdHttpExtReq
friend

Definition at line 82 of file XrdHttpProtocol.hh.

References XrdHttpExtReq.

Referenced by XrdHttpExtReq.

◆ XrdHttpReq

friend class XrdHttpReq
friend

Definition at line 81 of file XrdHttpProtocol.hh.

References XrdHttpReq.

Referenced by XrdHttpReq.

Member Data Documentation

◆ Addr_str

char* XrdHttpProtocol::Addr_str
protected

Our IP address, as a string. Please remember that this may not be unique for a given machine, hence we need to keep it here and recompute ad every new connection.

Definition at line 361 of file XrdHttpProtocol.hh.

Referenced by XrdHttpProtocol(), and Process().

◆ BPool

XrdBuffManager * XrdHttpProtocol::BPool = 0
staticprotected

Definition at line 352 of file XrdHttpProtocol.hh.

Referenced by Configure(), and Match().

◆ Bridge

XrdXrootd::Bridge* XrdHttpProtocol::Bridge
protected

The Bridge that we use to exercise the xrootd internals.

Definition at line 367 of file XrdHttpProtocol.hh.

Referenced by doChksum(), doStat(), and Process().

◆ CIA

XrdSecService * XrdHttpProtocol::CIA = 0
staticprotected

Definition at line 354 of file XrdHttpProtocol.hh.

◆ cksumHandler

XrdHttpChecksumHandler XrdHttpProtocol::cksumHandler = XrdHttpChecksumHandler()
static

Definition at line 135 of file XrdHttpProtocol.hh.

◆ compatNameGeneration

bool XrdHttpProtocol::compatNameGeneration = false
staticprotected

Definition at line 400 of file XrdHttpProtocol.hh.

◆ crlRefIntervalSec

int XrdHttpProtocol::crlRefIntervalSec = XrdTlsContext::DEFAULT_CRL_REF_INT_SEC
staticprotected

CRL thread refresh interval.

Definition at line 395 of file XrdHttpProtocol.hh.

◆ CurrentReq

XrdHttpReq XrdHttpProtocol::CurrentReq
protected

Area for coordinating request and responses to/from the bridge This also can process HTTP/DAV stuff

Definition at line 372 of file XrdHttpProtocol.hh.

Referenced by XrdHttpProtocol(), doChksum(), doStat(), and Process().

◆ eDest

XrdSysError XrdHttpProtocol::eDest = 0
staticprotected

Definition at line 353 of file XrdHttpProtocol.hh.

Referenced by Configure(), and Process().

◆ embeddedstatic

bool XrdHttpProtocol::embeddedstatic = true
staticprotected

If true, use the embedded css and icons.

Definition at line 421 of file XrdHttpProtocol.hh.

◆ gridmap

char * XrdHttpProtocol::gridmap = 0
staticprotected

Gridmap file location. The same used by XrdSecGsi.

Definition at line 398 of file XrdHttpProtocol.hh.

◆ hailWait

int XrdHttpProtocol::hailWait = 60000
staticprotected

Timeout for reading the handshake.

Definition at line 380 of file XrdHttpProtocol.hh.

Referenced by Match().

◆ hdr2cgimap

std::map< std::string, std::string > XrdHttpProtocol::hdr2cgimap
staticprotected

Rules that turn HTTP headers to cgi tokens in the URL, for internal comsumption.

Definition at line 437 of file XrdHttpProtocol.hh.

◆ isdesthttps

bool XrdHttpProtocol::isdesthttps = false
staticprotected

True if the redirections must be towards https targets.

Definition at line 409 of file XrdHttpProtocol.hh.

◆ isRequiredGridmap

bool XrdHttpProtocol::isRequiredGridmap = false
staticprotected

Definition at line 399 of file XrdHttpProtocol.hh.

◆ Link

XrdLink* XrdHttpProtocol::Link
protected

The link we are bound to.

Definition at line 357 of file XrdHttpProtocol.hh.

Referenced by Match(), and Process().

◆ listdeny

bool XrdHttpProtocol::listdeny = false
staticprotected

If true, any form of listing is denied.

Definition at line 415 of file XrdHttpProtocol.hh.

◆ listredir

char * XrdHttpProtocol::listredir = 0
staticprotected

Url to redirect to in the case a listing is requested.

Definition at line 412 of file XrdHttpProtocol.hh.

◆ m_bio_method

BIO_METHOD * XrdHttpProtocol::m_bio_method = NULL
staticprotected

C-style vptr table for our custom BIO objects.

Definition at line 443 of file XrdHttpProtocol.hh.

◆ m_bio_type

int XrdHttpProtocol::m_bio_type = 0
staticprotected

Type identifier for our custom BIO objects.

Definition at line 440 of file XrdHttpProtocol.hh.

◆ myRole

kXR_int32 XrdHttpProtocol::myRole = kXR_isManager
staticprotected

Our role.

Definition at line 434 of file XrdHttpProtocol.hh.

Referenced by Configure().

◆ pmarkHandle

XrdNetPMark * XrdHttpProtocol::pmarkHandle = nullptr
staticprotected

Packet marking handler pointer (assigned from the environment during the Config() call)

Definition at line 449 of file XrdHttpProtocol.hh.

◆ Port

int XrdHttpProtocol::Port = 1094
staticprotected

Our port.

Definition at line 386 of file XrdHttpProtocol.hh.

Referenced by Configure().

◆ Port_str

char * XrdHttpProtocol::Port_str = 0
staticprotected

Our port, as a string.

Definition at line 389 of file XrdHttpProtocol.hh.

Referenced by Configure(), and Process().

◆ ProtLink

XrdObject<XrdHttpProtocol> XrdHttpProtocol::ProtLink

Definition at line 128 of file XrdHttpProtocol.hh.

Referenced by XrdHttpProtocol(), and Recycle().

◆ ProtStack

XrdObjectQ< XrdHttpProtocol > XrdHttpProtocol::ProtStack
static

Definition at line 127 of file XrdHttpProtocol.hh.

Referenced by Configure(), Match(), and Recycle().

◆ ReadRangeConfig

XrdHttpReadRangeHandler::Configuration XrdHttpProtocol::ReadRangeConfig
static

configuration for the read range handler

Definition at line 138 of file XrdHttpProtocol.hh.

Referenced by XrdHttpProtocol().

◆ readWait

int XrdHttpProtocol::readWait = 300000
staticprotected

Timeout for reading data.

Definition at line 383 of file XrdHttpProtocol.hh.

◆ Sched

XrdScheduler * XrdHttpProtocol::Sched = 0
staticprotected

Definition at line 351 of file XrdHttpProtocol.hh.

Referenced by Configure().

◆ SecEntity

XrdSecEntity XrdHttpProtocol::SecEntity

Authentication area.

Definition at line 132 of file XrdHttpProtocol.hh.

Referenced by XrdHttpProtocol(), Match(), and Process().

◆ secretkey

char * XrdHttpProtocol::secretkey = 0
staticprotected

The key used to calculate the url hashes.

Definition at line 403 of file XrdHttpProtocol.hh.

Referenced by Process().

◆ selfhttps2http

bool XrdHttpProtocol::selfhttps2http = false
staticprotected

If client is HTTPS, self-redirect with HTTP+token.

Definition at line 418 of file XrdHttpProtocol.hh.

Referenced by Process().

◆ servGMap

XrdOucGMap * XrdHttpProtocol::servGMap = 0
staticprotected

The instance of the DN mapper. Created only when a valid path is given.

Definition at line 364 of file XrdHttpProtocol.hh.

◆ sslcadir

char * XrdHttpProtocol::sslcadir = 0
staticprotected

Definition at line 392 of file XrdHttpProtocol.hh.

Referenced by Process().

◆ sslcafile

char * XrdHttpProtocol::sslcafile = 0
staticprotected

Definition at line 392 of file XrdHttpProtocol.hh.

◆ sslcert

char * XrdHttpProtocol::sslcert = 0
staticprotected

OpenSSL stuff.

Definition at line 392 of file XrdHttpProtocol.hh.

◆ sslcipherfilter

char * XrdHttpProtocol::sslcipherfilter = 0
staticprotected

Definition at line 392 of file XrdHttpProtocol.hh.

◆ sslkey

char * XrdHttpProtocol::sslkey = 0
staticprotected

Definition at line 392 of file XrdHttpProtocol.hh.

◆ sslverifydepth

int XrdHttpProtocol::sslverifydepth = 9
staticprotected

Depth of verification of a certificate chain.

Definition at line 406 of file XrdHttpProtocol.hh.

◆ staticpreload

XrdOucHash< XrdHttpProtocol::StaticPreloadInfo > * XrdHttpProtocol::staticpreload = 0
staticprotected

Definition at line 431 of file XrdHttpProtocol.hh.

◆ staticredir

char * XrdHttpProtocol::staticredir = 0
staticprotected

Definition at line 424 of file XrdHttpProtocol.hh.

◆ tpcForwardCreds

bool XrdHttpProtocol::tpcForwardCreds = false
staticprotected

If set to true, the HTTP TPC transfers will forward the credentials to redirected hosts.

Definition at line 452 of file XrdHttpProtocol.hh.

◆ xrd_cslist

char * XrdHttpProtocol::xrd_cslist = nullptr
staticprotected

The list of checksums that were configured via the xrd.cksum parameter on the server config file.

Definition at line 446 of file XrdHttpProtocol.hh.

Referenced by Configure().


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