- add sources.
[platform/framework/web/crosswalk.git] / src / jingle / glue / fake_ssl_client_socket.cc
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