gadgets.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "base/IoManip.h"
11 #include "error/SysErrorDetail.h"
12 #include "security/Io.h"
13 #include "sbuf/Stream.h"
14 #include "ssl/gadgets.h"
15 
16 void
18 {
19  if (ERR_peek_last_error()) {
20  debugs(83, 5, "forgetting stale OpenSSL errors:" << ReportAndForgetErrors);
21  // forget errors if section/level-specific debugging above was disabled
22  while (ERR_get_error()) {}
23  }
24 
25  // Technically, the caller should just ignore (potentially stale) errno when
26  // no system calls have failed. However, due to OpenSSL error-reporting API
27  // deficiencies, many callers cannot detect when a TLS error was caused by a
28  // system call failure. We forget the stale errno (just like we forget stale
29  // OpenSSL errors above) so that the caller only uses fresh errno values.
30  errno = 0;
31 }
32 
33 std::ostream &
34 Ssl::ReportAndForgetErrors(std::ostream &os)
35 {
36  unsigned int reported = 0; // efficiently marks ForgetErrors() call boundary
37  while (const auto errorToForget = ERR_get_error())
38  os << Debug::Extra << "OpenSSL-saved error #" << (++reported) << ": " << asHex(errorToForget);
39  return os;
40 }
41 
42 [[ noreturn ]] static void
43 ThrowErrors(const char * const problem, const int savedErrno, const SourceLocation &where)
44 {
45  throw TextException(ToSBuf(problem, ": ",
47  ReportSysError(savedErrno)),
48  where);
49 }
50 
52 {
53  Security::PrivateKeyPointer pkey(EVP_PKEY_new());
54 
55  if (!pkey)
56  return NULL;
57 
58  BIGNUM_Pointer bn(BN_new());
59  if (!bn)
60  return NULL;
61 
62  if (!BN_set_word(bn.get(), RSA_F4))
63  return NULL;
64 
65  Ssl::RSA_Pointer rsa(RSA_new());
66  if (!rsa)
67  return NULL;
68 
69  int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable?
70  if (!RSA_generate_key_ex(rsa.get(), num, bn.get(), NULL))
71  return NULL;
72 
73  if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get())))
74  return NULL;
75 
76  rsa.release();
77  return pkey.release();
78 }
79 
84 static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial)
85 {
86  if (!ai)
87  return false;
88  Ssl::BIGNUM_Pointer bn(BN_new());
89  if (serial) {
90  bn.reset(BN_dup(serial));
91  } else {
92  if (!bn)
93  return false;
94 
95  if (!BN_pseudo_rand(bn.get(), 64, 0, 0))
96  return false;
97  }
98 
99  if (ai && !BN_to_ASN1_INTEGER(bn.get(), ai))
100  return false;
101  return true;
102 }
103 
104 bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey, std::string & bufferToWrite)
105 {
106  bufferToWrite.clear();
107  if (!pkey || !cert)
108  return false;
109  BIO_Pointer bio(BIO_new(BIO_s_mem()));
110  if (!bio)
111  return false;
112 
113  if (!PEM_write_bio_X509 (bio.get(), cert.get()))
114  return false;
115 
116  if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
117  return false;
118 
119  char *ptr = NULL;
120  long len = BIO_get_mem_data(bio.get(), &ptr);
121  if (!ptr)
122  return false;
123 
124  bufferToWrite = std::string(ptr, len);
125  return true;
126 }
127 
128 bool Ssl::appendCertToMemory(Security::CertPointer const & cert, std::string & bufferToWrite)
129 {
130  if (!cert)
131  return false;
132 
133  BIO_Pointer bio(BIO_new(BIO_s_mem()));
134  if (!bio)
135  return false;
136 
137  if (!PEM_write_bio_X509 (bio.get(), cert.get()))
138  return false;
139 
140  char *ptr = NULL;
141  long len = BIO_get_mem_data(bio.get(), &ptr);
142  if (!ptr)
143  return false;
144 
145  if (!bufferToWrite.empty())
146  bufferToWrite.append(" "); // add a space...
147 
148  bufferToWrite.append(ptr, len);
149  return true;
150 }
151 
152 bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, char const * bufferToRead)
153 {
154  Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
155  BIO_puts(bio.get(), bufferToRead);
156 
157  try {
158  cert = ReadCertificate(bio);
159  } catch (...) {
160  debugs(83, DBG_IMPORTANT, "ERROR: Cannot deserialize a signing certificate:" <<
161  Debug::Extra << "problem: " << CurrentException);
162  cert.reset();
163  pkey.reset();
164  return false;
165  }
166 
167  EVP_PKEY * pkeyPtr = NULL;
168  pkey.resetWithoutLocking(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, 0, 0));
169  if (!pkey)
170  return false;
171 
172  return true;
173 }
174 
175 // TODO: Convert matching BIO_s_mem() callers.
177 Ssl::ReadOnlyBioTiedTo(const char * const bufferToRead)
178 {
179  ForgetErrors();
180  // OpenSSL BIO API is not const-correct, but OpenSSL does not free or modify
181  // BIO_new_mem_buf() data because it is marked with BIO_FLAGS_MEM_RDONLY.
182  const auto castedBuffer = const_cast<char*>(bufferToRead);
183  if (const auto bio = BIO_new_mem_buf(castedBuffer, -1)) // no memcpy()
184  return BIO_Pointer(bio);
185  const auto savedErrno = errno;
186  ThrowErrors("cannot allocate OpenSSL BIO structure", savedErrno, Here());
187 }
188 
189 // According to RFC 5280 (Section A.1), the common name length in a certificate
190 // can be at most 64 characters
191 static const size_t MaxCnLen = 64;
192 
193 // Replace certs common name with the given
194 static bool replaceCommonName(Security::CertPointer & cert, std::string const &rawCn)
195 {
196  std::string cn = rawCn;
197 
198  if (cn.length() > MaxCnLen) {
199  // In the case the length of CN is more than the maximum supported size
200  // try to use the first upper level domain.
201  size_t pos = 0;
202  do {
203  pos = cn.find('.', pos + 1);
204  } while (pos != std::string::npos && (cn.length() - pos + 2) > MaxCnLen);
205 
206  // If no short domain found or this domain is a toplevel domain
207  // we failed to find a good cn name.
208  if (pos == std::string::npos || cn.find('.', pos + 1) == std::string::npos)
209  return false;
210 
211  std::string fixedCn(1, '*');
212  fixedCn.append(cn.c_str() + pos);
213  cn = fixedCn;
214  }
215 
216  // Assume [] surround an IPv6 address and strip them because browsers such
217  // as Firefox, Chromium, and Safari prefer bare IPv6 addresses in CNs.
218  if (cn.length() > 2 && *cn.begin() == '[' && *cn.rbegin() == ']')
219  cn = cn.substr(1, cn.size()-2);
220 
221  X509_NAME *name = X509_get_subject_name(cert.get());
222  if (!name)
223  return false;
224  // Remove the CN part:
225  int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
226  if (loc >=0) {
227  X509_NAME_ENTRY *tmp = X509_NAME_get_entry(name, loc);
228  X509_NAME_delete_entry(name, loc);
229  X509_NAME_ENTRY_free(tmp);
230  }
231 
232  // Add a new CN
233  return X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
234  (unsigned char *)(cn.c_str()), -1, -1, 0);
235 }
236 
237 const char *Ssl::CertSignAlgorithmStr[] = {
238  "signTrusted",
239  "signUntrusted",
240  "signSelf",
241  NULL
242 };
243 
244 const char *Ssl::CertAdaptAlgorithmStr[] = {
245  "setValidAfter",
246  "setValidBefore",
247  "setCommonName",
248  NULL
249 };
250 
252  setValidAfter(false),
253  setValidBefore(false),
254  setCommonName(false),
255  signAlgorithm(Ssl::algSignEnd),
256  signHash(NULL)
257 {}
258 
259 static void
260 printX509Signature(const Security::CertPointer &cert, std::string &out)
261 {
262  const ASN1_BIT_STRING *sig = Ssl::X509_get_signature(cert);
263  if (sig && sig->data) {
264  const unsigned char *s = sig->data;
265  for (int i = 0; i < sig->length; ++i) {
266  char hex[3];
267  snprintf(hex, sizeof(hex), "%02x", s[i]);
268  out.append(hex);
269  }
270  }
271 }
272 
273 std::string &
275 {
276  static std::string certKey;
277  certKey.clear();
278  certKey.reserve(4096);
279  if (properties.mimicCert.get())
280  printX509Signature(properties.mimicCert, certKey);
281 
282  if (certKey.empty()) {
283  certKey.append("/CN=", 4);
284  certKey.append(properties.commonName);
285  }
286 
287  if (properties.setValidAfter)
288  certKey.append("+SetValidAfter=on", 17);
289 
290  if (properties.setValidBefore)
291  certKey.append("+SetValidBefore=on", 18);
292 
293  if (properties.setCommonName) {
294  certKey.append("+SetCommonName=", 15);
295  certKey.append(properties.commonName);
296  }
297 
298  if (properties.signAlgorithm != Ssl::algSignEnd) {
299  certKey.append("+Sign=", 6);
300  certKey.append(certSignAlgorithm(properties.signAlgorithm));
301  }
302 
303  if (properties.signHash != NULL) {
304  certKey.append("+SignHash=", 10);
305  certKey.append(EVP_MD_name(properties.signHash));
306  }
307 
308  return certKey;
309 }
310 
317 static bool
319 {
320  if (!mimicCert.get() || !issuerCert.get())
321  return false;
322 
323  Ssl::AUTHORITY_KEYID_Pointer akid((AUTHORITY_KEYID *)X509_get_ext_d2i(mimicCert.get(), NID_authority_key_identifier, nullptr, nullptr));
324 
325  bool addKeyId = false, addIssuer = false;
326  if (akid.get()) {
327  addKeyId = (akid.get()->keyid != nullptr);
328  addIssuer = (akid.get()->issuer && akid.get()->serial);
329  }
330 
331  if (!addKeyId && !addIssuer)
332  return false; // No need to add AuthorityKeyIdentifier
333 
334  Ssl::ASN1_OCTET_STRING_Pointer issuerKeyId;
335  if (addKeyId) {
336  X509_EXTENSION *ext;
337  // Check if the issuer has the Subject Key Identifier extension
338  const int indx = X509_get_ext_by_NID(issuerCert.get(), NID_subject_key_identifier, -1);
339  if (indx >= 0 && (ext = X509_get_ext(issuerCert.get(), indx))) {
340  issuerKeyId.reset((ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext));
341  }
342  }
343 
344  Ssl::X509_NAME_Pointer issuerName;
345  Ssl::ASN1_INT_Pointer issuerSerial;
346  if (issuerKeyId.get() == nullptr || addIssuer) {
347  issuerName.reset(X509_NAME_dup(X509_get_issuer_name(issuerCert.get())));
348  issuerSerial.reset(ASN1_INTEGER_dup(X509_get_serialNumber(issuerCert.get())));
349  }
350 
351  Ssl::AUTHORITY_KEYID_Pointer theAuthKeyId(AUTHORITY_KEYID_new());
352  if (!theAuthKeyId.get())
353  return false;
354  theAuthKeyId.get()->keyid = issuerKeyId.release();
355  if (issuerName && issuerSerial) {
356  Ssl::GENERAL_NAME_STACK_Pointer genNames(sk_GENERAL_NAME_new_null());
357  if (genNames.get()) {
358  if (GENERAL_NAME *aname = GENERAL_NAME_new()) {
359  sk_GENERAL_NAME_push(genNames.get(), aname);
360  aname->type = GEN_DIRNAME;
361  aname->d.dirn = issuerName.release();
362  theAuthKeyId.get()->issuer = genNames.release();
363  theAuthKeyId.get()->serial = issuerSerial.release();
364  }
365  }
366  }
367 
368  // The Authority Key Identifier extension should include KeyId or/and both
370  if (!theAuthKeyId.get()->keyid && (!theAuthKeyId.get()->issuer || !theAuthKeyId.get()->serial))
371  return false;
372 
373  const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(NID_authority_key_identifier);
374  if (!method)
375  return false;
376 
377  unsigned char *ext_der = NULL;
378  int ext_len = ASN1_item_i2d((ASN1_VALUE *)theAuthKeyId.get(), &ext_der, ASN1_ITEM_ptr(method->it));
379  Ssl::ASN1_OCTET_STRING_Pointer extOct(ASN1_OCTET_STRING_new());
380  extOct.get()->data = ext_der;
381  extOct.get()->length = ext_len;
382  Ssl::X509_EXTENSION_Pointer extAuthKeyId(X509_EXTENSION_create_by_NID(NULL, NID_authority_key_identifier, 0, extOct.get()));
383  if (!extAuthKeyId.get())
384  return false;
385 
386  extOct.release();
387  if (!X509_add_ext(cert.get(), extAuthKeyId.get(), -1))
388  return false;
389 
390  return true;
391 }
392 
395 // Currently only extensions which are reported by the users that required are
396 // mimicked. More safe to mimic extensions would be added here if users request
397 // them.
398 static int
400 {
401  static int extensions[]= {
402  NID_key_usage,
403  NID_ext_key_usage,
404  NID_basic_constraints,
405  0
406  };
407 
408  // key usage bit names
409  enum {
410  DigitalSignature,
411  NonRepudiation,
412  KeyEncipherment, // NSS requires for RSA but not EC
413  DataEncipherment,
414  KeyAgreement,
415  KeyCertificateSign,
416  CRLSign,
417  EncipherOnly,
418  DecipherOnly
419  };
420 
421  // XXX: Add PublicKeyPointer. In OpenSSL, public and private keys are
422  // internally represented by EVP_PKEY pair, but GnuTLS uses distinct types.
423  const Security::PrivateKeyPointer certKey(X509_get_pubkey(mimicCert.get()));
424  const auto rsaPkey = EVP_PKEY_get0_RSA(certKey.get()) != nullptr;
425 
426  int added = 0;
427  int nid;
428  for (int i = 0; (nid = extensions[i]) != 0; ++i) {
429  const int pos = X509_get_ext_by_NID(mimicCert.get(), nid, -1);
430  if (X509_EXTENSION *ext = X509_get_ext(mimicCert.get(), pos)) {
431  // Mimic extension exactly.
432  if (X509_add_ext(cert.get(), ext, -1))
433  ++added;
434  if (nid == NID_key_usage && !rsaPkey) {
435  // NSS does not require the KeyEncipherment flag on EC keys
436  // but it does require it for RSA keys. Since ssl-bump
437  // substitutes RSA keys for EC ones, we need to ensure that
438  // that the more stringent requirements are met.
439 
440  const int p = X509_get_ext_by_NID(cert.get(), NID_key_usage, -1);
441  if ((ext = X509_get_ext(cert.get(), p)) != NULL) {
442  ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ext);
443  ASN1_BIT_STRING_set_bit(keyusage, KeyEncipherment, 1);
444 
445  //Build the ASN1_OCTET_STRING
446  const X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
447  assert(method && method->it);
448  unsigned char *ext_der = NULL;
449  int ext_len = ASN1_item_i2d((ASN1_VALUE *)keyusage,
450  &ext_der,
451  (const ASN1_ITEM *)ASN1_ITEM_ptr(method->it));
452 
453  ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
454  ext_oct->data = ext_der;
455  ext_oct->length = ext_len;
456  X509_EXTENSION_set_data(ext, ext_oct);
457 
458  ASN1_OCTET_STRING_free(ext_oct);
459  ASN1_BIT_STRING_free(keyusage);
460  }
461  }
462  }
463  }
464 
465  if (mimicAuthorityKeyId(cert, mimicCert, issuerCert))
466  ++added;
467 
468  // We could also restrict mimicking of the CA extension to CA:FALSE
469  // because Squid does not generate valid fake CA certificates.
470 
471  return added;
472 }
473 
476 static bool
478 {
479  X509_NAME *name = X509_get_subject_name(cert.get());
480  if (!name)
481  return false;
482 
483  const int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
484  if (loc < 0)
485  return false;
486 
487  ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, loc));
488  if (!cn_data)
489  return false;
490 
491  char dnsName[1024]; // DNS names are limited to 256 characters
492  const int res = snprintf(dnsName, sizeof(dnsName), "DNS:%*s", cn_data->length, cn_data->data);
493  if (res <= 0 || res >= static_cast<int>(sizeof(dnsName)))
494  return false;
495 
496  X509_EXTENSION *ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, dnsName);
497  if (!ext)
498  return false;
499 
500  const bool result = X509_add_ext(cert.get(), ext, -1);
501 
502  X509_EXTENSION_free(ext);
503  return result;
504 }
505 
507 {
508  // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name()
509  // returns a pointer to the existing subject name. Nothing to clean here.
510  if (properties.mimicCert.get()) {
511  // Leave subject empty if we cannot extract it from true cert.
512  if (X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) {
513  // X509_set_subject_name will call X509_dup for name
514  X509_set_subject_name(cert.get(), name);
515  }
516  }
517 
518  if (properties.setCommonName || !properties.mimicCert.get()) {
519  // In this case the CN of the certificate given by the user
520  // Ignore errors: it is better to make a certificate with no CN
521  // than to quit ssl-crtd helper because we cannot make a certificate.
522  // Most errors are caused by user input such as huge domain names.
523  (void)replaceCommonName(cert, properties.commonName);
524  }
525 
526  // We should get caCert notBefore and notAfter fields and do not allow
527  // notBefore/notAfter values from certToMimic before/after notBefore/notAfter
528  // fields from caCert.
529  // Currently there is not any way in openssl tollkit to compare two ASN1_TIME
530  // objects.
531  ASN1_TIME *aTime = NULL;
532  if (!properties.setValidBefore && properties.mimicCert.get())
533  aTime = X509_getm_notBefore(properties.mimicCert.get());
534  if (!aTime && properties.signWithX509.get())
535  aTime = X509_getm_notBefore(properties.signWithX509.get());
536 
537  if (aTime) {
538  if (!X509_set1_notBefore(cert.get(), aTime))
539  return false;
540  } else if (!X509_gmtime_adj(X509_getm_notBefore(cert.get()), (-2)*24*60*60))
541  return false;
542 
543  aTime = NULL;
544  if (!properties.setValidAfter && properties.mimicCert.get())
545  aTime = X509_getm_notAfter(properties.mimicCert.get());
546  if (!aTime && properties.signWithX509.get())
547  aTime = X509_getm_notAfter(properties.signWithX509.get());
548  if (aTime) {
549  if (!X509_set1_notAfter(cert.get(), aTime))
550  return false;
551  } else if (!X509_gmtime_adj(X509_getm_notAfter(cert.get()), 60*60*24*365*3))
552  return false;
553 
554  int addedExtensions = 0;
555  bool useCommonNameAsAltName = true;
556  // mimic the alias and possibly subjectAltName
557  if (properties.mimicCert.get()) {
558  unsigned char *alStr;
559  int alLen;
560  alStr = X509_alias_get0(properties.mimicCert.get(), &alLen);
561  if (alStr) {
562  X509_alias_set1(cert.get(), alStr, alLen);
563  }
564 
565  // Mimic subjectAltName unless we used a configured CN: browsers reject
566  // certificates with CN unrelated to subjectAltNames.
567  if (!properties.setCommonName) {
568  int pos = X509_get_ext_by_NID(properties.mimicCert.get(), NID_subject_alt_name, -1);
569  X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos);
570  if (ext) {
571  if (X509_add_ext(cert.get(), ext, -1))
572  ++addedExtensions;
573  }
574  // We want to mimic the server-sent subjectAltName, not enhance it.
575  useCommonNameAsAltName = false;
576  }
577 
578  addedExtensions += mimicExtensions(cert, properties.mimicCert, properties.signWithX509);
579  }
580 
581  if (useCommonNameAsAltName && addAltNameWithSubjectCn(cert))
582  ++addedExtensions;
583 
584  // According to RFC 5280, using extensions requires v3 certificate.
585  if (addedExtensions)
586  X509_set_version(cert.get(), 2); // value 2 means v3
587 
588  return true;
589 }
590 
591 static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
592 {
593  Security::PrivateKeyPointer pkey;
594  // Use signing certificates private key as generated certificate private key
595  if (properties.signWithPkey.get())
596  pkey.resetAndLock(properties.signWithPkey.get());
597  else // if not exist generate one
598  pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
599 
600  if (!pkey)
601  return false;
602 
603  Security::CertPointer cert(X509_new());
604  if (!cert)
605  return false;
606 
607  // Set pub key and serial given by the caller
608  if (!X509_set_pubkey(cert.get(), pkey.get()))
609  return false;
610  if (!setSerialNumber(X509_get_serialNumber(cert.get()), serial.get()))
611  return false;
612 
613  // Fill the certificate with the required properties
614  if (!buildCertificate(cert, properties))
615  return false;
616 
617  int ret = 0;
618  // Set issuer name, from CA or our subject name for self signed cert
619  if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithX509.get())
620  ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(properties.signWithX509.get()));
621  else // Self signed certificate, set issuer to self
622  ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(cert.get()));
623  if (!ret)
624  return false;
625 
626  const EVP_MD *hash = properties.signHash ? properties.signHash : EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE);
627  assert(hash);
628  /*Now sign the request */
629  if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithPkey.get())
630  ret = X509_sign(cert.get(), properties.signWithPkey.get(), hash);
631  else //else sign with self key (self signed request)
632  ret = X509_sign(cert.get(), pkey.get(), hash);
633 
634  if (!ret)
635  return false;
636 
637  certToStore = std::move(cert);
638  pkeyToStore = std::move(pkey);
639  return true;
640 }
641 
642 static BIGNUM *createCertSerial(unsigned char *md, unsigned int n)
643 {
644 
645  assert(n == 20); //for sha1 n is 20 (for md5 n is 16)
646 
647  BIGNUM *serial = NULL;
648  serial = BN_bin2bn(md, n, NULL);
649 
650  // if the serial is "0" set it to '1'
651  if (BN_is_zero(serial) == true)
652  BN_one(serial);
653 
654  // serial size does not exceed 20 bytes
655  assert(BN_num_bits(serial) <= 160);
656 
657  // According the RFC 5280, serial is an 20 bytes ASN.1 INTEGER (a signed big integer)
658  // and the maximum value for X.509 certificate serial number is 2^159-1 and
659  // the minimum 0. If the first bit of the serial is '1' ( eg 2^160-1),
660  // will result to a negative integer.
661  // To handle this, if the produced serial is greater than 2^159-1
662  // truncate the last bit
663  if (BN_is_bit_set(serial, 159))
664  BN_clear_bit(serial, 159);
665 
666  return serial;
667 }
668 
671 static BIGNUM *x509Digest(Security::CertPointer const & cert)
672 {
673  unsigned int n;
674  unsigned char md[EVP_MAX_MD_SIZE];
675 
676  if (!X509_digest(cert.get(),EVP_sha1(),md,&n))
677  return NULL;
678 
679  return createCertSerial(md, n);
680 }
681 
682 static BIGNUM *x509Pubkeydigest(Security::CertPointer const & cert)
683 {
684  unsigned int n;
685  unsigned char md[EVP_MAX_MD_SIZE];
686 
687  if (!X509_pubkey_digest(cert.get(),EVP_sha1(),md,&n))
688  return NULL;
689 
690  return createCertSerial(md, n);
691 }
692 
695 static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
696 {
697  Security::PrivateKeyPointer fakePkey;
698  Security::CertPointer fakeCert;
699 
700  serial.reset(x509Pubkeydigest(properties.signWithX509));
701  if (!serial.get()) {
702  serial.reset(BN_new());
703  BN_zero(serial.get());
704  }
705 
706  if (!generateFakeSslCertificate(fakeCert, fakePkey, properties, serial))
707  return false;
708 
709  // The x509Fingerprint return an SHA1 hash.
710  // both SHA1 hash and maximum serial number size are 20 bytes.
711  BIGNUM *r = x509Digest(fakeCert);
712  if (!r)
713  return false;
714 
715  serial.reset(r);
716  return true;
717 }
718 
719 bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties)
720 {
721  Ssl::BIGNUM_Pointer serial;
722 
723  if (!createSerial(serial, properties))
724  return false;
725 
726  return generateFakeSslCertificate(certToStore, pkeyToStore, properties, serial);
727 }
728 
729 bool
731 {
732  bio.reset(BIO_new(BIO_s_file()));
733  if (!bio)
734  return false;
735  if (!BIO_read_filename(bio.get(), filename))
736  return false;
737  return true;
738 }
739 
742 {
743  Assure(bio);
744  ForgetErrors();
745  if (const auto cert = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr))
746  return Security::CertPointer(cert);
747  const auto savedErrno = errno;
748 
749  // PEM_R_NO_START_LINE means OpenSSL could not find a BEGIN CERTIFICATE
750  // marker after successfully reading input. That includes such use cases as
751  // empty input, valid input exhausted by previous extractions, malformed
752  // input, and valid key-only input without the certificate. We cannot
753  // distinguish all these outcomes and treat this error as an EOF condition.
754  if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
755  // consume PEM_R_NO_START_LINE to clean global error queue (if that was
756  // the only error) and/or to let us check for other errors (otherwise)
757  (void)ERR_get_error();
758  if (!ERR_peek_last_error())
759  return nullptr; // EOF without any other errors
760  }
761 
762  ThrowErrors("cannot read a PEM-encoded certificate", savedErrno, Here());
763 }
764 
767 {
768  if (const auto cert = ReadOptionalCertificate(bio))
769  return cert;
770 
771  // PEM_R_NO_START_LINE
772  throw TextException("missing a required PEM-encoded certificate", Here());
773 }
774 
775 bool
776 Ssl::ReadPrivateKey(Ssl::BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
777 {
778  assert(bio);
779  if (EVP_PKEY *akey = PEM_read_bio_PrivateKey(bio.get(), NULL, passwd_callback, NULL)) {
780  pkey.resetWithoutLocking(akey);
781  return true;
782  }
783  return false;
784 }
785 
786 void
787 Ssl::ReadPrivateKeyFromFile(char const * keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
788 {
789  if (!keyFilename)
790  return;
791  Ssl::BIO_Pointer bio;
792  if (!OpenCertsFileForReading(bio, keyFilename))
793  return;
794  ReadPrivateKey(bio, pkey, passwd_callback);
795 }
796 
797 bool
799 {
800  bio.reset(BIO_new(BIO_s_file()));
801  if (!bio)
802  return false;
803  if (!BIO_write_filename(bio.get(), const_cast<char *>(filename)))
804  return false;
805  return true;
806 }
807 
808 bool
810 {
811  if (!cert || !bio)
812  return false;
813  if (!PEM_write_bio_X509(bio.get(), cert.get()))
814  return false;
815  return true;
816 }
817 
818 bool
819 Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
820 {
821  if (!pkey || !bio)
822  return false;
823  if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
824  return false;
825  return true;
826 }
827 
829 Ssl::OneLineSummary(X509_NAME &name)
830 {
831  return Ssl::UniqueCString(X509_NAME_oneline(&name, nullptr, 0));
832 }
833 
834 bool Ssl::sslDateIsInTheFuture(char const * date)
835 {
836  ASN1_UTCTIME tm;
837  tm.flags = 0;
838  tm.type = 23;
839  tm.data = (unsigned char *)date;
840  tm.length = strlen(date);
841 
842  return (X509_cmp_current_time(&tm) > 0);
843 }
844 
846 static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen)
847 {
848  // ASN1_Time holds time to UTCTime or GeneralizedTime form.
849  // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset]
850  // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset]
851 
852  // length should have space for data plus 2 extra bytes for the two extra year fields
853  // plus the '\0' char.
854  if ((aTime->length + 3) > bufLen)
855  return false;
856 
857  char *str;
858  if (aTime->type == V_ASN1_UTCTIME) {
859  if (aTime->data[0] > '5') { // RFC 2459, section 4.1.2.5.1
860  buf[0] = '1';
861  buf[1] = '9';
862  } else {
863  buf[0] = '2';
864  buf[1] = '0';
865  }
866  str = buf +2;
867  } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
868  str = buf;
869 
870  memcpy(str, aTime->data, aTime->length);
871  str[aTime->length] = '\0';
872  return true;
873 }
874 
875 static int asn1time_cmp(ASN1_TIME *asnTime1, ASN1_TIME *asnTime2)
876 {
877  char strTime1[64], strTime2[64];
878  if (!asn1timeToGeneralizedTimeStr(asnTime1, strTime1, sizeof(strTime1)))
879  return -1;
880  if (!asn1timeToGeneralizedTimeStr(asnTime2, strTime2, sizeof(strTime2)))
881  return -1;
882 
883  return strcmp(strTime1, strTime2);
884 }
885 
886 bool Ssl::certificateMatchesProperties(X509 *cert, CertificateProperties const &properties)
887 {
888  assert(cert);
889 
890  // For non self-signed certificates we have to check if the signing certificate changed
891  if (properties.signAlgorithm != Ssl::algSignSelf) {
892  assert(properties.signWithX509.get());
893  if (X509_check_issued(properties.signWithX509.get(), cert) != X509_V_OK)
894  return false;
895  }
896 
897  X509 *cert2 = properties.mimicCert.get();
898  // If there is not certificate to mimic stop here
899  if (!cert2)
900  return true;
901 
902  if (!properties.setCommonName) {
903  X509_NAME *cert1_name = X509_get_subject_name(cert);
904  X509_NAME *cert2_name = X509_get_subject_name(cert2);
905  if (X509_NAME_cmp(cert1_name, cert2_name) != 0)
906  return false;
907  } else if (properties.commonName != CommonHostName(cert))
908  return false;
909 
910  if (!properties.setValidBefore) {
911  const auto aTime = X509_getm_notBefore(cert);
912  const auto bTime = X509_getm_notBefore(cert2);
913  if (asn1time_cmp(aTime, bTime) != 0)
914  return false;
915  } else if (X509_cmp_current_time(X509_getm_notBefore(cert)) >= 0) {
916  // notBefore does not exist (=0) or it is in the future (>0)
917  return false;
918  }
919 
920  if (!properties.setValidAfter) {
921  const auto aTime = X509_getm_notAfter(cert);
922  const auto bTime = X509_getm_notAfter(cert2);
923  if (asn1time_cmp(aTime, bTime) != 0)
924  return false;
925  } else if (X509_cmp_current_time(X509_getm_notAfter(cert)) <= 0) {
926  // notAfter does not exist (0) or it is in the past (<0)
927  return false;
928  }
929 
930  char *alStr1;
931  int alLen;
932  alStr1 = (char *)X509_alias_get0(cert, &alLen);
933  char *alStr2 = (char *)X509_alias_get0(cert2, &alLen);
934  if ((!alStr1 && alStr2) || (alStr1 && !alStr2) ||
935  (alStr1 && alStr2 && strcmp(alStr1, alStr2)) != 0)
936  return false;
937 
938  // Compare subjectAltName extension
939  STACK_OF(GENERAL_NAME) * cert1_altnames;
940  cert1_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
941  STACK_OF(GENERAL_NAME) * cert2_altnames;
942  cert2_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert2, NID_subject_alt_name, NULL, NULL);
943  bool match = true;
944  if (cert1_altnames) {
945  int numalts = sk_GENERAL_NAME_num(cert1_altnames);
946  for (int i = 0; match && i < numalts; ++i) {
947  GENERAL_NAME *aName = sk_GENERAL_NAME_value(cert1_altnames, i);
948  match = sk_GENERAL_NAME_find(cert2_altnames, aName);
949  }
950  } else if (cert2_altnames)
951  match = false;
952 
953  sk_GENERAL_NAME_pop_free(cert1_altnames, GENERAL_NAME_free);
954  sk_GENERAL_NAME_pop_free(cert2_altnames, GENERAL_NAME_free);
955 
956  return match;
957 }
958 
959 static const char *getSubjectEntry(X509 *x509, int nid)
960 {
961  static char name[1024] = ""; // stores common name (CN)
962 
963  if (!x509)
964  return NULL;
965 
966  // TODO: What if the entry is a UTF8String? See X509_NAME_get_index_by_NID(3ssl).
967  const int nameLen = X509_NAME_get_text_by_NID(
968  X509_get_subject_name(x509),
969  nid, name, sizeof(name));
970 
971  if (nameLen > 0)
972  return name;
973 
974  return NULL;
975 }
976 
977 const char *Ssl::CommonHostName(X509 *x509)
978 {
979  return getSubjectEntry(x509, NID_commonName);
980 }
981 
982 const char *Ssl::getOrganization(X509 *x509)
983 {
984  return getSubjectEntry(x509, NID_organizationName);
985 }
986 
987 bool
989 {
990  if (!cert1 || ! cert2)
991  return false;
992 
993  int cert1Len;
994  unsigned char *cert1Asn = NULL;
995  cert1Len = ASN1_item_i2d((ASN1_VALUE *)cert1.get(), &cert1Asn, ASN1_ITEM_rptr(X509));
996 
997  int cert2Len;
998  unsigned char *cert2Asn = NULL;
999  cert2Len = ASN1_item_i2d((ASN1_VALUE *)cert2.get(), &cert2Asn, ASN1_ITEM_rptr(X509));
1000 
1001  if (cert1Len != cert2Len)
1002  return false;
1003 
1004  bool ret = (memcmp(cert1Asn, cert2Asn, cert1Len) == 0);
1005 
1006  OPENSSL_free(cert1Asn);
1007  OPENSSL_free(cert2Asn);
1008 
1009  return ret;
1010 }
1011 
1012 const ASN1_BIT_STRING *
1014 {
1015  SQUID_CONST_X509_GET0_SIGNATURE_ARGS ASN1_BIT_STRING *sig = nullptr;
1016  SQUID_CONST_X509_GET0_SIGNATURE_ARGS X509_ALGOR *sig_alg = nullptr;
1017 
1018  X509_get0_signature(&sig, &sig_alg, cert.get());
1019  return sig;
1020 }
1021 
#define Assure(condition)
Definition: Assure.h:35
#define false
Definition: GnuRegex.c:233
#define Here()
source code location of the caller
Definition: Here.h:15
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: IoManip.h:81
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
#define assert(EX)
Definition: assert.h:19
static std::ostream & Extra(std::ostream &os)
prefixes each grouped debugs() line after the first one in the group
Definition: Stream.h:117
a stream manipulator for printing a system call error (if any)
void reset()
Forget the raw pointer - unlock if any value was set. Become a nil pointer.
T * get() const
Returns raw and possibly nullptr pointer.
a source code location that is cheap to create, copy, and store
Definition: Here.h:30
Security::PrivateKeyPointer signWithPkey
The key of the signing certificate.
Definition: gadgets.h:237
Security::CertPointer signWithX509
Certificate to sign the generated request.
Definition: gadgets.h:236
bool setCommonName
Replace the CN field of the mimicking subject with the given.
Definition: gadgets.h:240
bool setValidAfter
Do not mimic "Not Valid After" field.
Definition: gadgets.h:238
CertSignAlgorithm signAlgorithm
The signing algorithm to use.
Definition: gadgets.h:242
bool setValidBefore
Do not mimic "Not Valid Before" field.
Definition: gadgets.h:239
Security::CertPointer mimicCert
Certificate to mimic.
Definition: gadgets.h:235
const EVP_MD * signHash
The signing hash to use.
Definition: gadgets.h:243
std::string commonName
A CN to use for the generated certificate.
Definition: gadgets.h:241
an std::runtime_error with thrower location info
Definition: TextException.h:21
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
const char * getOrganization(X509 *x509)
Definition: gadgets.cc:982
const char * CommonHostName(X509 *x509)
Definition: gadgets.cc:977
bool CertificatesCmp(const Security::CertPointer &cert1, const Security::CertPointer &cert2)
Definition: gadgets.cc:988
static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const *serial)
Definition: gadgets.cc:84
void ReadPrivateKeyFromFile(char const *keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
Definition: gadgets.cc:787
bool ReadPrivateKey(BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
Definition: gadgets.cc:776
bool OpenCertsFileForWriting(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:798
bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
Definition: gadgets.cc:819
bool appendCertToMemory(Security::CertPointer const &cert, std::string &bufferToWrite)
Definition: gadgets.cc:128
bool sslDateIsInTheFuture(char const *date)
Definition: gadgets.cc:834
bool OpenCertsFileForReading(BIO_Pointer &bio, const char *filename)
Definition: gadgets.cc:730
std::string & OnDiskCertificateDbKey(const CertificateProperties &)
Definition: gadgets.cc:274
bool generateSslCertificate(Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, CertificateProperties const &properties)
Definition: gadgets.cc:719
bool writeCertAndPrivateKeyToMemory(Security::CertPointer const &cert, Security::PrivateKeyPointer const &pkey, std::string &bufferToWrite)
Definition: gadgets.cc:104
bool readCertAndPrivateKeyFromMemory(Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, char const *bufferToRead)
Definition: gadgets.cc:152
bool certificateMatchesProperties(X509 *peer_cert, CertificateProperties const &properties)
Definition: gadgets.cc:886
EVP_PKEY * createSslPrivateKey()
Definition: gadgets.cc:51
bool WriteX509Certificate(BIO_Pointer &bio, const Security::CertPointer &cert)
Definition: gadgets.cc:809
const char * CertAdaptAlgorithmStr[]
Definition: gadgets.cc:244
const char * CertSignAlgorithmStr[]
Definition: gadgets.cc:237
const char * certSignAlgorithm(int sg)
Definition: gadgets.h:182
@ algSignEnd
Definition: gadgets.h:169
@ algSignSelf
Definition: gadgets.h:169
Security::LockingPointer< X509, X509_free_cpp, HardFun< int, X509 *, X509_up_ref > > CertPointer
Definition: forward.h:82
void ForgetErrors()
clear any errors that a TLS library has accumulated in its global storage
Definition: Io.cc:57
Definition: Xaction.cc:48
std::unique_ptr< BIO, HardFun< void, BIO *, &BIO_vfree > > BIO_Pointer
Definition: gadgets.h:51
std::unique_ptr< BIGNUM, HardFun< void, BIGNUM *, &BN_free > > BIGNUM_Pointer
Definition: gadgets.h:49
std::unique_ptr< RSA, HardFun< void, RSA *, &RSA_free > > RSA_Pointer
Definition: gadgets.h:61
std::unique_ptr< ASN1_OCTET_STRING, HardFun< void, ASN1_OCTET_STRING *, &ASN1_OCTET_STRING_free > > ASN1_OCTET_STRING_Pointer
Definition: gadgets.h:55
std::ostream & ReportAndForgetErrors(std::ostream &)
Definition: gadgets.cc:34
Security::CertPointer ReadOptionalCertificate(const BIO_Pointer &)
Definition: gadgets.cc:741
const ASN1_BIT_STRING * X509_get_signature(const Security::CertPointer &)
Definition: gadgets.cc:1013
UniqueCString OneLineSummary(X509_NAME &)
a RAII wrapper for the memory-allocating flavor of X509_NAME_oneline()
Definition: gadgets.cc:829
Security::CertPointer ReadCertificate(const BIO_Pointer &)
Definition: gadgets.cc:766
std::unique_ptr< STACK_OF(GENERAL_NAME), sk_GENERAL_NAME_free_wrapper > GENERAL_NAME_STACK_Pointer
Definition: gadgets.h:68
BIO_Pointer ReadOnlyBioTiedTo(const char *)
Definition: gadgets.cc:177
std::unique_ptr< X509_NAME, HardFun< void, X509_NAME *, &X509_NAME_free > > X509_NAME_Pointer
Definition: gadgets.h:59
std::unique_ptr< ASN1_INTEGER, HardFun< void, ASN1_INTEGER *, &ASN1_INTEGER_free > > ASN1_INT_Pointer
Definition: gadgets.h:53
std::unique_ptr< X509_EXTENSION, HardFun< void, X509_EXTENSION *, &X509_EXTENSION_free > > X509_EXTENSION_Pointer
Definition: gadgets.h:72
std::unique_ptr< char, HardFun< void, char *, &OPENSSL_free_for_c_strings > > UniqueCString
Definition: gadgets.h:78
void ForgetErrors()
Clear any errors accumulated by OpenSSL in its global storage.
Definition: gadgets.cc:17
std::unique_ptr< AUTHORITY_KEYID, HardFun< void, AUTHORITY_KEYID *, &AUTHORITY_KEYID_free > > AUTHORITY_KEYID_Pointer
Definition: gadgets.h:65
RSA * EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
Definition: openssl.h:104
#define X509_getm_notAfter
Definition: openssl.h:247
#define X509_getm_notBefore
Definition: openssl.h:248
#define X509_set1_notBefore
Definition: openssl.h:250
void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x)
Definition: openssl.h:219
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
Definition: openssl.h:237
#define X509_set1_notAfter
Definition: openssl.h:249
static bool match(const char *fn, const REList *list)
Definition: purge.cc:398
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
static bool replaceCommonName(Security::CertPointer &cert, std::string const &rawCn)
Definition: gadgets.cc:194
static BIGNUM * x509Pubkeydigest(Security::CertPointer const &cert)
Definition: gadgets.cc:682
static bool buildCertificate(Security::CertPointer &cert, Ssl::CertificateProperties const &properties)
Definition: gadgets.cc:506
static void printX509Signature(const Security::CertPointer &cert, std::string &out)
Definition: gadgets.cc:260
static BIGNUM * createCertSerial(unsigned char *md, unsigned int n)
Definition: gadgets.cc:642
static int mimicExtensions(Security::CertPointer &cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
Definition: gadgets.cc:399
static BIGNUM * x509Digest(Security::CertPointer const &cert)
Definition: gadgets.cc:671
static const size_t MaxCnLen
Definition: gadgets.cc:191
static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
Definition: gadgets.cc:695
static bool mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
Definition: gadgets.cc:318
static bool generateFakeSslCertificate(Security::CertPointer &certToStore, Security::PrivateKeyPointer &pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
Definition: gadgets.cc:591
static const char * getSubjectEntry(X509 *x509, int nid)
Definition: gadgets.cc:959
static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen)
Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format.
Definition: gadgets.cc:846
static bool addAltNameWithSubjectCn(Security::CertPointer &cert)
Definition: gadgets.cc:477
static int asn1time_cmp(ASN1_TIME *asnTime1, ASN1_TIME *asnTime2)
Definition: gadgets.cc:875
static void ThrowErrors(const char *const problem, const int savedErrno, const SourceLocation &where)
Definition: gadgets.cc:43
#define SQUID_SSL_SIGN_HASH_IF_NONE
Definition: gadgets.h:40
static hash_table * hash
Definition: text_backend.cc:41
#define NULL
Definition: types.h:166

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors