Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
      6 #define NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
      7 #pragma once
      8 
      9 #include <certt.h>
     10 #include <keyt.h>
     11 #include <nspr.h>
     12 #include <nss.h>
     13 
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/synchronization/lock.h"
     19 #include "base/threading/platform_thread.h"
     20 #include "base/time.h"
     21 #include "base/timer.h"
     22 #include "net/base/cert_verify_result.h"
     23 #include "net/base/completion_callback.h"
     24 #include "net/base/host_port_pair.h"
     25 #include "net/base/net_log.h"
     26 #include "net/base/nss_memio.h"
     27 #include "net/base/ssl_config_service.h"
     28 #include "net/base/x509_certificate.h"
     29 #include "net/socket/ssl_client_socket.h"
     30 
     31 namespace net {
     32 
     33 class BoundNetLog;
     34 class CertVerifier;
     35 class ClientSocketHandle;
     36 class DnsCertProvenanceChecker;
     37 class SingleRequestCertVerifier;
     38 class SSLHostInfo;
     39 class X509Certificate;
     40 
     41 // An SSL client socket implemented with Mozilla NSS.
     42 class SSLClientSocketNSS : public SSLClientSocket {
     43  public:
     44   // Takes ownership of the |transport_socket|, which must already be connected.
     45   // The hostname specified in |host_and_port| will be compared with the name(s)
     46   // in the server's certificate during the SSL handshake.  If SSL client
     47   // authentication is requested, the host_and_port field of SSLCertRequestInfo
     48   // will be populated with |host_and_port|.  |ssl_config| specifies
     49   // the SSL settings.
     50   SSLClientSocketNSS(ClientSocketHandle* transport_socket,
     51                      const HostPortPair& host_and_port,
     52                      const SSLConfig& ssl_config,
     53                      SSLHostInfo* ssl_host_info,
     54                      CertVerifier* cert_verifier,
     55                      DnsCertProvenanceChecker* dnsrr_resolver);
     56   ~SSLClientSocketNSS();
     57 
     58   // For tests
     59   static void ClearSessionCache();
     60 
     61   // SSLClientSocket methods:
     62   virtual void GetSSLInfo(SSLInfo* ssl_info);
     63   virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
     64   virtual NextProtoStatus GetNextProto(std::string* proto);
     65   virtual void UseDNSSEC(DNSSECProvider* provider);
     66 
     67   // ClientSocket methods:
     68   virtual int Connect(CompletionCallback* callback
     69 #ifdef ANDROID
     70                       , bool wait_for_connect
     71 #endif
     72                      );
     73   virtual void Disconnect();
     74   virtual bool IsConnected() const;
     75   virtual bool IsConnectedAndIdle() const;
     76   virtual int GetPeerAddress(AddressList* address) const;
     77   virtual int GetLocalAddress(IPEndPoint* address) const;
     78   virtual const BoundNetLog& NetLog() const;
     79   virtual void SetSubresourceSpeculation();
     80   virtual void SetOmniboxSpeculation();
     81   virtual bool WasEverUsed() const;
     82   virtual bool UsingTCPFastOpen() const;
     83 
     84   // Socket methods:
     85   virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
     86   virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
     87   virtual bool SetReceiveBufferSize(int32 size);
     88   virtual bool SetSendBufferSize(int32 size);
     89 
     90  private:
     91   enum State {
     92     STATE_NONE,
     93     STATE_HANDSHAKE,
     94     STATE_VERIFY_DNSSEC,
     95     STATE_VERIFY_DNSSEC_COMPLETE,
     96     STATE_VERIFY_CERT,
     97     STATE_VERIFY_CERT_COMPLETE,
     98   };
     99 
    100   int Init();
    101 
    102   // Initializes NSS SSL options.  Returns a net error code.
    103   int InitializeSSLOptions();
    104 
    105   // Initializes the socket peer name in SSL.  Returns a net error code.
    106   int InitializeSSLPeerName();
    107 
    108 #if defined(OS_MACOSX) || defined(OS_WIN)
    109   // Creates an OS certificate from a DER-encoded certificate.
    110   static X509Certificate::OSCertHandle CreateOSCert(const SECItem& der_cert);
    111 #endif
    112   X509Certificate* UpdateServerCert();
    113   void UpdateConnectionStatus();
    114   void DoReadCallback(int result);
    115   void DoWriteCallback(int result);
    116   void DoConnectCallback(int result);
    117   void OnHandshakeIOComplete(int result);
    118   void OnSendComplete(int result);
    119   void OnRecvComplete(int result);
    120 
    121   int DoHandshakeLoop(int last_io_result);
    122   int DoReadLoop(int result);
    123   int DoWriteLoop(int result);
    124 
    125   int DoHandshake();
    126 
    127   int DoVerifyDNSSEC(int result);
    128   int DoVerifyDNSSECComplete(int result);
    129   int DoVerifyCert(int result);
    130   int DoVerifyCertComplete(int result);
    131   int DoPayloadRead();
    132   int DoPayloadWrite();
    133   void LogConnectionTypeMetrics() const;
    134   void SaveSSLHostInfo();
    135   void UncorkAfterTimeout();
    136 
    137   bool DoTransportIO();
    138   int BufferSend(void);
    139   void BufferSendComplete(int result);
    140   int BufferRecv(void);
    141   void BufferRecvComplete(int result);
    142 
    143   // Handles an NSS error generated while handshaking or performing IO.
    144   // Returns a network error code mapped from the original NSS error.
    145   int HandleNSSError(PRErrorCode error, bool handshake_error);
    146 
    147   // NSS calls this when checking certificates. We pass 'this' as the first
    148   // argument.
    149   static SECStatus OwnAuthCertHandler(void* arg, PRFileDesc* socket,
    150                                       PRBool checksig, PRBool is_server);
    151   // NSS calls this when client authentication is requested.
    152 #if defined(NSS_PLATFORM_CLIENT_AUTH)
    153   static SECStatus PlatformClientAuthHandler(void* arg,
    154                                              PRFileDesc* socket,
    155                                              CERTDistNames* ca_names,
    156                                              CERTCertList** result_certs,
    157                                              void** result_private_key);
    158 #else
    159   static SECStatus ClientAuthHandler(void* arg,
    160                                      PRFileDesc* socket,
    161                                      CERTDistNames* ca_names,
    162                                      CERTCertificate** result_certificate,
    163                                      SECKEYPrivateKey** result_private_key);
    164 #endif
    165   // NSS calls this when handshake is completed.  We pass 'this' as the second
    166   // argument.
    167   static void HandshakeCallback(PRFileDesc* socket, void* arg);
    168 
    169   // The following methods are for debugging bug 65948. Will remove this code
    170   // after fixing bug 65948.
    171   void EnsureThreadIdAssigned() const;
    172   bool CalledOnValidThread() const;
    173 
    174   CompletionCallbackImpl<SSLClientSocketNSS> buffer_send_callback_;
    175   CompletionCallbackImpl<SSLClientSocketNSS> buffer_recv_callback_;
    176   bool transport_send_busy_;
    177   bool transport_recv_busy_;
    178   // corked_ is true if we are currently suspending writes to the network. This
    179   // is named after the similar kernel flag, TCP_CORK.
    180   bool corked_;
    181   // uncork_timer_ is used to limit the amount of time that we'll delay the
    182   // Finished message while waiting for a Write.
    183   base::OneShotTimer<SSLClientSocketNSS> uncork_timer_;
    184   scoped_refptr<IOBuffer> recv_buffer_;
    185 
    186   CompletionCallbackImpl<SSLClientSocketNSS> handshake_io_callback_;
    187   scoped_ptr<ClientSocketHandle> transport_;
    188   HostPortPair host_and_port_;
    189   SSLConfig ssl_config_;
    190 
    191   CompletionCallback* user_connect_callback_;
    192   CompletionCallback* user_read_callback_;
    193   CompletionCallback* user_write_callback_;
    194 
    195   // Used by Read function.
    196   scoped_refptr<IOBuffer> user_read_buf_;
    197   int user_read_buf_len_;
    198 
    199   // Used by Write function.
    200   scoped_refptr<IOBuffer> user_write_buf_;
    201   int user_write_buf_len_;
    202 
    203   // Set when handshake finishes.  The server certificate is first received
    204   // from NSS as an NSS certificate handle (server_cert_nss_), and then
    205   // converted into an X509Certificate object (server_cert_).
    206   scoped_refptr<X509Certificate> server_cert_;
    207   CERTCertificate* server_cert_nss_;
    208   // |server_cert_verify_result_| points at the verification result, which may,
    209   // or may not be, |&local_server_cert_verify_result_|, depending on whether
    210   // we used an SSLHostInfo's verification.
    211   const CertVerifyResult* server_cert_verify_result_;
    212   CertVerifyResult local_server_cert_verify_result_;
    213   int ssl_connection_status_;
    214 
    215   // Stores client authentication information between ClientAuthHandler and
    216   // GetSSLCertRequestInfo calls.
    217   std::vector<scoped_refptr<X509Certificate> > client_certs_;
    218   bool client_auth_cert_needed_;
    219 
    220   CertVerifier* const cert_verifier_;
    221   scoped_ptr<SingleRequestCertVerifier> verifier_;
    222 
    223   // True if NSS has called HandshakeCallback.
    224   bool handshake_callback_called_;
    225 
    226   // True if the SSL handshake has been completed.
    227   bool completed_handshake_;
    228 
    229   // True iff we believe that the user has an ESET product intercepting our
    230   // HTTPS connections.
    231   bool eset_mitm_detected_;
    232 
    233   // True iff |ssl_host_info_| contained a predicted certificate chain and
    234   // that we found the prediction to be correct.
    235   bool predicted_cert_chain_correct_;
    236 
    237   // True if the peer name has been initialized.
    238   bool peername_initialized_;
    239 
    240   // This pointer is owned by the caller of UseDNSSEC.
    241   DNSSECProvider* dnssec_provider_;
    242   // The time when we started waiting for DNSSEC records.
    243   base::Time dnssec_wait_start_time_;
    244 
    245   State next_handshake_state_;
    246 
    247   // The NSS SSL state machine
    248   PRFileDesc* nss_fd_;
    249 
    250   // Buffers for the network end of the SSL state machine
    251   memio_Private* nss_bufs_;
    252 
    253   BoundNetLog net_log_;
    254 
    255   base::TimeTicks start_cert_verification_time_;
    256 
    257   scoped_ptr<SSLHostInfo> ssl_host_info_;
    258   DnsCertProvenanceChecker* const dns_cert_checker_;
    259 
    260   // The following two variables are added for debugging bug 65948. Will
    261   // remove this code after fixing bug 65948.
    262   // Added the following code Debugging in release mode.
    263   mutable base::Lock lock_;
    264   // This is mutable so that CalledOnValidThread can set it.
    265   // It's guarded by |lock_|.
    266   mutable base::PlatformThreadId valid_thread_id_;
    267 };
    268 
    269 }  // namespace net
    270 
    271 #endif  // NET_SOCKET_SSL_CLIENT_SOCKET_NSS_H_
    272