grpc 1.82.0 → 1.83.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/etc/roots.pem +10400 -3855
  4. data/include/grpc/grpc_audit_logging.h +2 -2
  5. data/include/grpc/grpc_security_constants.h +2 -0
  6. data/include/grpc/impl/channel_arg_names.h +23 -0
  7. data/src/core/call/call_filters.h +19 -3
  8. data/src/core/call/call_spine.h +4 -4
  9. data/src/core/call/client_call.cc +1 -1
  10. data/src/core/call/metadata.cc +7 -2
  11. data/src/core/call/server_call.cc +13 -3
  12. data/src/core/call/server_call.h +5 -3
  13. data/src/core/client_channel/backup_poller.cc +2 -17
  14. data/src/core/client_channel/client_channel.cc +17 -14
  15. data/src/core/client_channel/client_channel.h +3 -1
  16. data/src/core/client_channel/client_channel_filter.cc +11 -13
  17. data/src/core/client_channel/client_channel_service_config.cc +5 -13
  18. data/src/core/client_channel/direct_channel.cc +5 -1
  19. data/src/core/client_channel/direct_channel.h +3 -1
  20. data/src/core/config/experiment_env_var.cc +30 -0
  21. data/src/core/config/experiment_env_var.h +26 -0
  22. data/src/core/credentials/call/regional_access_boundary_fetcher.cc +6 -6
  23. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +14 -2
  24. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.cc +172 -0
  25. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.h +103 -0
  26. data/src/core/credentials/transport/tls/load_system_roots_fallback.cc +3 -2
  27. data/src/core/credentials/transport/tls/load_system_roots_supported.cc +10 -3
  28. data/src/core/credentials/transport/tls/tls_security_connector.cc +14 -2
  29. data/src/core/credentials/transport/xds/xds_credentials.cc +4 -12
  30. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +2 -1
  31. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +19 -13
  32. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +11 -9
  33. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  34. data/src/core/ext/transport/chttp2/transport/flow_control.h +3 -2
  35. data/src/core/ext/transport/chttp2/transport/frame.cc +58 -1
  36. data/src/core/ext/transport/chttp2/transport/frame.h +13 -1
  37. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -4
  38. data/src/core/ext/transport/chttp2/transport/frame_security.cc +10 -1
  39. data/src/core/ext/transport/chttp2/transport/frame_security.h +2 -1
  40. data/src/core/ext/transport/chttp2/transport/goaway.cc +11 -1
  41. data/src/core/ext/transport/chttp2/transport/goaway.h +17 -1
  42. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +9 -0
  43. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +117 -276
  44. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +44 -17
  45. data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +382 -496
  46. data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +75 -77
  47. data/src/core/ext/transport/chttp2/transport/http2_settings.cc +1 -1
  48. data/src/core/ext/transport/chttp2/transport/http2_settings.h +30 -11
  49. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +24 -9
  50. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +26 -0
  51. data/src/core/ext/transport/chttp2/transport/http2_transport.h +2 -0
  52. data/src/core/ext/transport/chttp2/transport/internal.h +4 -0
  53. data/src/core/ext/transport/chttp2/transport/parsing.cc +3 -2
  54. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +1 -1
  55. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +4 -10
  56. data/src/core/ext/transport/chttp2/transport/read_context.h +62 -20
  57. data/src/core/ext/transport/chttp2/transport/security_frame.h +1 -0
  58. data/src/core/ext/transport/chttp2/transport/stream.h +271 -120
  59. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +77 -61
  60. data/src/core/handshaker/security/secure_endpoint.cc +0 -13
  61. data/src/core/lib/channel/promise_based_filter.cc +77 -3
  62. data/src/core/lib/channel/promise_based_filter.h +238 -184
  63. data/src/core/lib/event_engine/extensions/receive_coalescing_extension.h +0 -4
  64. data/src/core/lib/event_engine/extensions/tcp_trace.h +1 -1
  65. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +2 -12
  66. data/src/core/lib/event_engine/shim.cc +2 -16
  67. data/src/core/lib/event_engine/shim.h +0 -4
  68. data/src/core/lib/experiments/experiments.cc +51 -102
  69. data/src/core/lib/experiments/experiments.h +37 -59
  70. data/src/core/lib/iomgr/error.cc +3 -73
  71. data/src/core/lib/iomgr/error.h +8 -6
  72. data/src/core/lib/iomgr/error_cfstream.cc +1 -2
  73. data/src/core/lib/iomgr/ev_epoll1_linux.cc +2 -6
  74. data/src/core/lib/iomgr/ev_poll_posix.cc +2 -6
  75. data/src/core/lib/iomgr/tcp_posix.cc +2 -6
  76. data/src/core/lib/security/authorization/audit_logging.cc +2 -2
  77. data/src/core/lib/security/authorization/audit_logging.h +3 -3
  78. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +11 -13
  79. data/src/core/lib/security/authorization/grpc_authorization_engine.h +1 -1
  80. data/src/core/lib/security/authorization/matchers.cc +20 -20
  81. data/src/core/lib/security/authorization/matchers.h +15 -16
  82. data/src/core/lib/security/authorization/rbac_policy.h +1 -1
  83. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  84. data/src/core/lib/security/authorization/stdout_logger.h +6 -5
  85. data/src/core/lib/surface/call.cc +0 -8
  86. data/src/core/lib/surface/call.h +2 -0
  87. data/src/core/lib/surface/channel.cc +21 -2
  88. data/src/core/lib/surface/channel.h +14 -6
  89. data/src/core/lib/surface/filter_stack_call.cc +10 -29
  90. data/src/core/lib/surface/legacy_channel.cc +7 -7
  91. data/src/core/lib/surface/legacy_channel.h +3 -1
  92. data/src/core/lib/surface/version.cc +2 -2
  93. data/src/core/lib/transport/bdp_estimator.cc +13 -13
  94. data/src/core/lib/transport/bdp_estimator.h +9 -5
  95. data/src/core/lib/transport/error_utils.cc +26 -138
  96. data/src/core/lib/transport/promise_endpoint.h +2 -4
  97. data/src/core/load_balancing/grpclb/grpclb.cc +2 -1
  98. data/src/core/load_balancing/pick_first/pick_first.cc +33 -2
  99. data/src/core/load_balancing/pick_first/pick_first.h +6 -0
  100. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -10
  101. data/src/core/load_balancing/rls/rls.cc +2 -1
  102. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +2 -7
  103. data/src/core/load_balancing/xds/cds.cc +80 -56
  104. data/src/core/load_balancing/xds/cds.h +21 -0
  105. data/src/core/mitigation_engine/mitigation.h +53 -0
  106. data/src/core/mitigation_engine/mitigation_provider.h +62 -0
  107. data/src/core/resolver/dns/dns_resolver_plugin.cc +1 -6
  108. data/src/core/resolver/xds/xds_resolver.cc +14 -11
  109. data/src/core/server/server.h +1 -4
  110. data/src/core/server/server_config_selector.h +5 -4
  111. data/src/core/server/server_config_selector_filter.cc +67 -80
  112. data/src/core/server/xds_server_config_fetcher.cc +681 -692
  113. data/src/core/server/xds_server_config_fetcher_legacy.cc +15 -12
  114. data/src/core/telemetry/call_tracer.cc +49 -2
  115. data/src/core/telemetry/call_tracer.h +1 -0
  116. data/src/core/telemetry/tcp_tracer.h +38 -0
  117. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  118. data/src/core/tsi/ssl_telemetry_utils.cc +343 -0
  119. data/src/core/tsi/ssl_telemetry_utils.h +74 -0
  120. data/src/core/tsi/ssl_transport_security.cc +577 -301
  121. data/src/core/tsi/ssl_transport_security.h +22 -6
  122. data/src/core/tsi/ssl_transport_security_utils.cc +2 -0
  123. data/src/core/tsi/transport_security.h +7 -0
  124. data/src/core/util/http_client/httpcli.cc +1 -4
  125. data/src/core/util/http_client/httpcli_security_connector.cc +2 -1
  126. data/src/core/util/status_helper.cc +71 -192
  127. data/src/core/util/status_helper.h +16 -21
  128. data/src/core/xds/grpc/file_watcher_certificate_provider_factory.cc +2 -11
  129. data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -7
  130. data/src/core/xds/grpc/xds_cluster_parser.cc +5 -16
  131. data/src/core/xds/grpc/xds_common_types.cc +94 -38
  132. data/src/core/xds/grpc/xds_common_types.h +33 -18
  133. data/src/core/xds/grpc/xds_common_types_parser.cc +168 -100
  134. data/src/core/xds/grpc/xds_common_types_parser.h +18 -1
  135. data/src/core/xds/grpc/xds_endpoint_parser.cc +6 -17
  136. data/src/core/xds/grpc/xds_http_filter_registry.cc +2 -10
  137. data/src/core/xds/grpc/xds_http_rbac_filter.cc +3 -12
  138. data/src/core/xds/grpc/xds_metadata_parser.cc +0 -2
  139. data/src/core/xds/grpc/xds_route_config_parser.cc +7 -11
  140. data/src/core/xds/grpc/xds_routing.cc +113 -82
  141. data/src/core/xds/grpc/xds_routing.h +70 -20
  142. data/src/core/xds/grpc/xds_server_grpc.cc +22 -13
  143. data/src/core/xds/grpc/xds_server_grpc.h +16 -2
  144. data/src/core/xds/grpc/xds_server_grpc_interface.h +10 -0
  145. data/src/core/xds/grpc/xds_transport_grpc.cc +123 -18
  146. data/src/core/xds/grpc/xds_transport_grpc.h +28 -4
  147. data/src/core/xds/xds_client/lrs_client.cc +3 -7
  148. data/src/core/xds/xds_client/xds_bootstrap.cc +4 -16
  149. data/src/core/xds/xds_client/xds_client.cc +2 -15
  150. data/src/core/xds/xds_client/xds_transport.h +3 -0
  151. data/src/ruby/lib/grpc/version.rb +1 -1
  152. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +1 -1
  153. metadata +9 -1
