Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: net/socket/ssl_server_socket_openssl.cc

Issue 274783002: Implement SSL server socket over OpenSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unnecessary comment. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/socket/ssl_server_socket_openssl.h"
6
7 #include <openssl/err.h>
8 #include <openssl/ssl.h>
9
10 #include "base/callback_helpers.h"
5 #include "base/logging.h" 11 #include "base/logging.h"
6 #include "net/socket/ssl_server_socket.h" 12 #include "crypto/openssl_util.h"
13 #include "crypto/rsa_private_key.h"
14 #include "net/base/net_errors.h"
15 #include "net/socket/openssl_ssl_util.h"
16 #include "net/socket/ssl_error_params.h"
7 17
8 // TODO(bulach): Provide simple stubs for EnableSSLServerSockets and 18 #define GotoState(s) next_handshake_state_ = s
9 // CreateSSLServerSocket so that when building for OpenSSL rather than NSS,
10 // so that the code using SSL server sockets can be compiled and disabled
11 // programatically rather than requiring to be carved out from the compile.
12 19
13 namespace net { 20 namespace net {
14 21
15 void EnableSSLServerSockets() { 22 void EnableSSLServerSockets() {
16 NOTIMPLEMENTED(); 23 // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
17 } 24 }
18 25
19 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( 26 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
20 scoped_ptr<StreamSocket> socket, 27 scoped_ptr<StreamSocket> socket,
21 X509Certificate* certificate, 28 X509Certificate* certificate,
22 crypto::RSAPrivateKey* key, 29 crypto::RSAPrivateKey* key,
23 const SSLConfig& ssl_config) { 30 const SSLConfig& ssl_config) {
31 crypto::EnsureOpenSSLInit();
32 return scoped_ptr<SSLServerSocket>(
33 new SSLServerSocketOpenSSL(socket.Pass(), certificate, key, ssl_config));
34 }
35
36 SSLServerSocketOpenSSL::SSLServerSocketOpenSSL(
37 scoped_ptr<StreamSocket> transport_socket,
38 scoped_refptr<X509Certificate> certificate,
39 crypto::RSAPrivateKey* key,
40 const SSLConfig& ssl_config)
41 : transport_send_busy_(false),
42 transport_recv_busy_(false),
43 transport_recv_eof_(false),
44 user_read_buf_len_(0),
45 user_write_buf_len_(0),
46 transport_write_error_(OK),
47 ssl_(NULL),
48 transport_bio_(NULL),
49 transport_socket_(transport_socket.Pass()),
50 ssl_config_(ssl_config),
51 cert_(certificate),
52 next_handshake_state_(STATE_NONE),
53 completed_handshake_(false) {
54 // TODO(byungchul): Need a better way to clone a key.
55 std::vector<uint8> key_bytes;
56 CHECK(key->ExportPrivateKey(&key_bytes));
57 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
58 CHECK(key_.get());
59 }
60
61 SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() {
62 if (ssl_) {
63 // Calling SSL_shutdown prevents the session from being marked as
64 // unresumable.
65 SSL_shutdown(ssl_);
66 SSL_free(ssl_);
67 ssl_ = NULL;
68 }
69 if (transport_bio_) {
70 BIO_free_all(transport_bio_);
71 transport_bio_ = NULL;
72 }
73 }
74
75 int SSLServerSocketOpenSSL::Handshake(const CompletionCallback& callback) {
76 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
77
78 // Set up new ssl object.
79 int rv = Init();
80 if (rv != OK) {
81 LOG(ERROR) << "Failed to initialize OpenSSL: rv=" << rv;
82 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
83 return rv;
84 }
85
86 // Set SSL to server mode. Handshake happens in the loop below.
87 SSL_set_accept_state(ssl_);
88
89 GotoState(STATE_HANDSHAKE);
90 rv = DoHandshakeLoop(OK);
91 if (rv == ERR_IO_PENDING) {
92 user_handshake_callback_ = callback;
93 } else {
94 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
95 }
96
97 return rv > OK ? OK : rv;
98 }
99
100 int SSLServerSocketOpenSSL::ExportKeyingMaterial(
101 const base::StringPiece& label,
102 bool has_context,
103 const base::StringPiece& context,
104 unsigned char* out,
105 unsigned int outlen) {
106 if (!IsConnected())
107 return ERR_SOCKET_NOT_CONNECTED;
108
109 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
110
111 int rv = SSL_export_keying_material(
112 ssl_, out, outlen, label.data(), label.size(),
113 reinterpret_cast<const unsigned char*>(context.data()),
114 context.length(), context.length() > 0);
115
116 if (rv != 1) {
117 int ssl_error = SSL_get_error(ssl_, rv);
118 LOG(ERROR) << "Failed to export keying material;"
119 << " returned " << rv
120 << ", SSL error code " << ssl_error;
121 return MapOpenSSLError(ssl_error, err_tracer);
122 }
123 return OK;
124 }
125
126 int SSLServerSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
24 NOTIMPLEMENTED(); 127 NOTIMPLEMENTED();
25 return scoped_ptr<SSLServerSocket>(); 128 return ERR_NOT_IMPLEMENTED;
129 }
130
131 int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
132 const CompletionCallback& callback) {
133 DCHECK(user_read_callback_.is_null());
134 DCHECK(user_handshake_callback_.is_null());
135 DCHECK(!user_read_buf_.get());
136 DCHECK(!callback.is_null());
137
138 user_read_buf_ = buf;
139 user_read_buf_len_ = buf_len;
140
141 DCHECK(completed_handshake_);
142
143 int rv = DoReadLoop(OK);
144
145 if (rv == ERR_IO_PENDING) {
146 user_read_callback_ = callback;
147 } else {
148 user_read_buf_ = NULL;
149 user_read_buf_len_ = 0;
150 }
151
152 return rv;
153 }
154
155 int SSLServerSocketOpenSSL::Write(IOBuffer* buf, int buf_len,
156 const CompletionCallback& callback) {
157 DCHECK(user_write_callback_.is_null());
158 DCHECK(!user_write_buf_.get());
159 DCHECK(!callback.is_null());
160
161 user_write_buf_ = buf;
162 user_write_buf_len_ = buf_len;
163
164 int rv = DoWriteLoop(OK);
165
166 if (rv == ERR_IO_PENDING) {
167 user_write_callback_ = callback;
168 } else {
169 user_write_buf_ = NULL;
170 user_write_buf_len_ = 0;
171 }
172 return rv;
173 }
174
175 int SSLServerSocketOpenSSL::SetReceiveBufferSize(int32 size) {
176 return transport_socket_->SetReceiveBufferSize(size);
177 }
178
179 int SSLServerSocketOpenSSL::SetSendBufferSize(int32 size) {
180 return transport_socket_->SetSendBufferSize(size);
181 }
182
183 int SSLServerSocketOpenSSL::Connect(const CompletionCallback& callback) {
184 NOTIMPLEMENTED();
185 return ERR_NOT_IMPLEMENTED;
186 }
187
188 void SSLServerSocketOpenSSL::Disconnect() {
189 transport_socket_->Disconnect();
190 }
191
192 bool SSLServerSocketOpenSSL::IsConnected() const {
193 // TODO(wtc): Check transport_socket_->IsConnected() as well.
wtc 2014/05/16 19:36:14 This comment should say "Find out if we should che
byungchul 2014/05/16 19:50:32 Done.
194 return completed_handshake_;
195 }
196
197 bool SSLServerSocketOpenSSL::IsConnectedAndIdle() const {
198 return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
199 }
200
201 int SSLServerSocketOpenSSL::GetPeerAddress(IPEndPoint* address) const {
202 if (!IsConnected())
203 return ERR_SOCKET_NOT_CONNECTED;
204 return transport_socket_->GetPeerAddress(address);
205 }
206
207 int SSLServerSocketOpenSSL::GetLocalAddress(IPEndPoint* address) const {
208 if (!IsConnected())
209 return ERR_SOCKET_NOT_CONNECTED;
210 return transport_socket_->GetLocalAddress(address);
211 }
212
213 const BoundNetLog& SSLServerSocketOpenSSL::NetLog() const {
214 return net_log_;
215 }
216
217 void SSLServerSocketOpenSSL::SetSubresourceSpeculation() {
218 transport_socket_->SetSubresourceSpeculation();
219 }
220
221 void SSLServerSocketOpenSSL::SetOmniboxSpeculation() {
222 transport_socket_->SetOmniboxSpeculation();
223 }
224
225 bool SSLServerSocketOpenSSL::WasEverUsed() const {
226 return transport_socket_->WasEverUsed();
227 }
228
229 bool SSLServerSocketOpenSSL::UsingTCPFastOpen() const {
230 return transport_socket_->UsingTCPFastOpen();
231 }
232
233 bool SSLServerSocketOpenSSL::WasNpnNegotiated() const {
234 NOTIMPLEMENTED();
235 return false;
236 }
237
238 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const {
239 // NPN is not supported by this class.
240 return kProtoUnknown;
241 }
242
243 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
244 NOTIMPLEMENTED();
245 return false;
246 }
247
248 void SSLServerSocketOpenSSL::OnSendComplete(int result) {
249 if (next_handshake_state_ == STATE_HANDSHAKE) {
250 // In handshake phase.
251 OnHandshakeIOComplete(result);
252 return;
253 }
254
255 // TODO(byungchul): This state machine is not correct. Copy the state machine
256 // of SSLClientSocketOpenSSL::OnSendComplete() which handles it better.
257 if (!completed_handshake_)
258 return;
259
260 if (user_write_buf_.get()) {
261 int rv = DoWriteLoop(result);
262 if (rv != ERR_IO_PENDING)
263 DoWriteCallback(rv);
264 } else {
265 // Ensure that any queued ciphertext is flushed.
266 DoTransportIO();
267 }
268 }
269
270 void SSLServerSocketOpenSSL::OnRecvComplete(int result) {
271 if (next_handshake_state_ == STATE_HANDSHAKE) {
272 // In handshake phase.
273 OnHandshakeIOComplete(result);
274 return;
275 }
276
277 // Network layer received some data, check if client requested to read
278 // decrypted data.
279 if (!user_read_buf_.get() || !completed_handshake_)
280 return;
281
282 int rv = DoReadLoop(result);
283 if (rv != ERR_IO_PENDING)
284 DoReadCallback(rv);
285 }
286
287 void SSLServerSocketOpenSSL::OnHandshakeIOComplete(int result) {
288 int rv = DoHandshakeLoop(result);
289 if (rv == ERR_IO_PENDING)
290 return;
291
292 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
293 if (!user_handshake_callback_.is_null())
294 DoHandshakeCallback(rv);
295 }
296
297 // Return 0 for EOF,
298 // > 0 for bytes transferred immediately,
299 // < 0 for error (or the non-error ERR_IO_PENDING).
300 int SSLServerSocketOpenSSL::BufferSend() {
301 if (transport_send_busy_)
302 return ERR_IO_PENDING;
303
304 if (!send_buffer_.get()) {
305 // Get a fresh send buffer out of the send BIO.
306 size_t max_read = BIO_ctrl_pending(transport_bio_);
307 if (!max_read)
308 return 0; // Nothing pending in the OpenSSL write BIO.
309 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
310 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
311 DCHECK_GT(read_bytes, 0);
312 CHECK_EQ(static_cast<int>(max_read), read_bytes);
313 }
314
315 int rv = transport_socket_->Write(
316 send_buffer_.get(),
317 send_buffer_->BytesRemaining(),
318 base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete,
319 base::Unretained(this)));
320 if (rv == ERR_IO_PENDING) {
321 transport_send_busy_ = true;
322 } else {
323 TransportWriteComplete(rv);
324 }
325 return rv;
326 }
327
328 void SSLServerSocketOpenSSL::BufferSendComplete(int result) {
329 transport_send_busy_ = false;
330 TransportWriteComplete(result);
331 OnSendComplete(result);
332 }
333
334 void SSLServerSocketOpenSSL::TransportWriteComplete(int result) {
335 DCHECK(ERR_IO_PENDING != result);
336 if (result < 0) {
337 // Got a socket write error; close the BIO to indicate this upward.
338 //
339 // TODO(davidben): The value of |result| gets lost. Feed the error back into
340 // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
341 // BIO_set_callback.
342 DVLOG(1) << "TransportWriteComplete error " << result;
343 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
344
345 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
346 // from the socket after a write error.
347 //
348 // TODO(davidben): Avoid having read and write ends interact this way.
349 transport_write_error_ = result;
350 (void)BIO_shutdown_wr(transport_bio_);
351 send_buffer_ = NULL;
352 } else {
353 DCHECK(send_buffer_.get());
354 send_buffer_->DidConsume(result);
355 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
356 if (send_buffer_->BytesRemaining() <= 0)
357 send_buffer_ = NULL;
358 }
359 }
360
361 int SSLServerSocketOpenSSL::BufferRecv() {
362 if (transport_recv_busy_)
363 return ERR_IO_PENDING;
364
365 // Determine how much was requested from |transport_bio_| that was not
366 // actually available.
367 size_t requested = BIO_ctrl_get_read_request(transport_bio_);
368 if (requested == 0) {
369 // This is not a perfect match of error codes, as no operation is
370 // actually pending. However, returning 0 would be interpreted as
371 // a possible sign of EOF, which is also an inappropriate match.
372 return ERR_IO_PENDING;
373 }
374
375 // Known Issue: While only reading |requested| data is the more correct
376 // implementation, it has the downside of resulting in frequent reads:
377 // One read for the SSL record header (~5 bytes) and one read for the SSL
378 // record body. Rather than issuing these reads to the underlying socket
379 // (and constantly allocating new IOBuffers), a single Read() request to
380 // fill |transport_bio_| is issued. As long as an SSL client socket cannot
381 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
382 // traffic, this over-subscribed Read()ing will not cause issues.
383 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
384 if (!max_write)
385 return ERR_IO_PENDING;
386
387 recv_buffer_ = new IOBuffer(max_write);
388 int rv = transport_socket_->Read(
389 recv_buffer_.get(),
390 max_write,
391 base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete,
392 base::Unretained(this)));
393 if (rv == ERR_IO_PENDING) {
394 transport_recv_busy_ = true;
395 } else {
396 rv = TransportReadComplete(rv);
397 }
398 return rv;
399 }
400
401 void SSLServerSocketOpenSSL::BufferRecvComplete(int result) {
402 result = TransportReadComplete(result);
403 OnRecvComplete(result);
404 }
405
406 int SSLServerSocketOpenSSL::TransportReadComplete(int result) {
407 DCHECK(ERR_IO_PENDING != result);
408 if (result <= 0) {
409 DVLOG(1) << "TransportReadComplete result " << result;
410 // Received 0 (end of file) or an error. Either way, bubble it up to the
411 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
412 // relay up to the SSL socket client (i.e. via DoReadCallback).
413 if (result == 0)
414 transport_recv_eof_ = true;
415 (void)BIO_shutdown_wr(transport_bio_);
416 } else if (transport_write_error_ < 0) {
417 // Mirror transport write errors as read failures; transport_bio_ has been
418 // shut down by TransportWriteComplete, so the BIO_write will fail, failing
419 // the CHECK. http://crbug.com/335557.
420 result = transport_write_error_;
421 } else {
422 DCHECK(recv_buffer_.get());
423 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
424 // A write into a memory BIO should always succeed.
425 DCHECK_EQ(result, ret);
426 }
427 recv_buffer_ = NULL;
428 transport_recv_busy_ = false;
429 return result;
430 }
431
432 // Do as much network I/O as possible between the buffer and the
433 // transport socket. Return true if some I/O performed, false
434 // otherwise (error or ERR_IO_PENDING).
435 bool SSLServerSocketOpenSSL::DoTransportIO() {
436 bool network_moved = false;
437 int rv;
438 // Read and write as much data as possible. The loop is necessary because
439 // Write() may return synchronously.
440 do {
441 rv = BufferSend();
442 if (rv != ERR_IO_PENDING && rv != 0)
443 network_moved = true;
444 } while (rv > 0);
445 if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
446 network_moved = true;
447 return network_moved;
448 }
449
450 int SSLServerSocketOpenSSL::DoPayloadRead() {
451 DCHECK(user_read_buf_.get());
452 DCHECK_GT(user_read_buf_len_, 0);
453 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
454 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
455 if (rv >= 0)
456 return rv;
457 int ssl_error = SSL_get_error(ssl_, rv);
458 int net_error = MapOpenSSLError(ssl_error, err_tracer);
459 if (net_error != ERR_IO_PENDING) {
460 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
461 CreateNetLogSSLErrorCallback(net_error, ssl_error));
462 }
463 return net_error;
464 }
465
466 int SSLServerSocketOpenSSL::DoPayloadWrite() {
467 DCHECK(user_write_buf_.get());
468 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
469 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
470 if (rv >= 0)
471 return rv;
472 int ssl_error = SSL_get_error(ssl_, rv);
473 int net_error = MapOpenSSLError(ssl_error, err_tracer);
474 if (net_error != ERR_IO_PENDING) {
475 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
476 CreateNetLogSSLErrorCallback(net_error, ssl_error));
477 }
478 return net_error;
479 }
480
481 int SSLServerSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
482 int rv = last_io_result;
483 do {
484 // Default to STATE_NONE for next state.
485 // (This is a quirk carried over from the windows
486 // implementation. It makes reading the logs a bit harder.)
487 // State handlers can and often do call GotoState just
488 // to stay in the current state.
489 State state = next_handshake_state_;
490 GotoState(STATE_NONE);
491 switch (state) {
492 case STATE_HANDSHAKE:
493 rv = DoHandshake();
494 break;
495 case STATE_NONE:
496 default:
497 rv = ERR_UNEXPECTED;
498 LOG(DFATAL) << "unexpected state " << state;
499 break;
500 }
501
502 // Do the actual network I/O
503 bool network_moved = DoTransportIO();
504 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
505 // In general we exit the loop if rv is ERR_IO_PENDING. In this
506 // special case we keep looping even if rv is ERR_IO_PENDING because
507 // the transport IO may allow DoHandshake to make progress.
508 rv = OK; // This causes us to stay in the loop.
509 }
510 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
511 return rv;
512 }
513
514 int SSLServerSocketOpenSSL::DoReadLoop(int result) {
515 DCHECK(completed_handshake_);
516 DCHECK(next_handshake_state_ == STATE_NONE);
517
518 if (result < 0)
519 return result;
520
521 bool network_moved;
522 int rv;
523 do {
524 rv = DoPayloadRead();
525 network_moved = DoTransportIO();
526 } while (rv == ERR_IO_PENDING && network_moved);
527 return rv;
528 }
529
530 int SSLServerSocketOpenSSL::DoWriteLoop(int result) {
531 DCHECK(completed_handshake_);
532 DCHECK_EQ(next_handshake_state_, STATE_NONE);
533
534 if (result < 0)
535 return result;
536
537 bool network_moved;
538 int rv;
539 do {
540 rv = DoPayloadWrite();
541 network_moved = DoTransportIO();
542 } while (rv == ERR_IO_PENDING && network_moved);
543 return rv;
544 }
545
546 int SSLServerSocketOpenSSL::DoHandshake() {
547 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
548 int net_error = OK;
549 int rv = SSL_do_handshake(ssl_);
550
551 if (rv == 1) {
552 completed_handshake_ = true;
553 } else {
554 int ssl_error = SSL_get_error(ssl_, rv);
555 net_error = MapOpenSSLError(ssl_error, err_tracer);
556
557 // If not done, stay in this state
558 if (net_error == ERR_IO_PENDING) {
559 GotoState(STATE_HANDSHAKE);
560 } else {
561 LOG(ERROR) << "handshake failed; returned " << rv
562 << ", SSL error code " << ssl_error
563 << ", net_error " << net_error;
564 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
565 CreateNetLogSSLErrorCallback(net_error, ssl_error));
566 }
567 }
568 return net_error;
569 }
570
571 void SSLServerSocketOpenSSL::DoHandshakeCallback(int rv) {
572 DCHECK_NE(rv, ERR_IO_PENDING);
573 ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
574 }
575
576 void SSLServerSocketOpenSSL::DoReadCallback(int rv) {
577 DCHECK(rv != ERR_IO_PENDING);
578 DCHECK(!user_read_callback_.is_null());
579
580 user_read_buf_ = NULL;
581 user_read_buf_len_ = 0;
582 ResetAndReturn(&user_read_callback_).Run(rv);
583 }
584
585 void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
586 DCHECK(rv != ERR_IO_PENDING);
587 DCHECK(!user_write_callback_.is_null());
588
589 user_write_buf_ = NULL;
590 user_write_buf_len_ = 0;
591 ResetAndReturn(&user_write_callback_).Run(rv);
592 }
593
594 int SSLServerSocketOpenSSL::Init() {
595 DCHECK(!ssl_);
596 DCHECK(!transport_bio_);
597
598 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
599
600 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx(
601 // It support SSLv2, SSLv3, and TLSv1.
602 SSL_CTX_new(SSLv23_server_method()));
603 ssl_ = SSL_new(ssl_ctx.get());
604 if (!ssl_)
605 return ERR_UNEXPECTED;
606
607 BIO* ssl_bio = NULL;
608 // 0 => use default buffer sizes.
609 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
610 return ERR_UNEXPECTED;
611 DCHECK(ssl_bio);
612 DCHECK(transport_bio_);
613
614 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
615
616 // Set certificate and private key.
617 DCHECK(cert_->os_cert_handle());
618 if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) {
619 LOG(ERROR) << "Cannot set certificate.";
620 return ERR_UNEXPECTED;
621 }
622
623 DCHECK(key_->key());
624 if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) {
625 LOG(ERROR) << "Cannot set private key.";
626 return ERR_UNEXPECTED;
627 }
628
629 // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
630 // set everything we care about to an absolute value.
631 SslSetClearMask options;
632 options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
633 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
634 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);
635 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
636 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
637 options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);
638 bool tls1_1_enabled =
639 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 &&
640 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);
641 options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);
642 bool tls1_2_enabled =
643 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 &&
644 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);
645 options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);
646
647 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
648
649 SSL_set_options(ssl_, options.set_mask);
650 SSL_clear_options(ssl_, options.clear_mask);
651
652 // Same as above, this time for the SSL mode.
653 SslSetClearMask mode;
654
655 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
656
657 SSL_set_mode(ssl_, mode.set_mask);
658 SSL_clear_mode(ssl_, mode.clear_mask);
659
660 return OK;
26 } 661 }
27 662
28 } // namespace net 663 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698