| 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/ocsp/nss_ocsp.h" | 5 #include "net/ocsp/nss_ocsp.h" |
| 6 | 6 |
| 7 #include <certt.h> | 7 #include <certt.h> |
| 8 #include <certdb.h> | 8 #include <certdb.h> |
| 9 #include <ocsp.h> | 9 #include <ocsp.h> |
| 10 #include <nspr.h> | 10 #include <nspr.h> |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 bool shutdown_; // Protected by |lock_|. | 78 bool shutdown_; // Protected by |lock_|. |
| 79 std::set<OCSPRequestSession*> requests_; // Protected by |lock_|. | 79 std::set<OCSPRequestSession*> requests_; // Protected by |lock_|. |
| 80 bool used_; // Protected by |lock_|. | 80 bool used_; // Protected by |lock_|. |
| 81 // This should not be modified after |used_|. | 81 // This should not be modified after |used_|. |
| 82 MessageLoopForIO* io_loop_; // Protected by |lock_|. | 82 MessageLoopForIO* io_loop_; // Protected by |lock_|. |
| 83 ThreadChecker thread_checker_; | 83 ThreadChecker thread_checker_; |
| 84 | 84 |
| 85 DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop); | 85 DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop); |
| 86 }; | 86 }; |
| 87 | 87 |
| 88 base::LazyInstance<OCSPIOLoop> g_ocsp_io_loop(base::LINKER_INITIALIZED); | 88 base::LazyInstance<OCSPIOLoop, base::LeakyLazyInstanceTraits<OCSPIOLoop> > |
| 89 g_ocsp_io_loop(base::LINKER_INITIALIZED); |
| 89 | 90 |
| 90 const int kRecvBufferSize = 4096; | 91 const int kRecvBufferSize = 4096; |
| 91 | 92 |
| 92 // All OCSP handlers should be called in the context of | 93 // All OCSP handlers should be called in the context of |
| 93 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). | 94 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). |
| 94 // It supports blocking mode only. | 95 // It supports blocking mode only. |
| 95 | 96 |
| 96 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, | 97 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, |
| 97 SEC_HTTP_SERVER_SESSION* pSession); | 98 SEC_HTTP_SERVER_SESSION* pSession); |
| 98 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, | 99 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 } | 554 } |
| 554 | 555 |
| 555 OCSPNSSInitialization::~OCSPNSSInitialization() {} | 556 OCSPNSSInitialization::~OCSPNSSInitialization() {} |
| 556 | 557 |
| 557 | 558 |
| 558 // OCSP Http Client functions. | 559 // OCSP Http Client functions. |
| 559 // Our Http Client functions operate in blocking mode. | 560 // Our Http Client functions operate in blocking mode. |
| 560 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, | 561 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, |
| 561 SEC_HTTP_SERVER_SESSION* pSession) { | 562 SEC_HTTP_SERVER_SESSION* pSession) { |
| 562 VLOG(1) << "OCSP create session: host=" << host << " port=" << portnum; | 563 VLOG(1) << "OCSP create session: host=" << host << " port=" << portnum; |
| 563 DCHECK(!MessageLoop::current()); | |
| 564 pthread_mutex_lock(&g_request_context_lock); | 564 pthread_mutex_lock(&g_request_context_lock); |
| 565 URLRequestContext* request_context = g_request_context; | 565 URLRequestContext* request_context = g_request_context; |
| 566 pthread_mutex_unlock(&g_request_context_lock); | 566 pthread_mutex_unlock(&g_request_context_lock); |
| 567 if (request_context == NULL) { | 567 if (request_context == NULL) { |
| 568 LOG(ERROR) << "No URLRequestContext for OCSP handler."; | 568 LOG(ERROR) << "No URLRequestContext for OCSP handler."; |
| 569 // The application failed to call SetURLRequestContextForOCSP, so we | 569 // The application failed to call SetURLRequestContextForOCSP, so we |
| 570 // can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an | 570 // can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an |
| 571 // accurate error code for this error condition, but is close enough. | 571 // accurate error code for this error condition, but is close enough. |
| 572 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | 572 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
| 573 return SECFailure; | 573 return SECFailure; |
| 574 } | 574 } |
| 575 *pSession = new OCSPServerSession(host, portnum); | 575 *pSession = new OCSPServerSession(host, portnum); |
| 576 return SECSuccess; | 576 return SECSuccess; |
| 577 } | 577 } |
| 578 | 578 |
| 579 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, | 579 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, |
| 580 PRPollDesc **pPollDesc) { | 580 PRPollDesc **pPollDesc) { |
| 581 VLOG(1) << "OCSP keep alive"; | 581 VLOG(1) << "OCSP keep alive"; |
| 582 DCHECK(!MessageLoop::current()); | |
| 583 if (pPollDesc) | 582 if (pPollDesc) |
| 584 *pPollDesc = NULL; | 583 *pPollDesc = NULL; |
| 585 return SECSuccess; | 584 return SECSuccess; |
| 586 } | 585 } |
| 587 | 586 |
| 588 SECStatus OCSPFreeSession(SEC_HTTP_SERVER_SESSION session) { | 587 SECStatus OCSPFreeSession(SEC_HTTP_SERVER_SESSION session) { |
| 589 VLOG(1) << "OCSP free session"; | 588 VLOG(1) << "OCSP free session"; |
| 590 DCHECK(!MessageLoop::current()); | |
| 591 delete reinterpret_cast<OCSPServerSession*>(session); | 589 delete reinterpret_cast<OCSPServerSession*>(session); |
| 592 return SECSuccess; | 590 return SECSuccess; |
| 593 } | 591 } |
| 594 | 592 |
| 595 SECStatus OCSPCreate(SEC_HTTP_SERVER_SESSION session, | 593 SECStatus OCSPCreate(SEC_HTTP_SERVER_SESSION session, |
| 596 const char* http_protocol_variant, | 594 const char* http_protocol_variant, |
| 597 const char* path_and_query_string, | 595 const char* path_and_query_string, |
| 598 const char* http_request_method, | 596 const char* http_request_method, |
| 599 const PRIntervalTime timeout, | 597 const PRIntervalTime timeout, |
| 600 SEC_HTTP_REQUEST_SESSION* pRequest) { | 598 SEC_HTTP_REQUEST_SESSION* pRequest) { |
| 601 VLOG(1) << "OCSP create protocol=" << http_protocol_variant | 599 VLOG(1) << "OCSP create protocol=" << http_protocol_variant |
| 602 << " path_and_query=" << path_and_query_string | 600 << " path_and_query=" << path_and_query_string |
| 603 << " http_request_method=" << http_request_method | 601 << " http_request_method=" << http_request_method |
| 604 << " timeout=" << timeout; | 602 << " timeout=" << timeout; |
| 605 DCHECK(!MessageLoop::current()); | |
| 606 OCSPServerSession* ocsp_session = | 603 OCSPServerSession* ocsp_session = |
| 607 reinterpret_cast<OCSPServerSession*>(session); | 604 reinterpret_cast<OCSPServerSession*>(session); |
| 608 | 605 |
| 609 OCSPRequestSession* req = ocsp_session->CreateRequest(http_protocol_variant, | 606 OCSPRequestSession* req = ocsp_session->CreateRequest(http_protocol_variant, |
| 610 path_and_query_string, | 607 path_and_query_string, |
| 611 http_request_method, | 608 http_request_method, |
| 612 timeout); | 609 timeout); |
| 613 SECStatus rv = SECFailure; | 610 SECStatus rv = SECFailure; |
| 614 if (req) { | 611 if (req) { |
| 615 req->AddRef(); // Release in OCSPFree(). | 612 req->AddRef(); // Release in OCSPFree(). |
| 616 rv = SECSuccess; | 613 rv = SECSuccess; |
| 617 } | 614 } |
| 618 *pRequest = req; | 615 *pRequest = req; |
| 619 return rv; | 616 return rv; |
| 620 } | 617 } |
| 621 | 618 |
| 622 SECStatus OCSPSetPostData(SEC_HTTP_REQUEST_SESSION request, | 619 SECStatus OCSPSetPostData(SEC_HTTP_REQUEST_SESSION request, |
| 623 const char* http_data, | 620 const char* http_data, |
| 624 const PRUint32 http_data_len, | 621 const PRUint32 http_data_len, |
| 625 const char* http_content_type) { | 622 const char* http_content_type) { |
| 626 VLOG(1) << "OCSP set post data len=" << http_data_len; | 623 VLOG(1) << "OCSP set post data len=" << http_data_len; |
| 627 DCHECK(!MessageLoop::current()); | |
| 628 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 624 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
| 629 | 625 |
| 630 req->SetPostData(http_data, http_data_len, http_content_type); | 626 req->SetPostData(http_data, http_data_len, http_content_type); |
| 631 return SECSuccess; | 627 return SECSuccess; |
| 632 } | 628 } |
| 633 | 629 |
| 634 SECStatus OCSPAddHeader(SEC_HTTP_REQUEST_SESSION request, | 630 SECStatus OCSPAddHeader(SEC_HTTP_REQUEST_SESSION request, |
| 635 const char* http_header_name, | 631 const char* http_header_name, |
| 636 const char* http_header_value) { | 632 const char* http_header_value) { |
| 637 VLOG(1) << "OCSP add header name=" << http_header_name | 633 VLOG(1) << "OCSP add header name=" << http_header_name |
| 638 << " value=" << http_header_value; | 634 << " value=" << http_header_value; |
| 639 DCHECK(!MessageLoop::current()); | |
| 640 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 635 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
| 641 | 636 |
| 642 req->AddHeader(http_header_name, http_header_value); | 637 req->AddHeader(http_header_name, http_header_value); |
| 643 return SECSuccess; | 638 return SECSuccess; |
| 644 } | 639 } |
| 645 | 640 |
| 646 // Sets response of |req| in the output parameters. | 641 // Sets response of |req| in the output parameters. |
| 647 // It is helper routine for OCSP trySendAndReceiveFcn. | 642 // It is helper routine for OCSP trySendAndReceiveFcn. |
| 648 // |http_response_data_len| could be used as input parameter. If it has | 643 // |http_response_data_len| could be used as input parameter. If it has |
| 649 // non-zero value, it is considered as maximum size of |http_response_data|. | 644 // non-zero value, it is considered as maximum size of |http_response_data|. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 const char** http_response_headers, | 684 const char** http_response_headers, |
| 690 const char** http_response_data, | 685 const char** http_response_data, |
| 691 PRUint32* http_response_data_len) { | 686 PRUint32* http_response_data_len) { |
| 692 if (http_response_data_len) { | 687 if (http_response_data_len) { |
| 693 // We must always set an output value, even on failure. The output value 0 | 688 // We must always set an output value, even on failure. The output value 0 |
| 694 // means the failure was unrelated to the acceptable response data length. | 689 // means the failure was unrelated to the acceptable response data length. |
| 695 *http_response_data_len = 0; | 690 *http_response_data_len = 0; |
| 696 } | 691 } |
| 697 | 692 |
| 698 VLOG(1) << "OCSP try send and receive"; | 693 VLOG(1) << "OCSP try send and receive"; |
| 699 DCHECK(!MessageLoop::current()); | |
| 700 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 694 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
| 701 // We support blocking mode only. | 695 // We support blocking mode only. |
| 702 if (pPollDesc) | 696 if (pPollDesc) |
| 703 *pPollDesc = NULL; | 697 *pPollDesc = NULL; |
| 704 | 698 |
| 705 if (req->Started() || req->Finished()) { | 699 if (req->Started() || req->Finished()) { |
| 706 // We support blocking mode only, so this function shouldn't be called | 700 // We support blocking mode only, so this function shouldn't be called |
| 707 // again when req has stareted or finished. | 701 // again when req has stareted or finished. |
| 708 NOTREACHED(); | 702 NOTREACHED(); |
| 709 PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE); // Simple approximation. | 703 PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE); // Simple approximation. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 return OCSPSetResponse( | 761 return OCSPSetResponse( |
| 768 req, http_response_code, | 762 req, http_response_code, |
| 769 http_response_content_type, | 763 http_response_content_type, |
| 770 http_response_headers, | 764 http_response_headers, |
| 771 http_response_data, | 765 http_response_data, |
| 772 http_response_data_len); | 766 http_response_data_len); |
| 773 } | 767 } |
| 774 | 768 |
| 775 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request) { | 769 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request) { |
| 776 VLOG(1) << "OCSP free"; | 770 VLOG(1) << "OCSP free"; |
| 777 DCHECK(!MessageLoop::current()); | |
| 778 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 771 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
| 779 req->Cancel(); | 772 req->Cancel(); |
| 780 req->Release(); | 773 req->Release(); |
| 781 return SECSuccess; | 774 return SECSuccess; |
| 782 } | 775 } |
| 783 | 776 |
| 784 // Data for GetAlternateOCSPAIAInfo. | 777 // Data for GetAlternateOCSPAIAInfo. |
| 785 | 778 |
| 786 // CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US | 779 // CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US |
| 787 // | 780 // |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 | 896 |
| 904 URLRequestContext* GetURLRequestContextForOCSP() { | 897 URLRequestContext* GetURLRequestContextForOCSP() { |
| 905 pthread_mutex_lock(&g_request_context_lock); | 898 pthread_mutex_lock(&g_request_context_lock); |
| 906 URLRequestContext* request_context = g_request_context; | 899 URLRequestContext* request_context = g_request_context; |
| 907 pthread_mutex_unlock(&g_request_context_lock); | 900 pthread_mutex_unlock(&g_request_context_lock); |
| 908 DCHECK(!request_context || request_context->is_main()); | 901 DCHECK(!request_context || request_context->is_main()); |
| 909 return request_context; | 902 return request_context; |
| 910 } | 903 } |
| 911 | 904 |
| 912 } // namespace net | 905 } // namespace net |
| OLD | NEW |