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 |