• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 15920880335

26 Jun 2025 03:30PM UTC coverage: 61.923% (-3.7%) from 65.652%
15920880335

push

github

web-flow
Merge pull request #15669 from miodvallat/serial_keyer

Increase zone serial number after zone key operations

38311 of 91850 branches covered (41.71%)

Branch coverage included in aggregate %.

27 of 29 new or added lines in 1 file covered. (93.1%)

6308 existing lines in 78 files now uncovered.

120482 of 164587 relevant lines covered (73.2%)

5965233.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.11
/pdns/libssl.cc
1
#include "config.h"
2
#include "libssl.hh"
3

4
#ifdef HAVE_LIBSSL
5

6
#include <atomic>
7
#include <fstream>
8
#include <cstring>
9
#include <mutex>
10
#include <unordered_map>
11
#include <pthread.h>
12

13
#include <openssl/conf.h>
14
#if defined(DNSDIST) && (OPENSSL_VERSION_MAJOR < 3 || !defined(HAVE_TLS_PROVIDERS))
15
#ifndef OPENSSL_NO_ENGINE
16
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage): used by the preprocessor below
17
#define DNSDIST_ENABLE_LIBSSL_ENGINE 1
18
#include <openssl/engine.h>
19
#endif
20
#endif
21
#include <openssl/err.h>
22
#ifndef DISABLE_OCSP_STAPLING
23
#include <openssl/ocsp.h>
24
#endif /* DISABLE_OCSP_STAPLING */
25
#include <openssl/pkcs12.h>
26
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
27
#include <openssl/provider.h>
28
#endif /* defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 */
29
#include <openssl/rand.h>
30
#include <openssl/ssl.h>
31
#include <openssl/x509v3.h>
32
#include <fcntl.h>
33

34
#if OPENSSL_VERSION_MAJOR >= 3
35
#include <openssl/param_build.h>
36
#include <openssl/core.h>
37
#include <openssl/core_names.h>
38
#include <openssl/evp.h>
39
#else
40
#include <openssl/hmac.h>
41
#endif
42

43
#ifdef HAVE_LIBSODIUM
44
#include <sodium.h>
45
#endif /* HAVE_LIBSODIUM */
46

47
#undef CERT
48
#include "misc.hh"
49
#include "tcpiohandler.hh"
50

51
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
52
/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
53

54
#include "lock.hh"
55
static std::vector<std::mutex> openssllocks;
56

57
extern "C" {
58
static void openssl_pthreads_locking_callback(int mode, int type, const char *file, int line)
59
{
60
  if (mode & CRYPTO_LOCK) {
61
    openssllocks.at(type).lock();
62

63
  } else {
64
    openssllocks.at(type).unlock();
65
  }
66
}
67

68
static unsigned long openssl_pthreads_id_callback()
69
{
70
  return (unsigned long)pthread_self();
71
}
72
}
73

74
static void openssl_thread_setup()
75
{
76
  openssllocks = std::vector<std::mutex>(CRYPTO_num_locks());
77
  CRYPTO_set_id_callback(&openssl_pthreads_id_callback);
78
  CRYPTO_set_locking_callback(&openssl_pthreads_locking_callback);
79
}
80

81
static void openssl_thread_cleanup()
82
{
83
  CRYPTO_set_locking_callback(nullptr);
84
  openssllocks.clear();
85
}
86

87
#endif /* (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL) */
88

89
static std::atomic<uint64_t> s_users;
90

91
#if OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS)
92
static LockGuarded<std::unordered_map<std::string, std::unique_ptr<OSSL_PROVIDER, decltype(&OSSL_PROVIDER_unload)>>> s_providers;
93
#else
94
#if defined(DNSDIST_ENABLE_LIBSSL_ENGINE)
95
static LockGuarded<std::unordered_map<std::string, std::unique_ptr<ENGINE, decltype(&ENGINE_free)>>> s_engines;
96
#endif
97
#endif
98

99
static int s_ticketsKeyIndex{-1};
100
static int s_countersIndex{-1};
101
static int s_keyLogIndex{-1};
102

103
void registerOpenSSLUser()
104
{
127✔
105
  if (s_users.fetch_add(1) == 0) {
127✔
106
#ifdef HAVE_OPENSSL_INIT_CRYPTO
86✔
107
#ifndef DISABLE_OPENSSL_ERROR_STRINGS
86✔
108
    uint64_t cryptoOpts = OPENSSL_INIT_LOAD_CONFIG;
86✔
109
    const uint64_t sslOpts = 0;
86✔
110
#else /* DISABLE_OPENSSL_ERROR_STRINGS */
111
    uint64_t cryptoOpts = OPENSSL_INIT_LOAD_CONFIG|OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS;
112
    const uint64_t sslOpts = OPENSSL_INIT_NO_LOAD_SSL_STRINGS;
113
#endif /* DISABLE_OPENSSL_ERROR_STRINGS */
114
    /* load the default configuration file (or one specified via OPENSSL_CONF),
115
       which can then be used to load engines.
116
    */
117
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
86✔
118
    /* Since 661595ca0933fe631faeadd14a189acd5d4185e0 we can no longer rely on the ciphers and digests
119
       required for TLS to be loaded by OPENSSL_init_ssl(), so let's give up and load everything */
120
#else /* OPENSSL_VERSION_MAJOR >= 3 */
121
    /* Do not load all ciphers and digests, we only need a few of them and these
122
       will be loaded by OPENSSL_init_ssl(). */
123
    cryptoOpts |= OPENSSL_INIT_NO_ADD_ALL_CIPHERS|OPENSSL_INIT_NO_ADD_ALL_DIGESTS;
124
#endif /* OPENSSL_VERSION_MAJOR >= 3 */
125

126
    OPENSSL_init_crypto(cryptoOpts, nullptr);
86✔
127
    OPENSSL_init_ssl(sslOpts, nullptr);
86✔
128
#endif /* HAVE_OPENSSL_INIT_CRYPTO */
86✔
129

130
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x2090100fL))
131
    /* load error strings for both libcrypto and libssl */
132
    SSL_load_error_strings();
133
    /* load all ciphers and digests needed for TLS support */
134
    OpenSSL_add_ssl_algorithms();
135
    openssl_thread_setup();
136
#endif
137
    s_ticketsKeyIndex = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
86✔
138

139
    if (s_ticketsKeyIndex == -1) {
86!
140
      throw std::runtime_error("Error getting an index for tickets key");
×
141
    }
×
142

143
    s_countersIndex = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
86✔
144

145
    if (s_countersIndex == -1) {
86!
146
      throw std::runtime_error("Error getting an index for counters");
×
147
    }
×
148

149
    s_keyLogIndex = SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
86✔
150

151
    if (s_keyLogIndex == -1) {
86!
152
      throw std::runtime_error("Error getting an index for TLS key logging");
×
153
    }
×
154
  }
86✔
155
}
127✔
156

157
void unregisterOpenSSLUser()
158
{
10✔
159
  if (s_users.fetch_sub(1) == 1) {
10!
160
#if defined(DNSDIST_ENABLE_LIBSSL_ENGINE)
161
    for (auto& [name, engine] : *s_engines.lock()) {
162
      ENGINE_finish(engine.get());
163
      engine.reset();
164
    }
165
    s_engines.lock()->clear();
166
#endif /* PDNS_ENABLE_LIBSSL_ENGINE */
167
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER && LIBRESSL_VERSION_NUMBER < 0x2090100fL))
168
    ERR_free_strings();
169

170
    EVP_cleanup();
171

172
    CONF_modules_finish();
173
    CONF_modules_free();
174
    CONF_modules_unload(1);
175

176
    CRYPTO_cleanup_all_ex_data();
177
    openssl_thread_cleanup();
178
#endif
UNCOV
179
  }
×
180
}
10✔
181

182
#if defined(HAVE_LIBSSL) && OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS)
183
std::pair<bool, std::string> libssl_load_provider(const std::string& providerName)
184
{
185
  if (s_users.load() == 0) {
186
    /* We need to make sure that OpenSSL has been properly initialized before loading an engine.
187
       This messes up our accounting a bit, so some memory might not be properly released when
188
       the program exits when engines are in use. */
189
    registerOpenSSLUser();
190
  }
191

192
  auto providers = s_providers.lock();
193
  if (providers->count(providerName) > 0) {
194
    return { false, "TLS provider already loaded" };
195
  }
196

197
  auto provider = std::unique_ptr<OSSL_PROVIDER, decltype(&OSSL_PROVIDER_unload)>(OSSL_PROVIDER_load(nullptr, providerName.c_str()), OSSL_PROVIDER_unload);
198
  if (provider == nullptr) {
199
    return { false, "unable to load TLS provider '" + providerName + "'" };
200
  }
201

202
  providers->insert({providerName, std::move(provider)});
203
  return { true, "" };
204
}
205
#endif /* HAVE_LIBSSL && OPENSSL_VERSION_MAJOR >= 3 && HAVE_TLS_PROVIDERS */
206

