1 /** @file
2  *
3  *  A brief file description
4  *
5  *  @section license License
6  *
7  *  Licensed to the Apache Software Foundation (ASF) under one
8  *  or more contributor license agreements.  See the NOTICE file
9  *  distributed with this work for additional information
10  *  regarding copyright ownership.  The ASF licenses this file
11  *  to you under the Apache License, Version 2.0 (the
12  *  "License"); you may not use this file except in compliance
13  *  with the License.  You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  */
23 
24 #include "QUICConfig.h"
25 
26 #include <openssl/ssl.h>
27 
28 #include <records/I_RecHttp.h>
29 
30 #include "P_SSLConfig.h"
31 
32 #include "QUICGlobals.h"
33 #include "QUICTransportParameters.h"
34 
35 int QUICConfig::_config_id                   = 0;
36 int QUICConfigParams::_connection_table_size = 65521;
37 
38 SSL_CTX *
quic_new_ssl_ctx()39 quic_new_ssl_ctx()
40 {
41   SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
42 
43   SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
44   SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
45 
46 #ifndef OPENSSL_IS_BORINGSSL
47   // FIXME: OpenSSL (1.1.1-alpha) enable this option by default. But this should be removed when OpenSSL disable this by default.
48   SSL_CTX_clear_options(ssl_ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
49 
50   SSL_CTX_set_max_early_data(ssl_ctx, UINT32_C(0xFFFFFFFF));
51 
52 #else
53   // QUIC Transport Parameters are accessible with SSL_set_quic_transport_params and SSL_get_peer_quic_transport_params
54 #endif
55 
56 #ifdef SSL_MODE_QUIC_HACK
57   // tatsuhiro-t's custom OpenSSL for QUIC draft-13
58   // https://github.com/tatsuhiro-t/openssl/tree/quic-draft-13
59   SSL_CTX_set_mode(ssl_ctx, SSL_MODE_QUIC_HACK);
60   SSL_CTX_add_custom_ext(ssl_ctx, QUICTransportParametersHandler::TRANSPORT_PARAMETER_ID,
61                          SSL_EXT_TLS_ONLY | SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
62                          &QUICTransportParametersHandler::add, &QUICTransportParametersHandler::free, nullptr,
63                          &QUICTransportParametersHandler::parse, nullptr);
64 
65 #endif
66 
67   return ssl_ctx;
68 }
69 
70 /**
71    ALPN and SNI should be set to SSL object with NETVC_OPTIONS
72  **/
73 static shared_SSL_CTX
quic_init_client_ssl_ctx(const QUICConfigParams * params)74 quic_init_client_ssl_ctx(const QUICConfigParams *params)
75 {
76   std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ssl_ctx(nullptr, &SSL_CTX_free);
77   ssl_ctx.reset(quic_new_ssl_ctx());
78 
79 #if defined(SSL_CTX_set1_groups_list) || defined(SSL_CTX_set1_curves_list)
80   if (params->client_supported_groups() != nullptr) {
81 #ifdef SSL_CTX_set1_groups_list
82     if (SSL_CTX_set1_groups_list(ssl_ctx.get(), params->client_supported_groups()) != 1) {
83 #else
84     if (SSL_CTX_set1_curves_list(ssl_ctx.get(), params->client_supported_groups()) != 1) {
85 #endif
86       Error("SSL_CTX_set1_groups_list failed");
87     }
88   }
89 #endif
90 
91   if (params->client_session_file() != nullptr) {
92     SSL_CTX_set_session_cache_mode(ssl_ctx.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE);
93     SSL_CTX_sess_set_new_cb(ssl_ctx.get(), QUIC::ssl_client_new_session);
94   }
95 
96 #ifdef SSL_MODE_QUIC_HACK
97   if (params->client_keylog_file() != nullptr) {
98     SSL_CTX_set_keylog_callback(ssl_ctx.get(), QUIC::ssl_client_keylog_cb);
99   }
100 #endif
101 
102   return ssl_ctx;
103 }
104 
105 //
106 // QUICConfigParams
107 //
108 QUICConfigParams::~QUICConfigParams()
109 {
110   this->_server_supported_groups = (char *)ats_free_null(this->_server_supported_groups);
111   this->_client_supported_groups = (char *)ats_free_null(this->_client_supported_groups);
112 
113   SSL_CTX_free(this->_client_ssl_ctx.get());
114 };
115 
116 void
117 QUICConfigParams::initialize()
118 {
119   REC_EstablishStaticConfigInt32U(this->_instance_id, "proxy.config.quic.instance_id");
120   REC_EstablishStaticConfigInt32(this->_connection_table_size, "proxy.config.quic.connection_table.size");
121   REC_EstablishStaticConfigInt32U(this->_stateless_retry, "proxy.config.quic.server.stateless_retry_enabled");
122   REC_EstablishStaticConfigInt32U(this->_vn_exercise_enabled, "proxy.config.quic.client.vn_exercise_enabled");
123   REC_EstablishStaticConfigInt32U(this->_cm_exercise_enabled, "proxy.config.quic.client.cm_exercise_enabled");
124   REC_EstablishStaticConfigInt32U(this->_quantum_readiness_test_enabled_out,
125                                   "proxy.config.quic.client.quantum_readiness_test_enabled");
126   REC_EstablishStaticConfigInt32U(this->_quantum_readiness_test_enabled_in,
127                                   "proxy.config.quic.server.quantum_readiness_test_enabled");
128 
129   REC_ReadConfigStringAlloc(this->_server_supported_groups, "proxy.config.quic.server.supported_groups");
130   REC_ReadConfigStringAlloc(this->_client_supported_groups, "proxy.config.quic.client.supported_groups");
131   REC_ReadConfigStringAlloc(this->_client_session_file, "proxy.config.quic.client.session_file");
132   REC_ReadConfigStringAlloc(this->_client_keylog_file, "proxy.config.quic.client.keylog_file");
133   REC_ReadConfigStringAlloc(this->_qlog_dir, "proxy.config.quic.qlog_dir");
134 
135   // Transport Parameters
136   REC_EstablishStaticConfigInt32U(this->_no_activity_timeout_in, "proxy.config.quic.no_activity_timeout_in");
137   REC_EstablishStaticConfigInt32U(this->_no_activity_timeout_out, "proxy.config.quic.no_activity_timeout_out");
138   REC_ReadConfigStringAlloc(this->_preferred_address_ipv4, "proxy.config.quic.preferred_address_ipv4");
139   if (this->_preferred_address_ipv4) {
140     ats_ip_pton(this->_preferred_address_ipv4, &this->_preferred_endpoint_ipv4);
141   }
142   REC_ReadConfigStringAlloc(this->_preferred_address_ipv6, "proxy.config.quic.preferred_address_ipv6");
143   if (this->_preferred_address_ipv6) {
144     ats_ip_pton(this->_preferred_address_ipv6, &this->_preferred_endpoint_ipv6);
145   }
146   REC_EstablishStaticConfigInt32U(this->_initial_max_data_in, "proxy.config.quic.initial_max_data_in");
147   REC_EstablishStaticConfigInt32U(this->_initial_max_data_out, "proxy.config.quic.initial_max_data_out");
148   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_local_in,
149                                   "proxy.config.quic.initial_max_stream_data_bidi_local_in");
150   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_local_out,
151                                   "proxy.config.quic.initial_max_stream_data_bidi_local_out");
152   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_remote_in,
153                                   "proxy.config.quic.initial_max_stream_data_bidi_remote_in");
154   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_bidi_remote_out,
155                                   "proxy.config.quic.initial_max_stream_data_bidi_remote_out");
156   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_uni_in, "proxy.config.quic.initial_max_stream_data_uni_in");
157   REC_EstablishStaticConfigInt32U(this->_initial_max_stream_data_uni_out, "proxy.config.quic.initial_max_stream_data_uni_out");
158   REC_EstablishStaticConfigInt32U(this->_initial_max_streams_bidi_in, "proxy.config.quic.initial_max_streams_bidi_in");
159   REC_EstablishStaticConfigInt32U(this->_initial_max_streams_bidi_out, "proxy.config.quic.initial_max_streams_bidi_out");
160   REC_EstablishStaticConfigInt32U(this->_initial_max_streams_uni_in, "proxy.config.quic.initial_max_streams_uni_in");
161   REC_EstablishStaticConfigInt32U(this->_initial_max_streams_uni_out, "proxy.config.quic.initial_max_streams_uni_out");
162   REC_EstablishStaticConfigInt32U(this->_ack_delay_exponent_in, "proxy.config.quic.ack_delay_exponent_in");
163   REC_EstablishStaticConfigInt32U(this->_ack_delay_exponent_out, "proxy.config.quic.ack_delay_exponent_out");
164   REC_EstablishStaticConfigInt32U(this->_max_ack_delay_in, "proxy.config.quic.max_ack_delay_in");
165   REC_EstablishStaticConfigInt32U(this->_max_ack_delay_out, "proxy.config.quic.max_ack_delay_out");
166   REC_EstablishStaticConfigInt32U(this->_active_cid_limit_in, "proxy.config.quic.active_cid_limit_in");
167   REC_EstablishStaticConfigInt32U(this->_active_cid_limit_out, "proxy.config.quic.active_cid_limit_out");
168   REC_EstablishStaticConfigInt32U(this->_disable_active_migration, "proxy.config.quic.disable_active_migration");
169 
170   // Loss Detection
171   REC_EstablishStaticConfigInt32U(this->_ld_packet_threshold, "proxy.config.quic.loss_detection.packet_threshold");
172   REC_EstablishStaticConfigFloat(this->_ld_time_threshold, "proxy.config.quic.loss_detection.time_threshold");
173 
174   uint32_t timeout = 0;
175   REC_EstablishStaticConfigInt32U(timeout, "proxy.config.quic.loss_detection.granularity");
176   this->_ld_granularity = HRTIME_MSECONDS(timeout);
177 
178   REC_EstablishStaticConfigInt32U(timeout, "proxy.config.quic.loss_detection.initial_rtt");
179   this->_ld_initial_rtt = HRTIME_MSECONDS(timeout);
180 
181   // Congestion Control
182   REC_EstablishStaticConfigInt32U(this->_cc_initial_window, "proxy.config.quic.congestion_control.initial_window");
183   REC_EstablishStaticConfigInt32U(this->_cc_minimum_window, "proxy.config.quic.congestion_control.minimum_window");
184   REC_EstablishStaticConfigFloat(this->_cc_loss_reduction_factor, "proxy.config.quic.congestion_control.loss_reduction_factor");
185   REC_EstablishStaticConfigInt32U(this->_cc_persistent_congestion_threshold,
186                                   "proxy.config.quic.congestion_control.persistent_congestion_threshold");
187 
188   this->_client_ssl_ctx = quic_init_client_ssl_ctx(this);
189 }
190 
191 uint32_t
192 QUICConfigParams::no_activity_timeout_in() const
193 {
194   return this->_no_activity_timeout_in;
195 }
196 
197 uint32_t
198 QUICConfigParams::no_activity_timeout_out() const
199 {
200   return this->_no_activity_timeout_out;
201 }
202 
203 const IpEndpoint *
204 QUICConfigParams::preferred_address_ipv4() const
205 {
206   if (!this->_preferred_address_ipv4) {
207     return nullptr;
208   }
209 
210   return &this->_preferred_endpoint_ipv4;
211 }
212 
213 const IpEndpoint *
214 QUICConfigParams::preferred_address_ipv6() const
215 {
216   if (!this->_preferred_address_ipv6) {
217     return nullptr;
218   }
219 
220   return &this->_preferred_endpoint_ipv6;
221 }
222 
223 uint32_t
224 QUICConfigParams::instance_id() const
225 {
226   return this->_instance_id;
227 }
228 
229 int
230 QUICConfigParams::connection_table_size()
231 {
232   return _connection_table_size;
233 }
234 
235 uint32_t
236 QUICConfigParams::stateless_retry() const
237 {
238   return this->_stateless_retry;
239 }
240 
241 uint32_t
242 QUICConfigParams::vn_exercise_enabled() const
243 {
244   return this->_vn_exercise_enabled;
245 }
246 
247 uint32_t
248 QUICConfigParams::cm_exercise_enabled() const
249 {
250   return this->_cm_exercise_enabled;
251 }
252 
253 uint32_t
254 QUICConfigParams::quantum_readiness_test_enabled_in() const
255 {
256   return this->_quantum_readiness_test_enabled_in;
257 }
258 
259 uint32_t
260 QUICConfigParams::quantum_readiness_test_enabled_out() const
261 {
262   return this->_quantum_readiness_test_enabled_out;
263 }
264 
265 uint32_t
266 QUICConfigParams::initial_max_data_in() const
267 {
268   return this->_initial_max_data_in;
269 }
270 
271 uint32_t
272 QUICConfigParams::initial_max_data_out() const
273 {
274   return this->_initial_max_data_out;
275 }
276 
277 uint32_t
278 QUICConfigParams::initial_max_stream_data_bidi_local_in() const
279 {
280   return this->_initial_max_stream_data_bidi_local_in;
281 }
282 
283 uint32_t
284 QUICConfigParams::initial_max_stream_data_bidi_local_out() const
285 {
286   return this->_initial_max_stream_data_bidi_local_out;
287 }
288 
289 uint32_t
290 QUICConfigParams::initial_max_stream_data_bidi_remote_in() const
291 {
292   return this->_initial_max_stream_data_bidi_remote_in;
293 }
294 
295 uint32_t
296 QUICConfigParams::initial_max_stream_data_bidi_remote_out() const
297 {
298   return this->_initial_max_stream_data_bidi_remote_out;
299 }
300 
301 uint32_t
302 QUICConfigParams::initial_max_stream_data_uni_in() const
303 {
304   return this->_initial_max_stream_data_uni_in;
305 }
306 
307 uint32_t
308 QUICConfigParams::initial_max_stream_data_uni_out() const
309 {
310   return this->_initial_max_stream_data_uni_out;
311 }
312 
313 uint64_t
314 QUICConfigParams::initial_max_streams_bidi_in() const
315 {
316   return this->_initial_max_streams_bidi_in;
317 }
318 
319 uint64_t
320 QUICConfigParams::initial_max_streams_bidi_out() const
321 {
322   return this->_initial_max_streams_bidi_out;
323 }
324 
325 uint64_t
326 QUICConfigParams::initial_max_streams_uni_in() const
327 {
328   return this->_initial_max_streams_uni_in;
329 }
330 
331 uint64_t
332 QUICConfigParams::initial_max_streams_uni_out() const
333 {
334   return this->_initial_max_streams_uni_out;
335 }
336 
337 uint8_t
338 QUICConfigParams::ack_delay_exponent_in() const
339 {
340   return this->_ack_delay_exponent_in;
341 }
342 
343 uint8_t
344 QUICConfigParams::ack_delay_exponent_out() const
345 {
346   return this->_ack_delay_exponent_out;
347 }
348 
349 uint8_t
350 QUICConfigParams::max_ack_delay_in() const
351 {
352   return this->_max_ack_delay_in;
353 }
354 
355 uint8_t
356 QUICConfigParams::max_ack_delay_out() const
357 {
358   return this->_max_ack_delay_out;
359 }
360 
361 uint8_t
362 QUICConfigParams::active_cid_limit_in() const
363 {
364   return this->_active_cid_limit_in;
365 }
366 
367 uint8_t
368 QUICConfigParams::active_cid_limit_out() const
369 {
370   return this->_active_cid_limit_out;
371 }
372 
373 bool
374 QUICConfigParams::disable_active_migration() const
375 {
376   return this->_disable_active_migration;
377 }
378 
379 const char *
380 QUICConfigParams::server_supported_groups() const
381 {
382   return this->_server_supported_groups;
383 }
384 
385 const char *
386 QUICConfigParams::client_supported_groups() const
387 {
388   return this->_client_supported_groups;
389 }
390 
391 shared_SSL_CTX
392 QUICConfigParams::client_ssl_ctx() const
393 {
394   return this->_client_ssl_ctx;
395 }
396 
397 uint32_t
398 QUICConfigParams::ld_packet_threshold() const
399 {
400   return _ld_packet_threshold;
401 }
402 
403 float
404 QUICConfigParams::ld_time_threshold() const
405 {
406   return _ld_time_threshold;
407 }
408 
409 ink_hrtime
410 QUICConfigParams::ld_granularity() const
411 {
412   return _ld_granularity;
413 }
414 
415 ink_hrtime
416 QUICConfigParams::ld_initial_rtt() const
417 {
418   return _ld_initial_rtt;
419 }
420 
421 uint32_t
422 QUICConfigParams::cc_initial_window() const
423 {
424   return _cc_initial_window;
425 }
426 
427 uint32_t
428 QUICConfigParams::cc_minimum_window() const
429 {
430   return _cc_minimum_window;
431 }
432 
433 float
434 QUICConfigParams::cc_loss_reduction_factor() const
435 {
436   return _cc_loss_reduction_factor;
437 }
438 
439 uint32_t
440 QUICConfigParams::cc_persistent_congestion_threshold() const
441 {
442   return _cc_persistent_congestion_threshold;
443 }
444 
445 uint8_t
446 QUICConfigParams::scid_len()
447 {
448   return QUICConfigParams::_scid_len;
449 }
450 
451 const char *
452 QUICConfigParams::client_session_file() const
453 {
454   return this->_client_session_file;
455 }
456 
457 const char *
458 QUICConfigParams::client_keylog_file() const
459 {
460   return this->_client_keylog_file;
461 }
462 
463 const char *
464 QUICConfigParams::qlog_dir() const
465 {
466   return this->_qlog_dir;
467 }
468 
469 //
470 // QUICConfig
471 //
472 void
473 QUICConfig::startup()
474 {
475   reconfigure();
476 }
477 
478 void
479 QUICConfig::reconfigure()
480 {
481   QUICConfigParams *params;
482   params = new QUICConfigParams;
483   // re-read configuration
484   params->initialize();
485   _config_id = configProcessor.set(_config_id, params);
486 
487   QUICConnectionId::SCID_LEN = params->scid_len();
488 }
489 
490 QUICConfigParams *
491 QUICConfig::acquire()
492 {
493   return static_cast<QUICConfigParams *>(configProcessor.get(_config_id));
494 }
495 
496 void
497 QUICConfig::release(QUICConfigParams *params)
498 {
499   configProcessor.release(_config_id, params);
500 }
501