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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors