proxygen
SSLUtil.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <wangle/ssl/SSLUtil.h>
17 
18 #include <folly/Format.h>
19 #include <folly/Memory.h>
21 
22 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL
23 #define OPENSSL_GE_101 1
24 #include <openssl/asn1.h>
25 #include <openssl/x509v3.h>
26 #include <openssl/bio.h>
27 #else
28 #undef OPENSSL_GE_101
29 #endif
30 
31 namespace wangle {
32 
34  SSLErrorEnum const error,
35  std::chrono::milliseconds const& latency,
36  uint64_t const bytesRead)
37  : std::runtime_error(folly::sformat(
38  "SSL error: {}; Elapsed time: {} ms; Bytes read: {}",
39  static_cast<int>(error),
40  latency.count(),
41  bytesRead)),
42  error_(error), latency_(latency), bytesRead_(bytesRead) {}
43 
45 
47  return sslSocket->getSSLSessionReused() ?
48  (sslSocket->sessionIDResumed() ?
52 }
53 
54 std::unique_ptr<std::string> SSLUtil::getCommonName(const X509* cert) {
55  X509_NAME* subject = X509_get_subject_name((X509*)cert);
56  if (!subject) {
57  return nullptr;
58  }
59  char cn[ub_common_name + 1];
60  int res = X509_NAME_get_text_by_NID(subject, NID_commonName,
61  cn, ub_common_name);
62  if (res <= 0) {
63  return nullptr;
64  } else {
65  cn[ub_common_name] = '\0';
66  return std::make_unique<std::string>(cn);
67  }
68 }
69 
70 std::unique_ptr<std::list<std::string>> SSLUtil::getSubjectAltName(
71  const X509* cert) {
72 #ifdef OPENSSL_GE_101
73  auto nameList = std::make_unique<std::list<std::string>>();
74  GENERAL_NAMES* names = (GENERAL_NAMES*)X509_get_ext_d2i(
75  (X509*)cert, NID_subject_alt_name, nullptr, nullptr);
76  if (names) {
77  auto guard = folly::makeGuard([names] { GENERAL_NAMES_free(names); });
78  size_t count = sk_GENERAL_NAME_num(names);
79  CHECK(count < std::numeric_limits<int>::max());
80  for (int i = 0; i < (int)count; ++i) {
81  GENERAL_NAME* generalName = sk_GENERAL_NAME_value(names, i);
82  if (generalName->type == GEN_DNS) {
83  ASN1_STRING* s = generalName->d.dNSName;
84  const char* name = (const char*)ASN1_STRING_get0_data(s);
85  // I can't find any docs on what a negative return value here
86  // would mean, so I'm going to ignore it.
87  auto len = ASN1_STRING_length(s);
88  DCHECK(len >= 0);
89  if (size_t(len) != strlen(name)) {
90  // Null byte(s) in the name; return an error rather than depending on
91  // the caller to safely handle this case.
92  return nullptr;
93  }
94  nameList->emplace_back(name);
95  }
96  }
97  }
98  return nameList;
99 #else
100  return nullptr;
101 #endif
102 }
103 
105  const std::string& certificateData) {
106  // BIO_new_mem_buf creates a bio pointing to a read-only buffer. However,
107  // older versions of OpenSSL fail to mark the first argument `const`.
109  BIO_new_mem_buf((void*)certificateData.data(), certificateData.length()));
110  if (!bio) {
111  throw std::runtime_error("Cannot create mem BIO");
112  }
113 
114  auto x509 = folly::ssl::X509UniquePtr(
115  PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
116  if (!x509) {
117  throw std::runtime_error("Cannot read X509 from PEM bio");
118  }
119  return x509;
120 }
121 
122 } // namespace wangle
bool sessionIDResumed() const
SSLResumeEnum
Definition: SSLUtil.h:35
static std::unique_ptr< std::list< std::string > > getSubjectAltName(const X509 *cert)
Definition: SSLUtil.cpp:70
SSLException(int sslError, unsigned long errError, int sslOperationReturnValue, int errno_copy)
Definition: SSLErrors.cpp:105
static folly::ssl::X509UniquePtr getX509FromCertificate(const std::string &certificateData)
Definition: SSLUtil.cpp:104
std::unique_ptr< X509, X509Deleter > X509UniquePtr
LogLevel max
Definition: LogLevel.cpp:31
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
SSLErrorEnum
Definition: SSLUtil.h:42
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
STL namespace.
unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
Definition: OpenSSL.cpp:199
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
const char * name
Definition: http_parser.c:437
static SSLResumeEnum getResumeState(folly::AsyncSSLSocket *sslSocket)
Definition: SSLUtil.cpp:46
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
static std::unique_ptr< std::string > getCommonName(const X509 *cert)
Definition: SSLUtil.cpp:54
virtual bool getSSLSessionReused() const
int * count
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
std::mutex mutex
const char * string
Definition: Conv.cpp:212
static set< string > s
static std::mutex sIndexLock_
Definition: SSLUtil.h:67