| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // 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 | 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_nss.h" | 5 #include "net/socket/ssl_server_socket_nss.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <winsock2.h> | 8 #include <winsock2.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 CHECK(key_.get()); | 83 CHECK(key_.get()); |
| 84 } | 84 } |
| 85 | 85 |
| 86 SSLServerSocketNSS::~SSLServerSocketNSS() { | 86 SSLServerSocketNSS::~SSLServerSocketNSS() { |
| 87 if (nss_fd_ != NULL) { | 87 if (nss_fd_ != NULL) { |
| 88 PR_Close(nss_fd_); | 88 PR_Close(nss_fd_); |
| 89 nss_fd_ = NULL; | 89 nss_fd_ = NULL; |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 int SSLServerSocketNSS::Init() { | |
| 94 // Initialize the NSS SSL library in a threadsafe way. This also | |
| 95 // initializes the NSS base library. | |
| 96 EnsureNSSSSLInit(); | |
| 97 if (!NSS_IsInitialized()) | |
| 98 return ERR_UNEXPECTED; | |
| 99 #if !defined(OS_MACOSX) && !defined(OS_WIN) | |
| 100 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop | |
| 101 // by MessageLoopForIO::current(). | |
| 102 // X509Certificate::Verify() runs on a worker thread of CertVerifier. | |
| 103 EnsureOCSPInit(); | |
| 104 #endif | |
| 105 | |
| 106 return OK; | |
| 107 } | |
| 108 | |
| 109 int SSLServerSocketNSS::Accept(CompletionCallback* callback) { | 93 int SSLServerSocketNSS::Accept(CompletionCallback* callback) { |
| 110 net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL); | 94 net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL); |
| 111 | 95 |
| 112 int rv = Init(); | 96 int rv = Init(); |
| 113 if (rv != OK) { | 97 if (rv != OK) { |
| 114 LOG(ERROR) << "Failed to initialize NSS"; | 98 LOG(ERROR) << "Failed to initialize NSS"; |
| 115 net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL); | 99 net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL); |
| 116 return rv; | 100 return rv; |
| 117 } | 101 } |
| 118 | 102 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 | 160 |
| 177 if (rv == ERR_IO_PENDING) { | 161 if (rv == ERR_IO_PENDING) { |
| 178 user_write_callback_ = callback; | 162 user_write_callback_ = callback; |
| 179 } else { | 163 } else { |
| 180 user_write_buf_ = NULL; | 164 user_write_buf_ = NULL; |
| 181 user_write_buf_len_ = 0; | 165 user_write_buf_len_ = 0; |
| 182 } | 166 } |
| 183 return rv; | 167 return rv; |
| 184 } | 168 } |
| 185 | 169 |
| 186 // static | 170 bool SSLServerSocketNSS::SetReceiveBufferSize(int32 size) { |
| 187 // NSS calls this if an incoming certificate needs to be verified. | 171 return false; |
| 188 // Do nothing but return SECSuccess. | |
| 189 // This is called only in full handshake mode. | |
| 190 // Peer certificate is retrieved in HandshakeCallback() later, which is called | |
| 191 // in full handshake mode or in resumption handshake mode. | |
| 192 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg, | |
| 193 PRFileDesc* socket, | |
| 194 PRBool checksig, | |
| 195 PRBool is_server) { | |
| 196 // TODO(hclam): Implement. | |
| 197 // Tell NSS to not verify the certificate. | |
| 198 return SECSuccess; | |
| 199 } | 172 } |
| 200 | 173 |
| 201 // static | 174 bool SSLServerSocketNSS::SetSendBufferSize(int32 size) { |
| 202 // NSS calls this when handshake is completed. | 175 return false; |
| 203 // After the SSL handshake is finished we need to verify the certificate. | |
| 204 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, | |
| 205 void* arg) { | |
| 206 // TODO(hclam): Implement. | |
| 207 } | 176 } |
| 208 | 177 |
| 209 int SSLServerSocketNSS::InitializeSSLOptions() { | 178 int SSLServerSocketNSS::InitializeSSLOptions() { |
| 210 // Transport connected, now hook it up to nss | 179 // Transport connected, now hook it up to nss |
| 211 // TODO(port): specify rx and tx buffer sizes separately | 180 // TODO(port): specify rx and tx buffer sizes separately |
| 212 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 181 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); |
| 213 if (nss_fd_ == NULL) { | 182 if (nss_fd_ == NULL) { |
| 214 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. | 183 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. |
| 215 } | 184 } |
| 216 | 185 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 // Tell SSL we're a server; needed if not letting NSPR do socket I/O | 343 // Tell SSL we're a server; needed if not letting NSPR do socket I/O |
| 375 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE); | 344 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE); |
| 376 if (rv != SECSuccess) { | 345 if (rv != SECSuccess) { |
| 377 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", ""); | 346 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", ""); |
| 378 return ERR_UNEXPECTED; | 347 return ERR_UNEXPECTED; |
| 379 } | 348 } |
| 380 | 349 |
| 381 return OK; | 350 return OK; |
| 382 } | 351 } |
| 383 | 352 |
| 353 void SSLServerSocketNSS::OnSendComplete(int result) { |
| 354 if (next_handshake_state_ == STATE_HANDSHAKE) { |
| 355 // In handshake phase. |
| 356 OnHandshakeIOComplete(result); |
| 357 return; |
| 358 } |
| 359 |
| 360 if (!user_write_buf_ || !completed_handshake_) |
| 361 return; |
| 362 |
| 363 int rv = DoWriteLoop(result); |
| 364 if (rv != ERR_IO_PENDING) |
| 365 DoWriteCallback(rv); |
| 366 } |
| 367 |
| 368 void SSLServerSocketNSS::OnRecvComplete(int result) { |
| 369 if (next_handshake_state_ == STATE_HANDSHAKE) { |
| 370 // In handshake phase. |
| 371 OnHandshakeIOComplete(result); |
| 372 return; |
| 373 } |
| 374 |
| 375 // Network layer received some data, check if client requested to read |
| 376 // decrypted data. |
| 377 if (!user_read_buf_ || !completed_handshake_) |
| 378 return; |
| 379 |
| 380 int rv = DoReadLoop(result); |
| 381 if (rv != ERR_IO_PENDING) |
| 382 DoReadCallback(rv); |
| 383 } |
| 384 |
| 385 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) { |
| 386 int rv = DoHandshakeLoop(result); |
| 387 if (rv != ERR_IO_PENDING) { |
| 388 net_log_.EndEvent(net::NetLog::TYPE_SSL_ACCEPT, NULL); |
| 389 if (user_accept_callback_) |
| 390 DoAcceptCallback(rv); |
| 391 } |
| 392 } |
| 393 |
| 384 // Return 0 for EOF, | 394 // Return 0 for EOF, |
| 385 // > 0 for bytes transferred immediately, | 395 // > 0 for bytes transferred immediately, |
| 386 // < 0 for error (or the non-error ERR_IO_PENDING). | 396 // < 0 for error (or the non-error ERR_IO_PENDING). |
| 387 int SSLServerSocketNSS::BufferSend(void) { | 397 int SSLServerSocketNSS::BufferSend(void) { |
| 388 if (transport_send_busy_) | 398 if (transport_send_busy_) |
| 389 return ERR_IO_PENDING; | 399 return ERR_IO_PENDING; |
| 390 | 400 |
| 391 const char* buf1; | 401 const char* buf1; |
| 392 const char* buf2; | 402 const char* buf2; |
| 393 unsigned int len1, len2; | 403 unsigned int len1, len2; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 char *buf; | 456 char *buf; |
| 447 memio_GetReadParams(nss_bufs_, &buf); | 457 memio_GetReadParams(nss_bufs_, &buf); |
| 448 memcpy(buf, recv_buffer_->data(), result); | 458 memcpy(buf, recv_buffer_->data(), result); |
| 449 } | 459 } |
| 450 recv_buffer_ = NULL; | 460 recv_buffer_ = NULL; |
| 451 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result)); | 461 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result)); |
| 452 transport_recv_busy_ = false; | 462 transport_recv_busy_ = false; |
| 453 OnRecvComplete(result); | 463 OnRecvComplete(result); |
| 454 } | 464 } |
| 455 | 465 |
| 456 void SSLServerSocketNSS::OnSendComplete(int result) { | |
| 457 if (next_handshake_state_ == STATE_HANDSHAKE) { | |
| 458 // In handshake phase. | |
| 459 OnHandshakeIOComplete(result); | |
| 460 return; | |
| 461 } | |
| 462 | |
| 463 if (!user_write_buf_ || !completed_handshake_) | |
| 464 return; | |
| 465 | |
| 466 int rv = DoWriteLoop(result); | |
| 467 if (rv != ERR_IO_PENDING) | |
| 468 DoWriteCallback(rv); | |
| 469 } | |
| 470 | |
| 471 void SSLServerSocketNSS::OnRecvComplete(int result) { | |
| 472 if (next_handshake_state_ == STATE_HANDSHAKE) { | |
| 473 // In handshake phase. | |
| 474 OnHandshakeIOComplete(result); | |
| 475 return; | |
| 476 } | |
| 477 | |
| 478 // Network layer received some data, check if client requested to read | |
| 479 // decrypted data. | |
| 480 if (!user_read_buf_ || !completed_handshake_) | |
| 481 return; | |
| 482 | |
| 483 int rv = DoReadLoop(result); | |
| 484 if (rv != ERR_IO_PENDING) | |
| 485 DoReadCallback(rv); | |
| 486 } | |
| 487 | |
| 488 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) { | |
| 489 int rv = DoHandshakeLoop(result); | |
| 490 if (rv != ERR_IO_PENDING) { | |
| 491 net_log_.EndEvent(net::NetLog::TYPE_SSL_ACCEPT, NULL); | |
| 492 if (user_accept_callback_) | |
| 493 DoAcceptCallback(rv); | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 void SSLServerSocketNSS::DoAcceptCallback(int rv) { | |
| 498 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 499 | |
| 500 CompletionCallback* c = user_accept_callback_; | |
| 501 user_accept_callback_ = NULL; | |
| 502 c->Run(rv > OK ? OK : rv); | |
| 503 } | |
| 504 | |
| 505 void SSLServerSocketNSS::DoReadCallback(int rv) { | |
| 506 DCHECK(rv != ERR_IO_PENDING); | |
| 507 DCHECK(user_read_callback_); | |
| 508 | |
| 509 // Since Run may result in Read being called, clear |user_read_callback_| | |
| 510 // up front. | |
| 511 CompletionCallback* c = user_read_callback_; | |
| 512 user_read_callback_ = NULL; | |
| 513 user_read_buf_ = NULL; | |
| 514 user_read_buf_len_ = 0; | |
| 515 c->Run(rv); | |
| 516 } | |
| 517 | |
| 518 void SSLServerSocketNSS::DoWriteCallback(int rv) { | |
| 519 DCHECK(rv != ERR_IO_PENDING); | |
| 520 DCHECK(user_write_callback_); | |
| 521 | |
| 522 // Since Run may result in Write being called, clear |user_write_callback_| | |
| 523 // up front. | |
| 524 CompletionCallback* c = user_write_callback_; | |
| 525 user_write_callback_ = NULL; | |
| 526 user_write_buf_ = NULL; | |
| 527 user_write_buf_len_ = 0; | |
| 528 c->Run(rv); | |
| 529 } | |
| 530 | |
| 531 // Do network I/O between the given buffer and the given socket. | 466 // Do network I/O between the given buffer and the given socket. |
| 532 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) | 467 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) |
| 533 bool SSLServerSocketNSS::DoTransportIO() { | 468 bool SSLServerSocketNSS::DoTransportIO() { |
| 534 bool network_moved = false; | 469 bool network_moved = false; |
| 535 if (nss_bufs_ != NULL) { | 470 if (nss_bufs_ != NULL) { |
| 536 int nsent = BufferSend(); | 471 int nsent = BufferSend(); |
| 537 int nreceived = BufferRecv(); | 472 int nreceived = BufferRecv(); |
| 538 network_moved = (nsent > 0 || nreceived >= 0); | 473 network_moved = (nsent > 0 || nreceived >= 0); |
| 539 } | 474 } |
| 540 return network_moved; | 475 return network_moved; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 LOG(ERROR) << "handshake failed; NSS error code " << prerr | 602 LOG(ERROR) << "handshake failed; NSS error code " << prerr |
| 668 << ", net_error " << net_error; | 603 << ", net_error " << net_error; |
| 669 net_log_.AddEvent( | 604 net_log_.AddEvent( |
| 670 NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 605 NetLog::TYPE_SSL_HANDSHAKE_ERROR, |
| 671 make_scoped_refptr(new SSLErrorParams(net_error, prerr))); | 606 make_scoped_refptr(new SSLErrorParams(net_error, prerr))); |
| 672 } | 607 } |
| 673 } | 608 } |
| 674 return net_error; | 609 return net_error; |
| 675 } | 610 } |
| 676 | 611 |
| 612 void SSLServerSocketNSS::DoAcceptCallback(int rv) { |
| 613 DCHECK_NE(rv, ERR_IO_PENDING); |
| 614 |
| 615 CompletionCallback* c = user_accept_callback_; |
| 616 user_accept_callback_ = NULL; |
| 617 c->Run(rv > OK ? OK : rv); |
| 618 } |
| 619 |
| 620 void SSLServerSocketNSS::DoReadCallback(int rv) { |
| 621 DCHECK(rv != ERR_IO_PENDING); |
| 622 DCHECK(user_read_callback_); |
| 623 |
| 624 // Since Run may result in Read being called, clear |user_read_callback_| |
| 625 // up front. |
| 626 CompletionCallback* c = user_read_callback_; |
| 627 user_read_callback_ = NULL; |
| 628 user_read_buf_ = NULL; |
| 629 user_read_buf_len_ = 0; |
| 630 c->Run(rv); |
| 631 } |
| 632 |
| 633 void SSLServerSocketNSS::DoWriteCallback(int rv) { |
| 634 DCHECK(rv != ERR_IO_PENDING); |
| 635 DCHECK(user_write_callback_); |
| 636 |
| 637 // Since Run may result in Write being called, clear |user_write_callback_| |
| 638 // up front. |
| 639 CompletionCallback* c = user_write_callback_; |
| 640 user_write_callback_ = NULL; |
| 641 user_write_buf_ = NULL; |
| 642 user_write_buf_len_ = 0; |
| 643 c->Run(rv); |
| 644 } |
| 645 |
| 646 // static |
| 647 // NSS calls this if an incoming certificate needs to be verified. |
| 648 // Do nothing but return SECSuccess. |
| 649 // This is called only in full handshake mode. |
| 650 // Peer certificate is retrieved in HandshakeCallback() later, which is called |
| 651 // in full handshake mode or in resumption handshake mode. |
| 652 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg, |
| 653 PRFileDesc* socket, |
| 654 PRBool checksig, |
| 655 PRBool is_server) { |
| 656 // TODO(hclam): Implement. |
| 657 // Tell NSS to not verify the certificate. |
| 658 return SECSuccess; |
| 659 } |
| 660 |
| 661 // static |
| 662 // NSS calls this when handshake is completed. |
| 663 // After the SSL handshake is finished we need to verify the certificate. |
| 664 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket, |
| 665 void* arg) { |
| 666 // TODO(hclam): Implement. |
| 667 } |
| 668 |
| 669 int SSLServerSocketNSS::Init() { |
| 670 // Initialize the NSS SSL library in a threadsafe way. This also |
| 671 // initializes the NSS base library. |
| 672 EnsureNSSSSLInit(); |
| 673 if (!NSS_IsInitialized()) |
| 674 return ERR_UNEXPECTED; |
| 675 #if !defined(OS_MACOSX) && !defined(OS_WIN) |
| 676 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop |
| 677 // by MessageLoopForIO::current(). |
| 678 // X509Certificate::Verify() runs on a worker thread of CertVerifier. |
| 679 EnsureOCSPInit(); |
| 680 #endif |
| 681 |
| 682 return OK; |
| 683 } |
| 684 |
| 677 } // namespace net | 685 } // namespace net |
| OLD | NEW |