OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 #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 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 return SECSuccess; | 592 return SECSuccess; |
593 } | 593 } |
594 | 594 |
595 SECStatus OCSPTrySendAndReceive(SEC_HTTP_REQUEST_SESSION request, | 595 SECStatus OCSPTrySendAndReceive(SEC_HTTP_REQUEST_SESSION request, |
596 PRPollDesc** pPollDesc, | 596 PRPollDesc** pPollDesc, |
597 PRUint16* http_response_code, | 597 PRUint16* http_response_code, |
598 const char** http_response_content_type, | 598 const char** http_response_content_type, |
599 const char** http_response_headers, | 599 const char** http_response_headers, |
600 const char** http_response_data, | 600 const char** http_response_data, |
601 PRUint32* http_response_data_len) { | 601 PRUint32* http_response_data_len) { |
602 if (http_response_data_len) { | 602 base::Time start_time, end_time; |
603 // We must always set an output value, even on failure. The output value 0 | |
604 // means the failure was unrelated to the acceptable response data length. | |
605 *http_response_data_len = 0; | |
606 } | |
607 | 603 |
608 LOG(INFO) << "OCSP try send and receive"; | 604 LOG(INFO) << "OCSP try send and receive"; |
609 DCHECK(!MessageLoop::current()); | 605 DCHECK(!MessageLoop::current()); |
610 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 606 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
611 // We support blocking mode only. | 607 // We support blocking mode only. |
612 if (pPollDesc) | 608 if (pPollDesc) |
613 *pPollDesc = NULL; | 609 *pPollDesc = NULL; |
614 | 610 |
615 if (req->Started() || req->Finished()) { | 611 if (req->Started() || req->Finished()) { |
616 // We support blocking mode only, so this function shouldn't be called | 612 // We support blocking mode only, so this function shouldn't be called |
617 // again when req has stareted or finished. | 613 // again when req has stareted or finished. |
618 NOTREACHED(); | 614 NOTREACHED(); |
619 PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE); // Simple approximation. | 615 goto failed; |
620 return SECFailure; | |
621 } | 616 } |
622 | 617 |
623 const base::Time start_time = base::Time::Now(); | 618 start_time = base::Time::Now(); |
624 req->Start(); | 619 req->Start(); |
625 if (!req->Wait() || req->http_response_code() == static_cast<PRUint16>(-1)) { | 620 if (!req->Wait()) |
626 // If the response code is -1, the request failed and there is no response. | 621 goto failed; |
627 PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE); // Simple approximation. | 622 end_time = base::Time::Now(); |
628 return SECFailure; | |
629 } | |
630 const base::TimeDelta duration = base::Time::Now() - start_time; | |
631 | 623 |
632 // We want to know if this was: | 624 if (req->http_request_method() == "POST") { |
633 // 1) An OCSP request | 625 UMA_HISTOGRAM_TIMES("Net.OCSPRequestTimeMs", end_time - start_time); |
634 // 2) A CRL request | 626 } else if (req->http_request_method() == "GET") { |
635 // 3) A request for a missing intermediate certificate | 627 UMA_HISTOGRAM_TIMES("Net.CRLRequestTimeMs", end_time - start_time); |
636 // There's no sure way to do this, so we use heuristics like MIME type and | |
637 // URL. | |
638 const char* mime_type = req->http_response_content_type().c_str(); | |
639 bool is_ocsp_resp = | |
640 strcasecmp(mime_type, "application/ocsp-response") != NULL; | |
641 bool is_crl_resp = strcasecmp(mime_type, "application/x-pkcs7-crl") != NULL || | |
642 strcasecmp(mime_type, "application/x-x509-crl") != NULL || | |
643 strcasecmp(mime_type, "application/pkix-crl") != NULL; | |
644 bool is_crt_resp = | |
645 strcasecmp(mime_type, "application/x-x509-ca-cert") != NULL || | |
646 strcasecmp(mime_type, "application/x-x509-server-cert") != NULL; | |
647 bool known_resp_type = is_crt_resp || is_crt_resp || is_ocsp_resp; | |
648 | |
649 bool crl_in_url, crt_in_url, ocsp_in_url, have_url_hint; | |
650 if (!known_resp_type) { | |
651 const char* path = req->url().path().c_str(); | |
652 const char* host = req->url().host().c_str(); | |
653 crl_in_url = strcasestr(path, ".crl") != NULL; | |
654 crt_in_url = strcasestr(path, ".crt") != NULL; | |
655 ocsp_in_url = strcasestr(host, "ocsp") != NULL; | |
656 have_url_hint = crl_in_url || crt_in_url || ocsp_in_url; | |
657 } | 628 } |
658 | 629 |
659 if (is_ocsp_resp || | 630 // If the response code is -1, the request failed and there is no response. |
660 (!known_resp_type && (ocsp_in_url || | 631 if (req->http_response_code() == static_cast<PRUint16>(-1)) |
661 (!have_url_hint && | 632 goto failed; |
662 req->http_request_method() == "POST")))) { | |
663 UMA_HISTOGRAM_TIMES("Net.OCSPRequestTimeMs", duration); | |
664 } else if (is_crl_resp || (!known_resp_type && crl_in_url)) { | |
665 UMA_HISTOGRAM_TIMES("Net.CRLRequestTimeMs", duration); | |
666 } else if (is_crt_resp || (!known_resp_type && crt_in_url)) { | |
667 UMA_HISTOGRAM_TIMES("Net.CRTRequestTimeMs", duration); | |
668 } else { | |
669 UMA_HISTOGRAM_TIMES("Net.UnknownTypeRequestTimeMs", duration); | |
670 } | |
671 | 633 |
672 return OCSPSetResponse( | 634 return OCSPSetResponse( |
673 req, http_response_code, | 635 req, http_response_code, |
674 http_response_content_type, | 636 http_response_content_type, |
675 http_response_headers, | 637 http_response_headers, |
676 http_response_data, | 638 http_response_data, |
677 http_response_data_len); | 639 http_response_data_len); |
| 640 |
| 641 failed: |
| 642 if (http_response_data_len) { |
| 643 // We must always set an output value, even on failure. The output value 0 |
| 644 // means the failure was unrelated to the acceptable response data length. |
| 645 *http_response_data_len = 0; |
| 646 } |
| 647 PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE); // Simple approximation. |
| 648 return SECFailure; |
678 } | 649 } |
679 | 650 |
680 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request) { | 651 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request) { |
681 LOG(INFO) << "OCSP free"; | 652 LOG(INFO) << "OCSP free"; |
682 DCHECK(!MessageLoop::current()); | 653 DCHECK(!MessageLoop::current()); |
683 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 654 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
684 req->Cancel(); | 655 req->Cancel(); |
685 req->Release(); | 656 req->Release(); |
686 return SECSuccess; | 657 return SECSuccess; |
687 } | 658 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 // This function would be called before NSS initialization. | 754 // This function would be called before NSS initialization. |
784 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { | 755 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { |
785 OCSPInitSingleton::set_url_request_context(request_context); | 756 OCSPInitSingleton::set_url_request_context(request_context); |
786 } | 757 } |
787 | 758 |
788 URLRequestContext* GetURLRequestContextForOCSP() { | 759 URLRequestContext* GetURLRequestContextForOCSP() { |
789 return OCSPInitSingleton::url_request_context(); | 760 return OCSPInitSingleton::url_request_context(); |
790 } | 761 } |
791 | 762 |
792 } // namespace net | 763 } // namespace net |
OLD | NEW |