Expose the time remaining in HHWheelTimer::Callback
[folly.git] / folly / ssl / OpenSSLCertUtils.cpp
index ae619048de93b2c2b18b684fc53329c5661c1477..9b9efa3eb3f89401f2e303a485dbda7efb00f207 100644 (file)
  */
 #include <folly/ssl/OpenSSLCertUtils.h>
 
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
 #include <folly/ScopeGuard.h>
+#include <folly/String.h>
+#include <folly/ssl/OpenSSLPtrTypes.h>
 
 namespace folly {
 namespace ssl {
@@ -44,7 +43,7 @@ Optional<std::string> OpenSSLCertUtils::getCommonName(X509& x509) {
     return none;
   }
 
-  auto cnData = reinterpret_cast<const char*>(ASN1_STRING_data(cnAsn));
+  auto cnData = reinterpret_cast<const char*>(ASN1_STRING_get0_data(cnAsn));
   auto cnLen = ASN1_STRING_length(cnAsn);
   if (!cnData || cnLen <= 0) {
     return none;
@@ -70,8 +69,8 @@ std::vector<std::string> OpenSSLCertUtils::getSubjectAltNames(X509& x509) {
     if (!genName || genName->type != GEN_DNS) {
       continue;
     }
-    auto nameData =
-        reinterpret_cast<const char*>(ASN1_STRING_data(genName->d.dNSName));
+    auto nameData = reinterpret_cast<const char*>(
+        ASN1_STRING_get0_data(genName->d.dNSName));
     auto nameLen = ASN1_STRING_length(genName->d.dNSName);
     if (!nameData || nameLen <= 0) {
       continue;
@@ -80,5 +79,142 @@ std::vector<std::string> OpenSSLCertUtils::getSubjectAltNames(X509& x509) {
   }
   return ret;
 }
+
+Optional<std::string> OpenSSLCertUtils::getSubject(X509& x509) {
+  auto subject = X509_get_subject_name(&x509);
+  if (!subject) {
+    return none;
+  }
+
+  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
+  if (bio == nullptr) {
+    throw std::runtime_error("Cannot allocate bio");
+  }
+  if (X509_NAME_print_ex(bio.get(), subject, 0, XN_FLAG_ONELINE) <= 0) {
+    return none;
+  }
+
+  char* bioData = nullptr;
+  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
+  return std::string(bioData, bioLen);
 }
+
+Optional<std::string> OpenSSLCertUtils::getIssuer(X509& x509) {
+  auto issuer = X509_get_issuer_name(&x509);
+  if (!issuer) {
+    return none;
+  }
+
+  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
+  if (bio == nullptr) {
+    throw std::runtime_error("Cannot allocate bio");
+  }
+
+  if (X509_NAME_print_ex(bio.get(), issuer, 0, XN_FLAG_ONELINE) <= 0) {
+    return none;
+  }
+
+  char* bioData = nullptr;
+  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
+  return std::string(bioData, bioLen);
 }
+
+folly::Optional<std::string> OpenSSLCertUtils::toString(X509& x509) {
+  auto in = BioUniquePtr(BIO_new(BIO_s_mem()));
+  if (in == nullptr) {
+    throw std::runtime_error("Cannot allocate bio");
+  }
+
+  int flags = 0;
+
+  flags |= X509_FLAG_NO_HEADER | /* A few bytes of cert and data */
+      X509_FLAG_NO_PUBKEY | /* Public key */
+      X509_FLAG_NO_AUX | /* Auxiliary info? */
+      X509_FLAG_NO_SIGDUMP | /* Prints the signature */
+      X509_FLAG_NO_SIGNAME; /* Signature algorithms */
+
+#ifdef X509_FLAG_NO_IDS
+  flags |= X509_FLAG_NO_IDS; /* Issuer/subject IDs */
+#endif
+
+  if (X509_print_ex(in.get(), &x509, XN_FLAG_ONELINE, flags) > 0) {
+    char* bioData = nullptr;
+    size_t bioLen = BIO_get_mem_data(in.get(), &bioData);
+    return std::string(bioData, bioLen);
+  } else {
+    return none;
+  }
+}
+
+std::string OpenSSLCertUtils::getNotAfterTime(X509& x509) {
+  return getDateTimeStr(X509_get_notAfter(&x509));
+}
+
+std::string OpenSSLCertUtils::getNotBeforeTime(X509& x509) {
+  return getDateTimeStr(X509_get_notBefore(&x509));
+}
+
+std::string OpenSSLCertUtils::getDateTimeStr(const ASN1_TIME* time) {
+  if (!time) {
+    return "";
+  }
+
+  auto bio = BioUniquePtr(BIO_new(BIO_s_mem()));
+  if (bio == nullptr) {
+    throw std::runtime_error("Cannot allocate bio");
+  }
+
+  if (ASN1_TIME_print(bio.get(), time) <= 0) {
+    throw std::runtime_error("Cannot print ASN1_TIME");
+  }
+
+  char* bioData = nullptr;
+  size_t bioLen = BIO_get_mem_data(bio.get(), &bioData);
+  return std::string(bioData, bioLen);
+}
+
+X509UniquePtr OpenSSLCertUtils::derDecode(ByteRange range) {
+  auto begin = range.data();
+  X509UniquePtr cert(d2i_X509(nullptr, &begin, range.size()));
+  if (!cert) {
+    throw std::runtime_error("could not read cert");
+  }
+  return cert;
+}
+
+std::unique_ptr<IOBuf> OpenSSLCertUtils::derEncode(X509& x509) {
+  auto len = i2d_X509(&x509, nullptr);
+  if (len < 0) {
+    throw std::runtime_error("Error computing length");
+  }
+  auto buf = IOBuf::create(len);
+  auto dataPtr = buf->writableData();
+  len = i2d_X509(&x509, &dataPtr);
+  if (len < 0) {
+    throw std::runtime_error("Error converting cert to DER");
+  }
+  buf->append(len);
+  return buf;
+}
+
+std::vector<X509UniquePtr> OpenSSLCertUtils::readCertsFromBuffer(
+    ByteRange range) {
+  BioUniquePtr b(
+      BIO_new_mem_buf(const_cast<unsigned char*>(range.data()), range.size()));
+  if (!b) {
+    throw std::runtime_error("failed to create BIO");
+  }
+  std::vector<X509UniquePtr> certs;
+  while (true) {
+    X509UniquePtr x509(PEM_read_bio_X509(b.get(), nullptr, nullptr, nullptr));
+    if (!x509) {
+      break;
+    }
+    certs.push_back(std::move(x509));
+  }
+
+  return certs;
+}
+
+} // namespace ssl
+} // namespace folly