OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/base/ssl_client_socket_nss.h" | 5 #include "net/base/ssl_client_socket_nss.h" |
6 | 6 |
7 #include <nspr.h> | 7 #include <nspr.h> |
8 #include <nss.h> | 8 #include <nss.h> |
9 #include <secerr.h> | 9 #include <secerr.h> |
10 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 | 10 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 : | 98 : |
99 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), | 99 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), |
100 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), | 100 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), |
101 transport_send_busy_(false), | 101 transport_send_busy_(false), |
102 transport_recv_busy_(false), | 102 transport_recv_busy_(false), |
103 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), | 103 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), |
104 transport_(transport_socket), | 104 transport_(transport_socket), |
105 hostname_(hostname), | 105 hostname_(hostname), |
106 ssl_config_(ssl_config), | 106 ssl_config_(ssl_config), |
107 user_callback_(NULL), | 107 user_callback_(NULL), |
108 user_buf_(NULL), | |
109 user_buf_len_(0), | 108 user_buf_len_(0), |
110 server_cert_error_(0), | 109 server_cert_error_(0), |
111 completed_handshake_(false), | 110 completed_handshake_(false), |
112 next_state_(STATE_NONE), | 111 next_state_(STATE_NONE), |
113 nss_fd_(NULL), | 112 nss_fd_(NULL), |
114 nss_bufs_(NULL) { | 113 nss_bufs_(NULL) { |
115 EnterFunction(""); | 114 EnterFunction(""); |
116 } | 115 } |
117 | 116 |
118 SSLClientSocketNSS::~SSLClientSocketNSS() { | 117 SSLClientSocketNSS::~SSLClientSocketNSS() { |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 // alert message from the server, and return false in that case. Although | 309 // alert message from the server, and return false in that case. Although |
311 // the close_notify alert message means EOF in the SSL layer, it is just | 310 // the close_notify alert message means EOF in the SSL layer, it is just |
312 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() | 311 // bytes to the transport layer below, so transport_->IsConnectedAndIdle() |
313 // returns the desired false when we receive close_notify. | 312 // returns the desired false when we receive close_notify. |
314 EnterFunction(""); | 313 EnterFunction(""); |
315 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); | 314 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); |
316 LeaveFunction(""); | 315 LeaveFunction(""); |
317 return ret; | 316 return ret; |
318 } | 317 } |
319 | 318 |
320 int SSLClientSocketNSS::Read(char* buf, int buf_len, | 319 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, |
321 CompletionCallback* callback) { | 320 CompletionCallback* callback) { |
322 EnterFunction(buf_len); | 321 EnterFunction(buf_len); |
323 DCHECK(completed_handshake_); | 322 DCHECK(completed_handshake_); |
324 DCHECK(next_state_ == STATE_NONE); | 323 DCHECK(next_state_ == STATE_NONE); |
325 DCHECK(!user_callback_); | 324 DCHECK(!user_callback_); |
326 DCHECK(!user_buf_); | 325 DCHECK(!user_buf_); |
327 | 326 |
328 user_buf_ = buf; | 327 user_buf_ = buf; |
329 user_buf_len_ = buf_len; | 328 user_buf_len_ = buf_len; |
330 | 329 |
331 GotoState(STATE_PAYLOAD_READ); | 330 GotoState(STATE_PAYLOAD_READ); |
332 int rv = DoLoop(OK); | 331 int rv = DoLoop(OK); |
333 if (rv == ERR_IO_PENDING) | 332 if (rv == ERR_IO_PENDING) |
334 user_callback_ = callback; | 333 user_callback_ = callback; |
335 LeaveFunction(rv); | 334 LeaveFunction(rv); |
336 return rv; | 335 return rv; |
337 } | 336 } |
338 | 337 |
339 int SSLClientSocketNSS::Write(const char* buf, int buf_len, | 338 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, |
340 CompletionCallback* callback) { | 339 CompletionCallback* callback) { |
341 EnterFunction(buf_len); | 340 EnterFunction(buf_len); |
342 DCHECK(completed_handshake_); | 341 DCHECK(completed_handshake_); |
343 DCHECK(next_state_ == STATE_NONE); | 342 DCHECK(next_state_ == STATE_NONE); |
344 DCHECK(!user_callback_); | 343 DCHECK(!user_callback_); |
345 DCHECK(!user_buf_); | 344 DCHECK(!user_buf_); |
346 | 345 |
347 user_buf_ = const_cast<char*>(buf); | 346 user_buf_ = buf; |
348 user_buf_len_ = buf_len; | 347 user_buf_len_ = buf_len; |
349 | 348 |
350 GotoState(STATE_PAYLOAD_WRITE); | 349 GotoState(STATE_PAYLOAD_WRITE); |
351 int rv = DoLoop(OK); | 350 int rv = DoLoop(OK); |
352 if (rv == ERR_IO_PENDING) | 351 if (rv == ERR_IO_PENDING) |
353 user_callback_ = callback; | 352 user_callback_ = callback; |
354 LeaveFunction(rv); | 353 LeaveFunction(rv); |
355 return rv; | 354 return rv; |
356 } | 355 } |
357 | 356 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 } | 397 } |
399 | 398 |
400 void SSLClientSocketNSS::DoCallback(int rv) { | 399 void SSLClientSocketNSS::DoCallback(int rv) { |
401 EnterFunction(rv); | 400 EnterFunction(rv); |
402 DCHECK(rv != ERR_IO_PENDING); | 401 DCHECK(rv != ERR_IO_PENDING); |
403 DCHECK(user_callback_); | 402 DCHECK(user_callback_); |
404 | 403 |
405 // since Run may result in Read being called, clear user_callback_ up front. | 404 // since Run may result in Read being called, clear user_callback_ up front. |
406 CompletionCallback* c = user_callback_; | 405 CompletionCallback* c = user_callback_; |
407 user_callback_ = NULL; | 406 user_callback_ = NULL; |
| 407 user_buf_ = NULL; |
408 c->Run(rv); | 408 c->Run(rv); |
409 LeaveFunction(""); | 409 LeaveFunction(""); |
410 } | 410 } |
411 | 411 |
412 void SSLClientSocketNSS::OnIOComplete(int result) { | 412 void SSLClientSocketNSS::OnIOComplete(int result) { |
413 EnterFunction(result); | 413 EnterFunction(result); |
414 int rv = DoLoop(result); | 414 int rv = DoLoop(result); |
415 if (rv != ERR_IO_PENDING && user_callback_ != NULL) | 415 if (rv != ERR_IO_PENDING && user_callback_ != NULL) |
416 DoCallback(rv); | 416 DoCallback(rv); |
417 LeaveFunction(""); | 417 LeaveFunction(""); |
418 } | 418 } |
419 | 419 |
420 // Map a Chromium net error code to an NSS error code | 420 // Map a Chromium net error code to an NSS error code |
421 // See _MD_unix_map_default_error in the NSS source | 421 // See _MD_unix_map_default_error in the NSS source |
422 // tree for inspiration. | 422 // tree for inspiration. |
423 static PRErrorCode MapErrorToNSS(int result) { | 423 static PRErrorCode MapErrorToNSS(int result) { |
424 if (result >=0) | 424 if (result >=0) |
425 return result; | 425 return result; |
426 // TODO(port): add real table | 426 // TODO(port): add real table |
427 LOG(ERROR) << "MapErrorToNSS " << result; | 427 LOG(ERROR) << "MapErrorToNSS " << result; |
428 return PR_UNKNOWN_ERROR; | 428 return PR_UNKNOWN_ERROR; |
429 } | 429 } |
430 | 430 |
431 /* | 431 // Do network I/O between the given buffer and the given socket. |
432 * Do network I/O between the given buffer and the given socket. | 432 // Return 0 for EOF, |
433 * Return 0 for EOF, | 433 // > 0 for bytes transferred immediately, |
434 * > 0 for bytes transferred immediately, | 434 // < 0 for error (or the non-error ERR_IO_PENDING). |
435 * < 0 for error (or the non-error ERR_IO_PENDING). | |
436 */ | |
437 int SSLClientSocketNSS::BufferSend(void) { | 435 int SSLClientSocketNSS::BufferSend(void) { |
438 if (transport_send_busy_) return ERR_IO_PENDING; | 436 if (transport_send_busy_) return ERR_IO_PENDING; |
439 | 437 |
440 const char *buf; | 438 const char *buf; |
441 int nb = memio_GetWriteParams(nss_bufs_, &buf); | 439 int nb = memio_GetWriteParams(nss_bufs_, &buf); |
442 EnterFunction(nb); | 440 EnterFunction(nb); |
443 | 441 |
444 int rv; | 442 int rv; |
445 if (!nb) { | 443 if (!nb) { |
446 rv = OK; | 444 rv = OK; |
447 } else { | 445 } else { |
448 rv = transport_->Write(buf, nb, &buffer_send_callback_); | 446 scoped_refptr<IOBuffer> send_buffer = new IOBuffer(nb); |
| 447 memcpy(send_buffer->data(), buf, nb); |
| 448 rv = transport_->Write(send_buffer, nb, &buffer_send_callback_); |
449 if (rv == ERR_IO_PENDING) | 449 if (rv == ERR_IO_PENDING) |
450 transport_send_busy_ = true; | 450 transport_send_busy_ = true; |
451 else | 451 else |
452 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); | 452 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); |
453 } | 453 } |
454 | 454 |
455 LeaveFunction(rv); | 455 LeaveFunction(rv); |
456 return rv; | 456 return rv; |
457 } | 457 } |
458 | 458 |
(...skipping 10 matching lines...) Expand all Loading... |
469 if (transport_recv_busy_) return ERR_IO_PENDING; | 469 if (transport_recv_busy_) return ERR_IO_PENDING; |
470 | 470 |
471 char *buf; | 471 char *buf; |
472 int nb = memio_GetReadParams(nss_bufs_, &buf); | 472 int nb = memio_GetReadParams(nss_bufs_, &buf); |
473 EnterFunction(nb); | 473 EnterFunction(nb); |
474 int rv; | 474 int rv; |
475 if (!nb) { | 475 if (!nb) { |
476 // buffer too full to read into, so no I/O possible at moment | 476 // buffer too full to read into, so no I/O possible at moment |
477 rv = ERR_IO_PENDING; | 477 rv = ERR_IO_PENDING; |
478 } else { | 478 } else { |
479 rv = transport_->Read(buf, nb, &buffer_recv_callback_); | 479 recv_buffer_ = new IOBuffer(nb); |
480 if (rv == ERR_IO_PENDING) | 480 rv = transport_->Read(recv_buffer_, nb, &buffer_recv_callback_); |
| 481 if (rv == ERR_IO_PENDING) { |
481 transport_recv_busy_ = true; | 482 transport_recv_busy_ = true; |
482 else | 483 } else { |
| 484 if (rv > 0) |
| 485 memcpy(buf, recv_buffer_->data(), rv); |
483 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); | 486 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); |
| 487 recv_buffer_ = NULL; |
| 488 } |
484 } | 489 } |
485 LeaveFunction(rv); | 490 LeaveFunction(rv); |
486 return rv; | 491 return rv; |
487 } | 492 } |
488 | 493 |
489 void SSLClientSocketNSS::BufferRecvComplete(int result) { | 494 void SSLClientSocketNSS::BufferRecvComplete(int result) { |
490 EnterFunction(result); | 495 EnterFunction(result); |
| 496 if (result > 0) { |
| 497 char *buf; |
| 498 memio_GetReadParams(nss_bufs_, &buf); |
| 499 memcpy(buf, recv_buffer_->data(), result); |
| 500 } |
| 501 recv_buffer_ = NULL; |
491 memio_PutReadResult(nss_bufs_, result); | 502 memio_PutReadResult(nss_bufs_, result); |
492 transport_recv_busy_ = false; | 503 transport_recv_busy_ = false; |
493 OnIOComplete(result); | 504 OnIOComplete(result); |
494 LeaveFunction(""); | 505 LeaveFunction(""); |
495 } | 506 } |
496 | 507 |
497 int SSLClientSocketNSS::DoLoop(int last_io_result) { | 508 int SSLClientSocketNSS::DoLoop(int last_io_result) { |
498 EnterFunction(last_io_result); | 509 EnterFunction(last_io_result); |
499 bool network_moved; | 510 bool network_moved; |
500 int rv = last_io_result; | 511 int rv = last_io_result; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 << ", net_error " << net_error; | 611 << ", net_error " << net_error; |
601 } | 612 } |
602 } | 613 } |
603 | 614 |
604 LeaveFunction(""); | 615 LeaveFunction(""); |
605 return net_error; | 616 return net_error; |
606 } | 617 } |
607 | 618 |
608 int SSLClientSocketNSS::DoPayloadRead() { | 619 int SSLClientSocketNSS::DoPayloadRead() { |
609 EnterFunction(user_buf_len_); | 620 EnterFunction(user_buf_len_); |
610 int rv = PR_Read(nss_fd_, user_buf_, user_buf_len_); | 621 int rv = PR_Read(nss_fd_, user_buf_->data(), user_buf_len_); |
611 if (rv >= 0) { | 622 if (rv >= 0) { |
612 LogData(user_buf_, rv); | 623 LogData(user_buf_->data(), rv); |
613 user_buf_ = NULL; | 624 user_buf_ = NULL; |
614 LeaveFunction(""); | 625 LeaveFunction(""); |
615 return rv; | 626 return rv; |
616 } | 627 } |
617 PRErrorCode prerr = PR_GetError(); | 628 PRErrorCode prerr = PR_GetError(); |
618 if (prerr == PR_WOULD_BLOCK_ERROR) { | 629 if (prerr == PR_WOULD_BLOCK_ERROR) { |
619 GotoState(STATE_PAYLOAD_READ); | 630 GotoState(STATE_PAYLOAD_READ); |
620 LeaveFunction(""); | 631 LeaveFunction(""); |
621 return ERR_IO_PENDING; | 632 return ERR_IO_PENDING; |
622 } | 633 } |
623 user_buf_ = NULL; | 634 user_buf_ = NULL; |
624 LeaveFunction(""); | 635 LeaveFunction(""); |
625 return NetErrorFromNSPRError(prerr); | 636 return NetErrorFromNSPRError(prerr); |
626 } | 637 } |
627 | 638 |
628 int SSLClientSocketNSS::DoPayloadWrite() { | 639 int SSLClientSocketNSS::DoPayloadWrite() { |
629 EnterFunction(user_buf_len_); | 640 EnterFunction(user_buf_len_); |
630 int rv = PR_Write(nss_fd_, user_buf_, user_buf_len_); | 641 int rv = PR_Write(nss_fd_, user_buf_->data(), user_buf_len_); |
631 if (rv >= 0) { | 642 if (rv >= 0) { |
632 LogData(user_buf_, rv); | 643 LogData(user_buf_->data(), rv); |
633 user_buf_ = NULL; | 644 user_buf_ = NULL; |
634 LeaveFunction(""); | 645 LeaveFunction(""); |
635 return rv; | 646 return rv; |
636 } | 647 } |
637 PRErrorCode prerr = PR_GetError(); | 648 PRErrorCode prerr = PR_GetError(); |
638 if (prerr == PR_WOULD_BLOCK_ERROR) { | 649 if (prerr == PR_WOULD_BLOCK_ERROR) { |
639 GotoState(STATE_PAYLOAD_WRITE); | 650 GotoState(STATE_PAYLOAD_WRITE); |
640 return ERR_IO_PENDING; | 651 return ERR_IO_PENDING; |
641 } | 652 } |
642 user_buf_ = NULL; | 653 user_buf_ = NULL; |
643 LeaveFunction(""); | 654 LeaveFunction(""); |
644 return NetErrorFromNSPRError(prerr); | 655 return NetErrorFromNSPRError(prerr); |
645 } | 656 } |
646 | 657 |
647 } // namespace net | 658 } // namespace net |
OLD | NEW |