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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors