1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// Copyright (c) 2012 The Chromium Authors. All rights reserved.
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Use of this source code is governed by a BSD-style license that can be
3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// found in the LICENSE file.
4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "jingle/glue/fake_ssl_client_socket.h"
6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include <cstdlib>
8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "base/basictypes.h"
10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "base/compiler_specific.h"
11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "base/logging.h"
12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "net/base/io_buffer.h"
13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "net/base/net_errors.h"
14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonnamespace jingle_glue {
16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertnamespace {
18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// The constants below were taken from libjingle's socketadapters.cc.
20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// Basically, we do a "fake" SSL handshake to fool proxies into
21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// thinking this is a real SSL connection.
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// This is a SSL v2 CLIENT_HELLO message.
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// TODO(juberti): Should this have a session id? The response doesn't have a
25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson// certificate, so the hello should have a session id.
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic const uint8 kSslClientHello[] = {
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  0x80, 0x46,                                            // msg len
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  0x01,                                                  // CLIENT_HELLO
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  0x03, 0x01,                                            // SSL 3.1
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  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.
43static 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
63net::DrainableIOBuffer* NewDrainableIOBufferWithSize(int size) {
64  return new net::DrainableIOBuffer(new net::IOBuffer(size), size);
65}
66
67}  // namespace
68
69base::StringPiece FakeSSLClientSocket::GetSslClientHello() {
70  return base::StringPiece(reinterpret_cast<const char*>(kSslClientHello),
71                           arraysize(kSslClientHello));
72}
73
74base::StringPiece FakeSSLClientSocket::GetSslServerHello() {
75  return base::StringPiece(reinterpret_cast<const char*>(kSslServerHello),
76                           arraysize(kSslServerHello));
77}
78
79FakeSSLClientSocket::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
90FakeSSLClientSocket::~FakeSSLClientSocket() {}
91
92int 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
99int 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
106int FakeSSLClientSocket::SetReceiveBufferSize(int32 size) {
107  return transport_socket_->SetReceiveBufferSize(size);
108}
109
110int FakeSSLClientSocket::SetSendBufferSize(int32 size) {
111  return transport_socket_->SetSendBufferSize(size);
112}
113
114int 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
132int 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
158void 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
166void FakeSSLClientSocket::DoHandshakeLoopWithUserConnectCallback() {
167  int status = DoHandshakeLoop();
168  if (status != net::ERR_IO_PENDING) {
169    RunUserConnectCallback(status);
170  }
171}
172
173int 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
183void 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
195void 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
201int 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
214void 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
225void 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
236int 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
249void 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
269net::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
290void 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
299bool FakeSSLClientSocket::IsConnected() const {
300  return handshake_completed_ && transport_socket_->IsConnected();
301}
302
303bool FakeSSLClientSocket::IsConnectedAndIdle() const {
304  return handshake_completed_ && transport_socket_->IsConnectedAndIdle();
305}
306
307int FakeSSLClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
308  return transport_socket_->GetPeerAddress(address);
309}
310
311int FakeSSLClientSocket::GetLocalAddress(net::IPEndPoint* address) const {
312  return transport_socket_->GetLocalAddress(address);
313}
314
315const net::BoundNetLog& FakeSSLClientSocket::NetLog() const {
316  return transport_socket_->NetLog();
317}
318
319void FakeSSLClientSocket::SetSubresourceSpeculation() {
320  transport_socket_->SetSubresourceSpeculation();
321}
322
323void FakeSSLClientSocket::SetOmniboxSpeculation() {
324  transport_socket_->SetOmniboxSpeculation();
325}
326
327bool FakeSSLClientSocket::WasEverUsed() const {
328  return transport_socket_->WasEverUsed();
329}
330
331bool FakeSSLClientSocket::UsingTCPFastOpen() const {
332  return transport_socket_->UsingTCPFastOpen();
333}
334
335bool FakeSSLClientSocket::WasNpnNegotiated() const {
336  return transport_socket_->WasNpnNegotiated();
337}
338
339net::NextProto FakeSSLClientSocket::GetNegotiatedProtocol() const {
340  return transport_socket_->GetNegotiatedProtocol();
341}
342
343bool FakeSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
344  return transport_socket_->GetSSLInfo(ssl_info);
345}
346
347}  // namespace jingle_glue
348