XRootD
Loading...
Searching...
No Matches
XrdHttpProtocol.cc File Reference
#include "XrdVersion.hh"
#include "Xrd/XrdBuffer.hh"
#include "Xrd/XrdLink.hh"
#include "XProtocol/XProtocol.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucGMap.hh"
#include "XrdSys/XrdSysE2T.hh"
#include "XrdSys/XrdSysTimer.hh"
#include "XrdOuc/XrdOucPinLoader.hh"
#include "XrdHttpTrace.hh"
#include "XrdHttpProtocol.hh"
#include <sys/stat.h>
#include "XrdHttpUtils.hh"
#include "XrdHttpSecXtractor.hh"
#include "XrdHttpExtHandler.hh"
#include "XrdTls/XrdTls.hh"
#include "XrdTls/XrdTlsContext.hh"
#include "XrdOuc/XrdOucUtils.hh"
#include "XrdOuc/XrdOucPrivateUtils.hh"
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <vector>
#include <arpa/inet.h>
#include <sstream>
#include <cctype>
#include <fcntl.h>
#include <algorithm>
+ Include dependency graph for XrdHttpProtocol.cc:

Go to the source code of this file.

Namespaces

namespace  XrdHttpProtoInfo
 

Macros

#define HTTPS_ALERT(x, y, z)
 
#define TRACELINK   lp
 
#define TRACELINK   Link
 
#define TRACELINK   Link
 
#define TS_Xeq(x, m)   (!strcmp(x,var)) GoNo = m(Config)
 
#define TS_Xeq3(x, m)   (!strcmp(x,var)) GoNo = m(Config, extHIVec)
 
#define XRHTTP_TK_GRACETIME   600
 

Functions

void * BIO_get_data (BIO *bio)
 
int BIO_get_flags (BIO *bio)
 
int BIO_get_init (BIO *bio)
 
int BIO_get_shutdown (BIO *bio)
 
void BIO_set_data (BIO *bio, void *ptr)
 
void BIO_set_flags (BIO *bio, int flags)
 
void BIO_set_init (BIO *bio, int init)
 
void BIO_set_shutdown (BIO *bio, int shut)
 
static int BIO_XrdLink_create (BIO *bio)
 
static long BIO_XrdLink_ctrl (BIO *bio, int cmd, long num, void *ptr)
 
static int BIO_XrdLink_destroy (BIO *bio)
 
static int BIO_XrdLink_read (BIO *bio, char *data, size_t datal, size_t *read)
 
int BIO_XrdLink_write (BIO *bio, const char *data, size_t datal, size_t *written)
 
static XrdVERSIONINFODEF (compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
 

Variables

static const int XrdHttpProtoInfo::hsmAuto = -1
 
static const int XrdHttpProtoInfo::hsmMan = 1
 
static const int XrdHttpProtoInfo::hsmOff = 0
 
static const int XrdHttpProtoInfo::hsmOn = 1
 
int XrdHttpProtoInfo::httpsmode = hsmAuto
 
bool XrdHttpProtoInfo::httpsspec = false
 
int XrdHttpProtoInfo::tlsCache = XrdTlsContext::scOff
 
XrdTlsContextXrdHttpProtoInfo::xrdctx = 0
 
bool XrdHttpProtoInfo::xrdctxVer = false
 
const char * XrdHttpSecEntityTident = "http"
 
XrdSysTrace XrdHttpTrace ("http")
 

Macro Definition Documentation

◆ HTTPS_ALERT

#define HTTPS_ALERT (   x,
  y,
 
)
Value:
httpsspec = true;\
if (xrdctx && httpsmode == hsmAuto && (z || xrdctx->x509Verify())) \
eDest.Say("Config http." x " overrides the xrd." y " directive.")
static XrdSysError eDest(0,"crypto_")
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
static const int hsmAuto
XrdTlsContext * xrdctx

Definition at line 976 of file XrdHttpProtocol.cc.

