OLD | NEW |
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): Find out if we should check transport_socket_->IsConnected() |
| 194 // as well. |
| 195 return completed_handshake_; |
| 196 } |
| 197 |
| 198 bool SSLServerSocketOpenSSL::IsConnectedAndIdle() const { |
| 199 return completed_handshake_ && transport_socket_->IsConnectedAndIdle(); |
| 200 } |
| 201 |
| 202 int SSLServerSocketOpenSSL::GetPeerAddress(IPEndPoint* address) const { |
| 203 if (!IsConnected()) |
| 204 return ERR_SOCKET_NOT_CONNECTED; |
| 205 return transport_socket_->GetPeerAddress(address); |
| 206 } |
| 207 |
| 208 int SSLServerSocketOpenSSL::GetLocalAddress(IPEndPoint* address) const { |
| 209 if (!IsConnected()) |
| 210 return ERR_SOCKET_NOT_CONNECTED; |
| 211 return transport_socket_->GetLocalAddress(address); |
| 212 } |
| 213 |
| 214 const BoundNetLog& SSLServerSocketOpenSSL::NetLog() const { |
| 215 return net_log_; |
| 216 } |
| 217 |
| 218 void SSLServerSocketOpenSSL::SetSubresourceSpeculation() { |
| 219 transport_socket_->SetSubresourceSpeculation(); |
| 220 } |
| 221 |
| 222 void SSLServerSocketOpenSSL::SetOmniboxSpeculation() { |
| 223 transport_socket_->SetOmniboxSpeculation(); |
| 224 } |
| 225 |
| 226 bool SSLServerSocketOpenSSL::WasEverUsed() const { |
| 227 return transport_socket_->WasEverUsed(); |
| 228 } |
| 229 |
| 230 bool SSLServerSocketOpenSSL::UsingTCPFastOpen() const { |
| 231 return transport_socket_->UsingTCPFastOpen(); |
| 232 } |
| 233 |
| 234 bool SSLServerSocketOpenSSL::WasNpnNegotiated() const { |
| 235 NOTIMPLEMENTED(); |
| 236 return false; |
| 237 } |
| 238 |
| 239 NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const { |
| 240 // NPN is not supported by this class. |
| 241 return kProtoUnknown; |
| 242 } |
| 243 |
| 244 bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { |
| 245 NOTIMPLEMENTED(); |
| 246 return false; |
| 247 } |
| 248 |
| 249 void SSLServerSocketOpenSSL::OnSendComplete(int result) { |
| 250 if (next_handshake_state_ == STATE_HANDSHAKE) { |
| 251 // In handshake phase. |
| 252 OnHandshakeIOComplete(result); |
| 253 return; |
| 254 } |
| 255 |
| 256 // TODO(byungchul): This state machine is not correct. Copy the state machine |
| 257 // of SSLClientSocketOpenSSL::OnSendComplete() which handles it better. |
| 258 if (!completed_handshake_) |
| 259 return; |
| 260 |
| 261 if (user_write_buf_.get()) { |
| 262 int rv = DoWriteLoop(result); |
| 263 if (rv != ERR_IO_PENDING) |
| 264 DoWriteCallback(rv); |
| 265 } else { |
| 266 // Ensure that any queued ciphertext is flushed. |
| 267 DoTransportIO(); |
| 268 } |
| 269 } |
| 270 |
| 271 void SSLServerSocketOpenSSL::OnRecvComplete(int result) { |
| 272 if (next_handshake_state_ == STATE_HANDSHAKE) { |
| 273 // In handshake phase. |
| 274 OnHandshakeIOComplete(result); |
| 275 return; |
| 276 } |
| 277 |
| 278 // Network layer received some data, check if client requested to read |
| 279 // decrypted data. |
| 280 if (!user_read_buf_.get() || !completed_handshake_) |
| 281 return; |
| 282 |
| 283 int rv = DoReadLoop(result); |
| 284 if (rv != ERR_IO_PENDING) |
| 285 DoReadCallback(rv); |
| 286 } |
| 287 |
| 288 void SSLServerSocketOpenSSL::OnHandshakeIOComplete(int result) { |
| 289 int rv = DoHandshakeLoop(result); |
| 290 if (rv == ERR_IO_PENDING) |
| 291 return; |
| 292 |
| 293 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv); |
| 294 if (!user_handshake_callback_.is_null()) |
| 295 DoHandshakeCallback(rv); |
| 296 } |
| 297 |
| 298 // Return 0 for EOF, |
| 299 // > 0 for bytes transferred immediately, |
| 300 // < 0 for error (or the non-error ERR_IO_PENDING). |
| 301 int SSLServerSocketOpenSSL::BufferSend() { |
| 302 if (transport_send_busy_) |
| 303 return ERR_IO_PENDING; |
| 304 |
| 305 if (!send_buffer_.get()) { |
| 306 // Get a fresh send buffer out of the send BIO. |
| 307 size_t max_read = BIO_ctrl_pending(transport_bio_); |
| 308 if (!max_read) |
| 309 return 0; // Nothing pending in the OpenSSL write BIO. |
| 310 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); |
| 311 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); |
| 312 DCHECK_GT(read_bytes, 0); |
| 313 CHECK_EQ(static_cast<int>(max_read), read_bytes); |
| 314 } |
| 315 |
| 316 int rv = transport_socket_->Write( |
| 317 send_buffer_.get(), |
| 318 send_buffer_->BytesRemaining(), |
| 319 base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete, |
| 320 base::Unretained(this))); |
| 321 if (rv == ERR_IO_PENDING) { |
| 322 transport_send_busy_ = true; |
| 323 } else { |
| 324 TransportWriteComplete(rv); |
| 325 } |
| 326 return rv; |
| 327 } |
| 328 |
| 329 void SSLServerSocketOpenSSL::BufferSendComplete(int result) { |
| 330 transport_send_busy_ = false; |
| 331 TransportWriteComplete(result); |
| 332 OnSendComplete(result); |
| 333 } |
| 334 |
| 335 void SSLServerSocketOpenSSL::TransportWriteComplete(int result) { |
| 336 DCHECK(ERR_IO_PENDING != result); |
| 337 if (result < 0) { |
| 338 // Got a socket write error; close the BIO to indicate this upward. |
| 339 // |
| 340 // TODO(davidben): The value of |result| gets lost. Feed the error back into |
| 341 // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with |
| 342 // BIO_set_callback. |
| 343 DVLOG(1) << "TransportWriteComplete error " << result; |
| 344 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_)); |
| 345 |
| 346 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads |
| 347 // from the socket after a write error. |
| 348 // |
| 349 // TODO(davidben): Avoid having read and write ends interact this way. |
| 350 transport_write_error_ = result; |
| 351 (void)BIO_shutdown_wr(transport_bio_); |
| 352 send_buffer_ = NULL; |
| 353 } else { |
| 354 DCHECK(send_buffer_.get()); |
| 355 send_buffer_->DidConsume(result); |
| 356 DCHECK_GE(send_buffer_->BytesRemaining(), 0); |
| 357 if (send_buffer_->BytesRemaining() <= 0) |
| 358 send_buffer_ = NULL; |
| 359 } |
| 360 } |
| 361 |
| 362 int SSLServerSocketOpenSSL::BufferRecv() { |
| 363 if (transport_recv_busy_) |
| 364 return ERR_IO_PENDING; |
| 365 |
| 366 // Determine how much was requested from |transport_bio_| that was not |
| 367 // actually available. |
| 368 size_t requested = BIO_ctrl_get_read_request(transport_bio_); |
| 369 if (requested == 0) { |
| 370 // This is not a perfect match of error codes, as no operation is |
| 371 // actually pending. However, returning 0 would be interpreted as |
| 372 // a possible sign of EOF, which is also an inappropriate match. |
| 373 return ERR_IO_PENDING; |
| 374 } |
| 375 |
| 376 // Known Issue: While only reading |requested| data is the more correct |
| 377 // implementation, it has the downside of resulting in frequent reads: |
| 378 // One read for the SSL record header (~5 bytes) and one read for the SSL |
| 379 // record body. Rather than issuing these reads to the underlying socket |
| 380 // (and constantly allocating new IOBuffers), a single Read() request to |
| 381 // fill |transport_bio_| is issued. As long as an SSL client socket cannot |
| 382 // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL |
| 383 // traffic, this over-subscribed Read()ing will not cause issues. |
| 384 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); |
| 385 if (!max_write) |
| 386 return ERR_IO_PENDING; |
| 387 |
| 388 recv_buffer_ = new IOBuffer(max_write); |
| 389 int rv = transport_socket_->Read( |
| 390 recv_buffer_.get(), |
| 391 max_write, |
| 392 base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete, |
| 393 base::Unretained(this))); |
| 394 if (rv == ERR_IO_PENDING) { |
| 395 transport_recv_busy_ = true; |
| 396 } else { |
| 397 rv = TransportReadComplete(rv); |
| 398 } |
| 399 return rv; |
| 400 } |
| 401 |
| 402 void SSLServerSocketOpenSSL::BufferRecvComplete(int result) { |
| 403 result = TransportReadComplete(result); |
| 404 OnRecvComplete(result); |
| 405 } |
| 406 |
| 407 int SSLServerSocketOpenSSL::TransportReadComplete(int result) { |
| 408 DCHECK(ERR_IO_PENDING != result); |
| 409 if (result <= 0) { |
| 410 DVLOG(1) << "TransportReadComplete result " << result; |
| 411 // Received 0 (end of file) or an error. Either way, bubble it up to the |
| 412 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to |
| 413 // relay up to the SSL socket client (i.e. via DoReadCallback). |
| 414 if (result == 0) |
| 415 transport_recv_eof_ = true; |
| 416 (void)BIO_shutdown_wr(transport_bio_); |
| 417 } else if (transport_write_error_ < 0) { |
| 418 // Mirror transport write errors as read failures; transport_bio_ has been |
| 419 // shut down by TransportWriteComplete, so the BIO_write will fail, failing |
| 420 // the CHECK. http://crbug.com/335557. |
| 421 result = transport_write_error_; |
| 422 } else { |
| 423 DCHECK(recv_buffer_.get()); |
| 424 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); |
| 425 // A write into a memory BIO should always succeed. |
| 426 DCHECK_EQ(result, ret); |
| 427 } |
| 428 recv_buffer_ = NULL; |
| 429 transport_recv_busy_ = false; |
| 430 return result; |
| 431 } |
| 432 |
| 433 // Do as much network I/O as possible between the buffer and the |
| 434 // transport socket. Return true if some I/O performed, false |
| 435 // otherwise (error or ERR_IO_PENDING). |
| 436 bool SSLServerSocketOpenSSL::DoTransportIO() { |
| 437 bool network_moved = false; |
| 438 int rv; |
| 439 // Read and write as much data as possible. The loop is necessary because |
| 440 // Write() may return synchronously. |
| 441 do { |
| 442 rv = BufferSend(); |
| 443 if (rv != ERR_IO_PENDING && rv != 0) |
| 444 network_moved = true; |
| 445 } while (rv > 0); |
| 446 if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING) |
| 447 network_moved = true; |
| 448 return network_moved; |
| 449 } |
| 450 |
| 451 int SSLServerSocketOpenSSL::DoPayloadRead() { |
| 452 DCHECK(user_read_buf_.get()); |
| 453 DCHECK_GT(user_read_buf_len_, 0); |
| 454 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 455 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_); |
| 456 if (rv >= 0) |
| 457 return rv; |
| 458 int ssl_error = SSL_get_error(ssl_, rv); |
| 459 int net_error = MapOpenSSLError(ssl_error, err_tracer); |
| 460 if (net_error != ERR_IO_PENDING) { |
| 461 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, |
| 462 CreateNetLogSSLErrorCallback(net_error, ssl_error)); |
| 463 } |
| 464 return net_error; |
| 465 } |
| 466 |
| 467 int SSLServerSocketOpenSSL::DoPayloadWrite() { |
| 468 DCHECK(user_write_buf_.get()); |
| 469 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 470 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
| 471 if (rv >= 0) |
| 472 return rv; |
| 473 int ssl_error = SSL_get_error(ssl_, rv); |
| 474 int net_error = MapOpenSSLError(ssl_error, err_tracer); |
| 475 if (net_error != ERR_IO_PENDING) { |
| 476 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, |
| 477 CreateNetLogSSLErrorCallback(net_error, ssl_error)); |
| 478 } |
| 479 return net_error; |
| 480 } |
| 481 |
| 482 int SSLServerSocketOpenSSL::DoHandshakeLoop(int last_io_result) { |
| 483 int rv = last_io_result; |
| 484 do { |
| 485 // Default to STATE_NONE for next state. |
| 486 // (This is a quirk carried over from the windows |
| 487 // implementation. It makes reading the logs a bit harder.) |
| 488 // State handlers can and often do call GotoState just |
| 489 // to stay in the current state. |
| 490 State state = next_handshake_state_; |
| 491 GotoState(STATE_NONE); |
| 492 switch (state) { |
| 493 case STATE_HANDSHAKE: |
| 494 rv = DoHandshake(); |
| 495 break; |
| 496 case STATE_NONE: |
| 497 default: |
| 498 rv = ERR_UNEXPECTED; |
| 499 LOG(DFATAL) << "unexpected state " << state; |
| 500 break; |
| 501 } |
| 502 |
| 503 // Do the actual network I/O |
| 504 bool network_moved = DoTransportIO(); |
| 505 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) { |
| 506 // In general we exit the loop if rv is ERR_IO_PENDING. In this |
| 507 // special case we keep looping even if rv is ERR_IO_PENDING because |
| 508 // the transport IO may allow DoHandshake to make progress. |
| 509 rv = OK; // This causes us to stay in the loop. |
| 510 } |
| 511 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); |
| 512 return rv; |
| 513 } |
| 514 |
| 515 int SSLServerSocketOpenSSL::DoReadLoop(int result) { |
| 516 DCHECK(completed_handshake_); |
| 517 DCHECK(next_handshake_state_ == STATE_NONE); |
| 518 |
| 519 if (result < 0) |
| 520 return result; |
| 521 |
| 522 bool network_moved; |
| 523 int rv; |
| 524 do { |
| 525 rv = DoPayloadRead(); |
| 526 network_moved = DoTransportIO(); |
| 527 } while (rv == ERR_IO_PENDING && network_moved); |
| 528 return rv; |
| 529 } |
| 530 |
| 531 int SSLServerSocketOpenSSL::DoWriteLoop(int result) { |
| 532 DCHECK(completed_handshake_); |
| 533 DCHECK_EQ(next_handshake_state_, STATE_NONE); |
| 534 |
| 535 if (result < 0) |
| 536 return result; |
| 537 |
| 538 bool network_moved; |
| 539 int rv; |
| 540 do { |
| 541 rv = DoPayloadWrite(); |
| 542 network_moved = DoTransportIO(); |
| 543 } while (rv == ERR_IO_PENDING && network_moved); |
| 544 return rv; |
| 545 } |
| 546 |
| 547 int SSLServerSocketOpenSSL::DoHandshake() { |
| 548 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 549 int net_error = OK; |
| 550 int rv = SSL_do_handshake(ssl_); |
| 551 |
| 552 if (rv == 1) { |
| 553 completed_handshake_ = true; |
| 554 } else { |
| 555 int ssl_error = SSL_get_error(ssl_, rv); |
| 556 net_error = MapOpenSSLError(ssl_error, err_tracer); |
| 557 |
| 558 // If not done, stay in this state |
| 559 if (net_error == ERR_IO_PENDING) { |
| 560 GotoState(STATE_HANDSHAKE); |
| 561 } else { |
| 562 LOG(ERROR) << "handshake failed; returned " << rv |
| 563 << ", SSL error code " << ssl_error |
| 564 << ", net_error " << net_error; |
| 565 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 566 CreateNetLogSSLErrorCallback(net_error, ssl_error)); |
| 567 } |
| 568 } |
| 569 return net_error; |
| 570 } |
| 571 |
| 572 void SSLServerSocketOpenSSL::DoHandshakeCallback(int rv) { |
| 573 DCHECK_NE(rv, ERR_IO_PENDING); |
| 574 ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv); |
| 575 } |
| 576 |
| 577 void SSLServerSocketOpenSSL::DoReadCallback(int rv) { |
| 578 DCHECK(rv != ERR_IO_PENDING); |
| 579 DCHECK(!user_read_callback_.is_null()); |
| 580 |
| 581 user_read_buf_ = NULL; |
| 582 user_read_buf_len_ = 0; |
| 583 ResetAndReturn(&user_read_callback_).Run(rv); |
| 584 } |
| 585 |
| 586 void SSLServerSocketOpenSSL::DoWriteCallback(int rv) { |
| 587 DCHECK(rv != ERR_IO_PENDING); |
| 588 DCHECK(!user_write_callback_.is_null()); |
| 589 |
| 590 user_write_buf_ = NULL; |
| 591 user_write_buf_len_ = 0; |
| 592 ResetAndReturn(&user_write_callback_).Run(rv); |
| 593 } |
| 594 |
| 595 int SSLServerSocketOpenSSL::Init() { |
| 596 DCHECK(!ssl_); |
| 597 DCHECK(!transport_bio_); |
| 598 |
| 599 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 600 |
| 601 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx( |
| 602 // It support SSLv2, SSLv3, and TLSv1. |
| 603 SSL_CTX_new(SSLv23_server_method())); |
| 604 ssl_ = SSL_new(ssl_ctx.get()); |
| 605 if (!ssl_) |
| 606 return ERR_UNEXPECTED; |
| 607 |
| 608 BIO* ssl_bio = NULL; |
| 609 // 0 => use default buffer sizes. |
| 610 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
| 611 return ERR_UNEXPECTED; |
| 612 DCHECK(ssl_bio); |
| 613 DCHECK(transport_bio_); |
| 614 |
| 615 SSL_set_bio(ssl_, ssl_bio, ssl_bio); |
| 616 |
| 617 // Set certificate and private key. |
| 618 DCHECK(cert_->os_cert_handle()); |
| 619 if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) { |
| 620 LOG(ERROR) << "Cannot set certificate."; |
| 621 return ERR_UNEXPECTED; |
| 622 } |
| 623 |
| 624 DCHECK(key_->key()); |
| 625 if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) { |
| 626 LOG(ERROR) << "Cannot set private key."; |
| 627 return ERR_UNEXPECTED; |
| 628 } |
| 629 |
| 630 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, |
| 631 // set everything we care about to an absolute value. |
| 632 SslSetClearMask options; |
| 633 options.ConfigureFlag(SSL_OP_NO_SSLv2, true); |
| 634 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); |
| 635 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); |
| 636 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 && |
| 637 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1); |
| 638 options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled); |
| 639 bool tls1_1_enabled = |
| 640 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 && |
| 641 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1); |
| 642 options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled); |
| 643 bool tls1_2_enabled = |
| 644 (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 && |
| 645 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2); |
| 646 options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled); |
| 647 |
| 648 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); |
| 649 |
| 650 SSL_set_options(ssl_, options.set_mask); |
| 651 SSL_clear_options(ssl_, options.clear_mask); |
| 652 |
| 653 // Same as above, this time for the SSL mode. |
| 654 SslSetClearMask mode; |
| 655 |
| 656 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); |
| 657 |
| 658 SSL_set_mode(ssl_, mode.set_mask); |
| 659 SSL_clear_mode(ssl_, mode.clear_mask); |
| 660 |
| 661 return OK; |
26 } | 662 } |
27 | 663 |
28 } // namespace net | 664 } // namespace net |
OLD | NEW |