support.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 83 SSL accelerator support */
10 
11 #include "squid.h"
12 
13 /* MS Visual Studio Projects are monolithic, so we need the following
14  * #if to exclude the SSL code from compile process when not needed.
15  */
16 #if USE_OPENSSL
17 
18 #include "acl/FilledChecklist.h"
19 #include "anyp/Host.h"
20 #include "anyp/PortCfg.h"
21 #include "anyp/Uri.h"
22 #include "fatal.h"
23 #include "fd.h"
24 #include "fde.h"
25 #include "globals.h"
26 #include "ip/Address.h"
27 #include "ipc/MemMap.h"
28 #include "security/CertError.h"
29 #include "security/Certificate.h"
30 #include "security/ErrorDetail.h"
31 #include "security/Session.h"
32 #include "SquidConfig.h"
33 #include "ssl/bio.h"
34 #include "ssl/Config.h"
35 #include "ssl/ErrorDetail.h"
36 #include "ssl/gadgets.h"
37 #include "ssl/support.h"
38 
39 #include <cerrno>
40 
41 // TODO: Move ssl_ex_index_* global variables from global.cc here.
43 
44 const EVP_MD *Ssl::DefaultSignHash = nullptr;
45 
46 std::vector<const char *> Ssl::BumpModeStr = {
47  "none",
48  "client-first",
49  "server-first",
50  "peek",
51  "stare",
52  "bump",
53  "splice",
54  "terminate"
55  /*,"err"*/
56 };
57 
58 namespace Ssl {
59 
62 {
63 public:
64  explicit OneNameMatcher(const AnyP::Host &needle): needle_(needle) {}
65 
66 protected:
67  /* GeneralNameMatcher API */
68  bool matchDomainName(const Dns::DomainName &) const override;
69  bool matchIp(const Ip::Address &) const override;
70 
72 };
73 
74 static CertsIndexedList &
76 {
77  static auto untrustedCerts = new CertsIndexedList();
78  return *untrustedCerts;
79 }
80 
81 } // namespace Ssl
82 
83 bool
85 {
86  if (const auto domain = name.domainName())
87  return matchDomainName(*domain);
88  if (const auto ip = name.ip())
89  return matchIp(*ip);
90  Assure(!"unreachable code: the above `if` statements must cover all name variants");
91  return false;
92 }
93 
94 bool
96  // TODO: Add debugs() stream manipulator to safely (i.e. without breaking
97  // cache.log message framing) dump raw input that may contain new lines. Use
98  // here and in similar contexts where we report such raw input.
99  debugs(83, 5, "needle=" << needle_ << " domain=" << rawName);
100  if (needle_.ip()) {
101  // for example, a 127.0.0.1 IP needle does not match DNS:127.0.0.1 SAN
102  debugs(83, 7, "needle is an IP; mismatch");
103  return false;
104  }
105 
106  Assure(needle_.domainName());
107  auto domainNeedle = *needle_.domainName();
108 
109  auto name = rawName;
110  if (name.length() > 0 && name[0] == '*')
111  name.consume(1);
112 
113  return ::matchDomainName(domainNeedle.c_str(), name.c_str(), mdnRejectSubsubDomains) == 0;
114 }
115 
116 bool
118  debugs(83, 5, "needle=" << needle_ << " ip=" << ip);
119  if (const auto needleIp = needle_.ip())
120  return (*needleIp == ip);
121  debugs(83, 7, "needle is not an IP; mismatch");
122  return false;
123 }
124 
130 int
131 Ssl::AskPasswordCb(char *buf, int size, int /* rwflag */, void *userdata)
132 {
133  FILE *in;
134  int len = 0;
135  char cmdline[1024];
136 
137  snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", ::Config.Program.ssl_password, (const char *)userdata);
138  in = popen(cmdline, "r");
139 
140  if (fgets(buf, size, in))
141 
142  len = strlen(buf);
143 
144  while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
145  --len;
146 
147  buf[len] = '\0';
148 
149  pclose(in);
150 
151  return len;
152 }
153 
155 static void
156 ssl_ask_password(SSL_CTX * context, const char * prompt)
157 {
159  SSL_CTX_set_default_passwd_cb(context, Ssl::AskPasswordCb);
160  SSL_CTX_set_default_passwd_cb_userdata(context, (void *)prompt);
161  }
162 }
163 
164 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
165 static RSA *
166 ssl_temp_rsa_cb(SSL *, int, int keylen)
167 {
168  static RSA *rsa_512 = nullptr;
169  static RSA *rsa_1024 = nullptr;
170  static BIGNUM *e = nullptr;
171  RSA *rsa = nullptr;
172  int newkey = 0;
173 
174  if (!e) {
175  e = BN_new();
176  if (!e || !BN_set_word(e, RSA_F4)) {
177  debugs(83, DBG_IMPORTANT, "ERROR: ssl_temp_rsa_cb: Failed to set exponent for key " << keylen);
178  BN_free(e);
179  e = nullptr;
180  return nullptr;
181  }
182  }
183 
184  switch (keylen) {
185 
186  case 512:
187 
188  if (!rsa_512) {
189  rsa_512 = RSA_new();
190  if (rsa_512 && RSA_generate_key_ex(rsa_512, 512, e, nullptr)) {
191  newkey = 1;
192  } else {
193  RSA_free(rsa_512);
194  rsa_512 = nullptr;
195  }
196  }
197 
198  rsa = rsa_512;
199  break;
200 
201  case 1024:
202 
203  if (!rsa_1024) {
204  rsa_1024 = RSA_new();
205  if (rsa_1024 && RSA_generate_key_ex(rsa_1024, 1024, e, nullptr)) {
206  newkey = 1;
207  } else {
208  RSA_free(rsa_1024);
209  rsa_1024 = nullptr;
210  }
211  }
212 
213  rsa = rsa_1024;
214  break;
215 
216  default:
217  debugs(83, DBG_IMPORTANT, "ERROR: ssl_temp_rsa_cb: Unexpected key length " << keylen);
218  return nullptr;
219  }
220 
221  if (rsa == NULL) {
222  debugs(83, DBG_IMPORTANT, "ERROR: ssl_temp_rsa_cb: Failed to generate key " << keylen);
223  return nullptr;
224  }
225 
226  if (newkey) {
227  if (Debug::Enabled(83, 5))
228  PEM_write_RSAPrivateKey(DebugStream(), rsa, nullptr, nullptr, 0, nullptr, nullptr);
229 
230  debugs(83, DBG_IMPORTANT, "Generated ephemeral RSA key of length " << keylen);
231  }
232 
233  return rsa;
234 }
235 #endif
236 
237 void
239 {
240 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
241  debugs(83, 9, "Setting RSA key generation callback.");
242  SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb);
243 #else
244  (void)ctx;
245 #endif
246 }
247 
248 int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len)
249 {
250  BIO *bio;
251  int write = 0;
252  bio = BIO_new(BIO_s_mem());
253  if (bio) {
254  if (ASN1_TIME_print(bio, tm))
255  write = BIO_read(bio, buf, len-1);
256  BIO_free(bio);
257  }
258  buf[write]='\0';
259  return write;
260 }
261 
262 static std::optional<AnyP::Host>
263 ParseSubjectAltName(const GENERAL_NAME &san)
264 {
265  switch(san.type) {
266  case GEN_DNS: {
267  Assure(san.d.dNSName);
268  // GEN_DNS is an IA5STRING. IA5STRING is a subset of ASCII that does not
269  // need to be converted to UTF-8 (or some such) before we parse it.
270  const auto buffer = Ssl::AsnToSBuf(*san.d.dNSName);
271  return AnyP::Host::ParseWildDomainName(buffer);
272  }
273 
274  case GEN_IPADD: {
275  // san.d.iPAddress is OpenSSL ASN1_OCTET_STRING
276  Assure(san.d.iPAddress);
277 
278  // RFC 5280 section 4.2.1.6 signals IPv4/IPv6 address family using data length
279 
280  if (san.d.iPAddress->length == 4) {
281  struct in_addr addr;
282  static_assert(sizeof(addr.s_addr) == 4);
283  memcpy(&addr.s_addr, san.d.iPAddress->data, sizeof(addr.s_addr));
284  const Ip::Address ip(addr);
285  return AnyP::Host::ParseIp(ip);
286  }
287 
288  if (san.d.iPAddress->length == 16) {
289  struct in6_addr addr;
290  static_assert(sizeof(addr.s6_addr) == 16);
291  memcpy(&addr.s6_addr, san.d.iPAddress->data, sizeof(addr.s6_addr));
292  const Ip::Address ip(addr);
293  return AnyP::Host::ParseIp(ip);
294  }
295 
296  debugs(83, 3, "unexpected length of an IP address SAN: " << san.d.iPAddress->length);
297  return std::nullopt;
298  }
299 
300  default:
301  debugs(83, 3, "unsupported SAN kind: " << san.type);
302  return std::nullopt;
303  }
304 }
305 
306 bool
308 {
309  const auto name = X509_get_subject_name(&cert);
310  for (int i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
311  debugs(83, 7, "checking CN at " << i);
312  if (const auto cn = ParseCommonNameAt(*name, i)) {
313  if (matcher.match(*cn))
314  return true;
315  }
316  }
317 
318  const Ssl::GENERAL_NAME_STACK_Pointer sans(static_cast<STACK_OF(GENERAL_NAME)*>(
319  X509_get_ext_d2i(&cert, NID_subject_alt_name, nullptr, nullptr)));
320  if (sans) {
321  const auto sanCount = sk_GENERAL_NAME_num(sans.get());
322  for (int i = 0; i < sanCount; ++i) {
323  debugs(83, 7, "checking SAN at " << i);
324  const auto rawSan = sk_GENERAL_NAME_value(sans.get(), i);
325  Assure(rawSan);
326  if (const auto san = ParseSubjectAltName(*rawSan)) {
327  if (matcher.match(*san))
328  return true;
329  }
330  }
331  }
332 
333  debugs(83, 7, "no matches");
334  return false;
335 }
336 
337 bool
338 Ssl::HasSubjectName(X509 &cert, const AnyP::Host &host)
339 {
340  return HasMatchingSubjectName(cert, OneNameMatcher(host));
341 }
342 
345 static int
346 ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
347 {
348  // preserve original ctx->error before SSL_ calls can overwrite it
349  Security::ErrorCode error_no = ok ? SSL_ERROR_NONE : X509_STORE_CTX_get_error(ctx);
350 
351  SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
352  SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
353  SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server);
354  void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
355  ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
356  X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert);
357  Security::CertPointer peer_cert;
358  peer_cert.resetAndLock(X509_STORE_CTX_get0_cert(ctx));
359 
360  // detect infinite loops
361  uint32_t *validationCounter = static_cast<uint32_t *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter));
362  if (!validationCounter) {
363  validationCounter = new uint32_t(1);
364  SSL_set_ex_data(ssl, ssl_ex_index_ssl_validation_counter, validationCounter);
365  } else {
366  // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
367  (*validationCounter)++;
368  }
369 
370  if ((*validationCounter) >= SQUID_CERT_VALIDATION_ITERATION_MAX) {
371  ok = 0; // or the validation loop will never stop
373  debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
374  *validationCounter << " iterations while checking " << *peer_cert);
375  }
376 
377  if (ok) {
378  debugs(83, 5, "SSL Certificate signature OK: " << *peer_cert);
379 
380  // Check for domain mismatch only if the current certificate is the peer certificate.
381  if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) {
382  // XXX: This code does not know where the server name came from. The
383  // name may be valid but not compatible with requirements assumed or
384  // enforced by the AnyP::Host::ParseSimpleDomainName() call below.
385  // TODO: Store AnyP::Host (or equivalent) in ssl_ex_index_server.
386  if (const auto host = Ssl::ParseAsSimpleDomainNameOrIp(*server)) {
387  if (Ssl::HasSubjectName(*peer_cert, *host)) {
388  debugs(83, 5, "certificate subject matches " << *host);
389  } else {
390  debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << *peer_cert << " does not match domainname " << *host);
391  ok = 0;
393  }
394  } else {
395  debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Cannot check whether certificate " << *peer_cert << " subject matches malformed domainname " << *server);
396  ok = 0;
398  }
399  }
400  }
401 
402  if (ok && peeked_cert) {
403  // Check whether the already peeked certificate matches the new one.
404  if (X509_cmp(peer_cert.get(), peeked_cert) != 0) {
405  debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << *peer_cert << " does not match peeked certificate");
406  ok = 0;
407  error_no = SQUID_X509_V_ERR_CERT_CHANGE;
408  }
409  }
410 
411  if (!ok && error_no == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
412  if (const auto params = Ssl::VerifyCallbackParameters::Find(*ssl)) {
413  if (params->callerHandlesMissingCertificates) {
414  debugs(83, 3, "hiding X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY");
415  params->hidMissingIssuer = true;
416  ok = 1;
417  }
418  }
419  }
420 
421  if (!ok) {
422  Security::CertPointer broken_cert;
423  broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx));
424  if (!broken_cert)
425  broken_cert = peer_cert;
426 
427  Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
428  const int depth = X509_STORE_CTX_get_error_depth(ctx);
429  if (!errs) {
430  errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth));
431  if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
432  debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << *peer_cert);
433  delete errs;
434  errs = nullptr;
435  }
436  } else // remember another error number
437  errs->push_back_unique(Security::CertError(error_no, broken_cert, depth));
438 
439  if (const auto description = Ssl::GetErrorDescr(error_no))
440  debugs(83, 5, *description << ": " << *peer_cert);
441  else
442  debugs(83, DBG_IMPORTANT, "ERROR: SSL unknown certificate error " << error_no << " in " << *peer_cert);
443 
444  // Check if the certificate error can be bypassed.
445  // Infinity validation loop errors can not bypassed.
446  if (error_no != SQUID_X509_V_ERR_INFINITE_VALIDATION) {
447  if (check) {
448  ACLFilledChecklist *filledCheck = Filled(check);
449  const auto savedErrors = filledCheck->sslErrors;
450  const auto sslErrors = std::make_unique<Security::CertErrors>(Security::CertError(error_no, broken_cert));
451  filledCheck->sslErrors = sslErrors.get();
452  filledCheck->serverCert = peer_cert;
453  if (check->fastCheck().allowed()) {
454  debugs(83, 3, "bypassing SSL error " << error_no << " in " << *peer_cert);
455  ok = 1;
456  } else {
457  debugs(83, 5, "confirming SSL error " << error_no);
458  }
459  filledCheck->sslErrors = savedErrors;
460  filledCheck->serverCert.reset();
461  }
462  // If the certificate validator is used then we need to allow all errors and
463  // pass them to certificate validator for more processing
464  else if (Ssl::TheConfig.ssl_crt_validator) {
465  ok = 1;
466  }
467  }
468  }
469 
470  if (Ssl::TheConfig.ssl_crt_validator) {
471  // Check if we have stored certificates chain. Store if not.
472  if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
473  STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
474  if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
475  sk_X509_pop_free(certStack, X509_free);
476  }
477  }
478 
479  if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
480 
481  // Find the broken certificate. It may be intermediate.
482  Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails
483  // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
484  if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
485  if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
486  broken_cert.resetAndLock(last_used_cert);
487  }
488 
489  std::unique_ptr<Security::ErrorDetail::Pointer> edp(new Security::ErrorDetail::Pointer(
490  new Security::ErrorDetail(error_no, peer_cert, broken_cert)));
491  if (SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, edp.get()))
492  edp.release();
493  else
494  debugs(83, 2, "failed to store a " << *peer_cert << " error detail: " << *edp);
495  }
496 
497  return ok;
498 }
499 
500 void
502 {
503  int mode;
504 
505  // assume each flag is exclusive; flags creator must check this assumption
506  if (flags & SSL_FLAG_DONT_VERIFY_PEER) {
507  debugs(83, DBG_IMPORTANT, "SECURITY WARNING: Peer certificates are not verified for validity!");
508  debugs(83, DBG_IMPORTANT, "WARNING: UPGRADE: The DONT_VERIFY_PEER flag is deprecated. Remove the clientca= option to disable client certificates.");
509  mode = SSL_VERIFY_NONE;
510  }
511  else if (flags & SSL_FLAG_DELAYED_AUTH) {
512  debugs(83, DBG_PARSE_NOTE(3), "not requesting client certificates until ACL processing requires one");
513  mode = SSL_VERIFY_NONE;
514  }
515  else if (flags & SSL_FLAG_CONDITIONAL_AUTH) {
516  debugs(83, DBG_PARSE_NOTE(3), "will request the client certificate but ignore its absence");
517  mode = SSL_VERIFY_PEER;
518  }
519  else {
520  debugs(83, DBG_PARSE_NOTE(3), "Requiring client certificates.");
521  mode = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
522  }
523 
524  SSL_CTX_set_verify(ctx.get(), mode, (mode != SSL_VERIFY_NONE) ? ssl_verify_cb : nullptr);
525 }
526 
527 void
529 {
530  debugs(83, DBG_PARSE_NOTE(3), "Not requiring any client certificates");
531  SSL_CTX_set_verify(ctx.get(),SSL_VERIFY_NONE,nullptr);
532 }
533 
534 static int VerifyCtxCertificates(X509_STORE_CTX *ctx, STACK_OF(X509) *extraCerts);
535 
536 bool
538 {
539  const auto peerCertificatesChain = SSL_get_peer_cert_chain(&sconn);
540 
541  // TODO: Replace debugs/return false with returning ErrorDetail::Pointer.
542  // Using Security::ErrorDetail terminology, errors in _this_ function are
543  // "non-validation errors", but VerifyCtxCertificates() errors may be
544  // "certificate validation errors". Callers detail SQUID_TLS_ERR_CONNECT.
545  // Some details should be created right here. Others extracted from OpenSSL.
546  // Why not throw? Most of the reasons detailed in the following commit apply
547  // here as well: https://github.com/measurement-factory/squid/commit/e862d33
548 
549  if (!peerCertificatesChain || sk_X509_num(peerCertificatesChain) == 0) {
550  debugs(83, 2, "no server certificates");
551  return false;
552  }
553 
554  const auto verificationStore = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(&sconn));
555  if (!verificationStore) {
556  debugs(83, 2, "no certificate store");
557  return false;
558  }
559 
560  const X509_STORE_CTX_Pointer storeCtx(X509_STORE_CTX_new());
561  if (!storeCtx) {
562  debugs(83, 2, "cannot create X509_STORE_CTX; likely OOM");
563  return false;
564  }
565 
566  const auto peerCert = sk_X509_value(peerCertificatesChain, 0);
567  if (!X509_STORE_CTX_init(storeCtx.get(), verificationStore, peerCert, peerCertificatesChain)) {
568  debugs(83, 2, "cannot initialize X509_STORE_CTX");
569  return false;
570  }
571 
572 #if defined(SSL_CERT_FLAG_SUITEB_128_LOS)
573  // overwrite context Suite B (RFC 5759) flags with connection non-defaults
574  // SSL_set_cert_flags() return type is long, but its implementation actually
575  // returns an unsigned long flags value expected by X509_STORE_CTX_set_flags
576  const unsigned long certFlags = SSL_set_cert_flags(&sconn, 0);
577  if (const auto suiteBflags = certFlags & SSL_CERT_FLAG_SUITEB_128_LOS)
578  X509_STORE_CTX_set_flags(storeCtx.get(), suiteBflags);
579 #endif
580 
581  if (!X509_STORE_CTX_set_ex_data(storeCtx.get(), SSL_get_ex_data_X509_STORE_CTX_idx(), &sconn)) {
582  debugs(83, 2, "cannot attach SSL object to X509_STORE_CTX");
583  return false;
584  }
585 
586  // If we ever add DANE support to Squid, we will supply DANE details here:
587  // X509_STORE_CTX_set0_dane(storeCtx.get(), SSL_get0_dane(&sconn));
588 
589  // tell OpenSSL we are verifying a server certificate
590  if (!X509_STORE_CTX_set_default(storeCtx.get(), "ssl_server")) {
591  debugs(83, 2, "cannot set default verification method to ssl_server");
592  return false;
593  }
594 
595  // overwrite context "verification parameters" with connection non-defaults
596  const auto param = X509_STORE_CTX_get0_param(storeCtx.get());
597  if (!param) {
598  debugs(83, 2, "no context verification parameters");
599  return false;
600  }
601 #if defined(HAVE_X509_VERIFY_PARAM_SET_AUTH_LEVEL)
602  X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(&sconn));
603 #endif
604  if (!X509_VERIFY_PARAM_set1(param, SSL_get0_param(&sconn))) {
605  debugs(83, 2, "cannot overwrite context verification parameters");
606  return false;
607  }
608 
609  // copy any connection "verify_callback function" to the validation context
610  // (\ref OpenSSL_vcb_disambiguation)
611  if (const auto cb = SSL_get_verify_callback(&sconn))
612  X509_STORE_CTX_set_verify_cb(storeCtx.get(), cb);
613 
614  // verify the server certificate chain in the prepared validation context
615  if (VerifyCtxCertificates(storeCtx.get(), extraCerts.get()) <= 0) {
616  // see also: ssl_verify_cb() details errors via ssl_ex_index_ssl_errors
617  const auto verifyResult = X509_STORE_CTX_get_error(storeCtx.get());
618  debugs(83, 3, "verification failure: " << verifyResult << ' ' << X509_verify_cert_error_string(verifyResult));
619  return false;
620  }
621 
622  debugs(83, 7, "success");
623  return true;
624 }
625 
626 /* Ssl::VerifyCallbackParameters */
627 
630 {
631  return static_cast<VerifyCallbackParameters*>(SSL_get_ex_data(&sconn, ssl_ex_index_verify_callback_parameters));
632 }
633 
636 {
637  Must(!Find(sconn));
638  const auto parameters = new VerifyCallbackParameters();
639  if (!SSL_set_ex_data(&sconn, ssl_ex_index_verify_callback_parameters, parameters)) {
640  delete parameters;
641  throw TextException("SSL_set_ex_data() failed; likely OOM", Here());
642  }
643  return parameters;
644 }
645 
648 {
649  const auto parameters = Find(sconn);
650  Must(parameters);
651  return *parameters;
652 }
653 
654 // "dup" function for SSL_get_ex_new_index("cert_err_check")
655 #if OPENSSL_VERSION_MAJOR >= 3
656 static int
657 ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void **,
658  int, long, void *)
659 #elif SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
660 static int
661 ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
662  int, long, void *)
663 #else
664 static int
665 ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
666  int, long, void *)
667 #endif
668 {
669  // We do not support duplication of ACLCheckLists.
670  // If duplication is needed, we can count copies with cbdata.
671  assert(false);
672  return 0;
673 }
674 
675 // "free" function for SSL_get_ex_new_index("cert_err_check")
676 static void
677 ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
678  int, long, void *)
679 {
680  delete static_cast<ACLChecklist *>(ptr); // may be NULL
681 }
682 
683 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
684 static void
685 ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
686  int, long, void *)
687 {
688  const auto errDetail = static_cast<Security::ErrorDetail::Pointer*>(ptr);
689  delete errDetail;
690 }
691 
692 static void
693 ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
694  int, long, void *)
695 {
696  Security::CertErrors *errs = static_cast <Security::CertErrors*>(ptr);
697  delete errs;
698 }
699 
700 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
701 static void
702 ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *,
703  int, long, void *)
704 {
705  uint32_t *counter = static_cast <uint32_t *>(ptr);
706  delete counter;
707 }
708 
712 static void
713 ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
714  int, long, void *)
715 {
716  STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
717  sk_X509_pop_free(certsChain,X509_free);
718 }
719 
720 // "free" function for X509 certificates
721 static void
722 ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
723  int, long, void *)
724 {
725  X509 *cert = static_cast <X509 *>(ptr);
726  X509_free(cert);
727 }
728 
729 // "free" function for SBuf
730 static void
731 ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *,
732  int, long, void *)
733 {
734  SBuf *buf = static_cast <SBuf *>(ptr);
735  delete buf;
736 }
737 
739 static void
740 ssl_free_VerifyCallbackParameters(void *, void *ptr, CRYPTO_EX_DATA *,
741  int, long, void *)
742 {
743  delete static_cast<Ssl::VerifyCallbackParameters*>(ptr);
744 }
745 
746 void
748 {
749  static bool initialized = false;
750  if (initialized)
751  return;
752  initialized = true;
753 
755 
756  if (::Config.SSL.ssl_engine) {
757 #if OPENSSL_VERSION_MAJOR < 3
758  debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: Support for ssl_engine is deprecated " <<
759  "in Squids built with OpenSSL 1.x (like this Squid). " <<
760  "It is removed in Squids built with OpenSSL 3.0 or newer.");
761 #if !defined(OPENSSL_NO_ENGINE)
762  ENGINE_load_builtin_engines();
763  ENGINE *e;
764  if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine)))
765  fatalf("Unable to find SSL engine '%s'\n", ::Config.SSL.ssl_engine);
766 
767  if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
768  const auto ssl_error = ERR_get_error();
769  fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error));
770  }
771 #else /* OPENSSL_NO_ENGINE */
772  throw TextException("Cannot use ssl_engine in Squid built with OpenSSL configured to disable SSL engine support", Here());
773 #endif
774 
775 #else /* OPENSSL_VERSION_MAJOR */
776  throw TextException("Cannot use ssl_engine in Squid built with OpenSSL 3.0 or newer", Here());
777 #endif
778  }
779 
780  const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE;
781  Ssl::DefaultSignHash = EVP_get_digestbyname(defName);
783  fatalf("Sign hash '%s' is not supported\n", defName);
784 
785  ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", nullptr, nullptr, ssl_free_SBuf);
786  ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", nullptr, nullptr, nullptr);
787  ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", nullptr, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
788  ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", nullptr, nullptr, &ssl_free_ErrorDetail);
789  ssl_ex_index_ssl_peeked_cert = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", nullptr, nullptr, &ssl_free_X509);
790  ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", nullptr, nullptr, &ssl_free_SslErrors);
791  ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", nullptr, nullptr, &ssl_free_CertChain);
792  ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", nullptr, nullptr, &ssl_free_int);
793  ssl_ex_index_verify_callback_parameters = SSL_get_ex_new_index(0, (void *) "verify_callback_parameters", nullptr, nullptr, &ssl_free_VerifyCallbackParameters);
794 }
795 
796 bool
798 {
799  if (!ctx)
800  return false;
801 
802  return true;
803 }
804 
805 bool
807 {
808  if (!ctx)
809  return false;
810 
811  if (!peer.sslCipher.isEmpty()) {
812  debugs(83, 5, "Using chiper suite " << peer.sslCipher << ".");
813 
814  const char *cipher = peer.sslCipher.c_str();
815  if (!SSL_CTX_set_cipher_list(ctx.get(), cipher)) {
816  const auto ssl_error = ERR_get_error();
817  fatalf("Failed to set SSL cipher suite '%s': %s\n",
818  cipher, Security::ErrorString(ssl_error));
819  }
820  }
821 
822  if (!peer.certs.empty()) {
823  // TODO: support loading multiple cert/key pairs
824  auto &keys = peer.certs.front();
825  if (!keys.certFile.isEmpty()) {
826  debugs(83, 2, "loading client certificate from " << keys.certFile);
827 
828  const char *certfile = keys.certFile.c_str();
829  if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
830  const auto ssl_error = ERR_get_error();
831  fatalf("Failed to acquire SSL certificate '%s': %s\n",
832  certfile, Security::ErrorString(ssl_error));
833  }
834 
835  debugs(83, 2, "loading private key from " << keys.privateKeyFile);
836  const char *keyfile = keys.privateKeyFile.c_str();
837  ssl_ask_password(ctx.get(), keyfile);
838 
839  if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
840  const auto ssl_error = ERR_get_error();
841  fatalf("Failed to acquire SSL private key '%s': %s\n",
842  keyfile, Security::ErrorString(ssl_error));
843  }
844 
845  debugs(83, 5, "Comparing private and public SSL keys.");
846 
847  if (!SSL_CTX_check_private_key(ctx.get())) {
848  const auto ssl_error = ERR_get_error();
849  fatalf("SSL private key '%s' does not match public key '%s': %s\n",
850  certfile, keyfile, Security::ErrorString(ssl_error));
851  }
852  }
853  }
854 
856 
858 
859  return true;
860 }
861 
863 static const char *
864 ssl_get_attribute(X509_NAME * name, const char *attribute_name)
865 {
866  static char buffer[1024];
867  buffer[0] = '\0';
868 
869  if (strcmp(attribute_name, "DN") == 0) {
870  X509_NAME_oneline(name, buffer, sizeof(buffer));
871  } else {
872  int nid = OBJ_txt2nid(const_cast<char *>(attribute_name));
873  if (nid == 0) {
874  debugs(83, DBG_IMPORTANT, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
875  return nullptr;
876  }
877  X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
878  }
879 
880  return *buffer ? buffer : nullptr;
881 }
882 
884 const char *
885 Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name)
886 {
887  X509_NAME *name;
888  const char *ret;
889 
890  if (!cert)
891  return nullptr;
892 
893  name = X509_get_subject_name(cert);
894 
895  ret = ssl_get_attribute(name, attribute_name);
896 
897  return ret;
898 }
899 
900 const char *
901 Ssl::GetX509Fingerprint(X509 * cert, const char *)
902 {
903  static char buf[1024];
904  if (!cert)
905  return nullptr;
906 
907  unsigned int n;
908  unsigned char md[EVP_MAX_MD_SIZE];
909  if (!X509_digest(cert, EVP_sha1(), md, &n))
910  return nullptr;
911 
912  assert(3 * n + 1 < sizeof(buf));
913 
914  char *s = buf;
915  for (unsigned int i=0; i < n; ++i, s += 3) {
916  const char term = (i + 1 < n) ? ':' : '\0';
917  snprintf(s, 4, "%02X%c", md[i], term);
918  }
919 
920  return buf;
921 }
922 
923 SBuf
924 Ssl::GetX509PEM(X509 * cert)
925 {
926  assert(cert);
927 
928  Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
929  PEM_write_bio_X509(bio.get(), cert);
930 
931  char *ptr;
932  const auto len = BIO_get_mem_data(bio.get(), &ptr);
933  return SBuf(ptr, len);
934 }
935 
937 const char *
938 Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
939 {
940 
941  X509_NAME *name;
942  const char *ret;
943 
944  if (!cert)
945  return nullptr;
946 
947  name = X509_get_issuer_name(cert);
948 
949  ret = ssl_get_attribute(name, attribute_name);
950 
951  return ret;
952 }
953 
954 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name)
955 {
956  if (!ssl)
957  return nullptr;
958 
959  X509 *cert = SSL_get_peer_certificate(ssl);
960 
961  const char *attr = Ssl::GetX509UserAttribute(cert, attribute_name);
962 
963  X509_free(cert);
964  return attr;
965 }
966 
967 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name)
968 {
969  if (!ssl)
970  return nullptr;
971 
972  X509 *cert = SSL_get_peer_certificate(ssl);
973 
974  const char *attr = Ssl::GetX509CAAttribute(cert, attribute_name);
975 
976  X509_free(cert);
977  return attr;
978 }
979 
980 const char *
981 sslGetUserEmail(SSL * ssl)
982 {
983  return sslGetUserAttribute(ssl, "emailAddress");
984 }
985 
986 SBuf
988 {
989  assert(ssl);
990 
991  if (const auto cert = SSL_get_peer_certificate(ssl))
992  return Ssl::GetX509PEM(cert);
993 
994  return SBuf();
995 }
996 
997 SBuf
999 {
1000  assert(ssl);
1001 
1002  auto chain = SSL_get_peer_cert_chain(ssl);
1003 
1004  if (!chain)
1005  return sslGetUserCertificatePEM(ssl);
1006 
1007  Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
1008 
1009  for (int i = 0; i < sk_X509_num(chain); ++i) {
1010  X509 *cert = sk_X509_value(chain, i);
1011  PEM_write_bio_X509(bio.get(), cert);
1012  }
1013 
1014  char *ptr;
1015  const auto len = BIO_get_mem_data(bio.get(), &ptr);
1016  return SBuf(ptr, len);
1017 }
1018 
1021 Ssl::createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &options)
1022 {
1024 
1025  if (!SSL_CTX_use_certificate(ctx.get(), x509.get()))
1026  return Security::ContextPointer();
1027 
1028  if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()))
1029  return Security::ContextPointer();
1030 
1031  if (!options.updateContextConfig(ctx))
1032  return Security::ContextPointer();
1033 
1034  return ctx;
1035 }
1036 
1039 {
1040  Security::CertPointer cert;
1041  Security::PrivateKeyPointer pkey;
1042  if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
1043  return Security::ContextPointer();
1044 
1045  Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
1046  if (ctx && trusted)
1047  Ssl::chainCertificatesToSSLContext(ctx, options);
1048  return ctx;
1049 }
1050 
1053 {
1054  Security::CertPointer cert;
1055  Security::PrivateKeyPointer pkey;
1056  if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
1057  return Security::ContextPointer();
1058 
1059  Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
1060  if (ctx && trusted)
1061  Ssl::chainCertificatesToSSLContext(ctx, options);
1062  return ctx;
1063 }
1064 
1065 void
1067 {
1068  assert(ctx);
1069  // Add signing certificate to the certificates chain
1070  X509 *signingCert = options.signingCa.cert.get();
1071  if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) {
1072  // increase the certificate lock
1073  X509_up_ref(signingCert);
1074  } else {
1075  const auto ssl_error = ERR_get_error();
1076  debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error));
1077  }
1078 
1079  for (auto cert : options.signingCa.chain) {
1080  if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert.get())) {
1081  // increase the certificate lock
1082  X509_up_ref(cert.get());
1083  } else {
1084  const auto error = ERR_get_error();
1085  debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL dynamic context chain: " << Security::ErrorString(error));
1086  }
1087  }
1088 }
1089 
1090 void
1092 {
1093  if (ctx && signAlgorithm == Ssl::algSignTrusted)
1095 }
1096 
1097 bool
1099 {
1100  Security::CertPointer cert;
1101  Security::PrivateKeyPointer pkey;
1102  if (!generateSslCertificate(cert, pkey, properties))
1103  return false;
1104 
1105  if (!cert)
1106  return false;
1107 
1108  if (!pkey)
1109  return false;
1110 
1111  if (!SSL_use_certificate(ssl, cert.get()))
1112  return false;
1113 
1114  if (!SSL_use_PrivateKey(ssl, pkey.get()))
1115  return false;
1116 
1117  return true;
1118 }
1119 
1120 bool
1122 {
1123  Security::CertPointer cert;
1124  Security::PrivateKeyPointer pkey;
1125  if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
1126  return false;
1127 
1128  if (!cert || !pkey)
1129  return false;
1130 
1131  if (!SSL_use_certificate(ssl, cert.get()))
1132  return false;
1133 
1134  if (!SSL_use_PrivateKey(ssl, pkey.get()))
1135  return false;
1136 
1137  return true;
1138 }
1139 
1140 bool
1142 {
1143 #if HAVE_SSL_CTX_GET0_CERTIFICATE
1144  X509 * cert = SSL_CTX_get0_certificate(ctx.get());
1145 #elif SQUID_USE_SSLGETCERTIFICATE_HACK
1146  // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
1147  // Try to retrieve certificate directly from Security::ContextPointer object
1148  X509 ***pCert = (X509 ***)ctx->cert;
1149  X509 * cert = pCert && *pCert ? **pCert : NULL;
1150 #elif SQUID_SSLGETCERTIFICATE_BUGGY
1151  X509 * cert = nullptr;
1152  assert(0);
1153 #else
1154  // Temporary ssl for getting X509 certificate from SSL_CTX.
1156  X509 * cert = SSL_get_certificate(ssl.get());
1157 #endif
1158  if (!cert)
1159  return false;
1160  const auto time_notBefore = X509_getm_notBefore(cert);
1161  const auto time_notAfter = X509_getm_notAfter(cert);
1162  return (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
1163 }
1164 
1165 void
1166 Ssl::setClientSNI(SSL *ssl, const char *fqdn)
1167 {
1168  const Ip::Address test(fqdn);
1169  if (!test.isAnyAddr())
1170  return; // raw IP is inappropriate for SNI
1171 
1172  //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
1173  // if the TLS servername extension (SNI) is enabled in openssl library.
1174 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
1175  if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
1176  const auto ssl_error = ERR_get_error();
1177  debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
1178  Security::ErrorString(ssl_error) << "\n");
1179  }
1180 #else
1181  debugs(83, 7, "no support for TLS servername extension (SNI)");
1182 #endif
1183 }
1184 
1185 const char *
1187 {
1188  AUTHORITY_INFO_ACCESS *info;
1189  if (!cert)
1190  return nullptr;
1191  info = static_cast<AUTHORITY_INFO_ACCESS *>(X509_get_ext_d2i(cert, NID_info_access, nullptr, nullptr));
1192  if (!info)
1193  return nullptr;
1194 
1195  static char uri[MAX_URL];
1196  uri[0] = '\0';
1197 
1198  for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
1199  ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
1200  if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
1201  if (ad->location->type == GEN_URI) {
1202  xstrncpy(uri,
1203  reinterpret_cast<const char *>(
1204  ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier)
1205  ),
1206  sizeof(uri));
1207  }
1208  break;
1209  }
1210  }
1211  AUTHORITY_INFO_ACCESS_free(info);
1212  return uri[0] != '\0' ? uri : nullptr;
1213 }
1214 
1215 bool
1216 Ssl::loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
1217 {
1218  const BIO_Pointer in(BIO_new_file(certsFile, "r"));
1219  if (!in) {
1220  debugs(83, DBG_IMPORTANT, "ERROR: Failed to open '" << certsFile << "' to load certificates");
1221  return false;
1222  }
1223 
1224  while (auto aCert = ReadOptionalCertificate(in)) {
1225  const auto name = Security::SubjectName(*aCert);
1226  list.insert(std::pair<SBuf, X509 *>(name, aCert.release()));
1227  }
1228  debugs(83, 4, "Loaded " << list.size() << " certificates from file: '" << certsFile << "'");
1229  return true;
1230 }
1231 
1234 static X509 *
1236 {
1237  const auto name = Security::IssuerName(*cert);
1238  if (name.isEmpty())
1239  return nullptr;
1240 
1241  const auto ret = list.equal_range(name);
1242  for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) {
1243  X509 *issuer = it->second;
1244  if (Security::IssuedBy(*cert, *issuer)) {
1245  return issuer;
1246  }
1247  }
1248  return nullptr;
1249 }
1250 
1252 static X509 *
1253 sk_x509_findIssuer(const STACK_OF(X509) *sk, X509 *cert)
1254 {
1255  if (!sk)
1256  return nullptr;
1257 
1258  const auto certCount = sk_X509_num(sk);
1259  for (int i = 0; i < certCount; ++i) {
1260  const auto issuer = sk_X509_value(sk, i);
1261  if (Security::IssuedBy(*cert, *issuer))
1262  return issuer;
1263  }
1264  return nullptr;
1265 }
1266 
1269 static X509 *
1270 findIssuerInCaDb(X509 *cert, const Security::ContextPointer &connContext)
1271 {
1272  if (!connContext)
1273  return nullptr;
1274 
1275  X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
1276  if (!storeCtx) {
1277  debugs(83, DBG_IMPORTANT, "ERROR: Failed to allocate STORE_CTX object");
1278  return nullptr;
1279  }
1280 
1281  X509 *issuer = nullptr;
1282  X509_STORE *store = SSL_CTX_get_cert_store(connContext.get());
1283  if (X509_STORE_CTX_init(storeCtx, store, nullptr, nullptr)) {
1284  const auto ret = X509_STORE_CTX_get1_issuer(&issuer, storeCtx, cert);
1285  if (ret > 0) {
1286  assert(issuer);
1287  debugs(83, 5, "found " << *issuer);
1288  } else {
1289  debugs(83, ret < 0 ? 2 : 3, "not found or failure: " << ret);
1290  assert(!issuer);
1291  }
1292  } else {
1293  const auto ssl_error = ERR_get_error();
1294  debugs(83, DBG_IMPORTANT, "ERROR: Failed to initialize STORE_CTX object: " << Security::ErrorString(ssl_error));
1295  }
1296 
1297  X509_STORE_CTX_free(storeCtx);
1298 
1299  return issuer;
1300 }
1301 
1303 Ssl::findIssuerCertificate(X509 *cert, const STACK_OF(X509) *serverCertificates, const Security::ContextPointer &context)
1304 {
1305  Must(cert);
1306 
1307  // check certificate chain, if any
1308  if (const auto issuer = serverCertificates ? sk_x509_findIssuer(serverCertificates, cert) : nullptr) {
1309  X509_up_ref(issuer);
1310  return Security::CertPointer(issuer);
1311  }
1312 
1313  // check untrusted certificates
1314  if (const auto issuer = findCertIssuerFast(SquidUntrustedCerts(), cert)) {
1315  X509_up_ref(issuer);
1316  return Security::CertPointer(issuer);
1317  }
1318 
1319  // check trusted CA certificates
1320  if (const auto issuer = findIssuerInCaDb(cert, context)) {
1321  // no X509_up_ref(issuer) because findIssuerInCaDb() ups reference count
1322  return Security::CertPointer(issuer);
1323  }
1324 
1325  return Security::CertPointer(nullptr);
1326 }
1327 
1328 bool
1329 Ssl::missingChainCertificatesUrls(std::queue<SBuf> &URIs, const STACK_OF(X509) &serverCertificates, const Security::ContextPointer &context)
1330 {
1331  for (int i = 0; i < sk_X509_num(&serverCertificates); ++i) {
1332  const auto cert = sk_X509_value(&serverCertificates, i);
1333 
1334  if (findIssuerCertificate(cert, &serverCertificates, context))
1335  continue;
1336 
1337  if (const auto issuerUri = findIssuerUri(cert)) {
1338  URIs.push(SBuf(issuerUri));
1339  } else {
1340  debugs(83, 3, "Issuer certificate for " <<
1341  *cert <<
1342  " is missing and its URI is not provided");
1343  }
1344  }
1345 
1346  debugs(83, (URIs.empty() ? 3 : 5), "found: " << URIs.size());
1347  return !URIs.empty();
1348 }
1349 
1351 static void
1352 completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) &untrustedCerts)
1353 {
1354  debugs(83, 2, "completing " << sk_X509_num(&untrustedCerts) <<
1355  " OpenSSL untrusted certs using " << Ssl::SquidUntrustedCerts().size() <<
1356  " configured untrusted certificates");
1357 
1358  const X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx);
1359  int depth = X509_VERIFY_PARAM_get_depth(param);
1360  Security::CertPointer current;
1361  current.resetAndLock(X509_STORE_CTX_get0_cert(ctx));
1362  int i = 0;
1363  for (i = 0; current && (i < depth); ++i) {
1364  if (Security::SelfSigned(*current)) {
1365  // either ctx->cert is itself self-signed or untrustedCerts
1366  // already contain the self-signed current certificate
1367  break;
1368  }
1369 
1370  // untrustedCerts is short, not worth indexing
1371  const Security::ContextPointer nullCtx;
1372  auto issuer = Ssl::findIssuerCertificate(current.get(), &untrustedCerts, nullCtx);
1373  current = issuer;
1374  if (issuer)
1375  sk_X509_push(&untrustedCerts, issuer.release());
1376  }
1377 
1378  if (i >= depth)
1379  debugs(83, 2, "exceeded the maximum certificate chain length: " << depth);
1380 }
1381 
1385 static int
1386 VerifyCtxCertificates(X509_STORE_CTX *ctx, STACK_OF(X509) *extraCerts)
1387 {
1388  // OpenSSL already maintains ctx->untrusted but we cannot modify
1389  // internal OpenSSL list directly. We have to give OpenSSL our own
1390  // list, but it must include certificates on the OpenSSL ctx->untrusted
1391  STACK_OF(X509) *oldUntrusted = X509_STORE_CTX_get0_untrusted(ctx);
1392  // X509_chain_up_ref() increments cert references _and_ dupes the stack
1393  Ssl::X509_STACK_Pointer untrustedCerts(oldUntrusted ? X509_chain_up_ref(oldUntrusted) : sk_X509_new_null());
1394 
1395  if (extraCerts) {
1396  for (int i = 0; i < sk_X509_num(extraCerts); ++i) {
1397  const auto cert = sk_X509_value(extraCerts, i);
1398  X509_up_ref(cert);
1399  sk_X509_push(untrustedCerts.get(), cert);
1400  }
1401  }
1402 
1403  // If the local untrusted certificates internal database is used
1404  // run completeIssuers to add missing certificates if possible.
1405  if (Ssl::SquidUntrustedCerts().size() > 0)
1406  completeIssuers(ctx, *untrustedCerts);
1407 
1408  X509_STORE_CTX_set0_untrusted(ctx, untrustedCerts.get()); // No locking/unlocking, just sets ctx->untrusted
1409  int ret = X509_verify_cert(ctx);
1410  X509_STORE_CTX_set0_untrusted(ctx, oldUntrusted); // Set back the old untrusted list
1411  return ret;
1412 }
1413 
1429 
1433 static int
1434 untrustedToStoreCtx_cb(X509_STORE_CTX *ctx, void *)
1435 {
1436  debugs(83, 4, "Try to use pre-downloaded intermediate certificates");
1437  return VerifyCtxCertificates(ctx, nullptr);
1438 }
1439 
1440 void
1441 Ssl::useSquidUntrusted(SSL_CTX *sslContext)
1442 {
1443  SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, nullptr);
1444 }
1445 
1446 bool
1447 Ssl::loadSquidUntrusted(const char *path)
1448 {
1449  return Ssl::loadCerts(path, SquidUntrustedCerts());
1450 }
1451 
1452 void
1454 {
1455  if (SquidUntrustedCerts().size()) {
1456  for (const auto &i: SquidUntrustedCerts()) {
1457  X509_free(i.second);
1458  }
1459  SquidUntrustedCerts().clear();
1460  }
1461 }
1462 
1463 bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const & pkey)
1464 {
1465  // Generate the self-signed certificate, using a hard-coded subject prefix
1466  Ssl::CertificateProperties certProperties;
1467  if (const char *cn = CommonHostName(cert.get())) {
1468  certProperties.commonName = "Not trusted by \"";
1469  certProperties.commonName += cn;
1470  certProperties.commonName += "\"";
1471  } else if (const char *org = getOrganization(cert.get())) {
1472  certProperties.commonName = "Not trusted by \"";
1473  certProperties.commonName += org;
1474  certProperties.commonName += "\"";
1475  } else
1476  certProperties.commonName = "Not trusted";
1477  certProperties.setCommonName = true;
1478  // O, OU, and other CA subject fields will be mimicked
1479  // Expiration date and other common properties will be mimicked
1480  certProperties.signAlgorithm = Ssl::algSignSelf;
1481  certProperties.signWithPkey.resetAndLock(pkey.get());
1482  certProperties.mimicCert.resetAndLock(cert.get());
1483  return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
1484 }
1485 
1487 {
1488  bool origSignatureAsKey = false;
1489  if (certProperties.mimicCert) {
1490  if (auto *sig = Ssl::X509_get_signature(certProperties.mimicCert)) {
1491  origSignatureAsKey = true;
1492  key.append((const char *)sig->data, sig->length);
1493  }
1494  }
1495 
1496  if (!origSignatureAsKey || certProperties.setCommonName) {
1497  // Use common name instead
1498  key.append(certProperties.commonName.c_str());
1499  }
1500  key.append(certProperties.setCommonName ? '1' : '0');
1501  key.append(certProperties.setValidAfter ? '1' : '0');
1502  key.append(certProperties.setValidBefore ? '1' : '0');
1503  key.append(certProperties.signAlgorithm != Ssl:: algSignEnd ? certSignAlgorithm(certProperties.signAlgorithm) : "-");
1504  key.append(certProperties.signHash ? EVP_MD_name(certProperties.signHash) : "-");
1505 
1506  if (certProperties.mimicCert) {
1507  Ssl::BIO_Pointer bio(BIO_new_SBuf(&key));
1508  ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bio.get(), (ASN1_VALUE *)certProperties.mimicCert.get());
1509  }
1510 }
1511 
1512 static int
1514 {
1515  BIO_set_init(bio, 0);
1516  BIO_set_data(bio, nullptr);
1517  return 1;
1518 }
1519 
1520 static int
1522 {
1523  if (!bio)
1524  return 0;
1525  return 1;
1526 }
1527 
1528 static int
1529 bio_sbuf_write(BIO* bio, const char* data, int len)
1530 {
1531  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1532  // TODO: Convert exceptions into BIO errors
1533  buf->append(data, len);
1534  return len;
1535 }
1536 
1537 static int
1538 bio_sbuf_puts(BIO *bio, const char *data)
1539 {
1540  // TODO: use bio_sbuf_write() instead
1541  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1542  size_t oldLen = buf->length();
1543  buf->append(data);
1544  return buf->length() - oldLen;
1545 }
1546 
1547 static long
1548 bio_sbuf_ctrl(BIO *bio, int cmd, long /* num */, void *)
1549 {
1550  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1551  switch (cmd) {
1552  case BIO_CTRL_RESET:
1553  // TODO: Convert exceptions into BIO errors
1554  buf->clear();
1555  return 1;
1556  case BIO_CTRL_FLUSH:
1557  return 1;
1558  default:
1559  return 0;
1560  }
1561 }
1562 
1564 {
1565 #if HAVE_LIBCRYPTO_BIO_METH_NEW
1566  static BIO_METHOD *BioSBufMethods = nullptr;
1567  if (!BioSBufMethods) {
1568  BioSBufMethods = BIO_meth_new(BIO_TYPE_MEM, "Squid-SBuf");
1569  BIO_meth_set_write(BioSBufMethods, bio_sbuf_write);
1570  BIO_meth_set_read(BioSBufMethods, nullptr);
1571  BIO_meth_set_puts(BioSBufMethods, bio_sbuf_puts);
1572  BIO_meth_set_gets(BioSBufMethods, nullptr);
1573  BIO_meth_set_ctrl(BioSBufMethods, bio_sbuf_ctrl);
1574  BIO_meth_set_create(BioSBufMethods, bio_sbuf_create);
1575  BIO_meth_set_destroy(BioSBufMethods, bio_sbuf_destroy);
1576  }
1577 #else
1578  static BIO_METHOD *BioSBufMethods = new BIO_METHOD({
1579  BIO_TYPE_MEM,
1580  "Squid SBuf",
1582  nullptr,
1583  bio_sbuf_puts,
1584  nullptr,
1585  bio_sbuf_ctrl,
1588  NULL
1589  });
1590 #endif
1591  BIO *bio = BIO_new(BioSBufMethods);
1592  Must(bio);
1593  BIO_set_data(bio, buf);
1594  BIO_set_init(bio, 1);
1595  return bio;
1596 }
1597 
1598 #endif /* USE_OPENSSL */
1599 
const char * sslGetCAAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:967
bool updateContextConfig(Security::ContextPointer &)
update the given TLS security context using squid.conf settings
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, Security::ParsedPortFlags)
initialize a TLS client context with OpenSSL specific settings
Definition: support.cc:806
int ErrorCode
Squid-defined error code (<0), an error code returned by X.509 API, or zero.
Definition: forward.h:131
int asn1timeToString(ASN1_TIME *tm, char *buf, int len)
Definition: support.cc:248
bool HasMatchingSubjectName(X509 &, const GeneralNameMatcher &)
Definition: support.cc:307
void Initialize()
Definition: support.cc:747
static void ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:713
#define Here()
source code location of the caller
Definition: Here.h:15
std::optional< AnyP::Host > ParseCommonNameAt(X509_NAME &, int)
interprets X.509 Subject or Issuer name entry (at the given position) as CN
Definition: gadgets.cc:504
void InRamCertificateDbKey(const Ssl::CertificateProperties &certProperties, SBuf &key)
Definition: support.cc:1486
static long bio_sbuf_ctrl(BIO *bio, int cmd, long, void *)
Definition: support.cc:1548
std::optional< SBuf > GetErrorDescr(Security::ErrorCode)
Definition: ErrorDetail.cc:159
CertSignAlgorithm
Definition: gadgets.h:169
bool missingChainCertificatesUrls(std::queue< SBuf > &URIs, const STACK_OF(X509) &serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1329
bool generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const &pkey)
Definition: support.cc:1463
std::shared_ptr< SSL_CTX > ContextPointer
Definition: Context.h:29
void MaybeSetupRsaCallback(Security::ContextPointer &)
if required, setup callback for generating ephemeral RSA keys
Definition: support.cc:238
void useSquidUntrusted(SSL_CTX *sslContext)
Definition: support.cc:1441
Security::CertPointer mimicCert
Certificate to mimic.
Definition: gadgets.h:235
static VerifyCallbackParameters * Find(Security::Connection &)
Definition: support.cc:629
const char * CommonHostName(X509 *x509)
Definition: gadgets.cc:1027
int ssl_ex_index_ssl_errors
@ SQUID_X509_V_ERR_DOMAIN_MISMATCH
Definition: forward.h:238
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &)
initialize a TLS server context with OpenSSL specific settings
Definition: support.cc:797
bool isEmpty() const
Definition: SBuf.h:435
#define SQUID_CERT_VALIDATION_ITERATION_MAX
Definition: support.h:51
const EVP_MD * signHash
The signing hash to use.
Definition: gadgets.h:243
Security::LockingPointer< X509, X509_free_cpp, HardFun< int, X509 *, X509_up_ref > > CertPointer
Definition: forward.h:88
GETX509ATTRIBUTE GetX509Fingerprint
Definition: support.h:124
SBuf AsnToSBuf(const ASN1_STRING &)
converts ASN1_STRING to SBuf
Definition: gadgets.cc:473
static void completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) &untrustedCerts)
add missing issuer certificates to untrustedCerts
Definition: support.cc:1352
bool isAnyAddr() const
Definition: Address.cc:190
std::unique_ptr< STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_free_wrapper > GENERAL_NAME_STACK_Pointer
Definition: gadgets.h:74
Security::ContextPointer createSSLContext(Security::CertPointer &x509, Security::PrivateKeyPointer &pkey, Security::ServerOptions &)
Create SSL context and apply ssl certificate and private key to it.
Definition: support.cc:1021
std::unique_ptr< BIO, HardFun< void, BIO *, &BIO_vfree > > BIO_Pointer
Definition: gadgets.h:57
void error(char *format,...)
struct SquidConfig::@90 Program
static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx)
Definition: support.cc:346
static void ssl_ask_password(SSL_CTX *context, const char *prompt)
Definition: support.cc:156
Definition: SBuf.h:93
std::unique_ptr< STACK_OF(X509), sk_X509_free_wrapper > X509_STACK_Pointer
Definition: gadgets.h:53
const char * certSignAlgorithm(int sg)
Definition: gadgets.h:182
X509_VERIFY_PARAM * SSL_get0_param(SSL *ssl)
Definition: openssl.h:300
static int bio_sbuf_write(BIO *bio, const char *data, int len)
Definition: support.cc:1529
GETX509PEM GetX509PEM
Definition: support.h:121
static CertsIndexedList & SquidUntrustedCerts()
Definition: support.cc:75
static VerifyCallbackParameters & At(Security::Connection &)
Definition: support.cc:647
static void ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:731
GETX509ATTRIBUTE GetX509CAAttribute
Definition: support.h:118
static X509 * findCertIssuerFast(Ssl::CertsIndexedList &list, X509 *cert)
Definition: support.cc:1235
#define SSL_FLAG_DELAYED_AUTH
Definition: forward.h:54
static int VerifyCtxCertificates(X509_STORE_CTX *ctx, STACK_OF(X509) *extraCerts)
Definition: support.cc:1386
static VerifyCallbackParameters * New(Security::Connection &)
Definition: support.cc:635
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
Security::CertPointer cert
public X.509 certificate from certFile
Definition: KeyData.h:31
const char * sslGetUserEmail(SSL *ssl)
Definition: support.cc:981
virtual bool matchDomainName(const Dns::DomainName &) const =0
BIO * BIO_new_SBuf(SBuf *buf)
Definition: support.cc:1563
int matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
Definition: Uri.cc:860
void reset()
Forget the raw pointer - unlock if any value was set. Become a nil pointer.
void * BIO_get_data(BIO *table)
Definition: openssl.h:62
bool matchIp(const Ip::Address &) const override
Definition: support.cc:117
CbcPointer< Security::CertErrors > sslErrors
SBuf SubjectName(Certificate &)
The SubjectName field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:68
static int port
Definition: ldap_backend.cc:70
const ASN1_BIT_STRING * X509_get_signature(const Security::CertPointer &)
Definition: gadgets.cc:1063
int ssl_ex_index_ssl_cert_chain
void clear()
Definition: SBuf.cc:175
static void ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:685
static std::optional< AnyP::Host > ParseSubjectAltName(const GENERAL_NAME &san)
Definition: support.cc:263
static bool Enabled(const int section, const int level)
whether debugging the given section and the given level produces output
Definition: Stream.h:75
static void ssl_free_VerifyCallbackParameters(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
"free" function for the ssl_ex_index_verify_callback_parameters entry
Definition: support.cc:740
static void ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:677
std::list< Security::KeyData > certs
details from the cert= and file= config parameters
Definition: PeerOptions.h:105
#define MAX_URL
Definition: defines.h:76
Security::CertPointer ReadOptionalCertificate(const BIO_Pointer &)
Definition: gadgets.cc:791
AnyP::Host needle_
a name we are looking for
Definition: support.cc:71
void BIO_set_data(BIO *table, void *data)
Definition: openssl.h:68
int size
Definition: ModDevPoll.cc:69
Security::CertPointer findIssuerCertificate(X509 *cert, const STACK_OF(X509) *serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1303
Security::CertPointer serverCert
#define NULL
Definition: types.h:145
OneNameMatcher(const AnyP::Host &needle)
Definition: support.cc:64
@ algSignTrusted
Definition: gadgets.h:169
SBuf consume(size_type n=npos)
Definition: SBuf.cc:481
#define X509_getm_notBefore
Definition: openssl.h:248
static char * keys[]
const EVP_MD * DefaultSignHash
Definition: support.cc:44
#define DBG_PARSE_NOTE(x)
Definition: Stream.h:42
X509 * X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
Definition: openssl.h:230
bool VerifyConnCertificates(Security::Connection &, const Ssl::X509_STACK_Pointer &extraCerts)
Definition: support.cc:537
Security::CertList chain
any certificates which must be chained from cert
Definition: KeyData.h:35
int ssl_ex_index_ssl_peeked_cert
TLS squid.conf settings for a remote server peer.
Definition: PeerOptions.h:25
ACLFilledChecklist * Filled(ACLChecklist *checklist)
convenience and safety wrapper for dynamic_cast<ACLFilledChecklist*>
const Acl::Answer & fastCheck()
Definition: Checklist.cc:298
@ algSignEnd
Definition: gadgets.h:169
bool generateSslCertificate(Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, CertificateProperties const &properties)
Definition: gadgets.cc:769
void configureUnconfiguredSslContext(Security::ContextPointer &, Ssl::CertSignAlgorithm signAlgorithm, AnyP::PortCfg &)
Definition: support.cc:1091
bool match(const Ssl::GeneralName &) const
whether the given name satisfies algorithm conditions
Definition: support.cc:84
Definition: Xaction.cc:39
const char * getOrganization(X509 *x509)
Definition: gadgets.cc:1032
static std::optional< Host > ParseWildDomainName(const SBuf &)
Definition: Host.cc:59
static int ssl_ex_index_verify_callback_parameters
Definition: support.cc:42
long ParsedPortFlags
Definition: forward.h:204
Security::SessionPointer NewSessionObject(const Security::ContextPointer &)
Definition: Session.cc:90
virtual bool matchIp(const Ip::Address &) const =0
const char * findIssuerUri(X509 *cert)
finds certificate issuer URI in the Authority Info Access extension
Definition: support.cc:1186
static std::optional< Host > ParseIp(const Ip::Address &)
converts an already parsed IP address to a Host object
Definition: Host.cc:15
static int untrustedToStoreCtx_cb(X509_STORE_CTX *ctx, void *)
Definition: support.cc:1434
Config TheConfig
Definition: Config.cc:12
#define assert(EX)
Definition: assert.h:17
either a domain name (as defined in DNS RFC 1034) or an IP address
Definition: Host.h:24
SSL Connection
Definition: Session.h:49
bool setValidBefore
Do not mimic "Not Valid Before" field.
Definition: gadgets.h:239
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
SBuf IssuerName(Certificate &)
The Issuer field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:28
Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char *data, Security::ServerOptions &, bool trusted)
Definition: support.cc:1038
#define X509_STORE_CTX_set0_untrusted
Definition: openssl.h:246
std::multimap< SBuf, X509 * > CertsIndexedList
certificates indexed by issuer name
Definition: support.h:150
FILE * DebugStream()
Definition: debug.cc:355
@ algSignSelf
Definition: gadgets.h:169
auto domainName() const
stored domain name (if any)
Definition: Host.h:48
Security::PrivateKeyPointer signWithPkey
The key of the signing certificate.
Definition: gadgets.h:237
#define Assure(condition)
Definition: Assure.h:35
static int ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *, int, long, void *)
Definition: support.cc:665
const char * c_str()
Definition: SBuf.cc:516
SBuf sslGetUserCertificateChainPEM(SSL *ssl)
Definition: support.cc:998
Security::ContextPointer GenerateSslContext(CertificateProperties const &, Security::ServerOptions &, bool trusted)
Definition: support.cc:1052
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:419
CbDataList< Security::CertError > CertErrors
Holds a list of X.509 certificate errors.
Definition: forward.h:74
static int bio_sbuf_create(BIO *bio)
Definition: support.cc:1513
const char * sslGetUserAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:954
void unloadSquidUntrusted()
Definition: support.cc:1453
#define SSL_FLAG_DONT_VERIFY_PEER
Definition: forward.h:55
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
static void ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:702
Security::ContextPointer createBlankContext() const override
generate an unset security context object
static int bio_sbuf_puts(BIO *bio, const char *data)
Definition: support.cc:1538
#define X509_getm_notAfter
Definition: openssl.h:247
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
Definition: openssl.h:292
int ssl_ex_index_server
bool IssuedBy(Certificate &cert, Certificate &issuer)
Definition: Certificate.cc:108
std::vector< const char * > BumpModeStr
Definition: support.cc:46
void SQUID_OPENSSL_init_ssl(void)
Definition: openssl.h:308
TLS squid.conf settings for a listening port.
Definition: ServerOptions.h:25
void chainCertificatesToSSLContext(Security::ContextPointer &, Security::ServerOptions &)
Definition: support.cc:1066
bool SelfSigned(Certificate &c)
Whether the given certificate is self-signed.
Definition: Certificate.h:34
bool push_back_unique(C const &element)
Definition: CbDataList.h:87
static int bio_sbuf_destroy(BIO *bio)
Definition: support.cc:1521
auto ip() const
Definition: Host.h:45
an algorithm for checking/testing/comparing X.509 certificate names
Definition: support.h:298
std::shared_ptr< SSL > SessionPointer
Definition: Session.h:53
void DisablePeerVerification(Security::ContextPointer &)
Definition: support.cc:528
bool allowed() const
Definition: Acl.h:82
static void ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:693
int AskPasswordCb(char *buf, int size, int rwflag, void *userdata)
Definition: support.cc:131
std::optional< AnyP::Host > ParseAsSimpleDomainNameOrIp(const SBuf &)
Definition: gadgets.cc:496
@ mdnRejectSubsubDomains
Definition: Uri.h:229
const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
Definition: openssl.h:54
bool configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
Definition: support.cc:1121
an std::runtime_error with thrower location info
Definition: TextException.h:20
std::string commonName
A CN to use for the generated certificate.
Definition: gadgets.h:241
static char server[MAXLINE]
bool verifySslCertificate(const Security::ContextPointer &, CertificateProperties const &)
Definition: support.cc:1141
static X509 * sk_x509_findIssuer(const STACK_OF(X509) *sk, X509 *cert)
slowly find the issuer certificate of a given cert using linear search
Definition: support.cc:1253
int ssl_ex_index_cert_error_check
GETX509ATTRIBUTE GetX509UserAttribute
Definition: support.h:115
static void ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:722
#define SSL_FLAG_CONDITIONAL_AUTH
Definition: forward.h:60
@ SQUID_X509_V_ERR_CERT_CHANGE
Definition: forward.h:237
std::unique_ptr< X509_STORE_CTX, HardFun< void, X509_STORE_CTX *, &X509_STORE_CTX_free > > X509_STORE_CTX_Pointer
Definition: gadgets.h:80
#define Must(condition)
Definition: TextException.h:75
char * ssl_password
Definition: SquidConfig.h:211
static X509 * findIssuerInCaDb(X509 *cert, const Security::ContextPointer &connContext)
Definition: support.cc:1270
#define DBG_IMPORTANT
Definition: Stream.h:38
static const char * ssl_get_attribute(X509_NAME *name, const char *attribute_name)
Definition: support.cc:864
CertSignAlgorithm signAlgorithm
The signing algorithm to use.
Definition: gadgets.h:242
bool HasSubjectName(X509 &, const AnyP::Host &)
whether at least one common or alternate subject name matches the given one
Definition: support.cc:338
int ssl_ex_index_ssl_validation_counter
bool matchDomainName(const Dns::DomainName &) const override
Definition: support.cc:95
bool setValidAfter
Do not mimic "Not Valid After" field.
Definition: gadgets.h:238
int ssl_ctx_ex_index_dont_verify_domain
GeneralNameMatcher for matching a single AnyP::Host given at construction time.
Definition: support.cc:61
void ConfigurePeerVerification(Security::ContextPointer &, const Security::ParsedPortFlags)
set the certificate verify callback for a context
Definition: support.cc:501
bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
Definition: support.cc:1216
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
Definition: openssl.h:237
void BIO_set_init(BIO *table, int init)
Definition: openssl.h:74
bool configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
Definition: support.cc:1098
bool setCommonName
Replace the CN field of the mimicking subject with the given.
Definition: gadgets.h:240
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
Definition: forward.h:152
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
@ SQUID_X509_V_ERR_INFINITE_VALIDATION
Definition: forward.h:239
Security::KeyData signingCa
x509 certificate and key for signing generated certificates
Definition: ServerOptions.h:87
bool loadSquidUntrusted(const char *path)
Definition: support.cc:1447
#define SQUID_SSL_SIGN_HASH_IF_NONE
Definition: gadgets.h:46
SBuf sslGetUserCertificatePEM(SSL *ssl)
Definition: support.cc:987
int ssl_ex_index_ssl_error_detail
void setClientSNI(SSL *ssl, const char *fqdn)
Definition: support.cc:1166
T * get() const
Returns raw and possibly nullptr pointer.
class SquidConfig Config
Definition: SquidConfig.cc:12
bool readCertAndPrivateKeyFromMemory(Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, char const *bufferToRead)
Definition: gadgets.cc:147

 

Introduction

Documentation

Support

Miscellaneous