207
#if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS)
208
std::pair<bool, std::string> libssl_load_engine([[maybe_unused]] const std::string& engineName, [[maybe_unused]] const std::optional<std::string>& defaultString)
209
{
×
210
#if defined(OPENSSL_NO_ENGINE)
×
211
  return { false, "OpenSSL has been built without engine support" };
×
212
#elif !defined(DNSDIST_ENABLE_LIBSSL_ENGINE)
213
  return { false, "SSL engine support not enabled" };
214
#else /* DNSDIST_ENABLE_LIBSSL_ENGINE */
215
  if (s_users.load() == 0) {
216
    /* We need to make sure that OpenSSL has been properly initialized before loading an engine.
217
       This messes up our accounting a bit, so some memory might not be properly released when
218
       the program exits when engines are in use. */
219
    registerOpenSSLUser();
220
  }
221

222
  auto engines = s_engines.lock();
223
  if (engines->count(engineName) > 0) {
224
    return { false, "TLS engine already loaded" };
225
  }
226

227
  auto engine = std::unique_ptr<ENGINE, decltype(&ENGINE_free)>(ENGINE_by_id(engineName.c_str()), ENGINE_free);
228
  if (engine == nullptr) {
229
    return { false, "unable to load TLS engine '" + engineName + "'" };
230
  }
231

232
  if (!ENGINE_init(engine.get())) {
233
    return { false, "Unable to init TLS engine '" + engineName + "'" };
234
  }
235

236
  if (defaultString) {
237
    if (ENGINE_set_default_string(engine.get(), defaultString->c_str()) == 0) {
238
      return { false, "error while setting the TLS engine default string" };
239
    }
240
  }
241

242
  engines->insert({engineName, std::move(engine)});
243
  return { true, "" };
244
#endif /* DNSDIST_ENABLE_LIBSSL_ENGINE */
245
}
×
246
#endif /* HAVE_LIBSSL && !HAVE_TLS_PROVIDERS */
247

248
void* libssl_get_ticket_key_callback_data(SSL* s)
249
{
1,643✔
250
  SSL_CTX* sslCtx = SSL_get_SSL_CTX(s);
1,643✔
251
  if (sslCtx == nullptr) {
1,643!
252
    return nullptr;
×
253
  }
×
254

255
  return SSL_CTX_get_ex_data(sslCtx, s_ticketsKeyIndex);
1,643✔
256
}
1,643✔
257

258
void libssl_set_ticket_key_callback_data(SSL_CTX* ctx, void* data)
259
{
155✔
260
  SSL_CTX_set_ex_data(ctx, s_ticketsKeyIndex, data);
155✔
261
}
155✔
262

263
#if OPENSSL_VERSION_MAJOR >= 3
264
int libssl_ticket_key_callback(SSL* /* s */, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx, int enc)
265
#else
266
int libssl_ticket_key_callback(SSL* /* s */, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx, int enc)
267
#endif
268
{
1,103✔
269
  if (enc != 0) {
1,103✔
270
    const auto key = keyring.getEncryptionKey();
848✔
271
    if (key == nullptr) {
848!
272
      return -1;
×
273
    }
×
274

275
    return key->encrypt(keyName, iv, ectx, hctx);
848✔
276
  }
848✔
277

278
  bool activeEncryptionKey = false;
255✔
279

280
  const auto key = keyring.getDecryptionKey(keyName, activeEncryptionKey);
255✔
281
  if (key == nullptr) {
255✔
282
    /* we don't know this key, just create a new ticket */
283
    return 0;
9✔
284
  }
9✔
285

286
  if (!key->decrypt(iv, ectx, hctx)) {
246!
287
    return -1;
×
288
  }
×
289

290
  if (!activeEncryptionKey) {
246✔
291
    /* this key is not active, please encrypt the ticket content with the currently active one */
292
    return 2;
12✔
293
  }
12✔
294

295
  return 1;
234✔
296
}
246✔
297

298
static int libssl_server_name_callback(SSL* ssl, int* /* alert */, void* /* arg */)
299
{
131✔
300
  if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) != nullptr) {
131!
301
    return SSL_TLSEXT_ERR_OK;
131✔
302
  }
131✔
303

304
  return SSL_TLSEXT_ERR_NOACK;
×
305
}
131✔
306

307
static void libssl_info_callback(const SSL *ssl, int where, int /* ret */)
308
{
12,251✔
309
  SSL_CTX* sslCtx = SSL_get_SSL_CTX(ssl);
12,251✔
310
  if (sslCtx == nullptr) {
12,251!
311
    return;
×
312
  }
×
313

314
  TLSErrorCounters* counters = reinterpret_cast<TLSErrorCounters*>(SSL_CTX_get_ex_data(sslCtx, s_countersIndex));
12,251✔
315
  if (counters == nullptr) {
12,251!
316
    return;
×
317
  }
×
318

319
  if (where & SSL_CB_ALERT) {
12,251✔
320
    const long lastError = ERR_peek_last_error();
969✔
321
    switch (ERR_GET_REASON(lastError)) {
969✔
322
#ifdef SSL_R_DH_KEY_TOO_SMALL
×
323
    case SSL_R_DH_KEY_TOO_SMALL:
×
324
      ++counters->d_dhKeyTooSmall;
×
325
      break;
×
326
#endif /* SSL_R_DH_KEY_TOO_SMALL */
×
327
    case SSL_R_NO_SHARED_CIPHER:
×
328
      ++counters->d_noSharedCipher;
×
329
      break;
×
330
    case SSL_R_UNKNOWN_PROTOCOL:
×
331
      ++counters->d_unknownProtocol;
×
332
      break;
×
333
    case SSL_R_UNSUPPORTED_PROTOCOL:
×
334
#ifdef SSL_R_VERSION_TOO_LOW
×
335
    case SSL_R_VERSION_TOO_LOW:
×
336
#endif /* SSL_R_VERSION_TOO_LOW */
×
337
      ++counters->d_unsupportedProtocol;
×
338
      break;
×
339
    case SSL_R_INAPPROPRIATE_FALLBACK:
×
340
      ++counters->d_inappropriateFallBack;
×
341
      break;
×
342
    case SSL_R_UNKNOWN_CIPHER_TYPE:
×
343
      ++counters->d_unknownCipherType;
×
344
      break;
×
345
    case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
×
346
      ++counters->d_unknownKeyExchangeType;
×
347
      break;
×
348
    case SSL_R_UNSUPPORTED_ELLIPTIC_CURVE:
×
349
      ++counters->d_unsupportedEC;
×
350
      break;
×
351
    default:
969!
352
      break;
969✔
353
    }
969✔
354
  }
969✔
355
}
12,251✔
356

357
void libssl_set_error_counters_callback(SSL_CTX& ctx, TLSErrorCounters* counters)
358
{
160✔
359
  SSL_CTX_set_ex_data(&ctx, s_countersIndex, counters);
160✔
360
  SSL_CTX_set_info_callback(&ctx, libssl_info_callback);
160✔
361
}
160✔
362

363
#ifndef DISABLE_OCSP_STAPLING
364
int libssl_ocsp_stapling_callback(SSL* ssl, const std::map<int, std::string>& ocspMap)
365
{
6✔
366
  auto pkey = SSL_get_privatekey(ssl);
6✔
367
  if (pkey == nullptr) {
6!
368
    return SSL_TLSEXT_ERR_NOACK;
×
369
  }
×
370

371
  /* look for an OCSP response for the corresponding private key type (RSA, ECDSA..) */
372
  const auto& data = ocspMap.find(EVP_PKEY_base_id(pkey));
6✔
373
  if (data == ocspMap.end()) {
6!
374
    return SSL_TLSEXT_ERR_NOACK;
×
375
  }
×
376

377
  /* we need to allocate a copy because OpenSSL will free the pointer passed to SSL_set_tlsext_status_ocsp_resp() */
378
  void* copy = OPENSSL_malloc(data->second.size());
6✔
379
  if (copy == nullptr) {
6!
380
    return SSL_TLSEXT_ERR_NOACK;
×
381
  }
×
382

383
  memcpy(copy, data->second.data(), data->second.size());
6✔
384
  SSL_set_tlsext_status_ocsp_resp(ssl, copy, data->second.size());
6✔
385
  return SSL_TLSEXT_ERR_OK;
6✔
386
}
6✔
387

388
static bool libssl_validate_ocsp_response(const std::string& response)
389
{
11✔
390
  auto responsePtr = reinterpret_cast<const unsigned char *>(response.data());
11✔
391
  std::unique_ptr<OCSP_RESPONSE, void(*)(OCSP_RESPONSE*)> resp(d2i_OCSP_RESPONSE(nullptr, &responsePtr, response.size()), OCSP_RESPONSE_free);
11✔
392
  if (resp == nullptr) {
11✔
393
    throw std::runtime_error("Unable to parse OCSP response");
3✔
394
  }
3✔
395

396
  int status = OCSP_response_status(resp.get());
8✔
397
  if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
8!
398
    throw std::runtime_error("OCSP response status is not successful: " + std::to_string(status));
×
399
  }
