983 {
986 std::vector<extHInfo> extHIVec;
987 char *var;
988 int cfgFD, GoNo, NoGo = 0, ismine;
989
990 var = nullptr;
993
994 pmarkHandle = (
XrdNetPMark* ) myEnv->GetPtr(
"XrdNetPMark*");
995
996 cksumHandler.configure(xrd_cslist);
997 auto nonIanaChecksums = cksumHandler.getNonIANAConfiguredCksums();
998 if(nonIanaChecksums.size()) {
999 std::stringstream warningMsgSS;
1000 warningMsgSS << "Config warning: the following checksum algorithms are not IANA compliant: [";
1001 std::string unknownCksumString;
1002 for(auto unknownCksum: nonIanaChecksums) {
1003 unknownCksumString += unknownCksum + ",";
1004 }
1005 unknownCksumString.erase(unknownCksumString.size() - 1);
1006 warningMsgSS << unknownCksumString << "]" << ". They therefore cannot be queried by a user via HTTP." ;
1007 eDest.
Say(warningMsgSS.str().c_str());
1008 }
1009
1010
1011 if (!m_bio_type) {
1012
1013 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1014 m_bio_type = (26|0x0400|0x0100);
1015 m_bio_method = static_cast<BIO_METHOD*>(OPENSSL_malloc(sizeof(BIO_METHOD)));
1016
1017 if (m_bio_method) {
1018 memset(m_bio_method, '\0', sizeof(BIO_METHOD));
1019 m_bio_method->type = m_bio_type;
1025 }
1026 #else
1027
1028
1029 m_bio_type = BIO_get_new_index();
1030 m_bio_method = BIO_meth_new(m_bio_type, "xrdhttp-bio-method");
1031
1032 if (m_bio_method) {
1038 }
1039
1040 #endif
1041 }
1042
1043
1044
1045
1047
1048
1049
1050 if ((cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
1051 return eDest.
Emsg(
"Config", errno,
"open config file", ConfigFN);
1053 static const char *cvec[] = { "*** http protocol config:", 0 };
1055
1056
1057
1058 while ((var =
Config.GetMyFirstWord())) {
1059 if ((ismine = !strncmp("http.", var, 5)) && var[5]) var += 5;
1060
1061 if (ismine) {
1062 if TS_Xeq(
"trace", xtrace);
1063 else if TS_Xeq(
"cert", xsslcert);
1064 else if TS_Xeq(
"key", xsslkey);
1065 else if TS_Xeq(
"cadir", xsslcadir);
1066 else if TS_Xeq(
"cipherfilter", xsslcipherfilter);
1067 else if TS_Xeq(
"gridmap", xgmap);
1068 else if TS_Xeq(
"cafile", xsslcafile);
1069 else if TS_Xeq(
"secretkey", xsecretkey);
1070 else if TS_Xeq(
"desthttps", xdesthttps);
1071 else if TS_Xeq(
"secxtractor", xsecxtractor);
1072 else if TS_Xeq3(
"exthandler", xexthandler);
1073 else if TS_Xeq(
"selfhttps2http", xselfhttps2http);
1074 else if TS_Xeq(
"embeddedstatic", xembeddedstatic);
1075 else if TS_Xeq(
"listingredir", xlistredir);
1076 else if TS_Xeq(
"staticredir", xstaticredir);
1077 else if TS_Xeq(
"staticpreload", xstaticpreload);
1078 else if TS_Xeq(
"staticheader", xstaticheader);
1079 else if TS_Xeq(
"listingdeny", xlistdeny);
1080 else if TS_Xeq(
"header2cgi", xheader2cgi);
1081 else if TS_Xeq(
"httpsmode", xhttpsmode);
1082 else if TS_Xeq(
"tlsreuse", xtlsreuse);
1083 else if TS_Xeq(
"auth", xauth);
1084 else {
1085 eDest.
Say(
"Config warning: ignoring unknown directive '", var,
"'.");
1087 continue;
1088 }
1089 if (GoNo) {
1091 NoGo = 1;
1092 }
1093 }
1094 }
1095
1096
1097
1098
1099 if (NoGo)
1100 {
eDest.
Say(
"Config failure: one or more directives are flawed!");
1101 return 1;
1102 }
1103
1104
1105
1106 hdr2cgimap["Cache-Control"] = "cache-control";
1107
1108
1109 if (getenv(
"XRDCL_EC"))
usingEC =
true;
1110
1111
1112
1113 const auto default_verb = m_staticheader_map.find("");
1114 std::string default_static_headers;
1115 if (default_verb != m_staticheader_map.end()) {
1116 for (const auto &header_entry : default_verb->second) {
1117 default_static_headers += header_entry.first + ": " + header_entry.second + "\r\n";
1118 }
1119 }
1120 m_staticheaders[""] = default_static_headers;
1121 for (const auto &item : m_staticheader_map) {
1122 if (item.first.empty()) {
1123 continue;
1124 }
1125 auto headers = default_static_headers;
1126 for (const auto &header_entry : item.second) {
1127 headers += header_entry.first + ": " + header_entry.second + "\r\n";
1128 }
1129
1130 m_staticheaders[item.first] = headers;
1131 }
1132
1133
1134
1135 if (myEnv->Get("XrdCache")) hasCache = true;
1136
1137
1138
1139
1140
1141
1144 : "was not configured.");
1145 const char *what = Configed();
1146
1147 eDest.
Say(
"Config warning: HTTPS functionality ", why);
1149
1150 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1151 if (what)
1152 {
eDest.
Say(
"Config failure: ", what,
" HTTPS but it ", why);
1153 NoGo = 1;
1154 }
1155 return NoGo;
1156 }
1157
1158
1159
1160
1161 if (sslkey && !sslcert)
1162 {
eDest.
Say(
"Config warning: specifying http.key without http.cert "
1163 "is meaningless; ignoring key!");
1164 free(sslkey); sslkey = 0;
1165 }
1166
1167
1168
1170 {if (!sslcert)
1171 {
eDest.
Say(
"Config failure: 'httpsmode manual' requires atleast a "
1172 "a cert specification!");
1173 return 1;
1174 }
1175 }
1176
1177
1178
1179
1180
1183 const char *what1 = 0, *what2 = 0, *what3 = 0;
1184
1185 if (!sslcert && cP->
cert.size())
1186 {sslcert = strdup(cP->
cert.c_str());
1187 if (cP->
pkey.size()) sslkey = strdup(cP->
pkey.c_str());
1188 what1 = "xrd.tls to supply 'cert' and 'key'.";
1189 }
1190 if (!sslcadir && cP->
cadir.size())
1191 {sslcadir = strdup(cP->
cadir.c_str());
1192 what2 = "xrd.tlsca to supply 'cadir'.";
1193 }
1194 if (!sslcafile && cP->
cafile.size())
1195 {sslcafile = strdup(cP->
cafile.c_str());
1196 what2 = (what2 ? "xrd.tlsca to supply 'cadir' and 'cafile'."
1197 : "xrd.tlsca to supply 'cafile'.");
1198 }
1200 crlRefIntervalSec = cP->
crlRT;
1201 what3 = "xrd.tlsca to supply 'refresh' interval.";
1202 }
1206 }
1207
1208
1209
1210 if (!(sslcadir || sslcafile))
1211 {const char *what = Configed();
1212 const char *why = (
httpsspec ?
"a cadir or cafile was not specified!"
1213 : "'xrd.tlsca noverify' was specified!");
1214 if (what)
1215 {
eDest.
Say(
"Config failure: ", what,
" cert verification but ", why);
1216 return 1;
1217 }
1218 }
1220
1221
1222
1223 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1224
1225
1226
1227
1228 const char *how = "completed.";
1229 eDest.
Say(
"++++++ HTTPS initialization started.");
1230 if (!InitTLS()) {NoGo = 1; how = "failed.";}
1231 eDest.
Say(
"------ HTTPS initialization ", how);
1232 if (NoGo) return NoGo;
1233
1234
1235
1236 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv)) return 1;
1237
1238
1239
1240 return (InitSecurity() ? NoGo : 1);
1241}
1242
1243
1244
1245
1246
1247const char *XrdHttpProtocol::Configed()
1248{
1249 if (secxtractor &&
gridmap)
return "gridmap and secxtractor require";
1250 if (secxtractor) return "secxtractor requires";
1251 if (
gridmap)
return "gridmap requires";
1252 return 0;
1253}
1254
1255
1256
1257
1258
1260
1262
1263 dest = "";
1264 char save;
1265
1266
1267 if (myBuffEnd >= myBuffStart) {
1268 int l = 0;
1269 for (char *p = myBuffStart; p < myBuffEnd; p++) {
1270 l++;
1271 if (*p == '\n') {
1272 save = *(p+1);
1273 *(p+1) = '\0';
1274 dest.
assign(myBuffStart, 0, l-1);
1275 *(p+1) = save;
1276
1277
1278
1279 BuffConsume(l);
1280
1281
1282 return l;
1283 }
1284
1285 }
1286
1287 return 0;
1288 } else {
1289
1290
1291
1292 int l = 0;
1293 for (
char *p = myBuffStart; p < myBuff->
buff + myBuff->
bsize; p++) {
1294 l++;
1295 if ((*p == '\n') || (*p == '\0')) {
1296 save = *(p+1);
1297 *(p+1) = '\0';
1298 dest.
assign(myBuffStart, 0, l-1);
1299 *(p+1) = save;
1300
1301
1302
1303 BuffConsume(l);
1304
1305
1306 return l;
1307 }
1308
1309 }
1310
1311
1312
1313 l = 0;
1314 for (
char *p = myBuff->
buff; p < myBuffEnd; p++) {
1315 l++;
1316 if ((*p == '\n') || (*p == '\0')) {
1317 save = *(p+1);
1318 *(p+1) = '\0';
1319
1320 int l1 = myBuff->
buff + myBuff->
bsize - myBuffStart;
1321
1322 dest.
assign(myBuffStart, 0, l1-1);
1323
1324 BuffConsume(l1);
1325
1326 dest.
insert(myBuffStart, l1, l-1);
1327
1328
1329 BuffConsume(l);
1330
1331 *(p+1) = save;
1332
1333
1334 return l + l1;
1335 }
1336
1337 }
1338
1339
1340
1341 }
1342
1343 return 0;
1344}
1345
1346
1347
1348
1349
1350int XrdHttpProtocol::getDataOneShot(int blen, bool wait) {
1351 int rlen, maxread;
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 maxread = std::min(blen, BuffAvailable());
1366 TRACE(
DEBUG,
"getDataOneShot BuffAvailable: " << BuffAvailable() <<
" maxread: " << maxread);
1367
1368 if (!maxread)
1369 return 2;
1370
1371 if (ishttps) {
1372 int sslavail = maxread;
1373
1374 if (!wait) {
1375 int l = SSL_pending(ssl);
1376 if (l > 0)
1377 sslavail = std::min(maxread, SSL_pending(ssl));
1378 }
1379
1380 if (sslavail < 0) {
1382 ERR_print_errors(sslbio_err);
1383 return -1;
1384 }
1385
1386 TRACE(
DEBUG,
"getDataOneShot sslavail: " << sslavail);
1387 if (sslavail <= 0) return 0;
1388
1389 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1391 myBuffEnd = myBuff->
buff;
1392 }
1393
1394 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1395 if (rlen <= 0) {
1397 ERR_print_errors(sslbio_err);
1398 return -1;
1399 }
1400
1401
1402 } else {
1403
1404 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1406 myBuffEnd = myBuff->
buff;
1407 }
1408
1409 if (wait)
1411 else
1412 rlen =
Link->
Recv(myBuffEnd, maxread);
1413
1414
1415 if (rlen == 0) {
1417 return -1;
1418 }
1419
1420 if (rlen < 0) {
1422 return -1;
1423 }
1424 }
1425
1426 myBuffEnd += rlen;
1427
1428 TRACE(REQ,
"read " << rlen <<
" of " << blen <<
" bytes");
1429
1430 return 0;
1431}
1432
1434
1435int XrdHttpProtocol::BuffAvailable() {
1436 int r;
1437
1438 if (myBuffEnd >= myBuffStart)
1439 r = myBuff->
buff + myBuff->
bsize - myBuffEnd;
1440 else
1441 r = myBuffStart - myBuffEnd;
1442
1443 if ((r < 0) || (r > myBuff->
bsize)) {
1444 TRACE(REQ,
"internal error, myBuffAvailable: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1445 abort();
1446 }
1447
1448 return r;
1449}
1450
1451
1452
1453
1454
1456
1457int XrdHttpProtocol::BuffUsed() {
1458 int r;
1459
1460 if (myBuffEnd >= myBuffStart)
1461 r = myBuffEnd - myBuffStart;
1462 else
1463
1464 r = myBuff->
bsize - (myBuffStart - myBuffEnd);
1465
1466 if ((r < 0) || (r > myBuff->
bsize)) {
1467 TRACE(REQ,
"internal error, myBuffUsed: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1468 abort();
1469 }
1470
1471 return r;
1472}
1473
1474
1475
1476
1477
1479
1480int XrdHttpProtocol::BuffFree() {
1481 return (myBuff->
bsize - BuffUsed());
1482}
1483
1484
1485
1486
1487
1488void XrdHttpProtocol::BuffConsume(int blen) {
1489
1490 if (blen > myBuff->
bsize) {
1491 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") smaller than buffsize");
1492 abort();
1493 }
1494
1495 if (blen > BuffUsed()) {
1496 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") larger than BuffUsed:" << BuffUsed());
1497 abort();
1498 }
1499
1500 myBuffStart = myBuffStart + blen;
1501
1502 if (myBuffStart >= myBuff->
buff + myBuff->
bsize)
1503 myBuffStart -= myBuff->
bsize;
1504
1505 if (myBuffEnd >= myBuff->
buff + myBuff->
bsize)
1506 myBuffEnd -= myBuff->
bsize;
1507
1508 if (BuffUsed() == 0)
1509 myBuffStart = myBuffEnd = myBuff->
buff;
1510}
1511
1512
1513
1514
1515
1524int XrdHttpProtocol::BuffgetData(int blen, char **data, bool wait) {
1525 int rlen;
1526
1527 TRACE(
DEBUG,
"BuffgetData: requested " << blen <<
" bytes");
1528
1529
1530 if (wait) {
1531
1532 if (blen > BuffUsed()) {
1533 TRACE(REQ,
"BuffgetData: need to read " << blen - BuffUsed() <<
" bytes");
1534 if ( getDataOneShot(blen - BuffUsed(), true) )
1535
1536 return 0;
1537 }
1538 } else {
1539
1540 if ( !BuffUsed() ) {
1541 if ( getDataOneShot(blen, false) )
1542
1543 return -1;
1544 }
1545 }
1546
1547
1548
1549 if (myBuffStart <= myBuffEnd) {
1550 rlen = std::min( (long) blen, (long)(myBuffEnd - myBuffStart) );
1551
1552 } else
1553 rlen = std::min( (
long) blen, (
long)(myBuff->
buff + myBuff->
bsize - myBuffStart) );
1554
1555 *data = myBuffStart;
1556 BuffConsume(rlen);
1557 return rlen;
1558}
1559
1560
1561
1562
1563
1565
1566int XrdHttpProtocol::SendData(const char *body, int bodylen) {
1567
1568 int r;
1569
1570 if (body && bodylen) {
1571 TRACE(REQ,
"Sending " << bodylen <<
" bytes");
1572 if (ishttps) {
1573 r = SSL_write(ssl, body, bodylen);
1574 if (r <= 0) {
1575 ERR_print_errors(sslbio_err);
1576 return -1;
1577 }
1578
1579 } else {
1581 if (r <= 0) return -1;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588
1589
1590
1591
1592int XrdHttpProtocol::StartSimpleResp(int code, const char *desc,
1593 const char *header_to_add,
1594 long long bodylen, bool keepalive) {
1595 static const std::unordered_map<int, std::string> statusTexts = {
1596 {100, "Continue"},
1597 {200, "OK"},
1598 {201, "Created"},
1599 {206, "Partial Content"},
1600 {302, "Redirect"},
1601 {307, "Temporary Redirect"},
1602 {400, "Bad Request"},
1603 {401, "Unauthorized"},
1604 {403, "Forbidden"},
1605 {404, "Not Found"},
1606 {405, "Method Not Allowed"},
1607 {409, "Conflict"},
1608 {416, "Range Not Satisfiable"},
1609 {423, "Locked"},
1610 {500, "Internal Server Error"},
1611 {502, "Bad Gateway"},
1612 {504, "Gateway Timeout"},
1613 {507, "Insufficient Storage"}};
1614
1615 std::stringstream ss;
1616 const std::string crlf = "\r\n";
1617
1618 ss << "HTTP/1.1 " << code << " ";
1619
1620 if (desc) {
1621 ss << desc;
1622 } else {
1623 auto it = statusTexts.find(code);
1624 if (it != statusTexts.end()) {
1625 ss << it->second;
1626 } else {
1627 ss << "Unknown";
1628 }
1629 }
1630 ss << crlf;
1631
1632 if (keepalive && (code != 100))
1633 ss << "Connection: Keep-Alive" << crlf;
1634 else
1635 ss << "Connection: Close" << crlf;
1636
1637 ss << "Server: XrootD/" << XrdVSTRING << crlf;
1638
1641 ss << iter->second;
1642 } else {
1644 }
1645
1646 if ((bodylen >= 0) && (code != 100))
1647 ss << "Content-Length: " << bodylen << crlf;
1648
1649 if (header_to_add && (header_to_add[0] != '\0')) ss << header_to_add << crlf;
1650
1651 ss << crlf;
1652
1653 const std::string &outhdr = ss.str();
1654 TRACEI(RSP,
"Sending resp: " << code <<
" header len:" << outhdr.size());
1655 if (SendData(outhdr.c_str(), outhdr.size()))
1656 return -1;
1657
1658 return 0;
1659}
1660
1661
1662
1663
1664
1665int XrdHttpProtocol::StartChunkedResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1666 const std::string crlf = "\r\n";
1667 std::stringstream ss;
1668
1669 if (header_to_add && (header_to_add[0] != '\0')) {
1670 ss << header_to_add << crlf;
1671 }
1672
1673 ss << "Transfer-Encoding: chunked";
1674 TRACEI(RSP,
"Starting chunked response");
1675 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1676}
1677
1678
1679
1680
1681
1682int XrdHttpProtocol::ChunkResp(const char *body, long long bodylen) {
1683 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1684 if (ChunkRespHeader(content_length))
1685 return -1;
1686
1687 if (body && SendData(body, content_length))
1688 return -1;
1689
1690 return ChunkRespFooter();
1691}
1692
1693
1694
1695
1696
1697int XrdHttpProtocol::ChunkRespHeader(long long bodylen) {
1698 const std::string crlf = "\r\n";
1699 std::stringstream ss;
1700
1701 ss << std::hex << bodylen << std::dec << crlf;
1702
1703 const std::string &chunkhdr = ss.str();
1704 TRACEI(RSP,
"Sending encoded chunk of size " << bodylen);
1705 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1706}
1707
1708
1709
1710
1711
1712int XrdHttpProtocol::ChunkRespFooter() {
1713 const std::string crlf = "\r\n";
1714 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1715}
1716
1717
1718
1719
1720
1724
1725int XrdHttpProtocol::SendSimpleResp(int code, const char *desc, const char *header_to_add, const char *body, long long bodylen, bool keepalive) {
1726
1727 long long content_length = bodylen;
1728 if (bodylen <= 0) {
1729 content_length = body ? strlen(body) : 0;
1730 }
1731
1732 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1733 return -1;
1734
1735
1736
1737
1738 if (body)
1739 return SendData(body, content_length);
1740
1741 return 0;
1742}
1743
1744
1745
1746
1747
1749
1750
1751
1752
1753
1754
1755
1756
1757 char *rdf;
1758
1759
1760
1763
1767
1769
1770
1771
1773
1774 {
1775 char buf[16];
1776 sprintf(buf,
"%d",
Port);
1778 }
1779
1780
1781
1782 rdf = (parms && *parms ? parms : pi->
ConfigFN);
1783 if (rdf && Config(rdf, pi->
theEnv))
return 0;
1785
1786
1788 if ((rdf = getenv("XRDROLE"))) {
1790
1791 if (!strcasecmp(rdf, "manager") || !strcasecmp(rdf, "supervisor")) {
1793 eDest.
Emsg(
"Config",
"Configured as HTTP(s) redirector.");
1794 } else {
1795
1796 eDest.
Emsg(
"Config",
"Configured as HTTP(s) data server.");
1797 }
1798
1799 } else {
1800 eDest.
Emsg(
"Config",
"No XRDROLE specified.");
1801 }
1802
1803
1804
1808
1809
1810
1811
1812 return 1;
1813}
1814
1815
1816
1817
1819 char *val, keybuf[1024], parmbuf[1024];
1820 char *parm;
1821
1822
1824 if (!val || !val[0]) {
1825 err.
Emsg(
"Config",
"No headerkey specified.");
1826 return 1;
1827 } else {
1828
1829
1830 while ( *val && !isalnum(*val) ) val++;
1831 strcpy(keybuf, val);
1832
1833
1834 char *pp;
1835 pp = keybuf + strlen(keybuf) - 1;
1836 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1837 *pp = '\0';
1838 pp--;
1839 }
1840
1842
1843
1844 if(!parm || !parm[0]) {
1845 err.
Emsg(
"Config",
"No header2cgi value specified. key: '", keybuf,
"'");
1846 return 1;
1847 }
1848
1849
1850 while ( *parm && !isalnum(*parm) ) parm++;
1851 strcpy(parmbuf, parm);
1852
1853
1854 pp = parmbuf + strlen(parmbuf) - 1;
1855 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1856 *pp = '\0';
1857 pp--;
1858 }
1859
1860
1861 try {
1862 header2cgi[keybuf] = parmbuf;
1863 } catch ( ... ) {
1864 err.
Emsg(
"Config",
"Can't insert new header2cgi rule. key: '", keybuf,
"'");
1865 return 1;
1866 }
1867
1868 }
1869 return 0;
1870}
1871
1872
1873
1874
1875
1876
1877bool XrdHttpProtocol::InitTLS() {
1878
1882
1883
1884
1887
1890
1891
1892
1895 return false;
1896 }
1897
1898
1899
1900
1901
1902 static const char *sess_ctx_id = "XrdHTTPSessionCtx";
1903 unsigned int n =(unsigned int)(strlen(sess_ctx_id)+1);
1905
1906
1907
1909 {
eDest.
Say(
"Config failure: ",
"Unable to set allowable https ciphers!");
1910 return false;
1911 }
1912
1913
1914
1915 return true;
1916}
1917
1918
1919
1920
1921
1922void XrdHttpProtocol::Cleanup() {
1923
1924 TRACE(ALL,
" Cleanup");
1925
1926 if (
BPool && myBuff) {
1927 BuffConsume(BuffUsed());
1929 myBuff = 0;
1930 }
1931
1932 if (ssl) {
1933
1934
1935
1936
1937
1938
1939
1940
1941 int ret = SSL_shutdown(ssl);
1942 if (ret != 1) {
1943 if(ret == 0) {
1944
1945 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1946 ERR_remove_thread_state(nullptr);
1947 #endif
1948 } else {
1949
1950 TRACE(ALL,
" SSL_shutdown failed");
1951 ERR_print_errors(sslbio_err);
1952 }
1953 }
1954
1955 if (secxtractor)
1957
1958 SSL_free(ssl);
1959
1960 }
1961
1962
1963 ssl = 0;
1964 sbio = 0;
1965
1974
1976
1979}
1980
1981
1982
1983
1984
1985void XrdHttpProtocol::Reset() {
1986
1987 TRACE(ALL,
" Reset");
1991
1992 if (myBuff) {
1994 myBuff = 0;
1995 }
1996 myBuffStart = myBuffEnd = 0;
1997
1998 DoingLogin = false;
1999 DoneSetInfo = false;
2000
2001 ResumeBytes = 0;
2002 Resume = 0;
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2019 ishttps = false;
2020 ssldone = false;
2021
2023 ssl = 0;
2024 sbio = 0;
2025
2026}
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043int XrdHttpProtocol::xhttpsmode(
XrdOucStream & Config) {
2044 char *val;
2045
2046
2047
2049 if (!val || !val[0]) {
2050 eDest.
Emsg(
"Config",
"httpsmode parameter not specified");
2051 return 1;
2052 }
2053
2054
2055
2059 else {
eDest.
Emsg(
"Config",
"invalid httpsmode parameter - ", val);
2060 return 1;
2061 }
2062 return 0;
2063}
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078int XrdHttpProtocol::xsslverifydepth(
XrdOucStream & Config) {
2079 char *val;
2080
2081
2082
2084 if (!val || !val[0]) {
2085 eDest.
Emsg(
"Config",
"sslverifydepth value not specified");
2086 return 1;
2087 }
2088
2089
2090
2092
2094 return 0;
2095}
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2111 char *val;
2112
2113
2114
2116 if (!val || !val[0]) {
2117 eDest.
Emsg(
"Config",
"HTTP X509 certificate not specified");
2118 return 1;
2119 }
2120
2121
2122
2125
2126
2127
2129 return 0;
2130}
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2146 char *val;
2147
2148
2149
2151 if (!val || !val[0]) {
2152 eDest.
Emsg(
"Config",
"HTTP X509 key not specified");
2153 return 1;
2154 }
2155
2156
2157
2160
2162 return 0;
2163}
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2183 char *val;
2184
2185
2186
2188 if (!val || !val[0]) {
2189 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file location not specified");
2190 return 1;
2191 }
2192
2193
2194
2195 if (!strncmp(val, "required", 8)) {
2198
2199 if (!val || !val[0]) {
2200 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after [required] "
2201 "parameter");
2202 return 1;
2203 }
2204 }
2205
2206
2207
2208 if (!strcmp(val, "compatNameGeneration")) {
2211 if (!val || !val[0]) {
2212 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after "
2213 "[compatNameGeneration] parameter");
2214 return 1;
2215 }
2216 }
2217
2218
2219
2220
2223 return 0;
2224}
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239int XrdHttpProtocol::xsslcafile(
XrdOucStream & Config) {
2240 char *val;
2241
2242
2243
2245 if (!val || !val[0]) {
2246 eDest.
Emsg(
"Config",
"HTTP X509 CAfile not specified");
2247 return 1;
2248 }
2249
2250
2251
2254
2256 return 0;
2257}
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272int XrdHttpProtocol::xsecretkey(
XrdOucStream & Config) {
2273 char *val;
2274 bool inFile = false;
2275
2276
2277
2279 if (!val || !val[0]) {
2280 eDest.
Emsg(
"Config",
"Shared secret key not specified");
2281 return 1;
2282 }
2283
2284
2285
2286
2287
2288 if (val[0] == '/') {
2290 inFile = true;
2291 int fd =
open(val, O_RDONLY);
2292
2293 if ( fd == -1 ) {
2294 eDest.
Emsg(
"Config", errno,
"open shared secret key file", val);
2295 return 1;
2296 }
2297
2298 if (
fstat(fd, &st) != 0 ) {
2299 eDest.
Emsg(
"Config", errno,
"fstat shared secret key file", val);
2301 return 1;
2302 }
2303
2304 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2306 "For your own security, the shared secret key file cannot be world readable or group writable '", val, "'");
2308 return 1;
2309 }
2310
2311 FILE *fp = fdopen(fd, "r");
2312
2313 if ( fp == nullptr ) {
2314 eDest.
Emsg(
"Config", errno,
"fdopen shared secret key file", val);
2316 return 1;
2317 }
2318
2319 char line[1024];
2320 while( fgets(line, 1024, fp) ) {
2321 char *pp;
2322
2323
2324 pp = line + strlen(line) - 1;
2325 while ( (pp >= line) && (!isalnum(*pp)) ) {
2326 *pp = '\0';
2327 pp--;
2328 }
2329
2330
2331 pp = line;
2332 while ( *pp && !isalnum(*pp) ) pp++;
2333
2334 if ( strlen(pp) >= 32 ) {
2335 eDest.
Say(
"Config",
"Secret key loaded.");
2336
2339
2341 return 0;
2342 }
2343
2344 }
2345
2347 eDest.
Emsg(
"Config",
"Cannot find useful secretkey in file '", val,
"'");
2348 return 1;
2349
2350 }
2351
2352 if ( strlen(val) < 32 ) {
2353 eDest.
Emsg(
"Config",
"Secret key is too short");
2354 return 1;
2355 }
2356
2357
2360 if (!inFile)
Config.noEcho();
2361
2362 return 0;
2363}
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2379 char *val;
2380
2381
2382
2384 if (!val || !val[0]) {
2385 eDest.
Emsg(
"Config",
"listingdeny flag not specified");
2386 return 1;
2387 }
2388
2389
2390
2391 listdeny = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2392
2393
2394 return 0;
2395}
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410int XrdHttpProtocol::xlistredir(
XrdOucStream & Config) {
2411 char *val;
2412
2413
2414
2416 if (!val || !val[0]) {
2417 eDest.
Emsg(
"Config",
"listingredir flag not specified");
2418 return 1;
2419 }
2420
2421
2422
2425
2426
2427 return 0;
2428}
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443int XrdHttpProtocol::xdesthttps(
XrdOucStream & Config) {
2444 char *val;
2445
2446
2447
2449 if (!val || !val[0]) {
2450 eDest.
Emsg(
"Config",
"desthttps flag not specified");
2451 return 1;
2452 }
2453
2454
2455
2456 isdesthttps = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2457
2458
2459 return 0;
2460}
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475int XrdHttpProtocol::xembeddedstatic(
XrdOucStream & Config) {
2476 char *val;
2477
2478
2479
2481 if (!val || !val[0]) {
2482 eDest.
Emsg(
"Config",
"embeddedstatic flag not specified");
2483 return 1;
2484 }
2485
2486
2487
2488 embeddedstatic = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2489
2490
2491 return 0;
2492}
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507int XrdHttpProtocol::xstaticredir(
XrdOucStream & Config) {
2508 char *val;
2509
2510
2511
2513 if (!val || !val[0]) {
2514 eDest.
Emsg(
"Config",
"staticredir url not specified");
2515 return 1;
2516 }
2517
2518
2519
2522
2523 return 0;
2524}
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542int XrdHttpProtocol::xstaticpreload(
XrdOucStream & Config) {
2543 char *val, *k, key[1024];
2544
2545
2546
2548 if (!k || !k[0]) {
2549 eDest.
Emsg(
"Config",
"preloadstatic urlpath not specified");
2550 return 1;
2551 }
2552
2553 strcpy(key, k);
2554
2555
2556
2558 if (!val || !val[0]) {
2559 eDest.
Emsg(
"Config",
"preloadstatic filename not specified");
2560 return 1;
2561 }
2562
2563
2564 int fp =
open(val, O_RDONLY);
2565 if( fp < 0 ) {
2566 eDest.
Emsg(
"Config", errno,
"open preloadstatic filename", val);
2567 return 1;
2568 }
2569
2570 StaticPreloadInfo *nfo = new StaticPreloadInfo;
2571
2572 nfo->data = (char *)malloc(65536);
2573 nfo->len =
read(fp, (
void *)nfo->data, 65536);
2575
2576 if (nfo->len <= 0) {
2577 eDest.
Emsg(
"Config", errno,
"read from preloadstatic filename", val);
2578 return 1;
2579 }
2580
2581 if (nfo->len >= 65536) {
2582 eDest.
Emsg(
"Config",
"Truncated preloadstatic filename. Max is 64 KB '", val,
"'");
2583 return 1;
2584 }
2585
2586
2587
2590
2592 return 0;
2593}
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612int XrdHttpProtocol::xstaticheader(
XrdOucStream & Config) {
2613 auto val =
Config.GetWord();
2614 std::vector<std::string> verbs;
2615 while (true) {
2616 if (!val || !val[0]) {
2617 eDest.
Emsg(
"Config",
"http.staticheader requires the header to be specified");
2618 return 1;
2619 }
2620
2621 std::string match_verb;
2622 std::string_view val_str(val);
2623 if (val_str.substr(0, 6) == "-verb=") {
2624 verbs.emplace_back(val_str.substr(6));
2625 } else if (val_str == "-") {
2626 eDest.
Emsg(
"Config",
"http.staticheader is ignoring unknown flag: ", val_str.data());
2627 } else {
2628 break;
2629 }
2630
2632 }
2633 if (verbs.empty()) {
2634 verbs.emplace_back();
2635 }
2636
2637 std::string header = val;
2638
2640 std::string header_value;
2641 if (val && val[0]) {
2642 header_value = val;
2643 }
2644
2645 for (const auto &verb : verbs) {
2648 if (!header_value.empty())
2650 } else if (header_value.empty()) {
2651 iter->second.clear();
2652 } else {
2653 iter->second.emplace_back(header, header_value);
2654 }
2655 }
2656
2657 return 0;
2658}
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674int XrdHttpProtocol::xselfhttps2http(
XrdOucStream & Config) {
2675 char *val;
2676
2677
2678
2680 if (!val || !val[0]) {
2681 eDest.
Emsg(
"Config",
"selfhttps2http flag not specified");
2682 return 1;
2683 }
2684
2685
2686
2687 selfhttps2http = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2688
2689
2690 return 0;
2691}
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709int XrdHttpProtocol::xsecxtractor(
XrdOucStream& Config) {
2710 char *val;
2711
2712
2713
2715 if (!val || !val[0]) {
2716 eDest.
Emsg(
"Config",
"No security extractor plugin specified.");
2717 return 1;
2718 } else {
2719
2720
2721 if (!strncmp(val, "required", 8)) {
2722 isRequiredXtractor = true;
2724
2725 if (!val || !val[0]) {
2726 eDest.
Emsg(
"Config",
"No security extractor plugin after [required] "
2727 "parameter");
2728 return 1;
2729 }
2730 }
2731
2732 char libName[4096];
2733 strlcpy(libName, val,
sizeof(libName));
2734 libName[sizeof(libName) - 1] = '\0';
2735 char libParms[4096];
2736
2737 if (!
Config.GetRest(libParms, 4095)) {
2738 eDest.
Emsg(
"Config",
"secxtractor config params longer than 4k");
2739 return 1;
2740 }
2741
2742
2743
2744 if (LoadSecXtractor(&
eDest, libName, libParms)) {
2745 return 1;
2746 }
2747 }
2748
2749 return 0;
2750}
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2770 std::vector<extHInfo> &hiVec) {
2771 char *val, path[1024], namebuf[1024];
2772 char *parm;
2773
2774 bool noTlsOK = false;
2775
2776
2777
2779 if (!val || !val[0]) {
2780 eDest.
Emsg(
"Config",
"No instance name specified for an http external handler plugin.");
2781 return 1;
2782 }
2783 if (strlen(val) >= 16) {
2784 eDest.
Emsg(
"Config",
"Instance name too long for an http external handler plugin.");
2785 return 1;
2786 }
2787 strncpy(namebuf, val, sizeof(namebuf));
2788 namebuf[ sizeof(namebuf)-1 ] = '\0';
2789
2790
2792
2793 if(val && !strcmp("+notls",val)) {
2794 noTlsOK = true;
2796 }
2797
2798
2799
2800 if (!val || !val[0]) {
2801 eDest.
Emsg(
"Config",
"No http external handler plugin specified.");
2802 return 1;
2803 }
2804 if (strlen(val) >= (int)sizeof(path)) {
2805 eDest.
Emsg(
"Config",
"Path too long for an http external handler plugin.");
2806 return 1;
2807 }
2808
2809 strcpy(path, val);
2810
2811
2812
2814
2815
2816
2817 for (int i = 0; i < (int)hiVec.size(); i++)
2818 {if (hiVec[i].extHName == namebuf) {
2819 eDest.
Emsg(
"Config",
"Instance name already present for "
2820 "http external handler plugin",
2821 hiVec[i].extHPath.c_str());
2822 return 1;
2823 }
2824 }
2825
2826
2827
2829 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
2830 return 1;
2831 }
2832
2833
2834
2835 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm : ""), noTlsOK));
2836
2837 return 0;
2838}
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856int XrdHttpProtocol::xheader2cgi(
XrdOucStream & Config) {
2858}
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2874 char *val;
2875
2876
2877
2879 if (!val || !val[0]) {
2880 eDest.
Emsg(
"Config",
"HTTP X509 CAdir not specified");
2881 return 1;
2882 }
2883
2884
2885
2888
2890 return 0;
2891}
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907int XrdHttpProtocol::xsslcipherfilter(
XrdOucStream & Config) {
2908 char *val;
2909
2910
2911
2913 if (!val || !val[0]) {
2914 eDest.
Emsg(
"Config",
"SSL cipherlist filter string not specified");
2915 return 1;
2916 }
2917
2918
2919
2922
2923 return 0;
2924}
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2938
2939 char *val;
2940
2941
2942
2944 if (!val || !val[0])
2945 {
eDest.
Emsg(
"Config",
"tlsreuse argument not specified");
return 1;}
2946
2947
2948
2949 if (!strcmp(val, "off"))
2951 return 0;
2952 }
2953
2954
2955
2956 if (!strcmp(val, "on"))
2958 return 0;
2959 }
2960
2961
2962
2963 eDest.
Emsg(
"config",
"invalid tlsreuse parameter -", val);
2964 return 1;
2965}
2966
2968 char *val =
Config.GetWord();
2969 if(val) {
2970 if(!strcmp("tpc",val)) {
2971 if(!(val =
Config.GetWord())) {
2972 eDest.
Emsg(
"Config",
"http.auth tpc value not specified.");
return 1;
2973 } else {
2974 if(!strcmp("fcreds",val)) {
2976 } else {
2977 eDest.
Emsg(
"Config",
"http.auth tpc value is invalid");
return 1;
2978 }
2979 }
2980 } else {
2981 eDest.
Emsg(
"Config",
"http.auth value is invalid");
return 1;
2982 }
2983 }
2984 return 0;
2985}
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3002
3003 char *val;
3004
3005 static struct traceopts {
3006 const char *opname;
3007 int opval;
3008 } tropts[] = {
3016 };
3017 int i, neg, trval = 0, numopts = sizeof (tropts) / sizeof (struct traceopts);
3018
3019 if (!(val =
Config.GetWord())) {
3020 eDest.
Emsg(
"config",
"trace option not specified");
3021 return 1;
3022 }
3023 while (val) {
3024 if (!strcmp(val, "off")) trval = 0;
3025 else {
3026 if ((neg = (val[0] == '-' && val[1]))) val++;
3027 for (i = 0; i < numopts; i++) {
3028 if (!strcmp(val, tropts[i].opname)) {
3029 if (neg) trval &= ~tropts[i].opval;
3030 else trval |= tropts[i].opval;
3031 break;
3032 }
3033 }
3034 if (i >= numopts)
3035 eDest.
Emsg(
"config",
"invalid trace option", val);
3036 }
3038 }
3040 return 0;
3041}
3042
3044 int l;
3045 bool b;
3049
3054 l = strlen(fname) + 1;
3056
3059 if (!b) {
3060 return -1;
3061 }
3062
3063
3064 return 0;
3065}
3066
3067
3068
3069
3070
3072 size_t length;
3079 length = fname.
length() + 1;
3081
3083
3085}
3086
3087
3088static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION);
3089
3090
3091int XrdHttpProtocol::LoadSecXtractor(
XrdSysError *myeDest,
const char *libName,
3092 const char *libParms) {
3093
3094
3095
3096 if (secxtractor) return 1;
3097
3098 XrdOucPinLoader myLib(myeDest, &compiledVer,
"secxtractorlib", libName);
3100
3101
3102
3104 if (ep && (secxtractor = ep(myeDest, NULL, libParms))) return 0;
3105 myLib.Unload();
3106 return 1;
3107}
3108
3109
3110
3111
3112int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec,
const char *cFN,
XrdOucEnv &myEnv) {
3113 for (int i = 0; i < (int) hiVec.size(); i++) {
3114 if(hiVec[i].extHNoTlsOK) {
3115
3116 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3117 hiVec[i].extHParm.c_str(), &myEnv,
3118 hiVec[i].extHName.c_str()))
3119 return 1;
3120 }
3121 }
3122 return 0;
3123}
3124
3125int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
3127
3128
3129
3134
3135
3136
3137 for (int i = 0; i < (int)hiVec.size(); i++) {
3138
3139
3140 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3141 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3142 hiVec[i].extHParm.c_str(), &myEnv,
3143 hiVec[i].extHName.c_str())) return 1;
3144 }
3145 }
3146 return 0;
3147}
3148
3149
3150int XrdHttpProtocol::LoadExtHandler(
XrdSysError *myeDest,
const char *libName,
3151 const char *configFN, const char *libParms,
3152 XrdOucEnv *myEnv,
const char *instName) {
3153
3154
3155
3156 if (ExtHandlerLoaded(instName)) {
3157 eDest.
Emsg(
"Config",
"Instance name already present for an http external handler plugin.");
3158 return 1;
3159 }
3161 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
3162 return 1;
3163 }
3164
3165 XrdOucPinLoader myLib(myeDest, &compiledVer,
"exthandlerlib", libName);
3167
3168
3169
3171
3173 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3174
3175
3176 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3177 exthandler[exthandlercnt].name[15] = '\0';
3178 exthandler[exthandlercnt++].ptr = newhandler;
3179
3180 return 0;
3181 }
3182
3183 myLib.Unload();
3184 return 1;
3185}
3186
3187
3188
3189
3190
3191bool XrdHttpProtocol::ExtHandlerLoaded(const char *handlername) {
3192 for (int i = 0; i < exthandlercnt; i++) {
3193 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3194 return true;
3195 }
3196 }
3197 return false;
3198}
3199
3200
3201
3203
3204 for (int i = 0; i < exthandlercnt; i++) {
3206 return exthandler[i].ptr;
3207 }
3208 }
3209 return NULL;
3210}
struct ClientQueryRequest query
struct ClientStatRequest stat
#define XrdHttpExtHandlerArgs
static int BIO_XrdLink_create(BIO *bio)
const char * XrdHttpSecEntityTident
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)
XrdSysTrace XrdHttpTrace("http")
static int BIO_XrdLink_read(BIO *bio, char *data, size_t datal, size_t *read)
static int BIO_XrdLink_destroy(BIO *bio)
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
#define MAX_XRDHTTPEXTHANDLERS
#define XrdHttpSecXtractorArgs
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_REFINT(cOpts, refi)
void Release(XrdBuffer *bp)
static char * secretkey
The key used to calculate the url hashes.
static char * gridmap
Gridmap file location. The same used by XrdSecGsi.
static XrdScheduler * Sched
static kXR_int32 myRole
Our role.
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.
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 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.
static int readWait
Timeout for reading data.
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 compatNameGeneration
static bool isdesthttps
True if the redirections must be towards https targets.
static XrdObjectQ< XrdHttpProtocol > ProtStack
static bool isRequiredGridmap
static char * listredir
Url to redirect to in the case a listing is requested.
static int crlRefIntervalSec
CRL thread refresh interval.
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.
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.
ClientRequest xrdreq
The last issued xrd request, often pending.
virtual int FreeSSL(SSL *)
int setEtext(const char *text)
int Recv(char *buff, int blen)
int Send(const char *buff, int blen)
void Set(int inQMax, time_t agemax=1800)
static bool Import(const char *var, char *&val)
void Put(const char *varname, const char *value)
T * Rep(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default)
void insert(const int i, int start=-1)
void assign(const char *s, int j, int k=-1)
const char * c_str() const
char * vorg
Entity's virtual organization(s)
const char * tident
Trace identifier always preset.
char * caps
Entity's capabilities.
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.
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)
XrdSysLogger * logger(XrdSysLogger *lp=0)
void SetLogger(XrdSysLogger *logp)
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)
virtual bool Run(const char *xreqP, char *xdataP=0, int xdataL=0)=0
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.