------------------------------------------------------------ revno: 12317 revision-id: chtsanti@users.sourceforge.net-20120906131226-ncmyiz302d2du9mw parent: squid3@treenet.co.nz-20120902102359-jpxv5xzgu1dgtr5w committer: Christos Tsantilas branch nick: trunk timestamp: Thu 2012-09-06 16:12:26 +0300 message: Bug fix: TLS/SSL Options does not apply to the dynamically generated certificates The TLS/SSL options configured with http_port configuration parameter does not used to generate SSL_CTX context objects used to establish SSL connections. This is means that certificate based authentication, or SSL version selection and other SSL/TLS http_port options does not work for ssl-bumped connection. This patch fixes this problem. This is a Measurement Factory project ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: chtsanti@users.sourceforge.net-20120906131226-\ # ncmyiz302d2du9mw # target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # testament_sha1: 9a9e5aabe85dd6ee18ee5725e1e9354557e672dd # timestamp: 2012-09-06 13:52:18 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # base_revision_id: squid3@treenet.co.nz-20120902102359-\ # jpxv5xzgu1dgtr5w # # Begin patch === modified file 'src/anyp/PortCfg.cc' --- src/anyp/PortCfg.cc 2012-05-14 10:37:40 +0000 +++ src/anyp/PortCfg.cc 2012-09-06 13:12:26 +0000 @@ -96,20 +96,6 @@ #if USE_SSL void AnyP::PortCfg::configureSslServerContext() { - staticSslContext.reset( - sslCreateServerContext(cert, key, - version, cipher, options, sslflags, clientca, - cafile, capath, crlfile, dhfile, - sslContextSessionId)); - - if (!staticSslContext) { - char buf[128]; - fatalf("%s_port %s initialization error", protocol, s.ToURL(buf, sizeof(buf))); - } - - if (!sslBump) - return; - if (cert) Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, cert, key); @@ -128,6 +114,35 @@ char buf[128]; fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", protocol, s.ToURL(buf, sizeof(buf))); } + + if (crlfile) + clientVerifyCrls.reset(Ssl::loadCrl(crlfile, sslContextFlags)); + + if (clientca) { + clientCA.reset(SSL_load_client_CA_file(clientca)); + if (clientCA.get() == NULL) { + fatalf("Unable to read client CAs! from %s", clientca); + } + } + + contextMethod = Ssl::contextMethod(version); + if (!contextMethod) + fatalf("Unable to compute context method to use"); + + if (dhfile) + dhParams.reset(Ssl::readDHParams(dhfile)); + + if (sslflags) + sslContextFlags = Ssl::parse_flags(sslflags); + + sslOptions = Ssl::parse_options(options); + + staticSslContext.reset(sslCreateServerContext(*this)); + + if (!staticSslContext) { + char buf[128]; + fatalf("%s_port %s initialization error", protocol, s.ToURL(buf, sizeof(buf))); + } } #endif === modified file 'src/anyp/PortCfg.h' --- src/anyp/PortCfg.h 2012-06-19 21:51:49 +0000 +++ src/anyp/PortCfg.h 2012-09-06 13:12:26 +0000 @@ -76,6 +76,13 @@ Ssl::X509_STACK_Pointer certsToChain; ///< x509 certificates to send with the generated cert Ssl::X509_Pointer untrustedSigningCert; ///< x509 certificate for signing untrusted generated certificates Ssl::EVP_PKEY_Pointer untrustedSignPkey; ///< private key for signing untrusted generated certificates + + Ssl::X509_CRL_STACK_Pointer clientVerifyCrls; ///< additional CRL lists to use when verifying the client certificate + Ssl::X509_NAME_STACK_Pointer clientCA; ///< CA certificates to use when verifying client certificates + Ssl::DH_Pointer dhParams; ///< DH parameters for temporary/ephemeral DH key exchanges + Ssl::ContextMethod contextMethod; ///< The context method (SSL_METHOD) to use when creating certificates + long sslContextFlags; ///< flags modifying the use of SSL + long sslOptions; ///< SSL engine options #endif CBDATA_CLASS2(PortCfg); // namespaced === modified file 'src/client_side.cc' --- src/client_side.cc 2012-08-30 09:02:06 +0000 +++ src/client_side.cc 2012-09-06 13:12:26 +0000 @@ -3700,7 +3700,7 @@ debugs(33, 5, HERE << "Certificate for " << sslConnectHostOrIp << " cannot be generated. ssl_crtd response: " << reply_message.getBody()); } else { debugs(33, 5, HERE << "Certificate for " << sslConnectHostOrIp << " was successfully recieved from ssl_crtd"); - SSL_CTX *ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str()); + SSL_CTX *ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port); getSslContextDone(ctx, true); return; } @@ -3844,7 +3844,7 @@ #endif // USE_SSL_CRTD debugs(33, 5, HERE << "Generating SSL certificate for " << certProperties.commonName); - dynCtx = Ssl::generateSslContext(certProperties); + dynCtx = Ssl::generateSslContext(certProperties, *port); getSslContextDone(dynCtx, true); return; } === modified file 'src/ssl/gadgets.h' --- src/ssl/gadgets.h 2012-08-28 13:00:30 +0000 +++ src/ssl/gadgets.h 2012-09-06 13:12:26 +0000 @@ -26,6 +26,12 @@ because they are used by ssl_crtd. */ +#if OPENSSL_VERSION_NUMBER < 0x00909000L +typedef SSL_METHOD * ContextMethod; +#else +typedef const SSL_METHOD * ContextMethod; +#endif + /** \ingroup SslCrtdSslAPI * Add SSL locking (a.k.a. reference counting) to TidyPointer @@ -55,6 +61,14 @@ function(a); \ } +// Macro to be used to define the C++ wrapper function of a sk_*_pop_free +// openssl family functions. The C++ function suffixed with the _free_wrapper +// extension +#define sk_free_wrapper(sk_object, argument, freefunction) \ + extern "C++" inline void sk_object ## _free_wrapper(argument a) { \ + sk_object ## _pop_free(a, freefunction); \ + } + /** \ingroup SslCrtdSslAPI * TidyPointer typedefs for common SSL objects @@ -62,8 +76,8 @@ CtoCpp1(X509_free, X509 *) typedef LockingPointer X509_Pointer; -CtoCpp1(sk_X509_free, STACK_OF(X509) *) -typedef TidyPointer X509_STACK_Pointer; +sk_free_wrapper(sk_X509, STACK_OF(X509) *, X509_free) +typedef TidyPointer X509_STACK_Pointer; CtoCpp1(EVP_PKEY_free, EVP_PKEY *) typedef LockingPointer EVP_PKEY_Pointer; @@ -95,6 +109,15 @@ CtoCpp1(SSL_free, SSL *) typedef TidyPointer SSL_Pointer; +CtoCpp1(DH_free, DH *); +typedef TidyPointer DH_Pointer; + +sk_free_wrapper(sk_X509_CRL, STACK_OF(X509_CRL) *, X509_CRL_free) +typedef TidyPointer X509_CRL_STACK_Pointer; + +sk_free_wrapper(sk_X509_NAME, STACK_OF(X509_NAME) *, X509_NAME_free) +typedef TidyPointer X509_NAME_STACK_Pointer; + /** \ingroup SslCrtdSslAPI * Create 1024 bits rsa key. === modified file 'src/ssl/support.cc' --- src/ssl/support.cc 2012-08-28 19:12:13 +0000 +++ src/ssl/support.cc 2012-09-06 13:12:26 +0000 @@ -41,6 +41,7 @@ #if USE_SSL #include "acl/FilledChecklist.h" +#include "anyp/PortCfg.h" #include "fde.h" #include "globals.h" #include "protos.h" @@ -451,8 +452,8 @@ }; /// \ingroup ServerProtocolSSLInternal -static long -ssl_parse_options(const char *options) +long +Ssl::parse_options(const char *options) { long op = 0; char *tmp; @@ -545,8 +546,8 @@ #define SSL_FLAG_VERIFY_CRL_ALL (1<<6) /// \ingroup ServerProtocolSSLInternal -static long -ssl_parse_flags(const char *flags) +long +Ssl::parse_flags(const char *flags) { long fl = 0; char *tmp; @@ -705,99 +706,71 @@ return count; } -SSL_CTX * -sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath, const char *CRLfile, const char *dhfile, const char *context) +STACK_OF(X509_CRL) * +Ssl::loadCrl(const char *CRLFile, long &flags) +{ + X509_CRL *crl; + BIO *in = BIO_new_file(CRLFile, "r"); + if (!in) { + debugs(83, 2, "WARNING: Failed to open CRL file '" << CRLFile << "'"); + return NULL; + } + + STACK_OF(X509_CRL) *CRLs = sk_X509_CRL_new_null(); + if (!CRLs) { + debugs(83, 2, "WARNING: Failed to allocate X509_CRL stack to load file '" << CRLFile << "'"); + return NULL; + } + + int count = 0; + while ((crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL))) { + if (!sk_X509_CRL_push(CRLs, crl)) + debugs(83, 2, "WARNING: Failed to add CRL from file '" << CRLFile << "'"); + else + ++count; + } + BIO_free(in); + + if (count) + flags |= SSL_FLAG_VERIFY_CRL; + + return CRLs; +} + +DH * +Ssl::readDHParams(const char *dhfile) +{ + FILE *in = fopen(dhfile, "r"); + DH *dh = NULL; + int codes; + + if (in) { + dh = PEM_read_DHparams(in, NULL, NULL, NULL); + fclose(in); + } + + if (!dh) + debugs(83, DBG_IMPORTANT, "WARNING: Failed to read DH parameters '" << dhfile << "'"); + else if (dh && DH_check(dh, &codes) == 0) { + if (codes) { + debugs(83, DBG_IMPORTANT, "WARNING: Failed to verify DH parameters '" << dhfile << "' (" << std::hex << codes << ")"); + DH_free(dh); + dh = NULL; + } + } + return dh; +} + +static bool +configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port) { int ssl_error; -#if OPENSSL_VERSION_NUMBER < 0x00909000L - SSL_METHOD *method; -#else - const SSL_METHOD *method; -#endif - SSL_CTX *sslContext; - long fl = ssl_parse_flags(flags); - - ssl_initialize(); - - if (!keyfile) - keyfile = certfile; - - if (!certfile) - certfile = keyfile; - - if (!CAfile) - CAfile = clientCA; - - if (!certfile) { - debugs(83, DBG_CRITICAL, "ERROR: No certificate file"); - return NULL; - } - - switch (version) { - - case 2: -#ifndef OPENSSL_NO_SSL2 - debugs(83, 5, "Using SSLv2."); - method = SSLv2_server_method(); -#else - debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy."); - return NULL; -#endif - break; - - case 3: - debugs(83, 5, "Using SSLv3."); - method = SSLv3_server_method(); - break; - - case 4: - debugs(83, 5, "Using TLSv1."); - method = 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_server_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"); - method = TLSv1_2_server_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."); - method = SSLv23_server_method(); - break; - } - - sslContext = SSL_CTX_new(method); - - if (sslContext == NULL) { - ssl_error = ERR_get_error(); - debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL)); - return NULL; - } - - SSL_CTX_set_options(sslContext, ssl_parse_options(options)); - - if (context && *context) { - SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)context, strlen(context)); - } - - if (fl & SSL_FLAG_NO_SESSION_REUSE) { + SSL_CTX_set_options(sslContext, port.sslOptions); + + if (port.sslContextSessionId) + SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId)); + + if (port.sslContextFlags & SSL_FLAG_NO_SESSION_REUSE) { SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF); } @@ -807,77 +780,38 @@ SSL_CTX_set_quiet_shutdown(sslContext, 1); } - if (cipher) { - debugs(83, 5, "Using chiper suite " << cipher << "."); + if (port.cipher) { + debugs(83, 5, "Using chiper suite " << port.cipher << "."); - if (!SSL_CTX_set_cipher_list(sslContext, cipher)) { + if (!SSL_CTX_set_cipher_list(sslContext, port.cipher)) { ssl_error = ERR_get_error(); - debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << cipher << "': " << ERR_error_string(ssl_error, NULL)); - SSL_CTX_free(sslContext); - return NULL; + debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.cipher << "': " << ERR_error_string(ssl_error, NULL)); + return false; } } - debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile); - - if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) { - ssl_error = ERR_get_error(); - debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL)); - SSL_CTX_free(sslContext); - return NULL; - } - - debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile); - ssl_ask_password(sslContext, keyfile); - - if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) { - ssl_error = ERR_get_error(); - debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL)); - SSL_CTX_free(sslContext); - return NULL; - } - - debugs(83, 5, "Comparing private and public SSL keys."); - - if (!SSL_CTX_check_private_key(sslContext)) { - ssl_error = ERR_get_error(); - debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" << - keyfile << "': " << ERR_error_string(ssl_error, NULL)); - SSL_CTX_free(sslContext); - return NULL; - } - debugs(83, 9, "Setting RSA key generation callback."); SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb); debugs(83, 9, "Setting CA certificate locations."); - if ((CAfile || CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) { + const char *cafile = port.cafile ? port.cafile : port.clientca; + if ((cafile || port.capath) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.capath)) { ssl_error = ERR_get_error(); debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL)); } - if (!(fl & SSL_FLAG_NO_DEFAULT_CA) && + if (!(port.sslContextFlags & SSL_FLAG_NO_DEFAULT_CA) && !SSL_CTX_set_default_verify_paths(sslContext)) { ssl_error = ERR_get_error(); debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL)); } - if (clientCA) { - STACK_OF(X509_NAME) *cert_names; - debugs(83, 9, "Set client certifying authority list."); - cert_names = SSL_load_client_CA_file(clientCA); - - if (cert_names == NULL) { - debugs(83, DBG_IMPORTANT, "ERROR: loading the client CA certificates from '" << clientCA << "\': " << ERR_error_string(ERR_get_error(),NULL)); - SSL_CTX_free(sslContext); - return NULL; - } - + if (port.clientCA.get()) { ERR_clear_error(); - SSL_CTX_set_client_CA_list(sslContext, cert_names); + SSL_CTX_set_client_CA_list(sslContext, port.clientCA.get()); - if (fl & SSL_FLAG_DELAYED_AUTH) { + if (port.sslContextFlags & SSL_FLAG_DELAYED_AUTH) { debugs(83, 9, "Not requesting client certificates until acl processing requires one"); SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); } else { @@ -885,17 +819,20 @@ SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); } - if (CRLfile) { - ssl_load_crl(sslContext, CRLfile); - fl |= SSL_FLAG_VERIFY_CRL; + if (port.clientVerifyCrls.get()) { + X509_STORE *st = SSL_CTX_get_cert_store(sslContext); + for (int i = 0; i < sk_X509_CRL_num(port.clientVerifyCrls.get()); ++i) { + X509_CRL *crl = sk_X509_CRL_value(port.clientVerifyCrls.get(), i); + if (!X509_STORE_add_crl(st, crl)) + debugs(83, 2, "WARNING: Failed to add CRL"); + } } #if X509_V_FLAG_CRL_CHECK - if (fl & SSL_FLAG_VERIFY_CRL_ALL) + if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL_ALL) X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - else if (fl & SSL_FLAG_VERIFY_CRL) + else if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL) X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK); - #endif } else { @@ -903,33 +840,94 @@ SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL); } - if (dhfile) { - FILE *in = fopen(dhfile, "r"); - DH *dh = NULL; - int codes; - - if (in) { - dh = PEM_read_DHparams(in, NULL, NULL, NULL); - fclose(in); - } - - if (!dh) - debugs(83, DBG_IMPORTANT, "WARNING: Failed to read DH parameters '" << dhfile << "'"); - else if (dh && DH_check(dh, &codes) == 0) { - if (codes) { - debugs(83, DBG_IMPORTANT, "WARNING: Failed to verify DH parameters '" << dhfile << "' (" << std::hex << codes << ")"); - DH_free(dh); - dh = NULL; - } - } - - if (dh) - SSL_CTX_set_tmp_dh(sslContext, dh); + if (port.dhParams.get()) { + SSL_CTX_set_tmp_dh(sslContext, port.dhParams.get()); } - if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN) + if (port.sslContextFlags & SSL_FLAG_DONT_VERIFY_DOMAIN) SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1); + return true; +} + +SSL_CTX * +sslCreateServerContext(AnyP::PortCfg &port) +{ + int ssl_error; + SSL_CTX *sslContext; + const char *keyfile, *certfile; + certfile = port.cert; + keyfile = port.key; + + ssl_initialize(); + + if (!keyfile) + keyfile = certfile; + + if (!certfile) + certfile = keyfile; + + sslContext = SSL_CTX_new(port.contextMethod); + + if (sslContext == NULL) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL)); + return NULL; + } + + if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL)); + SSL_CTX_free(sslContext); + return NULL; + } + + if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL)); + SSL_CTX_free(sslContext); + return NULL; + } + + Ssl::addChainToSslContext(sslContext, port.certsToChain.get()); + + /* Alternate code; + debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile); + + if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL)); + SSL_CTX_free(sslContext); + return NULL; + } + + debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile); + ssl_ask_password(sslContext, keyfile); + + if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL)); + SSL_CTX_free(sslContext); + return NULL; + } + + debugs(83, 5, "Comparing private and public SSL keys."); + + if (!SSL_CTX_check_private_key(sslContext)) { + ssl_error = ERR_get_error(); + debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" << + keyfile << "': " << ERR_error_string(ssl_error, NULL)); + SSL_CTX_free(sslContext); + return NULL; + } + */ + + if (!configureSslContext(sslContext, port)) { + debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context"); + SSL_CTX_free(sslContext); + return NULL; + } + return sslContext; } @@ -943,7 +941,7 @@ const SSL_METHOD *method; #endif SSL_CTX *sslContext; - long fl = ssl_parse_flags(flags); + long fl = Ssl::parse_flags(flags); ssl_initialize(); @@ -1011,7 +1009,7 @@ ERR_error_string(ssl_error, NULL)); } - SSL_CTX_set_options(sslContext, ssl_parse_options(options)); + SSL_CTX_set_options(sslContext, Ssl::parse_options(options)); if (cipher) { debugs(83, 5, "Using chiper suite " << cipher << "."); @@ -1299,21 +1297,84 @@ return str; } +Ssl::ContextMethod +Ssl::contextMethod(int version) +{ + Ssl::ContextMethod method; + + switch (version) { + + case 2: +#ifndef OPENSSL_NO_SSL2 + debugs(83, 5, "Using SSLv2."); + method = SSLv2_server_method(); +#else + debugs(83, DBG_IMPORTANT, "SSLv2 is not available in this Proxy."); + return NULL; +#endif + break; + + case 3: + debugs(83, 5, "Using SSLv3."); + method = SSLv3_server_method(); + break; + + case 4: + debugs(83, 5, "Using TLSv1."); + method = 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_server_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"); + method = TLSv1_2_server_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."); + method = SSLv23_server_method(); + break; + } + return method; +} + /// \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) +static SSL_CTX * +createSSLContext(Ssl::X509_Pointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port) { - Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(SSLv23_server_method())); + Ssl::SSL_CTX_Pointer sslContext(SSL_CTX_new(port.contextMethod)); if (!SSL_CTX_use_certificate(sslContext.get(), x509.get())) return NULL; if (!SSL_CTX_use_PrivateKey(sslContext.get(), pkey.get())) return NULL; + + if (!configureSslContext(sslContext.get(), port)) + return NULL; + return sslContext.release(); } -SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data) +SSL_CTX * +Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) { Ssl::X509_Pointer cert; Ssl::EVP_PKEY_Pointer pkey; @@ -1323,10 +1384,11 @@ if (!cert || !pkey) return NULL; - return createSSLContext(cert, pkey); + return createSSLContext(cert, pkey, port); } -SSL_CTX * Ssl::generateSslContext(CertificateProperties const &properties) +SSL_CTX * +Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) { Ssl::X509_Pointer cert; Ssl::EVP_PKEY_Pointer pkey; @@ -1339,7 +1401,7 @@ if (!pkey) return NULL; - return createSSLContext(cert, pkey); + return createSSLContext(cert, pkey, port); } bool Ssl::verifySslCertificate(SSL_CTX * sslContext, CertificateProperties const &properties) @@ -1432,6 +1494,12 @@ { if (keyFilename == NULL) keyFilename = certFilename; + + if (certFilename == NULL) + certFilename = keyFilename; + + debugs(83, DBG_IMPORTANT, "Using certificate in " << certFilename); + if (!chain) chain.reset(sk_X509_new_null()); if (!chain) === modified file 'src/ssl/support.h' --- src/ssl/support.h 2012-08-28 13:00:30 +0000 +++ src/ssl/support.h 2012-09-06 13:12:26 +0000 @@ -64,6 +64,11 @@ #define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_CERT_CHANGE #define SQUID_SSL_ERROR_MAX INT_MAX +namespace AnyP +{ +class PortCfg; +}; + namespace Ssl { /// Squid defined error code (<0), an error code returned by SSL X509 api, or SSL_ERROR_NONE @@ -74,7 +79,7 @@ } //namespace Ssl /// \ingroup ServerProtocolSSLAPI -SSL_CTX *sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath, const char *CRLfile, const char *dhpath, const char *context); +SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port); /// \ingroup ServerProtocolSSLAPI 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); @@ -130,6 +135,36 @@ } /** + \ingroup ServerProtocolSSLAPI + * Parses the SSL flags. + */ +long parse_flags(const char *flags); + +/** + \ingroup ServerProtocolSSLAPI + * Parses the SSL options. + */ +long parse_options(const char *options); + +/** + \ingroup ServerProtocolSSLAPI + * Load a CRLs list stored in a file + */ +STACK_OF(X509_CRL) *loadCrl(const char *CRLFile, long &flags); + +/** + \ingroup ServerProtocolSSLAPI + * Load DH params from file + */ +DH *readDHParams(const char *dhfile); + +/** + \ingroup ServerProtocolSSLAPI + * Compute the Ssl::ContextMethod (SSL_METHOD) from SSL version + */ +ContextMethod contextMethod(int version); + +/** \ingroup ServerProtocolSSLAPI * Generate a certificate to be used as untrusted signing certificate, based on a trusted CA */ @@ -139,7 +174,7 @@ \ingroup ServerProtocolSSLAPI * Decide on the kind of certificate and generate a CA- or self-signed one */ -SSL_CTX * generateSslContext(CertificateProperties const &properties); +SSL_CTX * generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port); /** \ingroup ServerProtocolSSLAPI @@ -155,7 +190,7 @@ * Read private key and certificate from memory and generate SSL context * using their. */ -SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data); +SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port); /** \ingroup ServerProtocolSSLAPI === modified file 'src/tests/stub_libsslsquid.cc' --- src/tests/stub_libsslsquid.cc 2012-08-28 13:00:30 +0000 +++ src/tests/stub_libsslsquid.cc 2012-09-06 13:12:26 +0000 @@ -42,7 +42,7 @@ const String & Ssl::ErrorDetail::toString() const STUB_RETSTATREF(String) #include "ssl/support.h" -SSL_CTX *sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath, const char *CRLfile, const char *dhpath, const char *context) STUB_RETVAL(NULL) +SSL_CTX *sslCreateServerContext(AnyP::PortCfg &) STUB_RETVAL(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) STUB_RETVAL(NULL) int ssl_read_method(int, char *, int) STUB_RETVAL(0) int ssl_write_method(int, const char *, int) STUB_RETVAL(0) @@ -53,8 +53,8 @@ // SSLGETATTRIBUTE sslGetCAAttribute; const char *sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(NULL) const char *sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(NULL) -SSL_CTX * Ssl::generateSslContext(CertificateProperties const &properties) STUB_RETVAL(NULL) -SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data) STUB_RETVAL(NULL) +SSL_CTX * Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &) STUB_RETVAL(NULL) +SSL_CTX * Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &) STUB_RETVAL(NULL) int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data)) STUB_RETVAL(0) int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len) STUB_RETVAL(0)