]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Separate tls-min-version= config from options= config
authorAmos Jeffries <amosjeffries@squid-cache.org>
Sat, 29 Dec 2018 22:56:07 +0000 (11:56 +1300)
committerAmos Jeffries <yadij@users.noreply.github.com>
Fri, 24 May 2019 11:27:14 +0000 (23:27 +1200)
.. until later when parsing the library-specific strings
into their parsedOptions binary form.

This allows multiple options= and tls-min-version= settings
with only the latest of each being used independent of what
is going on with the other config settings.

Also, add nil definitions for the NO_TLSv* OpenSSL options
to make the tls-min-version= not result in fatal errors when
using minimalized OpenSSL library builds.

src/security/PeerOptions.cc
src/security/PeerOptions.h

index 0ee2c17e6e4ea9143a12ace6adf8cee95ad31f7a..fd9e5968b80a3de6b5521753734051302ea7ea8f 100644 (file)
@@ -55,9 +55,9 @@ Security::PeerOptions::parse(const char *token)
     } else if (strncmp(token, "version=", 8) == 0) {
         debugs(0, DBG_PARSE_NOTE(1), "UPGRADE WARNING: SSL version= is deprecated. Use options= and tls-min-version= to limit protocols instead.");
         sslVersion = xatoi(token + 8);
-        optsReparse = true;
     } else if (strncmp(token, "min-version=", 12) == 0) {
         tlsMinVersion = SBuf(token + 12);
+        optsReparse = true;
     } else if (strncmp(token, "options=", 8) == 0) {
         sslOptions = SBuf(token + 8);
         optsReparse = true;
@@ -153,38 +153,31 @@ Security::PeerOptions::updateTlsVersionLimits()
     if (!tlsMinVersion.isEmpty()) {
         ::Parser::Tokenizer tok(tlsMinVersion);
         int64_t v = 0;
+        tlsMinOptions.clear();
         if (tok.skip('1') && tok.skip('.') && tok.int64(v, 10, false, 1) && v <= 3) {
             // only account for TLS here - SSL versions are handled by options= parameter
             // avoid affecting options= parameter in cachemgr config report
+            SBuf add;
 #if USE_OPENSSL
-#if SSL_OP_NO_TLSv1
             if (v > 0)
-                parsedOptions |= SSL_OP_NO_TLSv1;
-#endif
-#if SSL_OP_NO_TLSv1_1
+                add.append(":NO_TLSv1");
             if (v > 1)
-                parsedOptions |= SSL_OP_NO_TLSv1_1;
-#endif
-#if SSL_OP_NO_TLSv1_2
+                add.append(":NO_TLSv1_1");
             if (v > 2)
-                parsedOptions |= SSL_OP_NO_TLSv1_2;
-#endif
-
+                add.append(":NO_TLSv1_2");
 #elif USE_GNUTLS
-            // XXX: update parsedOptions directly to avoid polluting 'options=' dumps
-            SBuf add;
             if (v > 0)
                 add.append(":-VERS-TLS1.0");
             if (v > 1)
                 add.append(":-VERS-TLS1.1");
             if (v > 2)
                 add.append(":-VERS-TLS1.2");
+#endif
 
-            if (sslOptions.isEmpty())
+            if (!tlsMinOptions.isEmpty())
                 add.chop(1); // remove the initial ':'
-            sslOptions.append(add);
+            tlsMinOptions.append(add);
             optsReparse = true;
-#endif
 
         } else {
             debugs(0, DBG_PARSE_NOTE(1), "WARNING: Unknown TLS minimum version: " << tlsMinVersion);
@@ -202,28 +195,28 @@ Security::PeerOptions::updateTlsVersionLimits()
         switch (sslVersion) {
         case 3:
 #if USE_OPENSSL
-            parsedOptions |= (SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
+            add = ":NO_TLSv1:NO_TLSv1_1:NO_TLSv1_2";
 #elif USE_GNUTLS
             add = ":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2";
 #endif
             break;
         case 4:
 #if USE_OPENSSL
-            parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
+            add = ":NO_SSLv3:NO_TLSv1_1:NO_TLSv1_2";
 #elif USE_GNUTLS
             add = ":+VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2";
 #endif
             break;
         case 5:
 #if USE_OPENSSL
-            parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_2);
+            add = ":NO_SSLv3:NO_TLSv1:NO_TLSv1_2";
 #elif USE_GNUTLS
             add = ":-VERS-TLS1.0:+VERS-TLS1.1:-VERS-TLS1.2";
 #endif
             break;
         case 6:
 #if USE_OPENSSL
-            parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1);
+            add = ":NO_SSLv3:NO_TLSv1:NO_TLSv1_1";
 #elif USE_GNUTLS
             add = ":-VERS-TLS1.0:-VERS-TLS1.1";
 #endif
@@ -232,13 +225,11 @@ Security::PeerOptions::updateTlsVersionLimits()
             break;
         }
         if (add) {
-#if USE_GNUTLS // do not bother otherwise
             if (sslOptions.isEmpty())
                 sslOptions.append(add+1, strlen(add+1));
             else
                 sslOptions.append(add, strlen(add));
             optsReparse = true;
-#endif
         }
         sslVersion = 0; // prevent sslOptions being repeatedly appended
     }
@@ -393,16 +384,22 @@ static struct ssl_option {
     {
         "NO_TLSv1", SSL_OP_NO_TLSv1
     },
+#else
+    { "NO_TLSv1", 0 },
 #endif
 #if SSL_OP_NO_TLSv1_1
     {
         "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
     },
+#else
+    { "NO_TLSv1_1", 0 },
 #endif
 #if SSL_OP_NO_TLSv1_2
     {
         "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
     },
+#else
+    { "NO_TLSv1_2", 0 },
 #endif
 #if SSL_OP_NO_COMPRESSION
     {
@@ -441,8 +438,14 @@ Security::PeerOptions::parseOptions()
         return;
     optsReparse = false;
 
+    // combination of settings we have to set via parsedOptions.
+    // options= with override by tls-min-version=
+    SBuf str;
+    str.append(sslOptions);
+    str.append(tlsMinOptions);
+
 #if USE_OPENSSL
-    ::Parser::Tokenizer tok(sslOptions);
+    ::Parser::Tokenizer tok(str);
     long op = 0;
 
     while (!tok.atEnd()) {
@@ -507,13 +510,13 @@ Security::PeerOptions::parseOptions()
     parsedOptions = op;
 
 #elif USE_GNUTLS
-    if (sslOptions.isEmpty()) {
+    if (str.isEmpty()) {
         parsedOptions.reset();
         return;
     }
 
     const char *err = nullptr;
-    const char *priorities = sslOptions.c_str();
+    const char *priorities = str.c_str();
     gnutls_priority_t op;
     if (gnutls_priority_init(&op, priorities, &err) != GNUTLS_E_SUCCESS) {
         fatalf("Unknown TLS option '%s'", err);
@@ -753,7 +756,7 @@ Security::PeerOptions::updateSessionOptions(Security::SessionPointer &s)
     }
 
     if (x != GNUTLS_E_SUCCESS) {
-        debugs(83, DBG_IMPORTANT, "ERROR: Failed to set TLS options (" << errMsg << "). error: " << Security::ErrorString(x));
+        debugs(83, DBG_IMPORTANT, "ERROR: Failed to set TLS options (" << errMsg << ":" << tlsMinVersion << "). error: " << Security::ErrorString(x));
     }
 #endif
 }
index 844ac3e9eb39c255e7ad00496f3bed9eac4b37ee..da7721b91ddc94c45aac8995d022851a2a920a2e 100644 (file)
@@ -83,7 +83,12 @@ public:
     SBuf tlsMinVersion;  ///< version label for minimum TLS version to permit
 
 private:
-    /// parsed value of sslOptions
+    /// Library-specific options string generated from tlsMinVersion.
+    /// Call updateTlsVersionLimits() to regenerate this string.
+    SBuf tlsMinOptions;
+
+    /// Parsed value of sslOptions + tlsMinOptions settings.
+    /// Set optsReparse=true to have this re-parsed before next use.
     Security::ParsedOptions parsedOptions;
 
     /// whether parsedOptions content needs to be regenerated