]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Move tls-options= parser into Security::PeerOptions
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 30 Jun 2015 10:39:39 +0000 (03:39 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 30 Jun 2015 10:39:39 +0000 (03:39 -0700)
It no longer needs to be called by the SSL code, so can be a private
member without OpenSSL library dependency.

Also, remove c_str() performance regression by upgrading to use
::Parser::Tokenizer.

src/security/PeerOptions.cc
src/security/PeerOptions.h
src/tests/stub_libsecurity.cc

index 27595c929d5f15f2da7f456d244c256c4202625d..0903979f12bb812ab9bdffeccd6a485f36ac0998 100644 (file)
@@ -61,12 +61,7 @@ Security::PeerOptions::parse(const char *token)
         tlsMinVersion = SBuf(token + 12);
     } else if (strncmp(token, "options=", 8) == 0) {
         sslOptions = SBuf(token + 8);
-#if USE_OPENSSL
-        // 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 = Security::ParseOptions(sslOptions.c_str());
-#endif
+        parsedOptions = parseOptions();
     } else if (strncmp(token, "cipher=", 7) == 0) {
         sslCipher = SBuf(token + 7);
     } else if (strncmp(token, "cafile=", 7) == 0) {
@@ -325,60 +320,50 @@ static struct ssl_option {
     }
 };
 
+/**
+ * Pre-parse TLS options= parameter to be applied when the TLS objects created.
+ * Options must not used in the case of peek or stare bump mode.
+ */
 long
-Security::ParseOptions(const char *options)
+Security::PeerOptions::parseOptions()
 {
     long op = 0;
-    char *tmp;
-    char *option;
-
-    if (options) {
-
-    tmp = xstrdup(options);
-    option = strtok(tmp, ":,");
-
-    while (option) {
+    ::Parser::Tokenizer tok(sslOptions);
 
+    do {
         enum {
             MODE_ADD, MODE_REMOVE
         } mode;
 
-        switch (*option) {
-
-        case '!':
-
-        case '-':
+        if (tok.skip('-') || tok.skip('!'))
             mode = MODE_REMOVE;
-            ++option;
-            break;
-
-        case '+':
+        else {
+            (void)tok.skip('+'); // default action is add. ignore if missing operator
             mode = MODE_ADD;
-            ++option;
-            break;
+        }
 
-        default:
-            mode = MODE_ADD;
-            break;
+        static const CharacterSet optChars = CharacterSet("TLS-option", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
+        int64_t hex = 0;
+        SBuf option;
+        long value = 0;
+
+        if (tok.int64(hex, 16, false)) {
+            /* Special case.. hex specification */
+            value = hex;
         }
 
-        struct ssl_option *opt = NULL;
-        for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) {
-            if (strcmp(opttmp->name, option) == 0) {
-                opt = opttmp;
-                break;
+        else if (tok.prefix(option, optChars)) {
+            // find the named option in our supported set
+            for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) {
+                if (option.cmp(opttmp->name) == 0) {
+                    value = opttmp->value;
+                    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 TLS option '%s'", option);
-            value = 0;      /* Keep GCC happy */
+        if (!value) {
+            fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(option));
         }
 
         switch (mode) {
@@ -392,11 +377,12 @@ Security::ParseOptions(const char *options)
             break;
         }
 
-        option = strtok(NULL, ":,");
-    }
+        static const CharacterSet delims("TLS-option-delim",":,");
+        if (!tok.skipAll(delims) && !tok.atEnd()) {
+            fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
+        }
 
-    safe_free(tmp);
-    }
+    } while (!tok.atEnd());
 
 #if SSL_OP_NO_SSLv2
     // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
index cf5aefec37c8077d89de27f8e289cc050455e564..13e5fa8db6766f69e0ebda7b0f122163702993ec 100644 (file)
@@ -40,6 +40,10 @@ public:
     /// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
     void dumpCfg(Packable *, const char *pfx) const;
 
+private:
+    long parseOptions();
+
+public:
     SBuf certFile;       ///< path of file containing PEM format X509 certificate
     SBuf privateKeyFile; ///< path of file containing private key in PEM format
     SBuf sslOptions;     ///< library-specific options string
@@ -67,11 +71,6 @@ public:
 /// configuration options for DIRECT server access
 extern PeerOptions ProxyOutgoingConfig;
 
-/**
- * Parses the TLS options squid.conf parameter
- */
-long ParseOptions(const char *options);
-
 /**
  * Parses the TLS flags squid.conf parameter
  */
index 6d2396664c1a6a7cf80b90e26f4f6acafd713cc6..e1e80cbd901902a94f8e6a7662cb2ca1a138c86b 100644 (file)
@@ -22,7 +22,7 @@ void Security::PeerOptions::parse(char const*) STUB
 Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
 void Security::PeerOptions::updateTlsVersionLimits() STUB
 void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
+long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
 void parse_securePeerOptions(Security::PeerOptions *) STUB
-long Security::ParseOptions(const char *) STUB_RETVAL(0)
 long Security::ParseFlags(const SBuf &) STUB_RETVAL(0)