Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2012 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 #include "jingle/glue/fake_ssl_client_socket.h"
      6 
      7 #include <cstdlib>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/compiler_specific.h"
     11 #include "base/logging.h"
     12 #include "net/base/io_buffer.h"
     13 #include "net/base/net_errors.h"
     14 
     15 namespace jingle_glue {
     16 
     17 namespace {
     18 
     19 // The constants below were taken from libjingle's socketadapters.cc.
     20 // Basically, we do a "fake" SSL handshake to fool proxies into
     21 // thinking this is a real SSL connection.
     22 
     23 // This is a SSL v2 CLIENT_HELLO message.
     24 // TODO(juberti): Should this have a session id? The response doesn't have a
     25 // certificate, so the hello should have a session id.
     26 static const uint8 kSslClientHello[] = {
     27   0x80, 0x46,                                            // msg len
     28   0x01,                                                  // CLIENT_HELLO
     29   0x03, 0x01,                                            // SSL 3.1
     30   0x00, 0x2d,                                            // ciphersuite len
     31   0x00, 0x00,                                            // session id len
     32   0x00, 0x10,                                            // challenge len
     33   0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0,  // ciphersuites
     34   0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80,  //
     35   0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a,  //
     36   0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64,  //
     37   0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,  //
     38   0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,        // challenge
     39   0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea         //
     40 };
     41 
     42 // This is a TLSv1 SERVER_HELLO message.
     43 static const uint8 kSslServerHello[] = {
     44   0x16,                                            // handshake message
     45   0x03, 0x01,                                      // SSL 3.1
     46   0x00, 0x4a,                                      // message len
     47   0x02,                                            // SERVER_HELLO
     48   0x00, 0x00, 0x46,                                // handshake len
     49   0x03, 0x01,                                      // SSL 3.1
     50   0x42, 0x85, 0x45, 0xa7, 0x27, 0xa9, 0x5d, 0xa0,  // server random
     51   0xb3, 0xc5, 0xe7, 0x53, 0xda, 0x48, 0x2b, 0x3f,  //
     52   0xc6, 0x5a, 0xca, 0x89, 0xc1, 0x58, 0x52, 0xa1,  //
     53   0x78, 0x3c, 0x5b, 0x17, 0x46, 0x00, 0x85, 0x3f,  //
     54   0x20,                                            // session id len
     55   0x0e, 0xd3, 0x06, 0x72, 0x5b, 0x5b, 0x1b, 0x5f,  // session id
     56   0x15, 0xac, 0x13, 0xf9, 0x88, 0x53, 0x9d, 0x9b,  //
     57   0xe8, 0x3d, 0x7b, 0x0c, 0x30, 0x32, 0x6e, 0x38,  //
     58   0x4d, 0xa2, 0x75, 0x57, 0x41, 0x6c, 0x34, 0x5c,  //
     59   0x00, 0x04,                                      // RSA/RC4-128/MD5
     60   0x00                                             // null compression
     61 };
     62 
     63 net::DrainableIOBuffer* NewDrainableIOBufferWithSize(int size) {
     64   return new net::DrainableIOBuffer(new net::IOBuffer(size), size);
     65 }
     66 
     67 }  // namespace
     68 
     69 base::StringPiece FakeSSLClientSocket::GetSslClientHello() {
     70   return base::StringPiece(reinterpret_cast<const char*>(kSslClientHello),
     71                            arraysize(kSslClientHello));
     72 }
     73 
     74 base::StringPiece FakeSSLClientSocket::GetSslServerHello() {
     75   return base::StringPiece(reinterpret_cast<const char*>(kSslServerHello),
     76                            arraysize(kSslServerHello));
     77 }
     78 
     79 FakeSSLClientSocket::FakeSSLClientSocket(
     80     scoped_ptr<net::StreamSocket> transport_socket)
     81     : transport_socket_(transport_socket.Pass()),
     82       next_handshake_state_(STATE_NONE),
     83       handshake_completed_(false),
     84       write_buf_(NewDrainableIOBufferWithSize(arraysize(kSslClientHello))),
     85       read_buf_(NewDrainableIOBufferWithSize(arraysize(kSslServerHello))) {
     86   CHECK(transport_socket_.get());
     87   std::memcpy(write_buf_->data(), kSslClientHello, arraysize(kSslClientHello));
     88 }
     89 
     90 FakeSSLClientSocket::~FakeSSLClientSocket() {}
     91 
     92 int FakeSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
     93                               const net::CompletionCallback& callback) {
     94   DCHECK_EQ(next_handshake_state_, STATE_NONE);
     95   DCHECK(handshake_completed_);
     96   return transport_socket_->Read(buf, buf_len, callback);
     97 }
     98 
     99 int FakeSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
    100                                const net::CompletionCallback& callback) {
    101   DCHECK_EQ(next_handshake_state_, STATE_NONE);
    102   DCHECK(handshake_completed_);
    103   return transport_socket_->Write(buf, buf_len, callback);
    104 }
    105 
    106 bool FakeSSLClientSocket::SetReceiveBufferSize(int32 size) {
    107   return transport_socket_->SetReceiveBufferSize(size);
    108 }
    109 
    110 bool FakeSSLClientSocket::SetSendBufferSize(int32 size) {
    111   return transport_socket_->SetSendBufferSize(size);
    112 }
    113 
    114 int FakeSSLClientSocket::Connect(const net::CompletionCallback& callback) {
    115   // We don't support synchronous operation, even if
    116   // |transport_socket_| does.
    117   DCHECK(!callback.is_null());
    118   DCHECK_EQ(next_handshake_state_, STATE_NONE);
    119   DCHECK(!handshake_completed_);
    120   DCHECK(user_connect_callback_.is_null());
    121   DCHECK_EQ(write_buf_->BytesConsumed(), 0);
    122   DCHECK_EQ(read_buf_->BytesConsumed(), 0);
    123 
    124   next_handshake_state_ = STATE_CONNECT;
    125   int status = DoHandshakeLoop();
    126   if (status == net::ERR_IO_PENDING)
    127     user_connect_callback_ = callback;
    128 
    129   return status;
    130 }
    131 
    132 int FakeSSLClientSocket::DoHandshakeLoop() {
    133   DCHECK_NE(next_handshake_state_, STATE_NONE);
    134   int status = net::OK;
    135   do {
    136     HandshakeState state = next_handshake_state_;
    137     next_handshake_state_ = STATE_NONE;
    138     switch (state) {
    139       case STATE_CONNECT:
    140         status = DoConnect();
    141         break;
    142       case STATE_SEND_CLIENT_HELLO:
    143         status = DoSendClientHello();
    144         break;
    145       case STATE_VERIFY_SERVER_HELLO:
    146         status = DoVerifyServerHello();
    147         break;
    148       default:
    149         status = net::ERR_UNEXPECTED;
    150         LOG(DFATAL) << "unexpected state: " << state;
    151         break;
    152     }
    153   } while ((status != net::ERR_IO_PENDING) &&
    154            (next_handshake_state_ != STATE_NONE));
    155   return status;
    156 }
    157 
    158 void FakeSSLClientSocket::RunUserConnectCallback(int status) {
    159   DCHECK_LE(status, net::OK);
    160   next_handshake_state_ = STATE_NONE;
    161   net::CompletionCallback user_connect_callback = user_connect_callback_;
    162   user_connect_callback_.Reset();
    163   user_connect_callback.Run(status);
    164 }
    165 
    166 void FakeSSLClientSocket::DoHandshakeLoopWithUserConnectCallback() {
    167   int status = DoHandshakeLoop();
    168   if (status != net::ERR_IO_PENDING) {
    169     RunUserConnectCallback(status);
    170   }
    171 }
    172 
    173 int FakeSSLClientSocket::DoConnect() {
    174   int status = transport_socket_->Connect(
    175       base::Bind(&FakeSSLClientSocket::OnConnectDone, base::Unretained(this)));
    176   if (status != net::OK) {
    177     return status;
    178   }
    179   ProcessConnectDone();
    180   return net::OK;
    181 }
    182 
    183 void FakeSSLClientSocket::OnConnectDone(int status) {
    184   DCHECK_NE(status, net::ERR_IO_PENDING);
    185   DCHECK_LE(status, net::OK);
    186   DCHECK(!user_connect_callback_.is_null());
    187   if (status != net::OK) {
    188     RunUserConnectCallback(status);
    189     return;
    190   }
    191   ProcessConnectDone();
    192   DoHandshakeLoopWithUserConnectCallback();
    193 }
    194 
    195 void FakeSSLClientSocket::ProcessConnectDone() {
    196   DCHECK_EQ(write_buf_->BytesConsumed(), 0);
    197   DCHECK_EQ(read_buf_->BytesConsumed(), 0);
    198   next_handshake_state_ = STATE_SEND_CLIENT_HELLO;
    199 }
    200 
    201 int FakeSSLClientSocket::DoSendClientHello() {
    202   int status = transport_socket_->Write(
    203       write_buf_.get(),
    204       write_buf_->BytesRemaining(),
    205       base::Bind(&FakeSSLClientSocket::OnSendClientHelloDone,
    206                  base::Unretained(this)));
    207   if (status < net::OK) {
    208     return status;
    209   }
    210   ProcessSendClientHelloDone(static_cast<size_t>(status));
    211   return net::OK;
    212 }
    213 
    214 void FakeSSLClientSocket::OnSendClientHelloDone(int status) {
    215   DCHECK_NE(status, net::ERR_IO_PENDING);
    216   DCHECK(!user_connect_callback_.is_null());
    217   if (status < net::OK) {
    218     RunUserConnectCallback(status);
    219     return;
    220   }
    221   ProcessSendClientHelloDone(static_cast<size_t>(status));
    222   DoHandshakeLoopWithUserConnectCallback();
    223 }
    224 
    225 void FakeSSLClientSocket::ProcessSendClientHelloDone(size_t written) {
    226   DCHECK_LE(written, static_cast<size_t>(write_buf_->BytesRemaining()));
    227   DCHECK_EQ(read_buf_->BytesConsumed(), 0);
    228   if (written < static_cast<size_t>(write_buf_->BytesRemaining())) {
    229     next_handshake_state_ = STATE_SEND_CLIENT_HELLO;
    230     write_buf_->DidConsume(written);
    231   } else {
    232     next_handshake_state_ = STATE_VERIFY_SERVER_HELLO;
    233   }
    234 }
    235 
    236 int FakeSSLClientSocket::DoVerifyServerHello() {
    237   int status = transport_socket_->Read(
    238       read_buf_.get(),
    239       read_buf_->BytesRemaining(),
    240       base::Bind(&FakeSSLClientSocket::OnVerifyServerHelloDone,
    241                  base::Unretained(this)));
    242   if (status < net::OK) {
    243     return status;
    244   }
    245   size_t read = static_cast<size_t>(status);
    246   return ProcessVerifyServerHelloDone(read);
    247 }
    248 
    249 void FakeSSLClientSocket::OnVerifyServerHelloDone(int status) {
    250   DCHECK_NE(status, net::ERR_IO_PENDING);
    251   DCHECK(!user_connect_callback_.is_null());
    252   if (status < net::OK) {
    253     RunUserConnectCallback(status);
    254     return;
    255   }
    256   size_t read = static_cast<size_t>(status);
    257   status = ProcessVerifyServerHelloDone(read);
    258   if (status < net::OK) {
    259     RunUserConnectCallback(status);
    260     return;
    261   }
    262   if (handshake_completed_) {
    263     RunUserConnectCallback(net::OK);
    264   } else {
    265     DoHandshakeLoopWithUserConnectCallback();
    266   }
    267 }
    268 
    269 net::Error FakeSSLClientSocket::ProcessVerifyServerHelloDone(size_t read) {
    270   DCHECK_LE(read, static_cast<size_t>(read_buf_->BytesRemaining()));
    271   if (read == 0U) {
    272     return net::ERR_UNEXPECTED;
    273   }
    274   const uint8* expected_data_start =
    275       &kSslServerHello[arraysize(kSslServerHello) -
    276                        read_buf_->BytesRemaining()];
    277   if (std::memcmp(expected_data_start, read_buf_->data(), read) != 0) {
    278     return net::ERR_UNEXPECTED;
    279   }
    280   if (read < static_cast<size_t>(read_buf_->BytesRemaining())) {
    281     next_handshake_state_ = STATE_VERIFY_SERVER_HELLO;
    282     read_buf_->DidConsume(read);
    283   } else {
    284     next_handshake_state_ = STATE_NONE;
    285     handshake_completed_ = true;
    286   }
    287   return net::OK;
    288 }
    289 
    290 void FakeSSLClientSocket::Disconnect() {
    291   transport_socket_->Disconnect();
    292   next_handshake_state_ = STATE_NONE;
    293   handshake_completed_ = false;
    294   user_connect_callback_.Reset();
    295   write_buf_->SetOffset(0);
    296   read_buf_->SetOffset(0);
    297 }
    298 
    299 bool FakeSSLClientSocket::IsConnected() const {
    300   return handshake_completed_ && transport_socket_->IsConnected();
    301 }
    302 
    303 bool FakeSSLClientSocket::IsConnectedAndIdle() const {
    304   return handshake_completed_ && transport_socket_->IsConnectedAndIdle();
    305 }
    306 
    307 int FakeSSLClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
    308   return transport_socket_->GetPeerAddress(address);
    309 }
    310 
    311 int FakeSSLClientSocket::GetLocalAddress(net::IPEndPoint* address) const {
    312   return transport_socket_->GetLocalAddress(address);
    313 }
    314 
    315 const net::BoundNetLog& FakeSSLClientSocket::NetLog() const {
    316   return transport_socket_->NetLog();
    317 }
    318 
    319 void FakeSSLClientSocket::SetSubresourceSpeculation() {
    320   transport_socket_->SetSubresourceSpeculation();
    321 }
    322 
    323 void FakeSSLClientSocket::SetOmniboxSpeculation() {
    324   transport_socket_->SetOmniboxSpeculation();
    325 }
    326 
    327 bool FakeSSLClientSocket::WasEverUsed() const {
    328   return transport_socket_->WasEverUsed();
    329 }
    330 
    331 bool FakeSSLClientSocket::UsingTCPFastOpen() const {
    332   return transport_socket_->UsingTCPFastOpen();
    333 }
    334 
    335 bool FakeSSLClientSocket::WasNpnNegotiated() const {
    336   return transport_socket_->WasNpnNegotiated();
    337 }
    338 
    339 net::NextProto FakeSSLClientSocket::GetNegotiatedProtocol() const {
    340   return transport_socket_->GetNegotiatedProtocol();
    341 }
    342 
    343 bool FakeSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
    344   return transport_socket_->GetSSLInfo(ssl_info);
    345 }
    346 
    347 }  // namespace jingle_glue
    348