From: Christos Tsantilas Date: Fri, 6 Nov 2015 12:50:21 +0000 (+0200) Subject: Restrict the number of downloaded certificates and the nested certificates X-Git-Tag: SQUID_4_0_13~5^2~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e526b932d2d46bae9b7118316c425c8b0caff0b;p=thirdparty%2Fsquid.git Restrict the number of downloaded certificates and the nested certificates downloads per SSL connection - Do not allow more than Ssl::PeerConnector::MaxCertsDownloads downloaded certificates for each SSL connection. This variable set to 10 for now. - Restrict the number of nested certificates downloads. For example when the certificate located in an SSL site which requires to download a a missing certificate (... from an SSL site which requires to download a missing certificate )* --- diff --git a/src/Downloader.cc b/src/Downloader.cc index 2571683788..8d5312bd1f 100644 --- a/src/Downloader.cc +++ b/src/Downloader.cc @@ -7,12 +7,13 @@ CBDATA_CLASS_INIT(Downloader); -Downloader::Downloader(SBuf &url, const MasterXaction::Pointer &xact, AsyncCall::Pointer &aCallback): +Downloader::Downloader(SBuf &url, const MasterXaction::Pointer &xact, AsyncCall::Pointer &aCallback, unsigned int level): AsyncJob("Downloader"), ConnStateData(xact), url_(url), callback(aCallback), - status(Http::scNone) + status(Http::scNone), + level_(level) { maxObjectSize = 512*1024; } diff --git a/src/Downloader.h b/src/Downloader.h index a698b60411..aad8e174ce 100644 --- a/src/Downloader.h +++ b/src/Downloader.h @@ -19,9 +19,12 @@ public: Http::StatusCode status; }; - explicit Downloader(SBuf &url, const MasterXaction::Pointer &xact, AsyncCall::Pointer &aCallback); + explicit Downloader(SBuf &url, const MasterXaction::Pointer &xact, AsyncCall::Pointer &aCallback, unsigned int level = 0); virtual ~Downloader(); void downloadFinished(); + + /// The nested level of Downloader object (downloads inside downloads) + unsigned int nestedLevel() const {return level_;} /* ConnStateData API */ virtual bool isOpen() const; @@ -52,6 +55,7 @@ private: Http::StatusCode status; SBuf object; //object data size_t maxObjectSize; + unsigned int level_; ///< Holds the nested downloads level }; #endif diff --git a/src/ssl/PeerConnector.cc b/src/ssl/PeerConnector.cc index a2967510fb..71c5a620a4 100644 --- a/src/ssl/PeerConnector.cc +++ b/src/ssl/PeerConnector.cc @@ -42,7 +42,8 @@ Ssl::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, As callback(aCallback), negotiationTimeout(timeout), startTime(squid_curtime), - useCertValidator_(false) + useCertValidator_(false), + certsDownloads(0) { // if this throws, the caller's cb dialer is not our CbDialer Must(dynamic_cast(callback->getDialer())); @@ -638,14 +639,16 @@ Ssl::PeerConnector::startCertDownloading(SBuf &url) "Ssl::PeerConnector::certDownloadingDone", PeerConnectorCertDownloaderDialer(&Ssl::PeerConnector::certDownloadingDone, this)); + const Downloader *csd = dynamic_cast(request->clientConnectionManager.valid()); MasterXaction *xaction = new MasterXaction; - Downloader *dl = new Downloader(url, xaction, certCallback); + Downloader *dl = new Downloader(url, xaction, certCallback, csd ? csd->nestedLevel() + 1 : 1); AsyncJob::Start(dl); } void Ssl::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus) { + certsDownloads++; debugs(81, 5, "OK! certificate downloaded, status: " << downloadStatus << " data size: " << obj.length()); // Get ServerBio from SSL object @@ -667,7 +670,7 @@ Ssl::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus) } // Check if has uri to donwload and add it to urlsOfMissingCerts - if (urlsOfMissingCerts.size()) { + if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) { startCertDownloading(urlsOfMissingCerts.front()); urlsOfMissingCerts.pop(); return; @@ -680,6 +683,13 @@ Ssl::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus) bool Ssl::PeerConnector::checkForMissingCertificates () { + // Check for nested SSL certificates downloads. For example when the + // certificate located in an SSL site which requires to download a + // a missing certificate (... from an SSL site which requires to ...) + const Downloader *csd = dynamic_cast(request->clientConnectionManager.valid()); + if (csd && csd->nestedLevel() >= MaxNestedDownloads) + return false; + const int fd = serverConnection()->fd; SSL *ssl = fd_table[fd].ssl; BIO *b = SSL_get_rbio(ssl); diff --git a/src/ssl/PeerConnector.h b/src/ssl/PeerConnector.h index 8bec0943d0..ba5af4d5a7 100644 --- a/src/ssl/PeerConnector.h +++ b/src/ssl/PeerConnector.h @@ -177,13 +177,20 @@ private: /// A wrapper function for negotiateSsl for use with Comm::SetSelect static void NegotiateSsl(int fd, void *data); + + /// The maximum allowed missing certificates downloads + static const unsigned int MaxCertsDownloads = 10; + /// The maximum allowed nested certificates downloads + static const unsigned int MaxNestedDownloads = 3; + AsyncCall::Pointer callback; ///< we call this with the results AsyncCall::Pointer closeHandler; ///< we call this when the connection closed time_t negotiationTimeout; ///< the SSL connection timeout to use time_t startTime; ///< when the peer connector negotiation started bool useCertValidator_; ///< whether the certificate validator should bypassed - + /// The list of URLs where missing certificates should be downloaded std::queue urlsOfMissingCerts; + unsigned int certsDownloads; ///< The number of downloaded missing certificates }; /// A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.