| 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 |