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

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

Powered by Google App Engine
This is Rietveld 408576698