proxygen
SSLContext.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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 
18 
19 #include <folly/Format.h>
20 #include <folly/Memory.h>
21 #include <folly/Random.h>
22 #include <folly/SharedMutex.h>
23 #include <folly/SpinLock.h>
24 #include <folly/ssl/Init.h>
25 #include <folly/system/ThreadId.h>
26 
27 // ---------------------------------------------------------------------
28 // SSLContext implementation
29 // ---------------------------------------------------------------------
30 namespace folly {
31 //
32 // For OpenSSL portability API
33 using namespace folly::ssl;
34 
35 // SSLContext implementation
38 
39  ctx_ = SSL_CTX_new(SSLv23_method());
40  if (ctx_ == nullptr) {
41  throw std::runtime_error("SSL_CTX_new: " + getErrors());
42  }
43 
44  int opt = 0;
45  switch (version) {
46  case TLSv1:
47  opt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
48  break;
49  case SSLv3:
50  opt = SSL_OP_NO_SSLv2;
51  break;
52  case TLSv1_2:
53  opt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
54  SSL_OP_NO_TLSv1_1;
55  break;
56  default:
57  // do nothing
58  break;
59  }
60  int newOpt = SSL_CTX_set_options(ctx_, opt);
61  DCHECK((newOpt & opt) == opt);
62 
63  SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY);
64 
65  checkPeerName_ = false;
66 
67  SSL_CTX_set_options(ctx_, SSL_OP_NO_COMPRESSION);
68 
69  sslAcceptRunner_ = std::make_unique<SSLAcceptRunner>();
70 
71 #if FOLLY_OPENSSL_HAS_SNI
72  SSL_CTX_set_tlsext_servername_callback(ctx_, baseServerNameOpenSSLCallback);
73  SSL_CTX_set_tlsext_servername_arg(ctx_, this);
74 #endif
75 }
76 
78  if (ctx_ != nullptr) {
79  SSL_CTX_free(ctx_);
80  ctx_ = nullptr;
81  }
82 
83 #if FOLLY_OPENSSL_HAS_ALPN
84  deleteNextProtocolsStrings();
85 #endif
86 }
87 
88 void SSLContext::ciphers(const std::string& ciphers) {
89  setCiphersOrThrow(ciphers);
90 }
91 
93  const std::vector<std::string>& ecCurves) {
94  if (ecCurves.size() == 0) {
95  return;
96  }
97 #if OPENSSL_VERSION_NUMBER >= 0x1000200fL
98  std::string ecCurvesList;
99  join(":", ecCurves, ecCurvesList);
100  int rc = SSL_CTX_set1_curves_list(ctx_, ecCurvesList.c_str());
101  if (rc == 0) {
102  throw std::runtime_error("SSL_CTX_set1_curves_list " + getErrors());
103  }
104 #endif
105 }
106 
108 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
109  EC_KEY* ecdh = nullptr;
110  int nid;
111 
112  /*
113  * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
114  * from RFC 4492 section 5.1.1, or explicitly described curves over
115  * binary fields. OpenSSL only supports the "named curves", which provide
116  * maximum interoperability.
117  */
118 
119  nid = OBJ_sn2nid(curveName.c_str());
120  if (nid == 0) {
121  LOG(FATAL) << "Unknown curve name:" << curveName.c_str();
122  }
123  ecdh = EC_KEY_new_by_curve_name(nid);
124  if (ecdh == nullptr) {
125  LOG(FATAL) << "Unable to create curve:" << curveName.c_str();
126  }
127 
128  SSL_CTX_set_tmp_ecdh(ctx_, ecdh);
129  EC_KEY_free(ecdh);
130 #else
131  throw std::runtime_error("Elliptic curve encryption not allowed");
132 #endif
133 }
134 
136  const ssl::X509VerifyParam& x509VerifyParam) {
137  if (!x509VerifyParam) {
138  return;
139  }
140  if (SSL_CTX_set1_param(ctx_, x509VerifyParam.get()) != 1) {
141  throw std::runtime_error("SSL_CTX_set1_param " + getErrors());
142  }
143 }
144 
146  int rc = SSL_CTX_set_cipher_list(ctx_, ciphers.c_str());
147  if (rc == 0) {
148  throw std::runtime_error("SSL_CTX_set_cipher_list: " + getErrors());
149  }
150  providedCiphersString_ = ciphers;
151 }
152 
154  const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
155  CHECK(verifyPeer != SSLVerifyPeerEnum::USE_CTX); // dont recurse
156  verifyPeer_ = verifyPeer;
157 }
158 
160  const SSLContext::SSLVerifyPeerEnum& verifyPeer) {
161  CHECK(verifyPeer != SSLVerifyPeerEnum::USE_CTX);
162  int mode = SSL_VERIFY_NONE;
163  switch (verifyPeer) {
164  // case SSLVerifyPeerEnum::USE_CTX: // can't happen
165  // break;
166 
167  case SSLVerifyPeerEnum::VERIFY:
168  mode = SSL_VERIFY_PEER;
169  break;
170 
171  case SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT:
172  mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
173  break;
174 
175  case SSLVerifyPeerEnum::NO_VERIFY:
176  mode = SSL_VERIFY_NONE;
177  break;
178 
179  default:
180  break;
181  }
182  return mode;
183 }
184 
186  return getVerificationMode(verifyPeer_);
187 }
188 
190  bool checkPeerCert,
191  bool checkPeerName,
192  const std::string& peerName) {
193  int mode;
194  if (checkPeerCert) {
195  mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
196  SSL_VERIFY_CLIENT_ONCE;
197  checkPeerName_ = checkPeerName;
198  peerFixedName_ = peerName;
199  } else {
200  mode = SSL_VERIFY_NONE;
201  checkPeerName_ = false; // can't check name without cert!
202  peerFixedName_.clear();
203  }
204  SSL_CTX_set_verify(ctx_, mode, nullptr);
205 }
206 
207 void SSLContext::loadCertificate(const char* path, const char* format) {
208  if (path == nullptr || format == nullptr) {
209  throw std::invalid_argument(
210  "loadCertificateChain: either <path> or <format> is nullptr");
211  }
212  if (strcmp(format, "PEM") == 0) {
213  if (SSL_CTX_use_certificate_chain_file(ctx_, path) != 1) {
214  int errnoCopy = errno;
215  std::string reason("SSL_CTX_use_certificate_chain_file: ");
216  reason.append(path);
217  reason.append(": ");
218  reason.append(getErrors(errnoCopy));
219  throw std::runtime_error(reason);
220  }
221  } else {
222  throw std::runtime_error(
223  "Unsupported certificate format: " + std::string(format));
224  }
225 }
226 
228  if (cert.data() == nullptr) {
229  throw std::invalid_argument("loadCertificate: <cert> is nullptr");
230  }
231 
232  ssl::BioUniquePtr bio(BIO_new(BIO_s_mem()));
233  if (bio == nullptr) {
234  throw std::runtime_error("BIO_new: " + getErrors());
235  }
236 
237  int written = BIO_write(bio.get(), cert.data(), int(cert.size()));
238  if (written <= 0 || static_cast<unsigned>(written) != cert.size()) {
239  throw std::runtime_error("BIO_write: " + getErrors());
240  }
241 
242  ssl::X509UniquePtr x509(
243  PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
244  if (x509 == nullptr) {
245  throw std::runtime_error("PEM_read_bio_X509: " + getErrors());
246  }
247 
248  if (SSL_CTX_use_certificate(ctx_, x509.get()) == 0) {
249  throw std::runtime_error("SSL_CTX_use_certificate: " + getErrors());
250  }
251 }
252 
253 void SSLContext::loadPrivateKey(const char* path, const char* format) {
254  if (path == nullptr || format == nullptr) {
255  throw std::invalid_argument(
256  "loadPrivateKey: either <path> or <format> is nullptr");
257  }
258  if (strcmp(format, "PEM") == 0) {
259  if (SSL_CTX_use_PrivateKey_file(ctx_, path, SSL_FILETYPE_PEM) == 0) {
260  throw std::runtime_error("SSL_CTX_use_PrivateKey_file: " + getErrors());
261  }
262  } else {
263  throw std::runtime_error(
264  "Unsupported private key format: " + std::string(format));
265  }
266 }
267 
269  if (pkey.data() == nullptr) {
270  throw std::invalid_argument("loadPrivateKey: <pkey> is nullptr");
271  }
272 
273  ssl::BioUniquePtr bio(BIO_new(BIO_s_mem()));
274  if (bio == nullptr) {
275  throw std::runtime_error("BIO_new: " + getErrors());
276  }
277 
278  int written = BIO_write(bio.get(), pkey.data(), int(pkey.size()));
279  if (written <= 0 || static_cast<unsigned>(written) != pkey.size()) {
280  throw std::runtime_error("BIO_write: " + getErrors());
281  }
282 
284  PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
285  if (key == nullptr) {
286  throw std::runtime_error("PEM_read_bio_PrivateKey: " + getErrors());
287  }
288 
289  if (SSL_CTX_use_PrivateKey(ctx_, key.get()) == 0) {
290  throw std::runtime_error("SSL_CTX_use_PrivateKey: " + getErrors());
291  }
292 }
293 
295  folly::StringPiece cert,
296  folly::StringPiece pkey) {
297  loadCertificateFromBufferPEM(cert);
298  loadPrivateKeyFromBufferPEM(pkey);
299  if (!isCertKeyPairValid()) {
300  throw std::runtime_error("SSL certificate and private key do not match");
301  }
302 }
303 
305  const char* certPath,
306  const char* keyPath,
307  const char* certFormat,
308  const char* keyFormat) {
309  loadCertificate(certPath, certFormat);
310  loadPrivateKey(keyPath, keyFormat);
311  if (!isCertKeyPairValid()) {
312  throw std::runtime_error("SSL certificate and private key do not match");
313  }
314 }
315 
317  return SSL_CTX_check_private_key(ctx_) == 1;
318 }
319 
320 void SSLContext::loadTrustedCertificates(const char* path) {
321  if (path == nullptr) {
322  throw std::invalid_argument("loadTrustedCertificates: <path> is nullptr");
323  }
324  if (SSL_CTX_load_verify_locations(ctx_, path, nullptr) == 0) {
325  throw std::runtime_error("SSL_CTX_load_verify_locations: " + getErrors());
326  }
327  ERR_clear_error();
328 }
329 
330 void SSLContext::loadTrustedCertificates(X509_STORE* store) {
331  SSL_CTX_set_cert_store(ctx_, store);
332 }
333 
334 void SSLContext::loadClientCAList(const char* path) {
335  auto clientCAs = SSL_load_client_CA_file(path);
336  if (clientCAs == nullptr) {
337  LOG(ERROR) << "Unable to load ca file: " << path << " " << getErrors();
338  return;
339  }
340  SSL_CTX_set_client_CA_list(ctx_, clientCAs);
341 }
342 
344  std::shared_ptr<PasswordCollector> collector) {
345  if (collector == nullptr) {
346  LOG(ERROR) << "passwordCollector: ignore invalid password collector";
347  return;
348  }
349  collector_ = collector;
350  SSL_CTX_set_default_passwd_cb(ctx_, passwordCallback);
351  SSL_CTX_set_default_passwd_cb_userdata(ctx_, this);
352 }
353 
354 #if FOLLY_OPENSSL_HAS_SNI
355 
356 void SSLContext::setServerNameCallback(const ServerNameCallback& cb) {
357  serverNameCb_ = cb;
358 }
359 
360 void SSLContext::addClientHelloCallback(const ClientHelloCallback& cb) {
361  clientHelloCbs_.push_back(cb);
362 }
363 
364 int SSLContext::baseServerNameOpenSSLCallback(SSL* ssl, int* al, void* data) {
365  SSLContext* context = (SSLContext*)data;
366 
367  if (context == nullptr) {
368  return SSL_TLSEXT_ERR_NOACK;
369  }
370 
371  for (auto& cb : context->clientHelloCbs_) {
372  // Generic callbacks to happen after we receive the Client Hello.
373  // For example, we use one to switch which cipher we use depending
374  // on the user's TLS version. Because the primary purpose of
375  // baseServerNameOpenSSLCallback is for SNI support, and these callbacks
376  // are side-uses, we ignore any possible failures other than just logging
377  // them.
378  cb(ssl);
379  }
380 
381  if (!context->serverNameCb_) {
382  return SSL_TLSEXT_ERR_NOACK;
383  }
384 
385  ServerNameCallbackResult ret = context->serverNameCb_(ssl);
386  switch (ret) {
387  case SERVER_NAME_FOUND:
388  return SSL_TLSEXT_ERR_OK;
389  case SERVER_NAME_NOT_FOUND:
390  return SSL_TLSEXT_ERR_NOACK;
391  case SERVER_NAME_NOT_FOUND_ALERT_FATAL:
392  *al = TLS1_AD_UNRECOGNIZED_NAME;
393  return SSL_TLSEXT_ERR_ALERT_FATAL;
394  default:
395  CHECK(false);
396  }
397 
398  return SSL_TLSEXT_ERR_NOACK;
399 }
400 #endif // FOLLY_OPENSSL_HAS_SNI
401 
402 #if FOLLY_OPENSSL_HAS_ALPN
403 int SSLContext::alpnSelectCallback(
404  SSL* /* ssl */,
405  const unsigned char** out,
406  unsigned char* outlen,
407  const unsigned char* in,
408  unsigned int inlen,
409  void* data) {
410  SSLContext* context = (SSLContext*)data;
411  CHECK(context);
412  if (context->advertisedNextProtocols_.empty()) {
413  *out = nullptr;
414  *outlen = 0;
415  } else {
416  auto i = context->pickNextProtocols();
417  const auto& item = context->advertisedNextProtocols_[i];
418  if (SSL_select_next_proto(
419  (unsigned char**)out,
420  outlen,
421  item.protocols,
422  item.length,
423  in,
424  inlen) != OPENSSL_NPN_NEGOTIATED) {
425  return SSL_TLSEXT_ERR_NOACK;
426  }
427  }
428  return SSL_TLSEXT_ERR_OK;
429 }
430 
431 bool SSLContext::setAdvertisedNextProtocols(
432  const std::list<std::string>& protocols) {
433  return setRandomizedAdvertisedNextProtocols({{1, protocols}});
434 }
435 
436 bool SSLContext::setRandomizedAdvertisedNextProtocols(
437  const std::list<NextProtocolsItem>& items) {
438  unsetNextProtocols();
439  if (items.size() == 0) {
440  return false;
441  }
442  int total_weight = 0;
443  for (const auto& item : items) {
444  if (item.protocols.size() == 0) {
445  continue;
446  }
447  AdvertisedNextProtocolsItem advertised_item;
448  advertised_item.length = 0;
449  for (const auto& proto : item.protocols) {
450  ++advertised_item.length;
451  auto protoLength = proto.length();
452  if (protoLength >= 256) {
453  deleteNextProtocolsStrings();
454  return false;
455  }
456  advertised_item.length += unsigned(protoLength);
457  }
458  advertised_item.protocols = new unsigned char[advertised_item.length];
459  if (!advertised_item.protocols) {
460  throw std::runtime_error("alloc failure");
461  }
462  unsigned char* dst = advertised_item.protocols;
463  for (auto& proto : item.protocols) {
464  uint8_t protoLength = uint8_t(proto.length());
465  *dst++ = (unsigned char)protoLength;
466  memcpy(dst, proto.data(), protoLength);
467  dst += protoLength;
468  }
469  total_weight += item.weight;
470  advertisedNextProtocols_.push_back(advertised_item);
471  advertisedNextProtocolWeights_.push_back(item.weight);
472  }
473  if (total_weight == 0) {
474  deleteNextProtocolsStrings();
475  return false;
476  }
477  nextProtocolDistribution_ = std::discrete_distribution<>(
478  advertisedNextProtocolWeights_.begin(),
479  advertisedNextProtocolWeights_.end());
480  SSL_CTX_set_alpn_select_cb(ctx_, alpnSelectCallback, this);
481  // Client cannot really use randomized alpn
482  // Note that this function reverses the typical return value convention
483  // of openssl and returns 0 on success.
484  if (SSL_CTX_set_alpn_protos(
485  ctx_,
486  advertisedNextProtocols_[0].protocols,
487  advertisedNextProtocols_[0].length) != 0) {
488  return false;
489  }
490  return true;
491 }
492 
493 void SSLContext::deleteNextProtocolsStrings() {
494  for (auto protocols : advertisedNextProtocols_) {
495  delete[] protocols.protocols;
496  }
497  advertisedNextProtocols_.clear();
498  advertisedNextProtocolWeights_.clear();
499 }
500 
501 void SSLContext::unsetNextProtocols() {
502  deleteNextProtocolsStrings();
503  SSL_CTX_set_alpn_select_cb(ctx_, nullptr, nullptr);
504  SSL_CTX_set_alpn_protos(ctx_, nullptr, 0);
505  // clear the error stack here since openssl internals sometimes add a
506  // malloc failure when doing a memdup of NULL, 0..
507  ERR_clear_error();
508 }
509 
510 size_t SSLContext::pickNextProtocols() {
511  CHECK(!advertisedNextProtocols_.empty()) << "Failed to pickNextProtocols";
512  auto rng = ThreadLocalPRNG();
513  return size_t(nextProtocolDistribution_(rng));
514 }
515 
516 #endif // FOLLY_OPENSSL_HAS_ALPN
517 
518 SSL* SSLContext::createSSL() const {
519  SSL* ssl = SSL_new(ctx_);
520  if (ssl == nullptr) {
521  throw std::runtime_error("SSL_new: " + getErrors());
522  }
523  return ssl;
524 }
525 
527  SSL_CTX_set_session_id_context(
528  ctx_,
529  reinterpret_cast<const unsigned char*>(context.data()),
530  std::min<unsigned int>(
531  static_cast<unsigned int>(context.length()), SSL_MAX_SID_CTX_LENGTH));
532 }
533 
543 bool SSLContext::matchName(const char* host, const char* pattern, int size) {
544  bool match = false;
545  int i = 0, j = 0;
546  while (i < size && host[j] != '\0') {
547  if (toupper(pattern[i]) == toupper(host[j])) {
548  i++;
549  j++;
550  continue;
551  }
552  if (pattern[i] == '*') {
553  while (host[j] != '.' && host[j] != '\0') {
554  j++;
555  }
556  i++;
557  continue;
558  }
559  break;
560  }
561  if (i == size && host[j] == '\0') {
562  match = true;
563  }
564  return match;
565 }
566 
567 int SSLContext::passwordCallback(char* password, int size, int, void* data) {
568  SSLContext* context = (SSLContext*)data;
569  if (context == nullptr || context->passwordCollector() == nullptr) {
570  return 0;
571  }
572  std::string userPassword;
573  // call user defined password collector to get password
574  context->passwordCollector()->getPassword(userPassword, size);
575  auto const length = std::min(userPassword.size(), size_t(size));
576  std::memcpy(password, userPassword.data(), length);
577  return int(length);
578 }
579 
580 #if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
581 void SSLContext::enableFalseStart() {
582  SSL_CTX_set_mode(ctx_, SSL_MODE_HANDSHAKE_CUTTHROUGH);
583 }
584 #endif
585 
588 }
589 
590 void SSLContext::setOptions(long options) {
591  long newOpt = SSL_CTX_set_options(ctx_, options);
592  if ((newOpt & options) != options) {
593  throw std::runtime_error("SSL_CTX_set_options failed");
594  }
595 }
596 
598  std::string errors;
599  unsigned long errorCode;
600  char message[256];
601 
602  errors.reserve(512);
603  while ((errorCode = ERR_get_error()) != 0) {
604  if (!errors.empty()) {
605  errors += "; ";
606  }
607  const char* reason = ERR_reason_error_string(errorCode);
608  if (reason == nullptr) {
609  snprintf(message, sizeof(message) - 1, "SSL error # %08lX", errorCode);
610  reason = message;
611  }
612  errors += reason;
613  }
614  if (errors.empty()) {
615  errors = "error code: " + folly::to<std::string>(errnoCopy);
616  }
617  return errors;
618 }
619 
620 std::ostream& operator<<(std::ostream& os, const PasswordCollector& collector) {
621  os << collector.describe();
622  return os;
623 }
624 
625 } // namespace folly
static std::string getErrors()
Definition: SSLContext.h:137
virtual void loadCertificateFromBufferPEM(folly::StringPiece cert)
Definition: SSLContext.cpp:227
virtual void loadCertKeyPairFromBufferPEM(folly::StringPiece cert, folly::StringPiece pkey)
Definition: SSLContext.cpp:294
virtual std::shared_ptr< PasswordCollector > passwordCollector()
Definition: SSLContext.h:379
Definition: test.c:42
SSL * createSSL() const
Definition: SSLContext.cpp:518
virtual int getVerificationMode()
Definition: SSLContext.cpp:185
std::unique_ptr< X509, X509Deleter > X509UniquePtr
std::unique_ptr< BIO, BioDeleter > BioUniquePtr
virtual void setVerificationOption(const SSLVerifyPeerEnum &verifyPeer)
Definition: SSLContext.cpp:153
virtual bool isCertKeyPairValid() const
Definition: SSLContext.cpp:316
context
Definition: CMakeCache.txt:563
constexpr size_type size() const
Definition: Range.h:431
static bool matchName(const char *host, const char *pattern, int size)
Definition: SSLContext.cpp:543
void init()
Definition: Init.cpp:54
std::unique_ptr< EVP_PKEY, EvpPkeyDeleter > EvpPkeyUniquePtr
virtual void loadClientCAList(const char *path)
Definition: SSLContext.cpp:334
static void initializeOpenSSL()
Definition: SSLContext.cpp:586
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void setOptions(long options)
Definition: SSLContext.cpp:590
std::shared_ptr< FizzServerContext > ctx_
virtual void setCiphersOrThrow(const std::string &ciphers)
Definition: SSLContext.cpp:145
void setX509VerifyParam(const ssl::X509VerifyParam &x509VerifyParam)
Definition: SSLContext.cpp:135
virtual void loadCertKeyPairFromFiles(const char *certPath, const char *keyPath, const char *certFormat="PEM", const char *keyFormat="PEM")
Definition: SSLContext.cpp:304
folly::Optional< PskKeyExchangeMode > mode
auto rng
Definition: CollectTest.cpp:31
ProtocolVersion version
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
LogLevel min
Definition: LogLevel.cpp:30
virtual ~SSLContext()
Definition: SSLContext.cpp:77
virtual void loadPrivateKeyFromBufferPEM(folly::StringPiece pkey)
Definition: SSLContext.cpp:268
virtual std::string describe() const =0
constexpr Iter data() const
Definition: Range.h:446
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
virtual void ciphers(const std::string &ciphers)
Definition: SSLContext.cpp:88
virtual void loadPrivateKey(const char *path, const char *format="PEM")
Definition: SSLContext.cpp:253
virtual void loadCertificate(const char *path, const char *format="PEM")
Definition: SSLContext.cpp:207
std::string message
Definition: SPDYCodec.cpp:133
SSLContext(SSLVersion version=TLSv1)
Definition: SSLContext.cpp:36
virtual void authenticate(bool checkPeerCert, bool checkPeerName, const std::string &peerName=std::string())
Definition: SSLContext.cpp:189
virtual void loadTrustedCertificates(const char *path)
Definition: SSLContext.cpp:320
void setServerECCurve(const std::string &curveName)
Definition: SSLContext.cpp:107
void setSessionCacheContext(const std::string &context)
Definition: SSLContext.cpp:526
void setClientECCurvesList(const std::vector< std::string > &ecCurves)
Definition: SSLContext.cpp:92
const char * string
Definition: Conv.cpp:212
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
Definition: String-inl.h:498
static int passwordCallback(char *password, int size, int, void *data)
Definition: FizzUtil.cpp:19
static int passwordCallback(char *password, int size, int, void *data)
Definition: SSLContext.cpp:567
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
Definition: Format.h:271
virtual void passwordCollector(std::shared_ptr< PasswordCollector > collector)
Definition: SSLContext.cpp:343
std::unique_ptr< X509_VERIFY_PARAM, X509VerifyParamDeleter > X509VerifyParam
void clear() noexcept
Definition: Optional.h:251
std::ostream & operator<<(std::ostream &out, dynamic const &d)
Definition: dynamic-inl.h:1158