979 {
980 XrdOucEnv cfgEnv;
981 XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &cfgEnv, "=====> ");
982 std::vector<extHInfo> extHIVec;
983 char *var;
984 int cfgFD, GoNo, NoGo = 0, ismine;
985
986 var = nullptr;
987 XrdOucEnv::Import("XRD_READV_LIMITS", var);
988 XrdHttpReadRangeHandler::Configure(eDest, var, ReadRangeConfig);
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 // Initialize our custom BIO type.
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;
1016 m_bio_method->bwrite = BIO_XrdLink_write;
1017 m_bio_method->bread = BIO_XrdLink_read;
1018 m_bio_method->create = BIO_XrdLink_create;
1019 m_bio_method->destroy = BIO_XrdLink_destroy;
1020 m_bio_method->ctrl = BIO_XrdLink_ctrl;
1021 }
1022 #else
1023 // OpenSSL 1.1 has an internal counter for generating unique types.
1024 // We'll switch to that when widely available.
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) {
1029 BIO_meth_set_write(m_bio_method, BIO_XrdLink_write);
1030 BIO_meth_set_read(m_bio_method, BIO_XrdLink_read);
1031 BIO_meth_set_create(m_bio_method, BIO_XrdLink_create);
1032 BIO_meth_set_destroy(m_bio_method, BIO_XrdLink_destroy);
1033 BIO_meth_set_ctrl(m_bio_method, BIO_XrdLink_ctrl);
1034 }
1035
1036 #endif
1037 }
1038
1039 // If we have a tls context record whether it configured for verification
1040 // so that we can provide meaningful error and warning messages.
1041 //
1043
1044 // Open and attach the config file
1045 //
1046 if ((cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
1047 return eDest.Emsg("Config", errno, "open config file", ConfigFN);
1048 Config.Attach(cfgFD);
1049 static const char *cvec[] = { "*** http protocol config:", 0 };
1050 Config.Capture(cvec);
1051
1052 // Process items
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, "'.");
1081 Config.Echo();
1082 continue;
1083 }
1084 if (GoNo) {
1085 Config.Echo();
1086 NoGo = 1;
1087 }
1088 }
1089 }
1090
1091// To minimize message confusion down, if an error occurred during config
1092// parsing, just bail out now with a confirming message.
1093//
1094 if (NoGo)
1095 {eDest.Say("Config failure: one or more directives are flawed!");
1096 return 1;
1097 }
1098
1099// Some headers must always be converted to CGI key=value pairs
1100//
1101 hdr2cgimap["Cache-Control"] = "cache-control";
1102
1103// Test if XrdEC is loaded
1104 if (getenv("XRDCL_EC")) usingEC = true;
1105
1106// If https was disabled, then issue a warning message if xrdtls configured
1107// of it's disabled because httpsmode was auto and xrdtls was not configured.
1108// If we get past this point then we know https is a plausible option but we
1109// can still fail if we cannot supply any missing but required options.
1110//
1111 if (httpsmode == hsmOff || (httpsmode == hsmAuto && !xrdctx && !httpsspec))
1112 {const char *why = (httpsmode == hsmOff ? "has been disabled!"
1113 : "was not configured.");
1114 const char *what = Configed();
1115
1116 eDest.Say("Config warning: HTTPS functionality ", why);
1117 httpsmode = hsmOff;
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// Warn if a private key was specified without a cert as this has no meaning
1128// even as an auto overide as they must be paired.
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// If the mode is manual then we need to have at least a cert.
1137//
1138 if (httpsmode == hsmMan)
1139 {if (!sslcert)
1140 {eDest.Say("Config failure: 'httpsmode manual' requires atleast a "
1141 "a cert specification!");
1142 return 1;
1143 }
1144 }
1145
1146// If it's auto d through all possibilities. It's either auto with xrdtls
1147// configured or manual which needs at least a cert specification. For auto
1148// configuration we will only issue a warning if overrides were specified.
1149//
1150 if (httpsmode == hsmAuto && xrdctx)
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 }
1172 if (!httpsspec && what1) eDest.Say("Config Using ", what1);
1173 if (!httpsspec && what2) eDest.Say("Config Using ", what2);
1174 if (!httpsspec && what3) eDest.Say("Config Using ", what3);
1175 }
1176
1177// If a gridmap or secxtractor is present then we must be able to verify certs
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 }
1188 httpsmode = hsmOn;
1189
1190// Oddly we need to create an error bio at this point
1191//
1192 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1193
1194// Now we can configure HTTPS. We will not reuse the passed context as we will
1195// be setting our own options specific to out implementation. One day we will.
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// We can now load all the external handlers
1204//
1205 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv)) return 1;
1206
1207// At this point, we can actually initialize security plugins
1208//
1209 return (InitSecurity() ? NoGo : 1);
1210}
1211
1212/******************************************************************************/
1213/* C o n f i g e d */
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/* B u f f g e t L i n e */
1226/******************************************************************************/
1227
1229
1230int XrdHttpProtocol::BuffgetLine(XrdOucString &dest) {
1231
1232 dest = "";
1233 char save;
1234
1235 // Easy case
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 //strncpy(dest, myBuffStart, l);
1247 //dest[l] = '\0';
1248 BuffConsume(l);
1249
1250 //if (dest[l-1] == '\n') dest[l - 1] = '\0';
1251 return l;
1252 }
1253
1254 }
1255
1256 return 0;
1257 } else {
1258 // More complex case... we have to do it in two segments
1259
1260 // Segment 1: myBuffStart->myBuff->buff+myBuff->bsize
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 //strncpy(dest, myBuffStart, l);
1271
1272 BuffConsume(l);
1273
1274 //if (dest[l-1] == '\n') dest[l - 1] = '\0';
1275 return l;
1276 }
1277
1278 }
1279
1280 // We did not find the \n, let's keep on searching in the 2nd segment
1281 // Segment 2: myBuff->buff --> myBuffEnd
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 // Remember the 1st segment
1289 int l1 = myBuff->buff + myBuff->bsize - myBuffStart;
1290
1291 dest.assign(myBuffStart, 0, l1-1);
1292 //strncpy(dest, myBuffStart, l1);
1293 BuffConsume(l1);
1294
1295 dest.insert(myBuffStart, l1, l-1);
1296 //strncpy(dest + l1, myBuffStart, l);
1297 //dest[l + l1] = '\0';
1298 BuffConsume(l);
1299
1300 *(p+1) = save;
1301
1302 //if (dest[l + l1 - 1] == '\n') dest[l + l1 - 1] = '\0';
1303 return l + l1;
1304 }
1305
1306 }
1307
1308
1309
1310 }
1311
1312 return 0;
1313}
1314
1315/******************************************************************************/
1316/* g e t D a t a O n e S h o t */
1317/******************************************************************************/
1318
1319int XrdHttpProtocol::getDataOneShot(int blen, bool wait) {
1320 int rlen, maxread;
1321
1322 // Get up to blen bytes from the connection. Put them into mybuff.
1323 // This primitive, for the way it is used, is not supposed to block if wait=false
1324
1325 // Returns:
1326 // 2: no space left in buffer
1327 // 1: timeout
1328 // -1: error
1329 // 0: everything read correctly
1330
1331
1332
1333 // Check for buffer overflow first
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) {
1350 Link->setEtext("link SSL_pending error");
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) {
1359 TRACE(DEBUG, "getDataOneShot Buffer panic");
1360 myBuffEnd = myBuff->buff;
1361 }
1362
1363 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1364 if (rlen <= 0) {
1365 Link->setEtext("link SSL read error");
1366 ERR_print_errors(sslbio_err);
1367 return -1;
1368 }
1369
1370
1371 } else {
1372
1373 if (myBuffEnd - myBuff->buff >= myBuff->bsize) {
1374 TRACE(DEBUG, "getDataOneShot Buffer panic");
1375 myBuffEnd = myBuff->buff;
1376 }
1377
1378 if (wait)
1379 rlen = Link->Recv(myBuffEnd, maxread, readWait);
1380 else
1381 rlen = Link->Recv(myBuffEnd, maxread);
1382
1383
1384 if (rlen == 0) {
1385 Link->setEtext("link read error or closed");
1386 return -1;
1387 }
1388
1389 if (rlen < 0) {
1390 Link->setEtext("link timeout or other error");
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/* B u f f U s e d */
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/* B u f f F r e e */
1445/******************************************************************************/
1446
1448
1449int XrdHttpProtocol::BuffFree() {
1450 return (myBuff->bsize - BuffUsed());
1451}
1452
1453/******************************************************************************/
1454/* B u f f C o n s u m e */
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/* B u f f g e t D a t a */
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 // If there's not enough data in the buffer then wait on the socket until it comes
1501 if (blen > BuffUsed()) {
1502 TRACE(REQ, "BuffgetData: need to read " << blen - BuffUsed() << " bytes");
1503 if ( getDataOneShot(blen - BuffUsed(), true) )
1504 // The wanted data could not be read. Either timeout of connection closed
1505 return 0;
1506 }
1507 } else {
1508 // Get a peek at the socket, without waiting, if we have no data in the buffer
1509 if ( !BuffUsed() ) {
1510 if ( getDataOneShot(blen, false) )
1511 // The wanted data could not be read. Either timeout of connection closed
1512 return -1;
1513 }
1514 }
1515
1516 // And now make available the data taken from the buffer. Note that the buffer
1517 // may be empty...
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/* S e n d D a t a */
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 {
1549 r = Link->Send(body, bodylen);
1550 if (r <= 0) return -1;
1551 }
1552 }
1553
1554 return 0;
1555}
1556
1557/******************************************************************************/
1558/* S t a r t S i m p l e R e s p */
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/* S t a r t C h u n k e d R e s p */
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/* C h u n k R e s p */
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/* C h u n k R e s p H e a d e r */
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/* C h u n k R e s p F o o t e r */
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/* S e n d S i m p l e R e s p */
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 // Send the data
1683 //
1684 if (body)
1685 return SendData(body, content_length);
1686
1687 return 0;
1688}
1689
1690/******************************************************************************/
1691/* C o n f i g u r e */
1692/******************************************************************************/
1693
1694int XrdHttpProtocol::Configure(char *parms, XrdProtocol_Config * pi) {
1695 /*
1696 Function: Establish configuration at load time.
1697
1698 Input: None.
1699
1700 Output: 0 upon success or !0 otherwise.
1701 */
1702
1703 char *rdf;
1704
1705 // Copy out the special info we want to use at top level
1706 //
1707 eDest.logger(pi->eDest->logger());
1709 // SI = new XrdXrootdStats(pi->Stats);
1710 Sched = pi->Sched;
1711 BPool = pi->BPool;
1712 xrd_cslist = getenv("XRD_CSLIST");
1713
1714 Port = pi->Port;
1715
1716 // Copy out the current TLS context
1717 //
1718 xrdctx = pi->tlsCtx;
1719
1720 {
1721 char buf[16];
1722 sprintf(buf, "%d", Port);
1723 Port_str = strdup(buf);
1724 }
1725
1726 // Now process and configuration parameters
1727 //
1728 rdf = (parms && *parms ? parms : pi->ConfigFN);
1729 if (rdf && Config(rdf, pi->theEnv)) return 0;
1731
1732 // Set the redirect flag if we are a pure redirector
1734 if ((rdf = getenv("XRDROLE"))) {
1735 eDest.Emsg("Config", "XRDROLE: ", rdf);
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 // Schedule protocol object cleanup
1750 //
1753 ProtStack.Set((pi->ConnMax / 3 ? pi->ConnMax / 3 : 30), 60 * 60);
1754
1755 // Return success
1756 //
1757
1758 return 1;
1759}
1760
1761/******************************************************************************/
1762/* p a r s e H e a d e r 2 C G I */
1763/******************************************************************************/
1764int XrdHttpProtocol::parseHeader2CGI(XrdOucStream &Config, XrdSysError & err,std::map<std::string, std::string> &header2cgi) {
1765 char *val, keybuf[1024], parmbuf[1024];
1766 char *parm;
1767
1768 // Get the header key
1769 val = Config.GetWord();
1770 if (!val || !val[0]) {
1771 err.Emsg("Config", "No headerkey specified.");
1772 return 1;
1773 } else {
1774
1775 // Trim the beginning, in place
1776 while ( *val && !isalnum(*val) ) val++;
1777 strcpy(keybuf, val);
1778
1779 // Trim the end, in place
1780 char *pp;
1781 pp = keybuf + strlen(keybuf) - 1;
1782 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1783 *pp = '\0';
1784 pp--;
1785 }
1786
1787 parm = Config.GetWord();
1788
1789 // Avoids segfault in case a key is given without value
1790 if(!parm || !parm[0]) {
1791 err.Emsg("Config", "No header2cgi value specified. key: '", keybuf, "'");
1792 return 1;
1793 }
1794
1795 // Trim the beginning, in place
1796 while ( *parm && !isalnum(*parm) ) parm++;
1797 strcpy(parmbuf, parm);
1798
1799 // Trim the end, in place
1800 pp = parmbuf + strlen(parmbuf) - 1;
1801 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1802 *pp = '\0';
1803 pp--;
1804 }
1805
1806 // Add this mapping to the map that will be used
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/* I n i t T L S */
1821/******************************************************************************/
1822
1823bool XrdHttpProtocol::InitTLS() {
1824
1825 std::string eMsg;
1828
1829// Create a new TLS context
1830//
1831 if (sslverifydepth > 255) sslverifydepth = 255;
1833 //TLS_SET_REFINT will set the refresh interval in minutes, hence the division by 60
1836
1837// Make sure the context was created
1838//
1839 if (!xrdctx->isOK())
1840 {eDest.Say("Config failure: ", eMsg.c_str());
1841 return false;
1842 }
1843
1844// Setup session cache (this is controversial). The default is off but many
1845// programs expect it being enabled and break when it is disabled. In such
1846// cases it should be enabled. This is, of course, a big OpenSSL mess.
1847//
1848 static const char *sess_ctx_id = "XrdHTTPSessionCtx";
1849 unsigned int n =(unsigned int)(strlen(sess_ctx_id)+1);
1850 xrdctx->SessionCache(tlsCache, sess_ctx_id, n);
1851
1852// Set special ciphers if so specified.
1853//
1855 {eDest.Say("Config failure: ", "Unable to set allowable https ciphers!");
1856 return false;
1857 }
1858
1859// All done
1860//
1861 return true;
1862}
1863
1864/******************************************************************************/
1865/* C l e a n u p */
1866/******************************************************************************/
1867
1868void XrdHttpProtocol::Cleanup() {
1869
1870 TRACE(ALL, " Cleanup");
1871
1872 if (BPool && myBuff) {
1873 BuffConsume(BuffUsed());
1874 BPool->Release(myBuff);
1875 myBuff = 0;
1876 }
1877
1878 if (ssl) {
1879 // Shutdown the SSL/TLS connection
1880 // https://www.openssl.org/docs/man1.0.2/man3/SSL_shutdown.html
1881 // We don't need a bidirectional shutdown as
1882 // when we are here, the connection will not be re-used.
1883 // In the case SSL_shutdown returns 0,
1884 // "the output of SSL_get_error(3) may be misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred."
1885 // we will then just flush the thread's queue.
1886 // In the case an error really happened, we print the error that happened
1887 int ret = SSL_shutdown(ssl);
1888 if (ret != 1) {
1889 if(ret == 0) {
1890 // Clean this thread's error queue for the old openssl versions
1891 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1892 ERR_remove_thread_state(nullptr);
1893 #endif
1894 } else {
1895 //ret < 0, an error really happened.
1896 TRACE(ALL, " SSL_shutdown failed");
1897 ERR_print_errors(sslbio_err);
1898 }
1899 }
1900
1901 if (secxtractor)
1902 secxtractor->FreeSSL(ssl);
1903
1904 SSL_free(ssl);
1905
1906 }
1907
1908
1909 ssl = 0;
1910 sbio = 0;
1911
1912 if (SecEntity.caps) free(SecEntity.caps);
1913 if (SecEntity.grps) free(SecEntity.grps);
1915 if (SecEntity.vorg) free(SecEntity.vorg);
1916 if (SecEntity.role) free(SecEntity.role);
1917 if (SecEntity.name) free(SecEntity.name);
1918 if (SecEntity.host) free(SecEntity.host);
1920
1921 SecEntity.Reset();
1922
1923 if (Addr_str) free(Addr_str);
1924 Addr_str = 0;
1925}
1926
1927/******************************************************************************/
1928/* R e s e t */
1929/******************************************************************************/
1930
1931void XrdHttpProtocol::Reset() {
1932
1933 TRACE(ALL, " Reset");
1934 Link = 0;
1935 CurrentReq.reset();
1936 CurrentReq.reqstate = 0;
1937
1938 if (myBuff) {
1939 BPool->Release(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 // numReads = 0;
1952 // numReadP = 0;
1953 // numReadV = 0;
1954 // numSegsV = 0;
1955 // numWrites = 0;
1956 // numFiles = 0;
1957 // cumReads = 0;
1958 // cumReadV = 0;
1959 // cumSegsV = 0;
1960 // cumWrites = 0;
1961 // totReadP = 0;
1962
1963 SecEntity.Reset();
1965 ishttps = false;
1966 ssldone = false;
1967
1968 Bridge = 0;
1969 ssl = 0;
1970 sbio = 0;
1971
1972}
1973
1974/******************************************************************************/
1975/* x h t t p s m o d e */
1976/******************************************************************************/
1977
1978/* Function: xhttpsmode
1979
1980 Purpose: To parse the directive: httpsmode {auto | disable | manual}
1981
1982 auto configure https if configured in xrd framework.
1983 disable do not configure https no matter what
1984 manual configure https and ignore the xrd framework
1985
1986 Output: 0 upon success or !0 upon failure.
1987 */
1988
1989int XrdHttpProtocol::xhttpsmode(XrdOucStream & Config) {
1990 char *val;
1991
1992 // Get the val
1993 //
1994 val = Config.GetWord();
1995 if (!val || !val[0]) {
1996 eDest.Emsg("Config", "httpsmode parameter not specified");
1997 return 1;
1998 }
1999
2000 // Record the val
2001 //
2002 if (!strcmp(val, "auto")) httpsmode = hsmAuto;
2003 else if (!strcmp(val, "disable")) httpsmode = hsmOff;
2004 else if (!strcmp(val, "manual")) httpsmode = hsmMan;
2005 else {eDest.Emsg("Config", "invalid httpsmode parameter - ", val);
2006 return 1;
2007 }
2008 return 0;
2009}
2010
2011/******************************************************************************/
2012/* x s s l v e r i f y d e p t h */
2013/******************************************************************************/
2014
2015/* Function: xsslverifydepth
2016
2017 Purpose: To parse the directive: sslverifydepth <depth>
2018
2019 <depth> the max depth of the ssl cert verification
2020
2021 Output: 0 upon success or !0 upon failure.
2022 */
2023
2024int XrdHttpProtocol::xsslverifydepth(XrdOucStream & Config) {
2025 char *val;
2026
2027 // Get the val
2028 //
2029 val = Config.GetWord();
2030 if (!val || !val[0]) {
2031 eDest.Emsg("Config", "sslverifydepth value not specified");
2032 return 1;
2033 }
2034
2035 // Record the val
2036 //
2037 sslverifydepth = atoi(val);
2038
2039 if (xrdctxVer){ HTTPS_ALERT("verifydepth","tlsca",false); }
2040 return 0;
2041}
2042
2043/******************************************************************************/
2044/* x s s l c e r t */
2045/******************************************************************************/
2046
2047/* Function: xsslcert
2048
2049 Purpose: To parse the directive: sslcert <path>
2050
2051 <path> the path of the server certificate to be used.
2052
2053 Output: 0 upon success or !0 upon failure.
2054 */
2055
2056int XrdHttpProtocol::xsslcert(XrdOucStream & Config) {
2057 char *val;
2058
2059 // Get the path
2060 //
2061 val = Config.GetWord();
2062 if (!val || !val[0]) {
2063 eDest.Emsg("Config", "HTTP X509 certificate not specified");
2064 return 1;
2065 }
2066
2067 // Record the path
2068 //
2069 if (sslcert) free(sslcert);
2070 sslcert = strdup(val);
2071
2072 // If we have an xrd context issue reminder
2073 //
2074 HTTPS_ALERT("cert","tls",true);
2075 return 0;
2076}
2077
2078/******************************************************************************/
2079/* x s s l k e y */
2080/******************************************************************************/
2081
2082/* Function: xsslkey
2083
2084 Purpose: To parse the directive: sslkey <path>
2085
2086 <path> the path of the server key to be used.
2087
2088 Output: 0 upon success or !0 upon failure.
2089 */
2090
2091int XrdHttpProtocol::xsslkey(XrdOucStream & Config) {
2092 char *val;
2093
2094 // Get the path
2095 //
2096 val = Config.GetWord();
2097 if (!val || !val[0]) {
2098 eDest.Emsg("Config", "HTTP X509 key not specified");
2099 return 1;
2100 }
2101
2102 // Record the path
2103 //
2104 if (sslkey) free(sslkey);
2105 sslkey = strdup(val);
2106
2107 HTTPS_ALERT("key","tls",true);
2108 return 0;
2109}
2110
2111/******************************************************************************/
2112/* x g m a p */
2113/******************************************************************************/
2114
2115/* Function: xgmap
2116
2117 Purpose: To parse the directive: gridmap [required] [compatNameGeneration] <path>
2118
2119 required optional parameter which if present treats any grimap errors
2120 as fatal.
2121 <path> the path of the gridmap file to be used. Normally it's
2122 /etc/grid-security/gridmap. No mapfile means no translation
2123 required. Pointing to a non existing mapfile is an error.
2124
2125 Output: 0 upon success or !0 upon failure.
2126 */
2127
2128int XrdHttpProtocol::xgmap(XrdOucStream & Config) {
2129 char *val;
2130
2131 // Get the path
2132 //
2133 val = Config.GetWord();
2134 if (!val || !val[0]) {
2135 eDest.Emsg("Config", "HTTP X509 gridmap file location not specified");
2136 return 1;
2137 }
2138
2139 // Handle optional parameter "required"
2140 //
2141 if (!strncmp(val, "required", 8)) {
2142 isRequiredGridmap = true;
2143 val = Config.GetWord();
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 // Handle optional parameter "compatNameGeneration"
2153 //
2154 if (!strcmp(val, "compatNameGeneration")) {
2155 compatNameGeneration = true;
2156 val = Config.GetWord();
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 // Record the path
2166 //
2167 if (gridmap) free(gridmap);
2168 gridmap = strdup(val);
2169 return 0;
2170}
2171
2172/******************************************************************************/
2173/* x s s l c a f i l e */
2174/******************************************************************************/
2175
2176/* Function: xsslcafile
2177
2178 Purpose: To parse the directive: sslcafile <path>
2179
2180 <path> the path of the server key to be used.
2181
2182 Output: 0 upon success or !0 upon failure.
2183 */
2184
2185int XrdHttpProtocol::xsslcafile(XrdOucStream & Config) {
2186 char *val;
2187
2188 // Get the path
2189 //
2190 val = Config.GetWord();
2191 if (!val || !val[0]) {
2192 eDest.Emsg("Config", "HTTP X509 CAfile not specified");
2193 return 1;
2194 }
2195
2196 // Record the path
2197 //
2198 if (sslcafile) free(sslcafile);
2199 sslcafile = strdup(val);
2200
2201 if (xrdctxVer){ HTTPS_ALERT("cafile","tlsca",false); }
2202 return 0;
2203}
2204
2205/******************************************************************************/
2206/* x s e c r e t k e y */
2207/******************************************************************************/
2208
2209/* Function: xsecretkey
2210
2211 Purpose: To parse the directive: xsecretkey <key>
2212
2213 <key> the key to be used
2214
2215 Output: 0 upon success or !0 upon failure.
2216 */
2217
2218int XrdHttpProtocol::xsecretkey(XrdOucStream & Config) {
2219 char *val;
2220 bool inFile = false;
2221
2222 // Get the path
2223 //
2224 val = Config.GetWord();
2225 if (!val || !val[0]) {
2226 eDest.Emsg("Config", "Shared secret key not specified");
2227 return 1;
2228 }
2229
2230
2231 // If the token starts with a slash, then we interpret it as
2232 // the path to a file that contains the secretkey
2233 // otherwise, the token itself is the secretkey
2234 if (val[0] == '/') {
2235 struct stat st;
2236 inFile = true;
2237 int fd = open(val, O_RDONLY);
2238
2239 if ( fd == -1 ) {
2240 eDest.Emsg("Config", errno, "open shared secret key file", val);
2241 return 1;
2242 }
2243
2244 if ( fstat(fd, &st) != 0 ) {
2245 eDest.Emsg("Config", errno, "fstat shared secret key file", val);
2246 close(fd);
2247 return 1;
2248 }
2249
2250 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2251 eDest.Emsg("Config",
2252 "For your own security, the shared secret key file cannot be world readable or group writable '", val, "'");
2253 close(fd);
2254 return 1;
2255 }
2256
2257 FILE *fp = fdopen(fd, "r");
2258
2259 if ( fp == nullptr ) {
2260 eDest.Emsg("Config", errno, "fdopen shared secret key file", val);
2261 close(fd);
2262 return 1;
2263 }
2264
2265 char line[1024];
2266 while( fgets(line, 1024, fp) ) {
2267 char *pp;
2268
2269 // Trim the end
2270 pp = line + strlen(line) - 1;
2271 while ( (pp >= line) && (!isalnum(*pp)) ) {
2272 *pp = '\0';
2273 pp--;
2274 }
2275
2276 // Trim the beginning
2277 pp = line;
2278 while ( *pp && !isalnum(*pp) ) pp++;
2279
2280 if ( strlen(pp) >= 32 ) {
2281 eDest.Say("Config", "Secret key loaded.");
2282 // Record the path
2283 if (secretkey) free(secretkey);
2284 secretkey = strdup(pp);
2285
2286 fclose(fp);
2287 return 0;
2288 }
2289
2290 }
2291
2292 fclose(fp);
2293 eDest.Emsg("Config", "Cannot find useful secretkey in file '", val, "'");
2294 return 1;
2295
2296 }
2297
2298 if ( strlen(val) < 32 ) {
2299 eDest.Emsg("Config", "Secret key is too short");
2300 return 1;
2301 }
2302
2303 // Record the path
2304 if (secretkey) free(secretkey);
2305 secretkey = strdup(val);
2306 if (!inFile) Config.noEcho();
2307
2308 return 0;
2309}
2310
2311/******************************************************************************/
2312/* x l i s t d e n y */
2313/******************************************************************************/
2314
2315/* Function: xlistdeny
2316
2317 Purpose: To parse the directive: listingdeny <yes|no|0|1>
2318
2319 <val> makes this redirector deny listings with an error
2320
2321 Output: 0 upon success or !0 upon failure.
2322 */
2323
2324int XrdHttpProtocol::xlistdeny(XrdOucStream & Config) {
2325 char *val;
2326
2327 // Get the path
2328 //
2329 val = Config.GetWord();
2330 if (!val || !val[0]) {
2331 eDest.Emsg("Config", "listingdeny flag not specified");
2332 return 1;
2333 }
2334
2335 // Record the value
2336 //
2337 listdeny = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2338
2339
2340 return 0;
2341}
2342
2343/******************************************************************************/
2344/* x l i s t r e d i r */
2345/******************************************************************************/
2346
2347/* Function: xlistredir
2348
2349 Purpose: To parse the directive: listingredir <Url>
2350
2351 <Url> http/https server to redirect to in the case of listing
2352
2353 Output: 0 upon success or !0 upon failure.
2354 */
2355
2356int XrdHttpProtocol::xlistredir(XrdOucStream & Config) {
2357 char *val;
2358
2359 // Get the path
2360 //
2361 val = Config.GetWord();
2362 if (!val || !val[0]) {
2363 eDest.Emsg("Config", "listingredir flag not specified");
2364 return 1;
2365 }
2366
2367 // Record the value
2368 //
2369 if (listredir) free(listredir);
2370 listredir = strdup(val);
2371
2372
2373 return 0;
2374}
2375
2376/******************************************************************************/
2377/* x s s l d e s t h t t p s */
2378/******************************************************************************/
2379
2380/* Function: xdesthttps
2381
2382 Purpose: To parse the directive: desthttps <yes|no|0|1>
2383
2384 <val> makes this redirector produce http or https redirection targets
2385
2386 Output: 0 upon success or !0 upon failure.
2387 */
2388
2389int XrdHttpProtocol::xdesthttps(XrdOucStream & Config) {
2390 char *val;
2391
2392 // Get the path
2393 //
2394 val = Config.GetWord();
2395 if (!val || !val[0]) {
2396 eDest.Emsg("Config", "desthttps flag not specified");
2397 return 1;
2398 }
2399
2400 // Record the value
2401 //
2402 isdesthttps = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2403
2404
2405 return 0;
2406}
2407
2408/******************************************************************************/
2409/* x e m b e d d e d s t a t i c */
2410/******************************************************************************/
2411
2412/* Function: xembeddedstatic
2413
2414 Purpose: To parse the directive: embeddedstatic <yes|no|0|1|true|false>
2415
2416 <val> this server will redirect HTTPS to itself using HTTP+token
2417
2418 Output: 0 upon success or !0 upon failure.
2419 */
2420
2421int XrdHttpProtocol::xembeddedstatic(XrdOucStream & Config) {
2422 char *val;
2423
2424 // Get the path
2425 //
2426 val = Config.GetWord();
2427 if (!val || !val[0]) {
2428 eDest.Emsg("Config", "embeddedstatic flag not specified");
2429 return 1;
2430 }
2431
2432 // Record the value
2433 //
2434 embeddedstatic = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2435
2436
2437 return 0;
2438}
2439
2440/******************************************************************************/
2441/* x r e d i r s t a t i c */
2442/******************************************************************************/
2443
2444/* Function: xstaticredir
2445
2446 Purpose: To parse the directive: staticredir <Url>
2447
2448 <Url> http/https server to redirect to in the case of /static
2449
2450 Output: 0 upon success or !0 upon failure.
2451 */
2452
2453int XrdHttpProtocol::xstaticredir(XrdOucStream & Config) {
2454 char *val;
2455
2456 // Get the path
2457 //
2458 val = Config.GetWord();
2459 if (!val || !val[0]) {
2460 eDest.Emsg("Config", "staticredir url not specified");
2461 return 1;
2462 }
2463
2464 // Record the value
2465 //
2466 if (staticredir) free(staticredir);
2467 staticredir = strdup(val);
2468
2469 return 0;
2470}
2471
2472/******************************************************************************/
2473/* x p r e l o a d s t a t i c */
2474/******************************************************************************/
2475
2476/* Function: xpreloadstatic
2477
2478 Purpose: To parse the directive: preloadstatic <http url path> <local file>
2479
2480 <http url path> http/http path whose response we are preloading
2481 e.g. /static/mycss.css
2482 NOTE: this must start with /static
2483
2484
2485 Output: 0 upon success or !0 upon failure.
2486 */
2487
2488int XrdHttpProtocol::xstaticpreload(XrdOucStream & Config) {
2489 char *val, *k, key[1024];
2490
2491 // Get the key
2492 //
2493 k = Config.GetWord();
2494 if (!k || !k[0]) {
2495 eDest.Emsg("Config", "preloadstatic urlpath not specified");
2496 return 1;
2497 }
2498
2499 strcpy(key, k);
2500
2501 // Get the val
2502 //
2503 val = Config.GetWord();
2504 if (!val || !val[0]) {
2505 eDest.Emsg("Config", "preloadstatic filename not specified");
2506 return 1;
2507 }
2508
2509 // Try to load the file into memory
2510 int fp = open(val, O_RDONLY);
2511 if( fp < 0 ) {
2512 eDest.Emsg("Config", errno, "open preloadstatic filename", val);
2513 return 1;
2514 }
2515
2516 StaticPreloadInfo *nfo = new StaticPreloadInfo;
2517 // Max 64Kb ok?
2518 nfo->data = (char *)malloc(65536);
2519 nfo->len = read(fp, (void *)nfo->data, 65536);
2520 close(fp);
2521
2522 if (nfo->len <= 0) {
2523 eDest.Emsg("Config", errno, "read from preloadstatic filename", val);
2524 return 1;
2525 }
2526
2527 if (nfo->len >= 65536) {
2528 eDest.Emsg("Config", "Truncated preloadstatic filename. Max is 64 KB '", val, "'");
2529 return 1;
2530 }
2531
2532 // Record the value
2533 //
2534 if (!staticpreload)
2536
2537 staticpreload->Rep((const char *)key, nfo);
2538 return 0;
2539}
2540
2541/******************************************************************************/
2542/* x s e l f h t t p s 2 h t t p */
2543/******************************************************************************/
2544
2545/* Function: selfhttps2http
2546
2547 Purpose: To parse the directive: selfhttps2http <yes|no|0|1>
2548
2549 <val> this server will redirect HTTPS to itself using HTTP+token
2550
2551 Output: 0 upon success or !0 upon failure.
2552 */
2553
2554int XrdHttpProtocol::xselfhttps2http(XrdOucStream & Config) {
2555 char *val;
2556
2557 // Get the path
2558 //
2559 val = Config.GetWord();
2560 if (!val || !val[0]) {
2561 eDest.Emsg("Config", "selfhttps2http flag not specified");
2562 return 1;
2563 }
2564
2565 // Record the value
2566 //
2567 selfhttps2http = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2568
2569
2570 return 0;
2571}
2572
2573/******************************************************************************/
2574/* x s e c x t r a c t o r */
2575/******************************************************************************/
2576
2577/* Function: xsecxtractor
2578
2579 Purpose: To parse the directive: secxtractor [required] <path> <params>
2580
2581 required optional parameter which if present treats any secxtractor
2582 errors as fatal.
2583 <path> the path of the plugin to be loaded
2584 <params> parameters passed to the secxtractor library
2585
2586 Output: 0 upon success or !0 upon failure.
2587 */
2588
2589int XrdHttpProtocol::xsecxtractor(XrdOucStream& Config) {
2590 char *val;
2591
2592 // Get the path
2593 //
2594 val = Config.GetWord();
2595 if (!val || !val[0]) {
2596 eDest.Emsg("Config", "No security extractor plugin specified.");
2597 return 1;
2598 } else {
2599 // Handle optional parameter [required]
2600 //
2601 if (!strncmp(val, "required", 8)) {
2602 isRequiredXtractor = true;
2603 val = Config.GetWord();
2604
2605 if (!val || !val[0]) {
2606 eDest.Emsg("Config", "No security extractor plugin after [required] "
2607 "parameter");
2608 return 1;
2609 }
2610 }
2611
2612 char libName[4096];
2613 strlcpy(libName, val, sizeof(libName));
2614 libName[sizeof(libName) - 1] = '\0';
2615 char libParms[4096];
2616
2617 if (!Config.GetRest(libParms, 4095)) {
2618 eDest.Emsg("Config", "secxtractor config params longer than 4k");
2619 return 1;
2620 }
2621
2622 // Try to load the plugin (if available) that extracts info from the
2623 // user cert/proxy
2624 if (LoadSecXtractor(&eDest, libName, libParms)) {
2625 return 1;
2626 }
2627 }
2628
2629 return 0;
2630}
2631
2632/******************************************************************************/
2633/* x e x t h a n d l e r */
2634/******************************************************************************/
2635
2636/* Function: xexthandler
2637 *
2638 * Purpose: To parse the directive: exthandler <name> <path> <initparm>
2639 *
2640 * <name> a unique name (max 16chars) to be given to this
2641 * instance, e.g 'myhandler1'
2642 * <path> the path of the plugin to be loaded
2643 * <initparm> a string parameter (e.g. a config file) that is
2644 * passed to the initialization of the plugin
2645 *
2646 * Output: 0 upon success or !0 upon failure.
2647 */
2648
2649int XrdHttpProtocol::xexthandler(XrdOucStream &Config,
2650 std::vector<extHInfo> &hiVec) {
2651 char *val, path[1024], namebuf[1024];
2652 char *parm;
2653 // By default, every external handler need TLS configured to be loaded
2654 bool noTlsOK = false;
2655
2656 // Get the name
2657 //
2658 val = Config.GetWord();
2659 if (!val || !val[0]) {
2660 eDest.Emsg("Config", "No instance name specified for an http external handler plugin.");
2661 return 1;
2662 }
2663 if (strlen(val) >= 16) {
2664 eDest.Emsg("Config", "Instance name too long for an http external handler plugin.");
2665 return 1;
2666 }
2667 strncpy(namebuf, val, sizeof(namebuf));
2668 namebuf[ sizeof(namebuf)-1 ] = '\0';
2669
2670 // Get the +notls option if it was provided
2671 val = Config.GetWord();
2672
2673 if(val && !strcmp("+notls",val)) {
2674 noTlsOK = true;
2675 val = Config.GetWord();
2676 }
2677
2678 // Get the path
2679 //
2680 if (!val || !val[0]) {
2681 eDest.Emsg("Config", "No http external handler plugin specified.");
2682 return 1;
2683 }
2684 if (strlen(val) >= (int)sizeof(path)) {
2685 eDest.Emsg("Config", "Path too long for an http external handler plugin.");
2686 return 1;
2687 }
2688
2689 strcpy(path, val);
2690
2691 // Everything else is a free string
2692 //
2693 parm = Config.GetWord();
2694
2695 // Verify whether this is a duplicate (we never supported replacements)
2696 //
2697 for (int i = 0; i < (int)hiVec.size(); i++)
2698 {if (hiVec[i].extHName == namebuf) {
2699 eDest.Emsg("Config", "Instance name already present for "
2700 "http external handler plugin",
2701 hiVec[i].extHPath.c_str());
2702 return 1;
2703 }
2704 }
2705
2706 // Verify that we don't have more already than we are allowed to have
2707 //
2708 if (hiVec.size() >= MAX_XRDHTTPEXTHANDLERS) {
2709 eDest.Emsg("Config", "Cannot load one more exthandler. Max is 4");
2710 return 1;
2711 }
2712
2713 // Create an info struct and push it on the list of ext handlers to load
2714 //
2715 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm : ""), noTlsOK));
2716
2717 return 0;
2718}
2719
2720/******************************************************************************/
2721/* x h e a d e r 2 c g i */
2722/******************************************************************************/
2723
2724/* Function: xheader2cgi
2725 *
2726 * Purpose: To parse the directive: header2cgi <headerkey> <cgikey>
2727 *
2728 * <headerkey> the name of an incoming HTTP header
2729 * to be transformed
2730 * <cgikey> the name to be given when adding it to the cgi info
2731 * that is kept only internally
2732 *
2733 * Output: 0 upon success or !0 upon failure.
2734 */
2735
2736int XrdHttpProtocol::xheader2cgi(XrdOucStream & Config) {
2737 return parseHeader2CGI(Config,eDest,hdr2cgimap);
2738}
2739
2740/******************************************************************************/
2741/* x s s l c a d i r */
2742/******************************************************************************/
2743
2744/* Function: xsslcadir
2745
2746 Purpose: To parse the directive: sslcadir <path>
2747
2748 <path> the path of the server key to be used.
2749
2750 Output: 0 upon success or !0 upon failure.
2751 */
2752
2753int XrdHttpProtocol::xsslcadir(XrdOucStream & Config) {
2754 char *val;
2755
2756 // Get the path
2757 //
2758 val = Config.GetWord();
2759 if (!val || !val[0]) {
2760 eDest.Emsg("Config", "HTTP X509 CAdir not specified");
2761 return 1;
2762 }
2763
2764 // Record the path
2765 //
2766 if (sslcadir) free(sslcadir);
2767 sslcadir = strdup(val);
2768
2769 if (xrdctxVer){ HTTPS_ALERT("cadir","tlsca",false); }
2770 return 0;
2771}
2772
2773/******************************************************************************/
2774/* x s s l c i p h e r f i l t e r */
2775/******************************************************************************/
2776
2777/* Function: xsslcipherfilter
2778
2779 Purpose: To parse the directive: cipherfilter <filter>
2780
2781 <filter> the filter string to be used when generating
2782 the SSL cipher list
2783
2784 Output: 0 upon success or !0 upon failure.
2785 */
2786
2787int XrdHttpProtocol::xsslcipherfilter(XrdOucStream & Config) {
2788 char *val;
2789
2790 // Get the filter string
2791 //
2792 val = Config.GetWord();
2793 if (!val || !val[0]) {
2794 eDest.Emsg("Config", "SSL cipherlist filter string not specified");
2795 return 1;
2796 }
2797
2798 // Record the filter string
2799 //
2801 sslcipherfilter = strdup(val);
2802
2803 return 0;
2804}
2805
2806/******************************************************************************/
2807/* x t l s r e u s e */
2808/******************************************************************************/
2809
2810/* Function: xtlsreuse
2811
2812 Purpose: To parse the directive: tlsreuse {on | off}
2813
2814 Output: 0 upon success or 1 upon failure.
2815 */
2816
2817int XrdHttpProtocol::xtlsreuse(XrdOucStream & Config) {
2818
2819 char *val;
2820
2821// Get the argument
2822//
2823 val = Config.GetWord();
2824 if (!val || !val[0])
2825 {eDest.Emsg("Config", "tlsreuse argument not specified"); return 1;}
2826
2827// If it's off, we set it off
2828//
2829 if (!strcmp(val, "off"))
2831 return 0;
2832 }
2833
2834// If it's on we set it on.
2835//
2836 if (!strcmp(val, "on"))
2838 return 0;
2839 }
2840
2841// Bad argument
2842//
2843 eDest.Emsg("config", "invalid tlsreuse parameter -", val);
2844 return 1;
2845}
2846
2847int XrdHttpProtocol::xauth(XrdOucStream &Config) {
2848 char *val = Config.GetWord();
2849 if(val) {
2850 if(!strcmp("tpc",val)) {
2851 if(!(val = Config.GetWord())) {
2852 eDest.Emsg("Config", "http.auth tpc value not specified."); return 1;
2853 } else {
2854 if(!strcmp("fcreds",val)) {
2855 tpcForwardCreds = true;
2856 } else {
2857 eDest.Emsg("Config", "http.auth tpc value is invalid"); return 1;
2858 }
2859 }
2860 } else {
2861 eDest.Emsg("Config", "http.auth value is invalid"); return 1;
2862 }
2863 }
2864 return 0;
2865}
2866
2867/******************************************************************************/
2868/* x t r a c e */
2869/******************************************************************************/
2870
2871/* Function: xtrace
2872
2873 Purpose: To parse the directive: trace <events>
2874
2875 <events> the blank separated list of events to trace. Trace
2876 directives are cumulative.
2877
2878 Output: 0 upon success or 1 upon failure.
2879 */
2880
2881int XrdHttpProtocol::xtrace(XrdOucStream & Config) {
2882
2883 char *val;
2884
2885 static struct traceopts {
2886 const char *opname;
2887 int opval;
2888 } tropts[] = {
2889 {"all", TRACE_ALL},
2890 {"auth", TRACE_AUTH},
2891 {"debug", TRACE_DEBUG},
2892 {"mem", TRACE_MEM},
2893 {"redirect", TRACE_REDIR},
2894 {"request", TRACE_REQ},
2895 {"response", TRACE_RSP}
2896 };
2897 int i, neg, trval = 0, numopts = sizeof (tropts) / sizeof (struct traceopts);
2898
2899 if (!(val = Config.GetWord())) {
2900 eDest.Emsg("config", "trace option not specified");
2901 return 1;
2902 }
2903 while (val) {
2904 if (!strcmp(val, "off")) trval = 0;
2905 else {
2906 if ((neg = (val[0] == '-' && val[1]))) val++;
2907 for (i = 0; i < numopts; i++) {
2908 if (!strcmp(val, tropts[i].opname)) {
2909 if (neg) trval &= ~tropts[i].opval;
2910 else trval |= tropts[i].opval;
2911 break;
2912 }
2913 }
2914 if (i >= numopts)
2915 eDest.Emsg("config", "invalid trace option", val);
2916 }
2917 val = Config.GetWord();
2918 }
2919 XrdHttpTrace.What = trval;
2920 return 0;
2921}
2922
2923int XrdHttpProtocol::doStat(char *fname) {
2924 int l;
2925 bool b;
2926 CurrentReq.filesize = 0;
2929
2930 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2932 memset(CurrentReq.xrdreq.stat.reserved, 0,
2933 sizeof (CurrentReq.xrdreq.stat.reserved));
2934 l = strlen(fname) + 1;
2935 CurrentReq.xrdreq.stat.dlen = htonl(l);
2936
2937 if (!Bridge) return -1;
2938 b = Bridge->Run((char *) &CurrentReq.xrdreq, fname, l);
2939 if (!b) {
2940 return -1;
2941 }
2942
2943
2944 return 0;
2945}
2946
2947/******************************************************************************/
2948/* d o C h k s u m */
2949/******************************************************************************/
2950
2951int XrdHttpProtocol::doChksum(const XrdOucString &fname) {
2952 size_t length;
2953 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2959 length = fname.length() + 1;
2960 CurrentReq.xrdreq.query.dlen = htonl(length);
2961
2962 if (!Bridge) return -1;
2963
2964 return Bridge->Run(reinterpret_cast<char *>(&CurrentReq.xrdreq), const_cast<char *>(fname.c_str()), length) ? 0 : -1;
2965}
2966
2967
2968static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION);
2969
2970// Loads the SecXtractor plugin, if available
2971int XrdHttpProtocol::LoadSecXtractor(XrdSysError *myeDest, const char *libName,
2972 const char *libParms) {
2973
2974
2975 // We don't want to load it more than once
2976 if (secxtractor) return 1;
2977
2978 XrdOucPinLoader myLib(myeDest, &compiledVer, "secxtractorlib", libName);
2980
2981 // Get the entry point of the object creator
2982 //
2983 ep = (XrdHttpSecXtractor *(*)(XrdHttpSecXtractorArgs))(myLib.Resolve("XrdHttpGetSecXtractor"));
2984 if (ep && (secxtractor = ep(myeDest, NULL, libParms))) return 0;
2985 myLib.Unload();
2986 return 1;
2987}
2988/******************************************************************************/
2989/* L o a d E x t H a n d l e r */
2990/******************************************************************************/
2991
2992int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec, const char *cFN, XrdOucEnv &myEnv) {
2993 for (int i = 0; i < (int) hiVec.size(); i++) {
2994 if(hiVec[i].extHNoTlsOK) {
2995 // The external plugin does not need TLS to be loaded
2996 if (LoadExtHandler(&eDest, hiVec[i].extHPath.c_str(), cFN,
2997 hiVec[i].extHParm.c_str(), &myEnv,
2998 hiVec[i].extHName.c_str()))
2999 return 1;
3000 }
3001 }
3002 return 0;
3003}
3004
3005int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
3006 const char *cFN, XrdOucEnv &myEnv) {
3007
3008 // Add the pointer to the cadir and the cakey to the environment.
3009 //
3010 if (sslcadir) myEnv.Put("http.cadir", sslcadir);
3011 if (sslcafile) myEnv.Put("http.cafile", sslcafile);
3012 if (sslcert) myEnv.Put("http.cert", sslcert);
3013 if (sslkey) myEnv.Put("http.key" , sslkey);
3014
3015 // Load all of the specified external handlers.
3016 //
3017 for (int i = 0; i < (int)hiVec.size(); i++) {
3018 // Only load the external handlers that were not already loaded
3019 // by LoadExtHandlerNoTls(...)
3020 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3021 if (LoadExtHandler(&eDest, hiVec[i].extHPath.c_str(), cFN,
3022 hiVec[i].extHParm.c_str(), &myEnv,
3023 hiVec[i].extHName.c_str())) return 1;
3024 }
3025 }
3026 return 0;
3027}
3028
3029// Loads the external handler plugin, if available
3030int XrdHttpProtocol::LoadExtHandler(XrdSysError *myeDest, const char *libName,
3031 const char *configFN, const char *libParms,
3032 XrdOucEnv *myEnv, const char *instName) {
3033
3034
3035 // This function will avoid loading doubles. No idea why this happens
3036 if (ExtHandlerLoaded(instName)) {
3037 eDest.Emsg("Config", "Instance name already present for an http external handler plugin.");
3038 return 1;
3039 }
3040 if (exthandlercnt >= MAX_XRDHTTPEXTHANDLERS) {
3041 eDest.Emsg("Config", "Cannot load one more exthandler. Max is 4");
3042 return 1;
3043 }
3044
3045 XrdOucPinLoader myLib(myeDest, &compiledVer, "exthandlerlib", libName);
3047
3048 // Get the entry point of the object creator
3049 //
3050 ep = (XrdHttpExtHandler *(*)(XrdHttpExtHandlerArgs))(myLib.Resolve("XrdHttpGetExtHandler"));
3051
3052 XrdHttpExtHandler *newhandler;
3053 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3054
3055 // Handler has been loaded, it's the last one in the list
3056 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3057 exthandler[exthandlercnt].name[15] = '\0';
3058 exthandler[exthandlercnt++].ptr = newhandler;
3059
3060 return 0;
3061 }
3062
3063 myLib.Unload();
3064 return 1;
3065}
3066
3067
3068
3069// Tells if we have already loaded a certain exthandler. Try to
3070// privilege speed, as this func may be invoked pretty often
3071bool XrdHttpProtocol::ExtHandlerLoaded(const char *handlername) {
3072 for (int i = 0; i < exthandlercnt; i++) {
3073 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3074 return true;
3075 }
3076 }
3077 return false;
3078}
3079
3080// Locates a matching external handler for a given request, if available. Try to
3081// privilege speed, as this func is invoked for every incoming request
3082XrdHttpExtHandler * XrdHttpProtocol::FindMatchingExtHandler(const XrdHttpReq &req) {
3083
3084 for (int i = 0; i < exthandlercnt; i++) {
3085 if (exthandler[i].ptr->MatchesPath(req.requestverb.c_str(), req.resource.c_str())) {
3086 return exthandler[i].ptr;
3087 }
3088 }
3089 return NULL;
3090}
#define kXR_isManager
kXR_unt16 requestid
Definition XProtocol.hh:630
kXR_char reserved1[2]
Definition XProtocol.hh:632
kXR_char reserved[11]
Definition XProtocol.hh:770
kXR_char reserved2[8]
Definition XProtocol.hh:634
kXR_char fhandle[4]
Definition XProtocol.hh:633
@ kXR_query
Definition XProtocol.hh:113
@ kXR_stat
Definition XProtocol.hh:129
#define kXR_isServer
struct ClientQueryRequest query
Definition XProtocol.hh:866
kXR_unt16 requestid
Definition XProtocol.hh:768
struct ClientStatRequest stat
Definition XProtocol.hh:873
@ kXR_Qcksum
Definition XProtocol.hh:617
#define DEBUG(x)
#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)
#define TS_Xeq(x, m)
XrdSysTrace XrdHttpTrace("http")
static int BIO_XrdLink_read(BIO *bio, char *data, size_t datal, size_t *read)
#define TS_Xeq3(x, m)
static int BIO_XrdLink_destroy(BIO *bio)
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
#define MAX_XRDHTTPEXTHANDLERS
#define XrdHttpSecXtractorArgs
#define TRACE_AUTH
#define TRACE_REQ
#define TRACE_RSP
#define TRACE_REDIR
int fclose(FILE *stream)
#define close(a)
Definition XrdPosix.hh:43
#define fstat(a, b)
Definition XrdPosix.hh:57
#define open
Definition XrdPosix.hh:71
#define stat(a, b)
Definition XrdPosix.hh:96
#define read(a, b, c)
Definition XrdPosix.hh:77
#define eMsg(x)
struct myOpts opts
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TLS_SET_VDEPTH(cOpts, vdv)
#define TLS_SET_REFINT(cOpts, refi)
#define TRACE_DEBUG
Definition XrdTrace.hh:36
#define TRACE_MEM
Definition XrdTrace.hh:38
#define TRACE(act, x)
Definition XrdTrace.hh:63
#define TRACE_ALL
Definition XrdTrace.hh:35
#define TRACEI(act, x)
Definition XrdTrace.hh:66
void Release(XrdBuffer *bp)
Definition XrdBuffer.cc:221
char * buff
Definition XrdBuffer.hh:45
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 * sslcafile
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 XrdSysError eDest
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.
static char * sslkey
int doStat(char *fname)
Perform a Stat request.
static int readWait
Timeout for reading data.
static char * sslcadir
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 int Port
Our port.
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.
std::string requestverb
long filemodtime
long long filesize
ClientRequest xrdreq
The last issued xrd request, often pending.
virtual void reset()
virtual int FreeSSL(SSL *)
void Set(int inQMax, time_t agemax=1800)
Definition XrdObject.icc:90
static bool Import(const char *var, char *&val)
Definition XrdOucEnv.cc:204
void Put(const char *varname, const char *value)
Definition XrdOucEnv.hh:85
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)
int length() const
const char * c_str() const
XrdBuffManager * BPool
XrdScheduler * Sched
XrdTlsContext * tlsCtx
XrdSysError * eDest
XrdOucEnv * theEnv
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
XrdCmsConfig Config
static const int hsmOff
static const int hsmMan
static const int hsmOn
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.