×
400

401
  std::unique_ptr<OCSP_BASICRESP, void(*)(OCSP_BASICRESP*)> basic(OCSP_response_get1_basic(resp.get()), OCSP_BASICRESP_free);
8✔
402
  if (basic == nullptr) {
8!
403
    throw std::runtime_error("Error getting a basic OCSP response");
×
404
  }
×
405

406
  if (OCSP_resp_count(basic.get()) != 1) {
8!
407
    throw std::runtime_error("More than one single response in an OCSP basic response");
×
408
  }
×
409

410
  auto singleResponse = OCSP_resp_get0(basic.get(), 0);
8✔
411
  if (singleResponse == nullptr) {
8!
412
    throw std::runtime_error("Error getting a single response from the basic OCSP response");
×
413
  }
×
414

415
  int reason;
8✔
416
  ASN1_GENERALIZEDTIME* revTime = nullptr;
8✔
417
  ASN1_GENERALIZEDTIME* thisUpdate = nullptr;
8✔
418
  ASN1_GENERALIZEDTIME* nextUpdate = nullptr;
8✔
419

420
  auto singleResponseStatus = OCSP_single_get0_status(singleResponse, &reason, &revTime, &thisUpdate, &nextUpdate);
8✔
421
  if (singleResponseStatus != V_OCSP_CERTSTATUS_GOOD) {
8!
422
    throw std::runtime_error("Invalid status for OCSP single response (" + std::to_string(singleResponseStatus) + ")");
×
423
  }
×
424
  if (thisUpdate == nullptr || nextUpdate == nullptr) {
8!
425
    throw std::runtime_error("Error getting validity of OCSP single response");
×
426
  }
×
427

428
  auto validityResult = OCSP_check_validity(thisUpdate, nextUpdate, /* 5 minutes of leeway */ 5 * 60, -1);
8✔
429
  if (validityResult == 0) {
8!
430
    throw std::runtime_error("OCSP single response is not yet, or no longer, valid");
×
431
  }
×
432

433
  return true;
8✔
434
}
8✔
435

436
static std::map<int, std::string> libssl_load_ocsp_responses(const std::vector<std::string>& ocspFiles, std::vector<int> keyTypes, std::vector<std::string>& warnings)
437
{
11✔
438
  std::map<int, std::string> ocspResponses;
11✔
439

440
  if (ocspFiles.size() > keyTypes.size()) {
11!
441
    throw std::runtime_error("More OCSP files than certificates and keys loaded!");
×
442
  }
×
443

444
  size_t count = 0;
11✔
445
  for (const auto& filename : ocspFiles) {
11✔
446
    std::ifstream file(filename, std::ios::binary);
11✔
447
    std::string content;
11✔
448
    while (file) {
22✔
449
      char buffer[4096];
11✔
450
      file.read(buffer, sizeof(buffer));
11✔
451
      if (file.bad()) {
11!
452
        file.close();
×
453
        warnings.push_back("Unable to load OCSP response from " + filename);
×
454
        continue;
×
455
      }
×
456
      content.append(buffer, file.gcount());
11✔
457
    }
11✔
458
    file.close();
11✔
459

460
    try {
11✔
461
      libssl_validate_ocsp_response(content);
11✔
462
      ocspResponses.insert({keyTypes.at(count), std::move(content)});
11✔
463
    }
11✔
464
    catch (const std::exception& e) {
11✔
465
      warnings.push_back("Error checking the validity of OCSP response from '" + filename + "': " + e.what());
3✔
466
      continue;
3✔
467
    }
3✔
468
    ++count;
8✔
469
  }
8✔
470

471
  return ocspResponses;
11✔
472
}
11✔
473

474
#ifdef HAVE_OCSP_BASIC_SIGN
475
bool libssl_generate_ocsp_response(const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin)
476
{
10✔
477
  const EVP_MD* rmd = EVP_sha256();
10✔
478

479
  auto filePtr = pdns::UniqueFilePtr(fopen(certFile.c_str(), "r"));
10✔
480
  if (!filePtr) {
10!
481
    throw std::runtime_error("Unable to open '" + certFile + "' when loading the certificate to generate an OCSP response");
×
482
  }
×
483
  auto cert = std::unique_ptr<X509, void(*)(X509*)>(PEM_read_X509_AUX(filePtr.get(), nullptr, nullptr, nullptr), X509_free);
10✔
484

485
  filePtr = pdns::UniqueFilePtr(fopen(caCert.c_str(), "r"));
10✔
486
  if (!filePtr) {
10!
487
    throw std::runtime_error("Unable to open '" + caCert + "' when loading the issuer certificate to generate an OCSP response");
×
488
  }
×
489
  auto issuer = std::unique_ptr<X509, void(*)(X509*)>(PEM_read_X509_AUX(filePtr.get(), nullptr, nullptr, nullptr), X509_free);
10✔
490
  filePtr = pdns::UniqueFilePtr(fopen(caKey.c_str(), "r"));
10✔
491
  if (!filePtr) {
10!
492
    throw std::runtime_error("Unable to open '" + caKey + "' when loading the issuer key to generate an OCSP response");
×
493
  }
×
494
  auto issuerKey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(PEM_read_PrivateKey(filePtr.get(), nullptr, nullptr, nullptr), EVP_PKEY_free);
10✔
495
  filePtr.reset();
10✔
496

497
  auto bs = std::unique_ptr<OCSP_BASICRESP, void(*)(OCSP_BASICRESP*)>(OCSP_BASICRESP_new(), OCSP_BASICRESP_free);
10✔
498
  auto thisupd = std::unique_ptr<ASN1_TIME, void(*)(ASN1_TIME*)>(X509_gmtime_adj(nullptr, 0), ASN1_TIME_free);
10✔
499
  auto nextupd = std::unique_ptr<ASN1_TIME, void(*)(ASN1_TIME*)>(X509_time_adj_ex(nullptr, ndays, nmin * 60, nullptr), ASN1_TIME_free);
10✔
500

501
  auto cid = std::unique_ptr<OCSP_CERTID, void(*)(OCSP_CERTID*)>(OCSP_cert_to_id(rmd, cert.get(), issuer.get()), OCSP_CERTID_free);
10✔
502
  OCSP_basic_add1_status(bs.get(), cid.get(), V_OCSP_CERTSTATUS_GOOD, 0, nullptr, thisupd.get(), nextupd.get());
10✔
503

504
  if (OCSP_basic_sign(bs.get(), issuer.get(), issuerKey.get(), rmd, nullptr, OCSP_NOCERTS) != 1) {
10!
505
    throw std::runtime_error("Error while signing the OCSP response");
×
506
  }
×
507

508
  auto resp = std::unique_ptr<OCSP_RESPONSE, void(*)(OCSP_RESPONSE*)>(OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs.get()), OCSP_RESPONSE_free);
10✔
509
  auto bio = std::unique_ptr<BIO, void(*)(BIO*)>(BIO_new_file(outFile.c_str(), "wb"), BIO_vfree);
10✔
510
  if (!bio) {
10!
511
    throw std::runtime_error("Error opening file for writing the OCSP response");
×
512
  }
×
513

514
  // i2d_OCSP_RESPONSE_bio(bio.get(), resp.get()) is unusable from C++ because of an invalid cast
515
  ASN1_i2d_bio((i2d_of_void*)i2d_OCSP_RESPONSE, bio.get(), (unsigned char*)resp.get());
10✔
516

517
  return true;
10✔
518
}
10✔
519
#endif /* HAVE_OCSP_BASIC_SIGN */
520
#endif /* DISABLE_OCSP_STAPLING */
521

522
static int libssl_get_last_key_type(SSL_CTX& ctx)
523
{
95✔
524
#ifdef HAVE_SSL_CTX_GET0_PRIVATEKEY
95✔
525
  auto* pkey = SSL_CTX_get0_privatekey(&ctx);
95✔
526
#else
527
  auto temp = std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(&ctx), SSL_free);
528
  if (!temp) {
529
    return -1;
530
  }
531
  auto pkey = SSL_get_privatekey(temp.get());
532
#endif
533

534
  if (!pkey) {
95!
535
    return -1;
×
536
  }
×
537

538
  return EVP_PKEY_base_id(pkey);
95✔
539
}
95✔
540

541
struct StackOfNamesDeleter
542
{
543
  void operator()(STACK_OF(GENERAL_NAME)* ptr) const noexcept {
71✔
544
    sk_GENERAL_NAME_pop_free(ptr, GENERAL_NAME_free);
71✔
545
  }
71✔
546
};
547

548
#if defined(OPENSSL_IS_BORINGSSL)
549
/* return type of OpenSSL's sk_XXX_num() */
550
using SSLStackIndex = size_t;
551
#else
552
using SSLStackIndex = int;
553
#endif
554

555
static std::unordered_set<std::string> get_names_from_certificate(const X509* certificate)
556
{
71✔
557
  std::unordered_set<std::string> result;
71✔
558
  auto names = std::unique_ptr<STACK_OF(GENERAL_NAME), StackOfNamesDeleter>(static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr)));
71✔
559
  if (names) {
71!
560
    for (SSLStackIndex idx = 0; idx < sk_GENERAL_NAME_num(names.get()); idx++) {
282✔
561
      const auto* name = sk_GENERAL_NAME_value(names.get(), idx);
211✔
562
      if (name->type != GEN_DNS) {
211✔
563
        /* ignore GEN_IPADD / name->d.iPAddress (raw IP address bytes), it cannot be used in SNI anyway */
564
        continue;
71✔
565
      }
71✔
566
      unsigned char* str = nullptr;
140✔
567
      if (ASN1_STRING_to_UTF8(&str, name->d.dNSName) < 0) {
140!
568
        continue;
×
569
      }
×
570
      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): OpenSSL's API
571
      result.emplace(reinterpret_cast<const char*>(str));
140✔
572
      OPENSSL_free(str);
140✔
573
    }
140✔
574
  }
71✔
575

576
  auto* name = X509_get_subject_name(certificate);
71✔
577
  if (name != nullptr) {
71!
578
    int idx = -1;
71✔
579
    while ((idx = X509_NAME_get_index_by_NID(name, NID_commonName, idx)) != -1) {
142✔
580
      const auto* entry = X509_NAME_get_entry(name, idx);
71✔
581
      const auto* value = X509_NAME_ENTRY_get_data(entry);
71✔
582
      unsigned char* str = nullptr;
71✔
583
      if (ASN1_STRING_to_UTF8(&str, value) < 0) {
71!
584
        continue;
×
585
      }
×
586
      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): OpenSSL's API
587
      result.emplace(reinterpret_cast<const char*>(str));
71✔
588
      OPENSSL_free(str);
71✔
589
    }
71✔
590
  }
71✔
591

592
  return result;
71✔
593
}
71✔
594

595
static std::unordered_set<std::string> get_names_from_last_certificate(const SSL_CTX& ctx)
596
{
71✔
597
  const auto* cert = SSL_CTX_get0_certificate(&ctx);
71✔
598
  if (cert == nullptr) {
71!
599
    return {};
×
600
  }
×
601

602
  return get_names_from_certificate(cert);
71✔
603
}
71✔
604

605
LibsslTLSVersion libssl_tls_version_from_string(const std::string& str)
606
{
28✔
607
  if (str == "tls1.0") {
28!
608
    return LibsslTLSVersion::TLS10;
28✔
609
  }
28✔
610
  if (str == "tls1.1") {
×
611
    return LibsslTLSVersion::TLS11;
×
612
  }
×
613
  if (str == "tls1.2") {
×
614
    return LibsslTLSVersion::TLS12;
×
615
  }
×
616
  if (str == "tls1.3") {
×
617
    return LibsslTLSVersion::TLS13;
×
618
  }
×
619
  throw std::runtime_error("Unknown TLS version '" + str + "'");
×
620
}
×
621

622
const std::string& libssl_tls_version_to_string(LibsslTLSVersion version)
623
{
×
624
  static const std::map<LibsslTLSVersion, std::string> versions = {
×
625
    { LibsslTLSVersion::TLS10, "tls1.0" },
×
626
    { LibsslTLSVersion::TLS11, "tls1.1" },
×
627
    { LibsslTLSVersion::TLS12, "tls1.2" },
×
628
    { LibsslTLSVersion::TLS13, "tls1.3" }
×
629
  };
×
630

631
  const auto& it = versions.find(version);
×
632
  if (it == versions.end()) {
×
633
    throw std::runtime_error("Unknown TLS version (" + std::to_string((int)version) + ")");
×
634
  }
×
635
  return it->second;
×
636
}
×
637

638
static bool libssl_set_min_tls_version(SSL_CTX& ctx, LibsslTLSVersion version)
639
{
95✔
640
#if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) || defined(SSL_CTX_set_min_proto_version)
95✔
641
  /* These functions have been introduced in 1.1.0, and the use of SSL_OP_NO_* is deprecated
642
     Warning: SSL_CTX_set_min_proto_version is a function-like macro in OpenSSL */
643
  int vers;
95✔
644
  switch(version) {
95✔
645
  case LibsslTLSVersion::TLS10:
95!
646
    vers = TLS1_VERSION;
95✔
647
    break;
95✔
648
  case LibsslTLSVersion::TLS11:
×
649
    vers = TLS1_1_VERSION;
×
650
    break;
×
651
  case LibsslTLSVersion::TLS12:
×
652
    vers = TLS1_2_VERSION;
×
653
    break;
×
654
  case LibsslTLSVersion::TLS13:
×
655
#ifdef TLS1_3_VERSION
×
656
    vers = TLS1_3_VERSION;
×
657
#else
658
    return false;
659
#endif /* TLS1_3_VERSION */
660
    break;
×
661
  default:
×
662
    return false;
×
663
  }
95✔
664

665
  if (SSL_CTX_set_min_proto_version(&ctx, vers) != 1) {
95!
666
    return false;
×
667
  }
×
668
  return true;
95✔
669
#else
670
  long vers = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
671
  switch(version) {
672
  case LibsslTLSVersion::TLS10:
673
    break;
674
  case LibsslTLSVersion::TLS11:
675
    vers |= SSL_OP_NO_TLSv1;
676
    break;
677
  case LibsslTLSVersion::TLS12:
678
    vers |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
679
    break;
680
  case LibsslTLSVersion::TLS13:
681
    vers |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
682
    break;
683
  default:
684
    return false;
685
  }
686

687
  long options = SSL_CTX_get_options(&ctx);
688
  SSL_CTX_set_options(&ctx, options | vers);
689
  return true;
690
#endif
691
}
95✔
692

693
OpenSSLTLSTicketKeysRing::OpenSSLTLSTicketKeysRing(size_t capacity)
694
{
90✔
695
  d_ticketKeys.write_lock()->set_capacity(capacity);
90✔
696
}
90✔
697

698
OpenSSLTLSTicketKeysRing::~OpenSSLTLSTicketKeysRing() = default;
8✔
699

700
void OpenSSLTLSTicketKeysRing::addKey(std::shared_ptr<OpenSSLTLSTicketKey>&& newKey)
701
{
241✔
702
  d_ticketKeys.write_lock()->push_front(std::move(newKey));
241✔
703
  if (TLSCtx::hasTicketsKeyAddedHook()) {
241✔
704
    auto key = d_ticketKeys.read_lock()->front();
2✔
705
    auto keyContent = key->content();
2✔
706
    TLSCtx::getTicketsKeyAddedHook()(keyContent);
2✔
707
    // fills mem with 0's
708
    OPENSSL_cleanse(keyContent.data(), keyContent.size());
2✔
709
  }
2✔
710
}
241✔
711

712
std::shared_ptr<OpenSSLTLSTicketKey> OpenSSLTLSTicketKeysRing::getEncryptionKey()
713
{
848✔
714
  return d_ticketKeys.read_lock()->front();
848✔
715
}
848✔
716

717
std::shared_ptr<OpenSSLTLSTicketKey> OpenSSLTLSTicketKeysRing::getDecryptionKey(unsigned char name[TLS_TICKETS_KEY_NAME_SIZE], bool& activeKey)
718
{
255✔
719
  auto keys = d_ticketKeys.read_lock();
255✔
720
  for (auto& key : *keys) {
339✔
721
    if (key->nameMatches(name)) {
339✔
722
      activeKey = (key == keys->front());
246✔
723
      return key;
246✔
724
    }
246✔
725
  }
339✔
726
  return nullptr;
9✔
727
}
255✔
728

729
size_t OpenSSLTLSTicketKeysRing::getKeysCount()
730
{
12✔
731
  return d_ticketKeys.read_lock()->size();
12✔
732
}
12✔
733

734
void OpenSSLTLSTicketKeysRing::loadTicketsKeys(const std::string& keyFile)
735
{
18✔
736
  bool keyLoaded = false;
18✔
737
  std::ifstream file(keyFile);
18✔
738
  try {
18✔
739
    do {
102✔
740
      auto newKey = std::make_shared<OpenSSLTLSTicketKey>(file);
102✔
741
      addKey(std::move(newKey));
102✔
742
      keyLoaded = true;
102✔
743
    }
102✔
744
    while (!file.fail());
102✔
745
  }
18✔
746
  catch (const std::exception& e) {
18✔
747
    /* if we haven't been able to load at least one key, fail */
748
    if (!keyLoaded) {
18!
749
      throw;
×
750
    }
×
751
  }
18✔
752

753
  file.close();
18✔
754
}
18✔
755

