979 {
982 std::vector<extHInfo> extHIVec;
983 char *var;
984 int cfgFD, GoNo, NoGo = 0, ismine;
985
986 var = nullptr;
989
990 pmarkHandle = (
XrdNetPMark* ) myEnv->GetPtr(
"XrdNetPMark*");
991
992 cksumHandler.configure(xrd_cslist);
993 auto nonIanaChecksums = cksumHandler.getNonIANAConfiguredCksums();
994 if(nonIanaChecksums.size()) {
995 std::stringstream warningMsgSS;
996 warningMsgSS << "Config warning: the following checksum algorithms are not IANA compliant: [";
997 std::string unknownCksumString;
998 for(auto unknownCksum: nonIanaChecksums) {
999 unknownCksumString += unknownCksum + ",";
1000 }
1001 unknownCksumString.erase(unknownCksumString.size() - 1);
1002 warningMsgSS << unknownCksumString << "]" << ". They therefore cannot be queried by a user via HTTP." ;
1003 eDest.
Say(warningMsgSS.str().c_str());
1004 }
1005
1006
1007 if (!m_bio_type) {
1008
1009 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1010 m_bio_type = (26|0x0400|0x0100);
1011 m_bio_method = static_cast<BIO_METHOD*>(OPENSSL_malloc(sizeof(BIO_METHOD)));
1012
1013 if (m_bio_method) {
1014 memset(m_bio_method, '\0', sizeof(BIO_METHOD));
1015 m_bio_method->type = m_bio_type;
1021 }
1022 #else
1023
1024
1025 m_bio_type = BIO_get_new_index();
1026 m_bio_method = BIO_meth_new(m_bio_type, "xrdhttp-bio-method");
1027
1028 if (m_bio_method) {
1034 }
1035
1036 #endif
1037 }
1038
1039
1040
1041
1043
1044
1045
1046 if ((cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
1047 return eDest.
Emsg(
"Config", errno,
"open config file", ConfigFN);
1049 static const char *cvec[] = { "*** http protocol config:", 0 };
1051
1052
1053
1054 while ((var =
Config.GetMyFirstWord())) {
1055 if ((ismine = !strncmp("http.", var, 5)) && var[5]) var += 5;
1056
1057 if (ismine) {
1058 if TS_Xeq(
"trace", xtrace);
1059 else if TS_Xeq(
"cert", xsslcert);
1060 else if TS_Xeq(
"key", xsslkey);
1061 else if TS_Xeq(
"cadir", xsslcadir);
1062 else if TS_Xeq(
"cipherfilter", xsslcipherfilter);
1063 else if TS_Xeq(
"gridmap", xgmap);
1064 else if TS_Xeq(
"cafile", xsslcafile);
1065 else if TS_Xeq(
"secretkey", xsecretkey);
1066 else if TS_Xeq(
"desthttps", xdesthttps);
1067 else if TS_Xeq(
"secxtractor", xsecxtractor);
1068 else if TS_Xeq3(
"exthandler", xexthandler);
1069 else if TS_Xeq(
"selfhttps2http", xselfhttps2http);
1070 else if TS_Xeq(
"embeddedstatic", xembeddedstatic);
1071 else if TS_Xeq(
"listingredir", xlistredir);
1072 else if TS_Xeq(
"staticredir", xstaticredir);
1073 else if TS_Xeq(
"staticpreload", xstaticpreload);
1074 else if TS_Xeq(
"listingdeny", xlistdeny);
1075 else if TS_Xeq(
"header2cgi", xheader2cgi);
1076 else if TS_Xeq(
"httpsmode", xhttpsmode);
1077 else if TS_Xeq(
"tlsreuse", xtlsreuse);
1078 else if TS_Xeq(
"auth", xauth);
1079 else {
1080 eDest.
Say(
"Config warning: ignoring unknown directive '", var,
"'.");
1082 continue;
1083 }
1084 if (GoNo) {
1086 NoGo = 1;
1087 }
1088 }
1089 }
1090
1091
1092
1093
1094 if (NoGo)
1095 {
eDest.
Say(
"Config failure: one or more directives are flawed!");
1096 return 1;
1097 }
1098
1099
1100
1101 hdr2cgimap["Cache-Control"] = "cache-control";
1102
1103
1104 if (getenv(
"XRDCL_EC"))
usingEC =
true;
1105
1106
1107
1108
1109
1110
1113 : "was not configured.");
1114 const char *what = Configed();
1115
1116 eDest.
Say(
"Config warning: HTTPS functionality ", why);
1118
1119 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1120 if (what)
1121 {
eDest.
Say(
"Config failure: ", what,
" HTTPS but it ", why);
1122 NoGo = 1;
1123 }
1124 return NoGo;
1125 }
1126
1127
1128
1129
1130 if (sslkey && !sslcert)
1131 {
eDest.
Say(
"Config warning: specifying http.key without http.cert "
1132 "is meaningless; ignoring key!");
1133 free(sslkey); sslkey = 0;
1134 }
1135
1136
1137
1139 {if (!sslcert)
1140 {
eDest.
Say(
"Config failure: 'httpsmode manual' requires atleast a "
1141 "a cert specification!");
1142 return 1;
1143 }
1144 }
1145
1146
1147
1148
1149
1152 const char *what1 = 0, *what2 = 0, *what3 = 0;
1153
1154 if (!sslcert && cP->
cert.size())
1155 {sslcert = strdup(cP->
cert.c_str());
1156 if (cP->
pkey.size()) sslkey = strdup(cP->
pkey.c_str());
1157 what1 = "xrd.tls to supply 'cert' and 'key'.";
1158 }
1159 if (!sslcadir && cP->
cadir.size())
1160 {sslcadir = strdup(cP->
cadir.c_str());
1161 what2 = "xrd.tlsca to supply 'cadir'.";
1162 }
1163 if (!sslcafile && cP->
cafile.size())
1164 {sslcafile = strdup(cP->
cafile.c_str());
1165 what2 = (what2 ? "xrd.tlsca to supply 'cadir' and 'cafile'."
1166 : "xrd.tlsca to supply 'cafile'.");
1167 }
1169 crlRefIntervalSec = cP->
crlRT;
1170 what3 = "xrd.tlsca to supply 'refresh' interval.";
1171 }
1175 }
1176
1177
1178
1179 if (!(sslcadir || sslcafile))
1180 {const char *what = Configed();
1181 const char *why = (
httpsspec ?
"a cadir or cafile was not specified!"
1182 : "'xrd.tlsca noverify' was specified!");
1183 if (what)
1184 {
eDest.
Say(
"Config failure: ", what,
" cert verification but ", why);
1185 return 1;
1186 }
1187 }
1189
1190
1191
1192 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1193
1194
1195
1196
1197 const char *how = "completed.";
1198 eDest.
Say(
"++++++ HTTPS initialization started.");
1199 if (!InitTLS()) {NoGo = 1; how = "failed.";}
1200 eDest.
Say(
"------ HTTPS initialization ", how);
1201 if (NoGo) return NoGo;
1202
1203
1204
1205 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv)) return 1;
1206
1207
1208
1209 return (InitSecurity() ? NoGo : 1);
1210}
1211
1212
1213
1214
1215
1216const char *XrdHttpProtocol::Configed()
1217{
1218 if (secxtractor &&
gridmap)
return "gridmap and secxtractor require";
1219 if (secxtractor) return "secxtractor requires";
1220 if (
gridmap)
return "gridmap requires";
1221 return 0;
1222}
1223
1224
1225
1226
1227
1229
1231
1232 dest = "";
1233 char save;
1234
1235
1236 if (myBuffEnd >= myBuffStart) {
1237 int l = 0;
1238 for (char *p = myBuffStart; p < myBuffEnd; p++) {
1239 l++;
1240 if (*p == '\n') {
1241 save = *(p+1);
1242 *(p+1) = '\0';
1243 dest.
assign(myBuffStart, 0, l-1);
1244 *(p+1) = save;
1245
1246
1247
1248 BuffConsume(l);
1249
1250
1251 return l;
1252 }
1253
1254 }
1255
1256 return 0;
1257 } else {
1258
1259
1260
1261 int l = 0;
1262 for (
char *p = myBuffStart; p < myBuff->
buff + myBuff->
bsize; p++) {
1263 l++;
1264 if ((*p == '\n') || (*p == '\0')) {
1265 save = *(p+1);
1266 *(p+1) = '\0';
1267 dest.
assign(myBuffStart, 0, l-1);
1268 *(p+1) = save;
1269
1270
1271
1272 BuffConsume(l);
1273
1274
1275 return l;
1276 }
1277
1278 }
1279
1280
1281
1282 l = 0;
1283 for (
char *p = myBuff->
buff; p < myBuffEnd; p++) {
1284 l++;
1285 if ((*p == '\n') || (*p == '\0')) {
1286 save = *(p+1);
1287 *(p+1) = '\0';
1288
1289 int l1 = myBuff->
buff + myBuff->
bsize - myBuffStart;
1290
1291 dest.
assign(myBuffStart, 0, l1-1);
1292
1293 BuffConsume(l1);
1294
1295 dest.
insert(myBuffStart, l1, l-1);
1296
1297
1298 BuffConsume(l);
1299
1300 *(p+1) = save;
1301
1302
1303 return l + l1;
1304 }
1305
1306 }
1307
1308
1309
1310 }
1311
1312 return 0;
1313}
1314
1315
1316
1317
1318
1319int XrdHttpProtocol::getDataOneShot(int blen, bool wait) {
1320 int rlen, maxread;
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334 maxread = std::min(blen, BuffAvailable());
1335 TRACE(
DEBUG,
"getDataOneShot BuffAvailable: " << BuffAvailable() <<
" maxread: " << maxread);
1336
1337 if (!maxread)
1338 return 2;
1339
1340 if (ishttps) {
1341 int sslavail = maxread;
1342
1343 if (!wait) {
1344 int l = SSL_pending(ssl);
1345 if (l > 0)
1346 sslavail = std::min(maxread, SSL_pending(ssl));
1347 }
1348
1349 if (sslavail < 0) {
1351 ERR_print_errors(sslbio_err);
1352 return -1;
1353 }
1354
1355 TRACE(
DEBUG,
"getDataOneShot sslavail: " << sslavail);
1356 if (sslavail <= 0) return 0;
1357
1358 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1360 myBuffEnd = myBuff->
buff;
1361 }
1362
1363 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1364 if (rlen <= 0) {
1366 ERR_print_errors(sslbio_err);
1367 return -1;
1368 }
1369
1370
1371 } else {
1372
1373 if (myBuffEnd - myBuff->
buff >= myBuff->
bsize) {
1375 myBuffEnd = myBuff->
buff;
1376 }
1377
1378 if (wait)
1380 else
1381 rlen =
Link->
Recv(myBuffEnd, maxread);
1382
1383
1384 if (rlen == 0) {
1386 return -1;
1387 }
1388
1389 if (rlen < 0) {
1391 return -1;
1392 }
1393 }
1394
1395 myBuffEnd += rlen;
1396
1397 TRACE(REQ,
"read " << rlen <<
" of " << blen <<
" bytes");
1398
1399 return 0;
1400}
1401
1403
1404int XrdHttpProtocol::BuffAvailable() {
1405 int r;
1406
1407 if (myBuffEnd >= myBuffStart)
1408 r = myBuff->
buff + myBuff->
bsize - myBuffEnd;
1409 else
1410 r = myBuffStart - myBuffEnd;
1411
1412 if ((r < 0) || (r > myBuff->
bsize)) {
1413 TRACE(REQ,
"internal error, myBuffAvailable: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1414 abort();
1415 }
1416
1417 return r;
1418}
1419
1420
1421
1422
1423
1425
1426int XrdHttpProtocol::BuffUsed() {
1427 int r;
1428
1429 if (myBuffEnd >= myBuffStart)
1430 r = myBuffEnd - myBuffStart;
1431 else
1432
1433 r = myBuff->
bsize - (myBuffStart - myBuffEnd);
1434
1435 if ((r < 0) || (r > myBuff->
bsize)) {
1436 TRACE(REQ,
"internal error, myBuffUsed: " << r <<
" myBuff->bsize " << myBuff->
bsize);
1437 abort();
1438 }
1439
1440 return r;
1441}
1442
1443
1444
1445
1446
1448
1449int XrdHttpProtocol::BuffFree() {
1450 return (myBuff->
bsize - BuffUsed());
1451}
1452
1453
1454
1455
1456
1457void XrdHttpProtocol::BuffConsume(int blen) {
1458
1459 if (blen > myBuff->
bsize) {
1460 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") smaller than buffsize");
1461 abort();
1462 }
1463
1464 if (blen > BuffUsed()) {
1465 TRACE(REQ,
"internal error, BuffConsume(" << blen <<
") larger than BuffUsed:" << BuffUsed());
1466 abort();
1467 }
1468
1469 myBuffStart = myBuffStart + blen;
1470
1471 if (myBuffStart >= myBuff->
buff + myBuff->
bsize)
1472 myBuffStart -= myBuff->
bsize;
1473
1474 if (myBuffEnd >= myBuff->
buff + myBuff->
bsize)
1475 myBuffEnd -= myBuff->
bsize;
1476
1477 if (BuffUsed() == 0)
1478 myBuffStart = myBuffEnd = myBuff->
buff;
1479}
1480
1481
1482
1483
1484
1493int XrdHttpProtocol::BuffgetData(int blen, char **data, bool wait) {
1494 int rlen;
1495
1496 TRACE(
DEBUG,
"BuffgetData: requested " << blen <<
" bytes");
1497
1498
1499 if (wait) {
1500
1501 if (blen > BuffUsed()) {
1502 TRACE(REQ,
"BuffgetData: need to read " << blen - BuffUsed() <<
" bytes");
1503 if ( getDataOneShot(blen - BuffUsed(), true) )
1504
1505 return 0;
1506 }
1507 } else {
1508
1509 if ( !BuffUsed() ) {
1510 if ( getDataOneShot(blen, false) )
1511
1512 return -1;
1513 }
1514 }
1515
1516
1517
1518 if (myBuffStart <= myBuffEnd) {
1519 rlen = std::min( (long) blen, (long)(myBuffEnd - myBuffStart) );
1520
1521 } else
1522 rlen = std::min( (
long) blen, (
long)(myBuff->
buff + myBuff->
bsize - myBuffStart) );
1523
1524 *data = myBuffStart;
1525 BuffConsume(rlen);
1526 return rlen;
1527}
1528
1529
1530
1531
1532
1534
1535int XrdHttpProtocol::SendData(const char *body, int bodylen) {
1536
1537 int r;
1538
1539 if (body && bodylen) {
1540 TRACE(REQ,
"Sending " << bodylen <<
" bytes");
1541 if (ishttps) {
1542 r = SSL_write(ssl, body, bodylen);
1543 if (r <= 0) {
1544 ERR_print_errors(sslbio_err);
1545 return -1;
1546 }
1547
1548 } else {
1550 if (r <= 0) return -1;
1551 }
1552 }
1553
1554 return 0;
1555}
1556
1557
1558
1559
1560
1561int XrdHttpProtocol::StartSimpleResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1562 std::stringstream ss;
1563 const std::string crlf = "\r\n";
1564
1565 ss << "HTTP/1.1 " << code << " ";
1566 if (desc) {
1567 ss << desc;
1568 } else {
1569 if (code == 200) ss << "OK";
1570 else if (code == 100) ss << "Continue";
1571 else if (code == 206) ss << "Partial Content";
1572 else if (code == 302) ss << "Redirect";
1573 else if (code == 307) ss << "Temporary Redirect";
1574 else if (code == 400) ss << "Bad Request";
1575 else if (code == 403) ss << "Forbidden";
1576 else if (code == 404) ss << "Not Found";
1577 else if (code == 405) ss << "Method Not Allowed";
1578 else if (code == 416) ss << "Range Not Satisfiable";
1579 else if (code == 500) ss << "Internal Server Error";
1580 else if (code == 504) ss << "Gateway Timeout";
1581 else ss << "Unknown";
1582 }
1583 ss << crlf;
1584 if (keepalive && (code != 100))
1585 ss << "Connection: Keep-Alive" << crlf;
1586 else
1587 ss << "Connection: Close" << crlf;
1588
1589 ss << "Server: XrootD/" << XrdVSTRING << crlf;
1590
1591 if ((bodylen >= 0) && (code != 100))
1592 ss << "Content-Length: " << bodylen << crlf;
1593
1594 if (header_to_add && (header_to_add[0] != '\0'))
1595 ss << header_to_add << crlf;
1596
1597 ss << crlf;
1598
1599 const std::string &outhdr = ss.str();
1600 TRACEI(RSP,
"Sending resp: " << code <<
" header len:" << outhdr.size());
1601 if (SendData(outhdr.c_str(), outhdr.size()))
1602 return -1;
1603
1604 return 0;
1605}
1606
1607
1608
1609
1610
1611int XrdHttpProtocol::StartChunkedResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1612 const std::string crlf = "\r\n";
1613 std::stringstream ss;
1614
1615 if (header_to_add && (header_to_add[0] != '\0')) {
1616 ss << header_to_add << crlf;
1617 }
1618
1619 ss << "Transfer-Encoding: chunked";
1620 TRACEI(RSP,
"Starting chunked response");
1621 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1622}
1623
1624
1625
1626
1627
1628int XrdHttpProtocol::ChunkResp(const char *body, long long bodylen) {
1629 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1630 if (ChunkRespHeader(content_length))
1631 return -1;
1632
1633 if (body && SendData(body, content_length))
1634 return -1;
1635
1636 return ChunkRespFooter();
1637}
1638
1639
1640
1641
1642
1643int XrdHttpProtocol::ChunkRespHeader(long long bodylen) {
1644 const std::string crlf = "\r\n";
1645 std::stringstream ss;
1646
1647 ss << std::hex << bodylen << std::dec << crlf;
1648
1649 const std::string &chunkhdr = ss.str();
1650 TRACEI(RSP,
"Sending encoded chunk of size " << bodylen);
1651 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1652}
1653
1654
1655
1656
1657
1658int XrdHttpProtocol::ChunkRespFooter() {
1659 const std::string crlf = "\r\n";
1660 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1661}
1662
1663
1664
1665
1666
1670
1671int XrdHttpProtocol::SendSimpleResp(int code, const char *desc, const char *header_to_add, const char *body, long long bodylen, bool keepalive) {
1672
1673 long long content_length = bodylen;
1674 if (bodylen <= 0) {
1675 content_length = body ? strlen(body) : 0;
1676 }
1677
1678 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1679 return -1;
1680
1681
1682
1683
1684 if (body)
1685 return SendData(body, content_length);
1686
1687 return 0;
1688}
1689
1690
1691
1692
1693
1695
1696
1697
1698
1699
1700
1701
1702
1703 char *rdf;
1704
1705
1706
1709
1713
1715
1716
1717
1719
1720 {
1721 char buf[16];
1722 sprintf(buf,
"%d",
Port);
1724 }
1725
1726
1727
1728 rdf = (parms && *parms ? parms : pi->
ConfigFN);
1729 if (rdf && Config(rdf, pi->
theEnv))
return 0;
1731
1732
1734 if ((rdf = getenv("XRDROLE"))) {
1736
1737 if (!strcasecmp(rdf, "manager") || !strcasecmp(rdf, "supervisor")) {
1739 eDest.
Emsg(
"Config",
"Configured as HTTP(s) redirector.");
1740 } else {
1741
1742 eDest.
Emsg(
"Config",
"Configured as HTTP(s) data server.");
1743 }
1744
1745 } else {
1746 eDest.
Emsg(
"Config",
"No XRDROLE specified.");
1747 }
1748
1749
1750
1754
1755
1756
1757
1758 return 1;
1759}
1760
1761
1762
1763
1765 char *val, keybuf[1024], parmbuf[1024];
1766 char *parm;
1767
1768
1770 if (!val || !val[0]) {
1771 err.
Emsg(
"Config",
"No headerkey specified.");
1772 return 1;
1773 } else {
1774
1775
1776 while ( *val && !isalnum(*val) ) val++;
1777 strcpy(keybuf, val);
1778
1779
1780 char *pp;
1781 pp = keybuf + strlen(keybuf) - 1;
1782 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1783 *pp = '\0';
1784 pp--;
1785 }
1786
1788
1789
1790 if(!parm || !parm[0]) {
1791 err.
Emsg(
"Config",
"No header2cgi value specified. key: '", keybuf,
"'");
1792 return 1;
1793 }
1794
1795
1796 while ( *parm && !isalnum(*parm) ) parm++;
1797 strcpy(parmbuf, parm);
1798
1799
1800 pp = parmbuf + strlen(parmbuf) - 1;
1801 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1802 *pp = '\0';
1803 pp--;
1804 }
1805
1806
1807 try {
1808 header2cgi[keybuf] = parmbuf;
1809 } catch ( ... ) {
1810 err.
Emsg(
"Config",
"Can't insert new header2cgi rule. key: '", keybuf,
"'");
1811 return 1;
1812 }
1813
1814 }
1815 return 0;
1816}
1817
1818
1819
1820
1821
1822
1823bool XrdHttpProtocol::InitTLS() {
1824
1828
1829
1830
1833
1836
1837
1838
1841 return false;
1842 }
1843
1844
1845
1846
1847
1848 static const char *sess_ctx_id = "XrdHTTPSessionCtx";
1849 unsigned int n =(unsigned int)(strlen(sess_ctx_id)+1);
1851
1852
1853
1855 {
eDest.
Say(
"Config failure: ",
"Unable to set allowable https ciphers!");
1856 return false;
1857 }
1858
1859
1860
1861 return true;
1862}
1863
1864
1865
1866
1867
1868void XrdHttpProtocol::Cleanup() {
1869
1870 TRACE(ALL,
" Cleanup");
1871
1872 if (
BPool && myBuff) {
1873 BuffConsume(BuffUsed());
1875 myBuff = 0;
1876 }
1877
1878 if (ssl) {
1879
1880
1881
1882
1883
1884
1885
1886
1887 int ret = SSL_shutdown(ssl);
1888 if (ret != 1) {
1889 if(ret == 0) {
1890
1891 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1892 ERR_remove_thread_state(nullptr);
1893 #endif
1894 } else {
1895
1896 TRACE(ALL,
" SSL_shutdown failed");
1897 ERR_print_errors(sslbio_err);
1898 }
1899 }
1900
1901 if (secxtractor)
1903
1904 SSL_free(ssl);
1905
1906 }
1907
1908
1909 ssl = 0;
1910 sbio = 0;
1911
1920
1922
1925}
1926
1927
1928
1929
1930
1931void XrdHttpProtocol::Reset() {
1932
1933 TRACE(ALL,
" Reset");
1937
1938 if (myBuff) {
1940 myBuff = 0;
1941 }
1942 myBuffStart = myBuffEnd = 0;
1943
1944 DoingLogin = false;
1945 DoneSetInfo = false;
1946
1947 ResumeBytes = 0;
1948 Resume = 0;
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1965 ishttps = false;
1966 ssldone = false;
1967
1969 ssl = 0;
1970 sbio = 0;
1971
1972}
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989int XrdHttpProtocol::xhttpsmode(
XrdOucStream & Config) {
1990 char *val;
1991
1992
1993
1995 if (!val || !val[0]) {
1996 eDest.
Emsg(
"Config",
"httpsmode parameter not specified");
1997 return 1;
1998 }
1999
2000
2001
2005 else {
eDest.
Emsg(
"Config",
"invalid httpsmode parameter - ", val);
2006 return 1;
2007 }
2008 return 0;
2009}
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024int XrdHttpProtocol::xsslverifydepth(
XrdOucStream & Config) {
2025 char *val;
2026
2027
2028
2030 if (!val || !val[0]) {
2031 eDest.
Emsg(
"Config",
"sslverifydepth value not specified");
2032 return 1;
2033 }
2034
2035
2036
2038
2040 return 0;
2041}
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2057 char *val;
2058
2059
2060
2062 if (!val || !val[0]) {
2063 eDest.
Emsg(
"Config",
"HTTP X509 certificate not specified");
2064 return 1;
2065 }
2066
2067
2068
2071
2072
2073
2075 return 0;
2076}
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2092 char *val;
2093
2094
2095
2097 if (!val || !val[0]) {
2098 eDest.
Emsg(
"Config",
"HTTP X509 key not specified");
2099 return 1;
2100 }
2101
2102
2103
2106
2108 return 0;
2109}
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2129 char *val;
2130
2131
2132
2134 if (!val || !val[0]) {
2135 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file location not specified");
2136 return 1;
2137 }
2138
2139
2140
2141 if (!strncmp(val, "required", 8)) {
2144
2145 if (!val || !val[0]) {
2146 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after [required] "
2147 "parameter");
2148 return 1;
2149 }
2150 }
2151
2152
2153
2154 if (!strcmp(val, "compatNameGeneration")) {
2157 if (!val || !val[0]) {
2158 eDest.
Emsg(
"Config",
"HTTP X509 gridmap file missing after "
2159 "[compatNameGeneration] parameter");
2160 return 1;
2161 }
2162 }
2163
2164
2165
2166
2169 return 0;
2170}
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185int XrdHttpProtocol::xsslcafile(
XrdOucStream & Config) {
2186 char *val;
2187
2188
2189
2191 if (!val || !val[0]) {
2192 eDest.
Emsg(
"Config",
"HTTP X509 CAfile not specified");
2193 return 1;
2194 }
2195
2196
2197
2200
2202 return 0;
2203}
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218int XrdHttpProtocol::xsecretkey(
XrdOucStream & Config) {
2219 char *val;
2220 bool inFile = false;
2221
2222
2223
2225 if (!val || !val[0]) {
2226 eDest.
Emsg(
"Config",
"Shared secret key not specified");
2227 return 1;
2228 }
2229
2230
2231
2232
2233
2234 if (val[0] == '/') {
2236 inFile = true;
2237 if (
stat(val, &st) ) {
2238 eDest.
Emsg(
"Config", errno,
"stat shared secret key file", val);
2239 return 1;
2240 }
2241
2242 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2243 eDest.
Emsg(
"Config",
"For your own security, the shared secret key file cannot be world readable or group writable'", val,
"'");
2244 return 1;
2245 }
2246
2247 FILE *fp =
fopen(val,
"r");
2248
2249 if( fp == NULL ) {
2250 eDest.
Emsg(
"Config", errno,
"open shared secret key file", val);
2251 return 1;
2252 }
2253
2254 char line[1024];
2255 while( fgets(line, 1024, fp) ) {
2256 char *pp;
2257
2258
2259 pp = line + strlen(line) - 1;
2260 while ( (pp >= line) && (!isalnum(*pp)) ) {
2261 *pp = '\0';
2262 pp--;
2263 }
2264
2265
2266 pp = line;
2267 while ( *pp && !isalnum(*pp) ) pp++;
2268
2269 if ( strlen(pp) >= 32 ) {
2270 eDest.
Say(
"Config",
"Secret key loaded.");
2271
2274
2276 return 0;
2277 }
2278
2279 }
2280
2282 eDest.
Emsg(
"Config",
"Cannot find useful secretkey in file '", val,
"'");
2283 return 1;
2284
2285 }
2286
2287 if ( strlen(val) < 32 ) {
2288 eDest.
Emsg(
"Config",
"Secret key is too short");
2289 return 1;
2290 }
2291
2292
2295 if (!inFile)
Config.noEcho();
2296
2297 return 0;
2298}
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2314 char *val;
2315
2316
2317
2319 if (!val || !val[0]) {
2320 eDest.
Emsg(
"Config",
"listingdeny flag not specified");
2321 return 1;
2322 }
2323
2324
2325
2326 listdeny = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2327
2328
2329 return 0;
2330}
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345int XrdHttpProtocol::xlistredir(
XrdOucStream & Config) {
2346 char *val;
2347
2348
2349
2351 if (!val || !val[0]) {
2352 eDest.
Emsg(
"Config",
"listingredir flag not specified");
2353 return 1;
2354 }
2355
2356
2357
2360
2361
2362 return 0;
2363}
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378int XrdHttpProtocol::xdesthttps(
XrdOucStream & Config) {
2379 char *val;
2380
2381
2382
2384 if (!val || !val[0]) {
2385 eDest.
Emsg(
"Config",
"desthttps flag not specified");
2386 return 1;
2387 }
2388
2389
2390
2391 isdesthttps = (!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::xembeddedstatic(
XrdOucStream & Config) {
2411 char *val;
2412
2413
2414
2416 if (!val || !val[0]) {
2417 eDest.
Emsg(
"Config",
"embeddedstatic flag not specified");
2418 return 1;
2419 }
2420
2421
2422
2423 embeddedstatic = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2424
2425
2426 return 0;
2427}
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442int XrdHttpProtocol::xstaticredir(
XrdOucStream & Config) {
2443 char *val;
2444
2445
2446
2448 if (!val || !val[0]) {
2449 eDest.
Emsg(
"Config",
"staticredir url not specified");
2450 return 1;
2451 }
2452
2453
2454
2457
2458 return 0;
2459}
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477int XrdHttpProtocol::xstaticpreload(
XrdOucStream & Config) {
2478 char *val, *k, key[1024];
2479
2480
2481
2483 if (!k || !k[0]) {
2484 eDest.
Emsg(
"Config",
"preloadstatic urlpath not specified");
2485 return 1;
2486 }
2487
2488 strcpy(key, k);
2489
2490
2491
2493 if (!val || !val[0]) {
2494 eDest.
Emsg(
"Config",
"preloadstatic filename not specified");
2495 return 1;
2496 }
2497
2498
2499 int fp =
open(val, O_RDONLY);
2500 if( fp < 0 ) {
2501 eDest.
Emsg(
"Config", errno,
"open preloadstatic filename", val);
2502 return 1;
2503 }
2504
2505 StaticPreloadInfo *nfo = new StaticPreloadInfo;
2506
2507 nfo->data = (char *)malloc(65536);
2508 nfo->len =
read(fp, (
void *)nfo->data, 65536);
2510
2511 if (nfo->len <= 0) {
2512 eDest.
Emsg(
"Config", errno,
"read from preloadstatic filename", val);
2513 return 1;
2514 }
2515
2516 if (nfo->len >= 65536) {
2517 eDest.
Emsg(
"Config",
"Truncated preloadstatic filename. Max is 64 KB '", val,
"'");
2518 return 1;
2519 }
2520
2521
2522
2525
2527 return 0;
2528}
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543int XrdHttpProtocol::xselfhttps2http(
XrdOucStream & Config) {
2544 char *val;
2545
2546
2547
2549 if (!val || !val[0]) {
2550 eDest.
Emsg(
"Config",
"selfhttps2http flag not specified");
2551 return 1;
2552 }
2553
2554
2555
2556 selfhttps2http = (!strcasecmp(val,
"true") || !strcasecmp(val,
"yes") || !strcmp(val,
"1"));
2557
2558
2559 return 0;
2560}
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578int XrdHttpProtocol::xsecxtractor(
XrdOucStream& Config) {
2579 char *val;
2580
2581
2582
2584 if (!val || !val[0]) {
2585 eDest.
Emsg(
"Config",
"No security extractor plugin specified.");
2586 return 1;
2587 } else {
2588
2589
2590 if (!strncmp(val, "required", 8)) {
2591 isRequiredXtractor = true;
2593
2594 if (!val || !val[0]) {
2595 eDest.
Emsg(
"Config",
"No security extractor plugin after [required] "
2596 "parameter");
2597 return 1;
2598 }
2599 }
2600
2601 char libName[4096];
2602 strlcpy(libName, val,
sizeof(libName));
2603 libName[sizeof(libName) - 1] = '\0';
2604 char libParms[4096];
2605
2606 if (!
Config.GetRest(libParms, 4095)) {
2607 eDest.
Emsg(
"Config",
"secxtractor config params longer than 4k");
2608 return 1;
2609 }
2610
2611
2612
2613 if (LoadSecXtractor(&
eDest, libName, libParms)) {
2614 return 1;
2615 }
2616 }
2617
2618 return 0;
2619}
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2639 std::vector<extHInfo> &hiVec) {
2640 char *val, path[1024], namebuf[1024];
2641 char *parm;
2642
2643 bool noTlsOK = false;
2644
2645
2646
2648 if (!val || !val[0]) {
2649 eDest.
Emsg(
"Config",
"No instance name specified for an http external handler plugin.");
2650 return 1;
2651 }
2652 if (strlen(val) >= 16) {
2653 eDest.
Emsg(
"Config",
"Instance name too long for an http external handler plugin.");
2654 return 1;
2655 }
2656 strncpy(namebuf, val, sizeof(namebuf));
2657 namebuf[ sizeof(namebuf)-1 ] = '\0';
2658
2659
2661
2662 if(val && !strcmp("+notls",val)) {
2663 noTlsOK = true;
2665 }
2666
2667
2668
2669 if (!val || !val[0]) {
2670 eDest.
Emsg(
"Config",
"No http external handler plugin specified.");
2671 return 1;
2672 }
2673 if (strlen(val) >= (int)sizeof(path)) {
2674 eDest.
Emsg(
"Config",
"Path too long for an http external handler plugin.");
2675 return 1;
2676 }
2677
2678 strcpy(path, val);
2679
2680
2681
2683
2684
2685
2686 for (int i = 0; i < (int)hiVec.size(); i++)
2687 {if (hiVec[i].extHName == namebuf) {
2688 eDest.
Emsg(
"Config",
"Instance name already present for "
2689 "http external handler plugin",
2690 hiVec[i].extHPath.c_str());
2691 return 1;
2692 }
2693 }
2694
2695
2696
2698 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
2699 return 1;
2700 }
2701
2702
2703
2704 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm : ""), noTlsOK));
2705
2706 return 0;
2707}
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725int XrdHttpProtocol::xheader2cgi(
XrdOucStream & Config) {
2727}
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2743 char *val;
2744
2745
2746
2748 if (!val || !val[0]) {
2749 eDest.
Emsg(
"Config",
"HTTP X509 CAdir not specified");
2750 return 1;
2751 }
2752
2753
2754
2757
2759 return 0;
2760}
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776int XrdHttpProtocol::xsslcipherfilter(
XrdOucStream & Config) {
2777 char *val;
2778
2779
2780
2782 if (!val || !val[0]) {
2783 eDest.
Emsg(
"Config",
"SSL cipherlist filter string not specified");
2784 return 1;
2785 }
2786
2787
2788
2791
2792 return 0;
2793}
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2807
2808 char *val;
2809
2810
2811
2813 if (!val || !val[0])
2814 {
eDest.
Emsg(
"Config",
"tlsreuse argument not specified");
return 1;}
2815
2816
2817
2818 if (!strcmp(val, "off"))
2820 return 0;
2821 }
2822
2823
2824
2825 if (!strcmp(val, "on"))
2827 return 0;
2828 }
2829
2830
2831
2832 eDest.
Emsg(
"config",
"invalid tlsreuse parameter -", val);
2833 return 1;
2834}
2835
2837 char *val =
Config.GetWord();
2838 if(val) {
2839 if(!strcmp("tpc",val)) {
2840 if(!(val =
Config.GetWord())) {
2841 eDest.
Emsg(
"Config",
"http.auth tpc value not specified.");
return 1;
2842 } else {
2843 if(!strcmp("fcreds",val)) {
2845 } else {
2846 eDest.
Emsg(
"Config",
"http.auth tpc value is invalid");
return 1;
2847 }
2848 }
2849 } else {
2850 eDest.
Emsg(
"Config",
"http.auth value is invalid");
return 1;
2851 }
2852 }
2853 return 0;
2854}
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2871
2872 char *val;
2873
2874 static struct traceopts {
2875 const char *opname;
2876 int opval;
2877 } tropts[] = {
2885 };
2886 int i, neg, trval = 0, numopts = sizeof (tropts) / sizeof (struct traceopts);
2887
2888 if (!(val =
Config.GetWord())) {
2889 eDest.
Emsg(
"config",
"trace option not specified");
2890 return 1;
2891 }
2892 while (val) {
2893 if (!strcmp(val, "off")) trval = 0;
2894 else {
2895 if ((neg = (val[0] == '-' && val[1]))) val++;
2896 for (i = 0; i < numopts; i++) {
2897 if (!strcmp(val, tropts[i].opname)) {
2898 if (neg) trval &= ~tropts[i].opval;
2899 else trval |= tropts[i].opval;
2900 break;
2901 }
2902 }
2903 if (i >= numopts)
2904 eDest.
Emsg(
"config",
"invalid trace option", val);
2905 }
2907 }
2909 return 0;
2910}
2911
2913 int l;
2914 bool b;
2918
2923 l = strlen(fname) + 1;
2925
2928 if (!b) {
2929 return -1;
2930 }
2931
2932
2933 return 0;
2934}
2935
2936
2937
2938
2939
2941 size_t length;
2948 length = fname.
length() + 1;
2950
2952
2954}
2955
2956
2957static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION);
2958
2959
2960int XrdHttpProtocol::LoadSecXtractor(
XrdSysError *myeDest,
const char *libName,
2961 const char *libParms) {
2962
2963
2964
2965 if (secxtractor) return 1;
2966
2967 XrdOucPinLoader myLib(myeDest, &compiledVer,
"secxtractorlib", libName);
2969
2970
2971
2973 if (ep && (secxtractor = ep(myeDest, NULL, libParms))) return 0;
2974 myLib.Unload();
2975 return 1;
2976}
2977
2978
2979
2980
2981int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec,
const char *cFN,
XrdOucEnv &myEnv) {
2982 for (int i = 0; i < (int) hiVec.size(); i++) {
2983 if(hiVec[i].extHNoTlsOK) {
2984
2985 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
2986 hiVec[i].extHParm.c_str(), &myEnv,
2987 hiVec[i].extHName.c_str()))
2988 return 1;
2989 }
2990 }
2991 return 0;
2992}
2993
2994int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
2996
2997
2998
3003
3004
3005
3006 for (int i = 0; i < (int)hiVec.size(); i++) {
3007
3008
3009 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3010 if (LoadExtHandler(&
eDest, hiVec[i].extHPath.c_str(), cFN,
3011 hiVec[i].extHParm.c_str(), &myEnv,
3012 hiVec[i].extHName.c_str())) return 1;
3013 }
3014 }
3015 return 0;
3016}
3017
3018
3019int XrdHttpProtocol::LoadExtHandler(
XrdSysError *myeDest,
const char *libName,
3020 const char *configFN, const char *libParms,
3021 XrdOucEnv *myEnv,
const char *instName) {
3022
3023
3024
3025 if (ExtHandlerLoaded(instName)) {
3026 eDest.
Emsg(
"Config",
"Instance name already present for an http external handler plugin.");
3027 return 1;
3028 }
3030 eDest.
Emsg(
"Config",
"Cannot load one more exthandler. Max is 4");
3031 return 1;
3032 }
3033
3034 XrdOucPinLoader myLib(myeDest, &compiledVer,
"exthandlerlib", libName);
3036
3037
3038
3040
3042 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3043
3044
3045 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3046 exthandler[exthandlercnt].name[15] = '\0';
3047 exthandler[exthandlercnt++].ptr = newhandler;
3048
3049 return 0;
3050 }
3051
3052 myLib.Unload();
3053 return 1;
3054}
3055
3056
3057
3058
3059
3060bool XrdHttpProtocol::ExtHandlerLoaded(const char *handlername) {
3061 for (int i = 0; i < exthandlercnt; i++) {
3062 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3063 return true;
3064 }
3065 }
3066 return false;
3067}
3068
3069
3070
3072
3073 for (int i = 0; i < exthandlercnt; i++) {
3075 return exthandler[i].ptr;
3076 }
3077 }
3078 return NULL;
3079}
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 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 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.