◆ TRACELINK [1/3]

#define TRACELINK   lp

Definition at line 216 of file XrdHttpProtocol.cc.

◆ TRACELINK [2/3]

#define TRACELINK   Link

Definition at line 216 of file XrdHttpProtocol.cc.

◆ TRACELINK [3/3]

#define TRACELINK   Link

Definition at line 216 of file XrdHttpProtocol.cc.

◆ TS_Xeq

#define TS_Xeq (   x,
 
)    (!strcmp(x,var)) GoNo = m(Config)

Definition at line 972 of file XrdHttpProtocol.cc.

◆ TS_Xeq3

#define TS_Xeq3 (   x,
 
)    (!strcmp(x,var)) GoNo = m(Config, extHIVec)

Definition at line 974 of file XrdHttpProtocol.cc.

◆ XRHTTP_TK_GRACETIME

#define XRHTTP_TK_GRACETIME   600

Definition at line 58 of file XrdHttpProtocol.cc.

Function Documentation

◆ BIO_get_data()

void * BIO_get_data ( BIO *  bio)

Definition at line 157 of file XrdHttpProtocol.cc.

157 {
158 return bio->ptr;
159}

Referenced by BIO_XrdLink_destroy(), BIO_XrdLink_read(), and BIO_XrdLink_write().

