support.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2020 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 * ssl, int anInt, 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 #endif
177 }
178 
179 int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len)
180 {
181  BIO *bio;
182  int write = 0;
183  bio = BIO_new(BIO_s_mem());
184  if (bio) {
185  if (ASN1_TIME_print(bio, tm))
186  write = BIO_read(bio, buf, len-1);
187  BIO_free(bio);
188  }
189  buf[write]='\0';
190  return write;
191 }
192 
193 int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data))
194 {
195  assert(peer_cert);
196 
197  X509_NAME *name = X509_get_subject_name(peer_cert);
198 
199  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)) {
200 
201  ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
202 
203  if ( (*check_func)(check_data, cn_data) == 0)
204  return 1;
205  }
206 
207  STACK_OF(GENERAL_NAME) * altnames;
208  altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
209 
210  if (altnames) {
211  int numalts = sk_GENERAL_NAME_num(altnames);
212  for (int i = 0; i < numalts; ++i) {
213  const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
214  if (check->type != GEN_DNS) {
215  continue;
216  }
217  ASN1_STRING *cn_data = check->d.dNSName;
218 
219  if ( (*check_func)(check_data, cn_data) == 0) {
220  sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
221  return 1;
222  }
223  }
224  sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
225  }
226  return 0;
227 }
228 
229 static int check_domain( void *check_data, ASN1_STRING *cn_data)
230 {
231  char cn[1024];
232  const char *server = (const char *)check_data;
233 
234  if (cn_data->length == 0)
235  return 1; // zero length cn, ignore
236 
237  if (cn_data->length > (int)sizeof(cn) - 1)
238  return 1; //if does not fit our buffer just ignore
239 
240  char *s = reinterpret_cast<char*>(cn_data->data);
241  char *d = cn;
242  for (int i = 0; i < cn_data->length; ++i, ++d, ++s) {
243  if (*s == '\0')
244  return 1; // always a domain mismatch. contains 0x00
245  *d = *s;
246  }
247  cn[cn_data->length] = '\0';
248  debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn);
249  return matchDomainName(server, (cn[0] == '*' ? cn + 1 : cn), mdnRejectSubsubDomains);
250 }
251 
252 bool Ssl::checkX509ServerValidity(X509 *cert, const char *server)
253 {
254  return matchX509CommonNames(cert, (void *)server, check_domain);
255 }
256 
258 static int
259 ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
260 {
261  // preserve original ctx->error before SSL_ calls can overwrite it
262  Security::ErrorCode error_no = ok ? SSL_ERROR_NONE : X509_STORE_CTX_get_error(ctx);
263 
264  char buffer[256] = "";
265  SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
266  SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
267  SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server);
268  void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
269  ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
270  X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert);
271  Security::CertPointer peer_cert;
272  peer_cert.resetAndLock(X509_STORE_CTX_get0_cert(ctx));
273 
274  X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), buffer, sizeof(buffer));
275 
276  // detect infinite loops
277  uint32_t *validationCounter = static_cast<uint32_t *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter));
278  if (!validationCounter) {
279  validationCounter = new uint32_t(1);
280  SSL_set_ex_data(ssl, ssl_ex_index_ssl_validation_counter, validationCounter);
281  } else {
282  // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
283  (*validationCounter)++;
284  }
285 
286  if ((*validationCounter) >= SQUID_CERT_VALIDATION_ITERATION_MAX) {
287  ok = 0; // or the validation loop will never stop
289  debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
290  *validationCounter << " iterations while checking " << buffer);
291  }
292 
293  if (ok) {
294  debugs(83, 5, "SSL Certificate signature OK: " << buffer);
295 
296  // Check for domain mismatch only if the current certificate is the peer certificate.
297  if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) {
298  if (!Ssl::checkX509ServerValidity(peer_cert.get(), server->c_str())) {
299  debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
300  ok = 0;
302  }
303  }
304  }
305 
306  if (ok && peeked_cert) {
307  // Check whether the already peeked certificate matches the new one.
308  if (X509_cmp(peer_cert.get(), peeked_cert) != 0) {
309  debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer << " does not match peeked certificate");
310  ok = 0;
311  error_no = SQUID_X509_V_ERR_CERT_CHANGE;
312  }
313  }
314 
315  if (!ok) {
316  Security::CertPointer broken_cert;
317  broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx));
318  if (!broken_cert)
319  broken_cert = peer_cert;
320 
321  Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
322  const int depth = X509_STORE_CTX_get_error_depth(ctx);
323  if (!errs) {
324  errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth));
325  if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
326  debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer);
327  delete errs;
328  errs = NULL;
329  }
330  } else // remember another error number
331  errs->push_back_unique(Security::CertError(error_no, broken_cert, depth));
332 
333  if (const char *err_descr = Ssl::GetErrorDescr(error_no))
334  debugs(83, 5, err_descr << ": " << buffer);
335  else
336  debugs(83, DBG_IMPORTANT, "SSL unknown certificate error " << error_no << " in " << buffer);
337 
338  // Check if the certificate error can be bypassed.
339  // Infinity validation loop errors can not bypassed.
340  if (error_no != SQUID_X509_V_ERR_INFINITE_VALIDATION) {
341  if (check) {
342  ACLFilledChecklist *filledCheck = Filled(check);
343  assert(!filledCheck->sslErrors);
344  filledCheck->sslErrors = new Security::CertErrors(Security::CertError(error_no, broken_cert));
345  filledCheck->serverCert = peer_cert;
346  if (check->fastCheck().allowed()) {
347  debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
348  ok = 1;
349  } else {
350  debugs(83, 5, "confirming SSL error " << error_no);
351  }
352  delete filledCheck->sslErrors;
353  filledCheck->sslErrors = NULL;
354  filledCheck->serverCert.reset();
355  }
356  // If the certificate validator is used then we need to allow all errors and
357  // pass them to certificate validator for more processing
358  else if (Ssl::TheConfig.ssl_crt_validator) {
359  ok = 1;
360  }
361  }
362  }
363 
364  if (Ssl::TheConfig.ssl_crt_validator) {
365  // Check if we have stored certificates chain. Store if not.
366  if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
367  STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
368  if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
369  sk_X509_pop_free(certStack, X509_free);
370  }
371  }
372 
373  if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
374 
375  // Find the broken certificate. It may be intermediate.
376  Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails
377  // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
378  if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
379  if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
380  broken_cert.resetAndLock(last_used_cert);
381  }
382 
383  std::unique_ptr<Security::ErrorDetail::Pointer> edp(new Security::ErrorDetail::Pointer(
384  new Security::ErrorDetail(error_no, peer_cert, broken_cert)));
385  if (SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, edp.get()))
386  edp.release();
387  else
388  debugs(83, 2, "failed to store a " << buffer << " error detail: " << *edp);
389  }
390 
391  return ok;
392 }
393 
394 void
396 {
397  int mode;
398 
399  // assume each flag is exclusive; flags creator must check this assumption
400  if (flags & SSL_FLAG_DONT_VERIFY_PEER) {
401  debugs(83, DBG_IMPORTANT, "SECURITY WARNING: Peer certificates are not verified for validity!");
402  debugs(83, DBG_IMPORTANT, "UPGRADE NOTICE: The DONT_VERIFY_PEER flag is deprecated. Remove the clientca= option to disable client certificates.");
403  mode = SSL_VERIFY_NONE;
404  }
405  else if (flags & SSL_FLAG_DELAYED_AUTH) {
406  debugs(83, DBG_PARSE_NOTE(3), "not requesting client certificates until ACL processing requires one");
407  mode = SSL_VERIFY_NONE;
408  }
409  else if (flags & SSL_FLAG_CONDITIONAL_AUTH) {
410  debugs(83, DBG_PARSE_NOTE(3), "will request the client certificate but ignore its absense");
411  mode = SSL_VERIFY_PEER;
412  }
413  else {
414  debugs(83, DBG_PARSE_NOTE(3), "Requiring client certificates.");
415  mode = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
416  }
417 
418  SSL_CTX_set_verify(ctx.get(), mode, (mode != SSL_VERIFY_NONE) ? ssl_verify_cb : nullptr);
419 }
420 
421 void
423 {
424  debugs(83, DBG_PARSE_NOTE(3), "Not requiring any client certificates");
425  SSL_CTX_set_verify(ctx.get(),SSL_VERIFY_NONE,nullptr);
426 }
427 
428 // "dup" function for SSL_get_ex_new_index("cert_err_check")
429 #if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
430 static int
431 ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
432  int, long, void *)
433 #else
434 static int
435 ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
436  int, long, void *)
437 #endif
438 {
439  // We do not support duplication of ACLCheckLists.
440  // If duplication is needed, we can count copies with cbdata.
441  assert(false);
442  return 0;
443 }
444 
445 // "free" function for SSL_get_ex_new_index("cert_err_check")
446 static void
447 ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
448  int, long, void *)
449 {
450  delete static_cast<ACLChecklist *>(ptr); // may be NULL
451 }
452 
453 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
454 static void
455 ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
456  int, long, void *)
457 {
458  const auto errDetail = static_cast<Security::ErrorDetail::Pointer*>(ptr);
459  delete errDetail;
460 }
461 
462 static void
463 ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
464  int, long, void *)
465 {
466  Security::CertErrors *errs = static_cast <Security::CertErrors*>(ptr);
467  delete errs;
468 }
469 
470 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
471 static void
472 ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *,
473  int, long, void *)
474 {
475  uint32_t *counter = static_cast <uint32_t *>(ptr);
476  delete counter;
477 }
478 
482 static void
483 ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
484  int, long, void *)
485 {
486  STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
487  sk_X509_pop_free(certsChain,X509_free);
488 }
489 
490 // "free" function for X509 certificates
491 static void
492 ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
493  int, long, void *)
494 {
495  X509 *cert = static_cast <X509 *>(ptr);
496  X509_free(cert);
497 }
498 
499 // "free" function for SBuf
500 static void
501 ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *,
502  int, long, void *)
503 {
504  SBuf *buf = static_cast <SBuf *>(ptr);
505  delete buf;
506 }
507 
508 void
510 {
511  static bool initialized = false;
512  if (initialized)
513  return;
514  initialized = true;
515 
517 
518 #if !defined(OPENSSL_NO_ENGINE)
519  if (::Config.SSL.ssl_engine) {
520  ENGINE_load_builtin_engines();
521  ENGINE *e;
522  if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine)))
523  fatalf("Unable to find SSL engine '%s'\n", ::Config.SSL.ssl_engine);
524 
525  if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
526  const auto ssl_error = ERR_get_error();
527  fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error));
528  }
529  }
530 #else
531  if (::Config.SSL.ssl_engine)
532  fatalf("Your OpenSSL has no SSL engine support\n");
533 #endif
534 
535  const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE;
536  Ssl::DefaultSignHash = EVP_get_digestbyname(defName);
538  fatalf("Sign hash '%s' is not supported\n", defName);
539 
540  ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, ssl_free_SBuf);
541  ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
542  ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
543  ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
544  ssl_ex_index_ssl_peeked_cert = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL, NULL, &ssl_free_X509);
545  ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
546  ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
547  ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL, NULL, &ssl_free_int);
548  ssl_ex_index_ssl_untrusted_chain = SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL, NULL, &ssl_free_CertChain);
549 }
550 
551 bool
553 {
554  if (!ctx)
555  return false;
556 
557  return true;
558 }
559 
560 bool
562 {
563  if (!ctx)
564  return false;
565 
566  if (!peer.sslCipher.isEmpty()) {
567  debugs(83, 5, "Using chiper suite " << peer.sslCipher << ".");
568 
569  const char *cipher = peer.sslCipher.c_str();
570  if (!SSL_CTX_set_cipher_list(ctx.get(), cipher)) {
571  const auto ssl_error = ERR_get_error();
572  fatalf("Failed to set SSL cipher suite '%s': %s\n",
573  cipher, Security::ErrorString(ssl_error));
574  }
575  }
576 
577  if (!peer.certs.empty()) {
578  // TODO: support loading multiple cert/key pairs
579  auto &keys = peer.certs.front();
580  if (!keys.certFile.isEmpty()) {
581  debugs(83, DBG_IMPORTANT, "Using certificate in " << keys.certFile);
582 
583  const char *certfile = keys.certFile.c_str();
584  if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
585  const auto ssl_error = ERR_get_error();
586  fatalf("Failed to acquire SSL certificate '%s': %s\n",
587  certfile, Security::ErrorString(ssl_error));
588  }
589 
590  debugs(83, DBG_IMPORTANT, "Using private key in " << keys.privateKeyFile);
591  const char *keyfile = keys.privateKeyFile.c_str();
592  ssl_ask_password(ctx.get(), keyfile);
593 
594  if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
595  const auto ssl_error = ERR_get_error();
596  fatalf("Failed to acquire SSL private key '%s': %s\n",
597  keyfile, Security::ErrorString(ssl_error));
598  }
599 
600  debugs(83, 5, "Comparing private and public SSL keys.");
601 
602  if (!SSL_CTX_check_private_key(ctx.get())) {
603  const auto ssl_error = ERR_get_error();
604  fatalf("SSL private key '%s' does not match public key '%s': %s\n",
605  certfile, keyfile, Security::ErrorString(ssl_error));
606  }
607  }
608  }
609 
611 
613 
614  return true;
615 }
616 
618 static const char *
619 ssl_get_attribute(X509_NAME * name, const char *attribute_name)
620 {
621  static char buffer[1024];
622  buffer[0] = '\0';
623 
624  if (strcmp(attribute_name, "DN") == 0) {
625  X509_NAME_oneline(name, buffer, sizeof(buffer));
626  } else {
627  int nid = OBJ_txt2nid(const_cast<char *>(attribute_name));
628  if (nid == 0) {
629  debugs(83, DBG_IMPORTANT, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
630  return nullptr;
631  }
632  X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
633  }
634 
635  return *buffer ? buffer : nullptr;
636 }
637 
639 const char *
640 Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name)
641 {
642  X509_NAME *name;
643  const char *ret;
644 
645  if (!cert)
646  return NULL;
647 
648  name = X509_get_subject_name(cert);
649 
650  ret = ssl_get_attribute(name, attribute_name);
651 
652  return ret;
653 }
654 
655 const char *
656 Ssl::GetX509Fingerprint(X509 * cert, const char *)
657 {
658  static char buf[1024];
659  if (!cert)
660  return NULL;
661 
662  unsigned int n;
663  unsigned char md[EVP_MAX_MD_SIZE];
664  if (!X509_digest(cert, EVP_sha1(), md, &n))
665  return NULL;
666 
667  assert(3 * n + 1 < sizeof(buf));
668 
669  char *s = buf;
670  for (unsigned int i=0; i < n; ++i, s += 3) {
671  const char term = (i + 1 < n) ? ':' : '\0';
672  snprintf(s, 4, "%02X%c", md[i], term);
673  }
674 
675  return buf;
676 }
677 
678 SBuf
679 Ssl::GetX509PEM(X509 * cert)
680 {
681  assert(cert);
682 
683  Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
684  PEM_write_bio_X509(bio.get(), cert);
685 
686  char *ptr;
687  const auto len = BIO_get_mem_data(bio.get(), &ptr);
688  return SBuf(ptr, len);
689 }
690 
692 const char *
693 Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
694 {
695 
696  X509_NAME *name;
697  const char *ret;
698 
699  if (!cert)
700  return NULL;
701 
702  name = X509_get_issuer_name(cert);
703 
704  ret = ssl_get_attribute(name, attribute_name);
705 
706  return ret;
707 }
708 
709 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name)
710 {
711  if (!ssl)
712  return NULL;
713 
714  X509 *cert = SSL_get_peer_certificate(ssl);
715 
716  const char *attr = Ssl::GetX509UserAttribute(cert, attribute_name);
717 
718  X509_free(cert);
719  return attr;
720 }
721 
722 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name)
723 {
724  if (!ssl)
725  return NULL;
726 
727  X509 *cert = SSL_get_peer_certificate(ssl);
728 
729  const char *attr = Ssl::GetX509CAAttribute(cert, attribute_name);
730 
731  X509_free(cert);
732  return attr;
733 }
734 
735 const char *
736 sslGetUserEmail(SSL * ssl)
737 {
738  return sslGetUserAttribute(ssl, "emailAddress");
739 }
740 
741 SBuf
743 {
744  assert(ssl);
745 
746  if (const auto cert = SSL_get_peer_certificate(ssl))
747  return Ssl::GetX509PEM(cert);
748 
749  return SBuf();
750 }
751 
752 SBuf
754 {
755  assert(ssl);
756 
757  auto chain = SSL_get_peer_cert_chain(ssl);
758 
759  if (!chain)
760  return sslGetUserCertificatePEM(ssl);
761 
762  Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
763 
764  for (int i = 0; i < sk_X509_num(chain); ++i) {
765  X509 *cert = sk_X509_value(chain, i);
766  PEM_write_bio_X509(bio.get(), cert);
767  }
768 
769  char *ptr;
770  const auto len = BIO_get_mem_data(bio.get(), &ptr);
771  return SBuf(ptr, len);
772 }
773 
776 Ssl::createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &options)
777 {
779 
780  if (!SSL_CTX_use_certificate(ctx.get(), x509.get()))
781  return Security::ContextPointer();
782 
783  if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()))
784  return Security::ContextPointer();
785 
786  if (!options.updateContextConfig(ctx))
787  return Security::ContextPointer();
788 
789  return ctx;
790 }
791 
794 {
796  Security::PrivateKeyPointer pkey;
797  if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
798  return Security::ContextPointer();
799 
800  Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
801  if (ctx && trusted)
803  return ctx;
804 }
805 
808 {
810  Security::PrivateKeyPointer pkey;
811  if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
812  return Security::ContextPointer();
813 
814  Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
815  if (ctx && trusted)
817  return ctx;
818 }
819 
820 void
822 {
823  assert(ctx);
824  // Add signing certificate to the certificates chain
825  X509 *signingCert = options.signingCa.cert.get();
826  if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) {
827  // increase the certificate lock
828  X509_up_ref(signingCert);
829  } else {
830  const auto ssl_error = ERR_get_error();
831  debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error));
832  }
833 
834  for (auto cert : options.signingCa.chain) {
835  if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert.get())) {
836  // increase the certificate lock
837  X509_up_ref(cert.get());
838  } else {
839  const auto error = ERR_get_error();
840  debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL dynamic context chain: " << Security::ErrorString(error));
841  }
842  }
843 }
844 
845 void
847 {
848  if (ctx && signAlgorithm == Ssl::algSignTrusted)
850 }
851 
852 bool
854 {
856  Security::PrivateKeyPointer pkey;
857  if (!generateSslCertificate(cert, pkey, properties))
858  return false;
859 
860  if (!cert)
861  return false;
862 
863  if (!pkey)
864  return false;
865 
866  if (!SSL_use_certificate(ssl, cert.get()))
867  return false;
868 
869  if (!SSL_use_PrivateKey(ssl, pkey.get()))
870  return false;
871 
872  return true;
873 }
874 
875 bool
877 {
879  Security::PrivateKeyPointer pkey;
880  if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
881  return false;
882 
883  if (!cert || !pkey)
884  return false;
885 
886  if (!SSL_use_certificate(ssl, cert.get()))
887  return false;
888 
889  if (!SSL_use_PrivateKey(ssl, pkey.get()))
890  return false;
891 
892  return true;
893 }
894 
895 bool
897 {
898 #if HAVE_SSL_CTX_GET0_CERTIFICATE
899  X509 * cert = SSL_CTX_get0_certificate(ctx.get());
900 #elif SQUID_USE_SSLGETCERTIFICATE_HACK
901  // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
902  // Try to retrieve certificate directly from Security::ContextPointer object
903  X509 ***pCert = (X509 ***)ctx->cert;
904  X509 * cert = pCert && *pCert ? **pCert : NULL;
905 #elif SQUID_SSLGETCERTIFICATE_BUGGY
906  X509 * cert = NULL;
907  assert(0);
908 #else
909  // Temporary ssl for getting X509 certificate from SSL_CTX.
911  X509 * cert = SSL_get_certificate(ssl.get());
912 #endif
913  if (!cert)
914  return false;
915  const auto time_notBefore = X509_getm_notBefore(cert);
916  const auto time_notAfter = X509_getm_notAfter(cert);
917  return (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
918 }
919 
920 void
921 Ssl::setClientSNI(SSL *ssl, const char *fqdn)
922 {
923  const Ip::Address test(fqdn);
924  if (!test.isAnyAddr())
925  return; // raw IP is inappropriate for SNI
926 
927  //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
928  // if the TLS servername extension (SNI) is enabled in openssl library.
929 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
930  if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
931  const auto ssl_error = ERR_get_error();
932  debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
933  Security::ErrorString(ssl_error) << "\n");
934  }
935 #else
936  debugs(83, 7, "no support for TLS servername extension (SNI)");
937 #endif
938 }
939 
940 static const char *
942 {
943  AUTHORITY_INFO_ACCESS *info;
944  if (!cert)
945  return nullptr;
946  info = static_cast<AUTHORITY_INFO_ACCESS *>(X509_get_ext_d2i(cert, NID_info_access, NULL, NULL));
947  if (!info)
948  return nullptr;
949 
950  static char uri[MAX_URL];
951  uri[0] = '\0';
952 
953  for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
954  ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
955  if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
956  if (ad->location->type == GEN_URI) {
957  xstrncpy(uri,
958  reinterpret_cast<const char *>(
959  ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier)
960  ),
961  sizeof(uri));
962  }
963  break;
964  }
965  }
966  AUTHORITY_INFO_ACCESS_free(info);
967  return uri[0] != '\0' ? uri : nullptr;
968 }
969 
970 bool
971 Ssl::loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
972 {
973  BIO *in = BIO_new_file(certsFile, "r");
974  if (!in) {
975  debugs(83, DBG_IMPORTANT, "Failed to open '" << certsFile << "' to load certificates");
976  return false;
977  }
978 
979  X509 *aCert;
980  while((aCert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
981  static char buffer[2048];
982  X509_NAME_oneline(X509_get_subject_name(aCert), buffer, sizeof(buffer));
983  list.insert(std::pair<SBuf, X509 *>(SBuf(buffer), aCert));
984  }
985  debugs(83, 4, "Loaded " << list.size() << " certificates from file: '" << certsFile << "'");
986  BIO_free(in);
987  return true;
988 }
989 
992 static X509 *
994 {
995  static char buffer[2048];
996 
997  if (X509_NAME *issuerName = X509_get_issuer_name(cert))
998  X509_NAME_oneline(issuerName, buffer, sizeof(buffer));
999  else
1000  return NULL;
1001 
1002  const auto ret = list.equal_range(SBuf(buffer));
1003  for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) {
1004  X509 *issuer = it->second;
1005  if (X509_check_issued(issuer, cert) == X509_V_OK) {
1006  return issuer;
1007  }
1008  }
1009  return NULL;
1010 }
1011 
1013 static bool
1014 findCertIssuer(Security::CertList const &list, X509 *cert)
1015 {
1016  for (Security::CertList::const_iterator it = list.begin(); it != list.end(); ++it) {
1017  if (X509_check_issued(it->get(), cert) == X509_V_OK)
1018  return true;
1019  }
1020  return false;
1021 }
1022 
1024 static bool
1025 issuerExistInCaDb(X509 *cert, const Security::ContextPointer &connContext)
1026 {
1027  if (!connContext)
1028  return false;
1029 
1030  X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
1031  if (!storeCtx) {
1032  debugs(83, DBG_IMPORTANT, "Failed to allocate STORE_CTX object");
1033  return false;
1034  }
1035 
1036  bool gotIssuer = false;
1037  X509_STORE *store = SSL_CTX_get_cert_store(connContext.get());
1038  if (X509_STORE_CTX_init(storeCtx, store, nullptr, nullptr)) {
1039  X509 *issuer = nullptr;
1040  gotIssuer = (X509_STORE_CTX_get1_issuer(&issuer, storeCtx, cert) > 0);
1041  if (issuer)
1042  X509_free(issuer);
1043  } else {
1044  const auto ssl_error = ERR_get_error();
1045  debugs(83, DBG_IMPORTANT, "Failed to initialize STORE_CTX object: " << Security::ErrorString(ssl_error));
1046  }
1047  X509_STORE_CTX_free(storeCtx);
1048 
1049  return gotIssuer;
1050 }
1051 
1052 const char *
1053 Ssl::uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
1054 {
1055  if (!cert || !serverCertificates.size())
1056  return nullptr;
1057 
1058  if (!findCertIssuer(serverCertificates, cert)) {
1059  //if issuer is missing
1060  if (const char *issuerUri = hasAuthorityInfoAccessCaIssuers(cert)) {
1061  // There is a URI where we can download a certificate.
1063  !issuerExistInCaDb(cert, context)) {
1064  // and issuer not found in local databases containing
1065  // untrusted certificates and trusted CA certificates
1066  return issuerUri;
1067  }
1068  }
1069  }
1070  return nullptr;
1071 }
1072 
1073 void
1074 Ssl::missingChainCertificatesUrls(std::queue<SBuf> &URIs, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
1075 {
1076  if (!serverCertificates.size())
1077  return;
1078 
1079  for (const auto &i : serverCertificates) {
1080  if (const char *issuerUri = uriOfIssuerIfMissing(i.get(), serverCertificates, context))
1081  URIs.push(SBuf(issuerUri));
1082  }
1083 }
1084 
1085 void
1086 Ssl::SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
1087 {
1088  STACK_OF(X509) *untrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1089  if (!untrustedStack) {
1090  untrustedStack = sk_X509_new_null();
1091  if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain, untrustedStack)) {
1092  sk_X509_pop_free(untrustedStack, X509_free);
1093  throw TextException("Failed to attach untrusted certificates chain", Here());
1094  }
1095  }
1096  sk_X509_push(untrustedStack, cert);
1097 }
1098 
1100 static X509 *
1101 sk_x509_findIssuer(STACK_OF(X509) *sk, X509 *cert)
1102 {
1103  if (!sk)
1104  return NULL;
1105 
1106  const int skItemsNum = sk_X509_num(sk);
1107  for (int i = 0; i < skItemsNum; ++i) {
1108  X509 *issuer = sk_X509_value(sk, i);
1109  if (X509_check_issued(issuer, cert) == X509_V_OK)
1110  return issuer;
1111  }
1112  return NULL;
1113 }
1114 
1116 static void
1117 completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) *untrustedCerts)
1118 {
1119  debugs(83, 2, "completing " << sk_X509_num(untrustedCerts) << " OpenSSL untrusted certs using " << SquidUntrustedCerts.size() << " configured untrusted certificates");
1120 
1121  const X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx);
1122  int depth = X509_VERIFY_PARAM_get_depth(param);
1123  X509 *current = X509_STORE_CTX_get0_cert(ctx);
1124  int i = 0;
1125  for (i = 0; current && (i < depth); ++i) {
1126  if (X509_check_issued(current, current) == X509_V_OK) {
1127  // either ctx->cert is itself self-signed or untrustedCerts
1128  // already contain the self-signed current certificate
1129  break;
1130  }
1131 
1132  // untrustedCerts is short, not worth indexing
1133  X509 *issuer = sk_x509_findIssuer(untrustedCerts, current);
1134  if (!issuer) {
1135  if ((issuer = findCertIssuerFast(SquidUntrustedCerts, current)))
1136  sk_X509_push(untrustedCerts, issuer);
1137  }
1138  current = issuer;
1139  }
1140 
1141  if (i >= depth)
1142  debugs(83, 2, "exceeded the maximum certificate chain length: " << depth);
1143 }
1144 
1146 static int
1147 untrustedToStoreCtx_cb(X509_STORE_CTX *ctx,void *data)
1148 {
1149  debugs(83, 4, "Try to use pre-downloaded intermediate certificates");
1150 
1151  SSL *ssl = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
1152  STACK_OF(X509) *sslUntrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1153 
1154  // OpenSSL already maintains ctx->untrusted but we cannot modify
1155  // internal OpenSSL list directly. We have to give OpenSSL our own
1156  // list, but it must include certificates on the OpenSSL ctx->untrusted
1157  STACK_OF(X509) *oldUntrusted = X509_STORE_CTX_get0_untrusted(ctx);
1158  STACK_OF(X509) *sk = sk_X509_dup(oldUntrusted); // oldUntrusted is always not NULL
1159 
1160  for (int i = 0; i < sk_X509_num(sslUntrustedStack); ++i) {
1161  X509 *cert = sk_X509_value(sslUntrustedStack, i);
1162  sk_X509_push(sk, cert);
1163  }
1164 
1165  // If the local untrusted certificates internal database is used
1166  // run completeIssuers to add missing certificates if possible.
1167  if (SquidUntrustedCerts.size() > 0)
1168  completeIssuers(ctx, sk);
1169 
1170  X509_STORE_CTX_set0_untrusted(ctx, sk); // No locking/unlocking, just sets ctx->untrusted
1171  int ret = X509_verify_cert(ctx);
1172  X509_STORE_CTX_set0_untrusted(ctx, oldUntrusted); // Set back the old untrusted list
1173  sk_X509_free(sk); // Release sk list
1174  return ret;
1175 }
1176 
1177 void
1178 Ssl::useSquidUntrusted(SSL_CTX *sslContext)
1179 {
1180  SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, NULL);
1181 }
1182 
1183 bool
1184 Ssl::loadSquidUntrusted(const char *path)
1185 {
1186  return Ssl::loadCerts(path, SquidUntrustedCerts);
1187 }
1188 
1189 void
1191 {
1192  if (SquidUntrustedCerts.size()) {
1193  for (Ssl::CertsIndexedList::iterator it = SquidUntrustedCerts.begin(); it != SquidUntrustedCerts.end(); ++it) {
1194  X509_free(it->second);
1195  }
1196  SquidUntrustedCerts.clear();
1197  }
1198 }
1199 
1200 bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const & pkey)
1201 {
1202  // Generate the self-signed certificate, using a hard-coded subject prefix
1203  Ssl::CertificateProperties certProperties;
1204  if (const char *cn = CommonHostName(cert.get())) {
1205  certProperties.commonName = "Not trusted by \"";
1206  certProperties.commonName += cn;
1207  certProperties.commonName += "\"";
1208  } else if (const char *org = getOrganization(cert.get())) {
1209  certProperties.commonName = "Not trusted by \"";
1210  certProperties.commonName += org;
1211  certProperties.commonName += "\"";
1212  } else
1213  certProperties.commonName = "Not trusted";
1214  certProperties.setCommonName = true;
1215  // O, OU, and other CA subject fields will be mimicked
1216  // Expiration date and other common properties will be mimicked
1217  certProperties.signAlgorithm = Ssl::algSignSelf;
1218  certProperties.signWithPkey.resetAndLock(pkey.get());
1219  certProperties.mimicCert.resetAndLock(cert.get());
1220  return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
1221 }
1222 
1224 {
1225  bool origSignatureAsKey = false;
1226  if (certProperties.mimicCert) {
1227  if (auto *sig = Ssl::X509_get_signature(certProperties.mimicCert)) {
1228  origSignatureAsKey = true;
1229  key.append((const char *)sig->data, sig->length);
1230  }
1231  }
1232 
1233  if (!origSignatureAsKey || certProperties.setCommonName) {
1234  // Use common name instead
1235  key.append(certProperties.commonName.c_str());
1236  }
1237  key.append(certProperties.setCommonName ? '1' : '0');
1238  key.append(certProperties.setValidAfter ? '1' : '0');
1239  key.append(certProperties.setValidBefore ? '1' : '0');
1240  key.append(certProperties.signAlgorithm != Ssl:: algSignEnd ? certSignAlgorithm(certProperties.signAlgorithm) : "-");
1241  key.append(certProperties.signHash ? EVP_MD_name(certProperties.signHash) : "-");
1242 
1243  if (certProperties.mimicCert) {
1244  Ssl::BIO_Pointer bio(BIO_new_SBuf(&key));
1245  ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bio.get(), (ASN1_VALUE *)certProperties.mimicCert.get());
1246  }
1247 }
1248 
1249 static int
1251 {
1252  BIO_set_init(bio, 0);
1253  BIO_set_data(bio, NULL);
1254  return 1;
1255 }
1256 
1257 static int
1259 {
1260  if (!bio)
1261  return 0;
1262  return 1;
1263 }
1264 
1265 int
1266 bio_sbuf_write(BIO* bio, const char* data, int len)
1267 {
1268  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1269  // TODO: Convert exceptions into BIO errors
1270  buf->append(data, len);
1271  return len;
1272 }
1273 
1274 int
1275 bio_sbuf_puts(BIO* bio, const char* data)
1276 {
1277  // TODO: use bio_sbuf_write() instead
1278  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1279  size_t oldLen = buf->length();
1280  buf->append(data);
1281  return buf->length() - oldLen;
1282 }
1283 
1284 long
1285 bio_sbuf_ctrl(BIO* bio, int cmd, long num, void* ptr) {
1286  SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1287  switch (cmd) {
1288  case BIO_CTRL_RESET:
1289  // TODO: Convert exceptions into BIO errors
1290  buf->clear();
1291  return 1;
1292  case BIO_CTRL_FLUSH:
1293  return 1;
1294  default:
1295  return 0;
1296  }
1297 }
1298 
1300 {
1301 #if HAVE_LIBCRYPTO_BIO_METH_NEW
1302  static BIO_METHOD *BioSBufMethods = nullptr;
1303  if (!BioSBufMethods) {
1304  BioSBufMethods = BIO_meth_new(BIO_TYPE_MEM, "Squid-SBuf");
1305  BIO_meth_set_write(BioSBufMethods, bio_sbuf_write);
1306  BIO_meth_set_read(BioSBufMethods, nullptr);
1307  BIO_meth_set_puts(BioSBufMethods, bio_sbuf_puts);
1308  BIO_meth_set_gets(BioSBufMethods, nullptr);
1309  BIO_meth_set_ctrl(BioSBufMethods, bio_sbuf_ctrl);
1310  BIO_meth_set_create(BioSBufMethods, bio_sbuf_create);
1311  BIO_meth_set_destroy(BioSBufMethods, bio_sbuf_destroy);
1312  }
1313 #else
1314  static BIO_METHOD *BioSBufMethods = new BIO_METHOD({
1315  BIO_TYPE_MEM,
1316  "Squid SBuf",
1318  nullptr,
1319  bio_sbuf_puts,
1320  nullptr,
1321  bio_sbuf_ctrl,
1324  NULL
1325  });
1326 #endif
1327  BIO *bio = BIO_new(BioSBufMethods);
1328  Must(bio);
1329  BIO_set_data(bio, buf);
1330  BIO_set_init(bio, 1);
1331  return bio;
1332 }
1333 
1334 #endif /* USE_OPENSSL */
1335 
const char * sslGetCAAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:722
bool updateContextConfig(Security::ContextPointer &)
update the given TLS security context using squid.conf settings
static bool issuerExistInCaDb(X509 *cert, const Security::ContextPointer &connContext)
Definition: support.cc:1025
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, Security::ParsedPortFlags)
initialize a TLS client context with OpenSSL specific settings
Definition: support.cc:561
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:179
void Initialize()
Definition: support.cc:509
static void ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:483
#define Here()
source code location of the caller
Definition: Here.h:15
void InRamCertificateDbKey(const Ssl::CertificateProperties &certProperties, SBuf &key)
Definition: support.cc:1223
@ SQUID_X509_V_ERR_DOMAIN_MISMATCH
Definition: forward.h:206
static const char * hasAuthorityInfoAccessCaIssuers(X509 *cert)
Definition: support.cc:941
CertSignAlgorithm
Definition: gadgets.h:150
bool generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const &pkey)
Definition: support.cc:1200
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:1178
Security::CertPointer mimicCert
Certificate to mimic.
Definition: gadgets.h:216
const char * CommonHostName(X509 *x509)
Definition: gadgets.cc:903
int ssl_ex_index_ssl_errors
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &)
initialize a TLS server context with OpenSSL specific settings
Definition: support.cc:552
bool isEmpty() const
Definition: SBuf.h:420
#define SQUID_CERT_VALIDATION_ITERATION_MAX
Definition: support.h:45
static int untrustedToStoreCtx_cb(X509_STORE_CTX *ctx, void *data)
OpenSSL certificate validation callback.
Definition: support.cc:1147
const EVP_MD * signHash
The signing hash to use.
Definition: gadgets.h:224
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
Definition: Debug.h:114
virtual Security::ContextPointer createBlankContext() const
generate an unset security context object
GETX509ATTRIBUTE GetX509Fingerprint
Definition: support.h:118
bool isAnyAddr() const
Definition: Address.cc:170
static void completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) *untrustedCerts)
add missing issuer certificates to untrustedCerts
Definition: support.cc:1117
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:776
std::unique_ptr< BIO, HardFun< void, BIO *, &BIO_vfree > > BIO_Pointer
Definition: gadgets.h:50
void error(char *format,...)
#define SQUID_SSL_SIGN_HASH_IF_NONE
Definition: gadgets.h:39
void SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
Definition: support.cc:1086
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:193
static void ssl_ask_password(SSL_CTX *context, const char *prompt)
Definition: support.cc:89
Definition: SBuf.h:87
const char * certSignAlgorithm(int sg)
Definition: gadgets.h:163
long bio_sbuf_ctrl(BIO *bio, int cmd, long num, void *ptr)
Definition: support.cc:1285
GETX509PEM GetX509PEM
Definition: support.h:115
static void ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:501
GETX509ATTRIBUTE GetX509CAAttribute
Definition: support.h:112
static X509 * findCertIssuerFast(Ssl::CertsIndexedList &list, X509 *cert)
Definition: support.cc:993
#define SSL_FLAG_DELAYED_AUTH
Definition: forward.h:48
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:336
const char * sslGetUserEmail(SSL *ssl)
Definition: support.cc:736
BIO * BIO_new_SBuf(SBuf *buf)
Definition: support.cc:1299
int matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
Definition: Uri.cc:744
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:60
static int check_domain(void *check_data, ASN1_STRING *cn_data)
Definition: support.cc:229
#define DBG_IMPORTANT
Definition: Debug.h:46
static int port
Definition: ldap_backend.cc:69
const ASN1_BIT_STRING * X509_get_signature(const Security::CertPointer &)
Definition: gadgets.cc:939
int ssl_ex_index_ssl_cert_chain
bool checkX509ServerValidity(X509 *cert, const char *server)
Definition: support.cc:252
static void ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:455
static bool Enabled(const int section, const int level)
whether debugging the given section and the given level produces output
Definition: Debug.h:75
static void ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:447
std::list< Security::KeyData > certs
details from the cert= and file= config parameters
Definition: PeerOptions.h:103
#define MAX_URL
Definition: defines.h:118
void BIO_set_data(BIO *table, void *data)
Definition: openssl.h:66
int size
Definition: ModDevPoll.cc:77
const char * GetErrorDescr(Security::ErrorCode value)
A short description of the TLS error "value".
Definition: ErrorDetail.cc:158
Security::CertPointer serverCert
#define NULL
Definition: types.h:166
@ algSignTrusted
Definition: gadgets.h:150
const char * uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1053
#define X509_getm_notBefore
Definition: openssl.h:206
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:128
const EVP_MD * DefaultSignHash
Definition: support.cc:44
struct SquidConfig::@105 Program
X509 * X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
Definition: openssl.h:188
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:675
void configureUnconfiguredSslContext(Security::ContextPointer &, Ssl::CertSignAlgorithm signAlgorithm, AnyP::PortCfg &)
Definition: support.cc:846
const char * getOrganization(X509 *x509)
Definition: gadgets.cc:908
void const char HLPCB void * data
Definition: stub_helper.cc:16
long ParsedPortFlags
Definition: forward.h:172
Security::SessionPointer NewSessionObject(const Security::ContextPointer &)
Definition: Session.cc:97
Config TheConfig
Definition: Config.cc:12
#define assert(EX)
Definition: assert.h:19
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:793
int bio_sbuf_write(BIO *bio, const char *data, int len)
Definition: support.cc:1266
#define X509_STORE_CTX_set0_untrusted
Definition: openssl.h:204
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:435
const char * c_str()
Definition: SBuf.cc:523
SBuf sslGetUserCertificateChainPEM(SSL *ssl)
Definition: support.cc:753
Security::ContextPointer GenerateSslContext(CertificateProperties const &, Security::ServerOptions &, bool trusted)
Definition: support.cc:807
#define DBG_PARSE_NOTE(x)
Definition: Debug.h:50
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:1250
const char * sslGetUserAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:709
void unloadSquidUntrusted()
Definition: support.cc:1190
#define SSL_FLAG_DONT_VERIFY_PEER
Definition: forward.h:49
SBuf & append(const SBuf &S)
Definition: SBuf.cc:192
static void ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *, int, long, void *)
Definition: support.cc:472
static X509 * sk_x509_findIssuer(STACK_OF(X509) *sk, X509 *cert)
Search for the issuer certificate of cert in sk list.
Definition: support.cc:1101
#define X509_getm_notAfter
Definition: openssl.h:205
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
Definition: openssl.h:227
int ssl_ex_index_server
@ SQUID_X509_V_ERR_CERT_CHANGE
Definition: forward.h:205
std::vector< const char * > BumpModeStr
Definition: support.cc:46
static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx)
Definition: support.cc:259
@ SQUID_X509_V_ERR_INFINITE_VALIDATION
Definition: forward.h:207
void SQUID_OPENSSL_init_ssl(void)
Definition: openssl.h:236
TLS squid.conf settings for a listening port.
Definition: ServerOptions.h:26
void chainCertificatesToSSLContext(Security::ContextPointer &, Security::ServerOptions &)
Definition: support.cc:821
bool push_back_unique(C const &element)
Definition: CbDataList.h:87
static int bio_sbuf_destroy(BIO *bio)
Definition: support.cc:1258
std::shared_ptr< SSL > SessionPointer
Definition: Session.h:44
void DisablePeerVerification(Security::ContextPointer &)
Definition: support.cc:422
bool allowed() const
Definition: Acl.h:143
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:463
int AskPasswordCb(char *buf, int size, int rwflag, void *userdata)
Definition: support.cc:64
std::list< Security::CertPointer > CertList
Definition: forward.h:91
@ mdnRejectSubsubDomains
Definition: Uri.h:226
const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
Definition: openssl.h:52
bool configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
Definition: support.cc:876
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:896
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:492
#define SSL_FLAG_CONDITIONAL_AUTH
Definition: forward.h:54
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:72
char * ssl_password
Definition: SquidConfig.h:207
int bio_sbuf_puts(BIO *bio, const char *data)
Definition: support.cc:1275
static const char * ssl_get_attribute(X509_NAME *name, const char *attribute_name)
Definition: support.cc:619
static Ssl::CertsIndexedList SquidUntrustedCerts
Definition: support.cc:42
CertSignAlgorithm signAlgorithm
The signing algorithm to use.
Definition: gadgets.h:223
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
int ssl_ex_index_ssl_validation_counter
int ssl_ex_index_ssl_untrusted_chain
Definition: support.cc:40
bool setValidAfter
Do not mimic "Not Valid After" field.
Definition: gadgets.h:219
int ssl_ctx_ex_index_dont_verify_domain
void missingChainCertificatesUrls(std::queue< SBuf > &URIs, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1074
void ConfigurePeerVerification(Security::ContextPointer &, const Security::ParsedPortFlags)
set the certificate verify callback for a context
Definition: support.cc:395
bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
Definition: support.cc:971
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
Definition: openssl.h:195
void BIO_set_init(BIO *table, int init)
Definition: openssl.h:72
bool configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
Definition: support.cc:853
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:1184
static bool findCertIssuer(Security::CertList const &list, X509 *cert)
slowly find the issuer certificate of a given cert using linear search
Definition: support.cc:1014
void const char * buf
Definition: stub_helper.cc:16
SBuf sslGetUserCertificatePEM(SSL *ssl)
Definition: support.cc:742
int ssl_ex_index_ssl_error_detail
void setClientSNI(SSL *ssl, const char *fqdn)
Definition: support.cc:921
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