756
void OpenSSLTLSTicketKeysRing::loadTicketsKey(const std::string& key)
757
{
1✔
758
  bool keyLoaded = false;
1✔
759
  try {
1✔
760
    auto newKey = std::make_shared<OpenSSLTLSTicketKey>(key);
1✔
761
    addKey(std::move(newKey));
1✔
762
    keyLoaded = true;
1✔
763
  }
1✔
764
  catch (const std::exception& e) {
1✔
765
    /* if we haven't been able to load at least one key, fail */
766
    if (!keyLoaded) {
×
767
      throw;
×
768
    }
×
769
  }
×
770
}
1✔
771

772
void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t /* now */)
773
{
156✔
774
  auto newKey = std::make_shared<OpenSSLTLSTicketKey>();
156✔
775
  addKey(std::move(newKey));
156✔
776
}
156✔
777

778
OpenSSLTLSTicketKey::OpenSSLTLSTicketKey()
779
{
156✔
780
  if (RAND_bytes(d_name, sizeof(d_name)) != 1) {
156!
781
    throw std::runtime_error("Error while generating the name of the OpenSSL TLS ticket key");
×
782
  }
×
783

784
  if (RAND_bytes(d_cipherKey, sizeof(d_cipherKey)) != 1) {
156!
785
    throw std::runtime_error("Error while generating the cipher key of the OpenSSL TLS ticket key");
×
786
  }
×
787

788
  if (RAND_bytes(d_hmacKey, sizeof(d_hmacKey)) != 1) {
156!
789
    throw std::runtime_error("Error while generating the HMAC key of the OpenSSL TLS ticket key");
×
790
  }
×
791
#ifdef HAVE_LIBSODIUM
156✔
792
  sodium_mlock(d_name, sizeof(d_name));
156✔
793
  sodium_mlock(d_cipherKey, sizeof(d_cipherKey));
156✔
794
  sodium_mlock(d_hmacKey, sizeof(d_hmacKey));
156✔
795
#endif /* HAVE_LIBSODIUM */
156✔
796
}
156✔
797

798
OpenSSLTLSTicketKey::OpenSSLTLSTicketKey(std::ifstream& file)
799
{
102✔
800
  file.read(reinterpret_cast<char*>(d_name), sizeof(d_name));
102✔
801
  file.read(reinterpret_cast<char*>(d_cipherKey), sizeof(d_cipherKey));
102✔
802
  file.read(reinterpret_cast<char*>(d_hmacKey), sizeof(d_hmacKey));
102✔
803

804
  if (file.fail()) {
102✔
805
    throw std::runtime_error("Unable to load a ticket key from the OpenSSL tickets key file");
18✔
806
  }
18✔
807
#ifdef HAVE_LIBSODIUM
84✔
808
  sodium_mlock(d_name, sizeof(d_name));
84✔
809
  sodium_mlock(d_cipherKey, sizeof(d_cipherKey));
84✔
810
  sodium_mlock(d_hmacKey, sizeof(d_hmacKey));
84✔
811
#endif /* HAVE_LIBSODIUM */
84✔
812
}
84✔
813

814
OpenSSLTLSTicketKey::OpenSSLTLSTicketKey(const std::string& key)
815
{
1✔
816
  if (key.size() != (sizeof(d_name) + sizeof(d_cipherKey) + sizeof(d_hmacKey))) {
1!
817
    throw std::runtime_error("Unable to load a ticket key from given data");
×
818
  }
×
819
  size_t from = 0;
1✔
820
  memcpy(d_name, &key.at(from), sizeof(d_name));
1✔
821
  from += sizeof(d_name);
1✔
822
  memcpy(d_cipherKey, &key.at(from), sizeof(d_cipherKey));
1✔
823
  from += sizeof(d_cipherKey);
1✔
824
  memcpy(d_hmacKey, &key.at(from), sizeof(d_hmacKey));
1✔
825

826
#ifdef HAVE_LIBSODIUM
1✔
827
  sodium_mlock(d_name, sizeof(d_name));
1✔
828
  sodium_mlock(d_cipherKey, sizeof(d_cipherKey));
1✔
829
  sodium_mlock(d_hmacKey, sizeof(d_hmacKey));
1✔
830
#endif /* HAVE_LIBSODIUM */
1✔
831
}
1✔
832

833
OpenSSLTLSTicketKey::~OpenSSLTLSTicketKey()
834
{
148✔
835
#ifdef HAVE_LIBSODIUM
148✔
836
  sodium_munlock(d_name, sizeof(d_name));
148✔
837
  sodium_munlock(d_cipherKey, sizeof(d_cipherKey));
148✔
838
  sodium_munlock(d_hmacKey, sizeof(d_hmacKey));
148✔
839
#else
840
  OPENSSL_cleanse(d_name, sizeof(d_name));
841
  OPENSSL_cleanse(d_cipherKey, sizeof(d_cipherKey));
842
  OPENSSL_cleanse(d_hmacKey, sizeof(d_hmacKey));
843
#endif /* HAVE_LIBSODIUM */
844
}
148✔
845

846
bool OpenSSLTLSTicketKey::nameMatches(const unsigned char name[TLS_TICKETS_KEY_NAME_SIZE]) const
847
{
339✔
848
  return (memcmp(d_name, name, sizeof(d_name)) == 0);
339✔
849
}
339✔
850

851
std::string OpenSSLTLSTicketKey::content() const
852
{
2✔
853
  std::string result{};
2✔
854
  result.reserve(TLS_TICKETS_KEY_NAME_SIZE + TLS_TICKETS_CIPHER_KEY_SIZE + TLS_TICKETS_MAC_KEY_SIZE);
2✔
855
  // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
856
  result.append(reinterpret_cast<const char*>(d_name), TLS_TICKETS_KEY_NAME_SIZE);
2✔
857
  result.append(reinterpret_cast<const char*>(d_cipherKey), TLS_TICKETS_CIPHER_KEY_SIZE);
2✔
858
  result.append(reinterpret_cast<const char*>(d_hmacKey), TLS_TICKETS_MAC_KEY_SIZE);
2✔
859
  // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
860

861
  return result;
2✔
862
}
2✔
863

864
#if OPENSSL_VERSION_MAJOR >= 3
865
static const std::string sha256KeyName{"sha256"};
866
#endif
867

868
#if OPENSSL_VERSION_MAJOR >= 3
869
int OpenSSLTLSTicketKey::encrypt(unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx) const
870
#else
871
int OpenSSLTLSTicketKey::encrypt(unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx) const
872
#endif
873
{
848✔
874
  memcpy(keyName, d_name, sizeof(d_name));
848✔
875

876
  if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) != 1) {
848!
877
    return -1;
×
878
  }
×
879

880
  if (EVP_EncryptInit_ex(ectx, TLS_TICKETS_CIPHER_ALGO(), nullptr, d_cipherKey, iv) != 1) {
848!
881
    return -1;
×
882
  }
×
883

884
#if OPENSSL_VERSION_MAJOR >= 3
848✔
885
  using ParamsBuilder = std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)>;
848✔
886
  using Params = std::unique_ptr<OSSL_PARAM, decltype(&OSSL_PARAM_free)>;
848✔
887

888
  auto params_build = ParamsBuilder(OSSL_PARAM_BLD_new(), OSSL_PARAM_BLD_free);
848✔
889
  if (params_build == nullptr) {
848!
890
    return -1;
×
891
  }
×
892

893
  if (OSSL_PARAM_BLD_push_utf8_string(params_build.get(), OSSL_MAC_PARAM_DIGEST, sha256KeyName.c_str(), sha256KeyName.size()) == 0) {
848!
894
    return -1;
×
895
  }
×
896

897
  auto params = Params(OSSL_PARAM_BLD_to_param(params_build.get()), OSSL_PARAM_free);
848✔
898
  if (params == nullptr) {
848!
899
    return -1;
×
900
  }
×
901

902
  if (EVP_MAC_CTX_set_params(hctx, params.get()) == 0) {
848!
903
    return -1;
×
904
  }
×
905

906
  if (EVP_MAC_init(hctx, d_hmacKey, sizeof(d_hmacKey), nullptr) == 0) {
848!
907
    return -1;
×
908
  }
×
909
#else
910
  if (HMAC_Init_ex(hctx, d_hmacKey, sizeof(d_hmacKey), TLS_TICKETS_MAC_ALGO(), nullptr) != 1) {
911
    return -1;
912
  }
913
#endif
914

915
  return 1;
848✔
916
}
848✔
917

918
#if OPENSSL_VERSION_MAJOR >= 3
919
bool OpenSSLTLSTicketKey::decrypt(const unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx) const
920
#else
921
bool OpenSSLTLSTicketKey::decrypt(const unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx) const
922
#endif
923
{
246✔
924
#if OPENSSL_VERSION_MAJOR >= 3
246✔
925
  using ParamsBuilder = std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)>;
246✔
926
  using Params = std::unique_ptr<OSSL_PARAM, decltype(&OSSL_PARAM_free)>;
246✔
927

928
  auto params_build = ParamsBuilder(OSSL_PARAM_BLD_new(), OSSL_PARAM_BLD_free);
246✔
929
  if (params_build == nullptr) {
246!
930
    return false;
×
931
  }
×
932

933
  if (OSSL_PARAM_BLD_push_utf8_string(params_build.get(), OSSL_MAC_PARAM_DIGEST, sha256KeyName.c_str(), sha256KeyName.size()) == 0) {
246!
934
    return false;
×
935
  }
×
936

937
  auto params = Params(OSSL_PARAM_BLD_to_param(params_build.get()), OSSL_PARAM_free);
246✔
938
  if (params == nullptr) {
246!
939
    return false;
×
940
  }
×
941

942
  if (EVP_MAC_CTX_set_params(hctx, params.get()) == 0) {
246!
943
    return false;
×
944
  }
×
945

946
  if (EVP_MAC_init(hctx, d_hmacKey, sizeof(d_hmacKey), nullptr) == 0) {
246!
947
    return false;
×
948
  }
×
949
#else
950
  if (HMAC_Init_ex(hctx, d_hmacKey, sizeof(d_hmacKey), TLS_TICKETS_MAC_ALGO(), nullptr) != 1) {
951
    return false;
952
  }
953
#endif
954

955
  if (EVP_DecryptInit_ex(ectx, TLS_TICKETS_CIPHER_ALGO(), nullptr, d_cipherKey, iv) != 1) {
246!
956
    return false;
×
957
  }
×
958

959
  return true;
246✔
960
}
246✔
961

962
static std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> getNewServerContext(const TLSConfig& config, [[maybe_unused]] std::vector<std::string>& warnings)
963
{
95✔
964
  auto ctx = std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>(SSL_CTX_new(SSLv23_server_method()), SSL_CTX_free);
95✔
965

966
  if (!ctx) {
95!
967
    throw pdns::OpenSSL::error("Error creating an OpenSSL server context");
×
968
  }
×
969

970
  int sslOptions =
95✔
971
    SSL_OP_NO_SSLv2 |
95✔
972
    SSL_OP_NO_SSLv3 |
95✔
973
    SSL_OP_NO_COMPRESSION |
95✔
974
    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
95✔
975
    SSL_OP_SINGLE_DH_USE |
95✔
976
    SSL_OP_SINGLE_ECDH_USE;
95✔
977

978
  if (!config.d_enableTickets || config.d_numberOfTicketsKeys == 0) {
95!
979
    /* for TLS 1.3 this means no stateless tickets, but stateful tickets might still be issued,
980
       which is something we don't want. */
981
    sslOptions |= SSL_OP_NO_TICKET;
3✔
982
    /* really disable all tickets */
983
#ifdef HAVE_SSL_CTX_SET_NUM_TICKETS
3✔
984
    SSL_CTX_set_num_tickets(ctx.get(), 0);
3✔
985
#endif /* HAVE_SSL_CTX_SET_NUM_TICKETS */
3✔
986
  }
3✔
987

988
  if (config.d_ktls) {
95!
989
#ifdef SSL_OP_ENABLE_KTLS
×
990
    sslOptions |= SSL_OP_ENABLE_KTLS;
×
991
#endif /* SSL_OP_ENABLE_KTLS */
×
992
  }
×
993

994
  if (config.d_sessionTimeout > 0) {
95!
995
    SSL_CTX_set_timeout(ctx.get(), config.d_sessionTimeout);
×
996
  }
×
997

998
  if (config.d_preferServerCiphers) {
95!
999
    sslOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
95✔
1000
#ifdef SSL_OP_PRIORITIZE_CHACHA
95✔
1001
    sslOptions |= SSL_OP_PRIORITIZE_CHACHA;
95✔
1002
#endif /* SSL_OP_PRIORITIZE_CHACHA */
95✔
1003
  }
95✔
1004

1005
  if (!config.d_enableRenegotiation) {
95!
1006
#ifdef SSL_OP_NO_RENEGOTIATION
95✔
1007
    sslOptions |= SSL_OP_NO_RENEGOTIATION;
95✔
1008
#elif defined(SSL_OP_NO_CLIENT_RENEGOTIATION)
1009
    sslOptions |= SSL_OP_NO_CLIENT_RENEGOTIATION;
1010
#endif
1011
  }
95✔
1012

1013
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
95✔
1014
  sslOptions |= SSL_OP_IGNORE_UNEXPECTED_EOF;
95✔
1015
#endif
95✔
1016

1017
  SSL_CTX_set_options(ctx.get(), sslOptions);
95✔
1018
  if (!libssl_set_min_tls_version(*ctx, config.d_minTLSVersion)) {
95!
1019
    throw std::runtime_error("Failed to set the minimum version to '" + libssl_tls_version_to_string(config.d_minTLSVersion));
×
1020
  }
×
1021

1022
#ifdef SSL_CTX_set_ecdh_auto
95✔
1023
  SSL_CTX_set_ecdh_auto(ctx.get(), 1);
95✔
1024
#endif
95✔
1025

1026
  if (config.d_maxStoredSessions == 0) {
95✔
1027
    /* disable stored sessions entirely */
1028
    SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_OFF);
3✔
1029
  }
3✔
1030
  else {
92✔
1031
    /* use the internal built-in cache to store sessions */
1032
    SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_SERVER);
92✔
1033
    SSL_CTX_sess_set_cache_size(ctx.get(), config.d_maxStoredSessions);
92✔
1034
  }
92✔
1035

1036
  long mode = 0;
95✔
1037
#ifdef SSL_MODE_RELEASE_BUFFERS
95✔
1038
  if (config.d_releaseBuffers) {
95!
1039
    mode |= SSL_MODE_RELEASE_BUFFERS;
95✔
1040
  }
95✔
1041
#endif
95✔
1042

1043
  if (config.d_asyncMode) {
95!
1044
#ifdef SSL_MODE_ASYNC
×
1045
    mode |= SSL_MODE_ASYNC;
×
1046
#else
1047
    warnings.push_back("Warning: TLS async mode requested but not supported");
1048
#endif
1049
  }
×
1050

1051
  SSL_CTX_set_mode(ctx.get(), mode);
95✔
1052

1053
  /* we need to set this callback to acknowledge the server name sent by the client,
1054
     otherwise it will not stored in the session and will not be accessible when the
1055
     session is resumed, causing SSL_get_servername to return nullptr */
1056
  SSL_CTX_set_tlsext_servername_callback(ctx.get(), &libssl_server_name_callback);
95✔
1057

1058
  return ctx;
95✔
1059
}
95✔
1060

1061
static void mergeNewCertificateAndKey(pdns::libssl::ServerContext& serverContext, pdns::libssl::ServerContext::SharedContext newContext, std::unordered_set<std::string>& names, const std::function<void(pdns::libssl::ServerContext::SharedContext&)>& existingContextCallback)
1062
{
71✔
1063
  for (const auto& name : names) {
140✔
1064
    auto [existingEntry, inserted] = serverContext.d_sniMap.emplace(name, newContext);
140✔
1065
    if (!inserted) {
140✔
1066
      auto& existingContext = existingEntry->second;
4✔
1067
      existingContextCallback(existingContext);
4✔
1068
    }
4✔
1069
    else if (serverContext.d_sniMap.size() == 1) {
136✔
1070
      serverContext.d_defaultContext = newContext;
67✔
1071
    }
67✔
1072
  }
140✔
1073
}
71✔
1074

1075
std::pair<std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)>, std::vector<std::string>> libssl_init_server_context_no_sni(const TLSConfig& config,
1076
                                                                                                                         [[maybe_unused]] std::map<int, std::string>& ocspResponses)
