]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
merge from trunk-r14768
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 1 Aug 2016 11:11:47 +0000 (14:11 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 1 Aug 2016 11:11:47 +0000 (14:11 +0300)
1  2 
src/Makefile.am
src/client_side_reply.cc
src/client_side_request.cc
src/security/PeerConnector.cc
src/security/PeerConnector.h
src/security/forward.h
src/ssl/support.cc
src/ssl/support.h

diff --cc src/Makefile.am
Simple merge
Simple merge
Simple merge
index bc19bee365a88c46874a9e01fb9dc8ac3c3237d3,b3332088aeccf39b4e44f77fb2d27361fd6feae9..720ffa7f031b30f5c46f1e2c5af6f99b569a9a6a
  #include "squid.h"
  #include "acl/FilledChecklist.h"
  #include "comm/Loops.h"
 +#include "Downloader.h"
  #include "errorpage.h"
  #include "fde.h"
 +#include "http/Stream.h"
  #include "HttpRequest.h"
  #include "security/NegotiationHistory.h"
+ #include "security/PeerConnector.h"
  #include "SquidConfig.h"
+ #if USE_OPENSSL
  #include "ssl/bio.h"
  #include "ssl/cert_validate_message.h"
  #include "ssl/Config.h"
@@@ -33,9 -33,9 +35,10 @@@ Security::PeerConnector::PeerConnector(
      callback(aCallback),
      negotiationTimeout(timeout),
      startTime(squid_curtime),
 -    useCertValidator_(true)
 +    useCertValidator_(true),
 +    certsDownloads(0)
  {
+     debugs(83, 5, "Security::PeerConnector constructed, this=" << (void*)this);
      // if this throws, the caller's cb dialer is not our CbDialer
      Must(dynamic_cast<CbDialer*>(callback->getDialer()));
  }
@@@ -361,31 -382,10 +385,32 @@@ Security::PeerConnector::handleNegotiat
  }
  
  void
- Ssl::PeerConnector::noteWantRead()
+ Security::PeerConnector::noteWantRead()
  {
 -    setReadTimeout();
      const int fd = serverConnection()->fd;
-             Ssl::PeerConnector::NegotiateSsl(fd, this);
++#if USE_OPENSSL
 +    Security::SessionPtr ssl = fd_table[fd].ssl.get();
 +    BIO *b = SSL_get_rbio(ssl);
 +    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
 +    if (srvBio->holdRead()) {
 +        if (srvBio->gotHello()) {
 +            if (checkForMissingCertificates())
 +                return; // Wait to download certificates before proceed.
 +
 +            srvBio->holdRead(false);
 +            // schedule a negotiateSSl to allow openSSL parse received data
-             Ssl::PeerConnector::NegotiateSsl(fd, this);
++            Security::PeerConnector::NegotiateSsl(fd, this);
 +            return;
 +        } else if (srvBio->gotHelloFailed()) {
 +            srvBio->holdRead(false);
 +            debugs(83, DBG_IMPORTANT, "Error parsing SSL Server Hello Message on FD " << fd);
 +            // schedule a negotiateSSl to allow openSSL parse received data
++            Security::PeerConnector::NegotiateSsl(fd, this);
 +            return;
 +        }
 +    }
++#endif
 +    setReadTimeout();
      Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
  }
  
@@@ -513,104 -515,3 +540,105 @@@ Security::PeerConnector::status() cons
      return buf.content();
  }
  
-     typedef void (Ssl::PeerConnector::*Method)(SBuf &object, int status);
++#if USE_OPENSSL
 +/// CallDialer to allow use Downloader objects within PeerConnector class.
 +class PeerConnectorCertDownloaderDialer: public Downloader::CbDialer
 +{
 +public:
-     PeerConnectorCertDownloaderDialer(Method method, Ssl::PeerConnector *pc):
++    typedef void (Security::PeerConnector::*Method)(SBuf &object, int status);
 +
-     Method method_; ///< The Ssl::PeerConnector method to dial
-     CbcPointer<Ssl::PeerConnector> peerConnector_; ///< The Ssl::PeerConnector object
++    PeerConnectorCertDownloaderDialer(Method method, Security::PeerConnector *pc):
 +        method_(method),
 +        peerConnector_(pc) {}
 +
 +    /* CallDialer API */
 +    virtual bool canDial(AsyncCall &call) { return peerConnector_.valid(); }
 +    virtual void dial(AsyncCall &call) { ((&(*peerConnector_))->*method_)(object, status); }
- Ssl::PeerConnector::startCertDownloading(SBuf &url)
++    Method method_; ///< The Security::PeerConnector method to dial
++    CbcPointer<Security::PeerConnector> peerConnector_; ///< The Security::PeerConnector object
 +};
 +
 +void
