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