@@ -399,8 +399,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
399
399
  }
400
400
 
401
401
  absl::StatusOr<RefCountedPtr<ServerConfigSelector>> Watch(
402
- std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
403
- watcher) override {
402
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) override {
404
403
  GRPC_CHECK(watcher_ == nullptr);
405
404
  watcher_ = std::move(watcher);
406
405
  if (!static_resource_.ok()) {
@@ -412,7 +411,11 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
412
411
  static_resource_.value(), http_filters_);
413
412
  }
414
413
 
415
- void CancelWatch() override { watcher_.reset(); }
414
+ void CancelWatch(
415
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) override {
416
+ GRPC_CHECK(watcher == watcher_);
417
+ watcher_.reset();
418
+ }
416
419
 
417
420
  private:
418
421
  void Orphaned() override {}
@@ -425,7 +428,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
425
428
  // copying the HTTP filters here.
426
429
  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
427
430
  http_filters_;
428
- std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
431
+ std::shared_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
429
432
  watcher_;
430
433
  };
431
434
 
@@ -447,9 +450,9 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
447
450
  }
448
451
 
449
452
  absl::StatusOr<RefCountedPtr<ServerConfigSelector>> Watch(
450
- std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
451
- watcher) override;
452
- void CancelWatch() override;
453
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) override;
454
+ void CancelWatch(
455
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) override;
453
456
 