+ Here is the caller graph for this function:

◆ BIO_get_flags()

int BIO_get_flags ( BIO *  bio)

Definition at line 164 of file XrdHttpProtocol.cc.

164 {
165 return bio->flags;
166}

◆ BIO_get_init()

int BIO_get_init ( BIO *  bio)

Definition at line 171 of file XrdHttpProtocol.cc.

171 {
172 return bio->init;
173}

◆ BIO_get_shutdown()

int BIO_get_shutdown ( BIO *  bio)

Definition at line 180 of file XrdHttpProtocol.cc.

180 {
181 return bio->shutdown;
182}

Referenced by BIO_XrdLink_ctrl(), and BIO_XrdLink_destroy().

+ Here is the caller graph for this function:

◆ BIO_set_data()

void BIO_set_data ( BIO *  bio,
void *  ptr 
)

Definition at line 160 of file XrdHttpProtocol.cc.

160 {
161 bio->ptr = ptr;
162}

Referenced by BIO_XrdLink_create().

+ Here is the caller graph for this function:

◆ BIO_set_flags()

void BIO_set_flags ( BIO *  bio,
int  flags 
)

Definition at line 168 of file XrdHttpProtocol.cc.

168 {
169 bio->flags = flags;
170}

Referenced by BIO_XrdLink_create(), BIO_XrdLink_destroy(), and Tobase64().

