3434SSLStatsBlock ssl_rsb;
3535std::unordered_map<std::string, Metrics::Counter::AtomicType *> cipher_map;
3636
37- #ifdef OPENSSL_IS_BORINGSSL
37+ #if defined( OPENSSL_IS_BORINGSSL) || HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS
3838std::unordered_map<std::string, Metrics::Counter::AtomicType *> tls_group_map;
3939std::unordered_map<std::string, Metrics::Counter::AtomicType *> tls_group_handshake_time_map;
40- #elif defined(SSL_get_negotiated_group)
40+ #elif HAVE_SSL_GET_NEGOTIATED_GROUP
4141std::unordered_map<int , Metrics::Counter::AtomicType *> tls_group_map;
4242std::unordered_map<int , Metrics::Counter::AtomicType *> tls_group_handshake_time_map;
4343#endif
@@ -50,7 +50,7 @@ DbgCtl dbg_ctl_ssl{"ssl"};
5050constexpr std::string_view UNKNOWN_CIPHER{" (NONE)" };
5151#endif
5252
53- #if defined(OPENSSL_IS_BORINGSSL) || defined(SSL_get_negotiated_group)
53+ #if defined(OPENSSL_IS_BORINGSSL) || HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS || HAVE_SSL_GET_NEGOTIATED_GROUP
5454
5555template <typename T>
5656void
@@ -73,9 +73,10 @@ add_group_stat(T key, const std::string &name)
7373 Dbg (dbg_ctl_ssl, " registering SSL group handshake time metric '%s.handshake_time'" , name.c_str ());
7474 }
7575}
76- #endif // OPENSSL_IS_BORINGSSL or SSL_get_negotiated_group
76+ #endif // OPENSSL_IS_BORINGSSL or HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS or HAVE_SSL_GET_NEGOTIATED_GROUP
7777
78- #if not defined(OPENSSL_IS_BORINGSSL) and defined(SSL_get_negotiated_group) // OPENSSL 3.x
78+ #if not defined(OPENSSL_IS_BORINGSSL) and not HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS and \
79+ HAVE_SSL_GET_NEGOTIATED_GROUP // OPENSSL 3.x without SSL_CTX_get0_implemented_groups
7980
8081struct TLSGroup {
8182 int nid;
@@ -115,7 +116,7 @@ const TLSGroup TLS_GROUPS[] = {
115116#endif
116117};
117118
118- #endif // OPENSSL 3.x
119+ #endif // OPENSSL 3.x without SSL_CTX_get0_implemented_groups
119120
120121} // end anonymous namespace
121122
@@ -294,16 +295,18 @@ SSLInitializeStatistics()
294295 add_cipher_stat (cipher_name, stat_name);
295296 }
296297#else
297- // Get and register the SSL cipher stats. Note that we are using the default SSL context to obtain
298- // the cipher list. This means that the set of ciphers is fixed by the build configuration and not
299- // filtered by proxy.config.ssl.server.cipher_suite. This keeps the set of cipher suites stable across
300- // configuration reloads and works for the case where we honor the client cipher preference.
301- SSLMultiCertConfigLoader loader (nullptr );
302- SSL_CTX *ctx = loader.default_server_ssl_ctx ();
303- SSL *ssl = SSL_new (ctx);
298+ // Acquire the loaded SSL certificate configuration to enumerate ciphers and groups.
299+ // This must be called AFTER SSLCertificateConfig::startup().
300+ SSLCertificateConfig::scoped_config lookup;
301+ if (!lookup || !lookup->ssl_default ) {
302+ Dbg (dbg_ctl_ssl, " No SSL configuration, skipping cipher/group statistics initialization" );
303+ return ;
304+ }
305+
306+ SSL_CTX *ctx = lookup->ssl_default .get ();
307+ SSL *ssl = SSL_new (ctx);
304308 STACK_OF (SSL_CIPHER) *ciphers = SSL_get_ciphers (ssl);
305309
306- // BoringSSL has sk_SSL_CIPHER_num() return a size_t (well, sk_num() is)
307310 for (int index = 0 ; index < static_cast <int >(sk_SSL_CIPHER_num (ciphers)); index++) {
308311 SSL_CIPHER *cipher = const_cast <SSL_CIPHER *>(sk_SSL_CIPHER_value (ciphers, index));
309312 const char *cipherName = SSL_CIPHER_get_name (cipher);
@@ -312,14 +315,48 @@ SSLInitializeStatistics()
312315 add_cipher_stat (cipherName, statName);
313316 }
314317
318+ // TLS Group
319+ #if HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS
320+ STACK_OF (OPENSSL_CSTRING) *group_names = sk_OPENSSL_CSTRING_new_null ();
321+ if (group_names == nullptr ) {
322+ Error (" Failed to allocate stack for TLS group names" );
323+ } else {
324+ constexpr int ALL_GROUPS = 1 ;
325+ DbgPrint (dbg_ctl_ssl, " Calling SSL_CTX_get0_implemented_groups on loaded SSL context" );
326+ if (SSL_CTX_get0_implemented_groups (ctx, ALL_GROUPS, group_names) != 1 ) {
327+ Error (" Failed to get implemented groups via SSL_CTX_get0_implemented_groups" );
328+ }
329+ int const num_groups = sk_OPENSSL_CSTRING_num (group_names);
330+ DbgPrint (dbg_ctl_ssl, " SSL_CTX_get0_implemented_groups returned %d groups" , num_groups);
331+
332+ for (int index = 0 ; index < num_groups; index++) {
333+ const char *name = sk_OPENSSL_CSTRING_value (group_names, index);
334+ if (name == nullptr ) {
335+ Error (" NULL group name returned for index %d in SSL_CTX_get0_implemented_groups" , index);
336+ continue ;
337+ }
338+ add_group_stat<std::string>(name, name);
339+ }
340+
341+ // Note: We don't free group_names as the strings are owned by OpenSSL's internal structures.
342+ sk_OPENSSL_CSTRING_free (group_names);
343+ }
344+
345+ // Add "OTHER" for groups not discovered.
346+ add_group_stat<std::string>(" OTHER" , " OTHER" );
347+ #elif HAVE_SSL_GET_NEGOTIATED_GROUP
348+ // Use static NID table for group registration.
349+ for (auto group : TLS_GROUPS) {
350+ add_group_stat<int >(group.nid , group.name );
351+ }
352+ #endif // HAVE_SSL_CTX_GET0_IMPLEMENTED_GROUPS or HAVE_SSL_GET_NEGOTIATED_GROUP
353+
315354 SSL_free (ssl);
316- SSLReleaseContext (ctx);
317355#endif
318356
319357 // Add "OTHER" for ciphers not on the map
320358 add_cipher_stat (SSL_CIPHER_STAT_OTHER.c_str (), " proxy.process.ssl.cipher.user_agent." + SSL_CIPHER_STAT_OTHER);
321359
322- // TLS Group
323360#if defined(OPENSSL_IS_BORINGSSL)
324361 size_t list_size = SSL_get_all_group_names (nullptr , 0 );
325362 std::vector<const char *> group_list (list_size);
@@ -328,9 +365,5 @@ SSLInitializeStatistics()
328365 for (const char *name : group_list) {
329366 add_group_stat<std::string>(name, name);
330367 }
331- #elif defined(SSL_get_negotiated_group)
332- for (auto group : TLS_GROUPS) {
333- add_group_stat<int >(group.nid , group.name );
334- }
335- #endif // OPENSSL_IS_BORINGSSL or SSL_get_negotiated_group
368+ #endif // OPENSSL_IS_BORINGSSL
336369}
0 commit comments