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 <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 975 of file XrdHttpProtocol.cc.

978 {
979 XrdOucEnv cfgEnv;
980 XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &cfgEnv, "=====> ");
981 std::vector<extHInfo> extHIVec;
982 char *var;
983 int cfgFD, GoNo, NoGo = 0, ismine;
984
985 var = nullptr;
986 XrdOucEnv::Import("XRD_READV_LIMITS", var);
987 XrdHttpReadRangeHandler::Configure(eDest, var, ReadRangeConfig);
988
989 pmarkHandle = (XrdNetPMark* ) myEnv->GetPtr("XrdNetPMark*");
990
991 cksumHandler.configure(xrd_cslist);
992 auto nonIanaChecksums = cksumHandler.getNonIANAConfiguredCksums();
993 if(nonIanaChecksums.size()) {
994 std::stringstream warningMsgSS;
995 warningMsgSS << "Config warning: the following checksum algorithms are not IANA compliant: [";
996 std::string unknownCksumString;
997 for(auto unknownCksum: nonIanaChecksums) {
998 unknownCksumString += unknownCksum + ",";
999 }
1000 unknownCksumString.erase(unknownCksumString.size() - 1);
1001 warningMsgSS << unknownCksumString << "]" << ". They therefore cannot be queried by a user via HTTP." ;
1002 eDest.Say(warningMsgSS.str().c_str());
1003 }
1004
1005 // Initialize our custom BIO type.
1006 if (!m_bio_type) {
1007
1008 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1009 m_bio_type = (26|0x0400|0x0100);
1010 m_bio_method = static_cast<BIO_METHOD*>(OPENSSL_malloc(sizeof(BIO_METHOD)));
1011
1012 if (m_bio_method) {
1013 memset(m_bio_method, '\0', sizeof(BIO_METHOD));
1014 m_bio_method->type = m_bio_type;
1015 m_bio_method->bwrite = BIO_XrdLink_write;
1016 m_bio_method->bread = BIO_XrdLink_read;
1017 m_bio_method->create = BIO_XrdLink_create;
1018 m_bio_method->destroy = BIO_XrdLink_destroy;
1019 m_bio_method->ctrl = BIO_XrdLink_ctrl;
1020 }
1021 #else
1022 // OpenSSL 1.1 has an internal counter for generating unique types.
1023 // We'll switch to that when widely available.
1024 m_bio_type = BIO_get_new_index();
1025 m_bio_method = BIO_meth_new(m_bio_type, "xrdhttp-bio-method");
1026
1027 if (m_bio_method) {
1028 BIO_meth_set_write(m_bio_method, BIO_XrdLink_write);
1029 BIO_meth_set_read(m_bio_method, BIO_XrdLink_read);
1030 BIO_meth_set_create(m_bio_method, BIO_XrdLink_create);
1031 BIO_meth_set_destroy(m_bio_method, BIO_XrdLink_destroy);
1032 BIO_meth_set_ctrl(m_bio_method, BIO_XrdLink_ctrl);
1033 }
1034
1035 #endif
1036 }
1037
1038 // If we have a tls context record whether it configured for verification
1039 // so that we can provide meaningful error and warning messages.
1040 //
1042
1043 // Open and attach the config file
1044 //
1045 if ((cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
1046 return eDest.Emsg("Config", errno, "open config file", ConfigFN);
1047 Config.Attach(cfgFD);
1048 static const char *cvec[] = { "*** http protocol config:", 0 };
1049 Config.Capture(cvec);
1050
1051 // Process items
1052 //
1053 while ((var = Config.GetMyFirstWord())) {
1054 if ((ismine = !strncmp("http.", var, 5)) && var[5]) var += 5;
1055
1056 if (ismine) {
1057 if TS_Xeq("trace", xtrace);
1058 else if TS_Xeq("cert", xsslcert);
1059 else if TS_Xeq("key", xsslkey);
1060 else if TS_Xeq("cadir", xsslcadir);
1061 else if TS_Xeq("cipherfilter", xsslcipherfilter);
1062 else if TS_Xeq("gridmap", xgmap);
1063 else if TS_Xeq("cafile", xsslcafile);
1064 else if TS_Xeq("secretkey", xsecretkey);
1065 else if TS_Xeq("desthttps", xdesthttps);
1066 else if TS_Xeq("secxtractor", xsecxtractor);
1067 else if TS_Xeq3("exthandler", xexthandler);
1068 else if TS_Xeq("selfhttps2http", xselfhttps2http);
1069 else if TS_Xeq("embeddedstatic", xembeddedstatic);
1070 else if TS_Xeq("listingredir", xlistredir);
1071 else if TS_Xeq("staticredir", xstaticredir);
1072 else if TS_Xeq("staticpreload", xstaticpreload);
1073 else if TS_Xeq("listingdeny", xlistdeny);
1074 else if TS_Xeq("header2cgi", xheader2cgi);
1075 else if TS_Xeq("httpsmode", xhttpsmode);
1076 else if TS_Xeq("tlsreuse", xtlsreuse);
1077 else if TS_Xeq("auth", xauth);
1078 else {
1079 eDest.Say("Config warning: ignoring unknown directive '", var, "'.");
1080 Config.Echo();
1081 continue;
1082 }
1083 if (GoNo) {
1084 Config.Echo();
1085 NoGo = 1;
1086 }
1087 }
1088 }
1089
1090// To minimize message confusion down, if an error occurred during config
1091// parsing, just bail out now with a confirming message.
1092//
1093 if (NoGo)
1094 {eDest.Say("Config failure: one or more directives are flawed!");
1095 return 1;
1096 }
1097
1098// Some headers must always be converted to CGI key=value pairs
1099//
1100 hdr2cgimap["Cache-Control"] = "cache-control";
1101
1102// Test if XrdEC is loaded
1103 if (getenv("XRDCL_EC")) usingEC = true;
1104
1105// If https was disabled, then issue a warning message if xrdtls configured
1106// of it's disabled because httpsmode was auto and xrdtls was not configured.
1107// If we get past this point then we know https is a plausible option but we
1108// can still fail if we cannot supply any missing but required options.
1109//
1110 if (httpsmode == hsmOff || (httpsmode == hsmAuto && !xrdctx && !httpsspec))
1111 {const char *why = (httpsmode == hsmOff ? "has been disabled!"
1112 : "was not configured.");
1113 const char *what = Configed();
1114
1115 eDest.Say("Config warning: HTTPS functionality ", why);
1116 httpsmode = hsmOff;
1117
1118 LoadExtHandlerNoTls(extHIVec, ConfigFN, *myEnv);
1119 if (what)
1120 {eDest.Say("Config failure: ", what, " HTTPS but it ", why);
1121 NoGo = 1;
1122 }
1123 return NoGo;
1124 }
1125
1126// Warn if a private key was specified without a cert as this has no meaning
1127// even as an auto overide as they must be paired.
1128//
1129 if (sslkey && !sslcert)
1130 {eDest.Say("Config warning: specifying http.key without http.cert "
1131 "is meaningless; ignoring key!");
1132 free(sslkey); sslkey = 0;
1133 }
1134
1135// If the mode is manual then we need to have at least a cert.
1136//
1137 if (httpsmode == hsmMan)
1138 {if (!sslcert)
1139 {eDest.Say("Config failure: 'httpsmode manual' requires atleast a "
1140 "a cert specification!");
1141 return 1;
1142 }
1143 }
1144
1145// If it's auto d through all possibilities. It's either auto with xrdtls
1146// configured or manual which needs at least a cert specification. For auto
1147// configuration we will only issue a warning if overrides were specified.
1148//
1149 if (httpsmode == hsmAuto && xrdctx)
1151 const char *what1 = 0, *what2 = 0, *what3 = 0;
1152
1153 if (!sslcert && cP->cert.size())
1154 {sslcert = strdup(cP->cert.c_str());
1155 if (cP->pkey.size()) sslkey = strdup(cP->pkey.c_str());
1156 what1 = "xrd.tls to supply 'cert' and 'key'.";
1157 }
1158 if (!sslcadir && cP->cadir.size())
1159 {sslcadir = strdup(cP->cadir.c_str());
1160 what2 = "xrd.tlsca to supply 'cadir'.";
1161 }
1162 if (!sslcafile && cP->cafile.size())
1163 {sslcafile = strdup(cP->cafile.c_str());
1164 what2 = (what2 ? "xrd.tlsca to supply 'cadir' and 'cafile'."
1165 : "xrd.tlsca to supply 'cafile'.");
1166 }
1168 crlRefIntervalSec = cP->crlRT;
1169 what3 = "xrd.tlsca to supply 'refresh' interval.";
1170 }
1171 if (!httpsspec && what1) eDest.Say("Config Using ", what1);
1172 if (!httpsspec && what2) eDest.Say("Config Using ", what2);
1173 if (!httpsspec && what3) eDest.Say("Config Using ", what3);
1174 }
1175
1176// If a gridmap or secxtractor is present then we must be able to verify certs
1177//
1178 if (!(sslcadir || sslcafile))
1179 {const char *what = Configed();
1180 const char *why = (httpsspec ? "a cadir or cafile was not specified!"
1181 : "'xrd.tlsca noverify' was specified!");
1182 if (what)
1183 {eDest.Say("Config failure: ", what, " cert verification but ", why);
1184 return 1;
1185 }
1186 }
1187 httpsmode = hsmOn;
1188
1189// Oddly we need to create an error bio at this point
1190//
1191 sslbio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
1192
1193// Now we can configure HTTPS. We will not reuse the passed context as we will
1194// be setting our own options specific to out implementation. One day we will.
1195//
1196 const char *how = "completed.";
1197 eDest.Say("++++++ HTTPS initialization started.");
1198 if (!InitTLS()) {NoGo = 1; how = "failed.";}
1199 eDest.Say("------ HTTPS initialization ", how);
1200 if (NoGo) return NoGo;
1201
1202// We can now load all the external handlers
1203//
1204 if (LoadExtHandler(extHIVec, ConfigFN, *myEnv)) return 1;
1205
1206// At this point, we can actually initialize security plugins
1207//
1208 return (InitSecurity() ? NoGo : 1);
1209}
1210
1211/******************************************************************************/
1212/* C o n f i g e d */
1213/******************************************************************************/
1214
1215const char *XrdHttpProtocol::Configed()
1216{
1217 if (secxtractor && gridmap) return "gridmap and secxtractor require";
1218 if (secxtractor) return "secxtractor requires";
1219 if (gridmap) return "gridmap requires";
1220 return 0;
1221}
1222
1223/******************************************************************************/
1224/* B u f f g e t L i n e */
1225/******************************************************************************/
1226
1228
1229int XrdHttpProtocol::BuffgetLine(XrdOucString &dest) {
1230
1231 dest = "";
1232 char save;
1233
1234 // Easy case
1235 if (myBuffEnd >= myBuffStart) {
1236 int l = 0;
1237 for (char *p = myBuffStart; p < myBuffEnd; p++) {
1238 l++;
1239 if (*p == '\n') {
1240 save = *(p+1);
1241 *(p+1) = '\0';
1242 dest.assign(myBuffStart, 0, l-1);
1243 *(p+1) = save;
1244
1245 //strncpy(dest, myBuffStart, l);
1246 //dest[l] = '\0';
1247 BuffConsume(l);
1248
1249 //if (dest[l-1] == '\n') dest[l - 1] = '\0';
1250 return l;
1251 }
1252
1253 }
1254
1255 return 0;
1256 } else {
1257 // More complex case... we have to do it in two segments
1258
1259 // Segment 1: myBuffStart->myBuff->buff+myBuff->bsize
1260 int l = 0;
1261 for (char *p = myBuffStart; p < myBuff->buff + myBuff->bsize; p++) {
1262 l++;
1263 if ((*p == '\n') || (*p == '\0')) {
1264 save = *(p+1);
1265 *(p+1) = '\0';
1266 dest.assign(myBuffStart, 0, l-1);
1267 *(p+1) = save;
1268
1269 //strncpy(dest, myBuffStart, l);
1270
1271 BuffConsume(l);
1272
1273 //if (dest[l-1] == '\n') dest[l - 1] = '\0';
1274 return l;
1275 }
1276
1277 }
1278
1279 // We did not find the \n, let's keep on searching in the 2nd segment
1280 // Segment 2: myBuff->buff --> myBuffEnd
1281 l = 0;
1282 for (char *p = myBuff->buff; p < myBuffEnd; p++) {
1283 l++;
1284 if ((*p == '\n') || (*p == '\0')) {
1285 save = *(p+1);
1286 *(p+1) = '\0';
1287 // Remember the 1st segment
1288 int l1 = myBuff->buff + myBuff->bsize - myBuffStart;
1289
1290 dest.assign(myBuffStart, 0, l1-1);
1291 //strncpy(dest, myBuffStart, l1);
1292 BuffConsume(l1);
1293
1294 dest.insert(myBuffStart, l1, l-1);
1295 //strncpy(dest + l1, myBuffStart, l);
1296 //dest[l + l1] = '\0';
1297 BuffConsume(l);
1298
1299 *(p+1) = save;
1300
1301 //if (dest[l + l1 - 1] == '\n') dest[l + l1 - 1] = '\0';
1302 return l + l1;
1303 }
1304
1305 }
1306
1307
1308
1309 }
1310
1311 return 0;
1312}
1313
1314/******************************************************************************/
1315/* g e t D a t a O n e S h o t */
1316/******************************************************************************/
1317
1318int XrdHttpProtocol::getDataOneShot(int blen, bool wait) {
1319 int rlen, maxread;
1320
1321 // Get up to blen bytes from the connection. Put them into mybuff.
1322 // This primitive, for the way it is used, is not supposed to block if wait=false
1323
1324 // Returns:
1325 // 2: no space left in buffer
1326 // 1: timeout
1327 // -1: error
1328 // 0: everything read correctly
1329
1330
1331
1332 // Check for buffer overflow first
1333 maxread = std::min(blen, BuffAvailable());
1334 TRACE(DEBUG, "getDataOneShot BuffAvailable: " << BuffAvailable() << " maxread: " << maxread);
1335
1336 if (!maxread)
1337 return 2;
1338
1339 if (ishttps) {
1340 int sslavail = maxread;
1341
1342 if (!wait) {
1343 int l = SSL_pending(ssl);
1344 if (l > 0)
1345 sslavail = std::min(maxread, SSL_pending(ssl));
1346 }
1347
1348 if (sslavail < 0) {
1349 Link->setEtext("link SSL_pending error");
1350 ERR_print_errors(sslbio_err);
1351 return -1;
1352 }
1353
1354 TRACE(DEBUG, "getDataOneShot sslavail: " << sslavail);
1355 if (sslavail <= 0) return 0;
1356
1357 if (myBuffEnd - myBuff->buff >= myBuff->bsize) {
1358 TRACE(DEBUG, "getDataOneShot Buffer panic");
1359 myBuffEnd = myBuff->buff;
1360 }
1361
1362 rlen = SSL_read(ssl, myBuffEnd, sslavail);
1363 if (rlen <= 0) {
1364 Link->setEtext("link SSL read error");
1365 ERR_print_errors(sslbio_err);
1366 return -1;
1367 }
1368
1369
1370 } else {
1371
1372 if (myBuffEnd - myBuff->buff >= myBuff->bsize) {
1373 TRACE(DEBUG, "getDataOneShot Buffer panic");
1374 myBuffEnd = myBuff->buff;
1375 }
1376
1377 if (wait)
1378 rlen = Link->Recv(myBuffEnd, maxread, readWait);
1379 else
1380 rlen = Link->Recv(myBuffEnd, maxread);
1381
1382
1383 if (rlen == 0) {
1384 Link->setEtext("link read error or closed");
1385 return -1;
1386 }
1387
1388 if (rlen < 0) {
1389 Link->setEtext("link timeout or other error");
1390 return -1;
1391 }
1392 }
1393
1394 myBuffEnd += rlen;
1395
1396 TRACE(REQ, "read " << rlen << " of " << blen << " bytes");
1397
1398 return 0;
1399}
1400
1402
1403int XrdHttpProtocol::BuffAvailable() {
1404 int r;
1405
1406 if (myBuffEnd >= myBuffStart)
1407 r = myBuff->buff + myBuff->bsize - myBuffEnd;
1408 else
1409 r = myBuffStart - myBuffEnd;
1410
1411 if ((r < 0) || (r > myBuff->bsize)) {
1412 TRACE(REQ, "internal error, myBuffAvailable: " << r << " myBuff->bsize " << myBuff->bsize);
1413 abort();
1414 }
1415
1416 return r;
1417}
1418
1419/******************************************************************************/
1420/* B u f f U s e d */
1421/******************************************************************************/
1422
1424
1425int XrdHttpProtocol::BuffUsed() {
1426 int r;
1427
1428 if (myBuffEnd >= myBuffStart)
1429 r = myBuffEnd - myBuffStart;
1430 else
1431
1432 r = myBuff->bsize - (myBuffStart - myBuffEnd);
1433
1434 if ((r < 0) || (r > myBuff->bsize)) {
1435 TRACE(REQ, "internal error, myBuffUsed: " << r << " myBuff->bsize " << myBuff->bsize);
1436 abort();
1437 }
1438
1439 return r;
1440}
1441
1442/******************************************************************************/
1443/* B u f f F r e e */
1444/******************************************************************************/
1445
1447
1448int XrdHttpProtocol::BuffFree() {
1449 return (myBuff->bsize - BuffUsed());
1450}
1451
1452/******************************************************************************/
1453/* B u f f C o n s u m e */
1454/******************************************************************************/
1455
1456void XrdHttpProtocol::BuffConsume(int blen) {
1457
1458 if (blen > myBuff->bsize) {
1459 TRACE(REQ, "internal error, BuffConsume(" << blen << ") smaller than buffsize");
1460 abort();
1461 }
1462
1463 if (blen > BuffUsed()) {
1464 TRACE(REQ, "internal error, BuffConsume(" << blen << ") larger than BuffUsed:" << BuffUsed());
1465 abort();
1466 }
1467
1468 myBuffStart = myBuffStart + blen;
1469
1470 if (myBuffStart >= myBuff->buff + myBuff->bsize)
1471 myBuffStart -= myBuff->bsize;
1472
1473 if (myBuffEnd >= myBuff->buff + myBuff->bsize)
1474 myBuffEnd -= myBuff->bsize;
1475
1476 if (BuffUsed() == 0)
1477 myBuffStart = myBuffEnd = myBuff->buff;
1478}
1479
1480/******************************************************************************/
1481/* B u f f g e t D a t a */
1482/******************************************************************************/
1483
1492int XrdHttpProtocol::BuffgetData(int blen, char **data, bool wait) {
1493 int rlen;
1494
1495 TRACE(DEBUG, "BuffgetData: requested " << blen << " bytes");
1496
1497
1498 if (wait) {
1499 // If there's not enough data in the buffer then wait on the socket until it comes
1500 if (blen > BuffUsed()) {
1501 TRACE(REQ, "BuffgetData: need to read " << blen - BuffUsed() << " bytes");
1502 if ( getDataOneShot(blen - BuffUsed(), true) )
1503 // The wanted data could not be read. Either timeout of connection closed
1504 return 0;
1505 }
1506 } else {
1507 // Get a peek at the socket, without waiting, if we have no data in the buffer
1508 if ( !BuffUsed() ) {
1509 if ( getDataOneShot(blen, false) )
1510 // The wanted data could not be read. Either timeout of connection closed
1511 return -1;
1512 }
1513 }
1514
1515 // And now make available the data taken from the buffer. Note that the buffer
1516 // may be empty...
1517 if (myBuffStart <= myBuffEnd) {
1518 rlen = std::min( (long) blen, (long)(myBuffEnd - myBuffStart) );
1519
1520 } else
1521 rlen = std::min( (long) blen, (long)(myBuff->buff + myBuff->bsize - myBuffStart) );
1522
1523 *data = myBuffStart;
1524 BuffConsume(rlen);
1525 return rlen;
1526}
1527
1528/******************************************************************************/
1529/* S e n d D a t a */
1530/******************************************************************************/
1531
1533
1534int XrdHttpProtocol::SendData(const char *body, int bodylen) {
1535
1536 int r;
1537
1538 if (body && bodylen) {
1539 TRACE(REQ, "Sending " << bodylen << " bytes");
1540 if (ishttps) {
1541 r = SSL_write(ssl, body, bodylen);
1542 if (r <= 0) {
1543 ERR_print_errors(sslbio_err);
1544 return -1;
1545 }
1546
1547 } else {
1548 r = Link->Send(body, bodylen);
1549 if (r <= 0) return -1;
1550 }
1551 }
1552
1553 return 0;
1554}
1555
1556/******************************************************************************/
1557/* S t a r t S i m p l e R e s p */
1558/******************************************************************************/
1559
1560int XrdHttpProtocol::StartSimpleResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1561 std::stringstream ss;
1562 const std::string crlf = "\r\n";
1563
1564 ss << "HTTP/1.1 " << code << " ";
1565 if (desc) {
1566 ss << desc;
1567 } else {
1568 if (code == 200) ss << "OK";
1569 else if (code == 100) ss << "Continue";
1570 else if (code == 206) ss << "Partial Content";
1571 else if (code == 302) ss << "Redirect";
1572 else if (code == 307) ss << "Temporary Redirect";
1573 else if (code == 400) ss << "Bad Request";
1574 else if (code == 403) ss << "Forbidden";
1575 else if (code == 404) ss << "Not Found";
1576 else if (code == 405) ss << "Method Not Allowed";
1577 else if (code == 416) ss << "Range Not Satisfiable";
1578 else if (code == 500) ss << "Internal Server Error";
1579 else if (code == 504) ss << "Gateway Timeout";
1580 else ss << "Unknown";
1581 }
1582 ss << crlf;
1583 if (keepalive && (code != 100))
1584 ss << "Connection: Keep-Alive" << crlf;
1585 else
1586 ss << "Connection: Close" << crlf;
1587
1588 ss << "Server: XrootD/" << XrdVSTRING << crlf;
1589
1590 if ((bodylen >= 0) && (code != 100))
1591 ss << "Content-Length: " << bodylen << crlf;
1592
1593 if (header_to_add && (header_to_add[0] != '\0'))
1594 ss << header_to_add << crlf;
1595
1596 ss << crlf;
1597
1598 const std::string &outhdr = ss.str();
1599 TRACEI(RSP, "Sending resp: " << code << " header len:" << outhdr.size());
1600 if (SendData(outhdr.c_str(), outhdr.size()))
1601 return -1;
1602
1603 return 0;
1604}
1605
1606/******************************************************************************/
1607/* S t a r t C h u n k e d R e s p */
1608/******************************************************************************/
1609
1610int XrdHttpProtocol::StartChunkedResp(int code, const char *desc, const char *header_to_add, long long bodylen, bool keepalive) {
1611 const std::string crlf = "\r\n";
1612 std::stringstream ss;
1613
1614 if (header_to_add && (header_to_add[0] != '\0')) {
1615 ss << header_to_add << crlf;
1616 }
1617
1618 ss << "Transfer-Encoding: chunked";
1619 TRACEI(RSP, "Starting chunked response");
1620 return StartSimpleResp(code, desc, ss.str().c_str(), bodylen, keepalive);
1621}
1622
1623/******************************************************************************/
1624/* C h u n k R e s p */
1625/******************************************************************************/
1626
1627int XrdHttpProtocol::ChunkResp(const char *body, long long bodylen) {
1628 long long content_length = (bodylen <= 0) ? (body ? strlen(body) : 0) : bodylen;
1629 if (ChunkRespHeader(content_length))
1630 return -1;
1631
1632 if (body && SendData(body, content_length))
1633 return -1;
1634
1635 return ChunkRespFooter();
1636}
1637
1638/******************************************************************************/
1639/* C h u n k R e s p H e a d e r */
1640/******************************************************************************/
1641
1642int XrdHttpProtocol::ChunkRespHeader(long long bodylen) {
1643 const std::string crlf = "\r\n";
1644 std::stringstream ss;
1645
1646 ss << std::hex << bodylen << std::dec << crlf;
1647
1648 const std::string &chunkhdr = ss.str();
1649 TRACEI(RSP, "Sending encoded chunk of size " << bodylen);
1650 return (SendData(chunkhdr.c_str(), chunkhdr.size())) ? -1 : 0;
1651}
1652
1653/******************************************************************************/
1654/* C h u n k R e s p F o o t e r */
1655/******************************************************************************/
1656
1657int XrdHttpProtocol::ChunkRespFooter() {
1658 const std::string crlf = "\r\n";
1659 return (SendData(crlf.c_str(), crlf.size())) ? -1 : 0;
1660}
1661
1662/******************************************************************************/
1663/* S e n d S i m p l e R e s p */
1664/******************************************************************************/
1665
1669
1670int XrdHttpProtocol::SendSimpleResp(int code, const char *desc, const char *header_to_add, const char *body, long long bodylen, bool keepalive) {
1671
1672 long long content_length = bodylen;
1673 if (bodylen <= 0) {
1674 content_length = body ? strlen(body) : 0;
1675 }
1676
1677 if (StartSimpleResp(code, desc, header_to_add, content_length, keepalive) < 0)
1678 return -1;
1679
1680 //
1681 // Send the data
1682 //
1683 if (body)
1684 return SendData(body, content_length);
1685
1686 return 0;
1687}
1688
1689/******************************************************************************/
1690/* C o n f i g u r e */
1691/******************************************************************************/
1692
1693int XrdHttpProtocol::Configure(char *parms, XrdProtocol_Config * pi) {
1694 /*
1695 Function: Establish configuration at load time.
1696
1697 Input: None.
1698
1699 Output: 0 upon success or !0 otherwise.
1700 */
1701
1702 char *rdf;
1703
1704 // Copy out the special info we want to use at top level
1705 //
1706 eDest.logger(pi->eDest->logger());
1708 // SI = new XrdXrootdStats(pi->Stats);
1709 Sched = pi->Sched;
1710 BPool = pi->BPool;
1711 xrd_cslist = getenv("XRD_CSLIST");
1712
1713 Port = pi->Port;
1714
1715 // Copy out the current TLS context
1716 //
1717 xrdctx = pi->tlsCtx;
1718
1719 {
1720 char buf[16];
1721 sprintf(buf, "%d", Port);
1722 Port_str = strdup(buf);
1723 }
1724
1725 // Now process and configuration parameters
1726 //
1727 rdf = (parms && *parms ? parms : pi->ConfigFN);
1728 if (rdf && Config(rdf, pi->theEnv)) return 0;
1730
1731 // Set the redirect flag if we are a pure redirector
1733 if ((rdf = getenv("XRDROLE"))) {
1734 eDest.Emsg("Config", "XRDROLE: ", rdf);
1735
1736 if (!strcasecmp(rdf, "manager") || !strcasecmp(rdf, "supervisor")) {
1738 eDest.Emsg("Config", "Configured as HTTP(s) redirector.");
1739 } else {
1740
1741 eDest.Emsg("Config", "Configured as HTTP(s) data server.");
1742 }
1743
1744 } else {
1745 eDest.Emsg("Config", "No XRDROLE specified.");
1746 }
1747
1748 // Schedule protocol object cleanup
1749 //
1752 ProtStack.Set((pi->ConnMax / 3 ? pi->ConnMax / 3 : 30), 60 * 60);
1753
1754 // Return success
1755 //
1756
1757 return 1;
1758}
1759
1760/******************************************************************************/
1761/* p a r s e H e a d e r 2 C G I */
1762/******************************************************************************/
1763int XrdHttpProtocol::parseHeader2CGI(XrdOucStream &Config, XrdSysError & err,std::map<std::string, std::string> &header2cgi) {
1764 char *val, keybuf[1024], parmbuf[1024];
1765 char *parm;
1766
1767 // Get the header key
1768 val = Config.GetWord();
1769 if (!val || !val[0]) {
1770 err.Emsg("Config", "No headerkey specified.");
1771 return 1;
1772 } else {
1773
1774 // Trim the beginning, in place
1775 while ( *val && !isalnum(*val) ) val++;
1776 strcpy(keybuf, val);
1777
1778 // Trim the end, in place
1779 char *pp;
1780 pp = keybuf + strlen(keybuf) - 1;
1781 while ( (pp >= keybuf) && (!isalnum(*pp)) ) {
1782 *pp = '\0';
1783 pp--;
1784 }
1785
1786 parm = Config.GetWord();
1787
1788 // Avoids segfault in case a key is given without value
1789 if(!parm || !parm[0]) {
1790 err.Emsg("Config", "No header2cgi value specified. key: '", keybuf, "'");
1791 return 1;
1792 }
1793
1794 // Trim the beginning, in place
1795 while ( *parm && !isalnum(*parm) ) parm++;
1796 strcpy(parmbuf, parm);
1797
1798 // Trim the end, in place
1799 pp = parmbuf + strlen(parmbuf) - 1;
1800 while ( (pp >= parmbuf) && (!isalnum(*pp)) ) {
1801 *pp = '\0';
1802 pp--;
1803 }
1804
1805 // Add this mapping to the map that will be used
1806 try {
1807 header2cgi[keybuf] = parmbuf;
1808 } catch ( ... ) {
1809 err.Emsg("Config", "Can't insert new header2cgi rule. key: '", keybuf, "'");
1810 return 1;
1811 }
1812
1813 }
1814 return 0;
1815}
1816
1817
1818/******************************************************************************/
1819/* I n i t T L S */
1820/******************************************************************************/
1821
1822bool XrdHttpProtocol::InitTLS() {
1823
1824 std::string eMsg;
1827
1828// Create a new TLS context
1829//
1830 if (sslverifydepth > 255) sslverifydepth = 255;
1832 //TLS_SET_REFINT will set the refresh interval in minutes, hence the division by 60
1835
1836// Make sure the context was created
1837//
1838 if (!xrdctx->isOK())
1839 {eDest.Say("Config failure: ", eMsg.c_str());
1840 return false;
1841 }
1842
1843// Setup session cache (this is controversial). The default is off but many
1844// programs expect it being enabled and break when it is disabled. In such
1845// cases it should be enabled. This is, of course, a big OpenSSL mess.
1846//
1847 static const char *sess_ctx_id = "XrdHTTPSessionCtx";
1848 unsigned int n =(unsigned int)(strlen(sess_ctx_id)+1);
1849 xrdctx->SessionCache(tlsCache, sess_ctx_id, n);
1850
1851// Set special ciphers if so specified.
1852//
1854 {eDest.Say("Config failure: ", "Unable to set allowable https ciphers!");
1855 return false;
1856 }
1857
1858// All done
1859//
1860 return true;
1861}
1862
1863/******************************************************************************/
1864/* C l e a n u p */
1865/******************************************************************************/
1866
1867void XrdHttpProtocol::Cleanup() {
1868
1869 TRACE(ALL, " Cleanup");
1870
1871 if (BPool && myBuff) {
1872 BuffConsume(BuffUsed());
1873 BPool->Release(myBuff);
1874 myBuff = 0;
1875 }
1876
1877 if (ssl) {
1878 // Shutdown the SSL/TLS connection
1879 // https://www.openssl.org/docs/man1.0.2/man3/SSL_shutdown.html
1880 // We don't need a bidirectional shutdown as
1881 // when we are here, the connection will not be re-used.
1882 // In the case SSL_shutdown returns 0,
1883 // "the output of SSL_get_error(3) may be misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred."
1884 // we will then just flush the thread's queue.
1885 // In the case an error really happened, we print the error that happened
1886 int ret = SSL_shutdown(ssl);
1887 if (ret != 1) {
1888 if(ret == 0) {
1889 // Clean this thread's error queue for the old openssl versions
1890 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1891 ERR_remove_thread_state(nullptr);
1892 #endif
1893 } else {
1894 //ret < 0, an error really happened.
1895 TRACE(ALL, " SSL_shutdown failed");
1896 ERR_print_errors(sslbio_err);
1897 }
1898 }
1899
1900 if (secxtractor)
1901 secxtractor->FreeSSL(ssl);
1902
1903 SSL_free(ssl);
1904
1905 }
1906
1907
1908 ssl = 0;
1909 sbio = 0;
1910
1911 if (SecEntity.caps) free(SecEntity.caps);
1912 if (SecEntity.grps) free(SecEntity.grps);
1914 if (SecEntity.vorg) free(SecEntity.vorg);
1915 if (SecEntity.role) free(SecEntity.role);
1916 if (SecEntity.name) free(SecEntity.name);
1917 if (SecEntity.host) free(SecEntity.host);
1919
1920 SecEntity.Reset();
1921
1922 if (Addr_str) free(Addr_str);
1923 Addr_str = 0;
1924}
1925
1926/******************************************************************************/
1927/* R e s e t */
1928/******************************************************************************/
1929
1930void XrdHttpProtocol::Reset() {
1931
1932 TRACE(ALL, " Reset");
1933 Link = 0;
1934 CurrentReq.reset();
1935 CurrentReq.reqstate = 0;
1936
1937 if (myBuff) {
1938 BPool->Release(myBuff);
1939 myBuff = 0;
1940 }
1941 myBuffStart = myBuffEnd = 0;
1942
1943 DoingLogin = false;
1944 DoneSetInfo = false;
1945
1946 ResumeBytes = 0;
1947 Resume = 0;
1948
1949 //
1950 // numReads = 0;
1951 // numReadP = 0;
1952 // numReadV = 0;
1953 // numSegsV = 0;
1954 // numWrites = 0;
1955 // numFiles = 0;
1956 // cumReads = 0;
1957 // cumReadV = 0;
1958 // cumSegsV = 0;
1959 // cumWrites = 0;
1960 // totReadP = 0;
1961
1962 SecEntity.Reset();
1964 ishttps = false;
1965 ssldone = false;
1966
1967 Bridge = 0;
1968 ssl = 0;
1969 sbio = 0;
1970
1971}
1972
1973/******************************************************************************/
1974/* x h t t p s m o d e */
1975/******************************************************************************/
1976
1977/* Function: xhttpsmode
1978
1979 Purpose: To parse the directive: httpsmode {auto | disable | manual}
1980
1981 auto configure https if configured in xrd framework.
1982 disable do not configure https no matter what
1983 manual configure https and ignore the xrd framework
1984
1985 Output: 0 upon success or !0 upon failure.
1986 */
1987
1988int XrdHttpProtocol::xhttpsmode(XrdOucStream & Config) {
1989 char *val;
1990
1991 // Get the val
1992 //
1993 val = Config.GetWord();
1994 if (!val || !val[0]) {
1995 eDest.Emsg("Config", "httpsmode parameter not specified");
1996 return 1;
1997 }
1998
1999 // Record the val
2000 //
2001 if (!strcmp(val, "auto")) httpsmode = hsmAuto;
2002 else if (!strcmp(val, "disable")) httpsmode = hsmOff;
2003 else if (!strcmp(val, "manual")) httpsmode = hsmMan;
2004 else {eDest.Emsg("Config", "invalid httpsmode parameter - ", val);
2005 return 1;
2006 }
2007 return 0;
2008}
2009
2010/******************************************************************************/
2011/* x s s l v e r i f y d e p t h */
2012/******************************************************************************/
2013
2014/* Function: xsslverifydepth
2015
2016 Purpose: To parse the directive: sslverifydepth <depth>
2017
2018 <depth> the max depth of the ssl cert verification
2019
2020 Output: 0 upon success or !0 upon failure.
2021 */
2022
2023int XrdHttpProtocol::xsslverifydepth(XrdOucStream & Config) {
2024 char *val;
2025
2026 // Get the val
2027 //
2028 val = Config.GetWord();
2029 if (!val || !val[0]) {
2030 eDest.Emsg("Config", "sslverifydepth value not specified");
2031 return 1;
2032 }
2033
2034 // Record the val
2035 //
2036 sslverifydepth = atoi(val);
2037
2038 if (xrdctxVer){ HTTPS_ALERT("verifydepth","tlsca",false); }
2039 return 0;
2040}
2041
2042/******************************************************************************/
2043/* x s s l c e r t */
2044/******************************************************************************/
2045
2046/* Function: xsslcert
2047
2048 Purpose: To parse the directive: sslcert <path>
2049
2050 <path> the path of the server certificate to be used.
2051
2052 Output: 0 upon success or !0 upon failure.
2053 */
2054
2055int XrdHttpProtocol::xsslcert(XrdOucStream & Config) {
2056 char *val;
2057
2058 // Get the path
2059 //
2060 val = Config.GetWord();
2061 if (!val || !val[0]) {
2062 eDest.Emsg("Config", "HTTP X509 certificate not specified");
2063 return 1;
2064 }
2065
2066 // Record the path
2067 //
2068 if (sslcert) free(sslcert);
2069 sslcert = strdup(val);
2070
2071 // If we have an xrd context issue reminder
2072 //
2073 HTTPS_ALERT("cert","tls",true);
2074 return 0;
2075}
2076
2077/******************************************************************************/
2078/* x s s l k e y */
2079/******************************************************************************/
2080
2081/* Function: xsslkey
2082
2083 Purpose: To parse the directive: sslkey <path>
2084
2085 <path> the path of the server key to be used.
2086
2087 Output: 0 upon success or !0 upon failure.
2088 */
2089
2090int XrdHttpProtocol::xsslkey(XrdOucStream & Config) {
2091 char *val;
2092
2093 // Get the path
2094 //
2095 val = Config.GetWord();
2096 if (!val || !val[0]) {
2097 eDest.Emsg("Config", "HTTP X509 key not specified");
2098 return 1;
2099 }
2100
2101 // Record the path
2102 //
2103 if (sslkey) free(sslkey);
2104 sslkey = strdup(val);
2105
2106 HTTPS_ALERT("key","tls",true);
2107 return 0;
2108}
2109
2110/******************************************************************************/
2111/* x g m a p */
2112/******************************************************************************/
2113
2114/* Function: xgmap
2115
2116 Purpose: To parse the directive: gridmap [required] [compatNameGeneration] <path>
2117
2118 required optional parameter which if present treats any grimap errors
2119 as fatal.
2120 <path> the path of the gridmap file to be used. Normally it's
2121 /etc/grid-security/gridmap. No mapfile means no translation
2122 required. Pointing to a non existing mapfile is an error.
2123
2124 Output: 0 upon success or !0 upon failure.
2125 */
2126
2127int XrdHttpProtocol::xgmap(XrdOucStream & Config) {
2128 char *val;
2129
2130 // Get the path
2131 //
2132 val = Config.GetWord();
2133 if (!val || !val[0]) {
2134 eDest.Emsg("Config", "HTTP X509 gridmap file location not specified");
2135 return 1;
2136 }
2137
2138 // Handle optional parameter "required"
2139 //
2140 if (!strncmp(val, "required", 8)) {
2141 isRequiredGridmap = true;
2142 val = Config.GetWord();
2143
2144 if (!val || !val[0]) {
2145 eDest.Emsg("Config", "HTTP X509 gridmap file missing after [required] "
2146 "parameter");
2147 return 1;
2148 }
2149 }
2150
2151 // Handle optional parameter "compatNameGeneration"
2152 //
2153 if (!strcmp(val, "compatNameGeneration")) {
2154 compatNameGeneration = true;
2155 val = Config.GetWord();
2156 if (!val || !val[0]) {
2157 eDest.Emsg("Config", "HTTP X509 gridmap file missing after "
2158 "[compatNameGeneration] parameter");
2159 return 1;
2160 }
2161 }
2162
2163
2164 // Record the path
2165 //
2166 if (gridmap) free(gridmap);
2167 gridmap = strdup(val);
2168 return 0;
2169}
2170
2171/******************************************************************************/
2172/* x s s l c a f i l e */
2173/******************************************************************************/
2174
2175/* Function: xsslcafile
2176
2177 Purpose: To parse the directive: sslcafile <path>
2178
2179 <path> the path of the server key to be used.
2180
2181 Output: 0 upon success or !0 upon failure.
2182 */
2183
2184int XrdHttpProtocol::xsslcafile(XrdOucStream & Config) {
2185 char *val;
2186
2187 // Get the path
2188 //
2189 val = Config.GetWord();
2190 if (!val || !val[0]) {
2191 eDest.Emsg("Config", "HTTP X509 CAfile not specified");
2192 return 1;
2193 }
2194
2195 // Record the path
2196 //
2197 if (sslcafile) free(sslcafile);
2198 sslcafile = strdup(val);
2199
2200 if (xrdctxVer){ HTTPS_ALERT("cafile","tlsca",false); }
2201 return 0;
2202}
2203
2204/******************************************************************************/
2205/* x s e c r e t k e y */
2206/******************************************************************************/
2207
2208/* Function: xsecretkey
2209
2210 Purpose: To parse the directive: xsecretkey <key>
2211
2212 <key> the key to be used
2213
2214 Output: 0 upon success or !0 upon failure.
2215 */
2216
2217int XrdHttpProtocol::xsecretkey(XrdOucStream & Config) {
2218 char *val;
2219 bool inFile = false;
2220
2221 // Get the path
2222 //
2223 val = Config.GetWord();
2224 if (!val || !val[0]) {
2225 eDest.Emsg("Config", "Shared secret key not specified");
2226 return 1;
2227 }
2228
2229
2230 // If the token starts with a slash, then we interpret it as
2231 // the path to a file that contains the secretkey
2232 // otherwise, the token itself is the secretkey
2233 if (val[0] == '/') {
2234 struct stat st;
2235 inFile = true;
2236 if ( stat(val, &st) ) {
2237 eDest.Emsg("Config", errno, "stat shared secret key file", val);
2238 return 1;
2239 }
2240
2241 if ( st.st_mode & S_IWOTH & S_IWGRP & S_IROTH) {
2242 eDest.Emsg("Config", "For your own security, the shared secret key file cannot be world readable or group writable'", val, "'");
2243 return 1;
2244 }
2245
2246 FILE *fp = fopen(val,"r");
2247
2248 if( fp == NULL ) {
2249 eDest.Emsg("Config", errno, "open shared secret key file", val);
2250 return 1;
2251 }
2252
2253 char line[1024];
2254 while( fgets(line, 1024, fp) ) {
2255 char *pp;
2256
2257 // Trim the end
2258 pp = line + strlen(line) - 1;
2259 while ( (pp >= line) && (!isalnum(*pp)) ) {
2260 *pp = '\0';
2261 pp--;
2262 }
2263
2264 // Trim the beginning
2265 pp = line;
2266 while ( *pp && !isalnum(*pp) ) pp++;
2267
2268 if ( strlen(pp) >= 32 ) {
2269 eDest.Say("Config", "Secret key loaded.");
2270 // Record the path
2271 if (secretkey) free(secretkey);
2272 secretkey = strdup(pp);
2273
2274 fclose(fp);
2275 return 0;
2276 }
2277
2278 }
2279
2280 fclose(fp);
2281 eDest.Emsg("Config", "Cannot find useful secretkey in file '", val, "'");
2282 return 1;
2283
2284 }
2285
2286 if ( strlen(val) < 32 ) {
2287 eDest.Emsg("Config", "Secret key is too short");
2288 return 1;
2289 }
2290
2291 // Record the path
2292 if (secretkey) free(secretkey);
2293 secretkey = strdup(val);
2294 if (!inFile) Config.noEcho();
2295
2296 return 0;
2297}
2298
2299/******************************************************************************/
2300/* x l i s t d e n y */
2301/******************************************************************************/
2302
2303/* Function: xlistdeny
2304
2305 Purpose: To parse the directive: listingdeny <yes|no|0|1>
2306
2307 <val> makes this redirector deny listings with an error
2308
2309 Output: 0 upon success or !0 upon failure.
2310 */
2311
2312int XrdHttpProtocol::xlistdeny(XrdOucStream & Config) {
2313 char *val;
2314
2315 // Get the path
2316 //
2317 val = Config.GetWord();
2318 if (!val || !val[0]) {
2319 eDest.Emsg("Config", "listingdeny flag not specified");
2320 return 1;
2321 }
2322
2323 // Record the value
2324 //
2325 listdeny = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2326
2327
2328 return 0;
2329}
2330
2331/******************************************************************************/
2332/* x l i s t r e d i r */
2333/******************************************************************************/
2334
2335/* Function: xlistredir
2336
2337 Purpose: To parse the directive: listingredir <Url>
2338
2339 <Url> http/https server to redirect to in the case of listing
2340
2341 Output: 0 upon success or !0 upon failure.
2342 */
2343
2344int XrdHttpProtocol::xlistredir(XrdOucStream & Config) {
2345 char *val;
2346
2347 // Get the path
2348 //
2349 val = Config.GetWord();
2350 if (!val || !val[0]) {
2351 eDest.Emsg("Config", "listingredir flag not specified");
2352 return 1;
2353 }
2354
2355 // Record the value
2356 //
2357 if (listredir) free(listredir);
2358 listredir = strdup(val);
2359
2360
2361 return 0;
2362}
2363
2364/******************************************************************************/
2365/* x s s l d e s t h t t p s */
2366/******************************************************************************/
2367
2368/* Function: xdesthttps
2369
2370 Purpose: To parse the directive: desthttps <yes|no|0|1>
2371
2372 <val> makes this redirector produce http or https redirection targets
2373
2374 Output: 0 upon success or !0 upon failure.
2375 */
2376
2377int XrdHttpProtocol::xdesthttps(XrdOucStream & Config) {
2378 char *val;
2379
2380 // Get the path
2381 //
2382 val = Config.GetWord();
2383 if (!val || !val[0]) {
2384 eDest.Emsg("Config", "desthttps flag not specified");
2385 return 1;
2386 }
2387
2388 // Record the value
2389 //
2390 isdesthttps = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2391
2392
2393 return 0;
2394}
2395
2396/******************************************************************************/
2397/* x e m b e d d e d s t a t i c */
2398/******************************************************************************/
2399
2400/* Function: xembeddedstatic
2401
2402 Purpose: To parse the directive: embeddedstatic <yes|no|0|1|true|false>
2403
2404 <val> this server will redirect HTTPS to itself using HTTP+token
2405
2406 Output: 0 upon success or !0 upon failure.
2407 */
2408
2409int XrdHttpProtocol::xembeddedstatic(XrdOucStream & Config) {
2410 char *val;
2411
2412 // Get the path
2413 //
2414 val = Config.GetWord();
2415 if (!val || !val[0]) {
2416 eDest.Emsg("Config", "embeddedstatic flag not specified");
2417 return 1;
2418 }
2419
2420 // Record the value
2421 //
2422 embeddedstatic = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2423
2424
2425 return 0;
2426}
2427
2428/******************************************************************************/
2429/* x r e d i r s t a t i c */
2430/******************************************************************************/
2431
2432/* Function: xstaticredir
2433
2434 Purpose: To parse the directive: staticredir <Url>
2435
2436 <Url> http/https server to redirect to in the case of /static
2437
2438 Output: 0 upon success or !0 upon failure.
2439 */
2440
2441int XrdHttpProtocol::xstaticredir(XrdOucStream & Config) {
2442 char *val;
2443
2444 // Get the path
2445 //
2446 val = Config.GetWord();
2447 if (!val || !val[0]) {
2448 eDest.Emsg("Config", "staticredir url not specified");
2449 return 1;
2450 }
2451
2452 // Record the value
2453 //
2454 if (staticredir) free(staticredir);
2455 staticredir = strdup(val);
2456
2457 return 0;
2458}
2459
2460/******************************************************************************/
2461/* x p r e l o a d s t a t i c */
2462/******************************************************************************/
2463
2464/* Function: xpreloadstatic
2465
2466 Purpose: To parse the directive: preloadstatic <http url path> <local file>
2467
2468 <http url path> http/http path whose response we are preloading
2469 e.g. /static/mycss.css
2470 NOTE: this must start with /static
2471
2472
2473 Output: 0 upon success or !0 upon failure.
2474 */
2475
2476int XrdHttpProtocol::xstaticpreload(XrdOucStream & Config) {
2477 char *val, *k, key[1024];
2478
2479 // Get the key
2480 //
2481 k = Config.GetWord();
2482 if (!k || !k[0]) {
2483 eDest.Emsg("Config", "preloadstatic urlpath not specified");
2484 return 1;
2485 }
2486
2487 strcpy(key, k);
2488
2489 // Get the val
2490 //
2491 val = Config.GetWord();
2492 if (!val || !val[0]) {
2493 eDest.Emsg("Config", "preloadstatic filename not specified");
2494 return 1;
2495 }
2496
2497 // Try to load the file into memory
2498 int fp = open(val, O_RDONLY);
2499 if( fp < 0 ) {
2500 eDest.Emsg("Config", errno, "open preloadstatic filename", val);
2501 return 1;
2502 }
2503
2504 StaticPreloadInfo *nfo = new StaticPreloadInfo;
2505 // Max 64Kb ok?
2506 nfo->data = (char *)malloc(65536);
2507 nfo->len = read(fp, (void *)nfo->data, 65536);
2508 close(fp);
2509
2510 if (nfo->len <= 0) {
2511 eDest.Emsg("Config", errno, "read from preloadstatic filename", val);
2512 return 1;
2513 }
2514
2515 if (nfo->len >= 65536) {
2516 eDest.Emsg("Config", "Truncated preloadstatic filename. Max is 64 KB '", val, "'");
2517 return 1;
2518 }
2519
2520 // Record the value
2521 //
2522 if (!staticpreload)
2524
2525 staticpreload->Rep((const char *)key, nfo);
2526 return 0;
2527}
2528
2529/******************************************************************************/
2530/* x s e l f h t t p s 2 h t t p */
2531/******************************************************************************/
2532
2533/* Function: selfhttps2http
2534
2535 Purpose: To parse the directive: selfhttps2http <yes|no|0|1>
2536
2537 <val> this server will redirect HTTPS to itself using HTTP+token
2538
2539 Output: 0 upon success or !0 upon failure.
2540 */
2541
2542int XrdHttpProtocol::xselfhttps2http(XrdOucStream & Config) {
2543 char *val;
2544
2545 // Get the path
2546 //
2547 val = Config.GetWord();
2548 if (!val || !val[0]) {
2549 eDest.Emsg("Config", "selfhttps2http flag not specified");
2550 return 1;
2551 }
2552
2553 // Record the value
2554 //
2555 selfhttps2http = (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcmp(val, "1"));
2556
2557
2558 return 0;
2559}
2560
2561/******************************************************************************/
2562/* x s e c x t r a c t o r */
2563/******************************************************************************/
2564
2565/* Function: xsecxtractor
2566
2567 Purpose: To parse the directive: secxtractor [required] <path> <params>
2568
2569 required optional parameter which if present treats any secxtractor
2570 errors as fatal.
2571 <path> the path of the plugin to be loaded
2572 <params> parameters passed to the secxtractor library
2573
2574 Output: 0 upon success or !0 upon failure.
2575 */
2576
2577int XrdHttpProtocol::xsecxtractor(XrdOucStream& Config) {
2578 char *val;
2579
2580 // Get the path
2581 //
2582 val = Config.GetWord();
2583 if (!val || !val[0]) {
2584 eDest.Emsg("Config", "No security extractor plugin specified.");
2585 return 1;
2586 } else {
2587 // Handle optional parameter [required]
2588 //
2589 if (!strncmp(val, "required", 8)) {
2590 isRequiredXtractor = true;
2591 val = Config.GetWord();
2592
2593 if (!val || !val[0]) {
2594 eDest.Emsg("Config", "No security extractor plugin after [required] "
2595 "parameter");
2596 return 1;
2597 }
2598 }
2599
2600 char libName[4096];
2601 strlcpy(libName, val, sizeof(libName));
2602 libName[sizeof(libName) - 1] = '\0';
2603 char libParms[4096];
2604
2605 if (!Config.GetRest(libParms, 4095)) {
2606 eDest.Emsg("Config", "secxtractor config params longer than 4k");
2607 return 1;
2608 }
2609
2610 // Try to load the plugin (if available) that extracts info from the
2611 // user cert/proxy
2612 if (LoadSecXtractor(&eDest, libName, libParms)) {
2613 return 1;
2614 }
2615 }
2616
2617 return 0;
2618}
2619
2620/******************************************************************************/
2621/* x e x t h a n d l e r */
2622/******************************************************************************/
2623
2624/* Function: xexthandler
2625 *
2626 * Purpose: To parse the directive: exthandler <name> <path> <initparm>
2627 *
2628 * <name> a unique name (max 16chars) to be given to this
2629 * instance, e.g 'myhandler1'
2630 * <path> the path of the plugin to be loaded
2631 * <initparm> a string parameter (e.g. a config file) that is
2632 * passed to the initialization of the plugin
2633 *
2634 * Output: 0 upon success or !0 upon failure.
2635 */
2636
2637int XrdHttpProtocol::xexthandler(XrdOucStream &Config,
2638 std::vector<extHInfo> &hiVec) {
2639 char *val, path[1024], namebuf[1024];
2640 char *parm;
2641 // By default, every external handler need TLS configured to be loaded
2642 bool noTlsOK = false;
2643
2644 // Get the name
2645 //
2646 val = Config.GetWord();
2647 if (!val || !val[0]) {
2648 eDest.Emsg("Config", "No instance name specified for an http external handler plugin.");
2649 return 1;
2650 }
2651 if (strlen(val) >= 16) {
2652 eDest.Emsg("Config", "Instance name too long for an http external handler plugin.");
2653 return 1;
2654 }
2655 strncpy(namebuf, val, sizeof(namebuf));
2656 namebuf[ sizeof(namebuf)-1 ] = '\0';
2657
2658 // Get the +notls option if it was provided
2659 val = Config.GetWord();
2660
2661 if(val && !strcmp("+notls",val)) {
2662 noTlsOK = true;
2663 val = Config.GetWord();
2664 }
2665
2666 // Get the path
2667 //
2668 if (!val || !val[0]) {
2669 eDest.Emsg("Config", "No http external handler plugin specified.");
2670 return 1;
2671 }
2672 if (strlen(val) >= (int)sizeof(path)) {
2673 eDest.Emsg("Config", "Path too long for an http external handler plugin.");
2674 return 1;
2675 }
2676
2677 strcpy(path, val);
2678
2679 // Everything else is a free string
2680 //
2681 parm = Config.GetWord();
2682
2683 // Verify whether this is a duplicate (we never supported replacements)
2684 //
2685 for (int i = 0; i < (int)hiVec.size(); i++)
2686 {if (hiVec[i].extHName == namebuf) {
2687 eDest.Emsg("Config", "Instance name already present for "
2688 "http external handler plugin",
2689 hiVec[i].extHPath.c_str());
2690 return 1;
2691 }
2692 }
2693
2694 // Verify that we don't have more already than we are allowed to have
2695 //
2696 if (hiVec.size() >= MAX_XRDHTTPEXTHANDLERS) {
2697 eDest.Emsg("Config", "Cannot load one more exthandler. Max is 4");
2698 return 1;
2699 }
2700
2701 // Create an info struct and push it on the list of ext handlers to load
2702 //
2703 hiVec.push_back(extHInfo(namebuf, path, (parm ? parm : ""), noTlsOK));
2704
2705 return 0;
2706}
2707
2708/******************************************************************************/
2709/* x h e a d e r 2 c g i */
2710/******************************************************************************/
2711
2712/* Function: xheader2cgi
2713 *
2714 * Purpose: To parse the directive: header2cgi <headerkey> <cgikey>
2715 *
2716 * <headerkey> the name of an incoming HTTP header
2717 * to be transformed
2718 * <cgikey> the name to be given when adding it to the cgi info
2719 * that is kept only internally
2720 *
2721 * Output: 0 upon success or !0 upon failure.
2722 */
2723
2724int XrdHttpProtocol::xheader2cgi(XrdOucStream & Config) {
2725 return parseHeader2CGI(Config,eDest,hdr2cgimap);
2726}
2727
2728/******************************************************************************/
2729/* x s s l c a d i r */
2730/******************************************************************************/
2731
2732/* Function: xsslcadir
2733
2734 Purpose: To parse the directive: sslcadir <path>
2735
2736 <path> the path of the server key to be used.
2737
2738 Output: 0 upon success or !0 upon failure.
2739 */
2740
2741int XrdHttpProtocol::xsslcadir(XrdOucStream & Config) {
2742 char *val;
2743
2744 // Get the path
2745 //
2746 val = Config.GetWord();
2747 if (!val || !val[0]) {
2748 eDest.Emsg("Config", "HTTP X509 CAdir not specified");
2749 return 1;
2750 }
2751
2752 // Record the path
2753 //
2754 if (sslcadir) free(sslcadir);
2755 sslcadir = strdup(val);
2756
2757 if (xrdctxVer){ HTTPS_ALERT("cadir","tlsca",false); }
2758 return 0;
2759}
2760
2761/******************************************************************************/
2762/* x s s l c i p h e r f i l t e r */
2763/******************************************************************************/
2764
2765/* Function: xsslcipherfilter
2766
2767 Purpose: To parse the directive: cipherfilter <filter>
2768
2769 <filter> the filter string to be used when generating
2770 the SSL cipher list
2771
2772 Output: 0 upon success or !0 upon failure.
2773 */
2774
2775int XrdHttpProtocol::xsslcipherfilter(XrdOucStream & Config) {
2776 char *val;
2777
2778 // Get the filter string
2779 //
2780 val = Config.GetWord();
2781 if (!val || !val[0]) {
2782 eDest.Emsg("Config", "SSL cipherlist filter string not specified");
2783 return 1;
2784 }
2785
2786 // Record the filter string
2787 //
2789 sslcipherfilter = strdup(val);
2790
2791 return 0;
2792}
2793
2794/******************************************************************************/
2795/* x t l s r e u s e */
2796/******************************************************************************/
2797
2798/* Function: xtlsreuse
2799
2800 Purpose: To parse the directive: tlsreuse {on | off}
2801
2802 Output: 0 upon success or 1 upon failure.
2803 */
2804
2805int XrdHttpProtocol::xtlsreuse(XrdOucStream & Config) {
2806
2807 char *val;
2808
2809// Get the argument
2810//
2811 val = Config.GetWord();
2812 if (!val || !val[0])
2813 {eDest.Emsg("Config", "tlsreuse argument not specified"); return 1;}
2814
2815// If it's off, we set it off
2816//
2817 if (!strcmp(val, "off"))
2819 return 0;
2820 }
2821
2822// If it's on we set it on.
2823//
2824 if (!strcmp(val, "on"))
2826 return 0;
2827 }
2828
2829// Bad argument
2830//
2831 eDest.Emsg("config", "invalid tlsreuse parameter -", val);
2832 return 1;
2833}
2834
2835int XrdHttpProtocol::xauth(XrdOucStream &Config) {
2836 char *val = Config.GetWord();
2837 if(val) {
2838 if(!strcmp("tpc",val)) {
2839 if(!(val = Config.GetWord())) {
2840 eDest.Emsg("Config", "http.auth tpc value not specified."); return 1;
2841 } else {
2842 if(!strcmp("fcreds",val)) {
2843 tpcForwardCreds = true;
2844 } else {
2845 eDest.Emsg("Config", "http.auth tpc value is invalid"); return 1;
2846 }
2847 }
2848 } else {
2849 eDest.Emsg("Config", "http.auth value is invalid"); return 1;
2850 }
2851 }
2852 return 0;
2853}
2854
2855/******************************************************************************/
2856/* x t r a c e */
2857/******************************************************************************/
2858
2859/* Function: xtrace
2860
2861 Purpose: To parse the directive: trace <events>
2862
2863 <events> the blank separated list of events to trace. Trace
2864 directives are cumulative.
2865
2866 Output: 0 upon success or 1 upon failure.
2867 */
2868
2869int XrdHttpProtocol::xtrace(XrdOucStream & Config) {
2870
2871 char *val;
2872
2873 static struct traceopts {
2874 const char *opname;
2875 int opval;
2876 } tropts[] = {
2877 {"all", TRACE_ALL},
2878 {"auth", TRACE_AUTH},
2879 {"debug", TRACE_DEBUG},
2880 {"mem", TRACE_MEM},
2881 {"redirect", TRACE_REDIR},
2882 {"request", TRACE_REQ},
2883 {"response", TRACE_RSP}
2884 };
2885 int i, neg, trval = 0, numopts = sizeof (tropts) / sizeof (struct traceopts);
2886
2887 if (!(val = Config.GetWord())) {
2888 eDest.Emsg("config", "trace option not specified");
2889 return 1;
2890 }
2891 while (val) {
2892 if (!strcmp(val, "off")) trval = 0;
2893 else {
2894 if ((neg = (val[0] == '-' && val[1]))) val++;
2895 for (i = 0; i < numopts; i++) {
2896 if (!strcmp(val, tropts[i].opname)) {
2897 if (neg) trval &= ~tropts[i].opval;
2898 else trval |= tropts[i].opval;
2899 break;
2900 }
2901 }
2902 if (i >= numopts)
2903 eDest.Emsg("config", "invalid trace option", val);
2904 }
2905 val = Config.GetWord();
2906 }
2907 XrdHttpTrace.What = trval;
2908 return 0;
2909}
2910
2911int XrdHttpProtocol::doStat(char *fname) {
2912 int l;
2913 bool b;
2914 CurrentReq.filesize = 0;
2917
2918 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2920 memset(CurrentReq.xrdreq.stat.reserved, 0,
2921 sizeof (CurrentReq.xrdreq.stat.reserved));
2922 l = strlen(fname) + 1;
2923 CurrentReq.xrdreq.stat.dlen = htonl(l);
2924
2925 if (!Bridge) return -1;
2926 b = Bridge->Run((char *) &CurrentReq.xrdreq, fname, l);
2927 if (!b) {
2928 return -1;
2929 }
2930
2931
2932 return 0;
2933}
2934
2935/******************************************************************************/
2936/* d o C h k s u m */
2937/******************************************************************************/
2938
2939int XrdHttpProtocol::doChksum(const XrdOucString &fname) {
2940 size_t length;
2941 memset(&CurrentReq.xrdreq, 0, sizeof (ClientRequest));
2947 length = fname.length() + 1;
2948 CurrentReq.xrdreq.query.dlen = htonl(length);
2949
2950 if (!Bridge) return -1;
2951
2952 return Bridge->Run(reinterpret_cast<char *>(&CurrentReq.xrdreq), const_cast<char *>(fname.c_str()), length) ? 0 : -1;
2953}
2954
2955
2956static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION);
2957
2958// Loads the SecXtractor plugin, if available
2959int XrdHttpProtocol::LoadSecXtractor(XrdSysError *myeDest, const char *libName,
2960 const char *libParms) {
2961
2962
2963 // We don't want to load it more than once
2964 if (secxtractor) return 1;
2965
2966 XrdOucPinLoader myLib(myeDest, &compiledVer, "secxtractorlib", libName);
2968
2969 // Get the entry point of the object creator
2970 //
2971 ep = (XrdHttpSecXtractor *(*)(XrdHttpSecXtractorArgs))(myLib.Resolve("XrdHttpGetSecXtractor"));
2972 if (ep && (secxtractor = ep(myeDest, NULL, libParms))) return 0;
2973 myLib.Unload();
2974 return 1;
2975}
2976/******************************************************************************/
2977/* L o a d E x t H a n d l e r */
2978/******************************************************************************/
2979
2980int XrdHttpProtocol::LoadExtHandlerNoTls(std::vector<extHInfo> &hiVec, const char *cFN, XrdOucEnv &myEnv) {
2981 for (int i = 0; i < (int) hiVec.size(); i++) {
2982 if(hiVec[i].extHNoTlsOK) {
2983 // The external plugin does not need TLS to be loaded
2984 if (LoadExtHandler(&eDest, hiVec[i].extHPath.c_str(), cFN,
2985 hiVec[i].extHParm.c_str(), &myEnv,
2986 hiVec[i].extHName.c_str()))
2987 return 1;
2988 }
2989 }
2990 return 0;
2991}
2992
2993int XrdHttpProtocol::LoadExtHandler(std::vector<extHInfo> &hiVec,
2994 const char *cFN, XrdOucEnv &myEnv) {
2995
2996 // Add the pointer to the cadir and the cakey to the environment.
2997 //
2998 if (sslcadir) myEnv.Put("http.cadir", sslcadir);
2999 if (sslcafile) myEnv.Put("http.cafile", sslcafile);
3000 if (sslcert) myEnv.Put("http.cert", sslcert);
3001 if (sslkey) myEnv.Put("http.key" , sslkey);
3002
3003 // Load all of the specified external handlers.
3004 //
3005 for (int i = 0; i < (int)hiVec.size(); i++) {
3006 // Only load the external handlers that were not already loaded
3007 // by LoadExtHandlerNoTls(...)
3008 if(!ExtHandlerLoaded(hiVec[i].extHName.c_str())) {
3009 if (LoadExtHandler(&eDest, hiVec[i].extHPath.c_str(), cFN,
3010 hiVec[i].extHParm.c_str(), &myEnv,
3011 hiVec[i].extHName.c_str())) return 1;
3012 }
3013 }
3014 return 0;
3015}
3016
3017// Loads the external handler plugin, if available
3018int XrdHttpProtocol::LoadExtHandler(XrdSysError *myeDest, const char *libName,
3019 const char *configFN, const char *libParms,
3020 XrdOucEnv *myEnv, const char *instName) {
3021
3022
3023 // This function will avoid loading doubles. No idea why this happens
3024 if (ExtHandlerLoaded(instName)) {
3025 eDest.Emsg("Config", "Instance name already present for an http external handler plugin.");
3026 return 1;
3027 }
3028 if (exthandlercnt >= MAX_XRDHTTPEXTHANDLERS) {
3029 eDest.Emsg("Config", "Cannot load one more exthandler. Max is 4");
3030 return 1;
3031 }
3032
3033 XrdOucPinLoader myLib(myeDest, &compiledVer, "exthandlerlib", libName);
3035
3036 // Get the entry point of the object creator
3037 //
3038 ep = (XrdHttpExtHandler *(*)(XrdHttpExtHandlerArgs))(myLib.Resolve("XrdHttpGetExtHandler"));
3039
3040 XrdHttpExtHandler *newhandler;
3041 if (ep && (newhandler = ep(myeDest, configFN, libParms, myEnv))) {
3042
3043 // Handler has been loaded, it's the last one in the list
3044 strncpy( exthandler[exthandlercnt].name, instName, 16 );
3045 exthandler[exthandlercnt].name[15] = '\0';
3046 exthandler[exthandlercnt++].ptr = newhandler;
3047
3048 return 0;
3049 }
3050
3051 myLib.Unload();
3052 return 1;
3053}
3054
3055
3056
3057// Tells if we have already loaded a certain exthandler. Try to
3058// privilege speed, as this func may be invoked pretty often
3059bool XrdHttpProtocol::ExtHandlerLoaded(const char *handlername) {
3060 for (int i = 0; i < exthandlercnt; i++) {
3061 if ( !strncmp(exthandler[i].name, handlername, 15) ) {
3062 return true;
3063 }
3064 }
3065 return false;
3066}
3067
3068// Locates a matching external handler for a given request, if available. Try to
3069// privilege speed, as this func is invoked for every incoming request
3070XrdHttpExtHandler * XrdHttpProtocol::FindMatchingExtHandler(const XrdHttpReq &req) {
3071
3072 for (int i = 0; i < exthandlercnt; i++) {
3073 if (exthandler[i].ptr->MatchesPath(req.requestverb.c_str(), req.resource.c_str())) {
3074 return exthandler[i].ptr;
3075 }
3076 }
3077 return NULL;
3078}
#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:768
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:864
kXR_unt16 requestid
Definition XProtocol.hh:766
struct ClientStatRequest stat
Definition XProtocol.hh:871
@ 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 fopen(a, b)
Definition XrdPosix.hh:49
#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 215 of file XrdHttpProtocol.cc.