+ Here is the caller graph for this function:

◆ BIO_set_init()

void BIO_set_init ( BIO *  bio,
int  init 
)

Definition at line 174 of file XrdHttpProtocol.cc.

174 {
175 bio->init = init;
176}

Referenced by BIO_XrdLink_create(), and BIO_XrdLink_destroy().

+ Here is the caller graph for this function:

◆ BIO_set_shutdown()

void BIO_set_shutdown ( BIO *  bio,
int  shut 
)

Definition at line 177 of file XrdHttpProtocol.cc.

177 {
178 bio->shutdown = shut;
179}

Referenced by BIO_XrdLink_ctrl().

+ Here is the caller graph for this function:

◆ BIO_XrdLink_create()

static int BIO_XrdLink_create ( BIO *  bio)
static

Definition at line 404 of file XrdHttpProtocol.cc.

405{
406
407
408 BIO_set_init(bio, 0);
409 //BIO_set_next(bio, 0);
410 BIO_set_data(bio, NULL);
411 BIO_set_flags(bio, 0);
412
413#if OPENSSL_VERSION_NUMBER < 0x10100000L
414
415 bio->num = 0;
416
417#endif
418
419 return 1;
420}
void BIO_set_init(BIO *bio, int init)
void BIO_set_data(BIO *bio, void *ptr)
void BIO_set_flags(BIO *bio, int flags)

