diff --git a/src/crypto/Connect.cpp b/src/crypto/Connect.cpp index 46d57d86f..77caed3b5 100644 --- a/src/crypto/Connect.cpp +++ b/src/crypto/Connect.cpp @@ -55,7 +55,8 @@ static X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) #endif Connect::Connect(const string &_url, const string &method, int timeout, const string &useragent, const std::vector &certs) - : _timeout(timeout) + : _method(method) + , _timeout(timeout) { DEBUG("Connecting to URL: %s", _url.c_str()); char *_host = nullptr, *_port = nullptr, *_path = nullptr; @@ -74,6 +75,12 @@ Connect::Connect(const string &_url, const string &method, int timeout, const st OPENSSL_free(_host); OPENSSL_free(_port); OPENSSL_free(_path); + size_t pos = url.find("://"); + if(pos != string::npos) { + pos = url.find('/', pos + 3); + if(pos != string::npos) + baseurl = url.substr(0, pos); + } string hostname = host + ":" + port; Conf *c = Conf::instance(); @@ -159,7 +166,7 @@ Connect::Connect(const string &_url, const string &method, int timeout, const st waitReadWrite(false); BIO_printf(d, "%s %s HTTP/1.0\r\n", method.c_str(), path.c_str()); - if(port == "80") + if(port == "80" || port == "443") addHeader("Host", host); else addHeader("Host", host + ":" + port); @@ -180,12 +187,6 @@ void Connect::addHeader(const string &key, const string &value) BIO_printf(d, "%s: %s\r\n", key.c_str(), value.c_str()); } -void Connect::addHeaders(initializer_list> headers) -{ - for(const pair &it: headers) - addHeader(it.first, it.second); -} - std::string Connect::decompress(const std::string &encoding, const std::string &data) const { if(data.empty()) @@ -236,7 +237,9 @@ Connect::Result Connect::exec(initializer_list> headers, Connect::Result Connect::exec(initializer_list> headers, const unsigned char *data, size_t size) { - addHeaders(headers); + for(const pair &it: headers) + addHeader(it.first, it.second); + if(size != 0) { addHeader("Content-Length", to_string(size)); @@ -293,7 +296,13 @@ Connect::Result Connect::exec(initializer_list> headers, const auto it = r.headers.find("Content-Encoding"); if(it != r.headers.cend()) r.content = decompress(it->second, r.content); - return r; + + if(!r.isRedirect() || recursive > 3) + return r; + string url = r.headers["Location"].find("://") != string::npos ? r.headers["Location"] : baseurl + r.headers["Location"]; + Connect c(url, _method, _timeout); + c.recursive = recursive + 1; + return c.exec(headers); } void Connect::sendProxyAuth() diff --git a/src/crypto/Connect.h b/src/crypto/Connect.h index b335d9236..3f298946e 100644 --- a/src/crypto/Connect.h +++ b/src/crypto/Connect.h @@ -62,8 +62,6 @@ class Connect Connect(const std::string &url, const std::string &method = "POST", int timeout = 0, const std::string &useragent = {}, const std::vector &certs = {}); ~Connect(); - void addHeader(const std::string &key, const std::string &value); - void addHeaders(std::initializer_list> headers); Result exec(std::initializer_list> headers, const std::vector &data); Result exec(std::initializer_list> headers = {}, @@ -72,15 +70,18 @@ class Connect private: DISABLE_COPY(Connect); + void addHeader(const std::string &key, const std::string &value); void sendProxyAuth(); std::string decompress(const std::string &encoding, const std::string &data) const; void waitReadWrite(bool read) const; + std::string baseurl, _method; BIO *d = nullptr; std::shared_ptr ssl; int _timeout; bool doProxyConnect = false; int fd = -1; + int recursive = 0; }; } diff --git a/src/crypto/TSL.cpp b/src/crypto/TSL.cpp index 01eb2fb7c..8dbf1fa49 100644 --- a/src/crypto/TSL.cpp +++ b/src/crypto/TSL.cpp @@ -264,8 +264,6 @@ TSL::Result TSL::parse(const string &url, const vector &certs, { ofstream file(File::encodeName(tmp).c_str(), ofstream::binary); Connect::Result r = Connect(url, "GET", timeout).exec({{"Accept-Encoding", "gzip"}}); - if(r.isRedirect()) - r = Connect(r.headers["Location"], "GET", timeout).exec({{"Accept-Encoding", "gzip"}}); if(!r.isOK() || r.content.empty()) THROW("HTTP status code is not 200 or content is empty"); file << r.content; @@ -567,8 +565,6 @@ void TSL::validateETag(const string &url, int timeout) Connect::Result r; try { r = Connect(url, "HEAD", timeout).exec({{"Accept-Encoding", "gzip"}}); - if(r.isRedirect()) - r = Connect(r.headers["Location"], "HEAD", timeout).exec({{"Accept-Encoding", "gzip"}}); if(!r.isOK()) return; } catch(const Exception &e) { @@ -605,8 +601,6 @@ bool TSL::validateRemoteDigest(const std::string &url, int timeout) try { r= Connect(url.substr(0, pos) + ".sha2", "GET", timeout).exec(); - if(r.isRedirect()) - r = Connect(r.headers["Location"], "GET", timeout).exec(); if(!r.isOK()) return false; } catch(const Exception &e) { diff --git a/src/crypto/X509CertStore.cpp b/src/crypto/X509CertStore.cpp index 0a97e91b4..d0852d4c0 100644 --- a/src/crypto/X509CertStore.cpp +++ b/src/crypto/X509CertStore.cpp @@ -166,8 +166,6 @@ X509Cert X509CertStore::issuerFromAIA(const X509Cert &cert) const if(url.empty()) return X509Cert(); Connect::Result result = Connect(url, "GET").exec(); - if(result.isRedirect()) - result = Connect(result.headers["Location"], "GET").exec(); return X509Cert((const unsigned char*)result.content.c_str(), result.content.size()); }