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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors