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