blob: c0ed36d2b5044fe76ff78cfdf3b453b19edb86ba [file] [log] [blame]
[email protected]d518cd92010-09-29 12:27:441// Copyright (c) 2010 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// OpenSSL binding for SSLClientSocket. The class layout and general principle
6// of operation is derived from SSLClientSocketNSS.
7
8#include "net/socket/ssl_client_socket_openssl.h"
9
10#include <openssl/ssl.h>
11#include <openssl/err.h>
12
13#include "net/base/net_errors.h"
14#include "net/base/ssl_connection_status_flags.h"
15#include "net/base/ssl_info.h"
16#include "net/base/test_certificate_data.h" // TODO(joth): Remove!!
17
18namespace net {
19
20namespace {
21
22// Enable this to see logging for state machine state transitions.
23#if 0
24#define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
25 " jump to state " << s; \
26 next_handshake_state_ = s; } while (0)
27#else
28#define GotoState(s) next_handshake_state_ = s
29#endif
30
31const size_t kMaxRecvBufferSize = 4096;
32
33void MaybeLogSSLError() {
34 int error_num;
35 while ((error_num = ERR_get_error()) != 0) {
36 char buf[128]; // this buffer must be at least 120 chars long.
37 ERR_error_string_n(error_num, buf, arraysize(buf));
38 LOG(INFO) << "SSL error " << error_num << ": " << buf;
39 }
40}
41
42int MapOpenSSLError(int err) {
43 switch (err) {
44 case SSL_ERROR_WANT_READ:
45 case SSL_ERROR_WANT_WRITE:
46 return ERR_IO_PENDING;
47 default:
48 // TODO(joth): Implement full mapping.
49 LOG(WARNING) << "Unknown OpenSSL error " << err;
50 MaybeLogSSLError();
51 return ERR_SSL_PROTOCOL_ERROR;
52 }
53}
54
55} // namespace
56
57// static
58SSL_CTX* SSLClientSocketOpenSSL::g_ctx = NULL;
59
60SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
61 ClientSocketHandle* transport_socket,
62 const std::string& hostname,
63 const SSLConfig& ssl_config)
64 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
65 this, &SSLClientSocketOpenSSL::BufferSendComplete)),
66 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
67 this, &SSLClientSocketOpenSSL::BufferRecvComplete)),
68 transport_send_busy_(false),
69 transport_recv_busy_(false),
70 user_connect_callback_(NULL),
71 user_read_callback_(NULL),
72 user_write_callback_(NULL),
73 client_auth_cert_needed_(false),
74 ssl_(NULL),
75 transport_bio_(NULL),
76 transport_(transport_socket),
77 hostname_(hostname),
78 ssl_config_(ssl_config),
79 completed_handshake_(false),
80 net_log_(transport_socket->socket()->NetLog()) {
81}
82
83SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
84 Disconnect();
85}
86
87// TODO(joth): This method needs to be thread-safe.
88bool SSLClientSocketOpenSSL::InitOpenSSL() {
89 if (g_ctx)
90 return true;
91
92 SSL_load_error_strings();
93 MaybeLogSSLError();
94 SSL_library_init();
95 MaybeLogSSLError();
96
97 g_ctx = SSL_CTX_new(TLSv1_client_method());
98
99 if (!g_ctx) {
100 MaybeLogSSLError();
101 return false;
102 }
103
104 SSL_CTX_set_verify(g_ctx, SSL_VERIFY_NONE, NULL /*callback*/);
105
106 return true;
107}
108
109bool SSLClientSocketOpenSSL::Init() {
110 DCHECK(g_ctx);
111 ssl_ = SSL_new(g_ctx);
112 if (!ssl_) {
113 MaybeLogSSLError();
114 return false;
115 }
116
117 if (!SSL_set_tlsext_host_name(ssl_, hostname_.c_str())) {
118 MaybeLogSSLError();
119 return false;
120 }
121
122 BIO* ssl_bio = NULL;
123 // TODO(joth): Provide explicit write buffer sizes, rather than use defaults?
124 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) {
125 MaybeLogSSLError();
126 return false;
127 }
128 DCHECK(ssl_bio);
129 DCHECK(transport_bio_);
130
131 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
132
133 return true;
134}
135
136// SSLClientSocket methods
137
138void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
139 // Chrome DCHECKs that https pages provide a valid cert. For now (whilst in
140 // early dev) we just create a spoof cert.
141 // TODO(joth): implement X509Certificate for OpenSSL and remove this hack.
142 LOG(WARNING) << "Filling in certificate with bogus content";
143 ssl_info->Reset();
144 ssl_info->cert = X509Certificate::CreateFromBytes(
145 reinterpret_cast<const char*>(google_der), sizeof(google_der));
146 DCHECK(ssl_info->cert);
147 ssl_info->cert_status = 0;
148 ssl_info->security_bits = 56;
149 ssl_info->connection_status =
150 ((TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA) &
151 SSL_CONNECTION_CIPHERSUITE_MASK) << SSL_CONNECTION_CIPHERSUITE_SHIFT;
152
153 // Silence compiler about unused vars.
154 (void)google_der;
155 (void)webkit_der;
156 (void)thawte_der;
157 (void)paypal_null_der;
158}
159
160void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
161 SSLCertRequestInfo* cert_request_info) {
162 NOTREACHED();
163}
164
165SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
166 std::string* proto) {
167 proto->clear();
168 return kNextProtoUnsupported;
169}
170
171void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
172 // Since Run may result in Read being called, clear |user_read_callback_|
173 // up front.
174 CompletionCallback* c = user_read_callback_;
175 user_read_callback_ = NULL;
176 user_read_buf_ = NULL;
177 user_read_buf_len_ = 0;
178 c->Run(rv);
179}
180
181void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
182 // Since Run may result in Write being called, clear |user_write_callback_|
183 // up front.
184 CompletionCallback* c = user_write_callback_;
185 user_write_callback_ = NULL;
186 user_write_buf_ = NULL;
187 user_write_buf_len_ = 0;
188 c->Run(rv);
189}
190
191// ClientSocket methods
192
193int SSLClientSocketOpenSSL::Connect(CompletionCallback* callback) {
194 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
195
196 if (!InitOpenSSL()) {
197 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
198 return ERR_UNEXPECTED;
199 }
200
201 // Set up new ssl object.
202 if (!Init()) {
203 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
204 return ERR_UNEXPECTED;
205 }
206
207 // Set SSL to client mode. Handshake happens in the loop below.
208 SSL_set_connect_state(ssl_);
209
210 GotoState(STATE_HANDSHAKE);
211 int rv = DoHandshakeLoop(net::OK);
212 if (rv == ERR_IO_PENDING) {
213 user_connect_callback_ = callback;
214 } else {
215 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
216 }
217
218 return rv > OK ? OK : rv;
219}
220
221void SSLClientSocketOpenSSL::Disconnect() {
222 // Null all callbacks, delete all buffers.
223 transport_send_busy_ = false;
224 send_buffer_ = NULL;
225 transport_recv_busy_ = false;
226 recv_buffer_ = NULL;
227
228 user_connect_callback_ = NULL;
229 user_read_callback_ = NULL;
230 user_write_callback_ = NULL;
231 user_read_buf_ = NULL;
232 user_read_buf_len_ = 0;
233 user_write_buf_ = NULL;
234 user_write_buf_len_ = 0;
235
236 client_certs_.clear();
237 client_auth_cert_needed_ = false;
238
239 if (ssl_) {
240 SSL_free(ssl_);
241 ssl_ = NULL;
242 }
243 if (transport_bio_) {
244 BIO_free(transport_bio_);
245 transport_bio_ = NULL;
246 }
247
248 completed_handshake_ = false;
249 transport_->socket()->Disconnect();
250}
251
252int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
253 bool network_moved;
254 int rv = last_io_result;
255 do {
256 // Default to STATE_NONE for next state.
257 // (This is a quirk carried over from the windows
258 // implementation. It makes reading the logs a bit harder.)
259 // State handlers can and often do call GotoState just
260 // to stay in the current state.
261 State state = next_handshake_state_;
262 GotoState(STATE_NONE);
263 switch (state) {
264 case STATE_NONE:
265 // we're just pumping data between the buffer and the network
266 break;
267 case STATE_HANDSHAKE:
268 rv = DoHandshake();
269 break;
270#if 0 // TODO(joth): Implement cert verification.
271 case STATE_VERIFY_CERT:
272 DCHECK(rv == OK);
273 rv = DoVerifyCert(rv);
274 break;
275 case STATE_VERIFY_CERT_COMPLETE:
276 rv = DoVerifyCertComplete(rv);
277 break;
278#endif
279 default:
280 rv = ERR_UNEXPECTED;
281 NOTREACHED() << "unexpected state" << state;
282 break;
283 }
284
285 // To avoid getting an ERR_IO_PENDING here after handshake complete.
286 if (next_handshake_state_ == STATE_NONE)
287 break;
288
289 // Do the actual network I/O.
290 network_moved = DoTransportIO();
291 } while ((rv != ERR_IO_PENDING || network_moved) &&
292 next_handshake_state_ != STATE_NONE);
293 return rv;
294}
295
296int SSLClientSocketOpenSSL::DoHandshake() {
297 int net_error = net::OK;
298 int rv = SSL_do_handshake(ssl_);
299
300 if (rv == 1) {
301 // SSL handshake is completed. Let's verify the certificate.
302 // For now we are done, certificates not implemented yet.
303 // TODO(joth): Implement certificates
304 GotoState(STATE_NONE);
305 completed_handshake_ = true;
306 } else {
307 int ssl_error = SSL_get_error(ssl_, rv);
308
309 // If not done, stay in this state
310 GotoState(STATE_HANDSHAKE);
311 net_error = MapOpenSSLError(ssl_error);
312 }
313
314 return net_error;
315}
316
317bool SSLClientSocketOpenSSL::DoTransportIO() {
318 bool network_moved = false;
319 int nsent = BufferSend();
320 int nreceived = BufferRecv();
321 network_moved = (nsent > 0 || nreceived >= 0);
322 return network_moved;
323}
324
325int SSLClientSocketOpenSSL::BufferSend(void) {
326 if (transport_send_busy_)
327 return ERR_IO_PENDING;
328
329 if (!send_buffer_) {
330 // Get a fresh send buffer out of the send BIO.
331 size_t max_read = BIO_ctrl_pending(transport_bio_);
332 if (max_read > 0) {
333 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
334 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
335 DCHECK_GT(read_bytes, 0);
336 CHECK_EQ(static_cast<int>(max_read), read_bytes);
337 }
338 }
339
340 int rv = 0;
341 while (send_buffer_) {
342 rv = transport_->socket()->Write(send_buffer_,
343 send_buffer_->BytesRemaining(),
344 &buffer_send_callback_);
345 if (rv == ERR_IO_PENDING) {
346 transport_send_busy_ = true;
347 return rv;
348 }
349 TransportWriteComplete(rv);
350 }
351 return rv;
352}
353
354void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
355 transport_send_busy_ = false;
356 TransportWriteComplete(result);
357 OnSendComplete(result);
358}
359
360void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
361 if (result < 0) {
362 // Got a socket write error; close the BIO to indicate this upward.
363 (void)BIO_shutdown_wr(transport_bio_);
364 send_buffer_ = NULL;
365 } else {
366 DCHECK(send_buffer_);
367 send_buffer_->DidConsume(result);
368 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
369 if (send_buffer_->BytesRemaining() <= 0)
370 send_buffer_ = NULL;
371 }
372}
373
374int SSLClientSocketOpenSSL::BufferRecv(void) {
375 if (transport_recv_busy_)
376 return ERR_IO_PENDING;
377
378 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
379 if (max_write > kMaxRecvBufferSize)
380 max_write = kMaxRecvBufferSize;
381
382 if (!max_write)
383 return ERR_IO_PENDING;
384
385 recv_buffer_ = new IOBuffer(max_write);
386 int rv = transport_->socket()->Read(recv_buffer_, max_write,
387 &buffer_recv_callback_);
388 if (rv == ERR_IO_PENDING) {
389 transport_recv_busy_ = true;
390 } else {
391 TransportReadComplete(rv);
392 }
393 return rv;
394}
395
396void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
397 TransportReadComplete(result);
398 OnRecvComplete(result);
399}
400
401void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
402 if (result > 0) {
403 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
404 // A write into a memory BIO should always succeed.
405 CHECK_EQ(result, ret);
406 } else {
407 // Received end of file: bubble it up to the SSL layer via the BIO.
408 BIO_set_mem_eof_return(transport_bio_, 0);
409 (void)BIO_shutdown_wr(transport_bio_);
410 }
411 recv_buffer_ = NULL;
412 transport_recv_busy_ = false;
413}
414
415void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
416 CompletionCallback* c = user_connect_callback_;
417 user_connect_callback_ = NULL;
418 c->Run(rv > OK ? OK : rv);
419}
420
421void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
422 int rv = DoHandshakeLoop(result);
423 if (rv != ERR_IO_PENDING) {
424 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
425 DoConnectCallback(rv);
426 }
427}
428
429void SSLClientSocketOpenSSL::OnSendComplete(int result) {
430 if (next_handshake_state_ != STATE_NONE) {
431 // In handshake phase.
432 OnHandshakeIOComplete(result);
433 return;
434 }
435
436 // OnSendComplete may need to call DoPayloadRead while the renegotiation
437 // handshake is in progress.
438 int rv_read = ERR_IO_PENDING;
439 int rv_write = ERR_IO_PENDING;
440 bool network_moved;
441 do {
442 if (user_read_buf_)
443 rv_read = DoPayloadRead();
444 if (user_write_buf_)
445 rv_write = DoPayloadWrite();
446 network_moved = DoTransportIO();
447 } while (rv_read == ERR_IO_PENDING &&
448 rv_write == ERR_IO_PENDING &&
449 network_moved);
450
451 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
452 DoReadCallback(rv_read);
453 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
454 DoWriteCallback(rv_write);
455}
456
457void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
458 if (next_handshake_state_ != STATE_NONE) {
459 // In handshake phase.
460 OnHandshakeIOComplete(result);
461 return;
462 }
463
464 // Network layer received some data, check if client requested to read
465 // decrypted data.
466 if (!user_read_buf_)
467 return;
468
469 int rv = DoReadLoop(result);
470 if (rv != ERR_IO_PENDING)
471 DoReadCallback(rv);
472}
473
474bool SSLClientSocketOpenSSL::IsConnected() const {
475 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
476 return ret;
477}
478
479bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
480 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
481 return ret;
482}
483
484int SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const {
485 return transport_->socket()->GetPeerAddress(addressList);
486}
487
488const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
489 return net_log_;
490}
491
492void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
493 if (transport_.get() && transport_->socket()) {
494 transport_->socket()->SetSubresourceSpeculation();
495 } else {
496 NOTREACHED();
497 }
498}
499
500void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
501 if (transport_.get() && transport_->socket()) {
502 transport_->socket()->SetOmniboxSpeculation();
503 } else {
504 NOTREACHED();
505 }
506}
507
508bool SSLClientSocketOpenSSL::WasEverUsed() const {
509 if (transport_.get() && transport_->socket())
510 return transport_->socket()->WasEverUsed();
511
512 NOTREACHED();
513 return false;
514}
515
516// Socket methods
517
518int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
519 int buf_len,
520 CompletionCallback* callback) {
521 user_read_buf_ = buf;
522 user_read_buf_len_ = buf_len;
523
524 int rv = DoReadLoop(OK);
525
526 if (rv == ERR_IO_PENDING) {
527 user_read_callback_ = callback;
528 } else {
529 user_read_buf_ = NULL;
530 user_read_buf_len_ = 0;
531 }
532
533 return rv;
534}
535
536int SSLClientSocketOpenSSL::DoReadLoop(int result) {
537 if (result < 0)
538 return result;
539
540 bool network_moved;
541 int rv;
542 do {
543 rv = DoPayloadRead();
544 network_moved = DoTransportIO();
545 } while (rv == ERR_IO_PENDING && network_moved);
546
547 return rv;
548}
549
550int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
551 int buf_len,
552 CompletionCallback* callback) {
553 user_write_buf_ = buf;
554 user_write_buf_len_ = buf_len;
555
556 int rv = DoWriteLoop(OK);
557
558 if (rv == ERR_IO_PENDING) {
559 user_write_callback_ = callback;
560 } else {
561 user_write_buf_ = NULL;
562 user_write_buf_len_ = 0;
563 }
564
565 return rv;
566}
567
568int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
569 if (result < 0)
570 return result;
571
572 bool network_moved;
573 int rv;
574 do {
575 rv = DoPayloadWrite();
576 network_moved = DoTransportIO();
577 } while (rv == ERR_IO_PENDING && network_moved);
578
579 return rv;
580}
581
582bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
583 return transport_->socket()->SetReceiveBufferSize(size);
584}
585
586bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
587 return transport_->socket()->SetSendBufferSize(size);
588}
589
590int SSLClientSocketOpenSSL::DoPayloadRead() {
591 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
592 // We don't need to invalidate the non-client-authenticated SSL session
593 // because the server will renegotiate anyway.
594 if (client_auth_cert_needed_)
595 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
596
597 if (rv >= 0)
598 return rv;
599
600 int err = SSL_get_error(ssl_, rv);
601 return MapOpenSSLError(err);
602}
603
604int SSLClientSocketOpenSSL::DoPayloadWrite() {
605 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
606
607 if (rv >= 0)
608 return rv;
609
610 int err = SSL_get_error(ssl_, rv);
611 return MapOpenSSLError(err);
612}
613
614} // namespace net