]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/ssl/support.cc
merge from trunk
[thirdparty/squid.git] / src / ssl / support.cc
index f944bf0c4e21353848ce1facf9861daebf67c05c..33566e137a822289b232050fbb4339b729c13865 100644 (file)
 
 #include "acl/FilledChecklist.h"
 #include "anyp/PortCfg.h"
+#include "fd.h"
 #include "fde.h"
 #include "globals.h"
 #include "ipc/MemMap.h"
 #include "SquidConfig.h"
 #include "SquidTime.h"
+#include "ssl/bio.h"
 #include "ssl/Config.h"
 #include "ssl/ErrorDetail.h"
 #include "ssl/gadgets.h"
@@ -63,6 +65,7 @@ const char *Ssl::BumpModeStr[] = {
     "none",
     "client-first",
     "server-first",
+    "peek-and-splice",
     NULL
 };
 
@@ -1005,28 +1008,95 @@ sslCreateServerContext(AnyP::PortCfg &port)
     return sslContext;
 }
 
-SSL_CTX *
-sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile)
+int Ssl::OpenSSLtoSquidSSLVersion(int sslVersion)
 {
-    int ssl_error;
-    Ssl::ContextMethod method;
-    SSL_CTX * sslContext;
-    long fl = Ssl::parse_flags(flags);
+    if(sslVersion == SSL2_VERSION)
+        return 2;
+    else if(sslVersion == SSL3_VERSION)
+        return 3;
+    else if(sslVersion == TLS1_VERSION)
+        return 4;
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+    else if(sslVersion == TLS1_1_VERSION)
+        return 5;
+    else if(sslVersion == TLS1_2_VERSION)
+        return 6;
+#endif
+    else
+        return 1;
+}
 
-    ssl_initialize();
 
-    if (!keyfile)
-        keyfile = certfile;
+#if OPENSSL_VERSION_NUMBER < 0x00909000L
+SSL_METHOD *
+#else
+const SSL_METHOD *
+#endif
+Ssl::method(int version)
+{
+    switch (version) {
 
-    if (!certfile)
-        certfile = keyfile;
+    case 2:
+#ifndef OPENSSL_NO_SSL2
+        debugs(83, 5, "Using SSLv2.");
+        return SSLv2_client_method();
+#else
+        debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy.");
+        return NULL;
+#endif
+        break;
+
+    case 3:
+        debugs(83, 5, "Using SSLv3.");
+        return SSLv3_client_method();
+        break;
+
+    case 4:
+        debugs(83, 5, "Using TLSv1.");
+        return TLSv1_client_method();
+        break;
 
+    case 5:
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L  // NP: not sure exactly which sub-version yet.
+        debugs(83, 5, "Using TLSv1.1.");
+        return TLSv1_1_client_method();
+#else
+        debugs(83, DBG_IMPORTANT, "TLSv1.1 is not available in this Proxy.");
+        return NULL;
+#endif
+        break;
+
+    case 6:
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
+        debugs(83, 5, "Using TLSv1.2");
+        return TLSv1_2_client_method();
+#else
+        debugs(83, DBG_IMPORTANT, "TLSv1.2 is not available in this Proxy.");
+        return NULL;
+#endif
+        break;
+
+    case 1:
+
+    default:
+        debugs(83, 5, "Using SSLv2/SSLv3.");
+        return SSLv23_client_method();
+        break;
+    }
+
+    //Not reached
+    return NULL;
+}
+
+const SSL_METHOD *
+Ssl::serverMethod(int version)
+{
     switch (version) {
 
     case 2:
 #ifndef OPENSSL_NO_SSL2
         debugs(83, 5, "Using SSLv2.");
-        method = SSLv2_client_method();
+        return SSLv2_server_method();
 #else
         debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy.");
         return NULL;
@@ -1035,18 +1105,18 @@ sslCreateClientContext(const char *certfile, const char *keyfile, int version, c
 
     case 3:
         debugs(83, 5, "Using SSLv3.");
-        method = SSLv3_client_method();
+        return SSLv3_server_method();
         break;
 
     case 4:
         debugs(83, 5, "Using TLSv1.");
-        method = TLSv1_client_method();
+        return TLSv1_server_method();
         break;
 
     case 5:
 #if OPENSSL_VERSION_NUMBER >= 0x10001000L  // NP: not sure exactly which sub-version yet.
         debugs(83, 5, "Using TLSv1.1.");
-        method = TLSv1_1_client_method();
+        return TLSv1_1_server_method();
 #else
         debugs(83, DBG_IMPORTANT, "TLSv1.1 is not available in this Proxy.");
         return NULL;
@@ -1056,7 +1126,7 @@ sslCreateClientContext(const char *certfile, const char *keyfile, int version, c
     case 6:
 #if OPENSSL_VERSION_NUMBER >= 0x10001000L // NP: not sure exactly which sub-version yet.
         debugs(83, 5, "Using TLSv1.2");
-        method = TLSv1_2_client_method();
+        return TLSv1_2_server_method();
 #else
         debugs(83, DBG_IMPORTANT, "TLSv1.2 is not available in this Proxy.");
         return NULL;
@@ -1067,10 +1137,33 @@ sslCreateClientContext(const char *certfile, const char *keyfile, int version, c
 
     default:
         debugs(83, 5, "Using SSLv2/SSLv3.");
-        method = SSLv23_client_method();
+        return SSLv23_server_method();
         break;
     }
 
+    //Not reached
+    return NULL;
+}
+
+SSL_CTX *
+sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile)
+{
+    int ssl_error;
+    Ssl::ContextMethod method;
+    SSL_CTX * sslContext;
+    long fl = Ssl::parse_flags(flags);
+
+    ssl_initialize();
+
+    if (!keyfile)
+        keyfile = certfile;
+
+    if (!certfile)
+        certfile = keyfile;
+
+    if (!(method = Ssl::method(version)))
+        return NULL;
+        
     sslContext = SSL_CTX_new(method);
 
     if (sslContext == NULL) {
@@ -1460,8 +1553,8 @@ Ssl::contextMethod(int version)
 
 /// \ingroup ServerProtocolSSLInternal
 /// Create SSL context and apply ssl certificate and private key to it.
-static SSL_CTX *
-createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
+SSL_CTX *
+Ssl::createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
 {
     Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(port.contextMethod));
 
@@ -1508,6 +1601,49 @@ Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &
     return createSSLContext(cert, pkey, port);
 }
 
+bool
+Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
+{
+    Ssl::X509_Pointer cert;
+    Ssl::EVP_PKEY_Pointer pkey;
+    if (!generateSslCertificate(cert, pkey, properties))
+        return false;
+
+    if (!cert)
+        return false;
+
+    if (!pkey)
+        return false;
+
+    if (!SSL_use_certificate(ssl, cert.get()))
+        return false;
+
+    if (!SSL_use_PrivateKey(ssl, pkey.get()))
+        return false;
+
+    return true;
+}
+
+bool
+Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
+{
+    Ssl::X509_Pointer cert;
+    Ssl::EVP_PKEY_Pointer pkey;
+    if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
+        return false;
+
+    if (!cert || !pkey)
+        return false;
+
+    if (!SSL_use_certificate(ssl, cert.get()))
+        return false;
+
+    if (!SSL_use_PrivateKey(ssl, pkey.get()))
+        return false;
+
+    return true;
+}
+
 bool Ssl::verifySslCertificate(SSL_CTX * sslContext, CertificateProperties const &properties)
 {
     // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
@@ -1650,6 +1786,48 @@ bool Ssl::generateUntrustedCert(X509_Pointer &untrustedCert, EVP_PKEY_Pointer &u
     return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
 }
 
+SSL *
+SslCreate(SSL_CTX *sslContext, const int fd, Ssl::Bio::Type type, const char *squidCtx)
+{
+    const char *errAction = NULL;
+    int errCode = 0;
+    if (SSL *ssl = SSL_new(sslContext)) {
+        // without BIO, we would call SSL_set_fd(ssl, fd) instead
+        if (BIO *bio = Ssl::Bio::Create(fd, type)) {
+            Ssl::Bio::Link(ssl, bio); // cannot fail
+
+            fd_table[fd].ssl = ssl;
+            fd_table[fd].read_method = &ssl_read_method;
+            fd_table[fd].write_method = &ssl_write_method;
+            fd_note(fd, squidCtx);
+
+            return ssl;
+        }
+        errCode = ERR_get_error();
+        errAction = "failed to initialize I/O";
+        SSL_free(ssl);
+    } else {
+        errCode = ERR_get_error();
+        errAction = "failed to allocate handle";
+    }
+
+    debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
+           ": " << ERR_error_string(errCode, NULL));
+    return NULL;
+}
+
+SSL *
+Ssl::CreateClient(SSL_CTX *sslContext, const int fd, const char *squidCtx)
+{
+    return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_SERVER, squidCtx);
+}
+
+SSL *
+Ssl::CreateServer(SSL_CTX *sslContext, const int fd, const char *squidCtx)
+{
+    return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
+}
+
 Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert): code(anErr)
 {
     cert.resetAndLock(aCert);