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 /****************************************************************************
25
26 SSLNetVConnection.h
27
28 This file implements an I/O Processor for network I/O.
29
30
31 ****************************************************************************/
32 #pragma once
33
34 #include <memory>
35
36 #include "tscore/ink_platform.h"
37 #include "ts/apidefs.h"
38 #include <string_view>
39 #include <cstring>
40 #include <memory>
41
42 #include <openssl/ssl.h>
43 #include <openssl/err.h>
44 #include <openssl/objects.h>
45
46 #include "P_EventSystem.h"
47 #include "P_UnixNetVConnection.h"
48 #include "P_UnixNet.h"
49 #include "P_ALPNSupport.h"
50 #include "TLSSessionResumptionSupport.h"
51 #include "TLSSNISupport.h"
52 #include "P_SSLUtils.h"
53 #include "P_SSLConfig.h"
54
55 // These are included here because older OpenSSL libraries don't have them.
56 // Don't copy these defines, or use their values directly, they are merely
57 // here to avoid compiler errors.
58 #ifndef SSL_TLSEXT_ERR_OK
59 #define SSL_TLSEXT_ERR_OK 0
60 #endif
61
62 #ifndef SSL_TLSEXT_ERR_NOACK
63 #define SSL_TLSEXT_ERR_NOACK 3
64 #endif
65
66 #define SSL_OP_HANDSHAKE 0x16
67
68 // TS-2503: dynamic TLS record sizing
69 // For smaller records, we should also reserve space for various TCP options
70 // (timestamps, SACKs.. up to 40 bytes [1]), and account for TLS record overhead
71 // (another 20-60 bytes on average, depending on the negotiated ciphersuite [2]).
72 // All in all: 1500 - 40 (IP) - 20 (TCP) - 40 (TCP options) - TLS overhead (60-100)
73 // For larger records, the size is determined by TLS protocol record size
74 #define SSL_DEF_TLS_RECORD_SIZE 1300 // 1500 - 40 (IP) - 20 (TCP) - 40 (TCP options) - TLS overhead (60-100)
75 #define SSL_MAX_TLS_RECORD_SIZE 16383 // 2^14 - 1
76 #define SSL_DEF_TLS_RECORD_BYTE_THRESHOLD 1000000
77 #define SSL_DEF_TLS_RECORD_MSEC_THRESHOLD 1000
78
79 struct SSLCertLookup;
80
81 typedef enum {
82 SSL_HOOK_OP_DEFAULT, ///< Null / initialization value. Do normal processing.
83 SSL_HOOK_OP_TUNNEL, ///< Switch to blind tunnel
84 SSL_HOOK_OP_TERMINATE, ///< Termination connection / transaction.
85 SSL_HOOK_OP_LAST = SSL_HOOK_OP_TERMINATE ///< End marker value.
86 } SslVConnOp;
87
88 enum SSLHandshakeStatus { SSL_HANDSHAKE_ONGOING, SSL_HANDSHAKE_DONE, SSL_HANDSHAKE_ERROR };
89
90 //////////////////////////////////////////////////////////////////
91 //
92 // class NetVConnection
93 //
94 // A VConnection for a network socket.
95 //
96 //////////////////////////////////////////////////////////////////
97 class SSLNetVConnection : public UnixNetVConnection, public ALPNSupport, public TLSSessionResumptionSupport, public TLSSNISupport
98 {
99 typedef UnixNetVConnection super; ///< Parent type.
100
101 public:
102 int sslStartHandShake(int event, int &err) override;
103 void clear() override;
104 void free(EThread *t) override;
105
106 bool
trackFirstHandshake()107 trackFirstHandshake() override
108 {
109 bool retval = sslHandshakeBeginTime == 0;
110 if (retval) {
111 sslHandshakeBeginTime = Thread::get_hrtime();
112 }
113 return retval;
114 }
115
116 bool
getSSLHandShakeComplete()117 getSSLHandShakeComplete() const override
118 {
119 return sslHandshakeStatus != SSL_HANDSHAKE_ONGOING;
120 }
121
122 virtual void
setSSLHandShakeComplete(enum SSLHandshakeStatus state)123 setSSLHandShakeComplete(enum SSLHandshakeStatus state)
124 {
125 sslHandshakeStatus = state;
126 }
127
128 int sslServerHandShakeEvent(int &err);
129 int sslClientHandShakeEvent(int &err);
130 void net_read_io(NetHandler *nh, EThread *lthread) override;
131 int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs) override;
132 void do_io_close(int lerrno = -1) override;
133
134 ////////////////////////////////////////////////////////////
135 // Instances of NetVConnection should be allocated //
136 // only from the free list using NetVConnection::alloc(). //
137 // The constructor is public just to avoid compile errors.//
138 ////////////////////////////////////////////////////////////
139 SSLNetVConnection();
~SSLNetVConnection()140 ~SSLNetVConnection() override {}
141 static int advertise_next_protocol(SSL *ssl, const unsigned char **out, unsigned *outlen, void *);
142 static int select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
143 unsigned inlen, void *);
144
145 bool
getSSLClientRenegotiationAbort()146 getSSLClientRenegotiationAbort() const
147 {
148 return sslClientRenegotiationAbort;
149 }
150
151 void
setSSLClientRenegotiationAbort(bool state)152 setSSLClientRenegotiationAbort(bool state)
153 {
154 sslClientRenegotiationAbort = state;
155 }
156
157 bool
getTransparentPassThrough()158 getTransparentPassThrough() const
159 {
160 return transparentPassThrough;
161 }
162
163 void
setTransparentPassThrough(bool val)164 setTransparentPassThrough(bool val)
165 {
166 transparentPassThrough = val;
167 }
168
169 // Copy up here so we overload but don't override
170 using super::reenable;
171
172 /// Reenable the VC after a pre-accept or SNI hook is called.
173 virtual void reenable(NetHandler *nh, int event = TS_EVENT_CONTINUE);
174
175 int64_t read_raw_data();
176
177 void
initialize_handshake_buffers()178 initialize_handshake_buffers()
179 {
180 this->handShakeBuffer = new_MIOBuffer(SSLConfigParams::ssl_misc_max_iobuffer_size_index);
181 this->handShakeReader = this->handShakeBuffer->alloc_reader();
182 this->handShakeHolder = this->handShakeReader->clone();
183 this->handShakeBioStored = 0;
184 }
185
186 void
free_handshake_buffers()187 free_handshake_buffers()
188 {
189 if (this->handShakeReader) {
190 this->handShakeReader->dealloc();
191 }
192 if (this->handShakeHolder) {
193 this->handShakeHolder->dealloc();
194 }
195 if (this->handShakeBuffer) {
196 free_MIOBuffer(this->handShakeBuffer);
197 }
198 this->handShakeReader = nullptr;
199 this->handShakeHolder = nullptr;
200 this->handShakeBuffer = nullptr;
201 this->handShakeBioStored = 0;
202 }
203
204 // Returns true if all the hooks reenabled
205 bool callHooks(TSEvent eventId);
206
207 // Returns true if we have already called at
208 // least some of the hooks
209 bool
calledHooks(TSEvent eventId)210 calledHooks(TSEvent eventId) const
211 {
212 bool retval = false;
213 switch (this->sslHandshakeHookState) {
214 case HANDSHAKE_HOOKS_PRE:
215 case HANDSHAKE_HOOKS_PRE_INVOKE:
216 if (eventId == TS_EVENT_VCONN_START) {
217 if (curHook) {
218 retval = true;
219 }
220 }
221 break;
222 case HANDSHAKE_HOOKS_CLIENT_HELLO:
223 case HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE:
224 if (eventId == TS_EVENT_VCONN_START) {
225 retval = true;
226 } else if (eventId == TS_EVENT_SSL_CLIENT_HELLO) {
227 if (curHook) {
228 retval = true;
229 }
230 }
231 break;
232 case HANDSHAKE_HOOKS_SNI:
233 if (eventId == TS_EVENT_VCONN_START || eventId == TS_EVENT_SSL_CLIENT_HELLO) {
234 retval = true;
235 } else if (eventId == TS_EVENT_SSL_SERVERNAME) {
236 if (curHook) {
237 retval = true;
238 }
239 }
240 break;
241 case HANDSHAKE_HOOKS_CERT:
242 case HANDSHAKE_HOOKS_CERT_INVOKE:
243 if (eventId == TS_EVENT_VCONN_START || eventId == TS_EVENT_SSL_CLIENT_HELLO || eventId == TS_EVENT_SSL_SERVERNAME) {
244 retval = true;
245 } else if (eventId == TS_EVENT_SSL_CERT) {
246 if (curHook) {
247 retval = true;
248 }
249 }
250 break;
251 case HANDSHAKE_HOOKS_CLIENT_CERT:
252 case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE:
253 if (eventId == TS_EVENT_SSL_VERIFY_CLIENT || eventId == TS_EVENT_VCONN_START) {
254 retval = true;
255 }
256 break;
257
258 case HANDSHAKE_HOOKS_OUTBOUND_PRE:
259 case HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE:
260 if (eventId == TS_EVENT_VCONN_OUTBOUND_START) {
261 if (curHook) {
262 retval = true;
263 }
264 }
265 break;
266
267 case HANDSHAKE_HOOKS_VERIFY_SERVER:
268 retval = (eventId == TS_EVENT_SSL_VERIFY_SERVER);
269 break;
270
271 case HANDSHAKE_HOOKS_DONE:
272 retval = true;
273 break;
274 }
275 return retval;
276 }
277
278 const char *
getSSLProtocol()279 getSSLProtocol() const
280 {
281 return ssl ? SSL_get_version(ssl) : nullptr;
282 }
283
284 const char *
getSSLCipherSuite()285 getSSLCipherSuite() const
286 {
287 return ssl ? SSL_get_cipher_name(ssl) : nullptr;
288 }
289
290 const char *
getSSLCurve()291 getSSLCurve() const
292 {
293 if (!ssl) {
294 return nullptr;
295 }
296 ssl_curve_id curve;
297 if (getSSLSessionCacheHit()) {
298 curve = getSSLCurveNID();
299 } else {
300 curve = SSLGetCurveNID(ssl);
301 }
302 #ifndef OPENSSL_IS_BORINGSSL
303 if (curve == NID_undef) {
304 return nullptr;
305 }
306 return OBJ_nid2sn(curve);
307 #else
308 if (curve == 0) {
309 return nullptr;
310 }
311 return SSL_get_curve_name(curve);
312 #endif
313 }
314
315 bool
has_tunnel_destination()316 has_tunnel_destination() const
317 {
318 return tunnel_host != nullptr;
319 }
320
321 const char *
get_tunnel_host()322 get_tunnel_host() const
323 {
324 return tunnel_host;
325 }
326
327 ushort
get_tunnel_port()328 get_tunnel_port() const
329 {
330 return tunnel_port;
331 }
332
333 bool decrypt_tunnel() const;
334 bool upstream_tls() const;
335 SNIRoutingType tunnel_type() const;
336
337 void
set_tunnel_destination(const std::string_view & destination,SNIRoutingType type)338 set_tunnel_destination(const std::string_view &destination, SNIRoutingType type)
339 {
340 _tunnel_type = type;
341
342 auto pos = destination.find(":");
343 if (nullptr != tunnel_host) {
344 ats_free(tunnel_host);
345 }
346 if (pos != std::string::npos) {
347 tunnel_port = std::stoi(destination.substr(pos + 1).data());
348 tunnel_host = ats_strndup(destination.substr(0, pos).data(), pos);
349 } else {
350 tunnel_port = 0;
351 tunnel_host = ats_strndup(destination.data(), destination.length());
352 }
353 }
354
355 int populate_protocol(std::string_view *results, int n) const override;
356 const char *protocol_contains(std::string_view tag) const override;
357
358 /**
359 * Populate the current object based on the socket information in in the
360 * con parameter and the ssl object in the arg parameter
361 * This is logic is invoked when the NetVC object is created in a new thread context
362 */
363 int populate(Connection &con, Continuation *c, void *arg) override;
364
365 SSL *ssl = nullptr;
366 ink_hrtime sslHandshakeBeginTime = 0;
367 ink_hrtime sslHandshakeEndTime = 0;
368 ink_hrtime sslLastWriteTime = 0;
369 int64_t sslTotalBytesSent = 0;
370
371 // The serverName is either a pointer to the (null-terminated) name fetched from the
372 // SSL object or the empty string.
373 const char *
get_server_name()374 get_server_name() const override
375 {
376 return _get_sni_server_name() ? _get_sni_server_name() : "";
377 }
378
379 bool
support_sni()380 support_sni() const override
381 {
382 return true;
383 }
384
385 /// Set by asynchronous hooks to request a specific operation.
386 SslVConnOp hookOpRequested = SSL_HOOK_OP_DEFAULT;
387
388 // noncopyable
389 SSLNetVConnection(const SSLNetVConnection &) = delete;
390 SSLNetVConnection &operator=(const SSLNetVConnection &) = delete;
391
392 bool protocol_mask_set = false;
393 unsigned long protocol_mask;
394
395 // early data related stuff
396 bool early_data_finish = false;
397 MIOBuffer *early_data_buf = nullptr;
398 IOBufferReader *early_data_reader = nullptr;
399 int64_t read_from_early_data = 0;
400
401 // Only applies during the VERIFY certificate hooks (client and server side)
402 // Means to give the plugin access to the data structure passed in during the underlying
403 // openssl callback so the plugin can make more detailed decisions about the
404 // validity of the certificate in their cases
405 X509_STORE_CTX *
get_verify_cert()406 get_verify_cert()
407 {
408 return verify_cert;
409 }
410 void
set_verify_cert(X509_STORE_CTX * ctx)411 set_verify_cert(X509_STORE_CTX *ctx)
412 {
413 verify_cert = ctx;
414 }
415
416 const char *
get_sni_servername()417 get_sni_servername() const override
418 {
419 return SSL_get_servername(this->ssl, TLSEXT_NAMETYPE_host_name);
420 }
421
422 bool
peer_provided_cert()423 peer_provided_cert() const override
424 {
425 X509 *cert = SSL_get_peer_certificate(this->ssl);
426 if (cert != nullptr) {
427 X509_free(cert);
428 return true;
429 } else {
430 return false;
431 }
432 }
433
434 int
provided_cert()435 provided_cert() const override
436 {
437 if (this->get_context() == NET_VCONNECTION_OUT) {
438 return this->sent_cert;
439 } else {
440 return 1;
441 }
442 }
443
444 void
set_sent_cert(int send_the_cert)445 set_sent_cert(int send_the_cert)
446 {
447 sent_cert = send_the_cert;
448 }
449
450 void set_ca_cert_file(std::string_view file, std::string_view dir);
451
452 const char *
get_ca_cert_file()453 get_ca_cert_file()
454 {
455 return _ca_cert_file.get();
456 }
457 const char *
get_ca_cert_dir()458 get_ca_cert_dir()
459 {
460 return _ca_cert_dir.get();
461 }
462
463 void
set_valid_tls_protocols(unsigned long proto_mask,unsigned long max_mask)464 set_valid_tls_protocols(unsigned long proto_mask, unsigned long max_mask)
465 {
466 SSL_set_options(this->ssl, proto_mask);
467 SSL_clear_options(this->ssl, max_mask & ~proto_mask);
468 }
469
470 protected:
471 const IpEndpoint &
_getLocalEndpoint()472 _getLocalEndpoint() override
473 {
474 return local_addr;
475 }
476
477 void _fire_ssl_servername_event() override;
478
479 private:
480 std::string_view map_tls_protocol_to_tag(const char *proto_string) const;
481 bool update_rbio(bool move_to_socket);
482 void increment_ssl_version_metric(int version) const;
483 NetProcessor *_getNetProcessor() override;
484 void *_prepareForMigration() override;
485
486 enum SSLHandshakeStatus sslHandshakeStatus = SSL_HANDSHAKE_ONGOING;
487 bool sslClientRenegotiationAbort = false;
488 MIOBuffer *handShakeBuffer = nullptr;
489 IOBufferReader *handShakeHolder = nullptr;
490 IOBufferReader *handShakeReader = nullptr;
491 int handShakeBioStored = 0;
492
493 bool transparentPassThrough = false;
494
495 int sent_cert = 0;
496
497 /// The current hook.
498 /// @note For @C SSL_HOOKS_INVOKE, this is the hook to invoke.
499 class APIHook *curHook = nullptr;
500
501 enum SSLHandshakeHookState {
502 HANDSHAKE_HOOKS_PRE,
503 HANDSHAKE_HOOKS_PRE_INVOKE,
504 HANDSHAKE_HOOKS_CLIENT_HELLO,
505 HANDSHAKE_HOOKS_CLIENT_HELLO_INVOKE,
506 HANDSHAKE_HOOKS_SNI,
507 HANDSHAKE_HOOKS_CERT,
508 HANDSHAKE_HOOKS_CERT_INVOKE,
509 HANDSHAKE_HOOKS_CLIENT_CERT,
510 HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE,
511 HANDSHAKE_HOOKS_OUTBOUND_PRE,
512 HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE,
513 HANDSHAKE_HOOKS_VERIFY_SERVER,
514 HANDSHAKE_HOOKS_DONE
515 } sslHandshakeHookState = HANDSHAKE_HOOKS_PRE;
516
517 int64_t redoWriteSize = 0;
518 char *tunnel_host = nullptr;
519 in_port_t tunnel_port = 0;
520 SNIRoutingType _tunnel_type = SNIRoutingType::NONE;
521 X509_STORE_CTX *verify_cert = nullptr;
522
523 // Null-terminated string, or nullptr if there is no SNI server name.
524 std::unique_ptr<char[]> _ca_cert_file;
525 std::unique_ptr<char[]> _ca_cert_dir;
526
527 EventIO async_ep{};
528
529 private:
530 void _make_ssl_connection(SSL_CTX *ctx);
531 void _bindSSLObject();
532 void _unbindSSLObject();
533 };
534
535 typedef int (SSLNetVConnection::*SSLNetVConnHandler)(int, void *);
536
537 extern ClassAllocator<SSLNetVConnection> sslNetVCAllocator;
538
539 //
540 // Inline Functions
541 //
542 inline SNIRoutingType
tunnel_type()543 SSLNetVConnection::tunnel_type() const
544 {
545 return _tunnel_type;
546 }
547
548 /**
549 Returns true if this vc was configured for forward_route or partial_blind_route
550 */
551 inline bool
decrypt_tunnel()552 SSLNetVConnection::decrypt_tunnel() const
553 {
554 return _tunnel_type == SNIRoutingType::FORWARD || _tunnel_type == SNIRoutingType::PARTIAL_BLIND;
555 }
556
557 /**
558 Returns true if this vc was configured partial_blind_route
559 */
560 inline bool
upstream_tls()561 SSLNetVConnection::upstream_tls() const
562 {
563 return _tunnel_type == SNIRoutingType::PARTIAL_BLIND;
564 }
565