OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 // This file includes code GetDefaultCertNickname(), derived from | 5 // This file includes code GetDefaultCertNickname(), derived from |
6 // nsNSSCertificate::defaultServerNickName() | 6 // nsNSSCertificate::defaultServerNickName() |
7 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp | 7 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp |
8 // and SSLClientSocketNSS::DoVerifyCertComplete() derived from | 8 // and SSLClientSocketNSS::DoVerifyCertComplete() derived from |
9 // AuthCertificateCallback() in | 9 // AuthCertificateCallback() in |
10 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 10 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 | 74 |
75 static const int kRecvBufferSize = 4096; | 75 static const int kRecvBufferSize = 4096; |
76 | 76 |
77 namespace net { | 77 namespace net { |
78 | 78 |
79 // State machines are easier to debug if you log state transitions. | 79 // State machines are easier to debug if you log state transitions. |
80 // Enable these if you want to see what's going on. | 80 // Enable these if you want to see what's going on. |
81 #if 1 | 81 #if 1 |
82 #define EnterFunction(x) | 82 #define EnterFunction(x) |
83 #define LeaveFunction(x) | 83 #define LeaveFunction(x) |
84 #define GotoState(s) next_state_ = s | 84 #define GotoState(s) next_handshake_state_ = s |
85 #define LogData(s, len) | 85 #define LogData(s, len) |
86 #else | 86 #else |
87 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 87 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
88 " enter " << x << "; next_state " << next_state_ | 88 " enter " << x << \ |
| 89 "; next_handshake_state " << next_handshake_state_ |
89 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 90 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
90 " leave " << x << "; next_state " << next_state_ | 91 " leave " << x << \ |
| 92 "; next_handshake_state " << next_handshake_state_ |
91 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 93 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
92 " jump to state " << s; next_state_ = s; } while (0) | 94 " jump to state " << s; \ |
| 95 next_handshake_state_ = s; } while (0) |
93 #define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 96 #define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ |
94 " data [" << std::string(s, len) << "]"; | 97 " data [" << std::string(s, len) << "]"; |
95 | 98 |
96 #endif | 99 #endif |
97 | 100 |
98 namespace { | 101 namespace { |
99 | 102 |
100 // Gets default certificate nickname from cert. | 103 // Gets default certificate nickname from cert. |
101 // Derived from nsNSSCertificate::defaultServerNickname | 104 // Derived from nsNSSCertificate::defaultServerNickname |
102 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp. | 105 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 bool SSLClientSocketNSS::nss_options_initialized_ = false; | 189 bool SSLClientSocketNSS::nss_options_initialized_ = false; |
187 | 190 |
188 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, | 191 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, |
189 const std::string& hostname, | 192 const std::string& hostname, |
190 const SSLConfig& ssl_config) | 193 const SSLConfig& ssl_config) |
191 : | 194 : |
192 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), | 195 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), |
193 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), | 196 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), |
194 transport_send_busy_(false), | 197 transport_send_busy_(false), |
195 transport_recv_busy_(false), | 198 transport_recv_busy_(false), |
196 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), | 199 handshake_io_callback_(this, &SSLClientSocketNSS::OnHandshakeIOComplete), |
197 transport_(transport_socket), | 200 transport_(transport_socket), |
198 hostname_(hostname), | 201 hostname_(hostname), |
199 ssl_config_(ssl_config), | 202 ssl_config_(ssl_config), |
200 user_connect_callback_(NULL), | 203 user_connect_callback_(NULL), |
201 user_callback_(NULL), | 204 user_read_callback_(NULL), |
202 user_buf_len_(0), | 205 user_write_callback_(NULL), |
| 206 user_read_buf_len_(0), |
| 207 user_write_buf_len_(0), |
203 completed_handshake_(false), | 208 completed_handshake_(false), |
204 next_state_(STATE_NONE), | 209 next_handshake_state_(STATE_NONE), |
205 nss_fd_(NULL), | 210 nss_fd_(NULL), |
206 nss_bufs_(NULL) { | 211 nss_bufs_(NULL) { |
207 EnterFunction(""); | 212 EnterFunction(""); |
208 } | 213 } |
209 | 214 |
210 SSLClientSocketNSS::~SSLClientSocketNSS() { | 215 SSLClientSocketNSS::~SSLClientSocketNSS() { |
211 EnterFunction(""); | 216 EnterFunction(""); |
212 Disconnect(); | 217 Disconnect(); |
213 LeaveFunction(""); | 218 LeaveFunction(""); |
214 } | 219 } |
215 | 220 |
216 int SSLClientSocketNSS::Init() { | 221 int SSLClientSocketNSS::Init() { |
217 EnterFunction(""); | 222 EnterFunction(""); |
218 // Initialize NSS in a threadsafe way. | 223 // Initialize NSS in a threadsafe way. |
219 base::EnsureNSSInit(); | 224 base::EnsureNSSInit(); |
220 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop | 225 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop |
221 // by MessageLoopForIO::current(). | 226 // by MessageLoopForIO::current(). |
222 // X509Certificate::Verify() runs on a worker thread of CertVerifier. | 227 // X509Certificate::Verify() runs on a worker thread of CertVerifier. |
223 EnsureOCSPInit(); | 228 EnsureOCSPInit(); |
224 | 229 |
225 LeaveFunction(""); | 230 LeaveFunction(""); |
226 return OK; | 231 return OK; |
227 } | 232 } |
228 | 233 |
229 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { | 234 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { |
230 EnterFunction(""); | 235 EnterFunction(""); |
231 DCHECK(transport_.get()); | 236 DCHECK(transport_.get()); |
232 DCHECK(next_state_ == STATE_NONE); | 237 DCHECK(next_handshake_state_ == STATE_NONE); |
233 DCHECK(!user_callback_); | 238 DCHECK(!user_read_callback_); |
| 239 DCHECK(!user_write_callback_); |
234 DCHECK(!user_connect_callback_); | 240 DCHECK(!user_connect_callback_); |
235 DCHECK(!user_buf_); | 241 DCHECK(!user_read_buf_); |
| 242 DCHECK(!user_write_buf_); |
236 | 243 |
237 if (Init() != OK) { | 244 if (Init() != OK) { |
238 NOTREACHED() << "Couldn't initialize nss"; | 245 NOTREACHED() << "Couldn't initialize nss"; |
239 } | 246 } |
240 | 247 |
241 // Transport connected, now hook it up to nss | 248 // Transport connected, now hook it up to nss |
242 // TODO(port): specify rx and tx buffer sizes separately | 249 // TODO(port): specify rx and tx buffer sizes separately |
243 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 250 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); |
244 if (nss_fd_ == NULL) { | 251 if (nss_fd_ == NULL) { |
245 return 9999; // TODO(port): real error | 252 return 9999; // TODO(port): real error |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this); | 321 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this); |
315 if (rv != SECSuccess) | 322 if (rv != SECSuccess) |
316 return ERR_UNEXPECTED; | 323 return ERR_UNEXPECTED; |
317 | 324 |
318 // Tell SSL the hostname we're trying to connect to. | 325 // Tell SSL the hostname we're trying to connect to. |
319 SSL_SetURL(nss_fd_, hostname_.c_str()); | 326 SSL_SetURL(nss_fd_, hostname_.c_str()); |
320 | 327 |
321 // Tell SSL we're a client; needed if not letting NSPR do socket I/O | 328 // Tell SSL we're a client; needed if not letting NSPR do socket I/O |
322 SSL_ResetHandshake(nss_fd_, 0); | 329 SSL_ResetHandshake(nss_fd_, 0); |
323 | 330 |
324 GotoState(STATE_HANDSHAKE_READ); | 331 GotoState(STATE_HANDSHAKE); |
325 rv = DoLoop(OK); | 332 rv = DoHandshakeLoop(OK); |
326 if (rv == ERR_IO_PENDING) | 333 if (rv == ERR_IO_PENDING) |
327 user_connect_callback_ = callback; | 334 user_connect_callback_ = callback; |
328 | 335 |
329 LeaveFunction(""); | 336 LeaveFunction(""); |
330 return rv > OK ? OK : rv; | 337 return rv > OK ? OK : rv; |
331 } | 338 } |
332 | 339 |
333 void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { | 340 void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { |
334 if (UpdateServerCert() != NULL && | 341 if (UpdateServerCert() != NULL && |
335 ssl_config_.IsAllowedBadCert(server_cert_)) { | 342 ssl_config_.IsAllowedBadCert(server_cert_)) { |
336 SSL_InvalidateSession(nss_fd_); | 343 SSL_InvalidateSession(nss_fd_); |
337 } | 344 } |
338 } | 345 } |
339 | 346 |
340 void SSLClientSocketNSS::Disconnect() { | 347 void SSLClientSocketNSS::Disconnect() { |
341 EnterFunction(""); | 348 EnterFunction(""); |
342 | 349 |
343 // TODO(wtc): Send SSL close_notify alert. | 350 // TODO(wtc): Send SSL close_notify alert. |
344 if (nss_fd_ != NULL) { | 351 if (nss_fd_ != NULL) { |
345 InvalidateSessionIfBadCertificate(); | 352 InvalidateSessionIfBadCertificate(); |
346 PR_Close(nss_fd_); | 353 PR_Close(nss_fd_); |
347 nss_fd_ = NULL; | 354 nss_fd_ = NULL; |
348 } | 355 } |
349 | 356 |
350 // Shut down anything that may call us back (through buffer_send_callback_, | 357 // Shut down anything that may call us back (through buffer_send_callback_, |
351 // buffer_recv_callback, or io_callback_). | 358 // buffer_recv_callback, or handshake_io_callback_). |
352 verifier_.reset(); | 359 verifier_.reset(); |
353 transport_->Disconnect(); | 360 transport_->Disconnect(); |
354 | 361 |
355 // Reset object state | 362 // Reset object state |
356 transport_send_busy_ = false; | 363 transport_send_busy_ = false; |
357 transport_recv_busy_ = false; | 364 transport_recv_busy_ = false; |
358 user_connect_callback_ = NULL; | 365 user_connect_callback_ = NULL; |
359 user_callback_ = NULL; | 366 user_read_callback_ = NULL; |
360 user_buf_ = NULL; | 367 user_write_callback_ = NULL; |
361 user_buf_len_ = 0; | 368 user_read_buf_ = NULL; |
| 369 user_read_buf_len_ = 0; |
| 370 user_write_buf_ = NULL; |
| 371 user_write_buf_len_ = 0; |
362 server_cert_ = NULL; | 372 server_cert_ = NULL; |
363 server_cert_verify_result_.Reset(); | 373 server_cert_verify_result_.Reset(); |
364 completed_handshake_ = false; | 374 completed_handshake_ = false; |
365 nss_bufs_ = NULL; | 375 nss_bufs_ = NULL; |
366 | 376 |
367 LeaveFunction(""); | 377 LeaveFunction(""); |
368 } | 378 } |
369 | 379 |
370 bool SSLClientSocketNSS::IsConnected() const { | 380 bool SSLClientSocketNSS::IsConnected() const { |
371 // Ideally, we should also check if we have received the close_notify alert | 381 // Ideally, we should also check if we have received the close_notify alert |
(...skipping 19 matching lines...) Expand all Loading... |
391 EnterFunction(""); | 401 EnterFunction(""); |
392 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); | 402 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); |
393 LeaveFunction(""); | 403 LeaveFunction(""); |
394 return ret; | 404 return ret; |
395 } | 405 } |
396 | 406 |
397 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, | 407 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, |
398 CompletionCallback* callback) { | 408 CompletionCallback* callback) { |
399 EnterFunction(buf_len); | 409 EnterFunction(buf_len); |
400 DCHECK(completed_handshake_); | 410 DCHECK(completed_handshake_); |
401 DCHECK(next_state_ == STATE_NONE); | 411 DCHECK(next_handshake_state_ == STATE_NONE); |
402 DCHECK(!user_callback_); | 412 DCHECK(!user_read_callback_); |
403 DCHECK(!user_connect_callback_); | 413 DCHECK(!user_connect_callback_); |
404 DCHECK(!user_buf_); | 414 DCHECK(!user_read_buf_); |
| 415 DCHECK(nss_bufs_); |
405 | 416 |
406 user_buf_ = buf; | 417 user_read_buf_ = buf; |
407 user_buf_len_ = buf_len; | 418 user_read_buf_len_ = buf_len; |
408 | 419 |
409 GotoState(STATE_PAYLOAD_READ); | 420 int rv = DoReadLoop(OK); |
410 int rv = DoLoop(OK); | 421 |
411 if (rv == ERR_IO_PENDING) | 422 if (rv == ERR_IO_PENDING) |
412 user_callback_ = callback; | 423 user_read_callback_ = callback; |
413 LeaveFunction(rv); | 424 LeaveFunction(rv); |
414 return rv; | 425 return rv; |
415 } | 426 } |
416 | 427 |
417 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, | 428 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, |
418 CompletionCallback* callback) { | 429 CompletionCallback* callback) { |
419 EnterFunction(buf_len); | 430 EnterFunction(buf_len); |
420 DCHECK(completed_handshake_); | 431 DCHECK(completed_handshake_); |
421 DCHECK(next_state_ == STATE_NONE); | 432 DCHECK(next_handshake_state_ == STATE_NONE); |
422 DCHECK(!user_callback_); | 433 DCHECK(!user_write_callback_); |
423 DCHECK(!user_connect_callback_); | 434 DCHECK(!user_connect_callback_); |
424 DCHECK(!user_buf_); | 435 DCHECK(!user_write_buf_); |
| 436 DCHECK(nss_bufs_); |
425 | 437 |
426 user_buf_ = buf; | 438 user_write_buf_ = buf; |
427 user_buf_len_ = buf_len; | 439 user_write_buf_len_ = buf_len; |
428 | 440 |
429 GotoState(STATE_PAYLOAD_WRITE); | 441 int rv = DoWriteLoop(OK); |
430 int rv = DoLoop(OK); | 442 |
431 if (rv == ERR_IO_PENDING) | 443 if (rv == ERR_IO_PENDING) |
432 user_callback_ = callback; | 444 user_write_callback_ = callback; |
433 LeaveFunction(rv); | 445 LeaveFunction(rv); |
434 return rv; | 446 return rv; |
435 } | 447 } |
436 | 448 |
437 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | 449 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { |
438 return transport_->SetReceiveBufferSize(size); | 450 return transport_->SetReceiveBufferSize(size); |
439 } | 451 } |
440 | 452 |
441 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { | 453 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { |
442 return transport_->SetSendBufferSize(size); | 454 return transport_->SetSendBufferSize(size); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 DCHECK(server_cert_ != NULL); | 496 DCHECK(server_cert_ != NULL); |
485 ssl_info->cert = server_cert_; | 497 ssl_info->cert = server_cert_; |
486 LeaveFunction(""); | 498 LeaveFunction(""); |
487 } | 499 } |
488 | 500 |
489 void SSLClientSocketNSS::GetSSLCertRequestInfo( | 501 void SSLClientSocketNSS::GetSSLCertRequestInfo( |
490 SSLCertRequestInfo* cert_request_info) { | 502 SSLCertRequestInfo* cert_request_info) { |
491 // TODO(wtc): implement this. | 503 // TODO(wtc): implement this. |
492 } | 504 } |
493 | 505 |
494 void SSLClientSocketNSS::DoCallback(int rv) { | 506 void SSLClientSocketNSS::DoReadCallback(int rv) { |
495 EnterFunction(rv); | 507 EnterFunction(rv); |
496 DCHECK(rv != ERR_IO_PENDING); | 508 DCHECK(rv != ERR_IO_PENDING); |
497 DCHECK(user_callback_); | 509 DCHECK(user_read_callback_); |
498 | 510 |
499 // Since Run may result in Read being called, clear |user_callback_| up front. | 511 // Since Run may result in Read being called, clear |user_read_callback_| |
500 CompletionCallback* c = user_callback_; | 512 // up front. |
501 user_callback_ = NULL; | 513 CompletionCallback* c = user_read_callback_; |
502 user_buf_ = NULL; | 514 user_read_callback_ = NULL; |
503 c->Run(rv); | 515 c->Run(rv); |
504 LeaveFunction(""); | 516 LeaveFunction(""); |
505 } | 517 } |
| 518 |
| 519 void SSLClientSocketNSS::DoWriteCallback(int rv) { |
| 520 EnterFunction(rv); |
| 521 DCHECK(rv != ERR_IO_PENDING); |
| 522 DCHECK(user_write_callback_); |
| 523 |
| 524 // Since Run may result in Write being called, clear |user_write_callback_| |
| 525 // up front. |
| 526 CompletionCallback* c = user_write_callback_; |
| 527 user_write_callback_ = NULL; |
| 528 c->Run(rv); |
| 529 LeaveFunction(""); |
| 530 } |
506 | 531 |
507 // As part of Connect(), the SSLClientSocketNSS object performs an SSL | 532 // As part of Connect(), the SSLClientSocketNSS object performs an SSL |
508 // handshake. This requires network IO, which in turn calls | 533 // handshake. This requires network IO, which in turn calls |
509 // BufferRecvComplete() with a non-zero byte count. This byte count eventually | 534 // BufferRecvComplete() with a non-zero byte count. This byte count eventually |
510 // winds its way through the state machine and ends up being passed to the | 535 // winds its way through the state machine and ends up being passed to the |
511 // callback. For Read() and Write(), that's what we want. But for Connect(), | 536 // callback. For Read() and Write(), that's what we want. But for Connect(), |
512 // the caller expects OK (i.e. 0) for success. | 537 // the caller expects OK (i.e. 0) for success. |
513 // | 538 // |
514 void SSLClientSocketNSS::DoConnectCallback(int rv) { | 539 void SSLClientSocketNSS::DoConnectCallback(int rv) { |
515 EnterFunction(rv); | 540 EnterFunction(rv); |
516 DCHECK_NE(rv, ERR_IO_PENDING); | 541 DCHECK_NE(rv, ERR_IO_PENDING); |
517 DCHECK(user_connect_callback_); | 542 DCHECK(user_connect_callback_); |
518 | 543 |
519 // Since Run may result in Read being called, clear |user_connect_callback_| | |
520 // up front. | |
521 CompletionCallback* c = user_connect_callback_; | 544 CompletionCallback* c = user_connect_callback_; |
522 user_connect_callback_ = NULL; | 545 user_connect_callback_ = NULL; |
523 c->Run(rv > OK ? OK : rv); | 546 c->Run(rv > OK ? OK : rv); |
524 LeaveFunction(""); | 547 LeaveFunction(""); |
525 } | 548 } |
526 | 549 |
527 void SSLClientSocketNSS::OnIOComplete(int result) { | 550 void SSLClientSocketNSS::OnHandshakeIOComplete(int result) { |
528 EnterFunction(result); | 551 EnterFunction(result); |
529 int rv = DoLoop(result); | 552 int rv = DoHandshakeLoop(result); |
530 if (rv != ERR_IO_PENDING) { | 553 DCHECK(user_connect_callback_); |
531 if (user_callback_) { | 554 if (rv != ERR_IO_PENDING) |
532 DoCallback(rv); | 555 DoConnectCallback(rv); |
533 } else if (user_connect_callback_) { | |
534 DoConnectCallback(rv); | |
535 } | |
536 } | |
537 LeaveFunction(""); | 556 LeaveFunction(""); |
538 } | 557 } |
539 | 558 |
| 559 void SSLClientSocketNSS::OnSendComplete(int result) { |
| 560 EnterFunction(result); |
| 561 if (next_handshake_state_ != STATE_NONE) { |
| 562 // In handshake phase. |
| 563 OnHandshakeIOComplete(result); |
| 564 LeaveFunction(""); |
| 565 return; |
| 566 } |
| 567 |
| 568 // Network layer sent some data, check if client requested to write |
| 569 // more data. |
| 570 if (!user_write_buf_) { |
| 571 LeaveFunction(""); |
| 572 return; |
| 573 } |
| 574 |
| 575 int rv = DoWriteLoop(result); |
| 576 if (rv != ERR_IO_PENDING) |
| 577 DoWriteCallback(rv); |
| 578 LeaveFunction(""); |
| 579 } |
| 580 |
| 581 void SSLClientSocketNSS::OnRecvComplete(int result) { |
| 582 EnterFunction(result); |
| 583 if (next_handshake_state_ != STATE_NONE) { |
| 584 // In handshake phase. |
| 585 OnHandshakeIOComplete(result); |
| 586 LeaveFunction(""); |
| 587 return; |
| 588 } |
| 589 |
| 590 // Network layer received some data, check if client requested to read |
| 591 // decrypted data. |
| 592 if (!user_read_buf_) { |
| 593 LeaveFunction(""); |
| 594 return; |
| 595 } |
| 596 |
| 597 int rv = DoReadLoop(result); |
| 598 if (rv != ERR_IO_PENDING) |
| 599 DoReadCallback(rv); |
| 600 LeaveFunction(""); |
| 601 } |
| 602 |
540 // Map a Chromium net error code to an NSS error code | 603 // Map a Chromium net error code to an NSS error code |
541 // See _MD_unix_map_default_error in the NSS source | 604 // See _MD_unix_map_default_error in the NSS source |
542 // tree for inspiration. | 605 // tree for inspiration. |
543 static PRErrorCode MapErrorToNSS(int result) { | 606 static PRErrorCode MapErrorToNSS(int result) { |
544 if (result >=0) | 607 if (result >=0) |
545 return result; | 608 return result; |
546 // TODO(port): add real table | 609 // TODO(port): add real table |
547 LOG(ERROR) << "MapErrorToNSS " << result; | 610 LOG(ERROR) << "MapErrorToNSS " << result; |
548 return PR_UNKNOWN_ERROR; | 611 return PR_UNKNOWN_ERROR; |
549 } | 612 } |
550 | 613 |
551 // Do network I/O between the given buffer and the given socket. | 614 // Do network I/O between the given buffer and the given socket. |
| 615 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) |
| 616 bool SSLClientSocketNSS::DoTransportIO() { |
| 617 bool network_moved = false; |
| 618 if (nss_bufs_ != NULL) { |
| 619 int nsent = BufferSend(); |
| 620 int nreceived = BufferRecv(); |
| 621 network_moved = (nsent > 0 || nreceived >= 0); |
| 622 } |
| 623 return network_moved; |
| 624 } |
| 625 |
552 // Return 0 for EOF, | 626 // Return 0 for EOF, |
553 // > 0 for bytes transferred immediately, | 627 // > 0 for bytes transferred immediately, |
554 // < 0 for error (or the non-error ERR_IO_PENDING). | 628 // < 0 for error (or the non-error ERR_IO_PENDING). |
555 int SSLClientSocketNSS::BufferSend(void) { | 629 int SSLClientSocketNSS::BufferSend(void) { |
556 if (transport_send_busy_) return ERR_IO_PENDING; | 630 if (transport_send_busy_) return ERR_IO_PENDING; |
557 | 631 |
558 const char *buf; | 632 const char *buf; |
559 int nb = memio_GetWriteParams(nss_bufs_, &buf); | 633 int nb = memio_GetWriteParams(nss_bufs_, &buf); |
560 EnterFunction(nb); | 634 EnterFunction(nb); |
561 | 635 |
(...skipping 11 matching lines...) Expand all Loading... |
573 } | 647 } |
574 | 648 |
575 LeaveFunction(rv); | 649 LeaveFunction(rv); |
576 return rv; | 650 return rv; |
577 } | 651 } |
578 | 652 |
579 void SSLClientSocketNSS::BufferSendComplete(int result) { | 653 void SSLClientSocketNSS::BufferSendComplete(int result) { |
580 EnterFunction(result); | 654 EnterFunction(result); |
581 memio_PutWriteResult(nss_bufs_, result); | 655 memio_PutWriteResult(nss_bufs_, result); |
582 transport_send_busy_ = false; | 656 transport_send_busy_ = false; |
583 OnIOComplete(result); | 657 OnSendComplete(result); |
584 LeaveFunction(""); | 658 LeaveFunction(""); |
585 } | 659 } |
586 | 660 |
587 | 661 |
588 int SSLClientSocketNSS::BufferRecv(void) { | 662 int SSLClientSocketNSS::BufferRecv(void) { |
589 if (transport_recv_busy_) return ERR_IO_PENDING; | 663 if (transport_recv_busy_) return ERR_IO_PENDING; |
590 | 664 |
591 char *buf; | 665 char *buf; |
592 int nb = memio_GetReadParams(nss_bufs_, &buf); | 666 int nb = memio_GetReadParams(nss_bufs_, &buf); |
593 EnterFunction(nb); | 667 EnterFunction(nb); |
(...skipping 20 matching lines...) Expand all Loading... |
614 void SSLClientSocketNSS::BufferRecvComplete(int result) { | 688 void SSLClientSocketNSS::BufferRecvComplete(int result) { |
615 EnterFunction(result); | 689 EnterFunction(result); |
616 if (result > 0) { | 690 if (result > 0) { |
617 char *buf; | 691 char *buf; |
618 memio_GetReadParams(nss_bufs_, &buf); | 692 memio_GetReadParams(nss_bufs_, &buf); |
619 memcpy(buf, recv_buffer_->data(), result); | 693 memcpy(buf, recv_buffer_->data(), result); |
620 } | 694 } |
621 recv_buffer_ = NULL; | 695 recv_buffer_ = NULL; |
622 memio_PutReadResult(nss_bufs_, result); | 696 memio_PutReadResult(nss_bufs_, result); |
623 transport_recv_busy_ = false; | 697 transport_recv_busy_ = false; |
624 OnIOComplete(result); | 698 OnRecvComplete(result); |
625 LeaveFunction(""); | 699 LeaveFunction(""); |
626 } | 700 } |
627 | 701 |
628 int SSLClientSocketNSS::DoLoop(int last_io_result) { | 702 int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) { |
629 EnterFunction(last_io_result); | 703 EnterFunction(last_io_result); |
630 bool network_moved; | 704 bool network_moved; |
631 int rv = last_io_result; | 705 int rv = last_io_result; |
632 do { | 706 do { |
633 network_moved = false; | 707 network_moved = false; |
634 // Default to STATE_NONE for next state. | 708 // Default to STATE_NONE for next state. |
635 // (This is a quirk carried over from the windows | 709 // (This is a quirk carried over from the windows |
636 // implementation. It makes reading the logs a bit harder.) | 710 // implementation. It makes reading the logs a bit harder.) |
637 // State handlers can and often do call GotoState just | 711 // State handlers can and often do call GotoState just |
638 // to stay in the current state. | 712 // to stay in the current state. |
639 State state = next_state_; | 713 State state = next_handshake_state_; |
640 GotoState(STATE_NONE); | 714 GotoState(STATE_NONE); |
641 switch (state) { | 715 switch (state) { |
642 case STATE_NONE: | 716 case STATE_NONE: |
643 // we're just pumping data between the buffer and the network | 717 // we're just pumping data between the buffer and the network |
644 break; | 718 break; |
645 case STATE_HANDSHAKE_READ: | 719 case STATE_HANDSHAKE: |
646 rv = DoHandshakeRead(); | 720 rv = DoHandshake(); |
647 break; | 721 break; |
648 case STATE_VERIFY_CERT: | 722 case STATE_VERIFY_CERT: |
649 DCHECK(rv == OK); | 723 DCHECK(rv == OK); |
650 rv = DoVerifyCert(rv); | 724 rv = DoVerifyCert(rv); |
651 break; | 725 break; |
652 case STATE_VERIFY_CERT_COMPLETE: | 726 case STATE_VERIFY_CERT_COMPLETE: |
653 rv = DoVerifyCertComplete(rv); | 727 rv = DoVerifyCertComplete(rv); |
654 break; | 728 break; |
655 case STATE_PAYLOAD_READ: | |
656 rv = DoPayloadRead(); | |
657 break; | |
658 case STATE_PAYLOAD_WRITE: | |
659 rv = DoPayloadWrite(); | |
660 break; | |
661 default: | 729 default: |
662 rv = ERR_UNEXPECTED; | 730 rv = ERR_UNEXPECTED; |
663 NOTREACHED() << "unexpected state"; | 731 NOTREACHED() << "unexpected state"; |
664 break; | 732 break; |
665 } | 733 } |
666 | 734 |
667 // Do the actual network I/O | 735 // Do the actual network I/O |
668 if (nss_bufs_ != NULL) { | 736 network_moved = DoTransportIO(); |
669 int nsent = BufferSend(); | |
670 int nreceived = BufferRecv(); | |
671 network_moved = (nsent > 0 || nreceived >= 0); | |
672 } | |
673 } while ((rv != ERR_IO_PENDING || network_moved) && | 737 } while ((rv != ERR_IO_PENDING || network_moved) && |
674 next_state_ != STATE_NONE); | 738 next_handshake_state_ != STATE_NONE); |
675 LeaveFunction(""); | 739 LeaveFunction(""); |
676 return rv; | 740 return rv; |
677 } | 741 } |
| 742 |
| 743 int SSLClientSocketNSS::DoReadLoop(int result) { |
| 744 EnterFunction(""); |
| 745 DCHECK(completed_handshake_); |
| 746 DCHECK(next_handshake_state_ == STATE_NONE); |
| 747 |
| 748 if (result < 0) |
| 749 return result; |
| 750 |
| 751 if (!nss_bufs_) |
| 752 return ERR_UNEXPECTED; |
| 753 |
| 754 while (DoTransportIO()) continue; |
| 755 bool network_moved; |
| 756 int rv; |
| 757 do { |
| 758 network_moved = false; |
| 759 rv = DoPayloadRead(); |
| 760 if (rv != ERR_IO_PENDING) |
| 761 break; |
| 762 network_moved = DoTransportIO(); |
| 763 } while (network_moved); |
| 764 |
| 765 LeaveFunction(""); |
| 766 return rv; |
| 767 } |
| 768 |
| 769 int SSLClientSocketNSS::DoWriteLoop(int result) { |
| 770 EnterFunction(""); |
| 771 DCHECK(completed_handshake_); |
| 772 DCHECK(next_handshake_state_ == STATE_NONE); |
| 773 |
| 774 if (result < 0) |
| 775 return result; |
| 776 |
| 777 if (!nss_bufs_) |
| 778 return ERR_UNEXPECTED; |
| 779 |
| 780 bool network_moved; |
| 781 int rv; |
| 782 do { |
| 783 network_moved = false; |
| 784 rv = DoPayloadWrite(); |
| 785 if (rv != ERR_IO_PENDING) |
| 786 break; |
| 787 network_moved = DoTransportIO(); |
| 788 } while (network_moved); |
| 789 while (DoTransportIO()) continue; |
| 790 |
| 791 LeaveFunction(""); |
| 792 return rv; |
| 793 } |
678 | 794 |
679 // static | 795 // static |
680 // NSS calls this if an incoming certificate needs to be verified. | 796 // NSS calls this if an incoming certificate needs to be verified. |
681 // Do nothing but return SECSuccess. | 797 // Do nothing but return SECSuccess. |
682 // This is called only in full handshake mode. | 798 // This is called only in full handshake mode. |
683 // Peer certificate is retrieved in HandshakeCallback() later, which is called | 799 // Peer certificate is retrieved in HandshakeCallback() later, which is called |
684 // in full handshake mode or in resumption handshake mode. | 800 // in full handshake mode or in resumption handshake mode. |
685 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, | 801 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, |
686 PRFileDesc* socket, | 802 PRFileDesc* socket, |
687 PRBool checksig, | 803 PRBool checksig, |
688 PRBool is_server) { | 804 PRBool is_server) { |
689 // Tell NSS to not verify the certificate. | 805 // Tell NSS to not verify the certificate. |
690 return SECSuccess; | 806 return SECSuccess; |
691 } | 807 } |
692 | 808 |
693 // static | 809 // static |
694 // NSS calls this when handshake is completed. | 810 // NSS calls this when handshake is completed. |
695 // After the SSL handshake is finished, use CertVerifier to verify | 811 // After the SSL handshake is finished, use CertVerifier to verify |
696 // the saved server certificate. | 812 // the saved server certificate. |
697 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, | 813 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, |
698 void* arg) { | 814 void* arg) { |
699 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 815 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); |
700 | 816 |
701 that->UpdateServerCert(); | 817 that->UpdateServerCert(); |
702 } | 818 } |
703 | 819 |
704 int SSLClientSocketNSS::DoHandshakeRead() { | 820 int SSLClientSocketNSS::DoHandshake() { |
705 EnterFunction(""); | 821 EnterFunction(""); |
706 int net_error = net::OK; | 822 int net_error = net::OK; |
707 int rv = SSL_ForceHandshake(nss_fd_); | 823 int rv = SSL_ForceHandshake(nss_fd_); |
708 | 824 |
709 if (rv == SECSuccess) { | 825 if (rv == SECSuccess) { |
710 // SSL handshake is completed. Let's verify the certificate. | 826 // SSL handshake is completed. Let's verify the certificate. |
711 GotoState(STATE_VERIFY_CERT); | 827 GotoState(STATE_VERIFY_CERT); |
712 // Done! | 828 // Done! |
713 } else { | 829 } else { |
714 PRErrorCode prerr = PR_GetError(); | 830 PRErrorCode prerr = PR_GetError(); |
715 | 831 |
716 // If the server closed on us, it is a protocol error. | 832 // If the server closed on us, it is a protocol error. |
717 // Some TLS-intolerant servers do this when we request TLS. | 833 // Some TLS-intolerant servers do this when we request TLS. |
718 if (prerr == PR_END_OF_FILE_ERROR) { | 834 if (prerr == PR_END_OF_FILE_ERROR) { |
719 net_error = ERR_SSL_PROTOCOL_ERROR; | 835 net_error = ERR_SSL_PROTOCOL_ERROR; |
720 } else { | 836 } else { |
721 net_error = NetErrorFromNSPRError(prerr); | 837 net_error = NetErrorFromNSPRError(prerr); |
722 } | 838 } |
723 | 839 |
724 // If not done, stay in this state | 840 // If not done, stay in this state |
725 if (net_error == ERR_IO_PENDING) { | 841 if (net_error == ERR_IO_PENDING) { |
726 GotoState(STATE_HANDSHAKE_READ); | 842 GotoState(STATE_HANDSHAKE); |
727 } else { | 843 } else { |
728 LOG(ERROR) << "handshake failed; NSS error code " << prerr | 844 LOG(ERROR) << "handshake failed; NSS error code " << prerr |
729 << ", net_error " << net_error; | 845 << ", net_error " << net_error; |
730 } | 846 } |
731 } | 847 } |
732 | 848 |
733 LeaveFunction(""); | 849 LeaveFunction(""); |
734 return net_error; | 850 return net_error; |
735 } | 851 } |
736 | 852 |
737 int SSLClientSocketNSS::DoVerifyCert(int result) { | 853 int SSLClientSocketNSS::DoVerifyCert(int result) { |
738 DCHECK(server_cert_); | 854 DCHECK(server_cert_); |
739 GotoState(STATE_VERIFY_CERT_COMPLETE); | 855 GotoState(STATE_VERIFY_CERT_COMPLETE); |
740 int flags = 0; | 856 int flags = 0; |
741 if (ssl_config_.rev_checking_enabled) | 857 if (ssl_config_.rev_checking_enabled) |
742 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 858 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
743 if (ssl_config_.verify_ev_cert) | 859 if (ssl_config_.verify_ev_cert) |
744 flags |= X509Certificate::VERIFY_EV_CERT; | 860 flags |= X509Certificate::VERIFY_EV_CERT; |
745 verifier_.reset(new CertVerifier); | 861 verifier_.reset(new CertVerifier); |
746 return verifier_->Verify(server_cert_, hostname_, flags, | 862 return verifier_->Verify(server_cert_, hostname_, flags, |
747 &server_cert_verify_result_, &io_callback_); | 863 &server_cert_verify_result_, |
| 864 &handshake_io_callback_); |
748 } | 865 } |
749 | 866 |
750 // Derived from AuthCertificateCallback() in | 867 // Derived from AuthCertificateCallback() in |
751 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. | 868 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. |
752 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { | 869 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { |
753 DCHECK(verifier_.get()); | 870 DCHECK(verifier_.get()); |
754 verifier_.reset(); | 871 verifier_.reset(); |
755 | 872 |
756 if (result == OK) { | 873 if (result == OK) { |
757 // Remember the intermediate CA certs if the server sends them to us. | 874 // Remember the intermediate CA certs if the server sends them to us. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 if (IsCertificateError(result) && | 915 if (IsCertificateError(result) && |
799 ssl_config_.IsAllowedBadCert(server_cert_)) { | 916 ssl_config_.IsAllowedBadCert(server_cert_)) { |
800 LOG(INFO) << "accepting bad SSL certificate, as user told us to"; | 917 LOG(INFO) << "accepting bad SSL certificate, as user told us to"; |
801 result = OK; | 918 result = OK; |
802 } | 919 } |
803 | 920 |
804 completed_handshake_ = true; | 921 completed_handshake_ = true; |
805 // TODO(ukai): we may not need this call because it is now harmless to have an | 922 // TODO(ukai): we may not need this call because it is now harmless to have an |
806 // session with a bad cert. | 923 // session with a bad cert. |
807 InvalidateSessionIfBadCertificate(); | 924 InvalidateSessionIfBadCertificate(); |
808 // Exit DoLoop and return the result to the caller to Connect. | 925 // Exit DoHandshakeLoop and return the result to the caller to Connect. |
809 DCHECK(next_state_ == STATE_NONE); | 926 DCHECK(next_handshake_state_ == STATE_NONE); |
810 return result; | 927 return result; |
811 } | 928 } |
812 | 929 |
813 int SSLClientSocketNSS::DoPayloadRead() { | 930 int SSLClientSocketNSS::DoPayloadRead() { |
814 EnterFunction(user_buf_len_); | 931 EnterFunction(user_read_buf_len_); |
815 int rv = PR_Read(nss_fd_, user_buf_->data(), user_buf_len_); | 932 DCHECK(user_read_buf_); |
| 933 DCHECK(user_read_buf_len_ > 0); |
| 934 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); |
816 if (rv >= 0) { | 935 if (rv >= 0) { |
817 LogData(user_buf_->data(), rv); | 936 LogData(user_read_buf_->data(), rv); |
818 user_buf_ = NULL; | 937 user_read_buf_ = NULL; |
| 938 user_read_buf_len_ = 0; |
819 LeaveFunction(""); | 939 LeaveFunction(""); |
820 return rv; | 940 return rv; |
821 } | 941 } |
822 PRErrorCode prerr = PR_GetError(); | 942 PRErrorCode prerr = PR_GetError(); |
823 if (prerr == PR_WOULD_BLOCK_ERROR) { | 943 if (prerr == PR_WOULD_BLOCK_ERROR) { |
824 GotoState(STATE_PAYLOAD_READ); | |
825 LeaveFunction(""); | 944 LeaveFunction(""); |
826 return ERR_IO_PENDING; | 945 return ERR_IO_PENDING; |
827 } | 946 } |
828 user_buf_ = NULL; | 947 user_read_buf_ = NULL; |
| 948 user_read_buf_len_ = 0; |
829 LeaveFunction(""); | 949 LeaveFunction(""); |
830 return NetErrorFromNSPRError(prerr); | 950 return NetErrorFromNSPRError(prerr); |
831 } | 951 } |
832 | 952 |
833 int SSLClientSocketNSS::DoPayloadWrite() { | 953 int SSLClientSocketNSS::DoPayloadWrite() { |
834 EnterFunction(user_buf_len_); | 954 EnterFunction(user_write_buf_len_); |
835 int rv = PR_Write(nss_fd_, user_buf_->data(), user_buf_len_); | 955 if (!user_write_buf_) |
| 956 return OK; |
| 957 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); |
836 if (rv >= 0) { | 958 if (rv >= 0) { |
837 LogData(user_buf_->data(), rv); | 959 LogData(user_write_buf_->data(), rv); |
838 user_buf_ = NULL; | 960 user_write_buf_ = NULL; |
| 961 user_write_buf_len_ = 0; |
839 LeaveFunction(""); | 962 LeaveFunction(""); |
840 return rv; | 963 return rv; |
841 } | 964 } |
842 PRErrorCode prerr = PR_GetError(); | 965 PRErrorCode prerr = PR_GetError(); |
843 if (prerr == PR_WOULD_BLOCK_ERROR) { | 966 if (prerr == PR_WOULD_BLOCK_ERROR) { |
844 GotoState(STATE_PAYLOAD_WRITE); | |
845 return ERR_IO_PENDING; | 967 return ERR_IO_PENDING; |
846 } | 968 } |
847 user_buf_ = NULL; | 969 user_write_buf_ = NULL; |
| 970 user_write_buf_len_ = 0; |
848 LeaveFunction(""); | 971 LeaveFunction(""); |
849 return NetErrorFromNSPRError(prerr); | 972 return NetErrorFromNSPRError(prerr); |
850 } | 973 } |
851 | 974 |
852 } // namespace net | 975 } // namespace net |
OLD | NEW |