991 {
994 std::vector<extHInfo> extHIVec;
995 char *var;
996 int cfgFD, GoNo, NoGo = 0, ismine;
997
998 var = nullptr;
1001
1002 pmarkHandle = (
XrdNetPMark* ) myEnv->GetPtr(
"XrdNetPMark*");
1003
1004 cksumHandler.configure(xrd_cslist);
1005 auto nonIanaChecksums = cksumHandler.getNonIANAConfiguredCksums();
1006 if(nonIanaChecksums.size()) {
1007 std::stringstream warningMsgSS;
1008 warningMsgSS << "Config warning: the following checksum algorithms are not IANA compliant: [";
1009 std::string unknownCksumString;
1010 for(auto unknownCksum: nonIanaChecksums) {
1011 unknownCksumString += unknownCksum + ",";
1012 }
1013 unknownCksumString.erase(unknownCksumString.size() - 1);
1014 warningMsgSS << unknownCksumString << "]" << ". They therefore cannot be queried by a user via HTTP." ;
1015 eDest.
Say(warningMsgSS.str().c_str());
1016 }
1017
1018
1019 if (!m_bio_type) {
1020
1021 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1022 m_bio_type = (26|0x0400|0x0100);
1023 m_bio_method = static_cast<BIO_METHOD*>(OPENSSL_malloc(sizeof(BIO_METHOD)));
1024
1025 if (m_bio_method) {
1026 memset(m_bio_method, '\0', sizeof(BIO_METHOD));
1027 m_bio_method->type = m_bio_type;
1033 }
1034 #else
1035
1036
1037 m_bio_type = BIO_get_new_index();
1038 m_bio_method = BIO_meth_new(m_bio_type, "xrdhttp-bio-method");
1039
1040 if (m_bio_method) {
1046 }
1047
1048 #endif
1049 }
1050
1051
1052
1053
1055
1056
1057
1058 if ((cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
1059 return eDest.
Emsg(
"Config", errno,
"open config file", ConfigFN);
1061 static const char *cvec[] = { "*** http protocol config:", 0 };
1063
1064
1065
1066 while ((var =
Config.GetMyFirstWord())) {
1067 if ((ismine = !strncmp("http.", var, 5)) && var[5]) var += 5;
1068
1069 if (ismine) {
1070 if TS_Xeq(
"trace", xtrace);
1071 else if TS_Xeq(
"cert", xsslcert);
1072 else if TS_Xeq(
"key", xsslkey);
1073 else if TS_Xeq(
"cadir", xsslcadir);
1074 else if TS_Xeq(
"cipherfilter", xsslcipherfilter);
1075 else if TS_Xeq(
"gridmap", xgmap);
1076 else if TS_Xeq(
"cafile", xsslcafile);
1077 else if TS_Xeq(
"secretkey", xsecretkey);
1078 else if TS_Xeq(
"desthttps", xdesthttps);
1079 else if TS_Xeq(
"secxtractor", xsecxtractor);
1080 else if TS_Xeq(
"cors", xcors);
1081 else if TS_Xeq3(
"exthandler", xexthandler);
1082 else if TS_Xeq(
"selfhttps2http", xselfhttps2http);
1083 else if TS_Xeq(
"embeddedstatic", xembeddedstatic);
1084 else if TS_Xeq(
"listingredir", xlistredir);
1085 else if TS_Xeq(
"staticredir", xstaticredir);
1086 else if TS_Xeq(
"staticpreload", xstaticpreload);
1087 else if TS_Xeq(
"staticheader", xstaticheader);
1088 else if TS_Xeq(
"listingdeny", xlistdeny);
1089 else if TS_Xeq(
"header2cgi", xheader2cgi);
1090 else if TS_Xeq(
"httpsmode", xhttpsmode);
1091 else if TS_Xeq(
"tlsreuse", xtlsreuse);
1092 else if TS_Xeq(
"auth", xauth);
1093 else if TS_Xeq(
"tlsclientauth", xtlsclientauth);
1094 else if TS_Xeq(
"maxdelay", xmaxdelay);
1095 else {
1096 eDest.
Say(
"Config warning: ignoring unknown directive '", var,
"'.");
1098 continue;
1099 }
1100 if (GoNo) {
1102 NoGo = 1;
1103 }
1104 }
1105 }
1106
1107
1108
1109
1110 if (NoGo)
1111 {
eDest.
Say(
"Config failure: one or more directives are flawed!");
1112 return 1;
1113 }
1114
1115
1116
1117 hdr2cgimap["Cache-Control"] = "cache-control";
1118
1119
1120 if (getenv(
"XRDCL_EC"))
usingEC =
true;
1121
1122
1123
1124 const auto default_verb = m_staticheader_map.find("");
1125 std::string default_static_headers;
1126 if (default_verb != m_staticheader_map.end()) {
1127 for (const auto &header_entry : default_verb->second) {
1128 default_static_headers += header_entry.first + ": " + header_entry.second + "\r\n";
1129 }
1130 }
1131 m_staticheaders[""] = default_static_headers;
1132 for (const auto &item : m_staticheader_map) {
1133 if (item.first.empty()) {
1134 continue;
1135 }
1136 auto headers = default_static_headers;
1137 for (const auto &header_entry : item.second) {
1138 headers += header_entry.first + ": " + header_entry.second + "\r\n";
1139 }
1140
1141 m_staticheaders[item.first] = headers;
1142 }
1143
1144
1145
1146 if (myEnv->Get("XrdCache")) hasCache = true;
1147
1148
1149 if(xrdcorsLibPath.size()) {
1150 if(LoadCorsHandler(&
eDest, xrdcorsLibPath.c_str()) != 0) {
1151 return 1;
1152 }
1153 if (xrdcors->Configure(ConfigFN, &
eDest) != 0) {
1154 return 1;
1155 }
1156 }
1157
1158
1159
1160
1161
1162
1165 : "was not configured.");
1166 const char *what = Configed();
1167
1168 eDest.
Say(
"Config warning: HTTPS functionality ", why);
1170
1171 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1172 if (what)
1173 {
eDest.
Say(
"Config failure: ", what,
" HTTPS but it ", why);
1174 NoGo = 1;
1175 }
1176 return NoGo;
1177 }
1178
1179
1180
1181
1182 if (sslkey && !sslcert)
1183 {
eDest.
Say(
"Config warning: specifying http.key without http.cert "
1184 "is meaningless; ignoring key!");
1185 free(sslkey); sslkey = 0;
1186 }
1187
1188
1189
1191 {if (!sslcert)
1192 {
eDest.
Say(
"Config failure: 'httpsmode manual' requires atleast a "
1193 "a cert specification!");
1194 return 1;
1195 }
1196 }
1197
1198
1199
1200
1201
1204 const char *what1 = 0, *what2 = 0, *what3 = 0;
1205
1206 if (!sslcert && cP->
cert.size())
1207 {sslcert = strdup(cP->
cert.c_str());
1208 if (cP->
pkey.size()) sslkey = strdup(cP->
pkey.c_str());
1209 what1 = "xrd.tls to supply 'cert' and 'key'.";
1210 }
1211 if (!sslcadir && cP->
cadir.size())
1212 {sslcadir = strdup(cP->
cadir.c_str());
1213 what2 = "xrd.tlsca to supply 'cadir'.";
1214 }
1215 if (!sslcafile && cP->
cafile.size())
1216 {sslcafile = strdup(cP->
cafile.c_str());
1217 what2 = (what2 ? "xrd.tlsca to supply 'cadir' and 'cafile'."
1218 : "xrd.tlsca to supply 'cafile'.");
1219 }
1221 crlRefIntervalSec = cP->
crlRT;
1222 what3 = "xrd.tlsca to supply 'refresh' interval.";
1223 }
1227 }
1228
1229
1230
1231 if (!(sslcadir || sslcafile))
1232 {const char *what = Configed();
1233 const char *why = (
httpsspec ?
"a cadir or cafile was not specified!"
1234 : "'xrd.tlsca noverify' was specified!");
1235 if (what)
1236 {
eDest.
Say(
"Config failure: ", what,
" cert verification but ", why);
1237 return 1;
1238 }
1239 }
1241
1242
1243
1244 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1245
1246
1247
1248
1249 const char *how = "completed.";
1250 eDest.
Say(
"++++++ HTTPS initialization started.");
1251 if (!InitTLS()) {NoGo = 1; how = "failed.";}
1252 eDest.
Say(
"------ HTTPS initialization ", how);
1253 if (NoGo) return NoGo;
1254
1255
1256
1257 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv)) return 1;
1258
1259
1260
1261 return (InitSecurity() ? NoGo : 1);
1262}
1263
1264
1265
1266
1267
1268const char *XrdHttpProtocol::Configed()
1269{
1270 if (secxtractor &&
gridmap)
return "gridmap and secxtractor require";
1271 if (secxtractor) return "secxtractor requires";
1272 if (
gridmap)
return "gridmap requires";
1273 return 0;
1274}
1275
1276
1277
1278
1279
1281
1283
1284 dest = "";
1285 char save;
1286
1287
1288 if (myBuffEnd >= myBuffStart) {
1289 int l = 0;
1290 for (char *p = myBuffStart; p < myBuffEnd; p++) {
1291 l++;
1292 if (*p == '\n') {
1293 save = *(p+1);
1294 *(p+1) = '\0';
1295 dest.
assign(myBuffStart, 0, l-1);
1296 *(p+1) = save;
1297
1298
1299
1300 BuffConsume(l);
1301
1302
1303 return l;
1304 }
1305
1306 }
1307
1308 return 0;
1309 } else {
1310
1311
1312
1313 int l = 0;
1314 for (
char *p = myBuffStart; p < myBuff->
buff + myBuff->
bsize; p++) {
1315 l++;
1316 if ((*p == '\n') || (*p == '\0')) {
1317 save = *(p+1);
1318 *(p+1) = '\0';
1319 dest.
assign(myBuffStart, 0, l-1);
1320 *(p+1) = save;
1321
1322
1323
1324 BuffConsume(l);
1325
1326
1327 return l;
1328 }
1329
1330 }
1331
1332
1333
1334 l = 0;
1335 for (
char *p = myBuff->
buff; p < myBuffEnd; p++) {
1336 l++;
1337 if ((*p == '\n') || (*p == '\0')) {
1338 save = *(p+1);
1339 *(p+1) = '\0';
1340
1341 int l1 = myBuff->
buff + myBuff->
bsize - myBuffStart;
1342
1343 dest.
assign(myBuffStart, 0, l1-1);
1344
1345 BuffConsume(l1);
1346
1347 dest.
insert(myBuffStart, l1, l-1);
1348
1349
1350 BuffConsume(l);
1351
1352 *(p+1) = save;
1353
1354
1355 return l + l1;
1356 }
1357
1358 }
1359
1360
1361
1362 }
1363
1364 return 0;
1365}
1366
1367
1368
1369
1370
1371int XrdHttpProtocol::getDataOneShot(int blen, bool wait) {
1372 int rlen, maxread;
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 maxread = std::min(blen, BuffAvailable());
1387 TRACE(
DEBUG,
"getDataOneShot BuffAvailable: " << BuffAvailable() <<
" maxread: " << maxread);
1388
1389 if (!maxread)
1390 return 2;
1391
1392 if (ishttps) {
1393 int sslavail = maxread;
1394
1395 if (!wait) {
1396 int l = SSL_pending(ssl);
1397 if (l > 0)
1398 sslavail = std::min(maxread, SSL_pending(ssl));
1399 }
1400
1401 if (sslavail < 0) {
1403 ERR_print_errors(sslbio_err);
1404 return -1;
1405 }
1406
1407 TRACE(
DEBUG,
"getDataOneShot sslavail: " << sslavail);
1408 if (sslavail <= 0) return 0;
1409
1410 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1412 myBuffEnd = myBuff->
buff;
1413 }
1414
1415 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1416 if (rlen <= 0) {
1418 ERR_print_errors(sslbio_err);
1419 return -1;
1420 }
1421
1422
1423 } else {
1424
1425 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1427 myBuffEnd = myBuff->
buff;
1428 }
1429
1430 if (wait)
1432 else
1433 rlen =
Link->
Recv(myBuffEnd, maxread);
1434
1435
1436 if (rlen == 0) {
1438 return -1;
1439 }
1440
1441 if (rlen < 0) {
1443 return -1;
1444 }
1445 }
1446
1447 myBuffEnd += rlen;
1448
1449 TRACE(REQ,
"read " << rlen <<
" of " << blen <<
" bytes");
1450
1451 return 0;
1452}
1453
1455
1456int XrdHttpProtocol::BuffAvailable() {
1457 int r;
1458
1459 if (myBuffEnd >= myBuffStart)
1460 r = myBuff->
buff + myBuff->
bsize - myBuffEnd;
1461 else
1462 r = myBuffStart - myBuffEnd;
1463
1464 if ((r < 0) || (r > myBuff->
bsize)) {
1465 TRACE(REQ,
"internal error, myBuffAvailable: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1466 abort();
1467 }
1468
1469 return r;
1470}
1471
1472
1473
1474
1475
1477
1478int XrdHttpProtocol::BuffUsed() {
1479 int r;
1480
1481 if (myBuffEnd >= myBuffStart)
1482 r = myBuffEnd - myBuffStart;
1483 else
1484
1485 r = myBuff->
bsize - (myBuffStart - myBuffEnd);
1486
1487 if ((r < 0) || (r > myBuff->
bsize)) {
1488 TRACE(REQ,
"internal error, myBuffUsed: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1489 abort();
1490 }
1491
1492 return r;
1493}
1494
1495
1496
1497
1498
1500
1501int XrdHttpProtocol::BuffFree() {
1502 return (myBuff->
bsize - BuffUsed());
1503}
1504
1505
1506
1507
1508
1509void XrdHttpProtocol::BuffConsume(int blen) {
1510
1511 if (blen > myBuff->
bsize) {
1512 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") smaller than buffsize");
1513 abort();
1514 }
1515
1516 if (blen > BuffUsed()) {
1517 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") larger than BuffUsed:" << BuffUsed());
1518 abort();
1519 }
1520
1521 myBuffStart = myBuffStart + blen;
1522
1523 if (myBuffStart >= myBuff->
buff + myBuff->
bsize)
1524 myBuffStart -= myBuff->
bsize;
1525
1526 if (myBuffEnd >= myBuff->
buff + myBuff->
bsize)
1527 myBuffEnd -= myBuff->
bsize;
1528
1529 if (BuffUsed() == 0)
1530 myBuffStart = myBuffEnd = myBuff->
buff;
1531}
1532
1533
1534
1535
1536
1545int XrdHttpProtocol::BuffgetData(int blen, char **data, bool wait) {
1546 int rlen;
1547
1548 TRACE(
DEBUG,
"BuffgetData: requested " << blen <<
" bytes");
1549
1550
1551 if (wait) {
1552
1553 if (blen > BuffUsed()) {
1554 TRACE(REQ,
"BuffgetData: need to read " << blen - BuffUsed() <<
" bytes");
1555 if ( getDataOneShot(blen - BuffUsed(), true) )
1556
1557 return 0;
1558 }
1559 } else {
1560
1561 if ( !BuffUsed() ) {
1562 if ( getDataOneShot(blen, false) )
1563
1564 return -1;
1565 }
1566 }
1567
1568
1569
1570 if (myBuffStart <= myBuffEnd) {
1571 rlen = std::min( (long) blen, (long)(myBuffEnd - myBuffStart) );
1572
1573 } else
1574 rlen = std::min( (
long) blen, (
long)(myBuff->
buff + myBuff->
bsize - myBuffStart) );
1575
1576 *data = myBuffStart;
1577 BuffConsume(rlen);
1578 return rlen;
1579}
1580
1581
1582
1583
1584
1586
1587int XrdHttpProtocol::SendData(const char *body, int bodylen) {
1588
1589 int r;
1590
1591 if (body && bodylen) {
1592 TRACE(REQ,
"Sending " << bodylen <<
" bytes");
1593 if (ishttps) {
1594 r = SSL_write(ssl, body, bodylen);
1595 if (r <= 0) {
1596 ERR_print_errors(sslbio_err);
1597 return -1;
1598 }
1599
1600 } else {
1602 if (r <= 0) return -1;
1603 }
1604 }
1605
1606 return 0;
1607}
1608
1609
1610
1611
1612
1613int XrdHttpProtocol::StartSimpleResp(int code, const char *desc,
1614 const char *header_to_add,
1615 long long bodylen, bool keepalive) {
1616 static const std::unordered_map<int, std::string> statusTexts = {
1617 {100, "Continue"},
1618 {200, "OK"},
1619 {201, "Created"},
1620 {206, "Partial Content"},
1621 {302, "Redirect"},
1622 {307, "Temporary Redirect"},
1623 {400, "Bad Request"},
1624 {401, "Unauthorized"},
1625 {403, "Forbidden"},
1626 {404, "Not Found"},
1627 {405, "Method Not Allowed"},
1628 {409, "Conflict"},
1629 {416, "Range Not Satisfiable"},
1630 {423, "Locked"},
1631 {500, "Internal Server Error"},
1632 {502, "Bad Gateway"},
1633 {504, "Gateway Timeout"},
1634 {507, "Insufficient Storage"}};
1635
1636 std::stringstream ss;
1637 const std::string crlf = "\r\n";
1638
1639 ss << "HTTP/1.1 " << code << " ";
1640
1641 if (desc) {
1642 ss << desc;
1643 } else {
1644 auto it = statusTexts.find(code);
1645 if (it != statusTexts.end()) {
1646 ss << it->second;
1647 } else {
1648 ss << "Unknown";
1649 }
1650 }
1651 ss << crlf;
1652
1653 if (keepalive && (code != 100))
1654 ss << "Connection: Keep-Alive" << crlf;
1655 else
1656 ss << "Connection: Close" << crlf;
1657
1658 ss << "Server: XrootD/" << XrdVSTRING << crlf;
1659
1662 ss << iter->second;
1663 } else {
1665 }
1666
1669 if(corsAllowOrigin) {
1670 ss << *corsAllowOrigin << crlf;
1671 }
1672 }
1673
1674 if ((bodylen >= 0) && (code != 100))
1675 ss << "Content-Length: " << bodylen << crlf;
1676
1677 if (header_to_add && (header_to_add[0] != '\0')) ss << header_to_add << crlf;
1678
1679 ss << crlf;
1680
1681 const std::string &outhdr = ss.str();
1682 TRACEI(RSP,
"Sending resp: " << code <<
" header len:" << outhdr.size());
1683 if (SendData(outhdr.c_str(), outhdr.size()))
1684 return -1;
1685
1686 return 0;
1687}
1688
1689
1690
1691
1692
1693int XrdHttpProtocol::StartChunkedResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1694 const std::string crlf = "\r\n";
1695 std::stringstream ss;
1696
1697 if (header_to_add && (header_to_add[0] != '\0')) {
1698 ss << header_to_add << crlf;
1699 }
1700
1701 ss << "Transfer-Encoding: chunked";
1702 TRACEI(RSP,
"Starting chunked response");
1703 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1704}
1705
1706
1707
1708
1709
1710int XrdHttpProtocol::ChunkResp(const char *body, long long bodylen) {
1711 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1712 if (ChunkRespHeader(content_length))
1713 return -1;
1714
1715 if (body && SendData(body, content_length))
1716 return -1;
1717
1718 return ChunkRespFooter();
1719}
1720
1721
1722
1723
1724
1725int XrdHttpProtocol::ChunkRespHeader(long long bodylen) {
1726 const std::string crlf = "\r\n";
1727 std::stringstream ss;
1728
1729 ss << std::hex << bodylen << std::dec << crlf;
1730
1731 const std::string &chunkhdr = ss.str();
1732 TRACEI(RSP,
"Sending encoded chunk of size " << bodylen);
1733 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1734}
1735
1736
1737
1738
1739
1740int XrdHttpProtocol::ChunkRespFooter() {
1741 const std::string crlf = "\r\n";
1742 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1743}
1744
1745
1746
1747
1748
1752
1753int XrdHttpProtocol::SendSimpleResp(int code, const char *desc, const char *header_to_add, const char *body, long long bodylen, bool keepalive) {
1754
1755 long long content_length = bodylen;
1756 if (bodylen <= 0) {
1757 content_length = body ? strlen(body) : 0;
1758 }
1759
1760 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1761 return -1;
1762
1763
1764
1765
1766 if (body)
1767 return SendData(body, content_length);
1768
1769 return 0;
1770}
1771
1772
1773
1774
1775
1777
1778
1779
1780
1781
1782
1783
1784
1785 char *rdf;
1786
1787
1788
1791
1795
1797
1798
1799
1801
1802 {
1803 char buf[16];
1804 sprintf(buf,
"%d",
Port);
1806 }
1807
1808
1809
1810 rdf = (parms && *parms ? parms : pi->
ConfigFN);
1811 if (rdf && Config(rdf, pi->
theEnv))
return 0;
1813
1814
1816 if ((rdf = getenv("XRDROLE"))) {
1818
1819 if (!strcasecmp(rdf, "manager") || !strcasecmp(rdf, "supervisor")) {
1821 eDest.
Emsg(
"Config",
"Configured as HTTP(s) redirector.");
1822 } else {
1823
1824 eDest.
Emsg(
"Config",
"Configured as HTTP(s) data server.");
1825 }
1826
1827 } else {
1828 eDest.
Emsg(
"Config",
"No XRDROLE specified.");
1829 }
1830
1831
1832
1836
1837
1838
1839
1840 return 1;
1841}
1842
1843
1844
1845
1847 char *val, keybuf[1024], parmbuf[1024];
1848 char *parm;
1849
1850
1852 if (!val || !val[0]) {
1853 err.
Emsg(
"Config",
"No headerkey specified.");
1854 return 1;
1855 } else {
1856
1857
1858 while ( *val && !isalnum(*val) ) val++;
1859 strcpy(keybuf, val);
1860
1861
1862 char *pp;
1863 pp = keybuf + strlen(keybuf) - 1;
1864 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1865 *pp = '\0';
1866 pp--;
1867 }
1868
1870
1871
1872 if(!parm || !parm[0]) {
1873 err.
Emsg(
"Config",
"No header2cgi value specified. key: '", keybuf,
"'");
1874 return 1;
1875 }
1876
1877
1878 while ( *parm && !isalnum(*parm) ) parm++;
1879 strcpy(parmbuf, parm);
1880
1881
1882 pp = parmbuf + strlen(parmbuf) - 1;
1883 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1884 *pp = '\0';
1885 pp--;
1886 }
1887
1888
1889 try {
1890 header2cgi[keybuf] = parmbuf;
1891 } catch ( ... ) {
1892 err.
Emsg(
"Config",
"Can't insert new header2cgi rule. key: '", keybuf,
"'");
1893 return 1;
1894 }
1895
1896 }
1897 return 0;
1898}
1899
1900
1901
1902
1903
1904
1905bool XrdHttpProtocol::InitTLS() {
1906
1910
1911
1912
1915
1918
1919
1920
1923 return false;
1924 }
1925
1926
1927
1928
1929
1930 static const char *sess_ctx_id = "XrdHTTPSessionCtx";
1931 unsigned int n =(unsigned int)(strlen(sess_ctx_id)+1);
1933
1934
1935
1937 {
eDest.
Say(
"Config failure: ",
"Unable to set allowable https ciphers!");
1938 return false;
1939 }
1940
1941
1943
1944
1945
1946 return true;
1947}
1948
1949
1950
1951
1952
1953void XrdHttpProtocol::Cleanup() {
1954
1955 TRACE(ALL,
" Cleanup");
1956
1957 if (
BPool && myBuff) {
1958 BuffConsume(BuffUsed());
1960 myBuff = 0;
1961 }
1962
1963 if (ssl) {
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973 int ret = SSL_shutdown(ssl);
1974 if (ret != 1) {
1975 if(ret == 0) {
1976
1977 ret = SSL_shutdown(ssl);
1978 if (ret != 1) {
1979 TRACE(ALL,
"SSL server failed to receive the SSL shutdown message from the client");
1980 ERR_print_errors(sslbio_err);
1981 }
1982 } else {
1983
1984 TRACE(ALL,
"SSL server failed to send the shutdown message to the client");
1985 ERR_print_errors(sslbio_err);
1986 }
1987 }
1988
1989 if (secxtractor)
1991
1992 SSL_free(ssl);
1993
1994 }
1995
1996
1997 ssl = 0;
1998 sbio = 0;
1999
2008
2010
2013}
2014
2015
2016
2017
2018
2019void XrdHttpProtocol::Reset() {
2020
2021 TRACE(ALL,
" Reset");
2025
2026 if (myBuff) {
2028 myBuff = 0;
2029 }
2030 myBuffStart = myBuffEnd = 0;
2031
2032 DoingLogin = false;
2033 DoneSetInfo = false;
2034
2035 ResumeBytes = 0;
2036 Resume = 0;
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2053 ishttps = false;
2054 ssldone = false;
2055
2057 ssl = 0;
2058 sbio = 0;
2059
2060}
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077int XrdHttpProtocol::xhttpsmode(
XrdOucStream & Config) {
2078 char *val;
2079
2080
2081
2083 if (!val || !val[0]) {
2084 eDest.
Emsg(
"Config",
"httpsmode parameter not specified");
2085 return 1;
2086 }
2087
2088
2089
2093 else {
eDest.
Emsg(
"Config",
"invalid httpsmode parameter - ", val);
2094 return 1;
2095 }
2096 return 0;
2097}
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112int XrdHttpProtocol::xsslverifydepth(
XrdOucStream & Config) {
2113 char *val;
2114
2115
2116
2118 if (!val || !val[0]) {
2119 eDest.
Emsg(
"Config",
"sslverifydepth value not specified");
2120 return 1;
2121 }
2122
2123
2124
2126
2128 return 0;
2129}
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2145 char *val;
2146
2147
2148
2150 if (!val || !val[0]) {
2151 eDest.
Emsg(
"Config",
"HTTP X509 certificate not specified");
2152 return 1;
2153 }
2154
2155
2156
2159
2160
2161
2163 return 0;
2164}
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2180 char *val;
2181
2182
2183
2185 if (!val || !val[0]) {
2186 eDest.
Emsg(
"Config",
"HTTP X509 key not specified");
2187 return 1;
2188 }
2189
2190
2191
2194
2196 return 0;
2197}
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2217 char *val;
2218
2219
2220
2222 if (!val || !val[0]) {
2223 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file location not specified");
2224 return 1;
2225 }
2226
2227
2228
2229 if (!strncmp(val, "required", 8)) {
2232
2233 if (!val || !val[0]) {
2234 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after [required] "
2235 "parameter");
2236 return 1;
2237 }
2238 }
2239
2240
2241
2242 if (!strcmp(val, "compatNameGeneration")) {
2245 if (!val || !val[0]) {
2246 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after "
2247 "[compatNameGeneration] parameter");
2248 return 1;
2249 }
2250 }
2251
2252
2253
2254
2257 return 0;
2258}
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273int XrdHttpProtocol::xsslcafile(
XrdOucStream & Config) {
2274 char *val;
2275
2276
2277
2279 if (!val || !val[0]) {
2280 eDest.
Emsg(
"Config",
"HTTP X509 CAfile not specified");
2281 return 1;
2282 }
2283
2284
2285
2288
2290 return 0;
2291}
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306int XrdHttpProtocol::xsecretkey(
XrdOucStream & Config) {
2307 char *val;
2308 bool inFile = false;
2309
2310
2311
2313 if (!val || !val[0]) {
2314 eDest.
Emsg(
"Config",
"Shared secret key not specified");
2315 return 1;
2316 }
2317
2318
2319
2320
2321
2322 if (val[0] == '/') {
2324 inFile = true;
2325 int fd =
open(val, O_RDONLY);
2326
2327 if ( fd == -1 ) {
2328 eDest.
Emsg(
"Config", errno,
"open shared secret key file", val);
2329 return 1;
2330 }
2331
2332 if (
fstat(fd, &st) != 0 ) {
2333 eDest.
Emsg(
"Config", errno,
"fstat shared secret key file", val);
2335 return 1;
2336 }
2337
2338 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2340 "For your own security, the shared secret key file cannot be world readable or group writable '", val, "'");
2342 return 1;
2343 }
2344
2345 FILE *fp = fdopen(fd, "r");
2346
2347 if ( fp == nullptr ) {
2348 eDest.
Emsg(
"Config", errno,
"fdopen shared secret key file", val);
2350 return 1;
2351 }
2352
2353 char line[1024];
2354 while( fgets(line, 1024, fp) ) {
2355 char *pp;
2356
2357
2358 pp = line + strlen(line) - 1;
2359 while ( (pp >= line) && (!isalnum(*pp)) ) {
2360 *pp = '\0';
2361 pp--;
2362 }
2363
2364
2365 pp = line;
2366 while ( *pp && !isalnum(*pp) ) pp++;
2367
2368 if ( strlen(pp) >= 32 ) {
2369 eDest.
Say(
"Config",
"Secret key loaded.");
2370
2373
2375 return 0;
2376 }
2377
2378 }
2379
2381 eDest.
Emsg(
"Config",
"Cannot find useful secretkey in file '", val,
"'");
2382 return 1;
2383
2384 }
2385
2386 if ( strlen(val) < 32 ) {
2387 eDest.
Emsg(
"Config",
"Secret key is too short");
2388 return 1;
2389 }
2390
2391
2394 if (!inFile)
Config.noEcho();
2395
2396 return 0;
2397}
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2413 char *val;
2414
2415
2416
2418 if (!val || !val[0]) {
2419 eDest.
Emsg(
"Config",
"listingdeny flag not specified");
2420 return 1;
2421 }
2422
2423
2424
2425 listdeny = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2426
2427
2428 return 0;
2429}
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444int XrdHttpProtocol::xlistredir(
XrdOucStream & Config) {
2445 char *val;
2446
2447
2448
2450 if (!val || !val[0]) {
2451 eDest.
Emsg(
"Config",
"listingredir flag not specified");
2452 return 1;
2453 }
2454
2455
2456
2459
2460
2461 return 0;
2462}
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477int XrdHttpProtocol::xdesthttps(
XrdOucStream & Config) {
2478 char *val;
2479
2480
2481
2483 if (!val || !val[0]) {
2484 eDest.
Emsg(
"Config",
"desthttps flag not specified");
2485 return 1;
2486 }
2487
2488
2489
2490 isdesthttps = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2491
2492
2493 return 0;
2494}
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509int XrdHttpProtocol::xembeddedstatic(
XrdOucStream & Config) {
2510 char *val;
2511
2512
2513
2515 if (!val || !val[0]) {
2516 eDest.
Emsg(
"Config",
"embeddedstatic flag not specified");
2517 return 1;
2518 }
2519
2520
2521
2522 embeddedstatic = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2523
2524
2525 return 0;
2526}
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541int XrdHttpProtocol::xstaticredir(
XrdOucStream & Config) {
2542 char *val;
2543
2544
2545
2547 if (!val || !val[0]) {
2548 eDest.
Emsg(
"Config",
"staticredir url not specified");
2549 return 1;
2550 }
2551
2552
2553
2556
2557 return 0;
2558}
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576int XrdHttpProtocol::xstaticpreload(
XrdOucStream & Config) {
2577 char *val, *k, key[1024];
2578
2579
2580
2582 if (!k || !k[0]) {
2583 eDest.
Emsg(
"Config",
"preloadstatic urlpath not specified");
2584 return 1;
2585 }
2586
2587 strcpy(key, k);
2588
2589
2590
2592 if (!val || !val[0]) {
2593 eDest.
Emsg(
"Config",
"preloadstatic filename not specified");
2594 return 1;
2595 }
2596
2597
2598 int fp =
open(val, O_RDONLY);
2599 if( fp < 0 ) {
2600 eDest.
Emsg(
"Config", errno,
"open preloadstatic filename", val);
2601 return 1;
2602 }
2603
2604 StaticPreloadInfo *nfo = new StaticPreloadInfo;
2605
2606 nfo->data = (char *)malloc(65536);
2607 nfo->len =
read(fp, (
void *)nfo->data, 65536);
2609
2610 if (nfo->len <= 0) {
2611 eDest.
Emsg(
"Config", errno,
"read from preloadstatic filename", val);
2612 return 1;
2613 }
2614
2615 if (nfo->len >= 65536) {
2616 eDest.
Emsg(
"Config",
"Truncated preloadstatic filename. Max is 64 KB '", val,
"'");
2617 return 1;
2618 }
2619
2620
2621
2624
2626 return 0;
2627}
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646int XrdHttpProtocol::xstaticheader(
XrdOucStream & Config) {
2647 auto val =
Config.GetWord();
2648 std::vector<std::string> verbs;
2649 while (true) {
2650 if (!val || !val[0]) {
2651 eDest.
Emsg(
"Config",
"http.staticheader requires the header to be specified");
2652 return 1;
2653 }
2654
2655 std::string match_verb;
2656 std::string_view val_str(val);
2657 if (val_str.substr(0, 6) == "-verb=") {
2658 verbs.emplace_back(val_str.substr(6));
2659 } else if (val_str == "-") {
2660 eDest.
Emsg(
"Config",
"http.staticheader is ignoring unknown flag: ", val_str.data());
2661 } else {
2662 break;
2663 }
2664
2666 }
2667 if (verbs.empty()) {
2668 verbs.emplace_back();
2669 }
2670
2671 std::string header = val;
2672
2674 std::string header_value;
2675 if (val && val[0]) {
2676 header_value = val;
2677 }
2678
2679 for (const auto &verb : verbs) {
2682 if (!header_value.empty())
2684 } else if (header_value.empty()) {
2685 iter->second.clear();
2686 } else {
2687 iter->second.emplace_back(header, header_value);
2688 }
2689 }
2690
2691 return 0;
2692}
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708int XrdHttpProtocol::xselfhttps2http(
XrdOucStream & Config) {
2709 char *val;
2710
2711
2712
2714 if (!val || !val[0]) {
2715 eDest.
Emsg(
"Config",
"selfhttps2http flag not specified");
2716 return 1;
2717 }
2718
2719
2720
2721 selfhttps2http = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2722
2723
2724 return 0;
2725}
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743int XrdHttpProtocol::xsecxtractor(
XrdOucStream& Config) {
2744 char *val;
2745
2746
2747
2749 if (!val || !val[0]) {
2750 eDest.
Emsg(
"Config",
"No security extractor plugin specified.");
2751 return 1;
2752 } else {
2753
2754
2755 if (!strncmp(val, "required", 8)) {
2756 isRequiredXtractor = true;
2758
2759 if (!val || !val[0]) {
2760 eDest.
Emsg(
"Config",
"No security extractor plugin after [required] "
2761 "parameter");
2762 return 1;
2763 }
2764 }
2765
2766 char libName[4096];
2767 strlcpy(libName, val,
sizeof(libName));
2768 libName[sizeof(libName) - 1] = '\0';
2769 char libParms[4096];
2770
2771 if (!
Config.GetRest(libParms, 4095)) {
2772 eDest.
Emsg(
"Config",
"secxtractor config params longer than 4k");
2773 return 1;
2774 }
2775
2776
2777
2778 if (LoadSecXtractor(&
eDest, libName, libParms)) {
2779 return 1;
2780 }
2781 }
2782
2783 return 0;
2784}
2785
2787 char * val;
2788
2790 if (!val || !val[0]) {
2791 eDest.
Emsg(
"Config",
"No CORS plugin specified.");
2792 return 1;
2793 }
2795 return 0;
2796}
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2816 std::vector<extHInfo> &hiVec) {
2817 char *val, path[1024], namebuf[1024];
2818 char *parm;
2819
2820 bool noTlsOK = false;
2821
2822
2823
2825 if (!val || !val[0]) {
2826 eDest.
Emsg(
"Config",
"No instance name specified for an http external handler plugin.");
2827 return 1;
2828 }
2829 if (strlen(val) >= 16) {
2830 eDest.
Emsg(
"Config",
"Instance name too long for an http external handler plugin.");
2831 return 1;
2832 }
2833 strncpy(namebuf, val, sizeof(namebuf));
2834 namebuf[ sizeof(namebuf)-1 ] = '\0';
2835
2836
2838
2839 if(val && !strcmp("+notls",val)) {
2840 noTlsOK = true;
2842 }
2843
2844
2845
2846 if (!val || !val[0]) {
2847 eDest.
Emsg(
"Config",
"No http external handler plugin specified.");
2848 return 1;
2849 }
2850 if (strlen(val) >= (int)sizeof(path)) {
2851 eDest.
Emsg(
"Config",
"Path too long for an http external handler plugin.");
2852 return 1;
2853 }
2854
2855 strcpy(path, val);
2856
2857
2858
2860
2861
2862
2863 for (int i = 0; i < (int)hiVec.size(); i++)
2864 {if (hiVec[i].extHName == namebuf) {
2865 eDest.
Emsg(
"Config",
"Instance name already present for "
2866 "http external handler plugin",
2867 hiVec[i].extHPath.c_str());
2868 return 1;
2869 }
2870 }
2871
2872
2873
2875 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
2876 return 1;
2877 }
2878
2879
2880
2881 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm : ""), noTlsOK));
2882
2883 return 0;
2884}
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902int XrdHttpProtocol::xheader2cgi(
XrdOucStream & Config) {
2904}
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2920 char *val;
2921
2922
2923
2925 if (!val || !val[0]) {
2926 eDest.
Emsg(
"Config",
"HTTP X509 CAdir not specified");
2927 return 1;
2928 }
2929
2930
2931
2934
2936 return 0;
2937}
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953int XrdHttpProtocol::xsslcipherfilter(
XrdOucStream & Config) {
2954 char *val;
2955
2956
2957
2959 if (!val || !val[0]) {
2960 eDest.
Emsg(
"Config",
"SSL cipherlist filter string not specified");
2961 return 1;
2962 }
2963
2964
2965
2968
2969 return 0;
2970}
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2984
2985 char *val;
2986
2987
2988
2990 if (!val || !val[0])
2991 {
eDest.
Emsg(
"Config",
"tlsreuse argument not specified");
return 1;}
2992
2993
2994
2995 if (!strcmp(val, "off"))
2997 return 0;
2998 }
2999
3000
3001
3002 if (!strcmp(val, "on"))
3004 return 0;
3005 }
3006
3007
3008
3009 eDest.
Emsg(
"config",
"invalid tlsreuse parameter -", val);
3010 return 1;
3011}
3012
3013int XrdHttpProtocol::xtlsclientauth(
XrdOucStream &Config) {
3014 auto val =
Config.GetWord();
3015 if (!val || !val[0])
3016 {
eDest.
Emsg(
"Config",
"tlsclientauth argument not specified");
return 1;}
3017
3018 if (!strcmp(val, "off"))
3020 return 0;
3021 }
3022 if (!strcmp(val, "on"))
3024 return 0;
3025 }
3026
3027 eDest.
Emsg(
"config",
"invalid tlsclientauth parameter -", val);
3028 return 1;
3029}
3030
3032 char *val =
Config.GetWord();
3033 if(val) {
3034 if(!strcmp("tpc",val)) {
3035 if(!(val =
Config.GetWord())) {
3036 eDest.
Emsg(
"Config",
"http.auth tpc value not specified.");
return 1;
3037 } else {
3038 if(!strcmp("fcreds",val)) {
3040 } else {
3041 eDest.
Emsg(
"Config",
"http.auth tpc value is invalid");
return 1;
3042 }
3043 }
3044 } else {
3045 eDest.
Emsg(
"Config",
"http.auth value is invalid");
return 1;
3046 }
3047 }
3048 return 0;
3049}
3050
3052 char *val =
Config.GetWord();
3053 if(val) {
3054 int maxdelay;
3057 } else {
3058 eDest.
Emsg(
"Config",
"http.maxdelay requires an argument in seconds (default is 30). Example: http.maxdelay 30");
3059 return 1;
3060 }
3061 return 0;
3062}
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3079
3080 char *val;
3081
3082 static struct traceopts {
3083 const char *opname;
3084 int opval;
3085 } tropts[] = {
3093 };
3094 int i, neg, trval = 0, numopts = sizeof (tropts) / sizeof (struct traceopts);
3095
3096 if (!(val =
Config.GetWord())) {
3097 eDest.
Emsg(
"config",
"trace option not specified");
3098 return 1;
3099 }
3100 while (val) {
3101 if (!strcmp(val, "off")) trval = 0;
3102 else {
3103 if ((neg = (val[0] == '-' && val[1]))) val++;
3104 for (i = 0; i < numopts; i++) {
3105 if (!strcmp(val, tropts[i].opname)) {
3106 if (neg) trval &= ~tropts[i].opval;
3107 else trval |= tropts[i].opval;
3108 break;
3109 }
3110 }
3111 if (i >= numopts)
3112 eDest.
Emsg(
"config",
"invalid trace option", val);
3113 }
3115 }
3117 return 0;
3118}
3119
3121 int l;
3122 bool b;
3126
3131 l = strlen(fname) + 1;
3133
3136 if (!b) {
3137 return -1;
3138 }
3139
3140
3141 return 0;
3142}
3143
3144
3145
3146
3147
3149 size_t length;
3156 length = fname.
length() + 1;
3158
3160
3162}
3163
3164
3165static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION);
3166
3167
3168int XrdHttpProtocol::LoadSecXtractor(
XrdSysError *myeDest,
const char *libName,
3169 const char *libParms) {
3170
3171
3172
3173 if (secxtractor) return 1;
3174
3175 XrdOucPinLoader myLib(myeDest, &compiledVer,
"secxtractorlib", libName);
3177
3178
3179
3181 if (ep && (secxtractor = ep(myeDest, NULL, libParms))) return 0;
3182 myLib.Unload();
3183 return 1;
3184}
3185
3186
3187
3188
3189int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec,
const char *cFN,
XrdOucEnv &myEnv) {
3190 for (int i = 0; i < (int) hiVec.size(); i++) {
3191 if(hiVec[i].extHNoTlsOK) {
3192
3193 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3194 hiVec[i].extHParm.c_str(), &myEnv,
3195 hiVec[i].extHName.c_str()))
3196 return 1;
3197 }
3198 }
3199 return 0;
3200}
3201
3202int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
3204
3205
3206
3211
3212
3213
3214 for (int i = 0; i < (int)hiVec.size(); i++) {
3215
3216
3217 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3218 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3219 hiVec[i].extHParm.c_str(), &myEnv,
3220 hiVec[i].extHName.c_str())) return 1;
3221 }
3222 }
3223 return 0;
3224}
3225
3226
3227int XrdHttpProtocol::LoadExtHandler(
XrdSysError *myeDest,
const char *libName,
3228 const char *configFN, const char *libParms,
3229 XrdOucEnv *myEnv,
const char *instName) {
3230
3231
3232
3233 if (ExtHandlerLoaded(instName)) {
3234 eDest.
Emsg(
"Config",
"Instance name already present for an http external handler plugin.");
3235 return 1;
3236 }
3238 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
3239 return 1;
3240 }
3241
3242 XrdOucPinLoader myLib(myeDest, &compiledVer,
"exthandlerlib", libName);
3244
3245
3246
3248
3250 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3251
3252
3253 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3254 exthandler[exthandlercnt].name[15] = '\0';
3255 exthandler[exthandlercnt++].ptr = newhandler;
3256
3257 return 0;
3258 }
3259
3260 myLib.Unload();
3261 return 1;
3262}
3263
3264
3265int XrdHttpProtocol::LoadCorsHandler(
XrdSysError *
eDest,
const char *libname) {
3270 if(ep && (
xrdcors = ep()))
return 0;
3271 corsLib.Unload();
3272 return 1;
3273}
3274
3275
3276
3277bool XrdHttpProtocol::ExtHandlerLoaded(const char *handlername) {
3278 for (int i = 0; i < exthandlercnt; i++) {
3279 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3280 return true;
3281 }
3282 }
3283 return false;
3284}
3285
3286
3287
3289
3290 for (int i = 0; i < exthandlercnt; i++) {
3292 return exthandler[i].ptr;
3293 }
3294 }
3295 return NULL;
3296}
struct ClientQueryRequest query
struct ClientStatRequest stat
#define XrdHttpCorsGetHandlerArgs
#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)
virtual std::optional< std::string > getCORSAllowOriginHeader(const std::string &origin)=0
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 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
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
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
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)
void SetTlsClientAuth(bool setting)
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.