24#include "XrdVersion.hh"
51#include <openssl/err.h>
52#include <openssl/ssl.h>
61#define XRHTTP_TK_GRACETIME 600
103BIO *XrdHttpProtocol::sslbio_err = 0;
105bool XrdHttpProtocol::isRequiredXtractor =
false;
109int XrdHttpProtocol::exthandlercnt = 0;
112bool XrdHttpProtocol::usingEC = false;
113bool XrdHttpProtocol::hasCache= false;
134const char *TraceID =
"Protocol";
161 "xrootd protocol anchor");
167#if OPENSSL_VERSION_NUMBER < 0x10100000L
174#if OPENSSL_VERSION_NUMBER < 0x1000105fL
189 bio->shutdown = shut;
192 return bio->shutdown;
230 char mybuf[16], mybuf2[1024];
233 bool myishttps =
false;
237 if ((dlen = lp->
Peek(mybuf, (
int) sizeof (mybuf),
hailWait)) < (
int)
sizeof (mybuf)) {
238 if (dlen <= 0) lp->
setEtext(
"handshake not received");
241 mybuf[dlen - 1] =
'\0';
249 for (
int i = 0; i < dlen; i++) {
251 sprintf(mybuf3,
"%.02d ", mybuf[i]);
252 strcat(mybuf2, mybuf3);
259 for (
int i = 0; i < dlen - 1; i++)
260 if (!isprint(mybuf[i]) && (mybuf[i] !=
'\r') && (mybuf[i] !=
'\n')) {
262 TRACEI(
DEBUG,
"This does not look like http at pos " << i);
267 if ((!ismine) && (dlen >= 4)) {
268 char check[4] = {00, 00, 00, 00};
269 if (memcmp(mybuf, check, 4)) {
276 TRACEI(ALL,
"This may look like https, but https is not configured");
283 TRACEI(
DEBUG,
"This does not look like https. Protocol not matched.");
291 TRACEI(REQ,
"Protocol matched. https: " << myishttps);
294 hp->ishttps = myishttps;
307 hp->myBuff =
BPool->Obtain(1024 * 1024);
309 hp->myBuffStart = hp->myBuffEnd = hp->myBuff->
buff;
317char *XrdHttpProtocol::GetClientIPStr() {
320 if (!
Link)
return strdup(
"unknown");
322 if (!ai)
return strdup(
"unknown");
330#if OPENSSL_VERSION_NUMBER < 0x1000105fL
341 int ret = lp->
Send(data, datal);
342 BIO_clear_retry_flags(bio);
345 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
346 BIO_set_retry_write(bio);
362 int ret = lp->
Send(data, datal);
363 BIO_clear_retry_flags(bio);
365 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
366 BIO_set_retry_write(bio);
373#if OPENSSL_VERSION_NUMBER < 0x1000105fL
384 int ret = lp->
Recv(data, datal);
385 BIO_clear_retry_flags(bio);
388 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
389 BIO_set_retry_read(bio);
404 int ret = lp->
Recv(data, datal);
405 BIO_clear_retry_flags(bio);
407 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
408 BIO_set_retry_read(bio);
424#if OPENSSL_VERSION_NUMBER < 0x10100000L
436 if (bio == NULL)
return 0;
452 case BIO_CTRL_GET_CLOSE:
455 case BIO_CTRL_SET_CLOSE:
470BIO *XrdHttpProtocol::CreateBIO(
XrdLink *lp)
489#define TRACELINK Link
497 if (!myBuff || !myBuff->buff || !myBuff->bsize) {
498 TRACE(ALL,
" Process. No buffer available. Internal error.");
504 char *nfo = GetClientIPStr();
506 TRACEI(REQ,
" Setting host: " << nfo);
515 if (ishttps && !ssldone) {
518 sbio = CreateBIO(
Link);
519 BIO_set_nbio(sbio, 1);
520 ssl = (SSL*)
xrdctx->Session();
525 ERR_print_errors(sslbio_err);
532 secxtractor->InitSSL(ssl,
sslcadir);
534 SSL_set_bio(ssl, sbio, sbio);
541 setsockopt(
Link->FDnum(), SOL_SOCKET, SO_RCVTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
542 setsockopt(
Link->FDnum(), SOL_SOCKET, SO_SNDTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
545 int res = SSL_accept(ssl);
547 if ((res == -1) && (SSL_get_error(ssl, res) == SSL_ERROR_WANT_READ)) {
548 TRACEI(
DEBUG,
" SSL_accept wants to read more bytes... err:" << SSL_get_error(ssl, res));
553 ERR_print_errors(sslbio_err);
562 BIO_set_nbio(sbio, 0);
588 if ((rc = getDataOneShot(BuffAvailable())) < 0) {
594 if (BuffUsed() < ResumeBytes)
return 1;
599 }
else if (!DoneSetInfo && !
CurrentReq.userAgent().empty()) {
600 std::string mon_info =
"monitor info " +
CurrentReq.userAgent();
602 if (mon_info.size() >= 1024) {
603 TRACEI(ALL,
"User agent string too long");
605 TRACEI(ALL,
"Internal logic error: Bridge is null after login");
612 CurrentReq.xrdreq.set.dlen = htonl(mon_info.size());
613 if (!
Bridge->Run((
char *) &
CurrentReq.xrdreq, (
char *) mon_info.c_str(), mon_info.size())) {
614 SendSimpleResp(500,
nullptr,
nullptr,
"Could not set user agent.", 0,
false);
629 while ((rc = BuffgetLine(tmpline)) > 0) {
630 std::string traceLine = tmpline.c_str();
634 TRACE(
DEBUG,
" rc:" << rc <<
" got hdr line: " << traceLine);
635 if ((rc == 2) && (tmpline.length() > 1) && (tmpline[rc - 1] ==
'\n')) {
637 TRACE(
DEBUG,
" rc:" << rc <<
" detected header end.");
643 TRACE(
DEBUG,
" Parsing first line: " << traceLine.c_str());
644 int result =
CurrentReq.parseFirstLine((
char *)tmpline.c_str(), rc);
646 TRACE(
DEBUG,
" Parsing of first line failed with " << result);
650 int result =
CurrentReq.parseLine((
char *) tmpline.c_str(), rc);
652 TRACE(
DEBUG,
" Parsing of header line failed with " << result)
653 SendSimpleResp(400,NULL,NULL,
"Malformed header line. Hint: ensure the line finishes with \"\\r\\n\"", 0,
false);
664 TRACEI(REQ,
" rc:" << rc <<
"Header not yet complete.");
669 if ((rc <= 0) && (BuffUsed() >= 16384)) {
670 TRACEI(ALL,
"Corrupted header detected, or line too long. Disconnecting client.");
689 time_t timenow = time(0);
707 TRACEI(REQ,
" rc:" << rc <<
" self-redirecting to http with security token.");
714 struct sockaddr_storage sa;
715 socklen_t sl =
sizeof(sa);
716 getsockname(this->
Link->AddrInfo()->SockFD(), (
struct sockaddr*)&sa, &sl);
722 switch (sa.ss_family) {
724 if (inet_ntop(AF_INET, &(((sockaddr_in*)&sa)->sin_addr), buf, INET_ADDRSTRLEN)) {
731 if (inet_ntop(AF_INET6, &(((sockaddr_in6*)&sa)->sin6_addr), buf, INET6_ADDRSTRLEN)) {
733 Addr_str = (
char *)malloc(strlen(buf)+3);
741 TRACEI(REQ,
" Can't recognize the address family of the local host.");
749 TRACEI(REQ,
" rc:"<<rc<<
" self-redirecting to http with security token: '"
750 << dest.
c_str() <<
"'");
754 SendSimpleResp(302, NULL, (
char *) dest.
c_str(), 0, 0,
true);
759 TRACEI(REQ,
" rc:" << rc <<
" Can't perform self-redirection.");
763 TRACEI(ALL,
" Could not calculate self-redirection hash");
769 if (!ishttps && !ssldone) {
773 char * tk =
CurrentReq.opaque->Get(
"xrdhttptk");
778 char * t =
CurrentReq.opaque->Get(
"xrdhttptime");
779 if (t) tim = atoi(t);
781 TRACEI(REQ,
" xrdhttptime not specified. Authentication failed.");
785 TRACEI(REQ,
" Token expired. Authentication failed.");
835 nfo =
CurrentReq.opaque->Get(
"xrdhttpendorsements");
842 nfo =
CurrentReq.opaque->Get(
"xrdhttpcredslen");
870 TRACEI(REQ,
" Invalid tk '" << tk <<
"' != '" << hash <<
"'(calculated). Authentication failed.");
877 TRACEI(ALL,
" Rejecting plain http with no valid token as we have a secretkey.");
885 TRACEI(ALL,
" Rejecting plain http with no valid token as we have a secretkey.");
905 TRACEI(REQ,
" Authorization failed.");
922 TRACEI(REQ,
"Process is exiting rc:" << rc);
930#define TRACELINK Link
984#define TS_Xeq(x,m) (!strcmp(x,var)) GoNo = m(Config)
986#define TS_Xeq3(x,m) (!strcmp(x,var)) GoNo = m(Config, extHIVec)
988#define HTTPS_ALERT(x,y,z) httpsspec = true;\
989 if (xrdctx && httpsmode == hsmAuto && (z || xrdctx->x509Verify())) \
990 eDest.Say("Config http." x " overrides the xrd." y " directive.")
992int XrdHttpProtocol::Config(
const char *ConfigFN,
XrdOucEnv *myEnv) {
995 std::vector<extHInfo> extHIVec;
997 int cfgFD, GoNo, NoGo = 0, ismine;
1007 if(nonIanaChecksums.size()) {
1008 std::stringstream warningMsgSS;
1009 warningMsgSS <<
"Config warning: the following checksum algorithms are not IANA compliant: [";
1010 std::string unknownCksumString;
1011 for(
auto unknownCksum: nonIanaChecksums) {
1012 unknownCksumString += unknownCksum +
",";
1014 unknownCksumString.erase(unknownCksumString.size() - 1);
1015 warningMsgSS << unknownCksumString <<
"]" <<
". They therefore cannot be queried by a user via HTTP." ;
1016 eDest.Say(warningMsgSS.str().c_str());
1022 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1024 m_bio_method =
static_cast<BIO_METHOD*
>(OPENSSL_malloc(
sizeof(BIO_METHOD)));
1059 if ((cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
1060 return eDest.Emsg(
"Config", errno,
"open config file", ConfigFN);
1061 Config.Attach(cfgFD);
1062 static const char *cvec[] = {
"*** http protocol config:", 0 };
1063 Config.Capture(cvec);
1067 while ((var = Config.GetMyFirstWord())) {
1068 if ((ismine = !strncmp(
"http.", var, 5)) && var[5]) var += 5;
1071 if TS_Xeq(
"trace", xtrace);
1072 else if TS_Xeq(
"cert", xsslcert);
1073 else if TS_Xeq(
"key", xsslkey);
1074 else if TS_Xeq(
"cadir", xsslcadir);
1075 else if TS_Xeq(
"cipherfilter", xsslcipherfilter);
1076 else if TS_Xeq(
"gridmap", xgmap);
1077 else if TS_Xeq(
"cafile", xsslcafile);
1078 else if TS_Xeq(
"secretkey", xsecretkey);
1079 else if TS_Xeq(
"desthttps", xdesthttps);
1080 else if TS_Xeq(
"secxtractor", xsecxtractor);
1081 else if TS_Xeq(
"cors", xcors);
1082 else if TS_Xeq3(
"exthandler", xexthandler);
1083 else if TS_Xeq(
"selfhttps2http", xselfhttps2http);
1084 else if TS_Xeq(
"embeddedstatic", xembeddedstatic);
1085 else if TS_Xeq(
"listingredir", xlistredir);
1086 else if TS_Xeq(
"staticredir", xstaticredir);
1087 else if TS_Xeq(
"staticpreload", xstaticpreload);
1088 else if TS_Xeq(
"staticheader", xstaticheader);
1089 else if TS_Xeq(
"listingdeny", xlistdeny);
1090 else if TS_Xeq(
"header2cgi", xheader2cgi);
1091 else if TS_Xeq(
"httpsmode", xhttpsmode);
1092 else if TS_Xeq(
"tlsreuse", xtlsreuse);
1093 else if TS_Xeq(
"auth", xauth);
1094 else if TS_Xeq(
"tlsclientauth", xtlsclientauth);
1095 else if TS_Xeq(
"maxdelay", xmaxdelay);
1097 eDest.Say(
"Config warning: ignoring unknown directive '", var,
"'.");
1112 {
eDest.Say(
"Config failure: one or more directives are flawed!");
1118 hdr2cgimap[
"Cache-Control"] =
"cache-control";
1121 if (getenv(
"XRDCL_EC"))
usingEC =
true;
1126 std::string default_static_headers;
1128 for (
const auto &header_entry : default_verb->second) {
1129 default_static_headers += header_entry.first +
": " + header_entry.second +
"\r\n";
1134 if (item.first.empty()) {
1137 auto headers = default_static_headers;
1138 for (
const auto &header_entry : item.second) {
1139 headers += header_entry.first +
": " + header_entry.second +
"\r\n";
1147 if (myEnv->
Get(
"XrdCache")) hasCache =
true;
1166 :
"was not configured.");
1167 const char *what = Configed();
1169 eDest.Say(
"Config warning: HTTPS functionality ", why);
1172 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1174 {
eDest.Say(
"Config failure: ", what,
" HTTPS but it ", why);
1184 {
eDest.Say(
"Config warning: specifying http.key without http.cert "
1185 "is meaningless; ignoring key!");
1193 {
eDest.Say(
"Config failure: 'httpsmode manual' requires atleast a "
1194 "a cert specification!");
1205 const char *what1 = 0, *what2 = 0, *what3 = 0;
1210 what1 =
"xrd.tls to supply 'cert' and 'key'.";
1214 what2 =
"xrd.tlsca to supply 'cadir'.";
1218 what2 = (what2 ?
"xrd.tlsca to supply 'cadir' and 'cafile'."
1219 :
"xrd.tlsca to supply 'cafile'.");
1223 what3 =
"xrd.tlsca to supply 'refresh' interval.";
1233 {
const char *what = Configed();
1234 const char *why = (
httpsspec ?
"a cadir or cafile was not specified!"
1235 :
"'xrd.tlsca noverify' was specified!");
1237 {
eDest.Say(
"Config failure: ", what,
" cert verification but ", why);
1245 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1250 const char *how =
"completed.";
1251 eDest.Say(
"++++++ HTTPS initialization started.");
1252 if (!InitTLS()) {NoGo = 1; how =
"failed.";}
1253 eDest.Say(
"------ HTTPS initialization ", how);
1254 if (NoGo)
return NoGo;
1258 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv))
return 1;
1262 return (InitSecurity() ? NoGo : 1);
1269const char *XrdHttpProtocol::Configed()
1271 if (secxtractor &&
gridmap)
return "gridmap and secxtractor require";
1272 if (secxtractor)
return "secxtractor requires";
1273 if (
gridmap)
return "gridmap requires";
1289 if (myBuffEnd >= myBuffStart) {
1291 for (
char *p = myBuffStart; p < myBuffEnd; p++) {
1296 dest.
assign(myBuffStart, 0, l-1);
1315 for (
char *p = myBuffStart; p < myBuff->buff + myBuff->bsize; p++) {
1317 if ((*p ==
'\n') || (*p ==
'\0')) {
1320 dest.
assign(myBuffStart, 0, l-1);
1336 for (
char *p = myBuff->buff; p < myBuffEnd; p++) {
1338 if ((*p ==
'\n') || (*p ==
'\0')) {
1342 int l1 = myBuff->buff + myBuff->bsize - myBuffStart;
1344 dest.
assign(myBuffStart, 0, l1-1);
1348 dest.
insert(myBuffStart, l1, l-1);
1372int XrdHttpProtocol::getDataOneShot(
int blen,
bool wait) {
1387 maxread = std::min(blen, BuffAvailable());
1388 TRACE(
DEBUG,
"getDataOneShot BuffAvailable: " << BuffAvailable() <<
" maxread: " << maxread);
1394 int sslavail = maxread;
1397 int l = SSL_pending(ssl);
1399 sslavail = std::min(maxread, SSL_pending(ssl));
1403 Link->setEtext(
"link SSL_pending error");
1404 ERR_print_errors(sslbio_err);
1408 TRACE(
DEBUG,
"getDataOneShot sslavail: " << sslavail);
1409 if (sslavail <= 0)
return 0;
1411 if (myBuffEnd - myBuff->buff >= myBuff->bsize) {
1413 myBuffEnd = myBuff->buff;
1416 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1418 Link->setEtext(
"link SSL read error");
1419 ERR_print_errors(sslbio_err);
1426 if (myBuffEnd - myBuff->buff >= myBuff->bsize) {
1428 myBuffEnd = myBuff->buff;
1434 rlen =
Link->Recv(myBuffEnd, maxread);
1438 Link->setEtext(
"link read error or closed");
1443 Link->setEtext(
"link timeout or other error");
1450 TRACE(REQ,
"read " << rlen <<
" of " << blen <<
" bytes");
1457int XrdHttpProtocol::BuffAvailable() {
1460 if (myBuffEnd >= myBuffStart)
1461 r = myBuff->buff + myBuff->bsize - myBuffEnd;
1463 r = myBuffStart - myBuffEnd;
1465 if ((r < 0) || (r > myBuff->bsize)) {
1466 TRACE(REQ,
"internal error, myBuffAvailable: " << r <<
" myBuff->bsize " << myBuff->bsize);
1479int XrdHttpProtocol::BuffUsed() {
1482 if (myBuffEnd >= myBuffStart)
1483 r = myBuffEnd - myBuffStart;
1486 r = myBuff->bsize - (myBuffStart - myBuffEnd);
1488 if ((r < 0) || (r > myBuff->bsize)) {
1489 TRACE(REQ,
"internal error, myBuffUsed: " << r <<
" myBuff->bsize " << myBuff->bsize);
1502int XrdHttpProtocol::BuffFree() {
1503 return (myBuff->bsize - BuffUsed());
1510void XrdHttpProtocol::BuffConsume(
int blen) {
1512 if (blen > myBuff->bsize) {
1513 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") smaller than buffsize");
1517 if (blen > BuffUsed()) {
1518 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") larger than BuffUsed:" << BuffUsed());
1522 myBuffStart = myBuffStart + blen;
1524 if (myBuffStart >= myBuff->buff + myBuff->bsize)
1525 myBuffStart -= myBuff->bsize;
1527 if (myBuffEnd >= myBuff->buff + myBuff->bsize)
1528 myBuffEnd -= myBuff->bsize;
1530 if (BuffUsed() == 0)
1531 myBuffStart = myBuffEnd = myBuff->buff;
1546int XrdHttpProtocol::BuffgetData(
int blen,
char **data,
bool wait) {
1549 TRACE(
DEBUG,
"BuffgetData: requested " << blen <<
" bytes");
1554 if (blen > BuffUsed()) {
1555 TRACE(REQ,
"BuffgetData: need to read " << blen - BuffUsed() <<
" bytes");
1556 if ( getDataOneShot(blen - BuffUsed(),
true) )
1562 if ( !BuffUsed() ) {
1563 if ( getDataOneShot(blen,
false) )
1571 if (myBuffStart <= myBuffEnd) {
1572 rlen = std::min( (
long) blen, (
long)(myBuffEnd - myBuffStart) );
1575 rlen = std::min( (
long) blen, (
long)(myBuff->buff + myBuff->bsize - myBuffStart) );
1577 *data = myBuffStart;
1588int XrdHttpProtocol::SendData(
const char *body,
int bodylen) {
1592 if (body && bodylen) {
1593 TRACE(REQ,
"Sending " << bodylen <<
" bytes");
1595 r = SSL_write(ssl, body, bodylen);
1597 ERR_print_errors(sslbio_err);
1602 r =
Link->Send(body, bodylen);
1603 if (r <= 0)
return -1;
1614int XrdHttpProtocol::StartSimpleResp(
int code,
const char *desc,
1615 const char *header_to_add,
1616 long long bodylen,
bool keepalive) {
1617 static const std::unordered_map<int, std::string> statusTexts = {
1621 {206,
"Partial Content"},
1623 {307,
"Temporary Redirect"},
1624 {400,
"Bad Request"},
1625 {401,
"Unauthorized"},
1628 {405,
"Method Not Allowed"},
1630 {416,
"Range Not Satisfiable"},
1632 {500,
"Internal Server Error"},
1633 {502,
"Bad Gateway"},
1634 {504,
"Gateway Timeout"},
1635 {507,
"Insufficient Storage"}};
1637 std::stringstream ss;
1638 const std::string crlf =
"\r\n";
1640 ss <<
"HTTP/1.1 " << code <<
" ";
1645 auto it = statusTexts.find(code);
1646 if (it != statusTexts.end()) {
1654 if (keepalive && (code != 100))
1655 ss <<
"Connection: Keep-Alive" << crlf;
1657 ss <<
"Connection: Close" << crlf;
1659 ss <<
"Server: XrootD/" << XrdVSTRING << crlf;
1670 if(corsAllowOrigin) {
1671 ss << *corsAllowOrigin << crlf;
1675 if ((bodylen >= 0) && (code != 100))
1676 ss <<
"Content-Length: " << bodylen << crlf;
1678 if (header_to_add && (header_to_add[0] !=
'\0')) ss << header_to_add << crlf;
1682 const std::string &outhdr = ss.str();
1683 TRACEI(RSP,
"Sending resp: " << code <<
" header len:" << outhdr.size());
1684 if (SendData(outhdr.c_str(), outhdr.size()))
1694int XrdHttpProtocol::StartChunkedResp(
int code,
const char *desc,
const char *header_to_add,
long long bodylen,
bool keepalive) {
1695 const std::string crlf =
"\r\n";
1696 std::stringstream ss;
1698 if (header_to_add && (header_to_add[0] !=
'\0')) {
1699 ss << header_to_add << crlf;
1702 ss <<
"Transfer-Encoding: chunked";
1703 TRACEI(RSP,
"Starting chunked response");
1704 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1711int XrdHttpProtocol::ChunkResp(
const char *body,
long long bodylen) {
1712 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1713 if (ChunkRespHeader(content_length))
1716 if (body && SendData(body, content_length))
1719 return ChunkRespFooter();
1726int XrdHttpProtocol::ChunkRespHeader(
long long bodylen) {
1727 const std::string crlf =
"\r\n";
1728 std::stringstream ss;
1730 ss << std::hex << bodylen << std::dec << crlf;
1732 const std::string &chunkhdr = ss.str();
1733 TRACEI(RSP,
"Sending encoded chunk of size " << bodylen);
1734 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1741int XrdHttpProtocol::ChunkRespFooter() {
1742 const std::string crlf =
"\r\n";
1743 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1754int XrdHttpProtocol::SendSimpleResp(
int code,
const char *desc,
const char *header_to_add,
const char *body,
long long bodylen,
bool keepalive) {
1756 long long content_length = bodylen;
1758 content_length = body ? strlen(body) : 0;
1761 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1768 return SendData(body, content_length);
1805 sprintf(buf,
"%d",
Port);
1811 rdf = (parms && *parms ? parms : pi->
ConfigFN);
1812 if (rdf && Config(rdf, pi->
theEnv))
return 0;
1817 if ((rdf = getenv(
"XRDROLE"))) {
1818 eDest.Emsg(
"Config",
"XRDROLE: ", rdf);
1820 if (!strcasecmp(rdf,
"manager") || !strcasecmp(rdf,
"supervisor")) {
1822 eDest.Emsg(
"Config",
"Configured as HTTP(s) redirector.");
1825 eDest.Emsg(
"Config",
"Configured as HTTP(s) data server.");
1829 eDest.Emsg(
"Config",
"No XRDROLE specified.");
1848 char *val, keybuf[1024], parmbuf[1024];
1852 val = Config.GetWord();
1853 if (!val || !val[0]) {
1854 err.
Emsg(
"Config",
"No headerkey specified.");
1859 while ( *val && !isalnum(*val) ) val++;
1860 strcpy(keybuf, val);
1864 pp = keybuf + strlen(keybuf) - 1;
1865 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1870 parm = Config.GetWord();
1873 if(!parm || !parm[0]) {
1874 err.
Emsg(
"Config",
"No header2cgi value specified. key: '", keybuf,
"'");
1879 while ( *parm && !isalnum(*parm) ) parm++;
1880 strcpy(parmbuf, parm);
1883 pp = parmbuf + strlen(parmbuf) - 1;
1884 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1891 header2cgi[keybuf] = parmbuf;
1893 err.
Emsg(
"Config",
"Can't insert new header2cgi rule. key: '", keybuf,
"'");
1906bool XrdHttpProtocol::InitTLS() {
1923 {
eDest.Say(
"Config failure: ",
eMsg.c_str());
1931 static const char *sess_ctx_id =
"XrdHTTPSessionCtx";
1932 unsigned int n =(
unsigned int)(strlen(sess_ctx_id)+1);
1938 {
eDest.Say(
"Config failure: ",
"Unable to set allowable https ciphers!");
1954void XrdHttpProtocol::Cleanup() {
1956 TRACE(ALL,
" Cleanup");
1958 if (
BPool && myBuff) {
1959 BuffConsume(BuffUsed());
1960 BPool->Release(myBuff);
1974 int ret = SSL_shutdown(ssl);
1978 ret = SSL_shutdown(ssl);
1980 TRACE(ALL,
"SSL server failed to receive the SSL shutdown message from the client");
1981 ERR_print_errors(sslbio_err);
1985 TRACE(ALL,
"SSL server failed to send the shutdown message to the client");
1986 ERR_print_errors(sslbio_err);
1991 secxtractor->FreeSSL(ssl);
2020void XrdHttpProtocol::Reset() {
2022 TRACE(ALL,
" Reset");
2028 BPool->Release(myBuff);
2031 myBuffStart = myBuffEnd = 0;
2034 DoneSetInfo =
false;
2078int XrdHttpProtocol::xhttpsmode(
XrdOucStream & Config) {
2083 val = Config.GetWord();
2084 if (!val || !val[0]) {
2085 eDest.Emsg(
"Config",
"httpsmode parameter not specified");
2094 else {
eDest.Emsg(
"Config",
"invalid httpsmode parameter - ", val);
2113int XrdHttpProtocol::xsslverifydepth(
XrdOucStream & Config) {
2118 val = Config.GetWord();
2119 if (!val || !val[0]) {
2120 eDest.Emsg(
"Config",
"sslverifydepth value not specified");
2150 val = Config.GetWord();
2151 if (!val || !val[0]) {
2152 eDest.Emsg(
"Config",
"HTTP X509 certificate not specified");
2185 val = Config.GetWord();
2186 if (!val || !val[0]) {
2187 eDest.Emsg(
"Config",
"HTTP X509 key not specified");
2222 val = Config.GetWord();
2223 if (!val || !val[0]) {
2224 eDest.Emsg(
"Config",
"HTTP X509 gridmap file location not specified");
2230 if (!strncmp(val,
"required", 8)) {
2232 val = Config.GetWord();
2234 if (!val || !val[0]) {
2235 eDest.Emsg(
"Config",
"HTTP X509 gridmap file missing after [required] "
2243 if (!strcmp(val,
"compatNameGeneration")) {
2245 val = Config.GetWord();
2246 if (!val || !val[0]) {
2247 eDest.Emsg(
"Config",
"HTTP X509 gridmap file missing after "
2248 "[compatNameGeneration] parameter");
2274int XrdHttpProtocol::xsslcafile(
XrdOucStream & Config) {
2279 val = Config.GetWord();
2280 if (!val || !val[0]) {
2281 eDest.Emsg(
"Config",
"HTTP X509 CAfile not specified");
2307int XrdHttpProtocol::xsecretkey(
XrdOucStream & Config) {
2309 bool inFile =
false;
2313 val = Config.GetWord();
2314 if (!val || !val[0]) {
2315 eDest.Emsg(
"Config",
"Shared secret key not specified");
2323 if (val[0] ==
'/') {
2326 int fd =
open(val, O_RDONLY);
2329 eDest.Emsg(
"Config", errno,
"open shared secret key file", val);
2333 if (
fstat(fd, &st) != 0 ) {
2334 eDest.Emsg(
"Config", errno,
"fstat shared secret key file", val);
2339 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2340 eDest.Emsg(
"Config",
2341 "For your own security, the shared secret key file cannot be world readable or group writable '", val,
"'");
2346 FILE *fp = fdopen(fd,
"r");
2348 if ( fp ==
nullptr ) {
2349 eDest.Emsg(
"Config", errno,
"fdopen shared secret key file", val);
2355 while( fgets(line, 1024, fp) ) {
2359 pp = line + strlen(line) - 1;
2360 while ( (pp >= line) && (!isalnum(*pp)) ) {
2367 while ( *pp && !isalnum(*pp) ) pp++;
2369 if ( strlen(pp) >= 32 ) {
2370 eDest.Say(
"Config",
"Secret key loaded.");
2382 eDest.Emsg(
"Config",
"Cannot find useful secretkey in file '", val,
"'");
2387 if ( strlen(val) < 32 ) {
2388 eDest.Emsg(
"Config",
"Secret key is too short");
2395 if (!inFile) Config.noEcho();
2418 val = Config.GetWord();
2419 if (!val || !val[0]) {
2420 eDest.Emsg(
"Config",
"listingdeny flag not specified");
2426 listdeny = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2445int XrdHttpProtocol::xlistredir(
XrdOucStream & Config) {
2450 val = Config.GetWord();
2451 if (!val || !val[0]) {
2452 eDest.Emsg(
"Config",
"listingredir flag not specified");
2478int XrdHttpProtocol::xdesthttps(
XrdOucStream & Config) {
2483 val = Config.GetWord();
2484 if (!val || !val[0]) {
2485 eDest.Emsg(
"Config",
"desthttps flag not specified");
2491 isdesthttps = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2510int XrdHttpProtocol::xembeddedstatic(
XrdOucStream & Config) {
2515 val = Config.GetWord();
2516 if (!val || !val[0]) {
2517 eDest.Emsg(
"Config",
"embeddedstatic flag not specified");
2523 embeddedstatic = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2542int XrdHttpProtocol::xstaticredir(
XrdOucStream & Config) {
2547 val = Config.GetWord();
2548 if (!val || !val[0]) {
2549 eDest.Emsg(
"Config",
"staticredir url not specified");
2577int XrdHttpProtocol::xstaticpreload(
XrdOucStream & Config) {
2578 char *val, *k, key[1024];
2582 k = Config.GetWord();
2584 eDest.Emsg(
"Config",
"preloadstatic urlpath not specified");
2592 val = Config.GetWord();
2593 if (!val || !val[0]) {
2594 eDest.Emsg(
"Config",
"preloadstatic filename not specified");
2599 int fp =
open(val, O_RDONLY);
2601 eDest.Emsg(
"Config", errno,
"open preloadstatic filename", val);
2607 nfo->
data = (
char *)malloc(65536);
2608 nfo->len =
read(fp, (
void *)nfo->data, 65536);
2611 if (nfo->len <= 0) {
2612 eDest.Emsg(
"Config", errno,
"read from preloadstatic filename", val);
2616 if (nfo->len >= 65536) {
2617 eDest.Emsg(
"Config",
"Truncated preloadstatic filename. Max is 64 KB '", val,
"'");
2647int XrdHttpProtocol::xstaticheader(
XrdOucStream & Config) {
2648 auto val = Config.GetWord();
2649 std::vector<std::string> verbs;
2651 if (!val || !val[0]) {
2652 eDest.Emsg(
"Config",
"http.staticheader requires the header to be specified");
2656 std::string match_verb;
2657 std::string_view val_str(val);
2658 if (val_str.substr(0, 6) ==
"-verb=") {
2659 verbs.emplace_back(val_str.substr(6));
2660 }
else if (val_str ==
"-") {
2661 eDest.Emsg(
"Config",
"http.staticheader is ignoring unknown flag: ", val_str.data());
2666 val = Config.GetWord();
2668 if (verbs.empty()) {
2669 verbs.emplace_back();
2672 std::string header = val;
2674 val = Config.GetWord();
2675 std::string header_value;
2676 if (val && val[0]) {
2680 for (
const auto &verb : verbs) {
2683 if (!header_value.empty())
2685 }
else if (header_value.empty()) {
2686 iter->second.clear();
2688 iter->second.emplace_back(header, header_value);
2709int XrdHttpProtocol::xselfhttps2http(
XrdOucStream & Config) {
2714 val = Config.GetWord();
2715 if (!val || !val[0]) {
2716 eDest.Emsg(
"Config",
"selfhttps2http flag not specified");
2722 selfhttps2http = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2744int XrdHttpProtocol::xsecxtractor(
XrdOucStream& Config) {
2749 val = Config.GetWord();
2750 if (!val || !val[0]) {
2751 eDest.Emsg(
"Config",
"No security extractor plugin specified.");
2756 if (!strncmp(val,
"required", 8)) {
2757 isRequiredXtractor =
true;
2758 val = Config.GetWord();
2760 if (!val || !val[0]) {
2761 eDest.Emsg(
"Config",
"No security extractor plugin after [required] "
2768 strlcpy(libName, val,
sizeof(libName));
2769 libName[
sizeof(libName) - 1] =
'\0';
2770 char libParms[4096];
2772 if (!Config.GetRest(libParms, 4095)) {
2773 eDest.Emsg(
"Config",
"secxtractor config params longer than 4k");
2779 if (LoadSecXtractor(&
eDest, libName, libParms)) {
2790 val = Config.GetWord();
2791 if (!val || !val[0]) {
2792 eDest.Emsg(
"Config",
"No CORS plugin specified.");
2817 std::vector<extHInfo> &hiVec) {
2818 char *val, path[1024], namebuf[1024];
2821 bool noTlsOK =
false;
2825 val = Config.GetWord();
2826 if (!val || !val[0]) {
2827 eDest.Emsg(
"Config",
"No instance name specified for an http external handler plugin.");
2830 if (strlen(val) >= 16) {
2831 eDest.Emsg(
"Config",
"Instance name too long for an http external handler plugin.");
2834 strncpy(namebuf, val,
sizeof(namebuf));
2835 namebuf[
sizeof(namebuf)-1 ] =
'\0';
2838 val = Config.GetWord();
2840 if(val && !strcmp(
"+notls",val)) {
2842 val = Config.GetWord();
2847 if (!val || !val[0]) {
2848 eDest.Emsg(
"Config",
"No http external handler plugin specified.");
2851 if (strlen(val) >= (
int)
sizeof(path)) {
2852 eDest.Emsg(
"Config",
"Path too long for an http external handler plugin.");
2860 parm = Config.GetWord();
2864 for (
int i = 0; i < (int)hiVec.size(); i++)
2865 {
if (hiVec[i].extHName == namebuf) {
2866 eDest.Emsg(
"Config",
"Instance name already present for "
2867 "http external handler plugin",
2868 hiVec[i].extHPath.c_str());
2876 eDest.Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
2882 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm :
""), noTlsOK));
2903int XrdHttpProtocol::xheader2cgi(
XrdOucStream & Config) {
2925 val = Config.GetWord();
2926 if (!val || !val[0]) {
2927 eDest.Emsg(
"Config",
"HTTP X509 CAdir not specified");
2954int XrdHttpProtocol::xsslcipherfilter(
XrdOucStream & Config) {
2959 val = Config.GetWord();
2960 if (!val || !val[0]) {
2961 eDest.Emsg(
"Config",
"SSL cipherlist filter string not specified");
2990 val = Config.GetWord();
2991 if (!val || !val[0])
2992 {
eDest.Emsg(
"Config",
"tlsreuse argument not specified");
return 1;}
2996 if (!strcmp(val,
"off"))
3003 if (!strcmp(val,
"on"))
3010 eDest.Emsg(
"config",
"invalid tlsreuse parameter -", val);
3014int XrdHttpProtocol::xtlsclientauth(
XrdOucStream &Config) {
3015 auto val = Config.GetWord();
3016 if (!val || !val[0])
3017 {
eDest.Emsg(
"Config",
"tlsclientauth argument not specified");
return 1;}
3019 if (!strcmp(val,
"off"))
3023 if (!strcmp(val,
"on"))
3028 eDest.Emsg(
"config",
"invalid tlsclientauth parameter -", val);
3033 char *val = Config.GetWord();
3035 if(!strcmp(
"tpc",val)) {
3036 if(!(val = Config.GetWord())) {
3037 eDest.Emsg(
"Config",
"http.auth tpc value not specified.");
return 1;
3039 if(!strcmp(
"fcreds",val)) {
3042 eDest.Emsg(
"Config",
"http.auth tpc value is invalid");
return 1;
3046 eDest.Emsg(
"Config",
"http.auth value is invalid");
return 1;
3053 char *val = Config.GetWord();
3059 eDest.Emsg(
"Config",
"http.maxdelay requires an argument in seconds (default is 30). Example: http.maxdelay 30");
3083 static struct traceopts {
3095 int i, neg, trval = 0, numopts =
sizeof (tropts) /
sizeof (
struct traceopts);
3097 if (!(val = Config.GetWord())) {
3098 eDest.Emsg(
"config",
"trace option not specified");
3102 if (!strcmp(val,
"off")) trval = 0;
3104 if ((neg = (val[0] ==
'-' && val[1]))) val++;
3105 for (i = 0; i < numopts; i++) {
3106 if (!strcmp(val, tropts[i].opname)) {
3107 if (neg) trval &= ~tropts[i].opval;
3108 else trval |= tropts[i].opval;
3113 eDest.Emsg(
"config",
"invalid trace option", val);
3115 val = Config.GetWord();
3132 l = strlen(fname) + 1;
3157 length = fname.
length() + 1;
3158 CurrentReq.xrdreq.query.dlen = htonl(length);
3162 return Bridge->Run(
reinterpret_cast<char *
>(&
CurrentReq.xrdreq),
const_cast<char *
>(fname.
c_str()), length) ? 0 : -1;
3169int XrdHttpProtocol::LoadSecXtractor(
XrdSysError *myeDest,
const char *libName,
3170 const char *libParms) {
3174 if (secxtractor)
return 1;
3176 XrdOucPinLoader myLib(myeDest, &compiledVer,
"secxtractorlib", libName);
3182 if (ep && (secxtractor = ep(myeDest, NULL, libParms)))
return 0;
3190int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec,
const char *cFN,
XrdOucEnv &myEnv) {
3191 for (
int i = 0; i < (int) hiVec.size(); i++) {
3192 if(hiVec[i].extHNoTlsOK) {
3194 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3195 hiVec[i].extHParm.c_str(), &myEnv,
3196 hiVec[i].extHName.c_str()))
3203int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
3215 for (
int i = 0; i < (int)hiVec.size(); i++) {
3218 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3219 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3220 hiVec[i].extHParm.c_str(), &myEnv,
3221 hiVec[i].extHName.c_str()))
return 1;
3228int XrdHttpProtocol::LoadExtHandler(
XrdSysError *myeDest,
const char *libName,
3229 const char *configFN,
const char *libParms,
3230 XrdOucEnv *myEnv,
const char *instName) {
3234 if (ExtHandlerLoaded(instName)) {
3235 eDest.Emsg(
"Config",
"Instance name already present for an http external handler plugin.");
3239 eDest.Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
3243 XrdOucPinLoader myLib(myeDest, &compiledVer,
"exthandlerlib", libName);
3250 XrdHttpExtHandler *newhandler;
3251 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3254 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3255 exthandler[exthandlercnt].name[15] =
'\0';
3256 exthandler[exthandlercnt++].ptr = newhandler;
3266int XrdHttpProtocol::LoadCorsHandler(
XrdSysError *
eDest,
const char *libname) {
3268 XrdOucPinLoader corsLib(
eDest, &compiledVer,
"corslib",libname);
3271 if(ep && (
xrdcors = ep()))
return 0;
3278bool XrdHttpProtocol::ExtHandlerLoaded(
const char *handlername) {
3279 for (
int i = 0; i < exthandlercnt; i++) {
3280 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3291 for (
int i = 0; i < exthandlercnt; i++) {
3293 return exthandler[i].ptr;
static XrdSysError eDest(0,"crypto_")
#define XrdHttpCorsGetHandlerArgs
#define XrdHttpExtHandlerArgs
int BIO_get_init(BIO *bio)
int BIO_get_shutdown(BIO *bio)
int BIO_get_flags(BIO *bio)
static int BIO_XrdLink_create(BIO *bio)
const char * XrdHttpSecEntityTident
void BIO_set_init(BIO *bio, int init)
int BIO_XrdLink_write(BIO *bio, const char *data, size_t datal, size_t *written)
#define HTTPS_ALERT(x, y, z)
static long BIO_XrdLink_ctrl(BIO *bio, int cmd, long num, void *ptr)
void BIO_set_shutdown(BIO *bio, int shut)
XrdSysTrace XrdHttpTrace("http")
static int BIO_XrdLink_read(BIO *bio, char *data, size_t datal, size_t *read)
void BIO_set_data(BIO *bio, void *ptr)
static int BIO_XrdLink_destroy(BIO *bio)
#define XRHTTP_TK_GRACETIME
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
void * BIO_get_data(BIO *bio)
void BIO_set_flags(BIO *bio, int flags)
A pragmatic implementation of the HTTP/DAV protocol for the Xrd framework.
#define MAX_XRDHTTPEXTHANDLERS
#define XrdHttpSecXtractorArgs
int compareHash(const char *h1, const char *h2)
void calcHashes(char *hash, const char *fn, kXR_int16 request, XrdSecEntity *secent, time_t tim, const char *key)
Utility functions for XrdHTTP.
std::string decode_str(const std::string &str)
std::string obfuscateAuth(const std::string &input)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_REFINT(cOpts, refi)
const std::vector< std::string > & getNonIANAConfiguredCksums() const
void configure(const char *csList)
virtual int Configure(const char *configFN, XrdSysError *errP)=0
static char * secretkey
The key used to calculate the url hashes.
static BIO_METHOD * m_bio_method
C-style vptr table for our custom BIO objects.
static char * gridmap
Gridmap file location. The same used by XrdSecGsi.
static XrdScheduler * Sched
static kXR_int32 myRole
Our role.
static XrdNetPMark * pmarkHandle
Packet marking handler pointer (assigned from the environment during the Config() call)
static char * Port_str
Our port, as a string.
XrdXrootd::Bridge * Bridge
The Bridge that we use to exercise the xrootd internals.
static char * staticredir
static bool selfhttps2http
If client is HTTPS, self-redirect with HTTP+token.
static XrdHttpChecksumHandler cksumHandler
static int hailWait
Timeout for reading the handshake.
int doChksum(const XrdOucString &fname)
Perform a checksum request.
static XrdOucHash< StaticPreloadInfo > * staticpreload
static char * xrd_cslist
The list of checksums that were configured via the xrd.cksum parameter on the server config file.
static char * sslcipherfilter
static int m_bio_type
Type identifier for our custom BIO objects.
static std::map< std::string, std::string > hdr2cgimap
Rules that turn HTTP headers to cgi tokens in the URL, for internal comsumption.
static char * sslcert
OpenSSL stuff.
XrdLink * Link
The link we are bound to.
int doStat(char *fname)
Perform a Stat request.
XrdObject< XrdHttpProtocol > ProtLink
static int readWait
Timeout for reading data.
void Recycle(XrdLink *lp, int consec, const char *reason)
Recycle this instance.
static std::unordered_map< std::string, std::vector< std::pair< std::string, std::string > > > m_staticheader_map
The static headers to always return; map is from verb to a list of (header, val) pairs.
XrdHttpProtocol operator=(const XrdHttpProtocol &rhs)
static XrdHttpCors * xrdcors
static bool compatNameGeneration
static std::string xrdcorsLibPath
static bool isdesthttps
True if the redirections must be towards https targets.
static XrdObjectQ< XrdHttpProtocol > ProtStack
XrdProtocol * Match(XrdLink *lp)
Tells if the oustanding bytes on the socket match this protocol implementation.
static bool isRequiredGridmap
static char * listredir
Url to redirect to in the case a listing is requested.
int Stats(char *buff, int blen, int do_sync=0)
Get activity stats.
static int crlRefIntervalSec
CRL thread refresh interval.
static XrdHttpReadRangeHandler::Configuration ReadRangeConfig
configuration for the read range handler
static XrdSecService * CIA
static XrdBuffManager * BPool
static std::unordered_map< std::string, std::string > m_staticheaders
static bool tpcForwardCreds
If set to true, the HTTP TPC transfers will forward the credentials to redirected hosts.
int Process(XrdLink *lp)
Process data incoming from the socket.
XrdHttpProtocol(const XrdHttpProtocol &)=default
Ctor, dtors and copy ctor.
static bool listdeny
If true, any form of listing is denied.
static int parseHeader2CGI(XrdOucStream &Config, XrdSysError &err, std::map< std::string, std::string > &header2cgi)
Use this function to parse header2cgi configurations.
XrdSecEntity SecEntity
Authentication area.
static bool embeddedstatic
If true, use the embedded css and icons.
static int sslverifydepth
Depth of verification of a certificate chain.
static int Configure(char *parms, XrdProtocol_Config *pi)
Read and apply the configuration.
static int Configure(XrdSysError &Eroute, const char *const parms, Configuration &cfg)
XrdOucString resource
The resource specified by the request, stripped of opaque data.
int setEtext(const char *text)
int Peek(char *buff, int blen, int timeout=-1)
int Recv(char *buff, int blen)
const XrdNetAddr * NetAddr() const
XrdNetAddrInfo * AddrInfo()
int Send(const char *buff, int blen)
static const int noPort
Do not add port number.
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtAddr
Address using suitable ipv4 or ipv6 format.
void SetDialect(const char *dP)
static bool Import(const char *var, char *&val)
char * Get(const char *varname)
void * GetPtr(const char *varname)
void Put(const char *varname, const char *value)
void insert(const int i, int start=-1)
void assign(const char *s, int j, int k=-1)
const char * c_str() const
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
XrdProtocol(const char *jname)
XrdNetAddrInfo * addrInfo
Entity's connection details.
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
int SessionCache(int opts=scNone, const char *id=0, int idlen=0)
static const int DEFAULT_CRL_REF_INT_SEC
Default CRL refresh interval in seconds.
static const uint64_t servr
This is a server context.
static const uint64_t rfCRL
Turn on the CRL refresh thread.
static const uint64_t logVF
Log verify failures.
static const uint64_t artON
Auto retry Handshake.
static const int scOff
Turn off cache.
bool SetContextCiphers(const char *ciphers)
static const int scSrvr
Turn on cache server mode (default)
void SetTlsClientAuth(bool setting)
static Bridge * Login(Result *rsltP, XrdLink *linkP, XrdSecEntity *seceP, const char *nameP, const char *protP)
std::string cafile
-> ca cert file.
std::string cadir
-> ca cert directory.
int crlRT
crl refresh interval time in seconds
std::string pkey
-> private key path.
std::string cert
-> certificate path.