| 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 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 | 10 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 |
| 10 // until NSS 3.12.2 comes out and we update to it. | 11 // until NSS 3.12.2 comes out and we update to it. |
| 11 #define Lock FOO_NSS_Lock | 12 #define Lock FOO_NSS_Lock |
| 12 #include <ssl.h> | 13 #include <ssl.h> |
| 14 #include <sslerr.h> |
| 13 #include <pk11pub.h> | 15 #include <pk11pub.h> |
| 14 #undef Lock | 16 #undef Lock |
| 15 | 17 |
| 16 #include "base/logging.h" | 18 #include "base/logging.h" |
| 17 #include "base/nss_init.h" | 19 #include "base/nss_init.h" |
| 18 #include "base/string_util.h" | 20 #include "base/string_util.h" |
| 19 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
| 20 #include "net/base/ssl_info.h" | 22 #include "net/base/ssl_info.h" |
| 21 | 23 |
| 22 static const int kRecvBufferSize = 4096; | 24 static const int kRecvBufferSize = 4096; |
| 23 | 25 |
| 24 /* | 26 // nss calls this if an incoming certificate is invalid. |
| 25 * nss calls this if an incoming certificate is invalid. | |
| 26 * TODO(port): expose to app via GetSSLInfo so it can put up | |
| 27 * the appropriate GUI and retry with override if desired | |
| 28 */ | |
| 29 static SECStatus | 27 static SECStatus |
| 30 ownBadCertHandler(void * arg, PRFileDesc * socket) | 28 ownBadCertHandler(void * arg, PRFileDesc * socket) |
| 31 { | 29 { |
| 32 PRErrorCode err = PR_GetError(); | 30 PRErrorCode err = PR_GetError(); |
| 33 LOG(ERROR) << "server certificate is invalid; NSS error code " << err; | 31 LOG(INFO) << "server certificate is invalid; NSS error code " << err; |
| 34 // Return SECSuccess to override the problem, SECFailure to let the original
function fail | 32 // Return SECSuccess to override the problem, |
| 35 return SECSuccess; /* override, say it's OK. */ | 33 // or SECFailure to let the original function fail |
| 34 // Chromium wants it to fail here, and may retry it later. |
| 35 return SECFailure; |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 namespace net { | 39 namespace net { |
| 40 | 40 |
| 41 // State machines are easier to debug if you log state transitions. | 41 // State machines are easier to debug if you log state transitions. |
| 42 // Enable these if you want to see what's going on. | 42 // Enable these if you want to see what's going on. |
| 43 #if 1 | 43 #if 1 |
| 44 #define EnterFunction(x) | 44 #define EnterFunction(x) |
| 45 #define LeaveFunction(x) | 45 #define LeaveFunction(x) |
| 46 #define GotoState(s) next_state_ = s | 46 #define GotoState(s) next_state_ = s |
| 47 #define LogData(s, len) |
| 47 #else | 48 #else |
| 48 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 49 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
| 49 " enter " << x << "; next_state " << next_state_ | 50 " enter " << x << "; next_state " << next_state_ |
| 50 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 51 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
| 51 " leave " << x << "; next_state " << next_state_ | 52 " leave " << x << "; next_state " << next_state_ |
| 52 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 53 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
| 53 " jump to state " << s; next_state_ = s; } while (0) | 54 " jump to state " << s; next_state_ = s; } while (0) |
| 55 #define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
| 56 " data [" << std::string(s, len) << "]"; |
| 57 |
| 54 #endif | 58 #endif |
| 55 | 59 |
| 60 namespace { |
| 61 |
| 62 int NetErrorFromNSPRError(PRErrorCode err) { |
| 63 // TODO(port): fill this out as we learn what's important |
| 64 switch (err) { |
| 65 case PR_WOULD_BLOCK_ERROR: |
| 66 return ERR_IO_PENDING; |
| 67 case SSL_ERROR_NO_CYPHER_OVERLAP: |
| 68 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; |
| 69 case SSL_ERROR_BAD_CERT_DOMAIN: |
| 70 return ERR_CERT_COMMON_NAME_INVALID; |
| 71 case SEC_ERROR_EXPIRED_CERTIFICATE: |
| 72 return ERR_CERT_DATE_INVALID; |
| 73 case SEC_ERROR_BAD_SIGNATURE: |
| 74 return ERR_CERT_INVALID; |
| 75 case SSL_ERROR_REVOKED_CERT_ALERT: |
| 76 case SEC_ERROR_REVOKED_CERTIFICATE: |
| 77 case SEC_ERROR_REVOKED_KEY: |
| 78 return ERR_CERT_REVOKED; |
| 79 case SEC_ERROR_UNKNOWN_ISSUER: |
| 80 return ERR_CERT_AUTHORITY_INVALID; |
| 81 |
| 82 default: { |
| 83 if (IS_SSL_ERROR(err)) { |
| 84 LOG(WARNING) << "Unknown SSL error " << err << |
| 85 " mapped to net::ERR_SSL_PROTOCOL_ERROR"; |
| 86 return ERR_SSL_PROTOCOL_ERROR; |
| 87 } |
| 88 if (IS_SEC_ERROR(err)) { |
| 89 // TODO(port): Probably not the best mapping |
| 90 LOG(WARNING) << "Unknown SEC error " << err << |
| 91 " mapped to net::ERR_CERT_INVALID"; |
| 92 return ERR_CERT_INVALID; |
| 93 } |
| 94 LOG(WARNING) << "Unknown error " << err << |
| 95 " mapped to net::ERR_FAILED"; |
| 96 return ERR_FAILED; |
| 97 } |
| 98 } |
| 99 } |
| 100 |
| 101 // Shared with the Windows code. TODO(avi): merge to a common place |
| 102 int CertStatusFromNetError(int error) { |
| 103 switch (error) { |
| 104 case ERR_CERT_COMMON_NAME_INVALID: |
| 105 return CERT_STATUS_COMMON_NAME_INVALID; |
| 106 case ERR_CERT_DATE_INVALID: |
| 107 return CERT_STATUS_DATE_INVALID; |
| 108 case ERR_CERT_AUTHORITY_INVALID: |
| 109 return CERT_STATUS_AUTHORITY_INVALID; |
| 110 case ERR_CERT_NO_REVOCATION_MECHANISM: |
| 111 return CERT_STATUS_NO_REVOCATION_MECHANISM; |
| 112 case ERR_CERT_UNABLE_TO_CHECK_REVOCATION: |
| 113 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; |
| 114 case ERR_CERT_REVOKED: |
| 115 return CERT_STATUS_REVOKED; |
| 116 case ERR_CERT_CONTAINS_ERRORS: |
| 117 NOTREACHED(); |
| 118 // Falls through. |
| 119 case ERR_CERT_INVALID: |
| 120 return CERT_STATUS_INVALID; |
| 121 default: |
| 122 return 0; |
| 123 } |
| 124 } |
| 125 |
| 126 } // namespace |
| 127 |
| 56 bool SSLClientSocketNSS::nss_options_initialized_ = false; | 128 bool SSLClientSocketNSS::nss_options_initialized_ = false; |
| 57 | 129 |
| 58 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, | 130 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, |
| 59 const std::string& hostname, | 131 const std::string& hostname, |
| 60 const SSLConfig& ssl_config) | 132 const SSLConfig& ssl_config) |
| 61 : | 133 : |
| 62 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), | 134 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), |
| 63 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), | 135 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), |
| 64 transport_send_busy_(false), | 136 transport_send_busy_(false), |
| 65 transport_recv_busy_(false), | 137 transport_recv_busy_(false), |
| 66 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), | 138 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), |
| 67 transport_(transport_socket), | 139 transport_(transport_socket), |
| 68 hostname_(hostname), | 140 hostname_(hostname), |
| 69 ssl_config_(ssl_config), | 141 ssl_config_(ssl_config), |
| 70 user_callback_(NULL), | 142 user_callback_(NULL), |
| 71 user_buf_(NULL), | 143 user_buf_(NULL), |
| 72 user_buf_len_(0), | 144 user_buf_len_(0), |
| 145 server_cert_status_(0), |
| 73 completed_handshake_(false), | 146 completed_handshake_(false), |
| 74 next_state_(STATE_NONE), | 147 next_state_(STATE_NONE), |
| 75 nss_fd_(NULL), | 148 nss_fd_(NULL), |
| 76 nss_bufs_(NULL) { | 149 nss_bufs_(NULL) { |
| 77 EnterFunction(""); | 150 EnterFunction(""); |
| 78 } | 151 } |
| 79 | 152 |
| 80 SSLClientSocketNSS::~SSLClientSocketNSS() { | 153 SSLClientSocketNSS::~SSLClientSocketNSS() { |
| 81 EnterFunction(""); | 154 EnterFunction(""); |
| 82 Disconnect(); | 155 Disconnect(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 DCHECK(!user_callback_); | 214 DCHECK(!user_callback_); |
| 142 DCHECK(!user_buf_); | 215 DCHECK(!user_buf_); |
| 143 | 216 |
| 144 user_buf_ = buf; | 217 user_buf_ = buf; |
| 145 user_buf_len_ = buf_len; | 218 user_buf_len_ = buf_len; |
| 146 | 219 |
| 147 GotoState(STATE_PAYLOAD_READ); | 220 GotoState(STATE_PAYLOAD_READ); |
| 148 int rv = DoLoop(OK); | 221 int rv = DoLoop(OK); |
| 149 if (rv == ERR_IO_PENDING) | 222 if (rv == ERR_IO_PENDING) |
| 150 user_callback_ = callback; | 223 user_callback_ = callback; |
| 151 LeaveFunction(""); | 224 LeaveFunction(rv); |
| 152 return rv; | 225 return rv; |
| 153 } | 226 } |
| 154 | 227 |
| 155 int SSLClientSocketNSS::Write(const char* buf, int buf_len, | 228 int SSLClientSocketNSS::Write(const char* buf, int buf_len, |
| 156 CompletionCallback* callback) { | 229 CompletionCallback* callback) { |
| 157 EnterFunction(buf_len); | 230 EnterFunction(buf_len); |
| 158 DCHECK(completed_handshake_); | 231 DCHECK(completed_handshake_); |
| 159 DCHECK(next_state_ == STATE_NONE); | 232 DCHECK(next_state_ == STATE_NONE); |
| 160 DCHECK(!user_callback_); | 233 DCHECK(!user_callback_); |
| 161 DCHECK(!user_buf_); | 234 DCHECK(!user_buf_); |
| 162 | 235 |
| 163 user_buf_ = const_cast<char*>(buf); | 236 user_buf_ = const_cast<char*>(buf); |
| 164 user_buf_len_ = buf_len; | 237 user_buf_len_ = buf_len; |
| 165 | 238 |
| 166 GotoState(STATE_PAYLOAD_WRITE); | 239 GotoState(STATE_PAYLOAD_WRITE); |
| 167 int rv = DoLoop(OK); | 240 int rv = DoLoop(OK); |
| 168 if (rv == ERR_IO_PENDING) | 241 if (rv == ERR_IO_PENDING) |
| 169 user_callback_ = callback; | 242 user_callback_ = callback; |
| 170 LeaveFunction(""); | 243 LeaveFunction(rv); |
| 171 return rv; | 244 return rv; |
| 172 } | 245 } |
| 173 | 246 |
| 174 void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { | 247 void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { |
| 175 EnterFunction(""); | 248 EnterFunction(""); |
| 176 // TODO(port): implement! | |
| 177 ssl_info->Reset(); | 249 ssl_info->Reset(); |
| 250 SSLChannelInfo channel_info; |
| 251 SECStatus ok = SSL_GetChannelInfo(nss_fd_, |
| 252 &channel_info, sizeof(channel_info)); |
| 253 if (ok == SECSuccess) { |
| 254 SSLCipherSuiteInfo cipher_info; |
| 255 ok = SSL_GetCipherSuiteInfo(channel_info.cipherSuite, |
| 256 &cipher_info, sizeof(cipher_info)); |
| 257 if (ok == SECSuccess) { |
| 258 ssl_info->security_bits = cipher_info.effectiveKeyBits; |
| 259 } else { |
| 260 ssl_info->security_bits = -1; |
| 261 NOTREACHED(); |
| 262 } |
| 263 } |
| 264 ssl_info->cert_status = server_cert_status_; |
| 265 // TODO(port): implement X509Certificate so we can set the cert field! |
| 266 // CERTCertificate *nssCert = SSL_PeerCertificate(nss_fd_); |
| 178 LeaveFunction(""); | 267 LeaveFunction(""); |
| 179 } | 268 } |
| 180 | 269 |
| 181 void SSLClientSocketNSS::DoCallback(int rv) { | 270 void SSLClientSocketNSS::DoCallback(int rv) { |
| 182 EnterFunction(rv); | 271 EnterFunction(rv); |
| 183 DCHECK(rv != ERR_IO_PENDING); | 272 DCHECK(rv != ERR_IO_PENDING); |
| 184 DCHECK(user_callback_); | 273 DCHECK(user_callback_); |
| 185 | 274 |
| 186 // since Run may result in Read being called, clear user_callback_ up front. | 275 // since Run may result in Read being called, clear user_callback_ up front. |
| 187 CompletionCallback* c = user_callback_; | 276 CompletionCallback* c = user_callback_; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 int rv; | 460 int rv; |
| 372 | 461 |
| 373 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); | 462 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); |
| 374 if (rv != SECSuccess) | 463 if (rv != SECSuccess) |
| 375 return ERR_UNEXPECTED; | 464 return ERR_UNEXPECTED; |
| 376 | 465 |
| 377 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled); | 466 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled); |
| 378 if (rv != SECSuccess) | 467 if (rv != SECSuccess) |
| 379 return ERR_UNEXPECTED; | 468 return ERR_UNEXPECTED; |
| 380 | 469 |
| 470 // SNI is enabled automatically if TLS is enabled -- as long as |
| 471 // SSL_V2_COMPATIBLE_HELLO isn't. |
| 472 // So don't do V2 compatible hellos unless we're really using SSL2, |
| 473 // to avoid errors like |
| 474 // "common name `mail.google.com' != requested host name `gmail.com'" |
| 475 rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, |
| 476 ssl_config_.ssl2_enabled); |
| 477 if (rv != SECSuccess) |
| 478 return ERR_UNEXPECTED; |
| 479 |
| 381 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled); | 480 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled); |
| 382 if (rv != SECSuccess) | 481 if (rv != SECSuccess) |
| 383 return ERR_UNEXPECTED; | 482 return ERR_UNEXPECTED; |
| 384 | 483 |
| 385 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.tls1_enabled); | 484 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled); |
| 386 if (rv != SECSuccess) | 485 if (rv != SECSuccess) |
| 387 return ERR_UNEXPECTED; | 486 return ERR_UNEXPECTED; |
| 388 | 487 |
| 488 #ifdef SSL_ENABLE_SESSION_TICKETS |
| 489 // Support RFC 5077 |
| 490 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); |
| 491 if (rv != SECSuccess) |
| 492 LOG(INFO) << "SSL_ENABLE_SESSION_TICKETS failed. Old system nss?"; |
| 493 #else |
| 494 #error "You need to install NSS-3.12 or later to build chromium" |
| 495 #endif |
| 496 |
| 389 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); | 497 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); |
| 390 if (rv != SECSuccess) | 498 if (rv != SECSuccess) |
| 391 return ERR_UNEXPECTED; | 499 return ERR_UNEXPECTED; |
| 392 | 500 |
| 393 rv = SSL_BadCertHook(nss_fd_, ownBadCertHandler, NULL); | 501 rv = SSL_BadCertHook(nss_fd_, ownBadCertHandler, NULL); |
| 394 if (rv != SECSuccess) | 502 if (rv != SECSuccess) |
| 395 return ERR_UNEXPECTED; | 503 return ERR_UNEXPECTED; |
| 396 | 504 |
| 397 // Tell SSL the hostname we're trying to connect to. | 505 // Tell SSL the hostname we're trying to connect to. |
| 398 SSL_SetURL(nss_fd_, hostname_.c_str()); | 506 SSL_SetURL(nss_fd_, hostname_.c_str()); |
| 399 | 507 |
| 400 // Tell SSL we're a client; needed if not letting NSPR do socket I/O | 508 // Tell SSL we're a client; needed if not letting NSPR do socket I/O |
| 401 SSL_ResetHandshake(nss_fd_, 0); | 509 SSL_ResetHandshake(nss_fd_, 0); |
| 402 GotoState(STATE_HANDSHAKE_READ); | 510 GotoState(STATE_HANDSHAKE_READ); |
| 403 // Return OK so DoLoop tries handshaking | 511 // Return OK so DoLoop tries handshaking |
| 404 LeaveFunction(""); | 512 LeaveFunction(""); |
| 405 return OK; | 513 return OK; |
| 406 } | 514 } |
| 407 | 515 |
| 408 int SSLClientSocketNSS::DoHandshakeRead() { | 516 int SSLClientSocketNSS::DoHandshakeRead() { |
| 409 EnterFunction(""); | 517 EnterFunction(""); |
| 518 int net_error; |
| 410 int rv = SSL_ForceHandshake(nss_fd_); | 519 int rv = SSL_ForceHandshake(nss_fd_); |
| 520 |
| 411 if (rv == SECSuccess) { | 521 if (rv == SECSuccess) { |
| 522 net_error = OK; |
| 412 // there's a callback for this, too | 523 // there's a callback for this, too |
| 413 completed_handshake_ = true; | 524 completed_handshake_ = true; |
| 414 // Indicate we're ready to handle I/O. Badly named? | 525 // Indicate we're ready to handle I/O. Badly named? |
| 415 GotoState(STATE_NONE); | 526 GotoState(STATE_NONE); |
| 416 LeaveFunction(""); | 527 } else { |
| 417 return OK; | 528 PRErrorCode prerr = PR_GetError(); |
| 529 net_error = NetErrorFromNSPRError(prerr); |
| 530 |
| 531 // If not done, stay in this state |
| 532 if (net_error == ERR_IO_PENDING) { |
| 533 GotoState(STATE_HANDSHAKE_READ); |
| 534 } else { |
| 535 server_cert_status_ = CertStatusFromNetError(net_error); |
| 536 LOG(ERROR) << "handshake failed; NSS error code " << prerr |
| 537 << ", net_error " << net_error << ", server_cert_status " << se
rver_cert_status_; |
| 538 } |
| 418 } | 539 } |
| 419 PRErrorCode prerr = PR_GetError(); | 540 |
| 420 if (prerr == PR_WOULD_BLOCK_ERROR) { | |
| 421 // at this point, it should have tried to send some bytes | |
| 422 GotoState(STATE_HANDSHAKE_READ); | |
| 423 LeaveFunction(""); | |
| 424 return ERR_IO_PENDING; | |
| 425 } | |
| 426 // TODO: map rv to net error code properly | |
| 427 LeaveFunction(""); | 541 LeaveFunction(""); |
| 428 return ERR_SSL_PROTOCOL_ERROR; | 542 return net_error; |
| 429 } | 543 } |
| 430 | 544 |
| 431 int SSLClientSocketNSS::DoPayloadRead() { | 545 int SSLClientSocketNSS::DoPayloadRead() { |
| 432 EnterFunction(user_buf_len_); | 546 EnterFunction(user_buf_len_); |
| 433 int rv = PR_Read(nss_fd_, user_buf_, user_buf_len_); | 547 int rv = PR_Read(nss_fd_, user_buf_, user_buf_len_); |
| 434 if (rv >= 0) { | 548 if (rv >= 0) { |
| 549 LogData(user_buf_, rv); |
| 435 user_buf_ = NULL; | 550 user_buf_ = NULL; |
| 436 LeaveFunction(""); | 551 LeaveFunction(""); |
| 437 return rv; | 552 return rv; |
| 438 } | 553 } |
| 439 PRErrorCode prerr = PR_GetError(); | 554 PRErrorCode prerr = PR_GetError(); |
| 440 if (prerr == PR_WOULD_BLOCK_ERROR) { | 555 if (prerr == PR_WOULD_BLOCK_ERROR) { |
| 441 GotoState(STATE_PAYLOAD_READ); | 556 GotoState(STATE_PAYLOAD_READ); |
| 442 LeaveFunction(""); | 557 LeaveFunction(""); |
| 443 return ERR_IO_PENDING; | 558 return ERR_IO_PENDING; |
| 444 } | 559 } |
| 445 user_buf_ = NULL; | 560 user_buf_ = NULL; |
| 446 LeaveFunction(""); | 561 LeaveFunction(""); |
| 447 // TODO: map rv to net error code properly | 562 // TODO: map rv to net error code properly |
| 448 return ERR_SSL_PROTOCOL_ERROR; | 563 return ERR_SSL_PROTOCOL_ERROR; |
| 449 } | 564 } |
| 450 | 565 |
| 451 int SSLClientSocketNSS::DoPayloadWrite() { | 566 int SSLClientSocketNSS::DoPayloadWrite() { |
| 452 EnterFunction(user_buf_len_); | 567 EnterFunction(user_buf_len_); |
| 453 int rv = PR_Write(nss_fd_, user_buf_, user_buf_len_); | 568 int rv = PR_Write(nss_fd_, user_buf_, user_buf_len_); |
| 454 if (rv >= 0) { | 569 if (rv >= 0) { |
| 570 LogData(user_buf_, rv); |
| 455 user_buf_ = NULL; | 571 user_buf_ = NULL; |
| 456 LeaveFunction(""); | 572 LeaveFunction(""); |
| 457 return rv; | 573 return rv; |
| 458 } | 574 } |
| 459 PRErrorCode prerr = PR_GetError(); | 575 PRErrorCode prerr = PR_GetError(); |
| 460 if (prerr == PR_WOULD_BLOCK_ERROR) { | 576 if (prerr == PR_WOULD_BLOCK_ERROR) { |
| 461 GotoState(STATE_PAYLOAD_WRITE); | 577 GotoState(STATE_PAYLOAD_WRITE); |
| 462 return ERR_IO_PENDING; | 578 return ERR_IO_PENDING; |
| 463 } | 579 } |
| 464 user_buf_ = NULL; | 580 user_buf_ = NULL; |
| 465 LeaveFunction(""); | 581 LeaveFunction(""); |
| 466 // TODO: map rv to net error code properly | 582 // TODO: map rv to net error code properly |
| 467 return ERR_SSL_PROTOCOL_ERROR; | 583 return ERR_SSL_PROTOCOL_ERROR; |
| 468 } | 584 } |
| 469 | 585 |
| 470 } // namespace net | 586 } // namespace net |
| 471 | 587 |
| OLD | NEW |