*/
#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 {
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;
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;
}
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