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.
5 #include "jingle/glue/fake_ssl_client_socket.h"
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"
15 namespace jingle_glue
{
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.
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
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 //
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
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
63 net::DrainableIOBuffer
* NewDrainableIOBufferWithSize(int size
) {
64 return new net::DrainableIOBuffer(new net::IOBuffer(size
), size
);
69 base::StringPiece
FakeSSLClientSocket::GetSslClientHello() {
70 return base::StringPiece(reinterpret_cast<const char*>(kSslClientHello
),
71 arraysize(kSslClientHello
));
74 base::StringPiece
FakeSSLClientSocket::GetSslServerHello() {
75 return base::StringPiece(reinterpret_cast<const char*>(kSslServerHello
),
76 arraysize(kSslServerHello
));
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
));
90 FakeSSLClientSocket::~FakeSSLClientSocket() {}
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
);
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
);
106 int FakeSSLClientSocket::SetReceiveBufferSize(int32 size
) {
107 return transport_socket_
->SetReceiveBufferSize(size
);
110 int FakeSSLClientSocket::SetSendBufferSize(int32 size
) {
111 return transport_socket_
->SetSendBufferSize(size
);
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);
124 next_handshake_state_
= STATE_CONNECT
;
125 int status
= DoHandshakeLoop();
126 if (status
== net::ERR_IO_PENDING
)
127 user_connect_callback_
= callback
;
132 int FakeSSLClientSocket::DoHandshakeLoop() {
133 DCHECK_NE(next_handshake_state_
, STATE_NONE
);
134 int status
= net::OK
;
136 HandshakeState state
= next_handshake_state_
;
137 next_handshake_state_
= STATE_NONE
;
140 status
= DoConnect();
142 case STATE_SEND_CLIENT_HELLO
:
143 status
= DoSendClientHello();
145 case STATE_VERIFY_SERVER_HELLO
:
146 status
= DoVerifyServerHello();
149 status
= net::ERR_UNEXPECTED
;
150 LOG(DFATAL
) << "unexpected state: " << state
;
153 } while ((status
!= net::ERR_IO_PENDING
) &&
154 (next_handshake_state_
!= STATE_NONE
));
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
);
166 void FakeSSLClientSocket::DoHandshakeLoopWithUserConnectCallback() {
167 int status
= DoHandshakeLoop();
168 if (status
!= net::ERR_IO_PENDING
) {
169 RunUserConnectCallback(status
);
173 int FakeSSLClientSocket::DoConnect() {
174 int status
= transport_socket_
->Connect(
175 base::Bind(&FakeSSLClientSocket::OnConnectDone
, base::Unretained(this)));
176 if (status
!= net::OK
) {
179 ProcessConnectDone();
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
);
191 ProcessConnectDone();
192 DoHandshakeLoopWithUserConnectCallback();
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
;
201 int FakeSSLClientSocket::DoSendClientHello() {
202 int status
= transport_socket_
->Write(
204 write_buf_
->BytesRemaining(),
205 base::Bind(&FakeSSLClientSocket::OnSendClientHelloDone
,
206 base::Unretained(this)));
207 if (status
< net::OK
) {
210 ProcessSendClientHelloDone(static_cast<size_t>(status
));
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
);
221 ProcessSendClientHelloDone(static_cast<size_t>(status
));
222 DoHandshakeLoopWithUserConnectCallback();
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
);
232 next_handshake_state_
= STATE_VERIFY_SERVER_HELLO
;
236 int FakeSSLClientSocket::DoVerifyServerHello() {
237 int status
= transport_socket_
->Read(
239 read_buf_
->BytesRemaining(),
240 base::Bind(&FakeSSLClientSocket::OnVerifyServerHelloDone
,
241 base::Unretained(this)));
242 if (status
< net::OK
) {
245 size_t read
= static_cast<size_t>(status
);
246 return ProcessVerifyServerHelloDone(read
);
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
);
256 size_t read
= static_cast<size_t>(status
);
257 status
= ProcessVerifyServerHelloDone(read
);
258 if (status
< net::OK
) {
259 RunUserConnectCallback(status
);
262 if (handshake_completed_
) {
263 RunUserConnectCallback(net::OK
);
265 DoHandshakeLoopWithUserConnectCallback();
269 net::Error
FakeSSLClientSocket::ProcessVerifyServerHelloDone(size_t read
) {
270 DCHECK_LE(read
, static_cast<size_t>(read_buf_
->BytesRemaining()));
272 return net::ERR_UNEXPECTED
;
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
;
280 if (read
< static_cast<size_t>(read_buf_
->BytesRemaining())) {
281 next_handshake_state_
= STATE_VERIFY_SERVER_HELLO
;
282 read_buf_
->DidConsume(read
);
284 next_handshake_state_
= STATE_NONE
;
285 handshake_completed_
= true;
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);
299 bool FakeSSLClientSocket::IsConnected() const {
300 return handshake_completed_
&& transport_socket_
->IsConnected();
303 bool FakeSSLClientSocket::IsConnectedAndIdle() const {
304 return handshake_completed_
&& transport_socket_
->IsConnectedAndIdle();
307 int FakeSSLClientSocket::GetPeerAddress(net::IPEndPoint
* address
) const {
308 return transport_socket_
->GetPeerAddress(address
);
311 int FakeSSLClientSocket::GetLocalAddress(net::IPEndPoint
* address
) const {
312 return transport_socket_
->GetLocalAddress(address
);
315 const net::BoundNetLog
& FakeSSLClientSocket::NetLog() const {
316 return transport_socket_
->NetLog();
319 void FakeSSLClientSocket::SetSubresourceSpeculation() {
320 transport_socket_
->SetSubresourceSpeculation();
323 void FakeSSLClientSocket::SetOmniboxSpeculation() {
324 transport_socket_
->SetOmniboxSpeculation();
327 bool FakeSSLClientSocket::WasEverUsed() const {
328 return transport_socket_
->WasEverUsed();
331 bool FakeSSLClientSocket::UsingTCPFastOpen() const {
332 return transport_socket_
->UsingTCPFastOpen();
335 bool FakeSSLClientSocket::WasNpnNegotiated() const {
336 return transport_socket_
->WasNpnNegotiated();
339 net::NextProto
FakeSSLClientSocket::GetNegotiatedProtocol() const {
340 return transport_socket_
->GetNegotiatedProtocol();
343 bool FakeSSLClientSocket::GetSSLInfo(net::SSLInfo
* ssl_info
) {
344 return transport_socket_
->GetSSLInfo(ssl_info
);
347 } // namespace jingle_glue