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