Copilot commented on code in PR #13088:
URL: https://github.com/apache/trafficserver/pull/13088#discussion_r3104295213


##########
src/iocore/net/SSLClientUtils.cc:
##########
@@ -247,6 +249,18 @@ SSLInitClientContext(const SSLConfigParams *params)
   }
 #endif
 
+  if (params->client_cert_compression_algorithms) {
+    std::vector<std::string> algs;
+    SimpleTokenizer          tok(params->client_cert_compression_algorithms, 
',');
+    for (const char *token = tok.getNext(); token; token = tok.getNext()) {
+      algs.emplace_back(token);

Review Comment:
   The client-side parsing of 
`proxy.config.ssl.client.cert_compression.algorithms` doesn’t trim whitespace 
around comma-separated tokens. This makes common configs like `zlib, brotli` 
fail validation even though they’re logically correct. Trim each token (and 
skip empty tokens) before passing the list to 
`register_certificate_compression_preference()`.
   ```suggestion
         std::string algorithm(token);
         auto const  begin = algorithm.find_first_not_of(" \t\r\n\f\v");
   
         if (begin == std::string::npos) {
           continue;
         }
   
         auto const end = algorithm.find_last_not_of(" \t\r\n\f\v");
         algorithm      = algorithm.substr(begin, end - begin + 1);
         algs.emplace_back(std::move(algorithm));
   ```



##########
src/iocore/net/TLSCertCompression.cc:
##########
@@ -0,0 +1,128 @@
+/** @file
+
+  Functions for Certificate Compression
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include <openssl/ssl.h>
+
+#include "tscore/Diags.h"
+#include "TLSCertCompression.h"
+
+namespace
+{
+DbgCtl dbg_ctl_ssl_cert_compress{"ssl_cert_compress"};
+}
+
+constexpr unsigned int N_ALGORITHMS = 3;
+
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+#include "TLSCertCompression_zlib.h"
+
+#if HAVE_BROTLI_ENCODE_H
+#include "TLSCertCompression_brotli.h"
+#endif
+
+#if HAVE_ZSTD_H
+#include "TLSCertCompression_zstd.h"
+#endif
+#endif
+
+struct alg_info {
+  const char *name;
+  int32_t     number;
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+  ssl_cert_compression_func_t   compress_func;
+  ssl_cert_decompression_func_t decompress_func;
+#endif
+} supported_algs[] = {
+  {"zlib",   1,
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+   compression_func_zlib,   decompression_func_zlib
+#endif
+  },
+#if HAVE_BROTLI_ENCODE_H
+  {"brotli", 2,
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+   compression_func_brotli, decompression_func_brotli
+#endif
+  },
+#endif
+#if HAVE_ZSTD_H
+  {"zstd",   3,
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+   compression_func_zstd,   decompression_func_zstd
+#endif
+  },
+#endif
+};
+
+int
+register_certificate_compression_preference(SSL_CTX *ctx, 
std::vector<std::string> specified_algs)
+{
+  ink_assert(ctx != nullptr);
+  if (specified_algs.size() > N_ALGORITHMS) {
+    return 0;
+  }
+
+  if (specified_algs.empty()) {
+    return 1;
+  }
+
+#if HAVE_SSL_CTX_ADD_CERT_COMPRESSION_ALG
+  for (auto &&alg : specified_algs) {
+    struct alg_info *info = nullptr;
+
+    for (unsigned int i = 0; i < countof(supported_algs); ++i) {
+      if (strcmp(alg.c_str(), supported_algs[i].name) == 0) {
+        info = &supported_algs[i];
+      }
+    }
+    if (info != nullptr) {
+      if (SSL_CTX_add_cert_compression_alg(ctx, info->number, 
info->compress_func, info->decompress_func) == 0) {
+        return 0;
+      }
+      Dbg(dbg_ctl_ssl_cert_compress, "Enabled %s", info->name);
+    } else {
+      Dbg(dbg_ctl_ssl_cert_compress, "Unrecognized algorithm: %s", 
alg.c_str());
+      return 0;
+    }
+  }
+  return 1;
+#elif HAVE_SSL_CTX_SET1_CERT_COMP_PREFERENCE
+  int algs[N_ALGORITHMS];
+  int n = 0;
+
+  for (unsigned int i = 0; i < specified_algs.size(); ++i) {
+    for (unsigned int j = 0; j < countof(supported_algs); ++j) {
+      if (strcmp(specified_algs[i].c_str(), supported_algs[j].name) == 0) {
+        algs[n++] = supported_algs[j].number;
+        Dbg(dbg_ctl_ssl_cert_compress, "Enabled %s", supported_algs[j].name);
+      }
+    }

Review Comment:
   In the `HAVE_SSL_CTX_SET1_CERT_COMP_PREFERENCE` branch, unrecognized 
algorithm names are silently ignored (the loop only appends matches). This 
means typos or unsupported algorithms may not be reported, and 
`SSL_CTX_set1_cert_comp_preference()` may be called with `n == 0` even though 
the config was non-empty. Track whether each specified algorithm matched; if 
any didn’t, log/debug and return failure to keep behavior consistent with the 
`SSL_CTX_add_cert_compression_alg` branch.
   ```suggestion
     for (unsigned int i = 0; i < specified_algs.size(); ++i) {
       bool matched = false;
   
       for (unsigned int j = 0; j < countof(supported_algs); ++j) {
         if (strcmp(specified_algs[i].c_str(), supported_algs[j].name) == 0) {
           algs[n++] = supported_algs[j].number;
           Dbg(dbg_ctl_ssl_cert_compress, "Enabled %s", supported_algs[j].name);
           matched = true;
           break;
         }
       }
       if (!matched) {
         Dbg(dbg_ctl_ssl_cert_compress, "Unrecognized algorithm: %s", 
specified_algs[i].c_str());
         return 0;
       }
   ```



##########
src/iocore/net/SSLUtils.cc:
##########
@@ -435,6 +436,26 @@ DH_get_2048_256()
 }
 #endif
 
+bool
+SSLMultiCertConfigLoader::_enable_cert_compression(SSL_CTX *ctx)
+{
+  std::vector<std::string> algs;
+
+  if (this->_params->server_cert_compression_algorithms) {
+    SimpleTokenizer tok(this->_params->server_cert_compression_algorithms, 
',');
+    for (const char *token = tok.getNext(); token; token = tok.getNext()) {
+      algs.emplace_back(token);

Review Comment:
   When parsing the comma-separated algorithm list, tokens aren’t trimmed. 
Config values like `zlib, brotli` will produce a token with a leading space and 
fail to match supported algorithms (resulting in unexpected startup failures). 
Trim surrounding whitespace on each token before adding it to `algs` (and 
consider skipping empty tokens).
   ```suggestion
         std::string algorithm(token);
         auto const begin = algorithm.find_first_not_of(" \t\n\r\f\v");
   
         if (begin == std::string::npos) {
           continue;
         }
   
         auto const end = algorithm.find_last_not_of(" \t\n\r\f\v");
         algs.emplace_back(algorithm.substr(begin, end - begin + 1));
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to