24 #include "XrdVersion.hh"
48 #include <openssl/err.h>
49 #include <openssl/ssl.h>
51 #include <arpa/inet.h>
58 #define XRHTTP_TK_GRACETIME 600
99 BIO *XrdHttpProtocol::sslbio_err = 0;
101 bool XrdHttpProtocol::isRequiredXtractor =
false;
103 int XrdHttpProtocol::exthandlercnt = 0;
106 bool XrdHttpProtocol::usingEC = false;
127 const char *TraceID =
"Protocol";
155 "xrootd protocol anchor");
161 #if OPENSSL_VERSION_NUMBER < 0x10100000L
168 #if OPENSSL_VERSION_NUMBER < 0x1000105fL
183 bio->shutdown = shut;
186 return bio->shutdown;
198 :
XrdProtocol(
"HTTP protocol handler"), ProtLink(this),
199 SecEntity(
""), CurrentReq(this, ReadRangeConfig) {
224 char mybuf[16], mybuf2[1024];
227 bool myishttps =
false;
231 if ((dlen = lp->
Peek(mybuf, (
int) sizeof (mybuf),
hailWait)) < (
int)
sizeof (mybuf)) {
232 if (dlen <= 0) lp->
setEtext(
"handshake not received");
235 mybuf[dlen - 1] =
'\0';
243 for (
int i = 0; i < dlen; i++) {
245 sprintf(mybuf3,
"%.02d ", mybuf[i]);
246 strcat(mybuf2, mybuf3);
253 for (
int i = 0; i < dlen - 1; i++)
254 if (!isprint(mybuf[i]) && (mybuf[i] !=
'\r') && (mybuf[i] !=
'\n')) {
256 TRACEI(
DEBUG,
"This does not look like http at pos " << i);
261 if ((!ismine) && (dlen >= 4)) {
262 char check[4] = {00, 00, 00, 00};
263 if (memcmp(mybuf, check, 4)) {
270 TRACEI(ALL,
"This may look like https, but https is not configured");
277 TRACEI(
DEBUG,
"This does not look like https. Protocol not matched.");
285 TRACEI(REQ,
"Protocol matched. https: " << myishttps);
288 hp->ishttps = myishttps;
303 hp->myBuffStart = hp->myBuffEnd = hp->myBuff->
buff;
311 char *XrdHttpProtocol::GetClientIPStr() {
314 if (!
Link)
return strdup(
"unknown");
316 if (!ai)
return strdup(
"unknown");
324 #if OPENSSL_VERSION_NUMBER < 0x1000105fL
335 int ret = lp->
Send(data, datal);
336 BIO_clear_retry_flags(bio);
339 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
340 BIO_set_retry_write(bio);
356 int ret = lp->
Send(data, datal);
357 BIO_clear_retry_flags(bio);
359 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
360 BIO_set_retry_write(bio);
367 #if OPENSSL_VERSION_NUMBER < 0x1000105fL
378 int ret = lp->
Recv(data, datal);
379 BIO_clear_retry_flags(bio);
382 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
383 BIO_set_retry_read(bio);
398 int ret = lp->
Recv(data, datal);
399 BIO_clear_retry_flags(bio);
401 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
402 BIO_set_retry_read(bio);
418 #if OPENSSL_VERSION_NUMBER < 0x10100000L
430 if (bio == NULL)
return 0;
446 case BIO_CTRL_GET_CLOSE:
449 case BIO_CTRL_SET_CLOSE:
467 setsockopt(link->FDnum(), SOL_SOCKET, SO_RCVTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
468 setsockopt(link->FDnum(), SOL_SOCKET, SO_SNDTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
481 BIO *XrdHttpProtocol::CreateBIO(
XrdLink *lp)
500 #define TRACELINK Link
508 if (!myBuff || !myBuff->
buff || !myBuff->
bsize) {
509 TRACE(ALL,
" Process. No buffer available. Internal error.");
515 char *nfo = GetClientIPStr();
517 TRACEI(REQ,
" Setting host: " << nfo);
526 if (ishttps && !ssldone) {
529 sbio = CreateBIO(
Link);
530 BIO_set_nbio(sbio, 1);
533 postheaderauth =
false;
534 postheaderwait =
false;
535 postheaderauthdone =
false;
540 ERR_print_errors(sslbio_err);
549 SSL_set_bio(ssl, sbio, sbio);
556 setsockopt(
Link->
FDnum(), SOL_SOCKET, SO_RCVTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
557 setsockopt(
Link->
FDnum(), SOL_SOCKET, SO_SNDTIMEO, (
struct timeval *)&tv,
sizeof(
struct timeval));
560 int res = SSL_accept(ssl);
562 if ((res == -1) && (SSL_get_error(ssl, res) == SSL_ERROR_WANT_READ)) {
563 TRACEI(
DEBUG,
" SSL_accept wants to read more bytes... err:" << SSL_get_error(ssl, res));
568 ERR_print_errors(sslbio_err);
577 BIO_set_nbio(sbio, 0);
582 if (
tlsClientAuth == XrdTlsContext::ClientAuthSetting::kOn && HandleAuthentication(
Link)) {
603 if ((rc = getDataOneShot(BuffAvailable())) < 0) {
609 if (BuffUsed() < ResumeBytes)
return 1;
614 }
else if (!DoneSetInfo && !postheaderwait && !postheaderauth && !
CurrentReq.
userAgent().empty()) {
617 if (mon_info.size() >= 1024) {
618 TRACEI(ALL,
"User agent string too long");
620 TRACEI(ALL,
"Internal logic error: Bridge is null after login");
629 SendSimpleResp(500,
nullptr,
nullptr,
"Could not set user agent.", 0,
false);
634 }
else if (!postheaderwait) {
644 while ((rc = BuffgetLine(tmpline)) > 0) {
645 std::string traceLine = tmpline.
c_str();
649 TRACE(
DEBUG,
" rc:" << rc <<
" got hdr line: " << traceLine);
650 if ((rc == 2) && (tmpline.
length() > 1) && (tmpline[rc - 1] ==
'\n')) {
652 TRACE(
DEBUG,
" rc:" << rc <<
" detected header end.");
658 TRACE(
DEBUG,
" Parsing first line: " << traceLine.c_str());
661 TRACE(
DEBUG,
" Parsing of first line failed with " << result);
665 #if OPENSSL_VERSION_NUMBER >= 0x10100010L
668 if (!postheaderauthdone &&
tlsClientAuth == XrdTlsContext::ClientAuthSetting::kDefer)
671 {postheaderwait =
true;
682 TRACE(
DEBUG,
" Parsing of header line failed with " << result)
683 SendSimpleResp(400,NULL,NULL,
"Malformed header line. Hint: ensure the line finishes with \"\\r\\n\"", 0,
false);
694 TRACEI(REQ,
" rc:" << rc <<
"Header not yet complete.");
699 if ((rc <= 0) && (BuffUsed() >= 16384)) {
700 TRACEI(ALL,
"Corrupted header detected, or line too long. Disconnecting client.");
714 #if OPENSSL_VERSION_NUMBER >= 0x10100010L
715 if (postheaderwait) {
716 postheaderwait =
false;
717 if (SSL_verify_client_post_handshake(ssl) != 1) {
720 TRACEI(ALL,
"Unable to request client X.509 authentication");
721 ERR_print_errors(sslbio_err);
725 auto res = SSL_write_ex(ssl,
nullptr, 0, &write_size);
727 TRACEI(
DEBUG,
" SSL post-handshake auth failed; err:" << SSL_get_error(ssl, res));
728 ERR_print_errors(sslbio_err);
729 SendSimpleResp(500,
nullptr,
nullptr,
"Failed post-handshake authentication", 0,
false);
732 TRACEI(
DEBUG,
" SSL post-handshake auth finished successfully");
733 postheaderauth =
true;
738 if (postheaderauth) {
739 postheaderauth =
false;
740 postheaderauthdone =
true;
742 TRACEI(REQ,
"Reading out response to post-handshake authentication");
743 BIO_set_nbio(sbio, 1);
744 auto res = SSL_peek_ex(ssl,
nullptr, 0, &readbytes);
745 if ((res <= 0) && SSL_get_error(ssl, res) != SSL_ERROR_WANT_READ) {
746 SendSimpleResp(500,
nullptr,
nullptr,
"Failed to process authentication frames", 0,
false);
749 BIO_set_nbio(sbio, 0);
750 if (HandleAuthentication(
Link)) {
751 SendSimpleResp(500,
nullptr,
nullptr,
"Failed to extract authentication information from handshake", 0,
false);
763 time_t timenow = time(0);
781 TRACEI(REQ,
" rc:" << rc <<
" self-redirecting to http with security token.");
788 struct sockaddr_storage sa;
789 socklen_t sl =
sizeof(sa);
796 switch (sa.ss_family) {
798 if (inet_ntop(AF_INET, &(((sockaddr_in*)&sa)->sin_addr), buf, INET_ADDRSTRLEN)) {
805 if (inet_ntop(AF_INET6, &(((sockaddr_in6*)&sa)->sin6_addr), buf, INET6_ADDRSTRLEN)) {
807 Addr_str = (
char *)malloc(strlen(buf)+3);
815 TRACEI(REQ,
" Can't recognize the address family of the local host.");
823 TRACEI(REQ,
" rc:"<<rc<<
" self-redirecting to http with security token: '"
824 << dest.
c_str() <<
"'");
828 SendSimpleResp(302, NULL, (
char *) dest.
c_str(), 0, 0,
true);
833 TRACEI(REQ,
" rc:" << rc <<
" Can't perform self-redirection.");
837 TRACEI(ALL,
" Could not calculate self-redirection hash");
843 if (!ishttps && !ssldone) {
853 if (t) tim = atoi(t);
855 TRACEI(REQ,
" xrdhttptime not specified. Authentication failed.");
859 TRACEI(REQ,
" Token expired. Authentication failed.");
944 TRACEI(REQ,
" Invalid tk '" << tk <<
"' != '" << hash <<
"'(calculated). Authentication failed.");
951 TRACEI(ALL,
" Rejecting plain http with no valid token as we have a secretkey.");
959 TRACEI(ALL,
" Rejecting plain http with no valid token as we have a secretkey.");
979 TRACEI(REQ,
" Authorization failed.");
995 TRACEI(REQ,
"Process is exiting rc:" << rc);
1003 #define TRACELINK Link
1057 #define TS_Xeq(x,m) (!strcmp(x,var)) GoNo = m(Config)
1059 #define TS_Xeq3(x,m) (!strcmp(x,var)) GoNo = m(Config, extHIVec)
1061 #define HTTPS_ALERT(x,y,z) httpsspec = true;\
1062 if (xrdctx && httpsmode == hsmAuto && (z || xrdctx->x509Verify())) \
1063 eDest.Say("Config http." x " overrides the xrd." y " directive.")
1065 int XrdHttpProtocol::Config(
const char *ConfigFN,
XrdOucEnv *myEnv) {
1068 std::vector<extHInfo> extHIVec;
1070 int cfgFD, GoNo, NoGo = 0, ismine;
1080 if(nonIanaChecksums.size()) {
1081 std::stringstream warningMsgSS;
1082 warningMsgSS <<
"Config warning: the following checksum algorithms are not IANA compliant: [";
1083 std::string unknownCksumString;
1084 for(
auto unknownCksum: nonIanaChecksums) {
1085 unknownCksumString += unknownCksum +
",";
1087 unknownCksumString.erase(unknownCksumString.size() - 1);
1088 warningMsgSS << unknownCksumString <<
"]" <<
". They therefore cannot be queried by a user via HTTP." ;
1089 eDest.
Say(warningMsgSS.str().c_str());
1095 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1097 m_bio_method =
static_cast<BIO_METHOD*
>(OPENSSL_malloc(
sizeof(BIO_METHOD)));
1132 if ((cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
1133 return eDest.
Emsg(
"Config", errno,
"open config file", ConfigFN);
1135 static const char *cvec[] = {
"*** http protocol config:", 0 };
1140 while ((var =
Config.GetMyFirstWord())) {
1141 if ((ismine = !strncmp(
"http.", var, 5)) && var[5]) var += 5;
1144 if TS_Xeq(
"trace", xtrace);
1145 else if TS_Xeq(
"cert", xsslcert);
1146 else if TS_Xeq(
"key", xsslkey);
1147 else if TS_Xeq(
"cadir", xsslcadir);
1148 else if TS_Xeq(
"cipherfilter", xsslcipherfilter);
1149 else if TS_Xeq(
"gridmap", xgmap);
1150 else if TS_Xeq(
"cafile", xsslcafile);
1151 else if TS_Xeq(
"secretkey", xsecretkey);
1152 else if TS_Xeq(
"desthttps", xdesthttps);
1153 else if TS_Xeq(
"secxtractor", xsecxtractor);
1154 else if TS_Xeq3(
"exthandler", xexthandler);
1155 else if TS_Xeq(
"selfhttps2http", xselfhttps2http);
1156 else if TS_Xeq(
"embeddedstatic", xembeddedstatic);
1157 else if TS_Xeq(
"listingredir", xlistredir);
1158 else if TS_Xeq(
"staticredir", xstaticredir);
1159 else if TS_Xeq(
"staticpreload", xstaticpreload);
1160 else if TS_Xeq(
"staticheader", xstaticheader);
1161 else if TS_Xeq(
"listingdeny", xlistdeny);
1162 else if TS_Xeq(
"header2cgi", xheader2cgi);
1163 else if TS_Xeq(
"httpsmode", xhttpsmode);
1164 else if TS_Xeq(
"tlsreuse", xtlsreuse);
1165 else if TS_Xeq(
"auth", xauth);
1166 else if TS_Xeq(
"tlsclientauth", xtlsclientauth);
1167 else if TS_Xeq(
"tlsrequiredprefix", xtlsrequiredprefix);
1169 eDest.
Say(
"Config warning: ignoring unknown directive '", var,
"'.");
1184 {
eDest.
Say(
"Config failure: one or more directives are flawed!");
1190 hdr2cgimap[
"Cache-Control"] =
"cache-control";
1193 if (getenv(
"XRDCL_EC"))
usingEC =
true;
1198 std::string default_static_headers;
1200 for (
const auto &header_entry : default_verb->second) {
1201 default_static_headers += header_entry.first +
": " + header_entry.second +
"\r\n";
1205 auto headers = default_static_headers;
1206 for (
const auto &header_entry : item.second) {
1207 headers += header_entry.first +
": " + header_entry.second +
"\r\n";
1220 :
"was not configured.");
1221 const char *what = Configed();
1223 eDest.
Say(
"Config warning: HTTPS functionality ", why);
1226 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1228 {
eDest.
Say(
"Config failure: ", what,
" HTTPS but it ", why);
1238 {
eDest.
Say(
"Config warning: specifying http.key without http.cert "
1239 "is meaningless; ignoring key!");
1247 {
eDest.
Say(
"Config failure: 'httpsmode manual' requires atleast a "
1248 "a cert specification!");
1259 const char *what1 = 0, *what2 = 0, *what3 = 0;
1264 what1 =
"xrd.tls to supply 'cert' and 'key'.";
1268 what2 =
"xrd.tlsca to supply 'cadir'.";
1272 what2 = (what2 ?
"xrd.tlsca to supply 'cadir' and 'cafile'."
1273 :
"xrd.tlsca to supply 'cafile'.");
1277 what3 =
"xrd.tlsca to supply 'refresh' interval.";
1287 {
const char *what = Configed();
1288 const char *why = (
httpsspec ?
"a cadir or cafile was not specified!"
1289 :
"'xrd.tlsca noverify' was specified!");
1291 {
eDest.
Say(
"Config failure: ", what,
" cert verification but ", why);
1299 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1304 const char *how =
"completed.";
1305 eDest.
Say(
"++++++ HTTPS initialization started.");
1306 if (!
InitTLS()) {NoGo = 1; how =
"failed.";}
1307 eDest.
Say(
"------ HTTPS initialization ", how);
1308 if (NoGo)
return NoGo;
1312 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv))
return 1;
1316 return (InitSecurity() ? NoGo : 1);
1323 const char *XrdHttpProtocol::Configed()
1325 if (secxtractor &&
gridmap)
return "gridmap and secxtractor require";
1326 if (secxtractor)
return "secxtractor requires";
1327 if (
gridmap)
return "gridmap requires";
1343 if (myBuffEnd >= myBuffStart) {
1345 for (
char *p = myBuffStart; p < myBuffEnd; p++) {
1350 dest.
assign(myBuffStart, 0, l-1);
1369 for (
char *p = myBuffStart; p < myBuff->
buff + myBuff->
bsize; p++) {
1371 if ((*p ==
'\n') || (*p ==
'\0')) {
1374 dest.
assign(myBuffStart, 0, l-1);
1390 for (
char *p = myBuff->
buff; p < myBuffEnd; p++) {
1392 if ((*p ==
'\n') || (*p ==
'\0')) {
1396 int l1 = myBuff->
buff + myBuff->
bsize - myBuffStart;
1398 dest.
assign(myBuffStart, 0, l1-1);
1402 dest.
insert(myBuffStart, l1, l-1);
1426 int XrdHttpProtocol::getDataOneShot(
int blen,
bool wait) {
1441 maxread = std::min(blen, BuffAvailable());
1442 TRACE(
DEBUG,
"getDataOneShot BuffAvailable: " << BuffAvailable() <<
" maxread: " << maxread);
1448 int sslavail = maxread;
1451 int l = SSL_pending(ssl);
1453 sslavail = std::min(maxread, SSL_pending(ssl));
1458 ERR_print_errors(sslbio_err);
1462 TRACE(
DEBUG,
"getDataOneShot sslavail: " << sslavail);
1463 if (sslavail <= 0)
return 0;
1465 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1467 myBuffEnd = myBuff->
buff;
1470 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1473 ERR_print_errors(sslbio_err);
1480 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1482 myBuffEnd = myBuff->
buff;
1488 rlen =
Link->
Recv(myBuffEnd, maxread);
1504 TRACE(REQ,
"read " << rlen <<
" of " << blen <<
" bytes");
1511 int XrdHttpProtocol::BuffAvailable() {
1514 if (myBuffEnd >= myBuffStart)
1515 r = myBuff->
buff + myBuff->
bsize - myBuffEnd;
1517 r = myBuffStart - myBuffEnd;
1519 if ((r < 0) || (r > myBuff->
bsize)) {
1520 TRACE(REQ,
"internal error, myBuffAvailable: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1533 int XrdHttpProtocol::BuffUsed() {
1536 if (myBuffEnd >= myBuffStart)
1537 r = myBuffEnd - myBuffStart;
1540 r = myBuff->
bsize - (myBuffStart - myBuffEnd);
1542 if ((r < 0) || (r > myBuff->
bsize)) {
1543 TRACE(REQ,
"internal error, myBuffUsed: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1556 int XrdHttpProtocol::BuffFree() {
1557 return (myBuff->
bsize - BuffUsed());
1564 void XrdHttpProtocol::BuffConsume(
int blen) {
1566 if (blen > myBuff->
bsize) {
1567 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") smaller than buffsize");
1571 if (blen > BuffUsed()) {
1572 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") larger than BuffUsed:" << BuffUsed());
1576 myBuffStart = myBuffStart + blen;
1578 if (myBuffStart >= myBuff->
buff + myBuff->
bsize)
1579 myBuffStart -= myBuff->
bsize;
1581 if (myBuffEnd >= myBuff->
buff + myBuff->
bsize)
1582 myBuffEnd -= myBuff->
bsize;
1584 if (BuffUsed() == 0)
1585 myBuffStart = myBuffEnd = myBuff->
buff;
1600 int XrdHttpProtocol::BuffgetData(
int blen,
char **data,
bool wait) {
1603 TRACE(
DEBUG,
"BuffgetData: requested " << blen <<
" bytes");
1608 if (blen > BuffUsed()) {
1609 TRACE(REQ,
"BuffgetData: need to read " << blen - BuffUsed() <<
" bytes");
1610 if ( getDataOneShot(blen - BuffUsed(),
true) )
1616 if ( !BuffUsed() ) {
1617 if ( getDataOneShot(blen,
false) )
1625 if (myBuffStart <= myBuffEnd) {
1626 rlen = std::min( (
long) blen, (
long)(myBuffEnd - myBuffStart) );
1629 rlen = std::min( (
long) blen, (
long)(myBuff->
buff + myBuff->
bsize - myBuffStart) );
1631 *data = myBuffStart;
1642 int XrdHttpProtocol::SendData(
const char *body,
int bodylen) {
1646 if (body && bodylen) {
1647 TRACE(REQ,
"Sending " << bodylen <<
" bytes");
1649 r = SSL_write(ssl, body, bodylen);
1651 ERR_print_errors(sslbio_err);
1657 if (r <= 0)
return -1;
1668 int XrdHttpProtocol::StartSimpleResp(
int code,
const char *desc,
const char *header_to_add,
long long bodylen,
bool keepalive) {
1669 std::stringstream ss;
1670 const std::string crlf =
"\r\n";
1672 ss <<
"HTTP/1.1 " << code <<
" ";
1676 if (code == 200) ss <<
"OK";
1677 else if (code == 100) ss <<
"Continue";
1678 else if (code == 206) ss <<
"Partial Content";
1679 else if (code == 302) ss <<
"Redirect";
1680 else if (code == 307) ss <<
"Temporary Redirect";
1681 else if (code == 400) ss <<
"Bad Request";
1682 else if (code == 403) ss <<
"Forbidden";
1683 else if (code == 404) ss <<
"Not Found";
1684 else if (code == 405) ss <<
"Method Not Allowed";
1685 else if (code == 416) ss <<
"Range Not Satisfiable";
1686 else if (code == 500) ss <<
"Internal Server Error";
1687 else if (code == 504) ss <<
"Gateway Timeout";
1688 else ss <<
"Unknown";
1691 if (keepalive && (code != 100))
1692 ss <<
"Connection: Keep-Alive" << crlf;
1694 ss <<
"Connection: Close" << crlf;
1696 ss <<
"Server: XrootD/" << XrdVSTRING << crlf;
1703 if ((bodylen >= 0) && (code != 100))
1704 ss <<
"Content-Length: " << bodylen << crlf;
1706 if (header_to_add && (header_to_add[0] !=
'\0'))
1707 ss << header_to_add << crlf;
1711 const std::string &outhdr = ss.str();
1712 TRACEI(RSP,
"Sending resp: " << code <<
" header len:" << outhdr.size());
1713 if (SendData(outhdr.c_str(), outhdr.size()))
1723 int XrdHttpProtocol::StartChunkedResp(
int code,
const char *desc,
const char *header_to_add,
long long bodylen,
bool keepalive) {
1724 const std::string crlf =
"\r\n";
1725 std::stringstream ss;
1727 if (header_to_add && (header_to_add[0] !=
'\0')) {
1728 ss << header_to_add << crlf;
1731 ss <<
"Transfer-Encoding: chunked";
1732 TRACEI(RSP,
"Starting chunked response");
1733 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1740 int XrdHttpProtocol::ChunkResp(
const char *body,
long long bodylen) {
1741 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1742 if (ChunkRespHeader(content_length))
1745 if (body && SendData(body, content_length))
1748 return ChunkRespFooter();
1755 int XrdHttpProtocol::ChunkRespHeader(
long long bodylen) {
1756 const std::string crlf =
"\r\n";
1757 std::stringstream ss;
1761 const std::string &chunkhdr = ss.str();
1762 TRACEI(RSP,
"Sending encoded chunk of size " << bodylen);
1763 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1770 int XrdHttpProtocol::ChunkRespFooter() {
1771 const std::string crlf =
"\r\n";
1772 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1783 int XrdHttpProtocol::SendSimpleResp(
int code,
const char *desc,
const char *header_to_add,
const char *body,
long long bodylen,
bool keepalive) {
1785 long long content_length = bodylen;
1787 content_length = body ? strlen(body) : 0;
1790 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1797 return SendData(body, content_length);
1834 sprintf(buf,
"%d",
Port);
1840 rdf = (parms && *parms ? parms : pi->
ConfigFN);
1846 if ((rdf = getenv(
"XRDROLE"))) {
1849 if (!strcasecmp(rdf,
"manager") || !strcasecmp(rdf,
"supervisor")) {
1851 eDest.
Emsg(
"Config",
"Configured as HTTP(s) redirector.");
1854 eDest.
Emsg(
"Config",
"Configured as HTTP(s) data server.");
1858 eDest.
Emsg(
"Config",
"No XRDROLE specified.");
1877 char *val, keybuf[1024], parmbuf[1024];
1882 if (!val || !val[0]) {
1883 err.
Emsg(
"Config",
"No headerkey specified.");
1888 while ( *val && !isalnum(*val) ) val++;
1889 strcpy(keybuf, val);
1893 pp = keybuf + strlen(keybuf) - 1;
1894 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1902 if(!parm || !parm[0]) {
1903 err.
Emsg(
"Config",
"No header2cgi value specified. key: '", keybuf,
"'");
1908 while ( *parm && !isalnum(*parm) ) parm++;
1909 strcpy(parmbuf, parm);
1912 pp = parmbuf + strlen(parmbuf) - 1;
1913 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1920 header2cgi[keybuf] = parmbuf;
1922 err.
Emsg(
"Config",
"Can't insert new header2cgi rule. key: '", keybuf,
"'");
1935 bool XrdHttpProtocol::InitTLS() {
1960 static const char *sess_ctx_id =
"XrdHTTPSessionCtx";
1961 unsigned int n =(
unsigned int)(strlen(sess_ctx_id)+1);
1967 {
eDest.
Say(
"Config failure: ",
"Unable to set allowable https ciphers!");
1980 void XrdHttpProtocol::Cleanup() {
1982 TRACE(ALL,
" Cleanup");
1984 if (
BPool && myBuff) {
1985 BuffConsume(BuffUsed());
1999 int ret = SSL_shutdown(ssl);
2003 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2004 ERR_remove_thread_state(
nullptr);
2008 TRACE(ALL,
" SSL_shutdown failed");
2009 ERR_print_errors(sslbio_err);
2043 void XrdHttpProtocol::Reset() {
2045 TRACE(ALL,
" Reset");
2054 myBuffStart = myBuffEnd = 0;
2057 DoneSetInfo =
false;
2058 postheaderauth =
false;
2059 postheaderwait =
false;
2109 if (!val || !val[0]) {
2110 eDest.
Emsg(
"Config",
"httpsmode parameter not specified");
2119 else {
eDest.
Emsg(
"Config",
"invalid httpsmode parameter - ", val);
2144 if (!val || !val[0]) {
2145 eDest.
Emsg(
"Config",
"sslverifydepth value not specified");
2176 if (!val || !val[0]) {
2177 eDest.
Emsg(
"Config",
"HTTP X509 certificate not specified");
2211 if (!val || !val[0]) {
2212 eDest.
Emsg(
"Config",
"HTTP X509 key not specified");
2248 if (!val || !val[0]) {
2249 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file location not specified");
2255 if (!strncmp(val,
"required", 8)) {
2259 if (!val || !val[0]) {
2260 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after [required] "
2268 if (!strcmp(val,
"compatNameGeneration")) {
2271 if (!val || !val[0]) {
2272 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after "
2273 "[compatNameGeneration] parameter");
2305 if (!val || !val[0]) {
2306 eDest.
Emsg(
"Config",
"HTTP X509 CAfile not specified");
2334 bool inFile =
false;
2339 if (!val || !val[0]) {
2340 eDest.
Emsg(
"Config",
"Shared secret key not specified");
2348 if (val[0] ==
'/') {
2351 int fd =
open(val, O_RDONLY);
2354 eDest.
Emsg(
"Config", errno,
"open shared secret key file", val);
2358 if (
fstat(fd, &st) != 0 ) {
2359 eDest.
Emsg(
"Config", errno,
"fstat shared secret key file", val);
2364 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2366 "For your own security, the shared secret key file cannot be world readable or group writable '", val,
"'");
2371 FILE *fp = fdopen(fd,
"r");
2373 if ( fp ==
nullptr ) {
2374 eDest.
Emsg(
"Config", errno,
"fdopen shared secret key file", val);
2380 while( fgets(line, 1024, fp) ) {
2384 pp = line + strlen(line) - 1;
2385 while ( (pp >= line) && (!isalnum(*pp)) ) {
2392 while ( *pp && !isalnum(*pp) ) pp++;
2394 if ( strlen(pp) >= 32 ) {
2395 eDest.
Say(
"Config",
"Secret key loaded.");
2407 eDest.
Emsg(
"Config",
"Cannot find useful secretkey in file '", val,
"'");
2412 if ( strlen(val) < 32 ) {
2413 eDest.
Emsg(
"Config",
"Secret key is too short");
2420 if (!inFile)
Config.noEcho();
2444 if (!val || !val[0]) {
2445 eDest.
Emsg(
"Config",
"listingdeny flag not specified");
2451 listdeny = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2476 if (!val || !val[0]) {
2477 eDest.
Emsg(
"Config",
"listingredir flag not specified");
2509 if (!val || !val[0]) {
2510 eDest.
Emsg(
"Config",
"desthttps flag not specified");
2516 isdesthttps = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2541 if (!val || !val[0]) {
2542 eDest.
Emsg(
"Config",
"embeddedstatic flag not specified");
2548 embeddedstatic = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2573 if (!val || !val[0]) {
2574 eDest.
Emsg(
"Config",
"staticredir url not specified");
2603 char *val, *k, key[1024];
2609 eDest.
Emsg(
"Config",
"preloadstatic urlpath not specified");
2618 if (!val || !val[0]) {
2619 eDest.
Emsg(
"Config",
"preloadstatic filename not specified");
2624 int fp =
open(val, O_RDONLY);
2626 eDest.
Emsg(
"Config", errno,
"open preloadstatic filename", val);
2630 StaticPreloadInfo *nfo =
new StaticPreloadInfo;
2632 nfo->data = (
char *)malloc(65536);
2633 nfo->len =
read(fp, (
void *)nfo->data, 65536);
2636 if (nfo->len <= 0) {
2637 eDest.
Emsg(
"Config", errno,
"read from preloadstatic filename", val);
2641 if (nfo->len >= 65536) {
2642 eDest.
Emsg(
"Config",
"Truncated preloadstatic filename. Max is 64 KB '", val,
"'");
2673 auto val =
Config.GetWord();
2674 std::vector<std::string> verbs;
2676 if (!val || !val[0]) {
2677 eDest.
Emsg(
"Config",
"http.staticheader requires the header to be set to be specified");
2681 std::string match_verb;
2682 std::string_view val_str(val);
2683 if (val_str.substr(0, 6) ==
"-verb=") {
2684 verbs.emplace_back(val_str.substr(6));
2685 }
else if (val_str ==
"-") {
2686 eDest.
Emsg(
"Config",
"http.staticheader is ignoring unknown flag: ", val_str.data());
2693 if (verbs.empty()) {
2694 verbs.emplace_back();
2697 std::string header = val;
2700 std::string header_value;
2701 if (val && val[0]) {
2705 for (
const auto &verb : verbs) {
2709 }
else if (header_value.empty()) {
2710 iter->second.clear();
2712 iter->second.emplace_back(header, header_value);
2739 if (!val || !val[0]) {
2740 eDest.
Emsg(
"Config",
"selfhttps2http flag not specified");
2746 selfhttps2http = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2774 if (!val || !val[0]) {
2775 eDest.
Emsg(
"Config",
"No security extractor plugin specified.");
2780 if (!strncmp(val,
"required", 8)) {
2781 isRequiredXtractor =
true;
2784 if (!val || !val[0]) {
2785 eDest.
Emsg(
"Config",
"No security extractor plugin after [required] "
2792 strlcpy(libName, val,
sizeof(libName));
2793 libName[
sizeof(libName) - 1] =
'\0';
2794 char libParms[4096];
2796 if (!
Config.GetRest(libParms, 4095)) {
2797 eDest.
Emsg(
"Config",
"secxtractor config params longer than 4k");
2803 if (LoadSecXtractor(&
eDest, libName, libParms)) {
2829 std::vector<extHInfo> &hiVec) {
2830 char *val, path[1024], namebuf[1024];
2833 bool noTlsOK =
false;
2838 if (!val || !val[0]) {
2839 eDest.
Emsg(
"Config",
"No instance name specified for an http external handler plugin.");
2842 if (strlen(val) >= 16) {
2843 eDest.
Emsg(
"Config",
"Instance name too long for an http external handler plugin.");
2846 strncpy(namebuf, val,
sizeof(namebuf));
2847 namebuf[
sizeof(namebuf)-1 ] =
'\0';
2852 if(val && !strcmp(
"+notls",val)) {
2859 if (!val || !val[0]) {
2860 eDest.
Emsg(
"Config",
"No http external handler plugin specified.");
2863 if (strlen(val) >= (int)
sizeof(path)) {
2864 eDest.
Emsg(
"Config",
"Path too long for an http external handler plugin.");
2876 for (
int i = 0; i < (int)hiVec.size(); i++)
2877 {
if (hiVec[i].extHName == namebuf) {
2878 eDest.
Emsg(
"Config",
"Instance name already present for "
2879 "http external handler plugin",
2880 hiVec[i].extHPath.c_str());
2888 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
2894 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm :
""), noTlsOK));
2938 if (!val || !val[0]) {
2939 eDest.
Emsg(
"Config",
"HTTP X509 CAdir not specified");
2972 if (!val || !val[0]) {
2973 eDest.
Emsg(
"Config",
"SSL cipherlist filter string not specified");
3003 if (!val || !val[0])
3004 {
eDest.
Emsg(
"Config",
"tlsreuse argument not specified");
return 1;}
3008 if (!strcmp(val,
"off"))
3015 if (!strcmp(val,
"on"))
3022 eDest.
Emsg(
"config",
"invalid tlsreuse parameter -", val);
3027 auto val =
Config.GetWord();
3028 if (!val || !val[0])
3029 {
eDest.
Emsg(
"Config",
"tlsclientauth argument not specified");
return 1;}
3031 if (!strcmp(val,
"off"))
3035 if (!strcmp(val,
"on"))
3039 if (!strcmp(val,
"defer"))
3041 #if OPENSSL_VERSION_NUMBER >= 0x10100010L
3045 eDest.
Emsg(
"config",
"http.tlsclientauth defer is not supported on this platform");
3050 eDest.
Emsg(
"config",
"invalid tlsclientauth parameter -", val);
3055 auto val =
Config.GetWord();
3056 if (!val || !val[0])
3057 {
eDest.
Emsg(
"Config",
"tlsrequiredprefix argument not specified");
return 1;}
3060 {
eDest.
Emsg(
"Config",
"http.tlsrequiredprefix argument must be an absolute path");
return 1;}
3067 char *val =
Config.GetWord();
3069 if(!strcmp(
"tpc",val)) {
3070 if(!(val =
Config.GetWord())) {
3071 eDest.
Emsg(
"Config",
"http.auth tpc value not specified.");
return 1;
3073 if(!strcmp(
"fcreds",val)) {
3076 eDest.
Emsg(
"Config",
"http.auth tpc value is invalid");
return 1;
3080 eDest.
Emsg(
"Config",
"http.auth value is invalid");
return 1;
3104 static struct traceopts {
3116 int i, neg, trval = 0, numopts =
sizeof (tropts) /
sizeof (
struct traceopts);
3118 if (!(val =
Config.GetWord())) {
3119 eDest.
Emsg(
"config",
"trace option not specified");
3123 if (!strcmp(val,
"off")) trval = 0;
3125 if ((neg = (val[0] ==
'-' && val[1]))) val++;
3126 for (i = 0; i < numopts; i++) {
3127 if (!strcmp(val, tropts[i].opname)) {
3128 if (neg) trval &= ~tropts[i].opval;
3129 else trval |= tropts[i].opval;
3134 eDest.
Emsg(
"config",
"invalid trace option", val);
3153 l = strlen(fname) + 1;
3178 length = fname.
length() + 1;
3190 int XrdHttpProtocol::LoadSecXtractor(
XrdSysError *myeDest,
const char *libName,
3191 const char *libParms) {
3195 if (secxtractor)
return 1;
3197 XrdOucPinLoader myLib(myeDest, &compiledVer,
"secxtractorlib", libName);
3203 if (ep && (secxtractor = ep(myeDest, NULL, libParms)))
return 0;
3211 int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec,
const char *cFN,
XrdOucEnv &myEnv) {
3212 for (
int i = 0; i < (int) hiVec.size(); i++) {
3213 if(hiVec[i].extHNoTlsOK) {
3215 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3216 hiVec[i].extHParm.c_str(), &myEnv,
3217 hiVec[i].extHName.c_str()))
3224 int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
3236 for (
int i = 0; i < (int)hiVec.size(); i++) {
3239 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3240 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3241 hiVec[i].extHParm.c_str(), &myEnv,
3242 hiVec[i].extHName.c_str()))
return 1;
3249 int XrdHttpProtocol::LoadExtHandler(
XrdSysError *myeDest,
const char *libName,
3250 const char *configFN,
const char *libParms,
3251 XrdOucEnv *myEnv,
const char *instName) {
3255 if (ExtHandlerLoaded(instName)) {
3256 eDest.
Emsg(
"Config",
"Instance name already present for an http external handler plugin.");
3260 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
3264 XrdOucPinLoader myLib(myeDest, &compiledVer,
"exthandlerlib", libName);
3272 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3275 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3276 exthandler[exthandlercnt].name[15] =
'\0';
3277 exthandler[exthandlercnt++].ptr = newhandler;
3290 bool XrdHttpProtocol::ExtHandlerLoaded(
const char *handlername) {
3291 for (
int i = 0; i < exthandlercnt; i++) {
3292 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3303 for (
int i = 0; i < exthandlercnt; i++) {
3305 return exthandler[i].ptr;
struct ClientSetRequest set
struct ClientQueryRequest query
struct ClientStatRequest stat
#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")
void * BIO_get_data(BIO *bio)
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_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)
char * unquote(char *str)
void calcHashes(char *hash, const char *fn, kXR_int16 request, XrdSecEntity *secent, time_t tim, const char *key)
Utility functions for XrdHTTP.
std::string obfuscateAuth(const std::string &input)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fstat(int fildes, struct stat *buf)
ssize_t read(int fildes, void *buf, size_t nbyte)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_REFINT(cOpts, refi)
void Release(XrdBuffer *bp)
XrdBuffer * Obtain(int bsz)
const std::vector< std::string > & getNonIANAConfiguredCksums() const
void configure(const char *csList)
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.
XrdHttpProtocol operator=(const XrdHttpProtocol &rhs)
static bool compatNameGeneration
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 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.
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 std::unordered_map< std::string, std::string > m_staticheaders
static int crlRefIntervalSec
CRL thread refresh interval.
static XrdHttpReadRangeHandler::Configuration ReadRangeConfig
configuration for the read range handler
static XrdSecService * CIA
static XrdBuffManager * BPool
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)
int reqstate
State machine to talk to the bridge.
XrdOucString resource
The resource specified by the request, stripped of opaque data.
bool headerok
Tells if we have finished reading the header.
ReqType request
The request we got.
XrdOucEnv * opaque
The opaque data, after parsing.
int parseFirstLine(char *line, int len)
Parse the first line of the header.
int parseLine(char *line, int len)
Parse the header.
void appendOpaque(XrdOucString &s, XrdSecEntity *secent, char *hash, time_t tnow)
ClientRequest xrdreq
The last issued xrd request, often pending.
const std::string & userAgent() const
virtual int InitSSL(SSL *, char *)
virtual int FreeSSL(SSL *)
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)
void Set(int inQMax, time_t agemax=1800)
void Push(XrdObject< T > *Node)
static bool Import(const char *var, char *&val)
void * GetPtr(const char *varname)
char * Get(const char *varname)
void Put(const char *varname, const char *value)
void insert(const int i, int start=-1)
const char * c_str() const
void assign(const char *s, int j, int k=-1)
char * vorg
Entity's virtual organization(s)
int credslen
Length of the 'creds' data.
XrdNetAddrInfo * addrInfo
Entity's connection details.
const char * tident
Trace identifier always preset.
char prot[XrdSecPROTOIDSIZE]
Auth protocol used (e.g. krb5)
char * caps
Entity's capabilities.
char * creds
Raw entity credentials or cert.
char * grps
Entity's group name(s)
void Reset(const char *spV=0)
char * name
Entity's name.
char * role
Entity's role(s)
char * endorsements
Protocol specific endorsements.
void Display(XrdSysError &mDest)
char * moninfo
Information for monitoring.
char * host
Entity's host name dnr dependent.
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void SetLogger(XrdSysLogger *logp)
void SetTlsClientAuth(ClientAuthSetting setting)
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.
const CTX_Params * GetParams()
static const int scOff
Turn off cache.
bool SetContextCiphers(const char *ciphers)
static const int scSrvr
Turn on cache server mode (default)
static Bridge * Login(Result *rsltP, XrdLink *linkP, XrdSecEntity *seceP, const char *nameP, const char *protP)
virtual bool Run(const char *xreqP, char *xdataP=0, int xdataL=0)=0
CloseImpl< false > Close(Ctx< File > file, uint16_t timeout=0)
Factory for creating CloseImpl objects.
std::vector< std::string > tlsAuthRequestPrefixes
XrdTlsContext::ClientAuthSetting tlsClientAuth
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.