Fix AsyncSSLSocket handshake error reporting.
[folly.git] / folly / io / async / AsyncSSLSocket.h
1 /*
2  * Copyright 2016 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 <arpa/inet.h>
20 #include <iomanip>
21
22 #include <folly/Optional.h>
23 #include <folly/String.h>
24 #include <folly/io/async/AsyncSocket.h>
25 #include <folly/io/async/SSLContext.h>
26 #include <folly/io/async/AsyncTimeout.h>
27 #include <folly/io/async/OpenSSLPtrTypes.h>
28 #include <folly/io/async/TimeoutManager.h>
29
30 #include <folly/Bits.h>
31 #include <folly/io/IOBuf.h>
32 #include <folly/io/Cursor.h>
33
34 namespace folly {
35
36 class SSLException: public folly::AsyncSocketException {
37  public:
38   SSLException(int sslError,
39                unsigned long errError,
40                int sslOperationReturnValue,
41                int errno_copy);
42 };
43
44 /**
45  * A class for performing asynchronous I/O on an SSL connection.
46  *
47  * AsyncSSLSocket allows users to asynchronously wait for data on an
48  * SSL connection, and to asynchronously send data.
49  *
50  * The APIs for reading and writing are intentionally asymmetric.
51  * Waiting for data to read is a persistent API: a callback is
52  * installed, and is notified whenever new data is available.  It
53  * continues to be notified of new events until it is uninstalled.
54  *
55  * AsyncSSLSocket does not provide read timeout functionality,
56  * because it typically cannot determine when the timeout should be
57  * active.  Generally, a timeout should only be enabled when
58  * processing is blocked waiting on data from the remote endpoint.
59  * For server connections, the timeout should not be active if the
60  * server is currently processing one or more outstanding requests for
61  * this connection.  For client connections, the timeout should not be
62  * active if there are no requests pending on the connection.
63  * Additionally, if a client has multiple pending requests, it will
64  * ususally want a separate timeout for each request, rather than a
65  * single read timeout.
66  *
67  * The write API is fairly intuitive: a user can request to send a
68  * block of data, and a callback will be informed once the entire
69  * block has been transferred to the kernel, or on error.
70  * AsyncSSLSocket does provide a send timeout, since most callers
71  * want to give up if the remote end stops responding and no further
72  * progress can be made sending the data.
73  */
74 class AsyncSSLSocket : public virtual AsyncSocket {
75  public:
76   typedef std::unique_ptr<AsyncSSLSocket, Destructor> UniquePtr;
77   using X509_deleter = folly::static_function_deleter<X509, &X509_free>;
78
79   class HandshakeCB {
80    public:
81     virtual ~HandshakeCB() = default;
82
83     /**
84      * handshakeVer() is invoked during handshaking to give the
85      * application chance to validate it's peer's certificate.
86      *
87      * Note that OpenSSL performs only rudimentary internal
88      * consistency verification checks by itself. Any other validation
89      * like whether or not the certificate was issued by a trusted CA.
90      * The default implementation of this callback mimics what what
91      * OpenSSL does internally if SSL_VERIFY_PEER is set with no
92      * verification callback.
93      *
94      * See the passages on verify_callback in SSL_CTX_set_verify(3)
95      * for more details.
96      */
97     virtual bool handshakeVer(AsyncSSLSocket* /*sock*/,
98                                  bool preverifyOk,
99                                  X509_STORE_CTX* /*ctx*/) noexcept {
100       return preverifyOk;
101     }
102
103     /**
104      * handshakeSuc() is called when a new SSL connection is
105      * established, i.e., after SSL_accept/connect() returns successfully.
106      *
107      * The HandshakeCB will be uninstalled before handshakeSuc()
108      * is called.
109      *
110      * @param sock  SSL socket on which the handshake was initiated
111      */
112     virtual void handshakeSuc(AsyncSSLSocket *sock) noexcept = 0;
113
114     /**
115      * handshakeErr() is called if an error occurs while
116      * establishing the SSL connection.
117      *
118      * The HandshakeCB will be uninstalled before handshakeErr()
119      * is called.
120      *
121      * @param sock  SSL socket on which the handshake was initiated
122      * @param ex  An exception representing the error.
123      */
124     virtual void handshakeErr(
125       AsyncSSLSocket *sock,
126       const AsyncSocketException& ex)
127       noexcept = 0;
128   };
129
130   class HandshakeTimeout : public AsyncTimeout {
131    public:
132     HandshakeTimeout(AsyncSSLSocket* sslSocket, EventBase* eventBase)
133       : AsyncTimeout(eventBase)
134       , sslSocket_(sslSocket) {}
135
136     virtual void timeoutExpired() noexcept {
137       sslSocket_->timeoutExpired();
138     }
139
140    private:
141     AsyncSSLSocket* sslSocket_;
142   };
143
144
145   /**
146    * These are passed to the application via errno, packed in an SSL err which
147    * are outside the valid errno range.  The values are chosen to be unique
148    * against values in ssl.h
149    */
150   enum SSLError {
151     SSL_CLIENT_RENEGOTIATION_ATTEMPT = 900,
152     SSL_INVALID_RENEGOTIATION = 901,
153     SSL_EARLY_WRITE = 902
154   };
155
156   /**
157    * Create a client AsyncSSLSocket
158    */
159   AsyncSSLSocket(const std::shared_ptr<folly::SSLContext> &ctx,
160                  EventBase* evb, bool deferSecurityNegotiation = false);
161
162   /**
163    * Create a server/client AsyncSSLSocket from an already connected
164    * socket file descriptor.
165    *
166    * Note that while AsyncSSLSocket enables TCP_NODELAY for sockets it creates
167    * when connecting, it does not change the socket options when given an
168    * existing file descriptor.  If callers want TCP_NODELAY enabled when using
169    * this version of the constructor, they need to explicitly call
170    * setNoDelay(true) after the constructor returns.
171    *
172    * @param ctx             SSL context for this connection.
173    * @param evb EventBase that will manage this socket.
174    * @param fd  File descriptor to take over (should be a connected socket).
175    * @param server Is socket in server mode?
176    * @param deferSecurityNegotiation
177    *          unencrypted data can be sent before sslConn/Accept
178    */
179   AsyncSSLSocket(const std::shared_ptr<folly::SSLContext>& ctx,
180                  EventBase* evb, int fd,
181                  bool server = true, bool deferSecurityNegotiation = false);
182
183
184   /**
185    * Helper function to create a server/client shared_ptr<AsyncSSLSocket>.
186    */
187   static std::shared_ptr<AsyncSSLSocket> newSocket(
188     const std::shared_ptr<folly::SSLContext>& ctx,
189     EventBase* evb, int fd, bool server=true,
190     bool deferSecurityNegotiation = false) {
191     return std::shared_ptr<AsyncSSLSocket>(
192       new AsyncSSLSocket(ctx, evb, fd, server, deferSecurityNegotiation),
193       Destructor());
194   }
195
196   /**
197    * Helper function to create a client shared_ptr<AsyncSSLSocket>.
198    */
199   static std::shared_ptr<AsyncSSLSocket> newSocket(
200     const std::shared_ptr<folly::SSLContext>& ctx,
201     EventBase* evb, bool deferSecurityNegotiation = false) {
202     return std::shared_ptr<AsyncSSLSocket>(
203       new AsyncSSLSocket(ctx, evb, deferSecurityNegotiation),
204       Destructor());
205   }
206
207
208 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
209   /**
210    * Create a client AsyncSSLSocket with tlsext_servername in
211    * the Client Hello message.
212    */
213   AsyncSSLSocket(const std::shared_ptr<folly::SSLContext> &ctx,
214                   EventBase* evb,
215                  const std::string& serverName,
216                 bool deferSecurityNegotiation = false);
217
218   /**
219    * Create a client AsyncSSLSocket from an already connected
220    * socket file descriptor.
221    *
222    * Note that while AsyncSSLSocket enables TCP_NODELAY for sockets it creates
223    * when connecting, it does not change the socket options when given an
224    * existing file descriptor.  If callers want TCP_NODELAY enabled when using
225    * this version of the constructor, they need to explicitly call
226    * setNoDelay(true) after the constructor returns.
227    *
228    * @param ctx  SSL context for this connection.
229    * @param evb  EventBase that will manage this socket.
230    * @param fd   File descriptor to take over (should be a connected socket).
231    * @param serverName tlsext_hostname that will be sent in ClientHello.
232    */
233   AsyncSSLSocket(const std::shared_ptr<folly::SSLContext>& ctx,
234                   EventBase* evb,
235                   int fd,
236                  const std::string& serverName,
237                 bool deferSecurityNegotiation = false);
238
239   static std::shared_ptr<AsyncSSLSocket> newSocket(
240     const std::shared_ptr<folly::SSLContext>& ctx,
241     EventBase* evb,
242     const std::string& serverName,
243     bool deferSecurityNegotiation = false) {
244     return std::shared_ptr<AsyncSSLSocket>(
245       new AsyncSSLSocket(ctx, evb, serverName, deferSecurityNegotiation),
246       Destructor());
247   }
248 #endif
249
250   /**
251    * TODO: implement support for SSL renegotiation.
252    *
253    * This involves proper handling of the SSL_ERROR_WANT_READ/WRITE
254    * code as a result of SSL_write/read(), instead of returning an
255    * error. In that case, the READ/WRITE event should be registered,
256    * and a flag (e.g., writeBlockedOnRead) should be set to indiciate
257    * the condition. In the next invocation of read/write callback, if
258    * the flag is on, performWrite()/performRead() should be called in
259    * addition to the normal call to performRead()/performWrite(), and
260    * the flag should be reset.
261    */
262
263   // Inherit TAsyncTransport methods from AsyncSocket except the
264   // following.
265   // See the documentation in TAsyncTransport.h
266   // TODO: implement graceful shutdown in close()
267   // TODO: implement detachSSL() that returns the SSL connection
268   virtual void closeNow() override;
269   virtual void shutdownWrite() override;
270   virtual void shutdownWriteNow() override;
271   virtual bool good() const override;
272   virtual bool connecting() const override;
273   virtual std::string getApplicationProtocol() noexcept override;
274
275   virtual std::string getSecurityProtocol() const override { return "TLS"; }
276
277   bool isEorTrackingEnabled() const override;
278   virtual void setEorTracking(bool track) override;
279   virtual size_t getRawBytesWritten() const override;
280   virtual size_t getRawBytesReceived() const override;
281   void enableClientHelloParsing();
282
283   /**
284    * Accept an SSL connection on the socket.
285    *
286    * The callback will be invoked and uninstalled when an SSL
287    * connection has been established on the underlying socket.
288    * The value of verifyPeer determines the client verification method.
289    * By default, its set to use the value in the underlying context
290    *
291    * @param callback callback object to invoke on success/failure
292    * @param timeout timeout for this function in milliseconds, or 0 for no
293    *                timeout
294    * @param verifyPeer  SSLVerifyPeerEnum uses the options specified in the
295    *                context by default, can be set explcitly to override the
296    *                method in the context
297    */
298   virtual void sslAccept(HandshakeCB* callback, uint32_t timeout = 0,
299       const folly::SSLContext::SSLVerifyPeerEnum& verifyPeer =
300             folly::SSLContext::SSLVerifyPeerEnum::USE_CTX);
301
302   /**
303    * Invoke SSL accept following an asynchronous session cache lookup
304    */
305   void restartSSLAccept();
306
307   /**
308    * Connect to the given address, invoking callback when complete or on error
309    *
310    * Note timeout applies to TCP + SSL connection time
311    */
312   void connect(ConnectCallback* callback,
313                const folly::SocketAddress& address,
314                int timeout = 0,
315                const OptionMap &options = emptyOptionMap,
316                const folly::SocketAddress& bindAddr = anyAddress())
317                noexcept override;
318
319   using AsyncSocket::connect;
320
321   /**
322    * Initiate an SSL connection on the socket
323    * The callback will be invoked and uninstalled when an SSL connection
324    * has been establshed on the underlying socket.
325    * The verification option verifyPeer is applied if it's passed explicitly.
326    * If it's not, the options in SSLContext set on the underlying SSLContext
327    * are applied.
328    *
329    * @param callback callback object to invoke on success/failure
330    * @param timeout timeout for this function in milliseconds, or 0 for no
331    *                timeout
332    * @param verifyPeer  SSLVerifyPeerEnum uses the options specified in the
333    *                context by default, can be set explcitly to override the
334    *                method in the context. If verification is turned on sets
335    *                SSL_VERIFY_PEER and invokes
336    *                HandshakeCB::handshakeVer().
337    */
338   virtual void sslConn(HandshakeCB *callback, uint64_t timeout = 0,
339             const folly::SSLContext::SSLVerifyPeerEnum& verifyPeer =
340                   folly::SSLContext::SSLVerifyPeerEnum::USE_CTX);
341
342   enum SSLStateEnum {
343     STATE_UNINIT,
344     STATE_UNENCRYPTED,
345     STATE_ACCEPTING,
346     STATE_CACHE_LOOKUP,
347     STATE_ASYNC_PENDING,
348     STATE_CONNECTING,
349     STATE_ESTABLISHED,
350     STATE_REMOTE_CLOSED, /// remote end closed; we can still write
351     STATE_CLOSING,       ///< close() called, but waiting on writes to complete
352     /// close() called with pending writes, before connect() has completed
353     STATE_CONNECTING_CLOSING,
354     STATE_CLOSED,
355     STATE_ERROR
356   };
357
358   SSLStateEnum getSSLState() const { return sslState_;}
359
360   /**
361    * Get a handle to the negotiated SSL session.  This increments the session
362    * refcount and must be deallocated by the caller.
363    */
364   SSL_SESSION *getSSLSession();
365
366   /**
367    * Set the SSL session to be used during sslConn.  AsyncSSLSocket will
368    * hold a reference to the session until it is destroyed or released by the
369    * underlying SSL structure.
370    *
371    * @param takeOwnership if true, AsyncSSLSocket will assume the caller's
372    *                      reference count to session.
373    */
374   void setSSLSession(SSL_SESSION *session, bool takeOwnership = false);
375
376   /**
377    * Get the name of the protocol selected by the client during
378    * Next Protocol Negotiation (NPN) or Application Layer Protocol Negotiation
379    * (ALPN)
380    *
381    * Throw an exception if openssl does not support NPN
382    *
383    * @param protoName      Name of the protocol (not guaranteed to be
384    *                       null terminated); will be set to nullptr if
385    *                       the client did not negotiate a protocol.
386    *                       Note: the AsyncSSLSocket retains ownership
387    *                       of this string.
388    * @param protoNameLen   Length of the name.
389    * @param protoType      Whether this was an NPN or ALPN negotiation
390    */
391   virtual void getSelectedNextProtocol(
392       const unsigned char** protoName,
393       unsigned* protoLen,
394       SSLContext::NextProtocolType* protoType = nullptr) const;
395
396   /**
397    * Get the name of the protocol selected by the client during
398    * Next Protocol Negotiation (NPN) or Application Layer Protocol Negotiation
399    * (ALPN)
400    *
401    * @param protoName      Name of the protocol (not guaranteed to be
402    *                       null terminated); will be set to nullptr if
403    *                       the client did not negotiate a protocol.
404    *                       Note: the AsyncSSLSocket retains ownership
405    *                       of this string.
406    * @param protoNameLen   Length of the name.
407    * @param protoType      Whether this was an NPN or ALPN negotiation
408    * @return false if openssl does not support NPN
409    */
410   virtual bool getSelectedNextProtocolNoThrow(
411       const unsigned char** protoName,
412       unsigned* protoLen,
413       SSLContext::NextProtocolType* protoType = nullptr) const;
414
415   /**
416    * Determine if the session specified during setSSLSession was reused
417    * or if the server rejected it and issued a new session.
418    */
419   virtual bool getSSLSessionReused() const;
420
421   /**
422    * true if the session was resumed using session ID
423    */
424   bool sessionIDResumed() const { return sessionIDResumed_; }
425
426   void setSessionIDResumed(bool resumed) {
427     sessionIDResumed_ = resumed;
428   }
429
430   /**
431    * Get the negociated cipher name for this SSL connection.
432    * Returns the cipher used or the constant value "NONE" when no SSL session
433    * has been established.
434    */
435   virtual const char* getNegotiatedCipherName() const;
436
437   /**
438    * Get the server name for this SSL connection.
439    * Returns the server name used or the constant value "NONE" when no SSL
440    * session has been established.
441    * If openssl has no SNI support, throw TTransportException.
442    */
443   const char *getSSLServerName() const;
444
445   /**
446    * Get the server name for this SSL connection.
447    * Returns the server name used or the constant value "NONE" when no SSL
448    * session has been established.
449    * If openssl has no SNI support, return "NONE"
450    */
451   const char *getSSLServerNameNoThrow() const;
452
453   /**
454    * Get the SSL version for this connection.
455    * Possible return values are SSL2_VERSION, SSL3_VERSION, TLS1_VERSION,
456    * with hexa representations 0x200, 0x300, 0x301,
457    * or 0 if no SSL session has been established.
458    */
459   int getSSLVersion() const;
460
461   /**
462    * Get the signature algorithm used in the cert that is used for this
463    * connection.
464    */
465   const char *getSSLCertSigAlgName() const;
466
467   /**
468    * Get the certificate size used for this SSL connection.
469    */
470   int getSSLCertSize() const;
471
472   virtual void attachEventBase(EventBase* eventBase) override {
473     AsyncSocket::attachEventBase(eventBase);
474     handshakeTimeout_.attachEventBase(eventBase);
475   }
476
477   virtual void detachEventBase() override {
478     AsyncSocket::detachEventBase();
479     handshakeTimeout_.detachEventBase();
480   }
481
482   virtual bool isDetachable() const override {
483     return AsyncSocket::isDetachable() && !handshakeTimeout_.isScheduled();
484   }
485
486   virtual void attachTimeoutManager(TimeoutManager* manager) {
487     handshakeTimeout_.attachTimeoutManager(manager);
488   }
489
490   virtual void detachTimeoutManager() {
491     handshakeTimeout_.detachTimeoutManager();
492   }
493
494 #if OPENSSL_VERSION_NUMBER >= 0x009080bfL
495   /**
496    * This function will set the SSL context for this socket to the
497    * argument. This should only be used on client SSL Sockets that have
498    * already called detachSSLContext();
499    */
500   void attachSSLContext(const std::shared_ptr<folly::SSLContext>& ctx);
501
502   /**
503    * Detaches the SSL context for this socket.
504    */
505   void detachSSLContext();
506 #endif
507
508 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
509   /**
510    * Switch the SSLContext to continue the SSL handshake.
511    * It can only be used in server mode.
512    */
513   void switchServerSSLContext(
514     const std::shared_ptr<folly::SSLContext>& handshakeCtx);
515
516   /**
517    * Did server recognize/support the tlsext_hostname in Client Hello?
518    * It can only be used in client mode.
519    *
520    * @return true - tlsext_hostname is matched by the server
521    *         false - tlsext_hostname is not matched or
522    *                 is not supported by server
523    */
524   bool isServerNameMatch() const;
525
526   /**
527    * Set the SNI hostname that we'll advertise to the server in the
528    * ClientHello message.
529    */
530   void setServerName(std::string serverName) noexcept;
531 #endif
532
533   void timeoutExpired() noexcept;
534
535   /**
536    * Get the list of supported ciphers sent by the client in the client's
537    * preference order.
538    */
539   void getSSLClientCiphers(std::string& clientCiphers) const {
540     std::stringstream ciphersStream;
541     std::string cipherName;
542
543     if (parseClientHello_ == false
544         || clientHelloInfo_->clientHelloCipherSuites_.empty()) {
545       clientCiphers = "";
546       return;
547     }
548
549     for (auto originalCipherCode : clientHelloInfo_->clientHelloCipherSuites_)
550     {
551       // OpenSSL expects code as a big endian char array
552       auto cipherCode = htons(originalCipherCode);
553
554 #if defined(SSL_OP_NO_TLSv1_2)
555       const SSL_CIPHER* cipher =
556           TLSv1_2_method()->get_cipher_by_char((unsigned char*)&cipherCode);
557 #elif defined(SSL_OP_NO_TLSv1_1)
558       const SSL_CIPHER* cipher =
559           TLSv1_1_method()->get_cipher_by_char((unsigned char*)&cipherCode);
560 #elif defined(SSL_OP_NO_TLSv1)
561       const SSL_CIPHER* cipher =
562           TLSv1_method()->get_cipher_by_char((unsigned char*)&cipherCode);
563 #else
564       const SSL_CIPHER* cipher =
565           SSLv3_method()->get_cipher_by_char((unsigned char*)&cipherCode);
566 #endif
567
568       if (cipher == nullptr) {
569         ciphersStream << std::setfill('0') << std::setw(4) << std::hex
570                       << originalCipherCode << ":";
571       } else {
572         ciphersStream << SSL_CIPHER_get_name(cipher) << ":";
573       }
574     }
575
576     clientCiphers = ciphersStream.str();
577     clientCiphers.erase(clientCiphers.end() - 1);
578   }
579
580   /**
581    * Get the list of compression methods sent by the client in TLS Hello.
582    */
583   std::string getSSLClientComprMethods() const {
584     if (!parseClientHello_) {
585       return "";
586     }
587     return folly::join(":", clientHelloInfo_->clientHelloCompressionMethods_);
588   }
589
590   /**
591    * Get the list of TLS extensions sent by the client in the TLS Hello.
592    */
593   std::string getSSLClientExts() const {
594     if (!parseClientHello_) {
595       return "";
596     }
597     return folly::join(":", clientHelloInfo_->clientHelloExtensions_);
598   }
599
600   std::string getSSLClientSigAlgs() const {
601     if (!parseClientHello_) {
602       return "";
603     }
604
605     std::string sigAlgs;
606     sigAlgs.reserve(clientHelloInfo_->clientHelloSigAlgs_.size() * 4);
607     for (size_t i = 0; i < clientHelloInfo_->clientHelloSigAlgs_.size(); i++) {
608       if (i) {
609         sigAlgs.push_back(':');
610       }
611       sigAlgs.append(folly::to<std::string>(
612           clientHelloInfo_->clientHelloSigAlgs_[i].first));
613       sigAlgs.push_back(',');
614       sigAlgs.append(folly::to<std::string>(
615           clientHelloInfo_->clientHelloSigAlgs_[i].second));
616     }
617
618     return sigAlgs;
619   }
620
621   /**
622    * Get the list of shared ciphers between the server and the client.
623    * Works well for only SSLv2, not so good for SSLv3 or TLSv1.
624    */
625   void getSSLSharedCiphers(std::string& sharedCiphers) const {
626     char ciphersBuffer[1024];
627     ciphersBuffer[0] = '\0';
628     SSL_get_shared_ciphers(ssl_, ciphersBuffer, sizeof(ciphersBuffer) - 1);
629     sharedCiphers = ciphersBuffer;
630   }
631
632   /**
633    * Get the list of ciphers supported by the server in the server's
634    * preference order.
635    */
636   void getSSLServerCiphers(std::string& serverCiphers) const {
637     serverCiphers = SSL_get_cipher_list(ssl_, 0);
638     int i = 1;
639     const char *cipher;
640     while ((cipher = SSL_get_cipher_list(ssl_, i)) != nullptr) {
641       serverCiphers.append(":");
642       serverCiphers.append(cipher);
643       i++;
644     }
645   }
646
647   static int getSSLExDataIndex();
648   static AsyncSSLSocket* getFromSSL(const SSL *ssl);
649   static int eorAwareBioWrite(BIO *b, const char *in, int inl);
650   void resetClientHelloParsing(SSL *ssl);
651   static void clientHelloParsingCallback(int write_p, int version,
652       int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
653   static const char* getSSLServerNameFromSSL(SSL* ssl);
654
655   // http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
656   enum class TLSExtension: uint16_t {
657     SERVER_NAME = 0,
658     MAX_FRAGMENT_LENGTH = 1,
659     CLIENT_CERTIFICATE_URL = 2,
660     TRUSTED_CA_KEYS = 3,
661     TRUNCATED_HMAC = 4,
662     STATUS_REQUEST = 5,
663     USER_MAPPING = 6,
664     CLIENT_AUTHZ = 7,
665     SERVER_AUTHZ = 8,
666     CERT_TYPE = 9,
667     SUPPORTED_GROUPS = 10,
668     EC_POINT_FORMATS = 11,
669     SRP = 12,
670     SIGNATURE_ALGORITHMS = 13,
671     USE_SRTP = 14,
672     HEARTBEAT = 15,
673     APPLICATION_LAYER_PROTOCOL_NEGOTIATION = 16,
674     STATUS_REQUEST_V2 = 17,
675     SIGNED_CERTIFICATE_TIMESTAMP = 18,
676     CLIENT_CERTIFICATE_TYPE = 19,
677     SERVER_CERTIFICATE_TYPE = 20,
678     PADDING = 21,
679     ENCRYPT_THEN_MAC = 22,
680     EXTENDED_MASTER_SECRET = 23,
681     SESSION_TICKET = 35,
682     RENEGOTIATION_INFO = 65281
683   };
684
685   // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18
686   enum class HashAlgorithm: uint8_t {
687     NONE = 0,
688     MD5 = 1,
689     SHA1 = 2,
690     SHA224 = 3,
691     SHA256 = 4,
692     SHA384 = 5,
693     SHA512 = 6
694   };
695
696   // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
697   enum class SignatureAlgorithm: uint8_t {
698     ANONYMOUS = 0,
699     RSA = 1,
700     DSA = 2,
701     ECDSA = 3
702   };
703
704   struct ClientHelloInfo {
705     folly::IOBufQueue clientHelloBuf_;
706     uint8_t clientHelloMajorVersion_;
707     uint8_t clientHelloMinorVersion_;
708     std::vector<uint16_t> clientHelloCipherSuites_;
709     std::vector<uint8_t> clientHelloCompressionMethods_;
710     std::vector<TLSExtension> clientHelloExtensions_;
711     std::vector<
712       std::pair<HashAlgorithm, SignatureAlgorithm>> clientHelloSigAlgs_;
713   };
714
715   // For unit-tests
716   ClientHelloInfo* getClientHelloInfo() const {
717     return clientHelloInfo_.get();
718   }
719
720   /**
721    * Returns the time taken to complete a handshake.
722    */
723   virtual std::chrono::nanoseconds getHandshakeTime() const {
724     return handshakeEndTime_ - handshakeStartTime_;
725   }
726
727   void setMinWriteSize(size_t minWriteSize) {
728     minWriteSize_ = minWriteSize;
729   }
730
731   size_t getMinWriteSize() const {
732     return minWriteSize_;
733   }
734
735   void setReadCB(ReadCallback* callback) override;
736
737   /**
738    * Returns the peer certificate, or nullptr if no peer certificate received.
739    */
740   virtual X509_UniquePtr getPeerCert() const override {
741     if (!ssl_) {
742       return nullptr;
743     }
744
745     X509* cert = SSL_get_peer_certificate(ssl_);
746     return X509_UniquePtr(cert);
747   }
748
749   /**
750    * Force AsyncSSLSocket object to cache local and peer socket addresses.
751    * If called with "true" before connect() this function forces full local
752    * and remote socket addresses to be cached in the socket object and available
753    * through getLocalAddress()/getPeerAddress() methods even after the socket is
754    * closed.
755    */
756   void forceCacheAddrOnFailure(bool force) { cacheAddrOnFailure_ = force; }
757
758  private:
759
760   void init();
761
762  protected:
763
764   /**
765    * Protected destructor.
766    *
767    * Users of AsyncSSLSocket must never delete it directly.  Instead, invoke
768    * destroy() instead.  (See the documentation in DelayedDestruction.h for
769    * more details.)
770    */
771   ~AsyncSSLSocket();
772
773   // Inherit event notification methods from AsyncSocket except
774   // the following.
775   void prepareReadBuffer(void** buf, size_t* buflen) noexcept override;
776   void handleRead() noexcept override;
777   void handleWrite() noexcept override;
778   void handleAccept() noexcept;
779   void handleConnect() noexcept override;
780
781   void invalidState(HandshakeCB* callback);
782   bool willBlock(int ret,
783                  int* sslErrorOut,
784                  unsigned long* errErrorOut) noexcept;
785
786   virtual void checkForImmediateRead() noexcept override;
787   // AsyncSocket calls this at the wrong time for SSL
788   void handleInitialReadWrite() noexcept override {}
789
790   int interpretSSLError(int rc, int error);
791   ssize_t performRead(void** buf, size_t* buflen, size_t* offset) override;
792   ssize_t performWrite(const iovec* vec, uint32_t count, WriteFlags flags,
793                        uint32_t* countWritten, uint32_t* partialWritten)
794     override;
795
796   ssize_t performWriteIovec(const iovec* vec, uint32_t count,
797                             WriteFlags flags, uint32_t* countWritten,
798                             uint32_t* partialWritten);
799
800   // This virtual wrapper around SSL_write exists solely for testing/mockability
801   virtual int sslWriteImpl(SSL *ssl, const void *buf, int n) {
802     return SSL_write(ssl, buf, n);
803   }
804
805   /**
806    * Apply verification options passed to sslConn/sslAccept or those set
807    * in the underlying SSLContext object.
808    *
809    * @param ssl pointer to the SSL object on which verification options will be
810    * applied. If verifyPeer_ was explicitly set either via sslConn/sslAccept,
811    * those options override the settings in the underlying SSLContext.
812    */
813   void applyVerificationOptions(SSL * ssl);
814
815   /**
816    * A SSL_write wrapper that understand EOR
817    *
818    * @param ssl: SSL* object
819    * @param buf: Buffer to be written
820    * @param n:   Number of bytes to be written
821    * @param eor: Does the last byte (buf[n-1]) have the app-last-byte?
822    * @return:    The number of app bytes successfully written to the socket
823    */
824   int eorAwareSSLWrite(SSL *ssl, const void *buf, int n, bool eor);
825
826   // Inherit error handling methods from AsyncSocket, plus the following.
827   void failHandshake(const char* fn, const AsyncSocketException& ex);
828
829   void invokeHandshakeErr(const AsyncSocketException& ex);
830   void invokeHandshakeCB();
831
832   void cacheLocalPeerAddr();
833
834   static void sslInfoCallback(const SSL *ssl, int type, int val);
835
836   // SSL related members.
837   bool server_{false};
838   // Used to prevent client-initiated renegotiation.  Note that AsyncSSLSocket
839   // doesn't fully support renegotiation, so we could just fail all attempts
840   // to enforce this.  Once it is supported, we should make it an option
841   // to disable client-initiated renegotiation.
842   bool handshakeComplete_{false};
843   bool renegotiateAttempted_{false};
844   SSLStateEnum sslState_{STATE_UNINIT};
845   std::shared_ptr<folly::SSLContext> ctx_;
846   // Callback for SSL_accept() or SSL_connect()
847   HandshakeCB* handshakeCallback_{nullptr};
848   SSL* ssl_{nullptr};
849   SSL_SESSION *sslSession_{nullptr};
850   HandshakeTimeout handshakeTimeout_;
851   // whether the SSL session was resumed using session ID or not
852   bool sessionIDResumed_{false};
853
854   // The app byte num that we are tracking for the MSG_EOR
855   // Only one app EOR byte can be tracked.
856   size_t appEorByteNo_{0};
857
858   // Try to avoid calling SSL_write() for buffers smaller than this.
859   // It doesn't take effect when it is 0.
860   size_t minWriteSize_{1500};
861
862   // When openssl is about to sendmsg() across the minEorRawBytesNo_,
863   // it will pass MSG_EOR to sendmsg().
864   size_t minEorRawByteNo_{0};
865 #if OPENSSL_VERSION_NUMBER >= 0x1000105fL && !defined(OPENSSL_NO_TLSEXT)
866   std::shared_ptr<folly::SSLContext> handshakeCtx_;
867   std::string tlsextHostname_;
868 #endif
869   folly::SSLContext::SSLVerifyPeerEnum
870     verifyPeer_{folly::SSLContext::SSLVerifyPeerEnum::USE_CTX};
871
872   // Callback for SSL_CTX_set_verify()
873   static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx);
874
875   bool parseClientHello_{false};
876   bool cacheAddrOnFailure_{false};
877   std::unique_ptr<ClientHelloInfo> clientHelloInfo_;
878
879   // Time taken to complete the ssl handshake.
880   std::chrono::steady_clock::time_point handshakeStartTime_;
881   std::chrono::steady_clock::time_point handshakeEndTime_;
882 };
883
884 } // namespace