1077
{
24✔
1078
  std::vector<std::string> warnings;
24✔
1079
  auto ctx = getNewServerContext(config, warnings);
24✔
1080

1081
  std::vector<int> keyTypes;
24✔
1082
  /* load certificate and private key */
1083
  for (const auto& pair : config.d_certKeyPairs) {
24✔
1084
    if (!pair.d_key) {
24✔
1085
#if defined(HAVE_SSL_CTX_USE_CERT_AND_KEY)
1✔
1086
      // If no separate key is given, treat it as a pkcs12 file
1087
      auto filePtr = pdns::UniqueFilePtr(fopen(pair.d_cert.c_str(), "r"));
1✔
1088
      if (!filePtr) {
1!
1089
        throw std::runtime_error("Unable to open file " + pair.d_cert);
×
1090
      }
×
1091
      auto p12 = std::unique_ptr<PKCS12, void(*)(PKCS12*)>(d2i_PKCS12_fp(filePtr.get(), nullptr), PKCS12_free);
1✔
1092
      if (!p12) {
1!
1093
        throw std::runtime_error("Unable to open PKCS12 file " + pair.d_cert);
×
1094
      }
×
1095
      EVP_PKEY *keyptr = nullptr;
1✔
1096
      X509 *certptr = nullptr;
1✔
1097
      STACK_OF(X509) *captr = nullptr;
1✔
1098
      if (!PKCS12_parse(p12.get(), (pair.d_password ? pair.d_password->c_str() : nullptr), &keyptr, &certptr, &captr)) {
1!
1099
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
×
1100
        bool failed = true;
×
1101
        /* we might be opening a PKCS12 file that uses RC2 CBC or 3DES CBC which, since OpenSSL 3.0.0, requires loading the legacy provider */
1102
        auto libCtx = OSSL_LIB_CTX_get0_global_default();
×
1103
        /* check whether the legacy provider is already loaded */
1104
        if (!OSSL_PROVIDER_available(libCtx, "legacy")) {
×
1105
          /* it's not */
1106
          auto provider = OSSL_PROVIDER_load(libCtx, "legacy");
×
1107
          if (provider != nullptr) {
×
1108
            if (PKCS12_parse(p12.get(), (pair.d_password ? pair.d_password->c_str() : nullptr), &keyptr, &certptr, &captr)) {
×
1109
              failed = false;
×
1110
            }
×
1111
            /* we do not want to keep that provider around after that */
1112
            OSSL_PROVIDER_unload(provider);
×
1113
          }
×
1114
        }
×
1115
        if (failed) {
×
1116
#endif /* defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 */
×
1117
          ERR_print_errors_fp(stderr);
×
1118
          throw std::runtime_error("An error occured while parsing PKCS12 file " + pair.d_cert);
×
1119
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
×
1120
        }
×
1121
#endif /* defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 */
×
1122
      }
×
1123
      auto key = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(keyptr, EVP_PKEY_free);
1✔
1124
      auto cert = std::unique_ptr<X509, void(*)(X509*)>(certptr, X509_free);
1✔
1125
      auto ca = std::unique_ptr<STACK_OF(X509), void(*)(STACK_OF(X509)*)>(captr, [](STACK_OF(X509)* st){ sk_X509_free(st); });
1✔
1126

1127
      if (SSL_CTX_use_cert_and_key(ctx.get(), cert.get(), key.get(), ca.get(), 1) != 1) {
1!
1128
        ERR_print_errors_fp(stderr);
×
1129
        throw std::runtime_error("An error occurred while trying to load the TLS certificate and key from PKCS12 file " + pair.d_cert);
×
1130
      }
×
1131
#else
1132
      throw std::runtime_error("PKCS12 files are not supported by your openssl version");
1133
#endif /* HAVE_SSL_CTX_USE_CERT_AND_KEY */
1134
    } else {
23✔
1135
      if (SSL_CTX_use_certificate_chain_file(ctx.get(), pair.d_cert.c_str()) != 1) {
23!
1136
        ERR_print_errors_fp(stderr);
×
1137
        throw std::runtime_error("An error occurred while trying to load the TLS server certificate file: " + pair.d_cert);
×
1138
      }
×
1139
      if (SSL_CTX_use_PrivateKey_file(ctx.get(), pair.d_key->c_str(), SSL_FILETYPE_PEM) != 1) {
23!
1140
        ERR_print_errors_fp(stderr);
×
1141
        throw std::runtime_error("An error occurred while trying to load the TLS server private key file: " + pair.d_key.value());
×
1142
      }
×
1143
    }
23✔
1144

1145
    if (SSL_CTX_check_private_key(ctx.get()) != 1) {
24!
1146
      ERR_print_errors_fp(stderr);
×
1147
      throw std::runtime_error("The key from '" + pair.d_key.value() + "' does not match the certificate from '" + pair.d_cert + "'");
×
1148
    }
×
1149
    /* store the type of the new key, we might need it later to select the right OCSP stapling response */
1150
    auto keyType = libssl_get_last_key_type(*ctx);
24✔
1151
    if (keyType < 0) {
24!
1152
      throw std::runtime_error("The key from '" + pair.d_key.value() + "' has an unknown type");
×
1153
    }
×
1154
    keyTypes.push_back(keyType);
24✔
1155
 }
24✔
1156

1157
#ifndef DISABLE_OCSP_STAPLING
24✔
1158
  if (!config.d_ocspFiles.empty()) {
24✔
1159
    try {
4✔
1160
      ocspResponses = libssl_load_ocsp_responses(config.d_ocspFiles, std::move(keyTypes), warnings);
4✔
1161
    }
4✔
1162
    catch(const std::exception& e) {
4✔
1163
      throw std::runtime_error("Unable to load OCSP responses: " + std::string(e.what()));
×
1164
    }
×
1165
  }
4✔
1166
#endif /* DISABLE_OCSP_STAPLING */
24✔
1167

1168
  if (!config.d_ciphers.empty() && SSL_CTX_set_cipher_list(ctx.get(), config.d_ciphers.c_str()) != 1) {
24!
1169
    throw std::runtime_error("The TLS ciphers could not be set: " + config.d_ciphers);
×
1170
  }
×
1171

1172
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
24✔
1173
  if (!config.d_ciphers13.empty() && SSL_CTX_set_ciphersuites(ctx.get(), config.d_ciphers13.c_str()) != 1) {
24!
1174
    throw std::runtime_error("The TLS 1.3 ciphers could not be set: " + config.d_ciphers13);
×
1175
  }
×
1176
#endif /* HAVE_SSL_CTX_SET_CIPHERSUITES */
24✔
1177

1178
  return {std::move(ctx), std::move(warnings)};
24✔
1179
}
24✔
1180

