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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors