1 /** @file
2 
3   @section license License
4 
5   Licensed to the Apache Software Foundation (ASF) under one
6   or more contributor license agreements.  See the NOTICE file
7   distributed with this work for additional information
8   regarding copyright ownership.  The ASF licenses this file
9   to you under the Apache License, Version 2.0 (the
10   "License"); you may not use this file except in compliance
11   with the License.  You may obtain a copy of the License at
12 
13       http://www.apache.org/licenses/LICENSE-2.0
14 
15   Unless required by applicable law or agreed to in writing, software
16   distributed under the License is distributed on an "AS IS" BASIS,
17   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   See the License for the specific language governing permissions and
19   limitations under the License.
20  */
21 
22 #include "P_SSLUtils.h"
23 
24 #include "tscpp/util/TextView.h"
25 #include "tscore/ink_config.h"
26 #include "tscore/ink_platform.h"
27 #include "tscore/SimpleTokenizer.h"
28 #include "tscore/I_Layout.h"
29 #include "tscore/ink_cap.h"
30 #include "tscore/ink_mutex.h"
31 #include "tscore/Filenames.h"
32 #include "records/I_RecHttp.h"
33 #include "tscore/ts_file.h"
34 
35 #include "P_Net.h"
36 #include "InkAPIInternal.h"
37 
38 #include "P_OCSPStapling.h"
39 #include "P_SSLSNI.h"
40 #include "P_SSLConfig.h"
41 #include "SSLSessionCache.h"
42 #include "SSLSessionTicket.h"
43 #include "SSLDynlock.h"
44 #include "SSLDiags.h"
45 #include "SSLStats.h"
46 
47 #include <string>
48 #include <unistd.h>
49 #include <termios.h>
50 #include <vector>
51 
52 #include <openssl/asn1.h>
53 #include <openssl/bio.h>
54 #include <openssl/bn.h>
55 #include <openssl/conf.h>
56 #include <openssl/dh.h>
57 #include <openssl/ec.h>
58 #include <openssl/engine.h>
59 #include <openssl/err.h>
60 #include <openssl/evp.h>
61 #include <openssl/pem.h>
62 #include <openssl/rand.h>
63 #include <openssl/x509.h>
64 #include <openssl/x509v3.h>
65 
66 #if HAVE_OPENSSL_TS_H
67 #include <openssl/ts.h>
68 #endif
69 
70 using namespace std::literals;
71 
72 // ssl_multicert.config field names:
73 static constexpr std::string_view SSL_IP_TAG("dest_ip"sv);
74 static constexpr std::string_view SSL_CERT_TAG("ssl_cert_name"sv);
75 static constexpr std::string_view SSL_PRIVATE_KEY_TAG("ssl_key_name"sv);
76 static constexpr std::string_view SSL_OCSP_RESPONSE_TAG("ssl_ocsp_name"sv);
77 static constexpr std::string_view SSL_CA_TAG("ssl_ca_name"sv);
78 static constexpr std::string_view SSL_ACTION_TAG("action"sv);
79 static constexpr std::string_view SSL_ACTION_TUNNEL_TAG("tunnel"sv);
80 static constexpr std::string_view SSL_SESSION_TICKET_ENABLED("ssl_ticket_enabled"sv);
81 static constexpr std::string_view SSL_SESSION_TICKET_NUMBER("ssl_ticket_number"sv);
82 static constexpr std::string_view SSL_KEY_DIALOG("ssl_key_dialog"sv);
83 static constexpr std::string_view SSL_SERVERNAME("dest_fqdn"sv);
84 static constexpr char SSL_CERT_SEPARATE_DELIM = ',';
85 
86 #ifndef evp_md_func
87 #ifdef OPENSSL_NO_SHA256
88 #define evp_md_func EVP_sha1()
89 #else
90 #define evp_md_func EVP_sha256()
91 #endif
92 #endif
93 
94 SSLSessionCache *session_cache; // declared extern in P_SSLConfig.h
95 
96 static int ssl_vc_index = -1;
97 
98 static ink_mutex *mutex_buf      = nullptr;
99 static bool open_ssl_initialized = false;
100 
101 /* Using pthread thread ID and mutex functions directly, instead of
102  * ATS this_ethread / ProxyMutex, so that other linked libraries
103  * may use pthreads and openssl without confusing us here. (TS-2271).
104  */
105 
106 #if !defined(CRYPTO_THREADID_set_callback)
107 static void
SSL_pthreads_thread_id(CRYPTO_THREADID * id)108 SSL_pthreads_thread_id(CRYPTO_THREADID *id)
109 {
110   CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self());
111 }
112 #endif
113 
114 // The locking callback goes away with openssl 1.1 and CRYPTO_LOCK is on longer defined
115 #if defined(CRYPTO_LOCK) && !defined(CRYPTO_set_locking_callback)
116 static void
SSL_locking_callback(int mode,int type,const char * file,int line)117 SSL_locking_callback(int mode, int type, const char *file, int line)
118 {
119   Debug("v_ssl_lock", "file: %s line: %d type: %d", file, line, type);
120   ink_assert(type < CRYPTO_num_locks());
121 
122 #ifdef OPENSSL_FIPS
123   // don't need to lock for FIPS if it has POSTed and we are not going to change the mode on the fly
124   if (type == CRYPTO_LOCK_FIPS || type == CRYPTO_LOCK_FIPS2) {
125     return;
126   }
127 #endif
128 
129   if (mode & CRYPTO_LOCK) {
130     ink_mutex_acquire(&mutex_buf[type]);
131   } else if (mode & CRYPTO_UNLOCK) {
132     ink_mutex_release(&mutex_buf[type]);
133   } else {
134     Debug("ssl", "invalid SSL locking mode 0x%x", mode);
135     ink_assert(0);
136   }
137 }
138 #endif
139 
140 static bool
SSL_CTX_add_extra_chain_cert_bio(SSL_CTX * ctx,BIO * bio)141 SSL_CTX_add_extra_chain_cert_bio(SSL_CTX *ctx, BIO *bio)
142 {
143   X509 *cert;
144 
145   for (;;) {
146     cert = PEM_read_bio_X509_AUX(bio, nullptr, nullptr, nullptr);
147 
148     if (!cert) {
149       // No more the certificates in this file.
150       break;
151     }
152 
153 // This transfers ownership of the cert (X509) to the SSL context, if successful.
154 #ifdef SSL_CTX_add0_chain_cert
155     if (!SSL_CTX_add0_chain_cert(ctx, cert)) {
156 #else
157     if (!SSL_CTX_add_extra_chain_cert(ctx, cert)) {
158 #endif
159       X509_free(cert);
160       return false;
161     }
162   }
163 
164   return true;
165 }
166 
167 static bool
168 SSL_CTX_add_extra_chain_cert_file(SSL_CTX *ctx, const char *chainfile)
169 {
170   scoped_BIO bio(BIO_new_file(chainfile, "r"));
171   return SSL_CTX_add_extra_chain_cert_bio(ctx, bio);
172 }
173 
174 static SSL_SESSION *
175 #if OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20900000L)
176 ssl_get_cached_session(SSL *ssl, unsigned char *id, int len, int *copy)
177 #else
178 ssl_get_cached_session(SSL *ssl, const unsigned char *id, int len, int *copy)
179 #endif
180 {
181   TLSSessionResumptionSupport *srs = TLSSessionResumptionSupport::getInstance(ssl);
182 
183   ink_assert(srs);
184   if (srs) {
185     return srs->getSession(ssl, id, len, copy);
186   }
187 
188   return nullptr;
189 }
190 
191 static int
192 ssl_new_cached_session(SSL *ssl, SSL_SESSION *sess)
193 {
194 #ifdef TLS1_3_VERSION
195   if (SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION) {
196     return 0;
197   }
198 #endif
199 
200   unsigned int len        = 0;
201   const unsigned char *id = SSL_SESSION_get_id(sess, &len);
202 
203   SSLSessionID sid(id, len);
204 
205   if (diags->tag_activated("ssl.session_cache")) {
206     char printable_buf[(len * 2) + 1];
207 
208     sid.toString(printable_buf, sizeof(printable_buf));
209     Debug("ssl.session_cache.insert", "ssl_new_cached_session session '%s' and context %p", printable_buf, SSL_get_SSL_CTX(ssl));
210   }
211 
212   SSL_INCREMENT_DYN_STAT(ssl_session_cache_new_session);
213   session_cache->insertSession(sid, sess, ssl);
214 
215   // Call hook after new session is created
216   APIHook *hook = ssl_hooks->get(TSSslHookInternalID(TS_SSL_SESSION_HOOK));
217   while (hook) {
218     hook->invoke(TS_EVENT_SSL_SESSION_NEW, &sid);
219     hook = hook->m_link.next;
220   }
221 
222   return 0;
223 }
224 
225 static void
226 ssl_rm_cached_session(SSL_CTX *ctx, SSL_SESSION *sess)
227 {
228 #ifdef TLS1_3_VERSION
229   if (SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION) {
230     return;
231   }
232 #endif
233 
234   unsigned int len        = 0;
235   const unsigned char *id = SSL_SESSION_get_id(sess, &len);
236   SSLSessionID sid(id, len);
237 
238   // Call hook before session is removed
239   APIHook *hook = ssl_hooks->get(TSSslHookInternalID(TS_SSL_SESSION_HOOK));
240   while (hook) {
241     hook->invoke(TS_EVENT_SSL_SESSION_REMOVE, &sid);
242     hook = hook->m_link.next;
243   }
244 
245   if (diags->tag_activated("ssl.session_cache")) {
246     char printable_buf[(len * 2) + 1];
247     sid.toString(printable_buf, sizeof(printable_buf));
248     Debug("ssl.session_cache.remove", "ssl_rm_cached_session cached session '%s'", printable_buf);
249   }
250 
251   session_cache->removeSession(sid);
252 }
253 
254 static int
255 set_context_cert(SSL *ssl)
256 {
257   shared_SSL_CTX ctx  = nullptr;
258   SSL_CTX *verify_ctx = nullptr;
259   SSLCertContext *cc  = nullptr;
260   SSLCertificateConfig::scoped_config lookup;
261   const char *servername   = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
262   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
263   bool found               = true;
264   int retval               = 1;
265 
266   if (!netvc || netvc->ssl != ssl) {
267     Debug("ssl.error", "set_context_cert call back on stale netvc");
268     retval = 0; // Error
269     goto done;
270   }
271 
272   Debug("ssl", "set_context_cert ssl=%p server=%s handshake_complete=%d", ssl, servername, netvc->getSSLHandShakeComplete());
273 
274   // catch the client renegotiation early on
275   if (SSLConfigParams::ssl_allow_client_renegotiation == false && netvc->getSSLHandShakeComplete()) {
276     Debug("ssl", "set_context_cert trying to renegotiate from the client");
277     retval = 0; // Error
278     goto done;
279   }
280 
281   // The incoming SSL_CTX is either the one mapped from the inbound IP address or the default one. If we
282   // don't find a name-based match at this point, we *do not* want to mess with the context because we've
283   // already made a best effort to find the best match.
284   if (likely(servername)) {
285     cc = lookup->find(const_cast<char *>(servername));
286     if (cc) {
287       ctx = cc->getCtx();
288     }
289     if (cc && ctx && SSLCertContextOption::OPT_TUNNEL == cc->opt && netvc->get_is_transparent()) {
290       netvc->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL;
291       netvc->setSSLHandShakeComplete(SSL_HANDSHAKE_DONE);
292       retval = -1;
293       goto done;
294     }
295   }
296 
297   // If there's no match on the server name, try to match on the peer address.
298   if (ctx == nullptr) {
299     IpEndpoint ip;
300     int namelen = sizeof(ip);
301 
302     if (0 == safe_getsockname(netvc->get_socket(), &ip.sa, &namelen)) {
303       cc = lookup->find(ip);
304     }
305     if (cc) {
306       ctx = cc->getCtx();
307     }
308   }
309 
310   if (ctx != nullptr) {
311     SSL_set_SSL_CTX(ssl, ctx.get());
312 #if TS_HAS_TLS_SESSION_TICKET
313     // Reset the ticket callback if needed
314 #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
315     SSL_CTX_set_tlsext_ticket_key_evp_cb(ctx.get(), ssl_callback_session_ticket);
316 #else
317     SSL_CTX_set_tlsext_ticket_key_cb(ctx.get(), ssl_callback_session_ticket);
318 #endif
319 #endif
320     // After replacing the SSL_CTX, make sure the overridden ca_cert_file is still set
321     setClientCertCACerts(ssl, netvc->get_ca_cert_file(), netvc->get_ca_cert_dir());
322   } else {
323     found = false;
324   }
325 
326   verify_ctx = SSL_get_SSL_CTX(ssl);
327   Debug("ssl", "ssl_cert_callback %s SSL context %p for requested name '%s'", found ? "found" : "using", verify_ctx, servername);
328 
329   if (verify_ctx == nullptr) {
330     retval = 0;
331     goto done;
332   }
333 done:
334   return retval;
335 }
336 
337 // Callback function for verifying client certificate
338 static int
339 ssl_verify_client_callback(int preverify_ok, X509_STORE_CTX *ctx)
340 {
341   Debug("ssl", "Callback: verify client cert");
342   auto *ssl                = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
343   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
344 
345   if (!netvc || netvc->ssl != ssl) {
346     Debug("ssl.error", "ssl_verify_client_callback call back on stale netvc");
347     return false;
348   }
349 
350   netvc->set_verify_cert(ctx);
351   netvc->callHooks(TS_EVENT_SSL_VERIFY_CLIENT);
352   netvc->set_verify_cert(nullptr);
353 
354   if (netvc->getSSLHandShakeComplete()) { // hook moved the handshake state to terminal
355     Warning("TS_EVENT_SSL_VERIFY_CLIENT plugin failed the client certificate check for %s.", netvc->options.sni_servername.get());
356     return false;
357   }
358 
359   return preverify_ok;
360 }
361 
362 #if TS_USE_HELLO_CB
363 // Pausable callback
364 static int
365 ssl_client_hello_callback(SSL *s, int *al, void *arg)
366 {
367   TLSSNISupport *snis = TLSSNISupport::getInstance(s);
368   if (snis) {
369     snis->on_client_hello(s, al, arg);
370     int ret = snis->perform_sni_action();
371     if (ret != SSL_TLSEXT_ERR_OK) {
372       return SSL_CLIENT_HELLO_ERROR;
373     }
374   } else {
375     // This error suggests either of these:
376     // 1) Call back on unsupported netvc -- Don't register callback unnecessarily
377     // 2) Call back on stale netvc
378     Debug("ssl.error", "ssl_client_hello_callback was called unexpectedly");
379     return SSL_CLIENT_HELLO_ERROR;
380   }
381 
382   SSLNetVConnection *netvc = SSLNetVCAccess(s);
383   if (!netvc || netvc->ssl != s) {
384     Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc");
385     return SSL_CLIENT_HELLO_ERROR;
386   }
387 
388   bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO);
389 
390   if (!reenabled) {
391     return SSL_CLIENT_HELLO_RETRY;
392   }
393   return SSL_CLIENT_HELLO_SUCCESS;
394 }
395 #endif
396 
397 /**
398  * Called before either the server or the client certificate is used
399  * Return 1 on success, 0 on error, or -1 to pause
400  */
401 static int
402 ssl_cert_callback(SSL *ssl, void * /*arg*/)
403 {
404   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
405   bool reenabled;
406   int retval = 1;
407 
408   if (!netvc || netvc->ssl != ssl) {
409     Debug("ssl.error", "ssl_cert_callback call back on stale netvc");
410     return 0;
411   }
412 
413   // If we are in tunnel mode, don't select a cert.  Pause!
414   if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == netvc->attributes) {
415     return -1; // Pause
416   }
417 
418   // Do the common certificate lookup only once.  If we pause
419   // and restart processing, do not execute the common logic again
420   if (!netvc->calledHooks(TS_EVENT_SSL_CERT)) {
421     retval = set_context_cert(ssl);
422     if (retval != 1) {
423       return retval;
424     }
425   }
426 
427   // Call the plugin cert code
428   reenabled = netvc->callHooks(TS_EVENT_SSL_CERT);
429   // If it did not re-enable, return the code to
430   // stop the accept processing
431   if (!reenabled) {
432     retval = -1; // Pause
433   }
434 
435   // Return 1 for success, 0 for error, or -1 to pause
436   return retval;
437 }
438 
439 /*
440  * Cannot stop this callback. Always reeneabled
441  */
442 static int
443 ssl_servername_callback(SSL *ssl, int *al, void *arg)
444 {
445   TLSSNISupport *snis = TLSSNISupport::getInstance(ssl);
446   if (snis) {
447     snis->on_servername(ssl, al, arg);
448 #if !TS_USE_HELLO_CB
449     // Only call the SNI actions here if not already performed in the HELLO_CB
450     int ret = snis->perform_sni_action();
451     if (ret != SSL_TLSEXT_ERR_OK) {
452       return SSL_TLSEXT_ERR_ALERT_FATAL;
453     }
454 #endif
455   } else {
456     // This error suggests either of these:
457     // 1) Call back on unsupported netvc -- Don't register callback unnecessarily
458     // 2) Call back on stale netvc
459     Debug("ssl.error", "ssl_servername_callback was called unexpectedly");
460     return SSL_TLSEXT_ERR_ALERT_FATAL;
461   }
462 
463   return SSL_TLSEXT_ERR_OK;
464 }
465 
466 #if TS_USE_GET_DH_2048_256 == 0
467 /* Build 2048-bit MODP Group with 256-bit Prime Order Subgroup from RFC 5114 */
468 static DH *
469 DH_get_2048_256()
470 {
471   static const unsigned char dh2048_p[] = {
472     0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C, 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99, 0x8C, 0xEE, 0xF6, 0x08,
473     0x66, 0x0D, 0xD0, 0xF2, 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00, 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4,
474     0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30, 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA, 0x3B, 0xF4, 0x29, 0x6D,
475     0x83, 0x0E, 0x9A, 0x7C, 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD, 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED,
476     0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0, 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B, 0x6C, 0x5B, 0xFC, 0x11,
477     0xD4, 0x5F, 0x90, 0x88, 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8, 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C,
478     0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76, 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90, 0x2D, 0x52, 0x52, 0x67,
479     0x35, 0x48, 0x8A, 0x0E, 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB, 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E,
480     0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9, 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25, 0x1C, 0xCA, 0xCB, 0x83,
481     0xE6, 0xB4, 0x86, 0xF6, 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26, 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56,
482     0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21, 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3, 0x75, 0xF2, 0x63, 0x75,
483     0xD7, 0x01, 0x41, 0x03, 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12, 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F,
484     0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA, 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97};
485   static const unsigned char dh2048_g[] = {
486     0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, 0x4C, 0xA7, 0xB1, 0x8F,
487     0x21, 0xEF, 0x20, 0x54, 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F,
488     0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, 0xBC, 0x37, 0x73, 0xBF,
489     0x7E, 0x8C, 0x6F, 0x62, 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65,
490     0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, 0x77, 0x7D, 0xE6, 0x2A,
491     0xAA, 0xB8, 0xA8, 0x62, 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83,
492     0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, 0xDF, 0xC9, 0x67, 0xC1,
493     0xFB, 0x3F, 0x2E, 0x55, 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A,
494     0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, 0xB7, 0xD2, 0xBB, 0xD2,
495     0xDF, 0x01, 0x61, 0x99, 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37,
496     0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, 0x18, 0x4B, 0x52, 0x3D,
497     0x1D, 0xB2, 0x46, 0xC3, 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51,
498     0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59};
499   DH *dh;
500 
501   if ((dh = DH_new()) == nullptr)
502     return (nullptr);
503   dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), nullptr);
504   dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), nullptr);
505   if ((dh->p == nullptr) || (dh->g == nullptr)) {
506     DH_free(dh);
507     return (nullptr);
508   }
509   return (dh);
510 }
511 #endif
512 
513 static SSL_CTX *
514 ssl_context_enable_dhe(const char *dhparams_file, SSL_CTX *ctx)
515 {
516   DH *server_dh;
517 
518   if (dhparams_file) {
519     scoped_BIO bio(BIO_new_file(dhparams_file, "r"));
520     server_dh = PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr);
521   } else {
522     server_dh = DH_get_2048_256();
523   }
524 
525   if (!server_dh) {
526     Error("SSL dhparams source returned invalid parameters");
527     return nullptr;
528   }
529 
530   if (!SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE) || !SSL_CTX_set_tmp_dh(ctx, server_dh)) {
531     DH_free(server_dh);
532     Error("failed to configure SSL DH");
533     return nullptr;
534   }
535 
536   DH_free(server_dh);
537 
538   return ctx;
539 }
540 
541 // SSL_CTX_set_ecdh_auto() is removed by OpenSSL v1.1.0 and ECDH is enabled in default.
542 // TODO: remove this function when we drop support of OpenSSL v1.0.2* and lower.
543 static SSL_CTX *
544 ssl_context_enable_ecdh(SSL_CTX *ctx)
545 {
546 #if OPENSSL_VERSION_NUMBER < 0x10100000
547 
548 #if defined(SSL_CTX_set_ecdh_auto)
549   SSL_CTX_set_ecdh_auto(ctx, 1);
550 #elif defined(NID_X9_62_prime256v1)
551   EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
552 
553   if (ecdh) {
554     SSL_CTX_set_tmp_ecdh(ctx, ecdh);
555     EC_KEY_free(ecdh);
556   }
557 #endif /* SSL_CTRL_SET_ECDH_AUTO */
558 #endif /* OPENSSL_VERSION_NUMBER */
559 
560   return ctx;
561 }
562 
563 static ssl_ticket_key_block *
564 ssl_context_enable_tickets(SSL_CTX *ctx, const char *ticket_key_path)
565 {
566 #if TS_HAS_TLS_SESSION_TICKET
567   ssl_ticket_key_block *keyblock = nullptr;
568 
569   keyblock = ssl_create_ticket_keyblock(ticket_key_path);
570 
571   // Increase the stats.
572   if (ssl_rsb != nullptr) { // ssl_rsb is not initialized during the first run.
573     SSL_INCREMENT_DYN_STAT(ssl_total_ticket_keys_renewed_stat);
574   }
575 
576   // Setting the callback can only fail if OpenSSL does not recognize the
577   // SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB constant. we set the callback first
578   // so that we don't leave a ticket_key pointer attached if it fails.
579   if (SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_callback_session_ticket) == 0) {
580     Error("failed to set session ticket callback");
581     ticket_block_free(keyblock);
582     return nullptr;
583   }
584 
585   SSL_CTX_clear_options(ctx, SSL_OP_NO_TICKET);
586   return keyblock;
587 
588 #else  /* !TS_HAS_TLS_SESSION_TICKET */
589   (void)ticket_key_path;
590   return nullptr;
591 #endif /* TS_HAS_TLS_SESSION_TICKET */
592 }
593 
594 struct passphrase_cb_userdata {
595   const SSLConfigParams *_configParams;
596   const char *_serverDialog;
597   const char *_serverCert;
598   const char *_serverKey;
599 
600   passphrase_cb_userdata(const SSLConfigParams *params, const char *dialog, const char *cert, const char *key)
601     : _configParams(params), _serverDialog(dialog), _serverCert(cert), _serverKey(key)
602   {
603   }
604 };
605 
606 // RAII implementation for struct termios
607 struct ssl_termios : public termios {
608   ssl_termios(int fd)
609   {
610     _fd = -1;
611     // populate base class data
612     if (tcgetattr(fd, this) == 0) { // success
613       _fd = fd;
614     }
615     // save our copy
616     _initialAttr = *this;
617   }
618 
619   ~ssl_termios()
620   {
621     if (_fd != -1) {
622       tcsetattr(_fd, 0, &_initialAttr);
623     }
624   }
625 
626   bool
627   ok() const
628   {
629     return (_fd != -1);
630   }
631 
632 private:
633   int _fd;
634   struct termios _initialAttr;
635 };
636 
637 static int
638 ssl_getpassword(const char *prompt, char *buffer, int size)
639 {
640   fprintf(stdout, "%s", prompt);
641 
642   // disable echo and line buffering
643   ssl_termios tty_attr(STDIN_FILENO);
644 
645   if (!tty_attr.ok()) {
646     return -1;
647   }
648 
649   tty_attr.c_lflag &= ~ICANON; // no buffer, no backspace
650   tty_attr.c_lflag &= ~ECHO;   // no echo
651   tty_attr.c_lflag &= ~ISIG;   // no signal for ctrl-c
652 
653   if (tcsetattr(STDIN_FILENO, 0, &tty_attr) < 0) {
654     return -1;
655   }
656 
657   int i  = 0;
658   int ch = 0;
659 
660   *buffer = 0;
661   while ((ch = getchar()) != '\n' && ch != EOF) {
662     // make sure room in buffer
663     if (i >= size - 1) {
664       return -1;
665     }
666 
667     buffer[i]   = ch;
668     buffer[++i] = 0;
669   }
670 
671   return i;
672 }
673 
674 static int
675 ssl_private_key_passphrase_callback_exec(char *buf, int size, int rwflag, void *userdata)
676 {
677   if (0 == size) {
678     return 0;
679   }
680 
681   *buf                       = 0;
682   passphrase_cb_userdata *ud = static_cast<passphrase_cb_userdata *>(userdata);
683 
684   Debug("ssl", "ssl_private_key_passphrase_callback_exec rwflag=%d serverDialog=%s", rwflag, ud->_serverDialog);
685 
686   // only respond to reading private keys, not writing them (does ats even do that?)
687   if (0 == rwflag) {
688     // execute the dialog program and use the first line output as the passphrase
689     FILE *f = popen(ud->_serverDialog, "r");
690     if (f) {
691       if (fgets(buf, size, f)) {
692         // remove any ending CR or LF
693         for (char *pass = buf; *pass; pass++) {
694           if (*pass == '\n' || *pass == '\r') {
695             *pass = 0;
696             break;
697           }
698         }
699       }
700       pclose(f);
701     } else { // popen failed
702       Error("could not open dialog '%s' - %s", ud->_serverDialog, strerror(errno));
703     }
704   }
705   return strlen(buf);
706 }
707 
708 static int
709 ssl_private_key_passphrase_callback_builtin(char *buf, int size, int rwflag, void *userdata)
710 {
711   if (0 == size) {
712     return 0;
713   }
714 
715   *buf                       = 0;
716   passphrase_cb_userdata *ud = static_cast<passphrase_cb_userdata *>(userdata);
717 
718   Debug("ssl", "ssl_private_key_passphrase_callback rwflag=%d serverDialog=%s", rwflag, ud->_serverDialog);
719 
720   // only respond to reading private keys, not writing them (does ats even do that?)
721   if (0 == rwflag) {
722     // output request
723     fprintf(stdout, "Some of your private key files are encrypted for security reasons.\n");
724     fprintf(stdout, "In order to read them you have to provide the pass phrases.\n");
725     fprintf(stdout, "ssl_cert_name=%s", ud->_serverCert);
726     if (ud->_serverKey) { // output ssl_key_name if provided
727       fprintf(stdout, " ssl_key_name=%s", ud->_serverKey);
728     }
729     fprintf(stdout, "\n");
730     // get passphrase
731     // if error, then no passphrase
732     if (ssl_getpassword("Enter passphrase:", buf, size) <= 0) {
733       *buf = 0;
734     }
735     fprintf(stdout, "\n");
736   }
737   return strlen(buf);
738 }
739 
740 static bool
741 ssl_private_key_validate_exec(const char *cmdLine)
742 {
743   if (nullptr == cmdLine) {
744     errno = EINVAL;
745     return false;
746   }
747 
748   bool bReturn      = false;
749   char *cmdLineCopy = ats_strdup(cmdLine);
750   char *ptr         = cmdLineCopy;
751 
752   while (*ptr && !isspace(*ptr)) {
753     ++ptr;
754   }
755   *ptr = 0;
756   if (access(cmdLineCopy, X_OK) != -1) {
757     bReturn = true;
758   }
759   ats_free(cmdLineCopy);
760   return bReturn;
761 }
762 
763 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
764 #define ssl_malloc(size, file, line) ssl_malloc(size)
765 #define ssl_realloc(ptr, size, file, line) ssl_realloc(ptr, size)
766 #define ssl_free(ptr, file, line) ssl_free(ptr)
767 #define ssl_track_malloc(size, file, line) ssl_track_malloc(size)
768 #define ssl_track_realloc(ptr, size, file, line) ssl_track_realloc(ptr, size)
769 #define ssl_track_free(ptr, file, line) ssl_track_free(ptr)
770 #endif
771 
772 void *
773 ssl_malloc(size_t size, const char * /*filename */, int /*lineno*/)
774 {
775   return ats_malloc(size);
776 }
777 
778 void *
779 ssl_realloc(void *ptr, size_t size, const char * /*filename*/, int /*lineno*/)
780 {
781   return ats_realloc(ptr, size);
782 }
783 
784 void
785 ssl_free(void *ptr, const char * /*filename*/, int /*lineno*/)
786 {
787   ats_free(ptr);
788 }
789 
790 void *
791 ssl_track_malloc(size_t size, const char * /*filename*/, int /*lineno*/)
792 {
793   return ats_track_malloc(size, &ssl_memory_allocated);
794 }
795 
796 void *
797 ssl_track_realloc(void *ptr, size_t size, const char * /*filename*/, int /*lineno*/)
798 {
799   return ats_track_realloc(ptr, size, &ssl_memory_allocated, &ssl_memory_freed);
800 }
801 
802 void
803 ssl_track_free(void *ptr, const char * /*filename*/, int /*lineno*/)
804 {
805   ats_track_free(ptr, &ssl_memory_freed);
806 }
807 
808 /*
809  * Some items are only initialized if certain config values are set
810  * Must have a second pass that initializes after loading the SSL config
811  */
812 void
813 SSLPostConfigInitialize()
814 {
815   if (SSLConfigParams::engine_conf_file) {
816 #ifndef OPENSSL_IS_BORINGSSL
817     ENGINE_load_dynamic();
818 #endif
819 
820     OPENSSL_load_builtin_modules();
821     if (CONF_modules_load_file(SSLConfigParams::engine_conf_file, nullptr, 0) <= 0) {
822       Error("FATAL: error loading engine configuration file %s", SSLConfigParams::engine_conf_file);
823       // ERR_print_errors_fp(stderr);
824     }
825   }
826 }
827 
828 void
829 SSLInitializeLibrary()
830 {
831   if (!open_ssl_initialized) {
832 // BoringSSL does not have the memory functions
833 #ifdef HAVE_CRYPTO_SET_MEM_FUNCTIONS
834     if (res_track_memory >= 2) {
835       CRYPTO_set_mem_functions(ssl_track_malloc, ssl_track_realloc, ssl_track_free);
836     } else {
837       CRYPTO_set_mem_functions(ssl_malloc, ssl_realloc, ssl_free);
838     }
839 #endif
840 
841     SSL_load_error_strings();
842     SSL_library_init();
843 
844 #ifdef OPENSSL_FIPS
845     // calling FIPS_mode_set() will force FIPS to POST (Power On Self Test)
846     // After POST we don't have to lock for FIPS
847     int mode = FIPS_mode();
848     FIPS_mode_set(mode);
849     Debug("ssl", "FIPS_mode: %d", mode);
850 #endif
851 
852     mutex_buf = static_cast<ink_mutex *>(OPENSSL_malloc(CRYPTO_num_locks() * sizeof(ink_mutex)));
853 
854     for (int i = 0; i < CRYPTO_num_locks(); i++) {
855       ink_mutex_init(&mutex_buf[i]);
856     }
857 
858     CRYPTO_set_locking_callback(SSL_locking_callback);
859 #if !defined(CRYPTO_THREADID_set_callback)
860     CRYPTO_THREADID_set_callback(SSL_pthreads_thread_id);
861 #endif
862     CRYPTO_set_dynlock_create_callback(ssl_dyn_create_callback);
863     CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock_callback);
864     CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy_callback);
865   }
866 
867 #if TS_USE_TLS_OCSP
868   ssl_stapling_ex_init();
869 #endif /* TS_USE_TLS_OCSP */
870 
871   // Reserve an application data index so that we can attach
872   // the SSLNetVConnection to the SSL session.
873   ssl_vc_index = SSL_get_ex_new_index(0, (void *)"NetVC index", nullptr, nullptr, nullptr);
874 
875   TLSSessionResumptionSupport::initialize();
876   TLSSNISupport::initialize();
877 
878   open_ssl_initialized = true;
879 }
880 
881 SSL_CTX *
882 SSLMultiCertConfigLoader::default_server_ssl_ctx()
883 {
884   return SSL_CTX_new(SSLv23_server_method());
885 }
886 
887 static bool
888 SSLPrivateKeyHandler(SSL_CTX *ctx, const SSLConfigParams *params, const std::string &completeServerCertPath, const char *keyPath)
889 {
890   EVP_PKEY *pkey = nullptr;
891 #ifndef OPENSSL_IS_BORINGSSL
892   ENGINE *e = ENGINE_get_default_RSA();
893   if (e != nullptr) {
894     ats_scoped_str argkey;
895     if (keyPath == nullptr || keyPath[0] == '\0') {
896       argkey = completeServerCertPath.c_str();
897     } else {
898       argkey = Layout::get()->relative_to(params->serverKeyPathOnly, keyPath);
899     }
900     pkey = ENGINE_load_private_key(e, argkey.get(), nullptr, nullptr);
901     if (pkey) {
902       if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
903         SSLError("failed to load server private key from engine");
904         return false;
905       }
906     }
907   }
908 #endif
909   if (pkey == nullptr) {
910     if (!keyPath || keyPath[0] == '\0') {
911       // assume private key is contained in cert obtained from multicert file.
912       if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerCertPath.c_str(), SSL_FILETYPE_PEM)) {
913         SSLError("failed to load server private key from %s", completeServerCertPath.c_str());
914         return false;
915       }
916     } else if (params->serverKeyPathOnly != nullptr) {
917       ats_scoped_str completeServerKeyPath(Layout::get()->relative_to(params->serverKeyPathOnly, keyPath));
918       if (!SSL_CTX_use_PrivateKey_file(ctx, completeServerKeyPath, SSL_FILETYPE_PEM)) {
919         SSLError("failed to load server private key from %s", (const char *)completeServerKeyPath);
920         return false;
921       }
922       if (SSLConfigParams::load_ssl_file_cb) {
923         SSLConfigParams::load_ssl_file_cb(completeServerKeyPath);
924       }
925     } else {
926       SSLError("empty SSL private key path in %s", ts::filename::RECORDS);
927       return false;
928     }
929     if (!SSL_CTX_check_private_key(ctx)) {
930       SSLError("server private key does not match the certificate public key");
931       return false;
932     }
933   }
934 
935   return true;
936 }
937 
938 /**
939    returns 0 on OK or negative value on failure and update log as appropriate.
940 
941    Will check:
942    - if file exists, and has read permissions
943    - for truncation or other PEM read fail
944    - current time is between notBefore and notAfter dates of certificate
945    if anything is not kosher, a negative value is returned and appropriate error logged.
946 
947    @static
948  */
949 int
950 SSLMultiCertConfigLoader::check_server_cert_now(X509 *cert, const char *certname)
951 {
952   int timeCmpValue;
953 
954   if (!cert) {
955     // a truncated certificate would fall into here
956     Error("invalid certificate %s: file is truncated or corrupted", certname);
957     return -3;
958   }
959 
960   // XXX we should log the notBefore and notAfter dates in the errors ...
961 
962   timeCmpValue = X509_cmp_current_time(X509_get_notBefore(cert));
963   if (timeCmpValue == 0) {
964     // an error occurred parsing the time, which we'll call a bogosity
965     Error("invalid certificate %s: unable to parse notBefore time", certname);
966     return -3;
967   } else if (timeCmpValue > 0) {
968     // cert contains a date before the notBefore
969     Error("invalid certificate %s: notBefore date is in the future", certname);
970     return -4;
971   }
972 
973   timeCmpValue = X509_cmp_current_time(X509_get_notAfter(cert));
974   if (timeCmpValue == 0) {
975     // an error occurred parsing the time, which we'll call a bogosity
976     Error("invalid certificate %s: unable to parse notAfter time", certname);
977     return -3;
978   } else if (timeCmpValue < 0) {
979     // cert is expired
980     Error("invalid certificate %s: certificate expired", certname);
981     return -5;
982   }
983 
984   Debug("ssl", "server certificate %s passed accessibility and date checks", certname);
985   return 0; // all good
986 
987 } /* CheckServerCertNow() */
988 
989 static char *
990 asn1_strdup(ASN1_STRING *s)
991 {
992   // Make sure we have an 8-bit encoding.
993   ink_assert(ASN1_STRING_type(s) == V_ASN1_IA5STRING || ASN1_STRING_type(s) == V_ASN1_UTF8STRING ||
994              ASN1_STRING_type(s) == V_ASN1_PRINTABLESTRING || ASN1_STRING_type(s) == V_ASN1_T61STRING);
995 
996   return ats_strndup((const char *)ASN1_STRING_get0_data(s), ASN1_STRING_length(s));
997 }
998 
999 /**
1000    Given a certificate and it's corresponding SSL_CTX context, insert hash
1001    table aliases for subject CN and subjectAltNames DNS without wildcard,
1002    insert trie aliases for those with wildcard.
1003    @static
1004 */
1005 bool
1006 SSLMultiCertConfigLoader::index_certificate(SSLCertLookup *lookup, SSLCertContext const &cc, const char *sni_name)
1007 {
1008   bool inserted = false;
1009 
1010   Debug("ssl", "mapping '%s'", sni_name);
1011   if (lookup->insert(sni_name, cc) >= 0) {
1012     inserted = true;
1013   }
1014 
1015   return inserted;
1016 }
1017 
1018 // This callback function is executed while OpenSSL processes the SSL
1019 // handshake and does SSL record layer stuff.  It's used to trap
1020 // client-initiated renegotiations and update cipher stats
1021 static void
1022 ssl_callback_info(const SSL *ssl, int where, int ret)
1023 {
1024   Debug("ssl", "ssl_callback_info ssl: %p, where: %d, ret: %d, State: %s", ssl, where, ret, SSL_state_string_long(ssl));
1025 
1026   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
1027 
1028   if (!netvc || netvc->ssl != ssl) {
1029     Debug("ssl.error", "ssl_callback_info call back on stale netvc");
1030     return;
1031   }
1032 
1033   if ((where & SSL_CB_ACCEPT_LOOP) && netvc->getSSLHandShakeComplete() == true &&
1034       SSLConfigParams::ssl_allow_client_renegotiation == false) {
1035     int state = SSL_get_state(ssl);
1036 
1037 // TODO: ifdef can be removed in the future
1038 // Support for SSL23 only if we have it
1039 #ifdef SSL23_ST_SR_CLNT_HELLO_A
1040     if (state == SSL3_ST_SR_CLNT_HELLO_A || state == SSL23_ST_SR_CLNT_HELLO_A) {
1041 #else
1042 #ifdef SSL3_ST_SR_CLNT_HELLO_A
1043     if (state == SSL3_ST_SR_CLNT_HELLO_A) {
1044 #else
1045 #ifdef SSL_ST_RENEGOTIATE
1046     // This is for BoringSSL
1047     if (state == SSL_ST_RENEGOTIATE) {
1048 #else
1049     if (state == TLS_ST_SR_CLNT_HELLO) {
1050 #endif
1051 #endif
1052 #endif
1053 #ifdef TLS1_3_VERSION
1054       // TLSv1.3 has no renegotiation.
1055       if (SSL_version(ssl) >= TLS1_3_VERSION) {
1056         Debug("ssl", "TLSv1.3 has no renegotiation.");
1057         return;
1058       }
1059 #endif
1060       netvc->setSSLClientRenegotiationAbort(true);
1061       Debug("ssl", "ssl_callback_info trying to renegotiate from the client");
1062     }
1063   }
1064   if (where & SSL_CB_HANDSHAKE_DONE) {
1065     // handshake is complete
1066     const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
1067     if (cipher) {
1068       const char *cipherName = SSL_CIPHER_get_name(cipher);
1069       // lookup index of stat by name and incr count
1070       if (auto it = cipher_map.find(cipherName); it != cipher_map.end()) {
1071         SSL_INCREMENT_DYN_STAT((intptr_t)it->second);
1072       }
1073     }
1074   }
1075 }
1076 
1077 void
1078 SSLMultiCertConfigLoader::_set_handshake_callbacks(SSL_CTX *ctx)
1079 {
1080   // Make sure the callbacks are set
1081   SSL_CTX_set_cert_cb(ctx, ssl_cert_callback, nullptr);
1082   SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback);
1083 
1084 #if TS_USE_HELLO_CB
1085   SSL_CTX_set_client_hello_cb(ctx, ssl_client_hello_callback, nullptr);
1086 #endif
1087 }
1088 
1089 void
1090 setClientCertLevel(SSL *ssl, uint8_t certLevel)
1091 {
1092   SSLConfig::scoped_config params;
1093   int server_verify_client = SSL_VERIFY_NONE;
1094 
1095   if (certLevel == 2) {
1096     server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
1097   } else if (certLevel == 1) {
1098     server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
1099   } else if (certLevel == 0) {
1100     server_verify_client = SSL_VERIFY_NONE;
1101   } else {
1102     ink_release_assert(!"Invalid client verify level");
1103   }
1104 
1105   Debug("ssl", "setting cert level to %d", server_verify_client);
1106   SSL_set_verify(ssl, server_verify_client, ssl_verify_client_callback);
1107   SSL_set_verify_depth(ssl, params->verify_depth); // might want to make configurable at some point.
1108 }
1109 
1110 void
1111 setClientCertCACerts(SSL *ssl, const char *file, const char *dir)
1112 {
1113   if ((file != nullptr && file[0] != '\0') || (dir != nullptr && dir[0] != '\0')) {
1114 #if defined(SSL_set1_verify_cert_store)
1115     // The set0 version will take ownership of the X509_STORE object
1116     X509_STORE *ctx = X509_STORE_new();
1117     if (X509_STORE_load_locations(ctx, file && file[0] != '\0' ? file : nullptr, dir && dir[0] != '\0' ? dir : nullptr)) {
1118       SSL_set0_verify_cert_store(ssl, ctx);
1119     }
1120 
1121     // SSL_set_client_CA_list takes ownership of the STACK_OF(X509) structure
1122     // So we load it each time to pass into the SSL object
1123     if (file != nullptr && file[0] != '\0') {
1124       SSL_set_client_CA_list(ssl, SSL_load_client_CA_file(file));
1125     }
1126 #else
1127     ink_assert(!"Configuration checking should prevent reaching this code");
1128 #endif
1129   }
1130 }
1131 
1132 /**
1133    Initialize SSL_CTX for server
1134    This is public function because of used by SSLCreateServerContext.
1135  */
1136 SSL_CTX *
1137 SSLMultiCertConfigLoader::init_server_ssl_ctx(CertLoadData const &data, const SSLMultiCertConfigParams *sslMultCertSettings,
1138                                               std::set<std::string> &names)
1139 {
1140   const SSLConfigParams *params = this->_params;
1141 
1142   int server_verify_client;
1143   SSL_CTX *ctx = this->default_server_ssl_ctx();
1144 
1145   // disable selected protocols
1146   SSL_CTX_set_options(ctx, params->ssl_ctx_options);
1147 
1148   Debug("ssl.session_cache",
1149         "ssl context=%p: using session cache options, enabled=%d, size=%d, num_buckets=%d, "
1150         "skip_on_contention=%d, timeout=%d, auto_clear=%d",
1151         ctx, params->ssl_session_cache, params->ssl_session_cache_size, params->ssl_session_cache_num_buckets,
1152         params->ssl_session_cache_skip_on_contention, params->ssl_session_cache_timeout, params->ssl_session_cache_auto_clear);
1153 
1154   if (params->ssl_session_cache_timeout) {
1155     SSL_CTX_set_timeout(ctx, params->ssl_session_cache_timeout);
1156   }
1157 
1158   int additional_cache_flags = 0;
1159   additional_cache_flags |= (params->ssl_session_cache_auto_clear == 0) ? SSL_SESS_CACHE_NO_AUTO_CLEAR : 0;
1160 
1161   switch (params->ssl_session_cache) {
1162   case SSLConfigParams::SSL_SESSION_CACHE_MODE_OFF:
1163     Debug("ssl.session_cache", "disabling SSL session cache");
1164 
1165     SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF | SSL_SESS_CACHE_NO_INTERNAL);
1166     break;
1167   case SSLConfigParams::SSL_SESSION_CACHE_MODE_SERVER_OPENSSL_IMPL:
1168     Debug("ssl.session_cache", "enabling SSL session cache with OpenSSL implementation");
1169 
1170     SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | additional_cache_flags);
1171     SSL_CTX_sess_set_cache_size(ctx, params->ssl_session_cache_size);
1172     break;
1173   case SSLConfigParams::SSL_SESSION_CACHE_MODE_SERVER_ATS_IMPL: {
1174     Debug("ssl.session_cache", "enabling SSL session cache with ATS implementation");
1175     /* Add all the OpenSSL callbacks */
1176     SSL_CTX_sess_set_new_cb(ctx, ssl_new_cached_session);
1177     SSL_CTX_sess_set_remove_cb(ctx, ssl_rm_cached_session);
1178     SSL_CTX_sess_set_get_cb(ctx, ssl_get_cached_session);
1179 
1180     SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL | additional_cache_flags);
1181     break;
1182   }
1183   }
1184 
1185 #ifdef SSL_MODE_RELEASE_BUFFERS
1186   Debug("ssl", "enabling SSL_MODE_RELEASE_BUFFERS");
1187   SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
1188 #endif
1189 
1190 #ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG
1191   SSL_CTX_set_options(ctx, SSL_OP_SAFARI_ECDHE_ECDSA_BUG);
1192 #endif
1193 
1194   if (sslMultCertSettings) {
1195     if (sslMultCertSettings->dialog) {
1196       passphrase_cb_userdata ud(params, sslMultCertSettings->dialog, sslMultCertSettings->first_cert, sslMultCertSettings->key);
1197       // pass phrase dialog configuration
1198       pem_password_cb *passwd_cb = nullptr;
1199       if (strncmp(sslMultCertSettings->dialog, "exec:", 5) == 0) {
1200         ud._serverDialog = &sslMultCertSettings->dialog[5];
1201         // validate the exec program
1202         if (!ssl_private_key_validate_exec(ud._serverDialog)) {
1203           SSLError("failed to access '%s' pass phrase program: %s", (const char *)ud._serverDialog, strerror(errno));
1204           memset(static_cast<void *>(&ud), 0, sizeof(ud));
1205           goto fail;
1206         }
1207         passwd_cb = ssl_private_key_passphrase_callback_exec;
1208       } else if (strcmp(sslMultCertSettings->dialog, "builtin") == 0) {
1209         passwd_cb = ssl_private_key_passphrase_callback_builtin;
1210       } else { // unknown config
1211         SSLError("unknown %s configuration value '%s'", SSL_KEY_DIALOG.data(), (const char *)sslMultCertSettings->dialog);
1212         memset(static_cast<void *>(&ud), 0, sizeof(ud));
1213         goto fail;
1214       }
1215       SSL_CTX_set_default_passwd_cb(ctx, passwd_cb);
1216       SSL_CTX_set_default_passwd_cb_userdata(ctx, &ud);
1217       // Clear any password info lingering in the UD data structure
1218       memset(static_cast<void *>(&ud), 0, sizeof(ud));
1219     }
1220 
1221     if (sslMultCertSettings->cert) {
1222       if (!SSLMultiCertConfigLoader::load_certs(ctx, data, params, sslMultCertSettings)) {
1223         goto fail;
1224       }
1225     }
1226 
1227     // SSL_CTX_load_verify_locations() builds the cert chain from the
1228     // serverCACertFilename if that is not nullptr.  Otherwise, it uses the hashed
1229     // symlinks in serverCACertPath.
1230     //
1231     // if ssl_ca_name is NOT configured for this cert in ssl_multicert.config
1232     //     AND
1233     // if proxy.config.ssl.CA.cert.filename and proxy.config.ssl.CA.cert.path
1234     //     are configured
1235     //   pass that file as the chain (include all certs in that file)
1236     // else if proxy.config.ssl.CA.cert.path is configured (and
1237     //       proxy.config.ssl.CA.cert.filename is nullptr)
1238     //   use the hashed symlinks in that directory to build the chain
1239     if (!sslMultCertSettings->ca && params->serverCACertPath != nullptr) {
1240       if ((!SSL_CTX_load_verify_locations(ctx, params->serverCACertFilename, params->serverCACertPath)) ||
1241           (!SSL_CTX_set_default_verify_paths(ctx))) {
1242         SSLError("invalid CA Certificate file or CA Certificate path");
1243         goto fail;
1244       }
1245     }
1246 
1247 #if defined(SSL_OP_NO_TICKET)
1248     // Session tickets are enabled by default. Disable if explicitly requested.
1249     if (sslMultCertSettings->session_ticket_enabled == 0) {
1250       SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
1251       Debug("ssl", "ssl session ticket is disabled");
1252     }
1253 #endif
1254 #if defined(TLS1_3_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
1255     if (!(params->ssl_ctx_options & SSL_OP_NO_TLSv1_3)) {
1256       SSL_CTX_set_num_tickets(ctx, sslMultCertSettings->session_ticket_number);
1257       Debug("ssl", "ssl session ticket number set to %d", sslMultCertSettings->session_ticket_number);
1258     }
1259 #endif
1260   }
1261 
1262   if (params->clientCertLevel != 0) {
1263     if (params->serverCACertFilename != nullptr && params->serverCACertPath != nullptr) {
1264       if ((!SSL_CTX_load_verify_locations(ctx, params->serverCACertFilename, params->serverCACertPath)) ||
1265           (!SSL_CTX_set_default_verify_paths(ctx))) {
1266         SSLError("CA Certificate file or CA Certificate path invalid");
1267         goto fail;
1268       }
1269     }
1270 
1271     if (params->clientCertLevel == 2) {
1272       server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE;
1273     } else if (params->clientCertLevel == 1) {
1274       server_verify_client = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
1275     } else {
1276       // disable client cert support
1277       server_verify_client = SSL_VERIFY_NONE;
1278       Error("illegal client certification level %d in %s", server_verify_client, ts::filename::RECORDS);
1279     }
1280     SSL_CTX_set_verify(ctx, server_verify_client, ssl_verify_client_callback);
1281     SSL_CTX_set_verify_depth(ctx, params->verify_depth); // might want to make configurable at some point.
1282   }
1283 
1284   if (!SSLMultiCertConfigLoader::set_session_id_context(ctx, params, sslMultCertSettings)) {
1285     goto fail;
1286   }
1287 
1288   if (params->cipherSuite != nullptr) {
1289     if (!SSL_CTX_set_cipher_list(ctx, params->cipherSuite)) {
1290       SSLError("invalid cipher suite in %s", ts::filename::RECORDS);
1291       goto fail;
1292     }
1293   }
1294 
1295 #if TS_USE_TLS_SET_CIPHERSUITES
1296   if (params->server_tls13_cipher_suites != nullptr) {
1297     if (!SSL_CTX_set_ciphersuites(ctx, params->server_tls13_cipher_suites)) {
1298       SSLError("invalid tls server cipher suites in %s", ts::filename::RECORDS);
1299       goto fail;
1300     }
1301   }
1302 #endif
1303 
1304 #if defined(SSL_CTX_set1_groups_list) || defined(SSL_CTX_set1_curves_list)
1305   if (params->server_groups_list != nullptr) {
1306 #ifdef SSL_CTX_set1_groups_list
1307     if (!SSL_CTX_set1_groups_list(ctx, params->server_groups_list)) {
1308 #else
1309     if (!SSL_CTX_set1_curves_list(ctx, params->server_groups_list)) {
1310 #endif
1311       SSLError("invalid groups list for server in %s", ts::filename::RECORDS);
1312       goto fail;
1313     }
1314   }
1315 #endif
1316 
1317   if (!ssl_context_enable_dhe(params->dhparamsFile, ctx)) {
1318     goto fail;
1319   }
1320 
1321   ssl_context_enable_ecdh(ctx);
1322 
1323   if (sslMultCertSettings && sslMultCertSettings->dialog) {
1324     SSLMultiCertConfigLoader::clear_pw_references(ctx);
1325   }
1326   SSL_CTX_set_info_callback(ctx, ssl_callback_info);
1327 
1328   SSL_CTX_set_next_protos_advertised_cb(ctx, SSLNetVConnection::advertise_next_protocol, nullptr);
1329   SSL_CTX_set_alpn_select_cb(ctx, SSLNetVConnection::select_next_protocol, nullptr);
1330 
1331   if (SSLConfigParams::init_ssl_ctx_cb) {
1332     SSLConfigParams::init_ssl_ctx_cb(ctx, true);
1333   }
1334 
1335   return ctx;
1336 
1337 fail:
1338   SSLMultiCertConfigLoader::clear_pw_references(ctx);
1339   SSLReleaseContext(ctx);
1340   return nullptr;
1341 }
1342 
1343 SSL_CTX *
1344 SSLCreateServerContext(const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultiCertSettings, const char *cert_path,
1345                        const char *key_path)
1346 {
1347   SSLMultiCertConfigLoader loader(params);
1348   std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx(nullptr, &SSL_CTX_free);
1349   std::vector<X509 *> cert_list;
1350   std::set<std::string> common_names;
1351   std::unordered_map<int, std::set<std::string>> unique_names;
1352   SSLMultiCertConfigLoader::CertLoadData data;
1353   if (loader.load_certs_and_cross_reference_names(cert_list, data, params, sslMultiCertSettings, common_names, unique_names)) {
1354     ctx.reset(loader.init_server_ssl_ctx(data, sslMultiCertSettings, common_names));
1355   }
1356   for (auto &i : cert_list) {
1357     X509_free(i);
1358   }
1359   if (ctx && cert_path) {
1360     if (!SSL_CTX_use_certificate_file(ctx.get(), cert_path, SSL_FILETYPE_PEM)) {
1361       SSLError("SSLCreateServerContext(): failed to load server certificate.");
1362       ctx = nullptr;
1363     } else if (!key_path || key_path[0] == '\0') {
1364       key_path = cert_path;
1365     }
1366     if (ctx) {
1367       if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_path, SSL_FILETYPE_PEM)) {
1368         SSLError("SSLCreateServerContext(): failed to load server private key.");
1369         ctx = nullptr;
1370       } else if (!SSL_CTX_check_private_key(ctx.get())) {
1371         SSLError("SSLCreateServerContext(): server private key does not match server certificate.");
1372         ctx = nullptr;
1373       }
1374     }
1375   }
1376   return ctx.release();
1377 }
1378 
1379 /**
1380    Insert SSLCertContext (SSL_CTX and options) into SSLCertLookup with key.
1381    Do NOT call SSL_CTX_set_* functions from here. SSL_CTX should be set up by SSLMultiCertConfigLoader::init_server_ssl_ctx().
1382  */
1383 bool
1384 SSLMultiCertConfigLoader::_store_ssl_ctx(SSLCertLookup *lookup, const shared_SSLMultiCertConfigParams &sslMultCertSettings)
1385 {
1386   bool retval = true;
1387   std::vector<X509 *> cert_list;
1388   std::set<std::string> common_names;
1389   std::unordered_map<int, std::set<std::string>> unique_names;
1390   SSLMultiCertConfigLoader::CertLoadData data;
1391 
1392   const SSLConfigParams *params = this->_params;
1393 
1394   this->load_certs_and_cross_reference_names(cert_list, data, params, sslMultCertSettings.get(), common_names, unique_names);
1395 
1396   int i = 0;
1397   for (auto cert : cert_list) {
1398     const char *current_cert_name = data.cert_names_list[i].c_str();
1399     if (0 > SSLMultiCertConfigLoader::check_server_cert_now(cert, current_cert_name)) {
1400       /* At this point, we know cert is bad, and we've already printed a
1401          descriptive reason as to why cert is bad to the log file */
1402       Debug(this->_debug_tag(), "Marking certificate as NOT VALID: %s", current_cert_name);
1403       lookup->is_valid = false;
1404     }
1405     i++;
1406   }
1407 
1408   shared_SSL_CTX ctx(this->init_server_ssl_ctx(data, sslMultCertSettings.get(), common_names), SSL_CTX_free);
1409 
1410   if (!ctx || !sslMultCertSettings || !this->_store_single_ssl_ctx(lookup, sslMultCertSettings, ctx, common_names)) {
1411     std::string names;
1412     for (auto name : data.cert_names_list) {
1413       names.append(name);
1414       names.append(" ");
1415     }
1416     Warning("(%s) Failed to insert SSL_CTX for certificate %s entries for names already made", this->_debug_tag(), names.c_str());
1417   }
1418 
1419   for (auto iter = unique_names.begin(); retval && iter != unique_names.end(); ++iter) {
1420     size_t i = iter->first;
1421 
1422     SSLMultiCertConfigLoader::CertLoadData single_data;
1423     single_data.cert_names_list.push_back(data.cert_names_list[i]);
1424     if (i < data.key_list.size()) {
1425       single_data.key_list.push_back(data.key_list[i]);
1426     }
1427     single_data.ca_list.push_back(i < data.ca_list.size() ? data.ca_list[i] : "");
1428     single_data.ocsp_list.push_back(i < data.ocsp_list.size() ? data.ocsp_list[i] : "");
1429 
1430     shared_SSL_CTX unique_ctx(this->init_server_ssl_ctx(single_data, sslMultCertSettings.get(), iter->second), SSL_CTX_free);
1431     if (!unique_ctx || !this->_store_single_ssl_ctx(lookup, sslMultCertSettings, unique_ctx, iter->second)) {
1432       retval = false;
1433     }
1434   }
1435 
1436   for (auto &i : cert_list) {
1437     X509_free(i);
1438   }
1439 
1440   return retval;
1441 }
1442 
1443 bool
1444 SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const shared_SSLMultiCertConfigParams &sslMultCertSettings,
1445                                                 shared_SSL_CTX ctx, std::set<std::string> &names)
1446 {
1447   bool inserted                        = false;
1448   shared_ssl_ticket_key_block keyblock = nullptr;
1449   // Load the session ticket key if session tickets are not disabled
1450   if (sslMultCertSettings->session_ticket_enabled != 0) {
1451     keyblock = shared_ssl_ticket_key_block(ssl_context_enable_tickets(ctx.get(), nullptr), ticket_block_free);
1452   }
1453 
1454   // Index this certificate by the specified IP(v6) address. If the address is "*", make it the default context.
1455   if (sslMultCertSettings->addr) {
1456     if (strcmp(sslMultCertSettings->addr, "*") == 0) {
1457       if (lookup->insert(sslMultCertSettings->addr, SSLCertContext(ctx, sslMultCertSettings, keyblock)) >= 0) {
1458         inserted            = true;
1459         lookup->ssl_default = ctx;
1460         this->_set_handshake_callbacks(ctx.get());
1461       }
1462     } else {
1463       IpEndpoint ep;
1464 
1465       if (ats_ip_pton(sslMultCertSettings->addr, &ep) == 0) {
1466         if (lookup->insert(ep, SSLCertContext(ctx, sslMultCertSettings, keyblock)) >= 0) {
1467           inserted = true;
1468         }
1469       } else {
1470         Error("'%s' is not a valid IPv4 or IPv6 address", (const char *)sslMultCertSettings->addr);
1471         lookup->is_valid = false;
1472       }
1473     }
1474   }
1475 
1476   // Insert additional mappings. Note that this maps multiple keys to the same value, so when
1477   // this code is updated to reconfigure the SSL certificates, it will need some sort of
1478   // refcounting or alternate way of avoiding double frees.
1479   for (auto sni_name : names) {
1480     if (SSLMultiCertConfigLoader::index_certificate(lookup, SSLCertContext(ctx, sslMultCertSettings), sni_name.c_str())) {
1481       inserted = true;
1482     }
1483   }
1484 
1485   if (inserted) {
1486     if (SSLConfigParams::init_ssl_ctx_cb) {
1487       SSLConfigParams::init_ssl_ctx_cb(ctx.get(), true);
1488     }
1489   }
1490 
1491   if (!inserted) {
1492     ctx = nullptr;
1493   }
1494 
1495   return ctx.get();
1496 }
1497 
1498 static bool
1499 ssl_extract_certificate(const matcher_line *line_info, SSLMultiCertConfigParams *sslMultCertSettings)
1500 {
1501   for (int i = 0; i < MATCHER_MAX_TOKENS; ++i) {
1502     const char *label;
1503     const char *value;
1504 
1505     label = line_info->line[0][i];
1506     value = line_info->line[1][i];
1507 
1508     if (label == nullptr) {
1509       continue;
1510     }
1511 
1512     if (strcasecmp(label, SSL_IP_TAG) == 0) {
1513       sslMultCertSettings->addr = ats_strdup(value);
1514     }
1515 
1516     if (strcasecmp(label, SSL_CERT_TAG) == 0) {
1517       sslMultCertSettings->cert = ats_strdup(value);
1518     }
1519 
1520     if (strcasecmp(label, SSL_CA_TAG) == 0) {
1521       sslMultCertSettings->ca = ats_strdup(value);
1522     }
1523 
1524     if (strcasecmp(label, SSL_PRIVATE_KEY_TAG) == 0) {
1525       sslMultCertSettings->key = ats_strdup(value);
1526     }
1527 
1528     if (strcasecmp(label, SSL_OCSP_RESPONSE_TAG) == 0) {
1529       sslMultCertSettings->ocsp_response = ats_strdup(value);
1530     }
1531 
1532     if (strcasecmp(label, SSL_SESSION_TICKET_ENABLED) == 0) {
1533       sslMultCertSettings->session_ticket_enabled = atoi(value);
1534     }
1535 
1536     if (strcasecmp(label, SSL_SESSION_TICKET_NUMBER) == 0) {
1537       sslMultCertSettings->session_ticket_number = atoi(value);
1538     }
1539 
1540     if (strcasecmp(label, SSL_KEY_DIALOG) == 0) {
1541       sslMultCertSettings->dialog = ats_strdup(value);
1542     }
1543 
1544     if (strcasecmp(label, SSL_SERVERNAME) == 0) {
1545       sslMultCertSettings->servername = ats_strdup(value);
1546     }
1547 
1548     if (strcasecmp(label, SSL_ACTION_TAG) == 0) {
1549       if (strcasecmp(SSL_ACTION_TUNNEL_TAG, value) == 0) {
1550         sslMultCertSettings->opt = SSLCertContextOption::OPT_TUNNEL;
1551       } else {
1552         Error("Unrecognized action for %s", SSL_ACTION_TAG.data());
1553         return false;
1554       }
1555     }
1556   }
1557   // TS-4679:  It is ok to be missing the cert.  At least if the action is set to tunnel
1558   if (sslMultCertSettings->cert) {
1559     SimpleTokenizer cert_tok(sslMultCertSettings->cert, SSL_CERT_SEPARATE_DELIM);
1560     const char *first_cert = cert_tok.getNext();
1561     if (first_cert) {
1562       sslMultCertSettings->first_cert = ats_strdup(first_cert);
1563     }
1564   }
1565 
1566   return true;
1567 }
1568 
1569 bool
1570 SSLMultiCertConfigLoader::load(SSLCertLookup *lookup)
1571 {
1572   const SSLConfigParams *params = this->_params;
1573 
1574   char *tok_state   = nullptr;
1575   char *line        = nullptr;
1576   unsigned line_num = 0;
1577   matcher_line line_info;
1578 
1579   const matcher_tags sslCertTags = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, false};
1580 
1581   Note("%s loading ...", ts::filename::SSL_MULTICERT);
1582 
1583   std::error_code ec;
1584   std::string content{ts::file::load(ts::file::path{params->configFilePath}, ec)};
1585   if (ec) {
1586     switch (ec.value()) {
1587     case ENOENT:
1588       Warning("Cannot open SSL certificate configuration from %s - %s", params->configFilePath, strerror(ec.value()));
1589       break;
1590     default:
1591       Error("Failed to read SSL certificate configuration from %s - %s", params->configFilePath, strerror(ec.value()));
1592       return false;
1593     }
1594   }
1595 
1596   // Optionally elevate/allow file access to read root-only
1597   // certificates. The destructor will drop privilege for us.
1598   uint32_t elevate_setting = 0;
1599   REC_ReadConfigInteger(elevate_setting, "proxy.config.ssl.cert.load_elevated");
1600   ElevateAccess elevate_access(elevate_setting ? ElevateAccess::FILE_PRIVILEGE : 0);
1601 
1602   line = tokLine(content.data(), &tok_state);
1603   while (line != nullptr) {
1604     line_num++;
1605 
1606     // Skip all blank spaces at beginning of line.
1607     while (*line && isspace(*line)) {
1608       line++;
1609     }
1610 
1611     if (*line != '\0' && *line != '#') {
1612       shared_SSLMultiCertConfigParams sslMultiCertSettings = std::make_shared<SSLMultiCertConfigParams>();
1613       const char *errPtr;
1614 
1615       errPtr = parseConfigLine(line, &line_info, &sslCertTags);
1616       Debug("ssl", "currently parsing %s", line);
1617       if (errPtr != nullptr) {
1618         RecSignalWarning(REC_SIGNAL_CONFIG_ERROR, "%s: discarding %s entry at line %d: %s", __func__, params->configFilePath,
1619                          line_num, errPtr);
1620       } else {
1621         if (ssl_extract_certificate(&line_info, sslMultiCertSettings.get())) {
1622           // There must be a certificate specified unless the tunnel action is set
1623           if (sslMultiCertSettings->cert || sslMultiCertSettings->opt != SSLCertContextOption::OPT_TUNNEL) {
1624             this->_store_ssl_ctx(lookup, sslMultiCertSettings);
1625           } else {
1626             Warning("No ssl_cert_name specified and no tunnel action set");
1627           }
1628         }
1629       }
1630     }
1631 
1632     line = tokLine(nullptr, &tok_state);
1633   }
1634 
1635   // We *must* have a default context even if it can't possibly work. The default context is used to
1636   // bootstrap the SSL handshake so that we can subsequently do the SNI lookup to switch to the real
1637   // context.
1638   if (lookup->ssl_default == nullptr) {
1639     shared_SSLMultiCertConfigParams sslMultiCertSettings(new SSLMultiCertConfigParams);
1640     sslMultiCertSettings->addr = ats_strdup("*");
1641     if (!this->_store_ssl_ctx(lookup, sslMultiCertSettings)) {
1642       Error("failed set default context");
1643       return false;
1644     }
1645   }
1646 
1647   return true;
1648 }
1649 
1650 // Release SSL_CTX and the associated data. This works for both
1651 // client and server contexts and gracefully accepts nullptr.
1652 void
1653 SSLReleaseContext(SSL_CTX *ctx)
1654 {
1655   SSL_CTX_free(ctx);
1656 }
1657 
1658 void
1659 SSLNetVCAttach(SSL *ssl, SSLNetVConnection *vc)
1660 {
1661   SSL_set_ex_data(ssl, ssl_vc_index, vc);
1662 }
1663 
1664 void
1665 SSLNetVCDetach(SSL *ssl)
1666 {
1667   SSL_set_ex_data(ssl, ssl_vc_index, nullptr);
1668 }
1669 
1670 SSLNetVConnection *
1671 SSLNetVCAccess(const SSL *ssl)
1672 {
1673   SSLNetVConnection *netvc;
1674   netvc = static_cast<SSLNetVConnection *>(SSL_get_ex_data(ssl, ssl_vc_index));
1675 
1676   ink_assert(dynamic_cast<SSLNetVConnection *>(static_cast<NetVConnection *>(SSL_get_ex_data(ssl, ssl_vc_index))));
1677 
1678   return netvc;
1679 }
1680 
1681 ssl_error_t
1682 SSLWriteBuffer(SSL *ssl, const void *buf, int64_t nbytes, int64_t &nwritten)
1683 {
1684   nwritten = 0;
1685 
1686   if (unlikely(nbytes == 0)) {
1687     return SSL_ERROR_NONE;
1688   }
1689   ERR_clear_error();
1690 
1691   int ret;
1692 #if TS_HAS_TLS_EARLY_DATA
1693   if (SSL_version(ssl) >= TLS1_3_VERSION) {
1694     if (SSL_is_init_finished(ssl)) {
1695       ret = SSL_write(ssl, buf, static_cast<int>(nbytes));
1696     } else {
1697       size_t nwrite;
1698       ret = SSL_write_early_data(ssl, buf, static_cast<size_t>(nbytes), &nwrite);
1699       if (ret == 1) {
1700         ret = nwrite;
1701       }
1702     }
1703   } else {
1704     ret = SSL_write(ssl, buf, static_cast<int>(nbytes));
1705   }
1706 #else
1707   ret = SSL_write(ssl, buf, static_cast<int>(nbytes));
1708 #endif
1709 
1710   if (ret > 0) {
1711     nwritten = ret;
1712     BIO *bio = SSL_get_wbio(ssl);
1713     if (bio != nullptr) {
1714       (void)BIO_flush(bio);
1715     }
1716     return SSL_ERROR_NONE;
1717   }
1718   int ssl_error = SSL_get_error(ssl, ret);
1719   if (ssl_error == SSL_ERROR_SSL && is_debug_tag_set("ssl.error.write")) {
1720     char tempbuf[512];
1721     unsigned long e = ERR_peek_last_error();
1722     ERR_error_string_n(e, tempbuf, sizeof(tempbuf));
1723     Debug("ssl.error.write", "SSL write returned %d, ssl_error=%d, ERR_get_error=%ld (%s)", ret, ssl_error, e, tempbuf);
1724   }
1725   return ssl_error;
1726 }
1727 
1728 ssl_error_t
1729 SSLReadBuffer(SSL *ssl, void *buf, int64_t nbytes, int64_t &nread)
1730 {
1731   nread = 0;
1732 
1733   if (unlikely(nbytes == 0)) {
1734     return SSL_ERROR_NONE;
1735   }
1736   ERR_clear_error();
1737 
1738 #if TS_HAS_TLS_EARLY_DATA
1739   if (SSL_version(ssl) >= TLS1_3_VERSION) {
1740     SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
1741 
1742     int64_t early_data_len = 0;
1743     if (netvc->early_data_reader != nullptr) {
1744       early_data_len = netvc->early_data_reader->read_avail();
1745     }
1746 
1747     if (early_data_len > 0) {
1748       Debug("ssl_early_data", "Reading from early data buffer.");
1749       netvc->read_from_early_data += netvc->early_data_reader->read(buf, nbytes < early_data_len ? nbytes : early_data_len);
1750 
1751       if (nbytes < early_data_len) {
1752         nread = nbytes;
1753       } else {
1754         nread = early_data_len;
1755       }
1756 
1757       return SSL_ERROR_NONE;
1758     }
1759 
1760     if (SSLConfigParams::server_max_early_data > 0 && !netvc->early_data_finish) {
1761       Debug("ssl_early_data", "More early data to read.");
1762       ssl_error_t ssl_error = SSL_ERROR_NONE;
1763       size_t read_bytes     = 0;
1764 
1765       int ret = SSL_read_early_data(ssl, buf, static_cast<size_t>(nbytes), &read_bytes);
1766 
1767       if (ret == SSL_READ_EARLY_DATA_ERROR) {
1768         Debug("ssl_early_data", "SSL_READ_EARLY_DATA_ERROR");
1769         ssl_error = SSL_get_error(ssl, ret);
1770         Debug("ssl_early_data", "Error reading early data: %s", ERR_error_string(ERR_get_error(), nullptr));
1771       } else {
1772         if ((nread = read_bytes) > 0) {
1773           netvc->read_from_early_data += read_bytes;
1774           SSL_INCREMENT_DYN_STAT(ssl_early_data_received_count);
1775           if (is_debug_tag_set("ssl_early_data_show_received")) {
1776             std::string early_data_str(reinterpret_cast<char *>(buf), nread);
1777             Debug("ssl_early_data_show_received", "Early data buffer: \n%s", early_data_str.c_str());
1778           }
1779         }
1780 
1781         if (ret == SSL_READ_EARLY_DATA_FINISH) {
1782           netvc->early_data_finish = true;
1783           Debug("ssl_early_data", "SSL_READ_EARLY_DATA_FINISH: size = %" PRId64, nread);
1784         } else {
1785           Debug("ssl_early_data", "SSL_READ_EARLY_DATA_SUCCESS: size = %" PRId64, nread);
1786         }
1787       }
1788 
1789       return ssl_error;
1790     }
1791   }
1792 #endif
1793 
1794   int ret = SSL_read(ssl, buf, static_cast<int>(nbytes));
1795   if (ret > 0) {
1796     nread = ret;
1797     return SSL_ERROR_NONE;
1798   }
1799   int ssl_error = SSL_get_error(ssl, ret);
1800   if (ssl_error == SSL_ERROR_SSL && is_debug_tag_set("ssl.error.read")) {
1801     char tempbuf[512];
1802     unsigned long e = ERR_peek_last_error();
1803     ERR_error_string_n(e, tempbuf, sizeof(tempbuf));
1804     Debug("ssl.error.read", "SSL read returned %d, ssl_error=%d, ERR_get_error=%ld (%s)", ret, ssl_error, e, tempbuf);
1805   }
1806 
1807   return ssl_error;
1808 }
1809 
1810 ssl_error_t
1811 SSLAccept(SSL *ssl)
1812 {
1813   ERR_clear_error();
1814 
1815   int ret       = 0;
1816   int ssl_error = SSL_ERROR_NONE;
1817 
1818 #if TS_HAS_TLS_EARLY_DATA
1819   SSLNetVConnection *netvc = SSLNetVCAccess(ssl);
1820 
1821   if (SSLConfigParams::server_max_early_data > 0 && !netvc->early_data_finish) {
1822     size_t nread;
1823 
1824     while (true) {
1825       IOBufferBlock *block = new_IOBufferBlock();
1826       block->alloc(BUFFER_SIZE_INDEX_16K);
1827       ret = SSL_read_early_data(ssl, block->buf(), index_to_buffer_size(BUFFER_SIZE_INDEX_16K), &nread);
1828 
1829       if (ret == SSL_READ_EARLY_DATA_ERROR) {
1830         Debug("ssl_early_data", "SSL_READ_EARLY_DATA_ERROR");
1831         block->free();
1832         break;
1833       } else {
1834         if (nread > 0) {
1835           if (netvc->early_data_buf == nullptr) {
1836             netvc->early_data_buf    = new_MIOBuffer(BUFFER_SIZE_INDEX_16K);
1837             netvc->early_data_reader = netvc->early_data_buf->alloc_reader();
1838           }
1839           block->fill(nread);
1840           netvc->early_data_buf->append_block(block);
1841           SSL_INCREMENT_DYN_STAT(ssl_early_data_received_count);
1842 
1843           if (is_debug_tag_set("ssl_early_data_show_received")) {
1844             std::string early_data_str(reinterpret_cast<char *>(block->buf()), nread);
1845             Debug("ssl_early_data_show_received", "Early data buffer: \n%s", early_data_str.c_str());
1846           }
1847         } else {
1848           block->free();
1849         }
1850 
1851         if (ret == SSL_READ_EARLY_DATA_FINISH) {
1852           netvc->early_data_finish = true;
1853           Debug("ssl_early_data", "SSL_READ_EARLY_DATA_FINISH: size = %lu", nread);
1854 
1855           if (netvc->early_data_reader == nullptr || netvc->early_data_reader->read_avail() == 0) {
1856             Debug("ssl_early_data", "no data in early data buffer");
1857             ERR_clear_error();
1858             ret = SSL_accept(ssl);
1859           }
1860           break;
1861         }
1862         Debug("ssl_early_data", "SSL_READ_EARLY_DATA_SUCCESS: size = %lu", nread);
1863       }
1864     }
1865   } else {
1866     ret = SSL_accept(ssl);
1867   }
1868 #else
1869   ret = SSL_accept(ssl);
1870 #endif
1871 
1872   if (ret > 0) {
1873     return SSL_ERROR_NONE;
1874   }
1875   ssl_error = SSL_get_error(ssl, ret);
1876   if (ssl_error == SSL_ERROR_SSL && is_debug_tag_set("ssl.error.accept")) {
1877     char buf[512];
1878     unsigned long e = ERR_peek_last_error();
1879     ERR_error_string_n(e, buf, sizeof(buf));
1880     Debug("ssl.error.accept", "SSL accept returned %d, ssl_error=%d, ERR_get_error=%ld (%s)", ret, ssl_error, e, buf);
1881   }
1882 
1883   return ssl_error;
1884 }
1885 
1886 ssl_error_t
1887 SSLConnect(SSL *ssl)
1888 {
1889   ERR_clear_error();
1890   int ret = SSL_connect(ssl);
1891   if (ret > 0) {
1892     return SSL_ERROR_NONE;
1893   }
1894   int ssl_error = SSL_get_error(ssl, ret);
1895   if (ssl_error == SSL_ERROR_SSL && is_debug_tag_set("ssl.error.connect")) {
1896     char buf[512];
1897     unsigned long e = ERR_peek_last_error();
1898     ERR_error_string_n(e, buf, sizeof(buf));
1899     Debug("ssl.error.connect", "SSL connect returned %d, ssl_error=%d, ERR_get_error=%ld (%s)", ret, ssl_error, e, buf);
1900   }
1901 
1902   return ssl_error;
1903 }
1904 
1905 /**
1906  * Process the config to pull out the list of file names, and process the certs to get the list
1907  * of subject and sni names.  Thanks to dual cert configurations, there may be multiple files of each type.
1908  * If some names are not in all the listed certs they are listed in the uniqe_names map, keyed by the index
1909  * of the including certificate
1910  */
1911 bool
1912 SSLMultiCertConfigLoader::load_certs_and_cross_reference_names(std::vector<X509 *> &cert_list,
1913                                                                SSLMultiCertConfigLoader::CertLoadData &data,
1914                                                                const SSLConfigParams *params,
1915                                                                const SSLMultiCertConfigParams *sslMultCertSettings,
1916                                                                std::set<std::string> &common_names,
1917                                                                std::unordered_map<int, std::set<std::string>> &unique_names)
1918 {
1919   SimpleTokenizer cert_tok(sslMultCertSettings && sslMultCertSettings->cert ? (const char *)sslMultCertSettings->cert : "",
1920                            SSL_CERT_SEPARATE_DELIM);
1921 
1922   SimpleTokenizer key_tok(SSL_CERT_SEPARATE_DELIM);
1923   if (sslMultCertSettings && sslMultCertSettings->key) {
1924     key_tok.setString((const char *)sslMultCertSettings->key);
1925   } else {
1926     key_tok.setString("");
1927   }
1928 
1929   if (sslMultCertSettings && sslMultCertSettings->key && cert_tok.getNumTokensRemaining() != key_tok.getNumTokensRemaining()) {
1930     Error("the number of certificates in ssl_cert_name and ssl_key_name doesn't match");
1931     return false;
1932   }
1933 
1934   SimpleTokenizer ca_tok("", SSL_CERT_SEPARATE_DELIM);
1935   if (sslMultCertSettings && sslMultCertSettings->ca) {
1936     ca_tok.setString(sslMultCertSettings->ca);
1937     if (cert_tok.getNumTokensRemaining() != ca_tok.getNumTokensRemaining()) {
1938       Error("the number of certificates in ssl_cert_name and ssl_ca_name doesn't match");
1939       return false;
1940     }
1941   }
1942 
1943   SimpleTokenizer ocsp_tok("", SSL_CERT_SEPARATE_DELIM);
1944   if (sslMultCertSettings && sslMultCertSettings->ocsp_response) {
1945     ocsp_tok.setString(sslMultCertSettings->ocsp_response);
1946     if (cert_tok.getNumTokensRemaining() != ocsp_tok.getNumTokensRemaining()) {
1947       Error("the number of certificates in ssl_cert_name and ssl_ocsp_name doesn't match");
1948       return false;
1949     }
1950   }
1951 
1952   for (const char *keyname = key_tok.getNext(); keyname; keyname = key_tok.getNext()) {
1953     data.key_list.push_back(keyname);
1954   }
1955 
1956   for (const char *caname = ca_tok.getNext(); caname; caname = ca_tok.getNext()) {
1957     data.ca_list.push_back(caname);
1958   }
1959 
1960   for (const char *ocspname = ocsp_tok.getNext(); ocspname; ocspname = ocsp_tok.getNext()) {
1961     data.ocsp_list.push_back(ocspname);
1962   }
1963 
1964   bool first_pass = true;
1965   int cert_index  = 0;
1966   for (const char *certname = cert_tok.getNext(); certname; certname = cert_tok.getNext()) {
1967     data.cert_names_list.push_back(certname);
1968     std::string completeServerCertPath = Layout::relative_to(params->serverCertPathOnly, certname);
1969     scoped_BIO bio(BIO_new_file(completeServerCertPath.c_str(), "r"));
1970     X509 *cert = nullptr;
1971     if (bio) {
1972       cert = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr);
1973     }
1974     if (!bio || !cert) {
1975       SSLError("failed to load certificate chain from %s", completeServerCertPath.c_str());
1976       return false;
1977     }
1978 
1979     cert_list.push_back(cert);
1980     if (SSLConfigParams::load_ssl_file_cb) {
1981       SSLConfigParams::load_ssl_file_cb(completeServerCertPath.c_str());
1982     }
1983 
1984     std::set<std::string> name_set;
1985     // Grub through the names in the certs
1986     X509_NAME *subject = nullptr;
1987 
1988     // Insert a key for the subject CN.
1989     subject = X509_get_subject_name(cert);
1990     ats_scoped_str subj_name;
1991     if (subject) {
1992       int pos = -1;
1993       for (;;) {
1994         pos = X509_NAME_get_index_by_NID(subject, NID_commonName, pos);
1995         if (pos == -1) {
1996           break;
1997         }
1998 
1999         X509_NAME_ENTRY *e = X509_NAME_get_entry(subject, pos);
2000         ASN1_STRING *cn    = X509_NAME_ENTRY_get_data(e);
2001         subj_name          = asn1_strdup(cn);
2002 
2003         Debug("ssl", "subj '%s' in certificate %s %p", (const char *)subj_name, certname, cert);
2004         name_set.insert(subj_name.get());
2005       }
2006     }
2007 
2008     // Traverse the subjectAltNames (if any) and insert additional keys for the SSL context.
2009     GENERAL_NAMES *names = static_cast<GENERAL_NAMES *>(X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
2010     if (names) {
2011       unsigned count = sk_GENERAL_NAME_num(names);
2012       for (unsigned i = 0; i < count; ++i) {
2013         GENERAL_NAME *name;
2014 
2015         name = sk_GENERAL_NAME_value(names, i);
2016         if (name->type == GEN_DNS) {
2017           ats_scoped_str dns(asn1_strdup(name->d.dNSName));
2018           name_set.insert(dns.get());
2019         }
2020       }
2021       sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
2022     }
2023 
2024     if (first_pass) {
2025       first_pass   = false;
2026       common_names = name_set;
2027     } else {
2028       // Check that all elements in common_names are in name_set
2029       auto common_iter = common_names.begin();
2030       while (common_iter != common_names.end()) {
2031         auto iter = name_set.find(*common_iter);
2032         if (iter == name_set.end()) {
2033           // Common_name not in new set, move name to unique set
2034           auto iter = unique_names.find(cert_index - 1);
2035           if (iter == unique_names.end()) {
2036             std::set<std::string> new_set;
2037             new_set.insert(*common_iter);
2038             unique_names.insert({cert_index - 1, new_set});
2039           } else {
2040             iter->second.insert(*common_iter);
2041           }
2042           auto erase_iter = common_iter;
2043           ++common_iter;
2044           common_names.erase(erase_iter);
2045         } else {
2046           // New name already in common set, go ahead and remove it from further consideration
2047           name_set.erase(iter);
2048           ++common_iter;
2049         }
2050       }
2051       // Anything still in name_set was not in common_names
2052       for (auto name : name_set) {
2053         auto iter = unique_names.find(cert_index);
2054         if (iter == unique_names.end()) {
2055           std::set<std::string> new_set;
2056           new_set.insert(name);
2057           unique_names.insert({cert_index, new_set});
2058         } else {
2059           iter->second.insert(name);
2060         }
2061       }
2062     }
2063     cert_index++;
2064   }
2065   return true;
2066 }
2067 
2068 /**
2069    Load certificates to SSL_CTX
2070    @static
2071  */
2072 bool
2073 SSLMultiCertConfigLoader::load_certs(SSL_CTX *ctx, SSLMultiCertConfigLoader::CertLoadData const &data,
2074                                      const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultCertSettings)
2075 {
2076 #if TS_USE_TLS_OCSP
2077   if (SSLConfigParams::ssl_ocsp_enabled) {
2078     Debug("ssl", "SSL OCSP Stapling is enabled");
2079     SSL_CTX_set_tlsext_status_cb(ctx, ssl_callback_ocsp_stapling);
2080   } else {
2081     Debug("ssl", "SSL OCSP Stapling is disabled");
2082   }
2083 #else
2084   if (SSLConfigParams::ssl_ocsp_enabled) {
2085     Warning("failed to enable SSL OCSP Stapling; this version of OpenSSL does not support it");
2086   }
2087 #endif /* TS_USE_TLS_OCSP */
2088 
2089   for (size_t i = 0; i < data.cert_names_list.size(); i++) {
2090     std::string completeServerCertPath = Layout::relative_to(params->serverCertPathOnly, data.cert_names_list[i]);
2091     scoped_BIO bio(BIO_new_file(completeServerCertPath.c_str(), "r"));
2092     X509 *cert = nullptr;
2093     if (bio) {
2094       cert = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr);
2095     }
2096     if (!bio || !cert) {
2097       SSLError("failed to load certificate chain from %s", completeServerCertPath.c_str());
2098       return false;
2099     }
2100     if (!SSL_CTX_use_certificate(ctx, cert)) {
2101       SSLError("Failed to assign cert from %s to SSL_CTX", completeServerCertPath.c_str());
2102       X509_free(cert);
2103       return false;
2104     }
2105 
2106     // Load up any additional chain certificates
2107     SSL_CTX_add_extra_chain_cert_bio(ctx, bio);
2108 
2109     const char *keyPath = i < data.key_list.size() ? data.key_list[i].c_str() : nullptr;
2110     if (!SSLPrivateKeyHandler(ctx, params, completeServerCertPath, keyPath)) {
2111       return false;
2112     }
2113 
2114     if (SSLConfigParams::load_ssl_file_cb) {
2115       SSLConfigParams::load_ssl_file_cb(completeServerCertPath.c_str());
2116     }
2117 
2118     // Must load all the intermediate certificates before starting the next chain
2119 
2120     // First, load any CA chains from the global chain file.  This should probably
2121     // eventually be a comma separated list too.  For now we will load it in all chains even
2122     // though it only makes sense in one chain
2123     if (params->serverCertChainFilename) {
2124       ats_scoped_str completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, params->serverCertChainFilename));
2125       if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) {
2126         SSLError("failed to load global certificate chain from %s", (const char *)completeServerCertChainPath);
2127         return false;
2128       }
2129       if (SSLConfigParams::load_ssl_file_cb) {
2130         SSLConfigParams::load_ssl_file_cb(completeServerCertChainPath);
2131       }
2132     }
2133 
2134     // Now, load any additional certificate chains specified in this entry.
2135     if (sslMultCertSettings->ca) {
2136       const char *ca_name = data.ca_list[i].c_str();
2137       if (ca_name != nullptr) {
2138         ats_scoped_str completeServerCertChainPath(Layout::relative_to(params->serverCertPathOnly, ca_name));
2139         if (!SSL_CTX_add_extra_chain_cert_file(ctx, completeServerCertChainPath)) {
2140           SSLError("failed to load certificate chain from %s", (const char *)completeServerCertChainPath);
2141           return false;
2142         }
2143         if (SSLConfigParams::load_ssl_file_cb) {
2144           SSLConfigParams::load_ssl_file_cb(completeServerCertChainPath);
2145         }
2146       }
2147     }
2148 #if TS_USE_TLS_OCSP
2149     if (SSLConfigParams::ssl_ocsp_enabled) {
2150       if (sslMultCertSettings->ocsp_response) {
2151         const char *ocsp_response_name = data.ocsp_list[i].c_str();
2152         ats_scoped_str completeOCSPResponsePath(Layout::relative_to(params->ssl_ocsp_response_path_only, ocsp_response_name));
2153         if (!ssl_stapling_init_cert(ctx, cert, data.cert_names_list[i].c_str(), (const char *)completeOCSPResponsePath)) {
2154           Warning("failed to configure SSL_CTX for OCSP Stapling info for certificate at %s", data.cert_names_list[i].c_str());
2155         }
2156       } else {
2157         if (!ssl_stapling_init_cert(ctx, cert, data.cert_names_list[i].c_str(), nullptr)) {
2158           Warning("failed to configure SSL_CTX for OCSP Stapling info for certificate at %s", data.cert_names_list[i].c_str());
2159         }
2160       }
2161     }
2162 #endif /* TS_USE_TLS_OCSP */
2163     X509_free(cert);
2164   }
2165 
2166   return true;
2167 }
2168 
2169 /**
2170     Set session_id context for session reuse
2171     @static
2172  */
2173 bool
2174 SSLMultiCertConfigLoader::set_session_id_context(SSL_CTX *ctx, const SSLConfigParams *params,
2175                                                  const SSLMultiCertConfigParams *sslMultCertSettings)
2176 {
2177   EVP_MD_CTX *digest           = EVP_MD_CTX_new();
2178   STACK_OF(X509_NAME) *ca_list = nullptr;
2179   unsigned char hash_buf[EVP_MAX_MD_SIZE];
2180   unsigned int hash_len    = 0;
2181   const char *setting_cert = sslMultCertSettings ? sslMultCertSettings->cert.get() : nullptr;
2182   bool result              = false;
2183 
2184   if (params->serverCACertFilename) {
2185     ca_list = SSL_load_client_CA_file(params->serverCACertFilename);
2186   }
2187 
2188   if (EVP_DigestInit_ex(digest, evp_md_func, nullptr) == 0) {
2189     SSLError("EVP_DigestInit_ex failed");
2190     goto fail;
2191   }
2192 
2193   if (nullptr != setting_cert) {
2194     Debug("ssl", "Using '%s' in hash for session id context", sslMultCertSettings->cert.get());
2195     if (EVP_DigestUpdate(digest, sslMultCertSettings->cert, strlen(setting_cert)) == 0) {
2196       SSLError("EVP_DigestUpdate failed");
2197       goto fail;
2198     }
2199   }
2200 
2201   if (ca_list != nullptr) {
2202     size_t num_certs = sk_X509_NAME_num(ca_list);
2203 
2204     for (size_t i = 0; i < num_certs; i++) {
2205       X509_NAME *name = sk_X509_NAME_value(ca_list, i);
2206       if (X509_NAME_digest(name, evp_md_func, hash_buf /* borrow our final hash buffer. */, &hash_len) == 0 ||
2207           EVP_DigestUpdate(digest, hash_buf, hash_len) == 0) {
2208         SSLError("Adding X509 name to digest failed");
2209         goto fail;
2210       }
2211     }
2212 
2213     // Set the list of CA's to send to client if we ask for a client certificate
2214     SSL_CTX_set_client_CA_list(ctx, ca_list);
2215   }
2216 
2217   if (EVP_DigestFinal_ex(digest, hash_buf, &hash_len) == 0) {
2218     SSLError("EVP_DigestFinal_ex failed");
2219     goto fail;
2220   }
2221 
2222   if (SSL_CTX_set_session_id_context(ctx, hash_buf, hash_len) == 0) {
2223     SSLError("SSL_CTX_set_session_id_context failed");
2224     goto fail;
2225   }
2226 
2227   result = true;
2228 
2229 fail:
2230   EVP_MD_CTX_free(digest);
2231 
2232   return result;
2233 }
2234 
2235 const char *
2236 SSLMultiCertConfigLoader::_debug_tag() const
2237 {
2238   return "ssl";
2239 }
2240 
2241 /**
2242    Clear password in SSL_CTX
2243    @static
2244  */
2245 void
2246 SSLMultiCertConfigLoader::clear_pw_references(SSL_CTX *ssl_ctx)
2247 {
2248   SSL_CTX_set_default_passwd_cb(ssl_ctx, nullptr);
2249   SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, nullptr);
2250 }
2251 
2252 ssl_curve_id
2253 SSLGetCurveNID(SSL *ssl)
2254 {
2255 #ifndef OPENSSL_IS_BORINGSSL
2256   return SSL_get_shared_curve(ssl, 0);
2257 #else
2258   return SSL_get_curve_id(ssl);
2259 #endif
2260 }
2261