◆ TRACELINK [2/3]

#define TRACELINK   Link

Definition at line 215 of file XrdHttpProtocol.cc.

◆ TRACELINK [3/3]

#define TRACELINK   Link

Definition at line 215 of file XrdHttpProtocol.cc.

◆ TS_Xeq

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

Definition at line 971 of file XrdHttpProtocol.cc.

◆ TS_Xeq3

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

Definition at line 973 of file XrdHttpProtocol.cc.

◆ XRHTTP_TK_GRACETIME

#define XRHTTP_TK_GRACETIME   600

Definition at line 57 of file XrdHttpProtocol.cc.

Function Documentation

◆ BIO_get_data()

void * BIO_get_data ( BIO *  bio)

Definition at line 156 of file XrdHttpProtocol.cc.

156 {
157 return bio->ptr;
158}

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 163 of file XrdHttpProtocol.cc.

163 {
164 return bio->flags;
165}

◆ BIO_get_init()

int BIO_get_init ( BIO *  bio)

Definition at line 170 of file XrdHttpProtocol.cc.

170 {
171 return bio->init;
172}

◆ BIO_get_shutdown()

int BIO_get_shutdown ( BIO *  bio)

Definition at line 179 of file XrdHttpProtocol.cc.

179 {
180 return bio->shutdown;
181}

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 159 of file XrdHttpProtocol.cc.

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

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 167 of file XrdHttpProtocol.cc.

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

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 173 of file XrdHttpProtocol.cc.

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

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 176 of file XrdHttpProtocol.cc.

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

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 403 of file XrdHttpProtocol.cc.

404{
405
406
407 BIO_set_init(bio, 0);
408 //BIO_set_next(bio, 0);
409 BIO_set_data(bio, NULL);
410 BIO_set_flags(bio, 0);
411
412#if OPENSSL_VERSION_NUMBER < 0x10100000L
413
414 bio->num = 0;
415
416#endif
417
418 return 1;
419}
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 436 of file XrdHttpProtocol.cc.

437{
438 long ret = 1;
439 switch (cmd) {
440 case BIO_CTRL_GET_CLOSE:
441 ret = BIO_get_shutdown(bio);
442 break;
443 case BIO_CTRL_SET_CLOSE:
444 BIO_set_shutdown(bio, (int)num);
445 break;
446 case BIO_CTRL_DUP:
447 case BIO_CTRL_FLUSH:
448 ret = 1;
449 break;
450 default:
451 ret = 0;
452 break;
453 }
454 return ret;
455}
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 422 of file XrdHttpProtocol.cc.

423{
424 if (bio == NULL) return 0;
425 if (BIO_get_shutdown(bio)) {
426 if (BIO_get_data(bio)) {
427 static_cast<XrdLink*>(BIO_get_data(bio))->Close();
428 }
429 BIO_set_init(bio, 0);
430 BIO_set_flags(bio, 0);
431 }
432 return 1;
433}
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 362 of file XrdHttpProtocol.cc.

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

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 319 of file XrdHttpProtocol.cc.

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

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 65 of file XrdHttpProtocol.cc.

◆ XrdHttpTrace

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