References BIO_set_data(), BIO_set_flags(), and BIO_set_init().

+ Here is the call graph for this function:

◆ BIO_XrdLink_ctrl()

static long BIO_XrdLink_ctrl ( BIO *  bio,
int  cmd,
long  num,
void *  ptr 
)
static

Definition at line 437 of file XrdHttpProtocol.cc.

438{
439 long ret = 1;
440 switch (cmd) {
441 case BIO_CTRL_GET_CLOSE:
442 ret = BIO_get_shutdown(bio);
443 break;
444 case BIO_CTRL_SET_CLOSE:
445 BIO_set_shutdown(bio, (int)num);
446 break;
447 case BIO_CTRL_DUP:
448 case BIO_CTRL_FLUSH:
449 ret = 1;
450 break;
451 default:
452 ret = 0;
453 break;
454 }
455 return ret;
456}
int BIO_get_shutdown(BIO *bio)
void BIO_set_shutdown(BIO *bio, int shut)

References BIO_get_shutdown(), and BIO_set_shutdown().

+ Here is the call graph for this function:

◆ BIO_XrdLink_destroy()

static int BIO_XrdLink_destroy ( BIO *  bio)
static

Definition at line 423 of file XrdHttpProtocol.cc.

424{
425 if (bio == NULL) return 0;
426 if (BIO_get_shutdown(bio)) {
427 if (BIO_get_data(bio)) {
428 static_cast<XrdLink*>(BIO_get_data(bio))->Close();
429 }
430 BIO_set_init(bio, 0);
431 BIO_set_flags(bio, 0);
432 }
433 return 1;
434}
void * BIO_get_data(BIO *bio)
CloseImpl< false > Close(Ctx< File > file, uint16_t timeout=0)
Factory for creating CloseImpl objects.

