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