From: Amos Jeffries Date: Sat, 21 Mar 2015 13:35:24 +0000 (-0700) Subject: Shuffle Ssl::parse_options to Security::ParseOptions X-Git-Tag: merge-candidate-3-v1~38^2~21^2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6bd62757606d944e54904bfc8555fcbece9958a6;p=thirdparty%2Fsquid.git Shuffle Ssl::parse_options to Security::ParseOptions The function itself is generic, the options array entries are all conditional so library agnostic. Adjust the context creation functions to receive pre-parsed options instead of the string to avoid circular dependency between libsquidssl and libsecurity. --- diff --git a/src/anyp/PortCfg.cc b/src/anyp/PortCfg.cc index d2299244ac..e76d50b639 100644 --- a/src/anyp/PortCfg.cc +++ b/src/anyp/PortCfg.cc @@ -10,6 +10,7 @@ #include "anyp/PortCfg.h" #include "comm.h" #include "fatal.h" +#include "security/PeerOptions.h" #if USE_OPENSSL #include "ssl/support.h" #endif @@ -198,7 +199,7 @@ AnyP::PortCfg::configureSslServerContext() if (sslflags) sslContextFlags = Ssl::parse_flags(sslflags); - sslOptions = Ssl::parse_options(options); + sslOptions = Security::ParseOptions(options); staticSslContext.reset(sslCreateServerContext(*this)); diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc index bc60a20138..6f276713fd 100644 --- a/src/security/PeerOptions.cc +++ b/src/security/PeerOptions.cc @@ -8,6 +8,7 @@ #include "squid.h" #include "Debug.h" +#include "fatal.h" #include "globals.h" #include "Parsing.h" #include "security/PeerOptions.h" @@ -39,7 +40,7 @@ Security::PeerOptions::parse(const char *token) // Pre-parse SSL client options to be applied when the client SSL objects created. // Options must not used in the case of peek or stare bump mode. // XXX: performance regression. c_str() can reallocate - parsedOptions = Ssl::parse_options(sslOptions.c_str()); + parsedOptions = Security::ParseOptions(sslOptions.c_str()); #endif } else if (strncmp(token, "cipher=", 7) == 0) { sslCipher = SBuf(token + 7); @@ -65,12 +66,218 @@ Security::PeerOptions::createContext(bool setOptions) #if USE_OPENSSL // XXX: temporary performance regression. c_str() data copies and prevents this being a const method t = sslCreateClientContext(certFile.c_str(), privateKeyFile.c_str(), sslVersion, sslCipher.c_str(), - (setOptions ? sslOptions.c_str() : NULL), sslFlags.c_str(), caFile.c_str(), caDir.c_str(), crlFile.c_str()); + (setOptions ? parsedOptions : 0), sslFlags.c_str(), caFile.c_str(), caDir.c_str(), crlFile.c_str()); + #endif return t; } +/// set of options we can parse and what they map to +static struct ssl_option { + const char *name; + long value; + +} ssl_options[] = { + +#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + { + "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + }, +#endif +#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + { + "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + }, +#endif +#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + { + "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + }, +#endif +#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG + { + "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG + }, +#endif +#if SSL_OP_TLS_D5_BUG + { + "TLS_D5_BUG", SSL_OP_TLS_D5_BUG + }, +#endif +#if SSL_OP_TLS_BLOCK_PADDING_BUG + { + "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG + }, +#endif +#if SSL_OP_TLS_ROLLBACK_BUG + { + "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG + }, +#endif +#if SSL_OP_ALL + { + "ALL", (long)SSL_OP_ALL + }, +#endif +#if SSL_OP_SINGLE_DH_USE + { + "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE + }, +#endif +#if SSL_OP_EPHEMERAL_RSA + { + "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA + }, +#endif +#if SSL_OP_PKCS1_CHECK_1 + { + "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 + }, +#endif +#if SSL_OP_PKCS1_CHECK_2 + { + "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 + }, +#endif +#if SSL_OP_NETSCAPE_CA_DN_BUG + { + "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG + }, +#endif +#if SSL_OP_NON_EXPORT_FIRST + { + "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST + }, +#endif +#if SSL_OP_CIPHER_SERVER_PREFERENCE + { + "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE + }, +#endif +#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + { + "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + }, +#endif +#if SSL_OP_NO_SSLv3 + { + "NO_SSLv3", SSL_OP_NO_SSLv3 + }, +#endif +#if SSL_OP_NO_TLSv1 + { + "NO_TLSv1", SSL_OP_NO_TLSv1 + }, +#endif +#if SSL_OP_NO_TLSv1_1 + { + "NO_TLSv1_1", SSL_OP_NO_TLSv1_1 + }, +#endif +#if SSL_OP_NO_TLSv1_2 + { + "NO_TLSv1_2", SSL_OP_NO_TLSv1_2 + }, +#endif +#if SSL_OP_NO_COMPRESSION + { + "No_Compression", SSL_OP_NO_COMPRESSION + }, +#endif +#if SSL_OP_NO_TICKET + { + "NO_TICKET", SSL_OP_NO_TICKET + }, +#endif + { + "", 0 + }, + { + NULL, 0 + } +}; + +long +Security::ParseOptions(const char *options) +{ + long op = 0; + char *tmp; + char *option; + + if (options) { + + tmp = xstrdup(options); + option = strtok(tmp, ":,"); + + while (option) { + + enum { + MODE_ADD, MODE_REMOVE + } mode; + + switch (*option) { + + case '!': + + case '-': + mode = MODE_REMOVE; + ++option; + break; + + case '+': + mode = MODE_ADD; + ++option; + break; + + default: + mode = MODE_ADD; + break; + } + + struct ssl_option *opt = NULL; + for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) { + if (strcmp(opttmp->name, option) == 0) { + opt = opttmp; + break; + } + } + + long value = 0; + if (opt) + value = opt->value; + else if (strncmp(option, "0x", 2) == 0) { + /* Special case.. hex specification */ + value = strtol(option + 2, NULL, 16); + } else { + fatalf("Unknown SSL option '%s'", option); + value = 0; /* Keep GCC happy */ + } + + switch (mode) { + + case MODE_ADD: + op |= value; + break; + + case MODE_REMOVE: + op &= ~value; + break; + } + + option = strtok(NULL, ":,"); + } + + safe_free(tmp); + } + +#if SSL_OP_NO_SSLv2 + // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0 + op = op | SSL_OP_NO_SSLv2; +#endif + return op; +} + void parse_securePeerOptions(Security::PeerOptions *opt) { diff --git a/src/security/PeerOptions.h b/src/security/PeerOptions.h index c88732f512..08ac9b706d 100644 --- a/src/security/PeerOptions.h +++ b/src/security/PeerOptions.h @@ -53,6 +53,11 @@ public: /// configuration options for DIRECT server access extern PeerOptions ProxyOutgoingConfig; +/** + * Parses the TLS options squid.conf parameter + */ +long ParseOptions(const char *options); + } // namespace Security // parse the tls_outgoing_options directive diff --git a/src/ssl/support.cc b/src/ssl/support.cc index f6c744f915..b1d5068c40 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -348,215 +348,6 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx) return ok; } -/// \ingroup ServerProtocolSSLInternal -static struct ssl_option { - const char *name; - long value; -} - -ssl_options[] = { - -#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG - { - "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG - }, -#endif -#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG - { - "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG - }, -#endif -#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER - { - "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER - }, -#endif -#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG - { - "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG - }, -#endif -#if SSL_OP_TLS_D5_BUG - { - "TLS_D5_BUG", SSL_OP_TLS_D5_BUG - }, -#endif -#if SSL_OP_TLS_BLOCK_PADDING_BUG - { - "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG - }, -#endif -#if SSL_OP_TLS_ROLLBACK_BUG - { - "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG - }, -#endif -#if SSL_OP_ALL - { - "ALL", (long)SSL_OP_ALL - }, -#endif -#if SSL_OP_SINGLE_DH_USE - { - "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE - }, -#endif -#if SSL_OP_EPHEMERAL_RSA - { - "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA - }, -#endif -#if SSL_OP_PKCS1_CHECK_1 - { - "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 - }, -#endif -#if SSL_OP_PKCS1_CHECK_2 - { - "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 - }, -#endif -#if SSL_OP_NETSCAPE_CA_DN_BUG - { - "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG - }, -#endif -#if SSL_OP_NON_EXPORT_FIRST - { - "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST - }, -#endif -#if SSL_OP_CIPHER_SERVER_PREFERENCE - { - "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE - }, -#endif -#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG - { - "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG - }, -#endif -#if SSL_OP_NO_SSLv3 - { - "NO_SSLv3", SSL_OP_NO_SSLv3 - }, -#endif -#if SSL_OP_NO_TLSv1 - { - "NO_TLSv1", SSL_OP_NO_TLSv1 - }, -#endif -#if SSL_OP_NO_TLSv1_1 - { - "NO_TLSv1_1", SSL_OP_NO_TLSv1_1 - }, -#endif -#if SSL_OP_NO_TLSv1_2 - { - "NO_TLSv1_2", SSL_OP_NO_TLSv1_2 - }, -#endif -#if SSL_OP_NO_COMPRESSION - { - "No_Compression", SSL_OP_NO_COMPRESSION - }, -#endif -#if SSL_OP_NO_TICKET - { - "NO_TICKET", SSL_OP_NO_TICKET - }, -#endif - { - "", 0 - }, - { - NULL, 0 - } -}; - -/// \ingroup ServerProtocolSSLInternal -long -Ssl::parse_options(const char *options) -{ - long op = 0; - char *tmp; - char *option; - - if (!options) - goto no_options; - - tmp = xstrdup(options); - - option = strtok(tmp, ":,"); - - while (option) { - - struct ssl_option *opt = NULL, *opttmp; - long value = 0; - enum { - MODE_ADD, MODE_REMOVE - } mode; - - switch (*option) { - - case '!': - - case '-': - mode = MODE_REMOVE; - ++option; - break; - - case '+': - mode = MODE_ADD; - ++option; - break; - - default: - mode = MODE_ADD; - break; - } - - for (opttmp = ssl_options; opttmp->name; ++opttmp) { - if (strcmp(opttmp->name, option) == 0) { - opt = opttmp; - break; - } - } - - if (opt) - value = opt->value; - else if (strncmp(option, "0x", 2) == 0) { - /* Special case.. hex specification */ - value = strtol(option + 2, NULL, 16); - } else { - fatalf("Unknown SSL option '%s'", option); - value = 0; /* Keep GCC happy */ - } - - switch (mode) { - - case MODE_ADD: - op |= value; - break; - - case MODE_REMOVE: - op &= ~value; - break; - } - - option = strtok(NULL, ":,"); - } - - safe_free(tmp); - -no_options: -#if SSL_OP_NO_SSLv2 - // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0 - op = op | SSL_OP_NO_SSLv2; -#endif - return op; -} - /// \ingroup ServerProtocolSSLInternal #define SSL_FLAG_NO_DEFAULT_CA (1<<0) /// \ingroup ServerProtocolSSLInternal @@ -1107,7 +898,7 @@ Ssl::serverMethod(int version) } 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) +sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, long options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile) { int ssl_error; Ssl::ContextMethod method; @@ -1127,7 +918,7 @@ sslCreateClientContext(const char *certfile, const char *keyfile, int version, c ERR_error_string(ssl_error, NULL)); } - SSL_CTX_set_options(sslContext, Ssl::parse_options(options)); + SSL_CTX_set_options(sslContext, options); if (*cipher) { debugs(83, 5, "Using chiper suite " << cipher << "."); diff --git a/src/ssl/support.h b/src/ssl/support.h index fa52c9baca..2bde785c4e 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -92,7 +92,7 @@ typedef CbDataList CertErrors; 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); +SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, long options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile); /// \ingroup ServerProtocolSSLAPI int ssl_read_method(int, char *, int); @@ -163,12 +163,6 @@ inline const char *bumpMode(int bm) */ 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 diff --git a/src/tests/stub_libsecurity.cc b/src/tests/stub_libsecurity.cc index ec7903251e..041bfbabe8 100644 --- a/src/tests/stub_libsecurity.cc +++ b/src/tests/stub_libsecurity.cc @@ -21,4 +21,5 @@ Security::PeerOptions Security::ProxyOutgoingConfig; void Security::PeerOptions::parse(char const*) STUB Security::ContextPointer Security::PeerOptions::createContext(bool) STUB_RETVAL(NULL) void parse_securePeerOptions(Security::PeerOptions *) STUB +long Security::ParseOptions(const char *) STUB_RETVAL(0) diff --git a/src/tests/stub_libsslsquid.cc b/src/tests/stub_libsslsquid.cc index e52608b43a..2d131b772b 100644 --- a/src/tests/stub_libsslsquid.cc +++ b/src/tests/stub_libsslsquid.cc @@ -57,7 +57,7 @@ bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false) bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false) } // namespace Ssl SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port) 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) +SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, long 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) void ssl_shutdown_method(SSL *ssl) STUB @@ -73,7 +73,6 @@ namespace Ssl //GETX509ATTRIBUTE GetX509Fingerprint; const char *BumpModeStr[] = {""}; long parse_flags(const char *flags) STUB_RETVAL(0) -long parse_options(const char *options) STUB_RETVAL(0) STACK_OF(X509_CRL) *loadCrl(const char *CRLFile, long &flags) STUB_RETVAL(NULL) DH *readDHParams(const char *dhfile) STUB_RETVAL(NULL) ContextMethod contextMethod(int version) STUB_RETVAL(ContextMethod())