References BIO_get_data(), BIO_get_shutdown(), BIO_set_flags(), and BIO_set_init().

+ Here is the call graph for this function:

◆ BIO_XrdLink_read()

static int BIO_XrdLink_read ( BIO *  bio,
char *  data,
size_t  datal,
size_t *  read 
)
static

Definition at line 363 of file XrdHttpProtocol.cc.

364{
365 if (!data || !bio) {
366 *read = 0;
367 return 0;
368 }
369
370 errno = 0;
371
372 XrdLink *lp = static_cast<XrdLink *>(BIO_get_data(bio));
373 int ret = lp->Recv(data, datal);
374 BIO_clear_retry_flags(bio);
375 if (ret <= 0) {
376 *read = 0;
377 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
378 BIO_set_retry_read(bio);
379 return ret;
380 }
381 *read = ret;
382}

References BIO_get_data(), read, and XrdLink::Recv().

+ Here is the call graph for this function:

◆ BIO_XrdLink_write()

int BIO_XrdLink_write ( BIO *  bio,
const char *  data,
size_t  datal,
size_t *  written 
)

Definition at line 320 of file XrdHttpProtocol.cc.

321{
322 if (!data || !bio) {
323 *written = 0;
324 return 0;
325 }
326
327 XrdLink *lp=static_cast<XrdLink *>(BIO_get_data(bio));
328
329 errno = 0;
330 int ret = lp->Send(data, datal);
331 BIO_clear_retry_flags(bio);
332 if (ret <= 0) {
333 *written = 0;
334 if ((errno == EINTR) || (errno == EINPROGRESS) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
335 BIO_set_retry_write(bio);
336 return ret;
337 }
338 *written = ret;
339 return 1;
340}

References BIO_get_data(), and XrdLink::Send().

+ Here is the call graph for this function:

◆ XrdVERSIONINFODEF()

static XrdVERSIONINFODEF ( compiledVer  ,
XrdHttpProtocolTest  ,
XrdVNUMBER  ,
XrdVERSION   
)
static

Variable Documentation

◆ XrdHttpSecEntityTident

const char* XrdHttpSecEntityTident = "http"

Definition at line 66 of file XrdHttpProtocol.cc.

◆ XrdHttpTrace

XrdSysTrace XrdHttpTrace("http") ( "http"  )