-                                             "Ssl::PeerConnector::certDownloadingDone",
-                                             PeerConnectorCertDownloaderDialer(&Ssl::PeerConnector::certDownloadingDone, this));
++Security::PeerConnector::startCertDownloading(SBuf &url)
 +{
 +    AsyncCall::Pointer certCallback = asyncCall(81, 4,
- Ssl::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus)
++                                            "Security::PeerConnector::certDownloadingDone",
++                                            PeerConnectorCertDownloaderDialer(&Security::PeerConnector::certDownloadingDone, this));
 +
 +    const Downloader *csd = dynamic_cast<const Downloader*>(request->downloader.valid());
 +    Downloader *dl = new Downloader(url, certCallback, csd ? csd->nestedLevel() + 1 : 1);
 +    AsyncJob::Start(dl);
 +}
 +
 +void
-     Ssl::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
++Security::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus)
 +{
 +    ++certsDownloads;
 +    debugs(81, 5, "Certificate downloading status: " << downloadStatus << " certificate size: " << obj.length());
 +
 +    // get ServerBio from SSL object
 +    const int fd = serverConnection()->fd;
 +    Security::SessionPtr ssl = fd_table[fd].ssl.get();
 +    BIO *b = SSL_get_rbio(ssl);
 +    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
 +
 +    // Parse Certificate. Assume that it is in DER format.
 +    // According to RFC 4325:
 +    //  The server must provide a DER encoded certificate or a collection
 +    // collection of certificates in a "certs-only" CMS message.
 +    //  The applications MUST accept DER encoded certificates and SHOULD
 +    // be able to accept collection of certificates.
 +    // TODO: support collection of certificates
 +    const unsigned char *raw = (const unsigned char*)obj.rawContent();
 +    if (X509 *cert = d2i_X509(NULL, &raw, obj.length())) {
 +        char buffer[1024];
 +        debugs(81, 5, "Retrieved certificate: " << X509_NAME_oneline(X509_get_subject_name(cert), buffer, 1024));
 +        const Security::CertList &certsList = srvBio->serverCertificatesIfAny();
 +        if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert,  certsList)) {
 +            urlsOfMissingCerts.push(SBuf(issuerUri));
 +        }
 +        Ssl::SSL_add_untrusted_cert(ssl, cert);
 +    }
 +
 +    // Check if there are URIs to download from and if yes start downloading
 +    // the first in queue.
 +    if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) {
 +        startCertDownloading(urlsOfMissingCerts.front());
 +        urlsOfMissingCerts.pop();
 +        return;
 +    }
 +
 +    srvBio->holdRead(false);
- Ssl::PeerConnector::checkForMissingCertificates()
++    Security::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
 +}
 +
 +bool
++Security::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 = request->downloader.get();
 +    if (csd && csd->nestedLevel() >= MaxNestedDownloads)
 +        return false;
 +
 +    const int fd = serverConnection()->fd;
 +    Security::SessionPtr ssl = fd_table[fd].ssl.get();
 +    BIO *b = SSL_get_rbio(ssl);
 +    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
 +    const Security::CertList &certs = srvBio->serverCertificatesIfAny();
 +
 +    if (certs.size()) {
 +        debugs(83, 5, "SSL server sent " << certs.size() << " certificates");
 +        Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs);
 +        if (urlsOfMissingCerts.size()) {
 +            startCertDownloading(urlsOfMissingCerts.front());
 +            urlsOfMissingCerts.pop();
 +            return true;
 +        }
 +    }
 +
 +    return false;
 +}
++#endif //USE_OPENSSL
index 15351324a5de6c194acb361d4fe76aa913cda56c,5d434398c84e08a5fef1f9215a62ad50cc991a4b..fad47517cdc76bed7a1a2891af86eb391cc9db63
  #include "base/AsyncJob.h"
  #include "CommCalls.h"
  #include "security/EncryptorAnswer.h"
+ #include "security/forward.h"
+ #if USE_OPENSSL
  #include "ssl/support.h"
+ #endif
  
  #include <iosfwd>
 +#include <queue>
  
- #if USE_OPENSSL
  class HttpRequest;
  class ErrorState;
  class AccessLogEntry;
@@@ -125,18 -125,6 +126,20 @@@ protected
      /// Squid COMM_SELECT_READ handler.
      void noteWantRead();
  
++#if USE_OPENSSL
 +    /// Run the certificates list sent by the SSL server and check if there
 +    /// are missing certificates. Adds to the urlOfMissingCerts list the 
 +    /// URLS of missing certificates if this information provided by the
 +    /// issued certificates with Authority Info Access extension.
 +    bool checkForMissingCertificates();
 +
 +    /// Start downloading procedure for the given URL.
 +    void startCertDownloading(SBuf &url);
 +
 +    /// Called by Downloader after a certificate object downloaded.
 +    void certDownloadingDone(SBuf &object, int status);
++#endif
 +
      /// Called when the openSSL SSL_connect function needs to write data to
      /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler.
      virtual void noteWantWrite();
@@@ -198,13 -182,9 +203,12 @@@ private
      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<SBuf> urlsOfMissingCerts;
 +    unsigned int certsDownloads; ///< the number of downloaded missing certificates
  };
  
- } // namespace Ssl
+ } // namespace Security
  
- #endif /* USE_OPENSSL */
  #endif /* SQUID_SRC_SSL_PEERCONNECTOR_H */
  
Simple merge
Simple merge
Simple merge