454
457
  private:
455
458
  class RouteConfigWatcher;
@@ -468,7 +471,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
468
471
  http_filters_;
469
472
  RouteConfigWatcher* route_config_watcher_ = nullptr;
470
473
  Mutex mu_;
471
- std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
474
+ std::shared_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
472
475
  watcher_ ABSL_GUARDED_BY(mu_);
473
476
  absl::StatusOr<std::shared_ptr<const XdsRouteConfigResource>> resource_
474
477
  ABSL_GUARDED_BY(mu_);
@@ -1238,9 +1241,7 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1238
1241
  absl::StatusOr<RefCountedPtr<ServerConfigSelector>>
1239
1242
  XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1240
1243
  DynamicXdsServerConfigSelectorProvider::Watch(
1241
- std::unique_ptr<
1242
- ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
1243
- watcher) {
1244
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) {
1244
1245
  absl::StatusOr<std::shared_ptr<const XdsRouteConfigResource>> resource;
1245
1246
  {
1246
1247
  MutexLock lock(&mu_);
@@ -1258,8 +1259,10 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1258
1259
  }
1259
1260
 
1260
1261
  void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1261
- DynamicXdsServerConfigSelectorProvider::CancelWatch() {
1262
+ DynamicXdsServerConfigSelectorProvider::CancelWatch(
1263
+ std::shared_ptr<ServerConfigSelectorWatcher> watcher) {
1262
1264
  MutexLock lock(&mu_);
1265
+ GRPC_CHECK(watcher == watcher_);
1263
1266
  watcher_.reset();
1264
1267
  }
1265
1268
 
@@ -18,6 +18,9 @@
18
18
 
19
19
  #include "src/core/telemetry/call_tracer.h"
20
20
 
21
+ #include <grpc/event_engine/internal/write_event.h>
22
+
23
+ #include <cstddef>
21
24
  #include <memory>
22
25
  #include <string>
23
26
  #include <utility>
@@ -37,6 +40,7 @@
37
40
  #include "absl/functional/function_ref.h"
38
41
  #include "absl/status/status.h"
39
42
  #include "absl/strings/string_view.h"
43
+ #include "absl/time/time.h"
40
44
  #include "absl/types/span.h"
41
45
 
42
46
  namespace grpc_core {
@@ -91,6 +95,31 @@ ServerCallTracerFactory* g_server_call_tracer_factory_ = nullptr;
91
95
  const char* kServerCallTracerFactoryChannelArgName =
92
96
  "grpc.experimental.server_call_tracer_factory";
93
97
 
98
+ class DelegatingTcpCallTracer final : public TcpCallTracer {
99
+ public:
100
+ explicit DelegatingTcpCallTracer(
101
+ std::vector<std::shared_ptr<TcpCallTracer>> tracers)
102
+ : tracers_(std::move(tracers)) {}
103
+
104
+ void RecordConnectionTuple(const IpAddress& local_addr,
105
+ const IpAddress& peer_addr) override {
106
+ for (const auto& tracer : tracers_) {
107
+ tracer->RecordConnectionTuple(local_addr, peer_addr);
108
+ }
109
+ }
110
+
111
+ void RecordEvent(grpc_event_engine::experimental::internal::WriteEvent event,
112
+ absl::Time time, size_t byte_offset,
113
+ const std::vector<TcpEventMetric>& metrics) override {
114
+ for (const auto& tracer : tracers_) {
115
+ tracer->RecordEvent(event, time, byte_offset, metrics);
116
+ }
117
+ }
118
+
119
+ private:
120
+ const std::vector<std::shared_ptr<TcpCallTracer>> tracers_;
121
+ };
122
+
94
123
  } // namespace
95
124
 
96
125
  ServerCallTracerFactory* ServerCallTracerFactory::Get(
@@ -223,7 +252,15 @@ class DelegatingClientCallTracer : public ClientCallTracerInterface {
223
252
  }
224
253
  }
225
254
  std::shared_ptr<TcpCallTracer> StartNewTcpTrace() override {
226
- return nullptr;
255
+ std::vector<std::shared_ptr<TcpCallTracer>> tcp_tracers;
256
+ for (auto* tracer : tracers_) {
257
+ if (auto tcp_tracer = tracer->StartNewTcpTrace()) {
258
+ tcp_tracers.push_back(std::move(tcp_tracer));
259
+ }
260
+ }
261
+ if (tcp_tracers.empty()) return nullptr;
262
+ if (tcp_tracers.size() == 1) return tcp_tracers[0];
263
+ return std::make_shared<DelegatingTcpCallTracer>(std::move(tcp_tracers));
227
264
  }
228
265
  void SetOptionalLabel(OptionalLabelKey key,
229
266
  RefCountedStringValue value) override {
@@ -386,7 +423,17 @@ class DelegatingServerCallTracer : public ServerCallTracerInterface {
386
423
  tracer->RecordAnnotation(annotation);
387
424
  }
388
425
  }
389
- std::shared_ptr<TcpCallTracer> StartNewTcpTrace() override { return nullptr; }
426
+ std::shared_ptr<TcpCallTracer> StartNewTcpTrace() override {
427
+ std::vector<std::shared_ptr<TcpCallTracer>> tcp_tracers;
428
+ for (auto* tracer : tracers_) {
429
+ if (auto tcp_tracer = tracer->StartNewTcpTrace()) {
430
+ tcp_tracers.push_back(std::move(tcp_tracer));
431
+ }
432
+ }
433
+ if (tcp_tracers.empty()) return nullptr;
434
+ if (tcp_tracers.size() == 1) return tcp_tracers[0];
435
+ return std::make_shared<DelegatingTcpCallTracer>(std::move(tcp_tracers));
436
+ }
390
437
  std::string TraceId() override { return tracers_[0]->TraceId(); }
391
438
  std::string SpanId() override { return tracers_[0]->SpanId(); }
392
439
  bool IsSampled() override { return tracers_[0]->IsSampled(); }
@@ -206,6 +206,7 @@ class ClientCallTracerInterface : public CallTracerAnnotationInterface {
206
206
  kXdsServiceNamespace, // not public
207
207
  kLocality,
208
208
  kBackendService,
209
+ kTelemetryLabel,
209
210
  kSize // should be last
210
211
  };
211
212
 
@@ -19,10 +19,12 @@
19
19
  #ifndef GRPC_SRC_CORE_TELEMETRY_TCP_TRACER_H
20
20
  #define GRPC_SRC_CORE_TELEMETRY_TCP_TRACER_H
21
21
 
22
+ #include <grpc/event_engine/event_engine.h>
22
23
  #include <grpc/event_engine/internal/write_event.h>
23
24
  #include <grpc/support/port_platform.h>
24
25
  #include <stddef.h>
25
26
  #include <stdint.h>
27
+ #include <string.h>
26
28
 
27
29
  #include <optional>
28
30
  #include <string>
@@ -126,6 +128,42 @@ class TcpCallTracer {
126
128
 
127
129
  virtual ~TcpCallTracer() = default;
128
130
 
131
+ struct IpAddress {
132
+ uint16_t family = 0;
133
+ uint16_t port = 0;
134
+ uint8_t ip[16] = {0};
135
+ };
136
+
137
+ virtual void RecordConnectionTuple(const IpAddress& local_addr,
138
+ const IpAddress& peer_addr) {}
139
+
140
+ static IpAddress ExtractResolvedAddress(
141
+ const grpc_event_engine::experimental::EventEngine::ResolvedAddress&
142
+ addr) {
143
+ IpAddress out;
144
+ const sockaddr* sa = addr.address();
145
+ if (sa == nullptr) {
146
+ out.family = 0;
147
+ out.port = 0;
148
+ memset(out.ip, 0, sizeof(out.ip));
149
+ return out;
150
+ }
151
+ out.family = sa->sa_family;
152
+ memset(out.ip, 0, sizeof(out.ip));
153
+ if (sa->sa_family == AF_INET) {
154
+ const sockaddr_in* addr4 = reinterpret_cast<const sockaddr_in*>(sa);
155
+ out.port = ntohs(addr4->sin_port);
156
+ memcpy(out.ip, &addr4->sin_addr.s_addr, 4);
157
+ } else if (sa->sa_family == AF_INET6) {
158
+ const sockaddr_in6* addr6 = reinterpret_cast<const sockaddr_in6*>(sa);
159
+ out.port = ntohs(addr6->sin6_port);
160
+ memcpy(out.ip, &addr6->sin6_addr.s6_addr, 16);
161
+ } else {
162
+ out.port = 0;
163
+ }
164
+ return out;
165
+ }
166
+
129
167
  // Records a per-message event with an optional snapshot of connection
130
168
  // metrics.
131
169
  virtual void RecordEvent(
@@ -809,7 +809,7 @@ alts_handshaker_client* alts_grpc_handshaker_client_create(
809
809
  /*cq=*/nullptr, interested_parties,
810
810
  grpc_core::Slice::FromStaticString(ALTS_SERVICE_METHOD),
811
811
  /*authority=*/std::nullopt, grpc_core::Timestamp::InfFuture(),
812
- /*registered_method=*/true);
812
+ /*registered_method=*/true, std::nullopt);
813
813
  GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, grpc_cb, client,
814
814
  grpc_schedule_on_exec_ctx);
815
815
  GRPC_CLOSURE_INIT(&client->on_status_received, on_status_received, client,
@@ -0,0 +1,343 @@
1
+ //
2
+ //
3
+ // Copyright 2026 gRPC authors.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ //
17
+ //
18
+
19
+ #include "src/core/tsi/ssl_telemetry_utils.h"
20
+
21
+ #include <grpc/support/port_platform.h>
22
+ #include <openssl/err.h>
23
+ #include <openssl/ssl.h>
24
+ #include <openssl/x509.h>
25
+
26
+ namespace grpc_core {
27
+
28
+ #if defined(OPENSSL_IS_BORINGSSL)
29
+
30
+ namespace {
31
+
32
+ TlsTelemetryHandshakeResult MapVerifyResultToTlsTelemetryHandshakeResult(
33
+ long verify_result) {
34
+ if (verify_result == X509_V_OK) return TlsTelemetryHandshakeResult::kSuccess;
35
+ switch (verify_result) {
36
+ case X509_V_ERR_CERT_REVOKED:
37
+ return TlsTelemetryHandshakeResult::kCertificateRevoked;
38
+ case X509_V_ERR_CERT_HAS_EXPIRED:
39
+ return TlsTelemetryHandshakeResult::kCertificateExpired;
40
+ case X509_V_ERR_CERT_NOT_YET_VALID:
41
+ return TlsTelemetryHandshakeResult::kCertificateNotYetValid;
42
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
43
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
44
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
45
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
46
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
47
+ return TlsTelemetryHandshakeResult::kCertificateAuthorityInvalid;
48
+ case X509_V_ERR_HOSTNAME_MISMATCH:
49
+ return TlsTelemetryHandshakeResult::kCertificateHostnameMismatch;
50
+ case X509_V_ERR_CERT_REJECTED:
51
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
52
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
53
+ return TlsTelemetryHandshakeResult::kCrlNotFound;
54
+ case X509_V_ERR_CRL_HAS_EXPIRED:
55
+ case X509_V_ERR_CRL_NOT_YET_VALID:
56
+ return TlsTelemetryHandshakeResult::kCrlExpired;
57
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
58
+ return TlsTelemetryHandshakeResult::kCrlSignatureFailure;
59
+ case X509_V_ERR_INVALID_CA:
60
+ case X509_V_ERR_INVALID_NON_CA:
61
+ case X509_V_ERR_INVALID_PURPOSE:
62
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
63
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
64
+ return TlsTelemetryHandshakeResult::kCertificateMalformed;
65
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
66
+ return TlsTelemetryHandshakeResult::kSignatureVerificationFailed;
67
+ default:
68
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
69
+ }
70
+ }
71
+
72
+ } // namespace
73
+
74
+ TlsTelemetryHandshakeResult MapSslErrorToTlsTelemetryHandshakeResult(
75
+ int ssl_error, unsigned long err_code, long verify_result) {
76
+ if (ssl_error == SSL_ERROR_NONE) {
77
+ return MapVerifyResultToTlsTelemetryHandshakeResult(verify_result);
78
+ }
79
+
80
+ if (ssl_error == SSL_ERROR_ZERO_RETURN) {
81
+ return TlsTelemetryHandshakeResult::kPeerConnectionClosed;
82
+ }
83
+
84
+ if (ssl_error == SSL_ERROR_SYSCALL) {
85
+ return TlsTelemetryHandshakeResult::kPeerConnectionClosed;
86
+ }
87
+
88
+ if (ssl_error == SSL_ERROR_SSL) {
89
+ int reason = ERR_GET_REASON(err_code);
90
+ switch (reason) {
91
+ // Cipher suite mismatch failures
92
+ case SSL_R_NO_CIPHERS_AVAILABLE:
93
+ case SSL_R_NO_CIPHERS_PASSED:
94
+ case SSL_R_NO_CIPHER_MATCH:
95
+ case SSL_R_NO_SHARED_CIPHER:
96
+ case SSL_R_REQUIRED_CIPHER_MISSING:
97
+ case SSL_R_UNSUPPORTED_CIPHER:
98
+ case SSL_R_WRONG_CIPHER_RETURNED:
99
+ case SSL_R_CIPHER_MISMATCH_ON_EARLY_DATA:
100
+ case SSL_R_CIPHER_OR_HASH_UNAVAILABLE:
101
+ return TlsTelemetryHandshakeResult::kCipherSuiteMismatch;
102
+
103
+ // Protocol version unsupported failures
104
+ case SSL_R_UNKNOWN_PROTOCOL:
105
+ case SSL_R_UNKNOWN_SSL_VERSION:
106
+ case SSL_R_UNSUPPORTED_PROTOCOL:
107
+ case SSL_R_WRONG_SSL_VERSION:
108
+ case SSL_R_WRONG_VERSION_NUMBER:
109
+ case SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY:
110
+ case SSL_R_WRONG_VERSION_ON_EARLY_DATA:
111
+ case SSL_R_NO_SUPPORTED_VERSIONS_ENABLED:
112
+ case SSL_R_SECOND_SERVERHELLO_VERSION_MISMATCH:
113
+ return TlsTelemetryHandshakeResult::kProtocolVersionUnsupported;
114
+
115
+ // Inappropriate fallback
116
+ case SSL_R_INAPPROPRIATE_FALLBACK:
117
+ return TlsTelemetryHandshakeResult::kInappropriateFallback;
118
+
119
+ // No application protocol
120
+ case SSL_R_NO_APPLICATION_PROTOCOL:
121
+ case SSL_R_INVALID_ALPN_PROTOCOL:
122
+ case SSL_R_INVALID_ALPN_PROTOCOL_LIST:
123
+ case SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN:
124
+ case SSL_R_ALPN_MISMATCH_ON_EARLY_DATA:
125
+ return TlsTelemetryHandshakeResult::kNoApplicationProtocol;
126
+
127
+ // Cryptographic failures: Signature verification failed
128
+ case SSL_R_BAD_SIGNATURE:
129
+ case SSL_R_WRONG_SIGNATURE_TYPE:
130
+ return TlsTelemetryHandshakeResult::kSignatureVerificationFailed;
131
+
132
+ // Cryptographic failures: Decryption failed
133
+ case SSL_R_DECRYPTION_FAILED:
134
+ case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
135
+ case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:
136
+ return TlsTelemetryHandshakeResult::kDecryptionFailed;
137
+
138
+ // Cryptographic failures: Key exchange failure
139
+ case SSL_R_WRONG_CURVE:
140
+ case SSL_R_BAD_ECPOINT:
141
+ return TlsTelemetryHandshakeResult::kKeyExchangeFailure;
142
+
143
+ // Unexpected message
144
+ case SSL_R_UNEXPECTED_MESSAGE:
145
+ case SSL_R_UNEXPECTED_RECORD:
146
+ case SSL_R_APP_DATA_IN_HANDSHAKE:
147
+ case SSL_R_EXCESS_HANDSHAKE_DATA:
148
+ return TlsTelemetryHandshakeResult::kUnexpectedMessage;
149
+
150
+ // Handshake timeout
151
+ case SSL_R_READ_TIMEOUT_EXPIRED:
152
+ return TlsTelemetryHandshakeResult::kHandshakeTimeout;
153
+
154
+ // Certificate verification failures
155
+ case SSL_R_CERTIFICATE_VERIFY_FAILED: {
156
+ TlsTelemetryHandshakeResult result =
157
+ MapVerifyResultToTlsTelemetryHandshakeResult(verify_result);
158
+ if (result == TlsTelemetryHandshakeResult::kSuccess) {
159
+ // There's no more detail on certificate failure, this is as granular
160
+ // as we can get.
161
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
162
+ }
163
+ return result;
164
+ }
165
+
166
+ // Certificate malformed
167
+ case SSL_R_DECODE_ERROR:
168
+ return TlsTelemetryHandshakeResult::kCertificateMalformed;
169
+
170
+ // Peer Certificate required but missing
171
+ case SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:
172
+ case SSL_R_NO_CERTIFICATES_RETURNED:
173
+ case SSL_R_NO_CERTIFICATE_SET:
174
+ case SSL_R_NO_CERTIFICATE_ASSIGNED:
175
+ case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
176
+ case SSL_R_TLSV1_ALERT_CERTIFICATE_REQUIRED:
177
+ return TlsTelemetryHandshakeResult::kPeerCertificateRequiredButMissing;
178
+
179
+ // Internal / Resource failures
180
+ case ERR_R_MALLOC_FAILURE:
181
+ case ERR_R_INTERNAL_ERROR:
182
+ case ERR_R_OVERFLOW:
183
+ return TlsTelemetryHandshakeResult::kInternalSystemError;
184
+
185
+ default:
186
+ break;
187
+ }
188
+ }
189
+
190
+ return TlsTelemetryHandshakeResult::kUnknownFailure;
191
+ }
192
+
193
+ #else // !defined(OPENSSL_IS_BORINGSSL)
194
+
195
+ namespace {
196
+
197
+ TlsTelemetryHandshakeResult MapVerifyResultToTlsTelemetryHandshakeResult(
198
+ long verify_result) {
199
+ if (verify_result == X509_V_OK) return TlsTelemetryHandshakeResult::kSuccess;
200
+ switch (verify_result) {
201
+ case X509_V_ERR_CERT_REVOKED:
202
+ return TlsTelemetryHandshakeResult::kCertificateRevoked;
203
+ case X509_V_ERR_CERT_HAS_EXPIRED:
204
+ return TlsTelemetryHandshakeResult::kCertificateExpired;
205
+ case X509_V_ERR_CERT_NOT_YET_VALID:
206
+ return TlsTelemetryHandshakeResult::kCertificateNotYetValid;
207
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
208
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
209
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
210
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
211
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
212
+ return TlsTelemetryHandshakeResult::kCertificateAuthorityInvalid;
213
+ case X509_V_ERR_HOSTNAME_MISMATCH:
214
+ return TlsTelemetryHandshakeResult::kCertificateHostnameMismatch;
215
+ case X509_V_ERR_CERT_REJECTED:
216
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
217
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
218
+ return TlsTelemetryHandshakeResult::kCrlNotFound;
219
+ case X509_V_ERR_CRL_HAS_EXPIRED:
220
+ case X509_V_ERR_CRL_NOT_YET_VALID:
221
+ return TlsTelemetryHandshakeResult::kCrlExpired;
222
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
223
+ return TlsTelemetryHandshakeResult::kCrlSignatureFailure;
224
+ case X509_V_ERR_INVALID_CA:
225
+ case X509_V_ERR_INVALID_NON_CA:
226
+ case X509_V_ERR_INVALID_PURPOSE:
227
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
228
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
229
+ return TlsTelemetryHandshakeResult::kCertificateMalformed;
230
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
231
+ return TlsTelemetryHandshakeResult::kSignatureVerificationFailed;
232
+ default:
233
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
234
+ }
235
+ }
236
+
237
+ } // namespace
238
+
239
+ TlsTelemetryHandshakeResult MapSslErrorToTlsTelemetryHandshakeResult(
240
+ int ssl_error, unsigned long err_code, long verify_result) {
241
+ if (ssl_error == SSL_ERROR_NONE) {
242
+ return MapVerifyResultToTlsTelemetryHandshakeResult(verify_result);
243
+ }
244
+
245
+ if (ssl_error == SSL_ERROR_ZERO_RETURN) {
246
+ return TlsTelemetryHandshakeResult::kPeerConnectionClosed;
247
+ }
248
+
249
+ if (ssl_error == SSL_ERROR_SYSCALL) {
250
+ return TlsTelemetryHandshakeResult::kPeerConnectionClosed;
251
+ }
252
+
253
+ if (ssl_error == SSL_ERROR_SSL) {
254
+ int reason = ERR_GET_REASON(err_code);
255
+ switch (reason) {
256
+ // Cipher suite mismatch failures
257
+ case SSL_R_NO_CIPHERS_AVAILABLE:
258
+ case SSL_R_NO_CIPHER_MATCH:
259
+ case SSL_R_NO_SHARED_CIPHER:
260
+ case SSL_R_REQUIRED_CIPHER_MISSING:
261
+ case SSL_R_WRONG_CIPHER_RETURNED:
262
+ return TlsTelemetryHandshakeResult::kCipherSuiteMismatch;
263
+
264
+ // Protocol version unsupported failures
265
+ case SSL_R_UNKNOWN_PROTOCOL:
266
+ case SSL_R_UNKNOWN_SSL_VERSION:
267
+ case SSL_R_UNSUPPORTED_PROTOCOL:
268
+ case SSL_R_WRONG_SSL_VERSION:
269
+ case SSL_R_WRONG_VERSION_NUMBER:
270
+ return TlsTelemetryHandshakeResult::kProtocolVersionUnsupported;
271
+
272
+ // Inappropriate fallback
273
+ case SSL_R_INAPPROPRIATE_FALLBACK:
274
+ return TlsTelemetryHandshakeResult::kInappropriateFallback;
275
+
276
+ // No application protocol
277
+ #ifdef SSL_R_NO_APPLICATION_PROTOCOL
278
+ case SSL_R_NO_APPLICATION_PROTOCOL:
279
+ return TlsTelemetryHandshakeResult::kNoApplicationProtocol;
280
+ #endif
281
+
282
+ // Cryptographic failures: Signature verification failed
283
+ case SSL_R_BAD_SIGNATURE:
284
+ case SSL_R_WRONG_SIGNATURE_TYPE:
285
+ return TlsTelemetryHandshakeResult::kSignatureVerificationFailed;
286
+
287
+ // Cryptographic failures: Decryption failed
288
+ case SSL_R_DECRYPTION_FAILED:
289
+ case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
290
+ case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:
291
+ return TlsTelemetryHandshakeResult::kDecryptionFailed;
292
+
293
+ // Cryptographic failures: Key exchange failure
294
+ case SSL_R_WRONG_CURVE:
295
+ case SSL_R_BAD_ECPOINT:
296
+ return TlsTelemetryHandshakeResult::kKeyExchangeFailure;
297
+
298
+ // Unexpected message
299
+ case SSL_R_UNEXPECTED_MESSAGE:
300
+ case SSL_R_UNEXPECTED_RECORD:
301
+ case SSL_R_APP_DATA_IN_HANDSHAKE:
302
+ return TlsTelemetryHandshakeResult::kUnexpectedMessage;
303
+
304
+ // Handshake timeout
305
+ case SSL_R_READ_TIMEOUT_EXPIRED:
306
+ return TlsTelemetryHandshakeResult::kHandshakeTimeout;
307
+
308
+ // Certificate verification failures
309
+ case SSL_R_CERTIFICATE_VERIFY_FAILED: {
310
+ TlsTelemetryHandshakeResult result =
311
+ MapVerifyResultToTlsTelemetryHandshakeResult(verify_result);
312
+ if (result == TlsTelemetryHandshakeResult::kSuccess) {
313
+ // There's no more detail on certificate failure, this is as granular
314
+ // as we can get.
315
+ return TlsTelemetryHandshakeResult::kCertificateVerificationFailed;
316
+ }
317
+ return result;
318
+ }
319
+
320
+ // Peer Certificate required but missing
321
+ case SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:
322
+ case SSL_R_NO_CERTIFICATES_RETURNED:
323
+ case SSL_R_NO_CERTIFICATE_SET:
324
+ case SSL_R_NO_CERTIFICATE_ASSIGNED:
325
+ case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
326
+ return TlsTelemetryHandshakeResult::kPeerCertificateRequiredButMissing;
327
+
328
+ // Internal / Resource failures
329
+ case ERR_R_MALLOC_FAILURE:
330
+ case ERR_R_INTERNAL_ERROR:
331
+ return TlsTelemetryHandshakeResult::kInternalSystemError;
332
+
333
+ default:
334
+ break;
335
+ }
336
+ }
337
+
338
+ return TlsTelemetryHandshakeResult::kUnknownFailure;
339
+ }
340
+
341
+ #endif // OPENSSL_IS_BORINGSSL
342
+
343
+ } // namespace grpc_core
@@ -0,0 +1,74 @@
1
+ //
2
+ //
3
+ // Copyright 2026 gRPC authors.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ //
17
+ //
18
+
19
+ #ifndef GRPC_SRC_CORE_TSI_SSL_TELEMETRY_UTILS_H
20
+ #define GRPC_SRC_CORE_TSI_SSL_TELEMETRY_UTILS_H
21
+
22
+ #include <grpc/support/port_platform.h>
23
+
24
+ namespace grpc_core {
25
+
26
+ enum class TlsTelemetryHandshakeResult {
27
+ kUnknownFailure,
28
+ kSuccess,
29
+ // Peer certificate verification failures.
30
+ kCertificateVerificationFailed,
31
+ kCertificateRevoked,
32
+ kCertificateExpired,
33
+ kCertificateNotYetValid,
34
+ kCertificateAuthorityInvalid,
35
+ kPeerCertificateRequiredButMissing,
36
+ kCrlNotFound,
37
+ kCrlExpired,
38
+ kCrlSignatureFailure,
39
+ // TLS negotiation mismatch failures
40
+ kCertificateHostnameMismatch,
41
+ kCertificateMalformed,
42
+ kCipherSuiteMismatch,
43
+ kProtocolVersionUnsupported,
44
+ kInappropriateFallback,
45
+ kNoApplicationProtocol,
46
+ // Cryptograpic failures
47
+ kSignatureVerificationFailed,
48
+ kDecryptionFailed,
49
+ kKeyExchangeFailure,
50
+ kPrivateKeySigningFailed,
51
+ // Other failures
52
+ kUnexpectedMessage,
53
+ kHandshakeTimeout,
54
+ kPeerConnectionClosed,
55
+ kInternalSystemError
56
+ };
57
+
58
+ // Maps different kinds of handshake/SSL/TLS errors to a unified
59
+ // TlsTelemetryHandshakeResult.
60
+ //
61
+ // - ssl_error: the return code from SSL_get_error().
62
+ // - err_code: the packed error code from the OpenSSL error queue
63
+ // (ERR_get_error()).
64
+ // - verify_result: the certificate verification result from
65
+ // SSL_get_verify_result().
66
+ //
67
+ // - Returns the corresponding TlsTelemetryHandshakeResult mapping for the
68
+ // failures.
69
+ TlsTelemetryHandshakeResult MapSslErrorToTlsTelemetryHandshakeResult(
70
+ int ssl_error, unsigned long err_code, long verify_result);
71
+
72
+ } // namespace grpc_core
73
+
74
+ #endif // GRPC_SRC_CORE_TSI_SSL_TELEMETRY_UTILS_H