1181
std::pair<pdns::libssl::ServerContext, std::vector<std::string>> libssl_init_server_context(const TLSConfig& config)
1182
{
67✔
1183
  std::vector<std::string> warnings;
67✔
1184
  pdns::libssl::ServerContext serverContext;
67✔
1185

1186
  std::vector<int> keyTypes;
67✔
1187
  /* load certificate and private key */
1188
  for (const auto& pair : config.d_certKeyPairs) {
71✔
1189
    auto uniqueCtx = getNewServerContext(config, warnings);
71✔
1190
    auto ctx = std::shared_ptr<SSL_CTX>(uniqueCtx.release(), SSL_CTX_free);
71✔
1191
    if (!pair.d_key) {
71✔
1192
#if defined(HAVE_SSL_CTX_USE_CERT_AND_KEY)
3✔
1193
      // If no separate key is given, treat it as a pkcs12 file
1194
      auto filePtr = pdns::UniqueFilePtr(fopen(pair.d_cert.c_str(), "r"));
3✔
1195
      if (!filePtr) {
3!
1196
        throw std::runtime_error("Unable to open file " + pair.d_cert);
×
1197
      }
×
1198
      auto p12 = std::unique_ptr<PKCS12, void(*)(PKCS12*)>(d2i_PKCS12_fp(filePtr.get(), nullptr), PKCS12_free);
3✔
1199
      if (!p12) {
3!
1200
        throw std::runtime_error("Unable to open PKCS12 file " + pair.d_cert);
×
1201
      }
×
1202
      EVP_PKEY *keyptr = nullptr;
3✔
1203
      X509 *certptr = nullptr;
3✔
1204
      STACK_OF(X509) *captr = nullptr;
3✔
1205
      if (PKCS12_parse(p12.get(), (pair.d_password ? pair.d_password->c_str() : nullptr), &keyptr, &certptr, &captr) != 1) {
3!
1206
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
×
1207
        bool failed = true;
×
1208
        /* we might be opening a PKCS12 file that uses RC2 CBC or 3DES CBC which, since OpenSSL 3.0.0, requires loading the legacy provider */
1209
        auto* libCtx = OSSL_LIB_CTX_get0_global_default();
×
1210
        /* check whether the legacy provider is already loaded */
1211
        if (OSSL_PROVIDER_available(libCtx, "legacy") == 0) {
×
1212
          /* it's not */
1213
          auto* provider = OSSL_PROVIDER_load(libCtx, "legacy");
×
1214
          if (provider != nullptr) {
×
1215
            if (PKCS12_parse(p12.get(), (pair.d_password ? pair.d_password->c_str() : nullptr), &keyptr, &certptr, &captr) == 1) {
×
1216
              failed = false;
×
1217
            }
×
1218
            /* we do not want to keep that provider around after that */
1219
            OSSL_PROVIDER_unload(provider);
×
1220
          }
×
1221
        }
×
1222
        if (failed) {
×
1223
#endif /* defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 */
×
1224
          ERR_print_errors_fp(stderr);
×
1225
          throw std::runtime_error("An error occured while parsing PKCS12 file " + pair.d_cert);
×
1226
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
×
1227
        }
×
1228
#endif /* defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 */
×
1229
      }
×
1230
      auto key = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(keyptr, EVP_PKEY_free);
3✔
1231
      auto cert = std::unique_ptr<X509, void(*)(X509*)>(certptr, X509_free);
3✔
1232
      auto caList = std::unique_ptr<STACK_OF(X509), void(*)(STACK_OF(X509)*)>(captr, [](STACK_OF(X509)* stack){ sk_X509_free(stack); });
3✔
1233

1234
      auto addCertificateAndKey = [&pair, &key, &cert, &caList](std::shared_ptr<SSL_CTX>& tlsContext) {
3✔
1235
        if (SSL_CTX_use_cert_and_key(tlsContext.get(), cert.get(), key.get(), caList.get(), 1) != 1) {
3!
1236
          ERR_print_errors_fp(stderr);
×
1237
          throw std::runtime_error("An error occurred while trying to load the TLS certificate and key from PKCS12 file " + pair.d_cert);
×
1238
        }
×
1239
      };
3✔
1240

1241
      addCertificateAndKey(ctx);
3✔
1242
      auto names = get_names_from_last_certificate(*ctx);
3✔
1243
      mergeNewCertificateAndKey(serverContext, ctx, names, addCertificateAndKey);
3✔
1244
#else
1245
      throw std::runtime_error("PKCS12 files are not supported by your openssl version");
1246
#endif /* HAVE_SSL_CTX_USE_CERT_AND_KEY */
1247
    } else {
68✔
1248
      auto addCertificateAndKey = [&pair](std::shared_ptr<SSL_CTX>& tlsContext) {
72✔
1249
        if (SSL_CTX_use_certificate_chain_file(tlsContext.get(), pair.d_cert.c_str()) != 1) {
72!
1250
          ERR_print_errors_fp(stderr);
×
1251
          throw std::runtime_error("An error occurred while trying to load the TLS server certificate file: " + pair.d_cert);
×
1252
        }
×
1253
        if (SSL_CTX_use_PrivateKey_file(tlsContext.get(), pair.d_key->c_str(), SSL_FILETYPE_PEM) != 1) {
72!
1254
          ERR_print_errors_fp(stderr);
×
1255
          throw std::runtime_error("An error occurred while trying to load the TLS server private key file: " + pair.d_key.value());
×
1256
        }
×
1257
      };
72✔
1258

1259
      addCertificateAndKey(ctx);
68✔
1260
      auto names = get_names_from_last_certificate(*ctx);
68✔
1261
      mergeNewCertificateAndKey(serverContext, ctx, names, addCertificateAndKey);
68✔
1262
    }
68✔
1263

1264
    if (SSL_CTX_check_private_key(ctx.get()) != 1) {
71!
1265
      ERR_print_errors_fp(stderr);
×
1266
      throw std::runtime_error("The key from '" + pair.d_key.value() + "' does not match the certificate from '" + pair.d_cert + "'");
×
1267
    }
×
1268
    /* store the type of the new key, we might need it later to select the right OCSP stapling response */
1269
    auto keyType = libssl_get_last_key_type(*ctx);
71✔
1270
    if (keyType < 0) {
71!
1271
      throw std::runtime_error("The key from '" + pair.d_key.value() + "' has an unknown type");
×
1272
    }
×
1273
    keyTypes.push_back(keyType);
71✔
1274
 }
71✔
1275

1276
#ifndef DISABLE_OCSP_STAPLING
67✔
1277
  if (!config.d_ocspFiles.empty()) {
67✔
1278
    try {
7✔
1279
      serverContext.d_ocspResponses = libssl_load_ocsp_responses(config.d_ocspFiles, std::move(keyTypes), warnings);
7✔
1280
    }
7✔
1281
    catch(const std::exception& e) {
7✔
1282
      throw std::runtime_error("Unable to load OCSP responses: " + std::string(e.what()));
×
1283
    }
×
1284
  }
7✔
1285
#endif /* DISABLE_OCSP_STAPLING */
67✔
1286

1287
  for (auto& entry : serverContext.d_sniMap) {
136✔
1288
    auto& ctx = entry.second;
136✔
1289
    if (!config.d_ciphers.empty() && SSL_CTX_set_cipher_list(ctx.get(), config.d_ciphers.c_str()) != 1) {
136!
1290
      throw std::runtime_error("The TLS ciphers could not be set: " + config.d_ciphers);
×
1291
    }
×
1292

1293
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
136✔
1294
    if (!config.d_ciphers13.empty() && SSL_CTX_set_ciphersuites(ctx.get(), config.d_ciphers13.c_str()) != 1) {
136!
1295
      throw std::runtime_error("The TLS 1.3 ciphers could not be set: " + config.d_ciphers13);
×
1296
    }
×
1297
#endif /* HAVE_SSL_CTX_SET_CIPHERSUITES */
136✔
1298
  }
136✔
1299

1300
  return {std::move(serverContext), std::move(warnings)};
67✔
1301
}
67✔
1302

1303
#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
1304
static void libssl_key_log_file_callback(const SSL* ssl, const char* line)
1305
{
80✔
1306
  SSL_CTX* sslCtx = SSL_get_SSL_CTX(ssl);
80✔
1307
  if (sslCtx == nullptr) {
80!
1308
    return;
×
1309
  }
×
1310

1311
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): OpenSSL's API
1312
  auto* filePtr = reinterpret_cast<FILE*>(SSL_CTX_get_ex_data(sslCtx, s_keyLogIndex));
80✔
1313
  if (filePtr == nullptr) {
80!
1314
    return;
×
1315
  }
×
1316

1317
  fprintf(filePtr, "%s\n", line);
80✔
1318
  fflush(filePtr);
80✔
1319
}
80✔
1320
#endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
1321

1322
pdns::UniqueFilePtr libssl_set_key_log_file([[maybe_unused]] SSL_CTX* ctx, [[maybe_unused]] const std::string& logFile)
1323
{
4✔
1324
#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
4✔
1325
  auto filePtr = pdns::openFileForWriting(logFile, 0600, false, true);
4✔
1326
  if (!filePtr) {
4!
1327
    auto error = errno;
×
1328
    throw std::runtime_error("Error opening file " + logFile + " for writing: " + stringerror(error));
×
1329
  }
×
1330
  SSL_CTX_set_ex_data(ctx, s_keyLogIndex, filePtr.get());
4✔
1331
  SSL_CTX_set_keylog_callback(ctx, &libssl_key_log_file_callback);
4✔
1332
  return filePtr;
4✔
1333
#else
1334
  return pdns::UniqueFilePtr(nullptr);
1335
#endif /* HAVE_SSL_CTX_SET_KEYLOG_CALLBACK */
1336
}
4✔
1337

1338
/* called in a client context, if the client advertised more than one ALPN value and the server returned more than one as well, to select the one to use. */
1339
void libssl_set_alpn_select_callback([[maybe_unused]] SSL_CTX* ctx, [[maybe_unused]] int (*callback)(SSL* ssl, const unsigned char** out, unsigned char* outlen, const unsigned char* inPtr, unsigned int inlen, void* arg), [[maybe_unused]] void* arg)
1340
{
136✔
1341
#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
136✔
1342
  SSL_CTX_set_alpn_select_cb(ctx, callback, arg);
136✔
1343
#endif
136✔
1344
}
136✔
1345

1346
bool libssl_set_alpn_protos([[maybe_unused]] SSL_CTX* ctx, [[maybe_unused]] const std::vector<std::vector<uint8_t>>& protos)
1347
{
37✔
1348
#ifdef HAVE_SSL_CTX_SET_ALPN_PROTOS
37✔
1349
  std::vector<uint8_t> wire;
37✔
1350
  for (const auto& proto : protos) {
37✔
1351
    if (proto.size() > std::numeric_limits<uint8_t>::max()) {
30!
1352
      throw std::runtime_error("Invalid ALPN value");
×
1353
    }
×
1354
    uint8_t length = proto.size();
30✔
1355
    wire.push_back(length);
30✔
1356
    wire.insert(wire.end(), proto.begin(), proto.end());
30✔
1357
  }
30✔
1358
  return SSL_CTX_set_alpn_protos(ctx, wire.data(), wire.size()) == 0;
37✔
1359
#else
1360
  return false;
1361
#endif
1362
}
37✔
1363

1364

1365
std::string libssl_get_error_string()
1366
{
1✔
1367
  BIO *mem = BIO_new(BIO_s_mem());
1✔
1368
  ERR_print_errors(mem);
1✔
1369
  char *p;
1✔
1370
  size_t len = BIO_get_mem_data(mem, &p);
1✔
1371
  std::string msg(p, len);
1✔
1372
  // replace newlines by /
1373
  if (msg.back() == '\n') {
1!
1374
    msg.pop_back();
1✔
1375
  }
1✔
1376
  std::replace(msg.begin(), msg.end(), '\n', '/');
1✔
1377
  BIO_free(mem);
1✔
1378
  return msg;
1✔
1379
}
1✔
1380
#endif /* HAVE_LIBSSL */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc