SSLContext.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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. #pragma once
  17. #include <list>
  18. #include <map>
  19. #include <memory>
  20. #include <mutex>
  21. #include <random>
  22. #include <string>
  23. #include <vector>
  24. #include <glog/logging.h>
  25. #ifndef FOLLY_NO_CONFIG
  26. #include <folly/folly-config.h>
  27. #endif
  28. #include <folly/Function.h>
  29. #include <folly/Portability.h>
  30. #include <folly/Range.h>
  31. #include <folly/String.h>
  32. #include <folly/io/async/ssl/OpenSSLUtils.h>
  33. #include <folly/portability/OpenSSL.h>
  34. #include <folly/ssl/OpenSSLLockTypes.h>
  35. #include <folly/ssl/OpenSSLPtrTypes.h>
  36. namespace folly {
  37. /**
  38. * Override the default password collector.
  39. */
  40. class PasswordCollector {
  41. public:
  42. virtual ~PasswordCollector() = default;
  43. /**
  44. * Interface for customizing how to collect private key password.
  45. *
  46. * By default, OpenSSL prints a prompt on screen and request for password
  47. * while loading private key. To implement a custom password collector,
  48. * implement this interface and register it with SSLContext.
  49. *
  50. * @param password Pass collected password back to OpenSSL
  51. * @param size Maximum length of password including nullptr character
  52. */
  53. virtual void getPassword(std::string& password, int size) const = 0;
  54. /**
  55. * Return a description of this collector for logging purposes
  56. */
  57. virtual std::string describe() const = 0;
  58. };
  59. /**
  60. * Run SSL_accept via a runner
  61. */
  62. class SSLAcceptRunner {
  63. public:
  64. virtual ~SSLAcceptRunner() = default;
  65. /**
  66. * This is expected to run the first function and provide its return
  67. * value to the second function. This can be used to run the SSL_accept
  68. * in different contexts.
  69. */
  70. virtual void run(Function<int()> acceptFunc, Function<void(int)> finallyFunc)
  71. const {
  72. finallyFunc(acceptFunc());
  73. }
  74. };
  75. /**
  76. * Wrap OpenSSL SSL_CTX into a class.
  77. */
  78. class SSLContext {
  79. public:
  80. enum SSLVersion {
  81. SSLv2,
  82. SSLv3,
  83. TLSv1, // support TLS 1.0+
  84. TLSv1_2, // support for only TLS 1.2+
  85. };
  86. /**
  87. * Defines the way that peers are verified.
  88. **/
  89. enum SSLVerifyPeerEnum {
  90. // Used by AsyncSSLSocket to delegate to the SSLContext's setting
  91. USE_CTX,
  92. // For server side - request a client certificate and verify the
  93. // certificate if it is sent. Does not fail if the client does not present
  94. // a certificate.
  95. // For client side - validates the server certificate or fails.
  96. VERIFY,
  97. // For server side - same as VERIFY but will fail if no certificate
  98. // is sent.
  99. // For client side - same as VERIFY.
  100. VERIFY_REQ_CLIENT_CERT,
  101. // No verification is done for both server and client side.
  102. NO_VERIFY
  103. };
  104. struct NextProtocolsItem {
  105. NextProtocolsItem(int wt, const std::list<std::string>& ptcls)
  106. : weight(wt), protocols(ptcls) {}
  107. int weight;
  108. std::list<std::string> protocols;
  109. };
  110. // Function that selects a client protocol given the server's list
  111. using ClientProtocolFilterCallback = bool (*)(
  112. unsigned char**,
  113. unsigned int*,
  114. const unsigned char*,
  115. unsigned int);
  116. /**
  117. * Convenience function to call getErrors() with the current errno value.
  118. *
  119. * Make sure that you only call this when there was no intervening operation
  120. * since the last OpenSSL error that may have changed the current errno value.
  121. */
  122. static std::string getErrors() {
  123. return getErrors(errno);
  124. }
  125. /**
  126. * Constructor.
  127. *
  128. * @param version The lowest or oldest SSL version to support.
  129. */
  130. explicit SSLContext(SSLVersion version = TLSv1);
  131. virtual ~SSLContext();
  132. /**
  133. * Set default ciphers to be used in SSL handshake process.
  134. *
  135. * @param ciphers A list of ciphers to use for TLSv1.0
  136. */
  137. virtual void ciphers(const std::string& ciphers);
  138. /**
  139. * Low-level method that attempts to set the provided ciphers on the
  140. * SSL_CTX object, and throws if something goes wrong.
  141. */
  142. virtual void setCiphersOrThrow(const std::string& ciphers);
  143. /**
  144. * Set default ciphers to be used in SSL handshake process.
  145. */
  146. template <typename Iterator>
  147. void setCipherList(Iterator ibegin, Iterator iend) {
  148. if (ibegin != iend) {
  149. std::string opensslCipherList;
  150. folly::join(":", ibegin, iend, opensslCipherList);
  151. setCiphersOrThrow(opensslCipherList);
  152. }
  153. }
  154. template <typename Container>
  155. void setCipherList(const Container& cipherList) {
  156. using namespace std;
  157. setCipherList(begin(cipherList), end(cipherList));
  158. }
  159. template <typename Value>
  160. void setCipherList(const std::initializer_list<Value>& cipherList) {
  161. setCipherList(cipherList.begin(), cipherList.end());
  162. }
  163. /**
  164. * Sets the signature algorithms to be used during SSL negotiation
  165. * for TLS1.2+.
  166. */
  167. template <typename Iterator>
  168. void setSignatureAlgorithms(Iterator ibegin, Iterator iend) {
  169. if (ibegin != iend) {
  170. #if OPENSSL_VERSION_NUMBER >= 0x1000200fL
  171. std::string opensslSigAlgsList;
  172. join(":", ibegin, iend, opensslSigAlgsList);
  173. if (!SSL_CTX_set1_sigalgs_list(ctx_, opensslSigAlgsList.c_str())) {
  174. throw std::runtime_error("SSL_CTX_set1_sigalgs_list " + getErrors());
  175. }
  176. #endif
  177. }
  178. }
  179. template <typename Container>
  180. void setSignatureAlgorithms(const Container& sigalgs) {
  181. using namespace std;
  182. setSignatureAlgorithms(begin(sigalgs), end(sigalgs));
  183. }
  184. template <typename Value>
  185. void setSignatureAlgorithms(const std::initializer_list<Value>& sigalgs) {
  186. setSignatureAlgorithms(sigalgs.begin(), sigalgs.end());
  187. }
  188. /**
  189. * Sets the list of EC curves supported by the client.
  190. *
  191. * @param ecCurves A list of ec curves, eg: P-256
  192. */
  193. void setClientECCurvesList(const std::vector<std::string>& ecCurves);
  194. /**
  195. * Method to add support for a specific elliptic curve encryption algorithm.
  196. *
  197. * @param curveName: The name of the ec curve to support, eg: prime256v1.
  198. */
  199. void setServerECCurve(const std::string& curveName);
  200. /**
  201. * Sets an x509 verification param on the context.
  202. */
  203. void setX509VerifyParam(const ssl::X509VerifyParam& x509VerifyParam);
  204. /**
  205. * Method to set verification option in the context object.
  206. *
  207. * @param verifyPeer SSLVerifyPeerEnum indicating the verification
  208. * method to use.
  209. */
  210. virtual void setVerificationOption(const SSLVerifyPeerEnum& verifyPeer);
  211. /**
  212. * Method to check if peer verfication is set.
  213. *
  214. * @return true if peer verification is required.
  215. *
  216. */
  217. virtual bool needsPeerVerification() {
  218. return (
  219. verifyPeer_ == SSLVerifyPeerEnum::VERIFY ||
  220. verifyPeer_ == SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT);
  221. }
  222. /**
  223. * Method to fetch Verification mode for a SSLVerifyPeerEnum.
  224. * verifyPeer cannot be SSLVerifyPeerEnum::USE_CTX since there is no
  225. * context.
  226. *
  227. * @param verifyPeer SSLVerifyPeerEnum for which the flags need to
  228. * to be returned
  229. *
  230. * @return mode flags that can be used with SSL_set_verify
  231. */
  232. static int getVerificationMode(const SSLVerifyPeerEnum& verifyPeer);
  233. /**
  234. * Method to fetch Verification mode determined by the options
  235. * set using setVerificationOption.
  236. *
  237. * @return mode flags that can be used with SSL_set_verify
  238. */
  239. virtual int getVerificationMode();
  240. /**
  241. * Enable/Disable authentication. Peer name validation can only be done
  242. * if checkPeerCert is true.
  243. *
  244. * @param checkPeerCert If true, require peer to present valid certificate
  245. * @param checkPeerName If true, validate that the certificate common name
  246. * or alternate name(s) of peer matches the hostname
  247. * used to connect.
  248. * @param peerName If non-empty, validate that the certificate common
  249. * name of peer matches the given string (altername
  250. * name(s) are not used in this case).
  251. */
  252. virtual void authenticate(
  253. bool checkPeerCert,
  254. bool checkPeerName,
  255. const std::string& peerName = std::string());
  256. /**
  257. * Load server certificate.
  258. *
  259. * @param path Path to the certificate file
  260. * @param format Certificate file format
  261. */
  262. virtual void loadCertificate(const char* path, const char* format = "PEM");
  263. /**
  264. * Load server certificate from memory.
  265. *
  266. * @param cert A PEM formatted certificate
  267. */
  268. virtual void loadCertificateFromBufferPEM(folly::StringPiece cert);
  269. /**
  270. * Load private key.
  271. *
  272. * @param path Path to the private key file
  273. * @param format Private key file format
  274. */
  275. virtual void loadPrivateKey(const char* path, const char* format = "PEM");
  276. /**
  277. * Load private key from memory.
  278. *
  279. * @param pkey A PEM formatted key
  280. */
  281. virtual void loadPrivateKeyFromBufferPEM(folly::StringPiece pkey);
  282. /**
  283. * Load cert and key from PEM buffers. Guaranteed to throw if cert and
  284. * private key mismatch so no need to call isCertKeyPairValid.
  285. *
  286. * @param cert A PEM formatted certificate
  287. * @param pkey A PEM formatted key
  288. */
  289. virtual void loadCertKeyPairFromBufferPEM(
  290. folly::StringPiece cert,
  291. folly::StringPiece pkey);
  292. /**
  293. * Load cert and key from files. Guaranteed to throw if cert and key mismatch.
  294. * Equivalent to calling loadCertificate() and loadPrivateKey().
  295. *
  296. * @param certPath Path to the certificate file
  297. * @param keyPath Path to the private key file
  298. * @param certFormat Certificate file format
  299. * @param keyFormat Private key file format
  300. */
  301. virtual void loadCertKeyPairFromFiles(
  302. const char* certPath,
  303. const char* keyPath,
  304. const char* certFormat = "PEM",
  305. const char* keyFormat = "PEM");
  306. /**
  307. * Call after both cert and key are loaded to check if cert matches key.
  308. * Must call if private key is loaded before loading the cert.
  309. * No need to call if cert is loaded first before private key.
  310. * @return true if matches, or false if mismatch.
  311. */
  312. virtual bool isCertKeyPairValid() const;
  313. /**
  314. * Load trusted certificates from specified file.
  315. *
  316. * @param path Path to trusted certificate file
  317. */
  318. virtual void loadTrustedCertificates(const char* path);
  319. /**
  320. * Load trusted certificates from specified X509 certificate store.
  321. *
  322. * @param store X509 certificate store.
  323. */
  324. virtual void loadTrustedCertificates(X509_STORE* store);
  325. /**
  326. * Load a client CA list for validating clients
  327. */
  328. virtual void loadClientCAList(const char* path);
  329. /**
  330. * Override default OpenSSL password collector.
  331. *
  332. * @param collector Instance of user defined password collector
  333. */
  334. virtual void passwordCollector(std::shared_ptr<PasswordCollector> collector);
  335. /**
  336. * Obtain password collector.
  337. *
  338. * @return User defined password collector
  339. */
  340. virtual std::shared_ptr<PasswordCollector> passwordCollector() {
  341. return collector_;
  342. }
  343. #if FOLLY_OPENSSL_HAS_SNI
  344. /**
  345. * Provide SNI support
  346. */
  347. enum ServerNameCallbackResult {
  348. SERVER_NAME_FOUND,
  349. SERVER_NAME_NOT_FOUND,
  350. SERVER_NAME_NOT_FOUND_ALERT_FATAL,
  351. };
  352. /**
  353. * Callback function from openssl to give the application a
  354. * chance to check the tlsext_hostname just right after parsing
  355. * the Client Hello or Server Hello message.
  356. *
  357. * It is for the server to switch the SSL to another SSL_CTX
  358. * to continue the handshake. (i.e. Server Name Indication, SNI, in RFC6066).
  359. *
  360. * If the ServerNameCallback returns:
  361. * SERVER_NAME_FOUND:
  362. * server: Send a tlsext_hostname in the Server Hello
  363. * client: No-effect
  364. * SERVER_NAME_NOT_FOUND:
  365. * server: Does not send a tlsext_hostname in Server Hello
  366. * and continue the handshake.
  367. * client: No-effect
  368. * SERVER_NAME_NOT_FOUND_ALERT_FATAL:
  369. * server and client: Send fatal TLS1_AD_UNRECOGNIZED_NAME alert to
  370. * the peer.
  371. *
  372. * Quote from RFC 6066:
  373. * "...
  374. * If the server understood the ClientHello extension but
  375. * does not recognize the server name, the server SHOULD take one of two
  376. * actions: either abort the handshake by sending a fatal-level
  377. * unrecognized_name(112) alert or continue the handshake. It is NOT
  378. * RECOMMENDED to send a warning-level unrecognized_name(112) alert,
  379. * because the client's behavior in response to warning-level alerts is
  380. * unpredictable.
  381. * ..."
  382. */
  383. /**
  384. * Set the ServerNameCallback
  385. */
  386. typedef std::function<ServerNameCallbackResult(SSL* ssl)> ServerNameCallback;
  387. virtual void setServerNameCallback(const ServerNameCallback& cb);
  388. /**
  389. * Generic callbacks that are run after we get the Client Hello (right
  390. * before we run the ServerNameCallback)
  391. */
  392. typedef std::function<void(SSL* ssl)> ClientHelloCallback;
  393. virtual void addClientHelloCallback(const ClientHelloCallback& cb);
  394. #endif // FOLLY_OPENSSL_HAS_SNI
  395. /**
  396. * Create an SSL object from this context.
  397. */
  398. SSL* createSSL() const;
  399. /**
  400. * Sets the namespace to use for sessions created from this context.
  401. */
  402. void setSessionCacheContext(const std::string& context);
  403. /**
  404. * Set the options on the SSL_CTX object.
  405. */
  406. void setOptions(long options);
  407. #if FOLLY_OPENSSL_HAS_ALPN
  408. /**
  409. * Set the list of protocols that this SSL context supports. In client
  410. * mode, this is the list of protocols that will be advertised for Application
  411. * Layer Protocol Negotiation (ALPN). In server mode, the first protocol
  412. * advertised by the client that is also on this list is chosen.
  413. * Invoking this function with a list of length zero causes ALPN to be
  414. * disabled.
  415. *
  416. * @param protocols List of protocol names. This method makes a copy,
  417. * so the caller needn't keep the list in scope after
  418. * the call completes. The list must have at least
  419. * one element to enable ALPN. Each element must have
  420. * a string length < 256.
  421. * @return true if ALPN has been activated. False if ALPN is disabled.
  422. */
  423. bool setAdvertisedNextProtocols(const std::list<std::string>& protocols);
  424. /**
  425. * Set weighted list of lists of protocols that this SSL context supports.
  426. * In server mode, each element of the list contains a list of protocols that
  427. * could be advertised for Application Layer Protocol Negotiation (ALPN).
  428. * The list of protocols that will be advertised to a client is selected
  429. * randomly, based on weights of elements. Client mode doesn't support
  430. * randomized ALPN, so this list should contain only 1 element. The first
  431. * protocol advertised by the client that is also on the list of protocols
  432. * of this element is chosen. Invoking this function with a list of length
  433. * zero causes ALPN to be disabled.
  434. *
  435. * @param items List of NextProtocolsItems, Each item contains a list of
  436. * protocol names and weight. After the call of this fucntion
  437. * each non-empty list of protocols will be advertised with
  438. * probability weight/sum_of_weights. This method makes a copy,
  439. * so the caller needn't keep the list in scope after the call
  440. * completes. The list must have at least one element with
  441. * non-zero weight and non-empty protocols list to enable NPN.
  442. * Each name of the protocol must have a string length < 256.
  443. * @return true if ALPN has been activated. False if ALPN is disabled.
  444. */
  445. bool setRandomizedAdvertisedNextProtocols(
  446. const std::list<NextProtocolsItem>& items);
  447. /**
  448. * Disables ALPN on this SSL context.
  449. */
  450. void unsetNextProtocols();
  451. void deleteNextProtocolsStrings();
  452. #endif // FOLLY_OPENSSL_HAS_ALPN
  453. /**
  454. * Gets the underlying SSL_CTX for advanced usage
  455. */
  456. SSL_CTX* getSSLCtx() const {
  457. return ctx_;
  458. }
  459. /**
  460. * Examine OpenSSL's error stack, and return a string description of the
  461. * errors.
  462. *
  463. * This operation removes the errors from OpenSSL's error stack.
  464. */
  465. static std::string getErrors(int errnoCopy);
  466. bool checkPeerName() {
  467. return checkPeerName_;
  468. }
  469. std::string peerFixedName() {
  470. return peerFixedName_;
  471. }
  472. #if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
  473. /**
  474. * Enable TLS false start, saving a roundtrip for full handshakes. Will only
  475. * be used if the server uses NPN or ALPN, and a strong forward-secure cipher
  476. * is negotiated.
  477. */
  478. void enableFalseStart();
  479. #endif
  480. /**
  481. * Sets the runner used for SSL_accept. If none is given, the accept will be
  482. * done directly.
  483. */
  484. void sslAcceptRunner(std::unique_ptr<SSLAcceptRunner> runner) {
  485. if (nullptr == runner) {
  486. LOG(ERROR) << "Ignore invalid runner";
  487. return;
  488. }
  489. sslAcceptRunner_ = std::move(runner);
  490. }
  491. const SSLAcceptRunner* sslAcceptRunner() {
  492. return sslAcceptRunner_.get();
  493. }
  494. /**
  495. * Helper to match a hostname versus a pattern.
  496. */
  497. static bool matchName(const char* host, const char* pattern, int size);
  498. [[deprecated("Use folly::ssl::init")]] static void initializeOpenSSL();
  499. protected:
  500. SSL_CTX* ctx_;
  501. private:
  502. SSLVerifyPeerEnum verifyPeer_{SSLVerifyPeerEnum::NO_VERIFY};
  503. bool checkPeerName_;
  504. std::string peerFixedName_;
  505. std::shared_ptr<PasswordCollector> collector_;
  506. #if FOLLY_OPENSSL_HAS_SNI
  507. ServerNameCallback serverNameCb_;
  508. std::vector<ClientHelloCallback> clientHelloCbs_;
  509. #endif
  510. ClientProtocolFilterCallback clientProtoFilter_{nullptr};
  511. static bool initialized_;
  512. std::unique_ptr<SSLAcceptRunner> sslAcceptRunner_;
  513. #if FOLLY_OPENSSL_HAS_ALPN
  514. struct AdvertisedNextProtocolsItem {
  515. unsigned char* protocols;
  516. unsigned length;
  517. };
  518. /**
  519. * Wire-format list of advertised protocols for use in NPN.
  520. */
  521. std::vector<AdvertisedNextProtocolsItem> advertisedNextProtocols_;
  522. std::vector<int> advertisedNextProtocolWeights_;
  523. std::discrete_distribution<int> nextProtocolDistribution_;
  524. static int advertisedNextProtocolCallback(
  525. SSL* ssl,
  526. const unsigned char** out,
  527. unsigned int* outlen,
  528. void* data);
  529. static int alpnSelectCallback(
  530. SSL* ssl,
  531. const unsigned char** out,
  532. unsigned char* outlen,
  533. const unsigned char* in,
  534. unsigned int inlen,
  535. void* data);
  536. size_t pickNextProtocols();
  537. #endif // FOLLY_OPENSSL_HAS_ALPN
  538. static int passwordCallback(char* password, int size, int, void* data);
  539. #if FOLLY_OPENSSL_HAS_SNI
  540. /**
  541. * The function that will be called directly from openssl
  542. * in order for the application to get the tlsext_hostname just after
  543. * parsing the Client Hello or Server Hello message. It will then call
  544. * the serverNameCb_ function object. Hence, it is sort of a
  545. * wrapper/proxy between serverNameCb_ and openssl.
  546. *
  547. * The openssl's primary intention is for SNI support, but we also use it
  548. * generically for performing logic after the Client Hello comes in.
  549. */
  550. static int baseServerNameOpenSSLCallback(
  551. SSL* ssl,
  552. int* al /* alert (return value) */,
  553. void* data);
  554. #endif
  555. std::string providedCiphersString_;
  556. };
  557. typedef std::shared_ptr<SSLContext> SSLContextPtr;
  558. std::ostream& operator<<(
  559. std::ostream& os,
  560. const folly::PasswordCollector& collector);
  561. } // namespace folly