Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: nss/lib/certhigh/ocsp.c

Issue 105893015: Update third_party/nss to NSS 3.15.4. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Remove SVN property on new file nss/lib/freebl/rsapkcs.c Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « nss/lib/certhigh/ocsp.h ('k') | nss/lib/certhigh/ocspi.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* This Source Code Form is subject to the terms of the Mozilla Public 1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 4
5 /* 5 /*
6 * Implementation of OCSP services, for both client and server. 6 * Implementation of OCSP services, for both client and server.
7 * (XXX, really, mostly just for client right now, but intended to do both.) 7 * (XXX, really, mostly just for client right now, but intended to do both.)
8 */ 8 */
9 9
10 #include "prerror.h" 10 #include "prerror.h"
11 #include "prprf.h" 11 #include "prprf.h"
12 #include "plarena.h" 12 #include "plarena.h"
13 #include "prnetdb.h" 13 #include "prnetdb.h"
14 14
15 #include "seccomon.h" 15 #include "seccomon.h"
16 #include "secitem.h" 16 #include "secitem.h"
17 #include "secoidt.h" 17 #include "secoidt.h"
18 #include "secasn1.h" 18 #include "secasn1.h"
19 #include "secder.h" 19 #include "secder.h"
20 #include "cert.h" 20 #include "cert.h"
21 #include "xconst.h" 21 #include "xconst.h"
22 #include "secerr.h" 22 #include "secerr.h"
23 #include "secoid.h" 23 #include "secoid.h"
24 #include "hasht.h" 24 #include "hasht.h"
25 #include "sechash.h" 25 #include "sechash.h"
26 #include "secasn1.h" 26 #include "secasn1.h"
27 #include "plbase64.h"
27 #include "keyhi.h" 28 #include "keyhi.h"
28 #include "cryptohi.h" 29 #include "cryptohi.h"
29 #include "ocsp.h" 30 #include "ocsp.h"
30 #include "ocspti.h" 31 #include "ocspti.h"
31 #include "ocspi.h" 32 #include "ocspi.h"
32 #include "genname.h" 33 #include "genname.h"
33 #include "certxutl.h" 34 #include "certxutl.h"
34 #include "pk11func.h" /* for PK11_HashBuf */ 35 #include "pk11func.h" /* for PK11_HashBuf */
35 #include <stdarg.h> 36 #include <stdarg.h>
36 #include <plhash.h> 37 #include <plhash.h>
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 static struct OCSPGlobalStruct { 80 static struct OCSPGlobalStruct {
80 PRMonitor *monitor; 81 PRMonitor *monitor;
81 const SEC_HttpClientFcn *defaultHttpClientFcn; 82 const SEC_HttpClientFcn *defaultHttpClientFcn;
82 PRInt32 maxCacheEntries; 83 PRInt32 maxCacheEntries;
83 PRUint32 minimumSecondsToNextFetchAttempt; 84 PRUint32 minimumSecondsToNextFetchAttempt;
84 PRUint32 maximumSecondsToNextFetchAttempt; 85 PRUint32 maximumSecondsToNextFetchAttempt;
85 PRUint32 timeoutSeconds; 86 PRUint32 timeoutSeconds;
86 OCSPCacheData cache; 87 OCSPCacheData cache;
87 SEC_OcspFailureMode ocspFailureMode; 88 SEC_OcspFailureMode ocspFailureMode;
88 CERT_StringFromCertFcn alternateOCSPAIAFcn; 89 CERT_StringFromCertFcn alternateOCSPAIAFcn;
90 PRBool forcePost;
89 } OCSP_Global = { NULL, 91 } OCSP_Global = { NULL,
90 NULL, 92 NULL,
91 DEFAULT_OCSP_CACHE_SIZE, 93 DEFAULT_OCSP_CACHE_SIZE,
92 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, 94 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
93 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, 95 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
94 DEFAULT_OSCP_TIMEOUT_SECONDS, 96 DEFAULT_OSCP_TIMEOUT_SECONDS,
95 {NULL, 0, NULL, NULL}, 97 {NULL, 0, NULL, NULL},
96 ocspMode_FailureIsVerificationFailure, 98 ocspMode_FailureIsVerificationFailure,
97 NULL 99 NULL,
100 PR_FALSE
98 }; 101 };
99 102
100 103
101 104
102 /* Forward declarations */ 105 /* Forward declarations */
103 static SECItem * 106 static SECItem *
104 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, 107 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena,
105 CERTOCSPRequest *request, 108 CERTOCSPRequest *request,
106 const char *location, PRTime time, 109 const char *location,
110 » » » » const char *method,
111 » » » » PRTime time,
107 PRBool addServiceLocator, 112 PRBool addServiceLocator,
108 void *pwArg, 113 void *pwArg,
109 CERTOCSPRequest **pRequest); 114 CERTOCSPRequest **pRequest);
110 static SECStatus 115 static SECStatus
111 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 116 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
112 CERTOCSPCertID *certID, 117 CERTOCSPCertID *certID,
113 CERTCertificate *cert, 118 CERTCertificate *cert,
114 PRTime time, 119 PRTime time,
115 void *pwArg, 120 void *pwArg,
116 PRBool *certIDWasConsumed, 121 PRBool *certIDWasConsumed,
117 SECStatus *rv_ocsp); 122 SECStatus *rv_ocsp);
118 123
119 static SECStatus 124 static SECStatus
120 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, 125 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle,
121 » » » CERTOCSPCertID *certID, 126 » » » » » CERTOCSPCertID *certID,
122 » » » CERTCertificate *cert, 127 » » » » » CERTCertificate *cert,
123 » » » PRTime time, 128 » » » » » PRTime time,
124 » » » void *pwArg, 129 » » » » » void *pwArg,
125 » » » const SECItem *encodedResponse, 130 » » » » » const SECItem *encodedResponse,
126 » » » PRBool cacheInvalid, 131 » » » » » CERTOCSPResponse **pDecodedResponse,
127 » » » PRBool *certIDWasConsumed, 132 » » » » » CERTOCSPSingleResponse **pSingle);
128 » » » SECStatus *rv_ocsp);
129
130 static SECStatus
131 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
132 CERTOCSPResponse *response,
133 CERTOCSPCertID *certID,
134 CERTCertificate *signerCert,
135 PRTime time,
136 CERTOCSPSingleResponse **pSingleResponse );
137 133
138 static SECStatus 134 static SECStatus
139 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time); 135 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time);
140 136
141 static CERTOCSPCertID * 137 static CERTOCSPCertID *
142 cert_DupOCSPCertID(const CERTOCSPCertID *src); 138 cert_DupOCSPCertID(const CERTOCSPCertID *src);
143 139
144 #ifndef DEBUG 140 #ifndef DEBUG
145 #define OCSP_TRACE(msg) 141 #define OCSP_TRACE(msg)
146 #define OCSP_TRACE_TIME(msg, time) 142 #define OCSP_TRACE_TIME(msg, time)
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 OCSP_TRACE_TIME("nextFetchAttemptTime", 743 OCSP_TRACE_TIME("nextFetchAttemptTime",
748 latestTimeWhenResponseIsConsideredFresh); 744 latestTimeWhenResponseIsConsideredFresh);
749 745
750 PR_ExitMonitor(OCSP_Global.monitor); 746 PR_ExitMonitor(OCSP_Global.monitor);
751 } 747 }
752 748
753 static PRBool 749 static PRBool
754 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem) 750 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem)
755 { 751 {
756 PRTime now; 752 PRTime now;
757 PRBool retval; 753 PRBool fresh;
758 754
759 PR_EnterMonitor(OCSP_Global.monitor);
760 now = PR_Now(); 755 now = PR_Now();
761 retval = (cacheItem->nextFetchAttemptTime > now); 756
762 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval)); 757 fresh = cacheItem->nextFetchAttemptTime > now;
763 PR_ExitMonitor(OCSP_Global.monitor); 758
764 return retval; 759 /* Work around broken OCSP responders that return unknown responses for
760 * certificates, especially certificates that were just recently issued.
761 */
762 if (fresh && cacheItem->certStatusArena &&
763 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown) {
764 fresh = PR_FALSE;
765 }
766
767 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", fresh));
768
769 return fresh;
765 } 770 }
766 771
767 /* 772 /*
768 * Status in *certIDWasConsumed will always be correct, regardless of 773 * Status in *certIDWasConsumed will always be correct, regardless of
769 * return value. 774 * return value.
770 * If the caller is unable to transfer ownership of certID, 775 * If the caller is unable to transfer ownership of certID,
771 * then the caller must set certIDWasConsumed to NULL, 776 * then the caller must set certIDWasConsumed to NULL,
772 * and this function will potentially duplicate the certID object. 777 * and this function will potentially duplicate the certID object.
773 */ 778 */
774 static SECStatus 779 static SECStatus
775 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, 780 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache,
776 CERTOCSPCertID *certID, 781 CERTOCSPCertID *certID,
777 CERTOCSPSingleResponse *single, 782 CERTOCSPSingleResponse *single,
778 PRBool *certIDWasConsumed) 783 PRBool *certIDWasConsumed)
779 { 784 {
780 SECStatus rv; 785 SECStatus rv;
781 OCSPCacheItem *cacheItem; 786 OCSPCacheItem *cacheItem;
782 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); 787 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
783 788
784 if (certIDWasConsumed) 789 if (certIDWasConsumed)
785 *certIDWasConsumed = PR_FALSE; 790 *certIDWasConsumed = PR_FALSE;
786 791
787 PR_EnterMonitor(OCSP_Global.monitor); 792 PR_EnterMonitor(OCSP_Global.monitor);
788 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); 793 PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
789 794
790 cacheItem = ocsp_FindCacheEntry(cache, certID); 795 cacheItem = ocsp_FindCacheEntry(cache, certID);
796
797 /* Don't replace an unknown or revoked entry with an error entry, even if
798 * the existing entry is expired. Instead, we'll continue to use the
799 * existing (possibly expired) cache entry until we receive a valid signed
800 * response to replace it.
801 */
802 if (!single && cacheItem && cacheItem->certStatusArena &&
803 (cacheItem->certStatus.certStatusType == ocspCertStatus_revoked ||
804 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown)) {
805 PR_ExitMonitor(OCSP_Global.monitor);
806 return SECSuccess;
807 }
808
791 if (!cacheItem) { 809 if (!cacheItem) {
792 CERTOCSPCertID *myCertID; 810 CERTOCSPCertID *myCertID;
793 if (certIDWasConsumed) { 811 if (certIDWasConsumed) {
794 myCertID = certID; 812 myCertID = certID;
795 *certIDWasConsumed = PR_TRUE; 813 *certIDWasConsumed = PR_TRUE;
796 } else { 814 } else {
797 myCertID = cert_DupOCSPCertID(certID); 815 myCertID = cert_DupOCSPCertID(certID);
798 if (!myCertID) { 816 if (!myCertID) {
799 PR_ExitMonitor(OCSP_Global.monitor); 817 PR_ExitMonitor(OCSP_Global.monitor);
800 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 818 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 * not needed if not signing.) 1471 * not needed if not signing.)
1454 * RETURN: 1472 * RETURN:
1455 * Returns a NULL on error and a pointer to the SECItem with the 1473 * Returns a NULL on error and a pointer to the SECItem with the
1456 * encoded value otherwise. Any error is likely to be low-level 1474 * encoded value otherwise. Any error is likely to be low-level
1457 * (e.g. no memory). 1475 * (e.g. no memory).
1458 */ 1476 */
1459 SECItem * 1477 SECItem *
1460 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request, 1478 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request,
1461 void *pwArg) 1479 void *pwArg)
1462 { 1480 {
1463 ocspTBSRequest *tbsRequest;
1464 SECStatus rv; 1481 SECStatus rv;
1465 1482
1466 /* XXX All of these should generate errors if they fail. */ 1483 /* XXX All of these should generate errors if they fail. */
1467 PORT_Assert(request); 1484 PORT_Assert(request);
1468 PORT_Assert(request->tbsRequest); 1485 PORT_Assert(request->tbsRequest);
1469 1486
1470 tbsRequest = request->tbsRequest;
1471
1472 if (request->tbsRequest->extensionHandle != NULL) { 1487 if (request->tbsRequest->extensionHandle != NULL) {
1473 rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle); 1488 rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
1474 request->tbsRequest->extensionHandle = NULL; 1489 request->tbsRequest->extensionHandle = NULL;
1475 if (rv != SECSuccess) 1490 if (rv != SECSuccess)
1476 return NULL; 1491 return NULL;
1477 } 1492 }
1478 1493
1479 /* 1494 /*
1480 * XXX When signed requests are supported and request->optionalSignature 1495 * XXX When signed requests are supported and request->optionalSignature
1481 * is not NULL: 1496 * is not NULL:
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 } 1644 }
1630 1645
1631 /* 1646 /*
1632 * Digest the cert's subject public key using the specified algorithm. 1647 * Digest the cert's subject public key using the specified algorithm.
1633 * The necessary storage for the digest data is allocated. If "fill" is 1648 * The necessary storage for the digest data is allocated. If "fill" is
1634 * non-null, the data is put there, otherwise a SECItem is allocated. 1649 * non-null, the data is put there, otherwise a SECItem is allocated.
1635 * Allocation from "arena" if it is non-null, heap otherwise. Any problem 1650 * Allocation from "arena" if it is non-null, heap otherwise. Any problem
1636 * results in a NULL being returned (and an appropriate error set). 1651 * results in a NULL being returned (and an appropriate error set).
1637 */ 1652 */
1638 SECItem * 1653 SECItem *
1639 CERT_GetSPKIDigest(PLArenaPool *arena, const CERTCertificate *cert, 1654 CERT_GetSubjectPublicKeyDigest(PLArenaPool *arena, const CERTCertificate *cert,
1640 SECOidTag digestAlg, SECItem *fill) 1655 SECOidTag digestAlg, SECItem *fill)
1641 { 1656 {
1642 SECItem spk; 1657 SECItem spk;
1643 1658
1644 /* 1659 /*
1645 * Copy just the length and data pointer (nothing needs to be freed) 1660 * Copy just the length and data pointer (nothing needs to be freed)
1646 * of the subject public key so we can convert the length from bits 1661 * of the subject public key so we can convert the length from bits
1647 * to bytes, which is what the digest function expects. 1662 * to bytes, which is what the digest function expects.
1648 */ 1663 */
1649 spk = cert->subjectPublicKeyInfo.subjectPublicKey; 1664 spk = cert->subjectPublicKeyInfo.subjectPublicKey;
1650 DER_ConvertBitString(&spk); 1665 DER_ConvertBitString(&spk);
1651 1666
1652 return ocsp_DigestValue(arena, digestAlg, fill, &spk); 1667 return ocsp_DigestValue(arena, digestAlg, fill, &spk);
1653 } 1668 }
1654 1669
1655 /* 1670 /*
1656 * Digest the cert's subject name using the specified algorithm. 1671 * Digest the cert's subject name using the specified algorithm.
1657 */ 1672 */
1658 static SECItem * 1673 SECItem *
1659 cert_GetSubjectNameDigest(PLArenaPool *arena, const CERTCertificate *cert, 1674 CERT_GetSubjectNameDigest(PLArenaPool *arena, const CERTCertificate *cert,
1660 SECOidTag digestAlg, SECItem *fill) 1675 SECOidTag digestAlg, SECItem *fill)
1661 { 1676 {
1662 SECItem name; 1677 SECItem name;
1663 1678
1664 /* 1679 /*
1665 * Copy just the length and data pointer (nothing needs to be freed) 1680 * Copy just the length and data pointer (nothing needs to be freed)
1666 * of the subject name 1681 * of the subject name
1667 */ 1682 */
1668 name = cert->derSubject; 1683 name = cert->derSubject;
1669 1684
1670 return ocsp_DigestValue(arena, digestAlg, fill, &name); 1685 return ocsp_DigestValue(arena, digestAlg, fill, &name);
(...skipping 28 matching lines...) Expand all
1699 NULL); 1714 NULL);
1700 if (rv != SECSuccess) { 1715 if (rv != SECSuccess) {
1701 goto loser; 1716 goto loser;
1702 } 1717 }
1703 1718
1704 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); 1719 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
1705 if (issuerCert == NULL) { 1720 if (issuerCert == NULL) {
1706 goto loser; 1721 goto loser;
1707 } 1722 }
1708 1723
1709 if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1, 1724 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1,
1710 &(certID->issuerNameHash)) == NULL) { 1725 &(certID->issuerNameHash)) == NULL) {
1711 goto loser; 1726 goto loser;
1712 } 1727 }
1713 certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; 1728 certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
1714 certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; 1729 certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
1715 1730
1716 if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5, 1731 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5,
1717 &(certID->issuerMD5NameHash)) == NULL) { 1732 &(certID->issuerMD5NameHash)) == NULL) {
1718 goto loser; 1733 goto loser;
1719 } 1734 }
1720 1735
1721 if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2, 1736 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2,
1722 &(certID->issuerMD2NameHash)) == NULL) { 1737 &(certID->issuerMD2NameHash)) == NULL) {
1723 goto loser; 1738 goto loser;
1724 } 1739 }
1725 1740
1726 if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_SHA1, 1741 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_SHA1,
1727 » » » » &(certID->issuerKeyHash)) == NULL) { 1742 » » » » &certID->issuerKeyHash) == NULL) {
1728 goto loser; 1743 goto loser;
1729 } 1744 }
1730 certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; 1745 certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
1731 certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; 1746 certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
1732 /* cache the other two hash algorithms as well */ 1747 /* cache the other two hash algorithms as well */
1733 if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_MD5, 1748 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD5,
1734 » » » » &(certID->issuerMD5KeyHash)) == NULL) { 1749 » » » » &certID->issuerMD5KeyHash) == NULL) {
1735 goto loser; 1750 goto loser;
1736 } 1751 }
1737 if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_MD2, 1752 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD2,
1738 » » » » &(certID->issuerMD2KeyHash)) == NULL) { 1753 » » » » &certID->issuerMD2KeyHash) == NULL) {
1739 goto loser; 1754 goto loser;
1740 } 1755 }
1741 1756
1742 1757
1743 /* now we are done with issuerCert */ 1758 /* now we are done with issuerCert */
1744 CERT_DestroyCertificate(issuerCert); 1759 CERT_DestroyCertificate(issuerCert);
1745 issuerCert = NULL; 1760 issuerCert = NULL;
1746 1761
1747 rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber); 1762 rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
1748 if (rv != SECSuccess) { 1763 if (rv != SECSuccess) {
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after
2973 return NULL; 2988 return NULL;
2974 } 2989 }
2975 2990
2976 /* 2991 /*
2977 * Sends an encoded OCSP request to the server identified by "location", 2992 * Sends an encoded OCSP request to the server identified by "location",
2978 * and returns the socket on which it was sent (so can listen for the reply). 2993 * and returns the socket on which it was sent (so can listen for the reply).
2979 * "location" is expected to be a valid URL -- an error parsing it produces 2994 * "location" is expected to be a valid URL -- an error parsing it produces
2980 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems 2995 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems
2981 * connecting to it, or writing to it, or allocating memory, and the low-level 2996 * connecting to it, or writing to it, or allocating memory, and the low-level
2982 * errors appropriate to the problem will be set. 2997 * errors appropriate to the problem will be set.
2998 * if (encodedRequest == NULL)
2999 * then location MUST already include the full request,
3000 * including base64 and urlencode,
3001 * and the request will be sent with GET
3002 * if (encodedRequest != NULL)
3003 * then the request will be sent with POST
2983 */ 3004 */
2984 static PRFileDesc * 3005 static PRFileDesc *
2985 ocsp_SendEncodedRequest(const char *location, const SECItem *encodedRequest) 3006 ocsp_SendEncodedRequest(const char *location, const SECItem *encodedRequest)
2986 { 3007 {
2987 char *hostname = NULL; 3008 char *hostname = NULL;
2988 char *path = NULL; 3009 char *path = NULL;
2989 PRUint16 port; 3010 PRUint16 port;
2990 SECStatus rv; 3011 SECStatus rv;
2991 PRFileDesc *sock = NULL; 3012 PRFileDesc *sock = NULL;
2992 PRFileDesc *returnSock = NULL; 3013 PRFileDesc *returnSock = NULL;
(...skipping 12 matching lines...) Expand all
3005 3026
3006 sock = ocsp_ConnectToHost(hostname, port); 3027 sock = ocsp_ConnectToHost(hostname, port);
3007 if (sock == NULL) 3028 if (sock == NULL)
3008 goto loser; 3029 goto loser;
3009 3030
3010 portstr[0] = '\0'; 3031 portstr[0] = '\0';
3011 if (port != 80) { 3032 if (port != 80) {
3012 PR_snprintf(portstr, sizeof(portstr), ":%d", port); 3033 PR_snprintf(portstr, sizeof(portstr), ":%d", port);
3013 } 3034 }
3014 3035
3015 header = PR_smprintf("POST %s HTTP/1.0\r\n" 3036 if (!encodedRequest) {
3016 » » » "Host: %s%s\r\n" 3037 header = PR_smprintf("GET %s HTTP/1.0\r\n"
3017 » » » "Content-Type: application/ocsp-request\r\n" 3038 "Host: %s%s\r\n\r\n",
3018 » » » "Content-Length: %u\r\n\r\n", 3039 path, hostname, portstr);
3019 » » » path, hostname, portstr, encodedRequest->len); 3040 if (header == NULL)
3020 if (header == NULL) 3041 goto loser;
3021 » goto loser;
3022 3042
3023 /* 3043 /*
3024 * The NSPR documentation promises that if it can, it will write the full 3044 * The NSPR documentation promises that if it can, it will write the full
3025 * amount; this will not return a partial value expecting us to loop. 3045 * amount; this will not return a partial value expecting us to loop.
3026 */ 3046 */
3027 if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0) 3047 if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
3028 » goto loser; 3048 goto loser;
3049 }
3050 else {
3051 header = PR_smprintf("POST %s HTTP/1.0\r\n"
3052 "Host: %s%s\r\n"
3053 "Content-Type: application/ocsp-request\r\n"
3054 "Content-Length: %u\r\n\r\n",
3055 path, hostname, portstr, encodedRequest->len);
3056 if (header == NULL)
3057 goto loser;
3029 3058
3030 if (PR_Write(sock, encodedRequest->data, 3059 /*
3031 » » (PRInt32) encodedRequest->len) < 0) 3060 * The NSPR documentation promises that if it can, it will write the full
3032 » goto loser; 3061 * amount; this will not return a partial value expecting us to loop.
3062 */
3063 if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
3064 goto loser;
3065
3066 if (PR_Write(sock, encodedRequest->data,
3067 (PRInt32) encodedRequest->len) < 0)
3068 goto loser;
3069 }
3033 3070
3034 returnSock = sock; 3071 returnSock = sock;
3035 sock = NULL; 3072 sock = NULL;
3036 3073
3037 loser: 3074 loser:
3038 if (header != NULL) 3075 if (header != NULL)
3039 PORT_Free(header); 3076 PORT_Free(header);
3040 if (sock != NULL) 3077 if (sock != NULL)
3041 PR_Close(sock); 3078 PR_Close(sock);
3042 if (path != NULL) 3079 if (path != NULL)
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
3331 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) 3368 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath)
3332 { 3369 {
3333 return ocsp_ParseURL(url, pHostname, pPort, pPath); 3370 return ocsp_ParseURL(url, pHostname, pPort, pPath);
3334 } 3371 }
3335 3372
3336 /* 3373 /*
3337 * Limit the size of http responses we are willing to accept. 3374 * Limit the size of http responses we are willing to accept.
3338 */ 3375 */
3339 #define MAX_WANTED_OCSP_RESPONSE_LEN 64*1024 3376 #define MAX_WANTED_OCSP_RESPONSE_LEN 64*1024
3340 3377
3378 /* if (encodedRequest == NULL)
3379 * then location MUST already include the full request,
3380 * including base64 and urlencode,
3381 * and the request will be sent with GET
3382 * if (encodedRequest != NULL)
3383 * then the request will be sent with POST
3384 */
3341 static SECItem * 3385 static SECItem *
3342 fetchOcspHttpClientV1(PLArenaPool *arena, 3386 fetchOcspHttpClientV1(PLArenaPool *arena,
3343 const SEC_HttpClientFcnV1 *hcv1, 3387 const SEC_HttpClientFcnV1 *hcv1,
3344 const char *location, 3388 const char *location,
3345 const SECItem *encodedRequest) 3389 const SECItem *encodedRequest)
3346 { 3390 {
3347 char *hostname = NULL; 3391 char *hostname = NULL;
3348 char *path = NULL; 3392 char *path = NULL;
3349 PRUint16 port; 3393 PRUint16 port;
3350 SECItem *encodedResponse = NULL; 3394 SECItem *encodedResponse = NULL;
(...skipping 23 matching lines...) Expand all
3374 - the client will use blocking I/O 3418 - the client will use blocking I/O
3375 - TryFcn will not return WOULD_BLOCK nor a poll descriptor 3419 - TryFcn will not return WOULD_BLOCK nor a poll descriptor
3376 - it's sufficient to call TryFcn once 3420 - it's sufficient to call TryFcn once
3377 No lock for accessing OCSP_Global.timeoutSeconds, bug 406120 3421 No lock for accessing OCSP_Global.timeoutSeconds, bug 406120
3378 */ 3422 */
3379 3423
3380 if ((*hcv1->createFcn)( 3424 if ((*hcv1->createFcn)(
3381 pServerSession, 3425 pServerSession,
3382 "http", 3426 "http",
3383 path, 3427 path,
3384 "POST", 3428 encodedRequest ? "POST" : "GET",
3385 PR_TicksPerSecond() * OCSP_Global.timeoutSeconds, 3429 PR_TicksPerSecond() * OCSP_Global.timeoutSeconds,
3386 &pRequestSession) != SECSuccess) { 3430 &pRequestSession) != SECSuccess) {
3387 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3431 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
3388 goto loser; 3432 goto loser;
3389 } 3433 }
3390 3434
3391 if ((*hcv1->setPostDataFcn)( 3435 if (encodedRequest &&
3436 (*hcv1->setPostDataFcn)(
3392 pRequestSession, 3437 pRequestSession,
3393 (char*)encodedRequest->data, 3438 (char*)encodedRequest->data,
3394 encodedRequest->len, 3439 encodedRequest->len,
3395 "application/ocsp-request") != SECSuccess) { 3440 "application/ocsp-request") != SECSuccess) {
3396 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3441 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
3397 goto loser; 3442 goto loser;
3398 } 3443 }
3399 3444
3400 /* we don't want result objects larger than this: */ 3445 /* we don't want result objects larger than this: */
3401 myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN; 3446 myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3437 (*hcv1->freeSessionFcn)(pServerSession); 3482 (*hcv1->freeSessionFcn)(pServerSession);
3438 if (path != NULL) 3483 if (path != NULL)
3439 PORT_Free(path); 3484 PORT_Free(path);
3440 if (hostname != NULL) 3485 if (hostname != NULL)
3441 PORT_Free(hostname); 3486 PORT_Free(hostname);
3442 3487
3443 return encodedResponse; 3488 return encodedResponse;
3444 } 3489 }
3445 3490
3446 /* 3491 /*
3447 * FUNCTION: CERT_GetEncodedOCSPResponse 3492 * FUNCTION: CERT_GetEncodedOCSPResponseByMethod
3448 * Creates and sends a request to an OCSP responder, then reads and 3493 * Creates and sends a request to an OCSP responder, then reads and
3449 * returns the (encoded) response. 3494 * returns the (encoded) response.
3450 * INPUTS: 3495 * INPUTS:
3451 * PLArenaPool *arena 3496 * PLArenaPool *arena
3452 * Pointer to arena from which return value will be allocated. 3497 * Pointer to arena from which return value will be allocated.
3453 * If NULL, result will be allocated from the heap (and thus should 3498 * If NULL, result will be allocated from the heap (and thus should
3454 * be freed via SECITEM_FreeItem). 3499 * be freed via SECITEM_FreeItem).
3455 * CERTCertList *certList 3500 * CERTCertList *certList
3456 * A list of certs for which status will be requested. 3501 * A list of certs for which status will be requested.
3457 * Note that all of these certificates should have the same issuer, 3502 * Note that all of these certificates should have the same issuer,
3458 * or it's expected the response will be signed by a trusted responder. 3503 * or it's expected the response will be signed by a trusted responder.
3459 * If the certs need to be broken up into multiple requests, that 3504 * If the certs need to be broken up into multiple requests, that
3460 * must be handled by the caller (and thus by having multiple calls 3505 * must be handled by the caller (and thus by having multiple calls
3461 * to this routine), who knows about where the request(s) are being 3506 * to this routine), who knows about where the request(s) are being
3462 * sent and whether there are any trusted responders in place. 3507 * sent and whether there are any trusted responders in place.
3463 * const char *location 3508 * const char *location
3464 * The location of the OCSP responder (a URL). 3509 * The location of the OCSP responder (a URL).
3510 * const char *method
3511 * The protocol method used when retrieving the OCSP response.
3512 * Currently support: "GET" (http GET) and "POST" (http POST).
3513 * Additionals methods for http or other protocols might be added
3514 * in the future.
3465 * PRTime time 3515 * PRTime time
3466 * Indicates the time for which the certificate status is to be 3516 * Indicates the time for which the certificate status is to be
3467 * determined -- this may be used in the search for the cert's issuer 3517 * determined -- this may be used in the search for the cert's issuer
3468 * but has no other bearing on the operation. 3518 * but has no other bearing on the operation.
3469 * PRBool addServiceLocator 3519 * PRBool addServiceLocator
3470 * If true, the Service Locator extension should be added to the 3520 * If true, the Service Locator extension should be added to the
3471 * single request(s) for each cert. 3521 * single request(s) for each cert.
3472 * CERTCertificate *signerCert 3522 * CERTCertificate *signerCert
3473 * If non-NULL, means sign the request using this cert. Otherwise, 3523 * If non-NULL, means sign the request using this cert. Otherwise,
3474 * do not sign. 3524 * do not sign.
3475 * void *pwArg 3525 * void *pwArg
3476 * Pointer to argument for password prompting, if needed. (Definitely 3526 * Pointer to argument for password prompting, if needed. (Definitely
3477 * not needed if not signing.) 3527 * not needed if not signing.)
3478 * OUTPUTS: 3528 * OUTPUTS:
3479 * CERTOCSPRequest **pRequest 3529 * CERTOCSPRequest **pRequest
3480 * Pointer in which to store the OCSP request created for the given 3530 * Pointer in which to store the OCSP request created for the given
3481 * list of certificates. It is only filled in if the entire operation 3531 * list of certificates. It is only filled in if the entire operation
3482 * is successful and the pointer is not null -- and in that case the 3532 * is successful and the pointer is not null -- and in that case the
3483 * caller is then reponsible for destroying it. 3533 * caller is then reponsible for destroying it.
3484 * RETURN: 3534 * RETURN:
3485 * Returns a pointer to the SECItem holding the response. 3535 * Returns a pointer to the SECItem holding the response.
3486 * On error, returns null with error set describing the reason: 3536 * On error, returns null with error set describing the reason:
3487 * SEC_ERROR_UNKNOWN_ISSUER 3537 * SEC_ERROR_UNKNOWN_ISSUER
3488 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION 3538 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION
3489 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE 3539 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
3490 * Other errors are low-level problems (no memory, bad database, etc.). 3540 * Other errors are low-level problems (no memory, bad database, etc.).
3491 */ 3541 */
3492 SECItem * 3542 SECItem *
3543 CERT_GetEncodedOCSPResponseByMethod(PLArenaPool *arena, CERTCertList *certList,
3544 const char *location, const char *method,
3545 PRTime time, PRBool addServiceLocator,
3546 CERTCertificate *signerCert, void *pwArg,
3547 CERTOCSPRequest **pRequest)
3548 {
3549 CERTOCSPRequest *request;
3550 request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
3551 signerCert);
3552 if (!request)
3553 return NULL;
3554 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
3555 method, time, addServiceLocato r,
3556 pwArg, pRequest);
3557 }
3558
3559 /*
3560 * FUNCTION: CERT_GetEncodedOCSPResponse
3561 * Creates and sends a request to an OCSP responder, then reads and
3562 * returns the (encoded) response.
3563 *
3564 * This is a legacy API that behaves identically to
3565 * CERT_GetEncodedOCSPResponseByMethod using the "POST" method.
3566 */
3567 SECItem *
3493 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList, 3568 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList,
3494 const char *location, PRTime time, 3569 const char *location, PRTime time,
3495 PRBool addServiceLocator, 3570 PRBool addServiceLocator,
3496 CERTCertificate *signerCert, void *pwArg, 3571 CERTCertificate *signerCert, void *pwArg,
3497 CERTOCSPRequest **pRequest) 3572 CERTOCSPRequest **pRequest)
3498 { 3573 {
3499 CERTOCSPRequest *request; 3574 return CERT_GetEncodedOCSPResponseByMethod(arena, certList, location,
3500 request = CERT_CreateOCSPRequest(certList, time, addServiceLocator, 3575 » » » » » "POST", time, addServiceLocator,
3501 signerCert); 3576 » » » » » signerCert, pwArg, pRequest);
3502 if (!request)
3503 return NULL;
3504 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
3505 time, addServiceLocator,
3506 pwArg, pRequest);
3507 } 3577 }
3508 3578
3579 /* URL encode a buffer that consists of base64-characters, only,
3580 * which means we can use a simple encoding logic.
3581 *
3582 * No output buffer size checking is performed.
3583 * You should call the function twice, to calculate the required buffer size.
3584 *
3585 * If the outpufBuf parameter is NULL, the function will calculate the
3586 * required size, including the trailing zero termination char.
3587 *
3588 * The function returns the number of bytes calculated or produced.
3589 */
3590 size_t
3591 ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf)
3592 {
3593 const char *walkInput = NULL;
3594 char *walkOutput = outputBuf;
3595 size_t count = 0;
3596
3597 for (walkInput=base64Buf; *walkInput; ++walkInput) {
3598 char c = *walkInput;
3599 if (isspace(c))
3600 continue;
3601 switch (c) {
3602 case '+':
3603 if (outputBuf) {
3604 strcpy(walkOutput, "%2B");
3605 walkOutput += 3;
3606 }
3607 count += 3;
3608 break;
3609 case '/':
3610 if (outputBuf) {
3611 strcpy(walkOutput, "%2F");
3612 walkOutput += 3;
3613 }
3614 count += 3;
3615 break;
3616 case '=':
3617 if (outputBuf) {
3618 strcpy(walkOutput, "%3D");
3619 walkOutput += 3;
3620 }
3621 count += 3;
3622 break;
3623 default:
3624 if (outputBuf) {
3625 *walkOutput = *walkInput;
3626 ++walkOutput;
3627 }
3628 ++count;
3629 break;
3630 }
3631 }
3632 if (outputBuf) {
3633 *walkOutput = 0;
3634 }
3635 ++count;
3636 return count;
3637 }
3638
3639 enum { max_get_request_size = 255 }; /* defined by RFC2560 */
3640
3641 static SECItem *
3642 cert_GetOCSPResponse(PLArenaPool *arena, const char *location,
3643 const SECItem *encodedRequest);
3644
3509 static SECItem * 3645 static SECItem *
3510 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, 3646 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena,
3511 CERTOCSPRequest *request, 3647 CERTOCSPRequest *request,
3512 const char *location, PRTime time, 3648 const char *location,
3649 » » » » const char *method,
3650 » » » » PRTime time,
3513 PRBool addServiceLocator, 3651 PRBool addServiceLocator,
3514 void *pwArg, 3652 void *pwArg,
3515 CERTOCSPRequest **pRequest) 3653 CERTOCSPRequest **pRequest)
3516 { 3654 {
3517 SECItem *encodedRequest = NULL; 3655 SECItem *encodedRequest = NULL;
3518 SECItem *encodedResponse = NULL; 3656 SECItem *encodedResponse = NULL;
3519 SECStatus rv; 3657 SECStatus rv;
3520 3658
3659 if (!location || !*location) /* location should be at least one byte */
3660 goto loser;
3661
3521 rv = CERT_AddOCSPAcceptableResponses(request, 3662 rv = CERT_AddOCSPAcceptableResponses(request,
3522 SEC_OID_PKIX_OCSP_BASIC_RESPONSE); 3663 SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
3523 if (rv != SECSuccess) 3664 if (rv != SECSuccess)
3524 goto loser; 3665 goto loser;
3525 3666
3526 encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg); 3667 encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
3527 if (encodedRequest == NULL) 3668 if (encodedRequest == NULL)
3528 goto loser; 3669 goto loser;
3529 3670
3530 encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest); 3671 if (!strcmp(method, "GET")) {
3672 encodedResponse = cert_GetOCSPResponse(arena, location, encodedRequest);
3673 }
3674 else if (!strcmp(method, "POST")) {
3675 encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest);
3676 }
3677 else {
3678 » goto loser;
3679 }
3531 3680
3532 if (encodedResponse != NULL && pRequest != NULL) { 3681 if (encodedResponse != NULL && pRequest != NULL) {
3533 *pRequest = request; 3682 *pRequest = request;
3534 request = NULL; /* avoid destroying below */ 3683 request = NULL; /* avoid destroying below */
3535 } 3684 }
3536 3685
3537 loser: 3686 loser:
3538 if (request != NULL) 3687 if (request != NULL)
3539 CERT_DestroyOCSPRequest(request); 3688 CERT_DestroyOCSPRequest(request);
3540 if (encodedRequest != NULL) 3689 if (encodedRequest != NULL)
3541 SECITEM_FreeItem(encodedRequest, PR_TRUE); 3690 SECITEM_FreeItem(encodedRequest, PR_TRUE);
3691 return encodedResponse;
3692 }
3542 3693
3543 return encodedResponse; 3694 static SECItem *
3695 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location,
3696 const SECItem *encodedRequest);
3697
3698 /* using HTTP GET method */
3699 static SECItem *
3700 cert_GetOCSPResponse(PLArenaPool *arena, const char *location,
3701 const SECItem *encodedRequest)
3702 {
3703 char *walkOutput = NULL;
3704 char *fullGetPath = NULL;
3705 size_t pathLength;
3706 PRInt32 urlEncodedBufLength;
3707 size_t base64size;
3708 char b64ReqBuf[max_get_request_size+1];
3709 size_t slashLengthIfNeeded = 0;
3710 size_t getURLLength;
3711 SECItem *item;
3712
3713 if (!location || !*location) {
3714 » return NULL;
3715 }
3716
3717 pathLength = strlen(location);
3718 if (location[pathLength-1] != '/') {
3719 » slashLengthIfNeeded = 1;
3720 }
3721
3722 /* Calculation as documented by PL_Base64Encode function.
3723 * Use integer conversion to avoid having to use function ceil().
3724 */
3725 base64size = (((encodedRequest->len +2)/3) * 4);
3726 if (base64size > max_get_request_size) {
3727 » return NULL;
3728 }
3729 memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
3730 PL_Base64Encode((const char*)encodedRequest->data, encodedRequest->len,
3731 » » b64ReqBuf);
3732
3733 urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
3734 getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
3735
3736 /* urlEncodedBufLength already contains room for the zero terminator.
3737 * Add another if we must add the '/' char.
3738 */
3739 if (arena) {
3740 fullGetPath = (char*)PORT_ArenaAlloc(arena, getURLLength);
3741 } else {
3742 fullGetPath = (char*)PORT_Alloc(getURLLength);
3743 }
3744 if (!fullGetPath) {
3745 » return NULL;
3746 }
3747
3748 strcpy(fullGetPath, location);
3749 walkOutput = fullGetPath + pathLength;
3750
3751 if (walkOutput > fullGetPath && slashLengthIfNeeded) {
3752 strcpy(walkOutput, "/");
3753 ++walkOutput;
3754 }
3755 ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
3756
3757 item = cert_FetchOCSPResponse(arena, fullGetPath, NULL);
3758 if (!arena) {
3759 » PORT_Free(fullGetPath);
3760 }
3761 return item;
3544 } 3762 }
3545 3763
3546 SECItem * 3764 SECItem *
3547 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location, 3765 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location,
3548 const SECItem *encodedRequest) 3766 const SECItem *encodedRequest)
3549 { 3767 {
3768 return cert_FetchOCSPResponse(arena, location, encodedRequest);
3769 }
3770
3771 SECItem *
3772 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location,
3773 const SECItem *encodedRequest)
3774 {
3550 const SEC_HttpClientFcn *registeredHttpClient; 3775 const SEC_HttpClientFcn *registeredHttpClient;
3551 SECItem *encodedResponse = NULL; 3776 SECItem *encodedResponse = NULL;
3552 3777
3553 registeredHttpClient = SEC_GetRegisteredHttpClient(); 3778 registeredHttpClient = SEC_GetRegisteredHttpClient();
3554 3779
3555 if (registeredHttpClient && registeredHttpClient->version == 1) { 3780 if (registeredHttpClient && registeredHttpClient->version == 1) {
3556 encodedResponse = fetchOcspHttpClientV1( 3781 encodedResponse = fetchOcspHttpClientV1(
3557 arena, 3782 arena,
3558 &registeredHttpClient->fcnTable.ftable1, 3783 &registeredHttpClient->fcnTable.ftable1,
3559 location, 3784 location,
3560 encodedRequest); 3785 encodedRequest);
3561 } else { 3786 } else {
3562 /* use internal http client */ 3787 /* use internal http client */
3563 PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest); 3788 PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest);
3564 if (sock) { 3789 if (sock) {
3565 encodedResponse = ocsp_GetEncodedResponse(arena, sock); 3790 encodedResponse = ocsp_GetEncodedResponse(arena, sock);
3566 PR_Close(sock); 3791 PR_Close(sock);
3567 } 3792 }
3568 } 3793 }
3569 3794
3570 return encodedResponse; 3795 return encodedResponse;
3571 } 3796 }
3572 3797
3573 static SECItem * 3798 static SECItem *
3574 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena, 3799 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena,
3575 CERTOCSPCertID *certID, 3800 CERTOCSPCertID *certID,
3576 CERTCertificate *singleCert, 3801 CERTCertificate *singleCert,
3577 const char *location, PRTime time, 3802 const char *location,
3803 » » » » » const char *method,
3804 » » » » » PRTime time,
3578 PRBool addServiceLocator, 3805 PRBool addServiceLocator,
3579 void *pwArg, 3806 void *pwArg,
3580 CERTOCSPRequest **pRequest) 3807 CERTOCSPRequest **pRequest)
3581 { 3808 {
3582 CERTOCSPRequest *request; 3809 CERTOCSPRequest *request;
3583 request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, 3810 request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time,
3584 addServiceLocator, NULL); 3811 addServiceLocator, NULL);
3585 if (!request) 3812 if (!request)
3586 return NULL; 3813 return NULL;
3587 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 3814 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
3588 time, addServiceLocator, 3815 method, time, addServiceLocato r,
3589 pwArg, pRequest); 3816 pwArg, pRequest);
3590 } 3817 }
3591 3818
3592 /* Checks a certificate for the key usage extension of OCSP signer. */ 3819 /* Checks a certificate for the key usage extension of OCSP signer. */
3593 static PRBool 3820 static PRBool
3594 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert) 3821 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert)
3595 { 3822 {
3596 SECStatus rv; 3823 SECStatus rv;
3597 SECItem extItem; 3824 SECItem extItem;
3598 SECItem **oids; 3825 SECItem **oids;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 3896
3670 static PRBool 3897 static PRBool
3671 ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert) 3898 ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert)
3672 { 3899 {
3673 SECItem item; 3900 SECItem item;
3674 unsigned char buf[HASH_LENGTH_MAX]; 3901 unsigned char buf[HASH_LENGTH_MAX];
3675 3902
3676 item.data = buf; 3903 item.data = buf;
3677 item.len = SHA1_LENGTH; 3904 item.len = SHA1_LENGTH;
3678 3905
3679 if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_SHA1, &item) == NULL) { 3906 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_SHA1,
3907 » » » » &item) == NULL) {
3680 return PR_FALSE; 3908 return PR_FALSE;
3681 } 3909 }
3682 if (SECITEM_ItemsAreEqual(certIndex,&item)) { 3910 if (SECITEM_ItemsAreEqual(certIndex,&item)) {
3683 return PR_TRUE; 3911 return PR_TRUE;
3684 } 3912 }
3685 if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_MD5, &item) == NULL) { 3913 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_MD5,
3914 » » » » &item) == NULL) {
3686 return PR_FALSE; 3915 return PR_FALSE;
3687 } 3916 }
3688 if (SECITEM_ItemsAreEqual(certIndex,&item)) { 3917 if (SECITEM_ItemsAreEqual(certIndex,&item)) {
3689 return PR_TRUE; 3918 return PR_TRUE;
3690 } 3919 }
3691 if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_MD2, &item) == NULL) { 3920 if (CERT_GetSubjectPublicKeyDigest(NULL,testCert,SEC_OID_MD2,
3921 » » » » &item) == NULL) {
3692 return PR_FALSE; 3922 return PR_FALSE;
3693 } 3923 }
3694 if (SECITEM_ItemsAreEqual(certIndex,&item)) { 3924 if (SECITEM_ItemsAreEqual(certIndex,&item)) {
3695 return PR_TRUE; 3925 return PR_TRUE;
3696 } 3926 }
3697 3927
3698 return PR_FALSE; 3928 return PR_FALSE;
3699 } 3929 }
3700 3930
3701 static CERTCertificate * 3931 static CERTCertificate *
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 if (responder && ocsp_matchcert(certIndex,responder)) { 4012 if (responder && ocsp_matchcert(certIndex,responder)) {
3783 signerCert = CERT_DupCertificate(responder); 4013 signerCert = CERT_DupCertificate(responder);
3784 } else if (issuer && ocsp_matchcert(certIndex,issuer)) { 4014 } else if (issuer && ocsp_matchcert(certIndex,issuer)) {
3785 signerCert = CERT_DupCertificate(issuer); 4015 signerCert = CERT_DupCertificate(issuer);
3786 } 4016 }
3787 for (i=0; (signerCert == NULL) && (i < certCount); i++) { 4017 for (i=0; (signerCert == NULL) && (i < certCount); i++) {
3788 if (ocsp_matchcert(certIndex,certs[i])) { 4018 if (ocsp_matchcert(certIndex,certs[i])) {
3789 signerCert = CERT_DupCertificate(certs[i]); 4019 signerCert = CERT_DupCertificate(certs[i]);
3790 } 4020 }
3791 } 4021 }
4022 if (signerCert == NULL) {
4023 PORT_SetError(SEC_ERROR_UNKNOWN_CERT);
4024 }
3792 } 4025 }
3793 4026
3794 finish: 4027 finish:
3795 if (certs != NULL) { 4028 if (certs != NULL) {
3796 CERT_DestroyCertArray(certs, certCount); 4029 CERT_DestroyCertArray(certs, certCount);
3797 } 4030 }
3798 4031
3799 return signerCert; 4032 return signerCert;
3800 } 4033 }
3801 4034
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
4231 * 4464 *
4232 * First, lets check if signer of the response is the actual issuer 4465 * First, lets check if signer of the response is the actual issuer
4233 * of the cert. For that we will use signer cert key hash and cert subj 4466 * of the cert. For that we will use signer cert key hash and cert subj
4234 * name hash and will compare them with already calculated issuer key 4467 * name hash and will compare them with already calculated issuer key
4235 * hash and issuer name hash. The hash algorithm is picked from response 4468 * hash and issuer name hash. The hash algorithm is picked from response
4236 * certID hash to avoid second hash calculation. 4469 * certID hash to avoid second hash calculation.
4237 */ 4470 */
4238 4471
4239 hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm); 4472 hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
4240 4473
4241 keyHash = CERT_GetSPKIDigest(NULL, signerCert, hashAlg, NULL); 4474 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, signerCert, hashAlg, NULL);
4242 if (keyHash != NULL) { 4475 if (keyHash != NULL) {
4243 4476
4244 keyHashEQ = 4477 keyHashEQ =
4245 (SECITEM_CompareItem(keyHash, 4478 (SECITEM_CompareItem(keyHash,
4246 &certID->issuerKeyHash) == SECEqual); 4479 &certID->issuerKeyHash) == SECEqual);
4247 SECITEM_FreeItem(keyHash, PR_TRUE); 4480 SECITEM_FreeItem(keyHash, PR_TRUE);
4248 } 4481 }
4249 if (keyHashEQ && 4482 if (keyHashEQ &&
4250 (nameHash = cert_GetSubjectNameDigest(NULL, signerCert, 4483 (nameHash = CERT_GetSubjectNameDigest(NULL, signerCert,
4251 hashAlg, NULL))) { 4484 hashAlg, NULL))) {
4252 nameHashEQ = 4485 nameHashEQ =
4253 (SECITEM_CompareItem(nameHash, 4486 (SECITEM_CompareItem(nameHash,
4254 &certID->issuerNameHash) == SECEqual); 4487 &certID->issuerNameHash) == SECEqual);
4255 4488
4256 SECITEM_FreeItem(nameHash, PR_TRUE); 4489 SECITEM_FreeItem(nameHash, PR_TRUE);
4257 if (nameHashEQ) { 4490 if (nameHashEQ) {
4258 /* The issuer of the cert is the the signer of the response */ 4491 /* The issuer of the cert is the the signer of the response */
4259 return PR_TRUE; 4492 return PR_TRUE;
4260 } 4493 }
(...skipping 17 matching lines...) Expand all
4278 if (issuerCert == NULL) { 4511 if (issuerCert == NULL) {
4279 /* 4512 /*
4280 * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone, 4513 * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
4281 * but the following will give slightly more information. 4514 * but the following will give slightly more information.
4282 * Once we have an error stack, things will be much better. 4515 * Once we have an error stack, things will be much better.
4283 */ 4516 */
4284 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); 4517 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
4285 return PR_FALSE; 4518 return PR_FALSE;
4286 } 4519 }
4287 4520
4288 keyHash = CERT_GetSPKIDigest(NULL, issuerCert, hashAlg, NULL); 4521 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, issuerCert, hashAlg, NULL);
4289 nameHash = cert_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL); 4522 nameHash = CERT_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL);
4290 4523
4291 CERT_DestroyCertificate(issuerCert); 4524 CERT_DestroyCertificate(issuerCert);
4292 4525
4293 if (keyHash != NULL && nameHash != NULL) { 4526 if (keyHash != NULL && nameHash != NULL) {
4294 keyHashEQ = 4527 keyHashEQ =
4295 (SECITEM_CompareItem(keyHash, 4528 (SECITEM_CompareItem(keyHash,
4296 &certID->issuerKeyHash) == SECEqual); 4529 &certID->issuerKeyHash) == SECEqual);
4297 4530
4298 nameHashEQ = 4531 nameHashEQ =
4299 (SECITEM_CompareItem(nameHash, 4532 (SECITEM_CompareItem(nameHash,
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
4665 if (LL_CMP(revokedTime, >, time)) 4898 if (LL_CMP(revokedTime, >, time))
4666 return SECSuccess; 4899 return SECSuccess;
4667 4900
4668 return SECFailure; 4901 return SECFailure;
4669 } 4902 }
4670 4903
4671 /* 4904 /*
4672 * See if the cert represented in the single response had a good status 4905 * See if the cert represented in the single response had a good status
4673 * at the specified time. 4906 * at the specified time.
4674 */ 4907 */
4675 static SECStatus 4908 SECStatus
4676 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time) 4909 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time)
4677 { 4910 {
4678 SECStatus rv; 4911 SECStatus rv;
4679 switch (status->certStatusType) { 4912 switch (status->certStatusType) {
4680 case ocspCertStatus_good: 4913 case ocspCertStatus_good:
4681 rv = SECSuccess; 4914 rv = SECSuccess;
4682 break; 4915 break;
4683 case ocspCertStatus_revoked: 4916 case ocspCertStatus_revoked:
4684 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); 4917 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
4685 break; 4918 break;
(...skipping 11 matching lines...) Expand all
4697 return rv; 4930 return rv;
4698 } 4931 }
4699 4932
4700 static SECStatus 4933 static SECStatus
4701 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single, 4934 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single,
4702 PRTime time) 4935 PRTime time)
4703 { 4936 {
4704 return ocsp_CertHasGoodStatus(single->certStatus, time); 4937 return ocsp_CertHasGoodStatus(single->certStatus, time);
4705 } 4938 }
4706 4939
4707 /* Return value SECFailure means: not found or not fresh. 4940 /* SECFailure means the arguments were invalid.
4708 * On SECSuccess, the out parameters contain the OCSP status. 4941 * On SECSuccess, the out parameters contain the OCSP status.
4709 * rvOcsp contains the overall result of the OCSP operation. 4942 * rvOcsp contains the overall result of the OCSP operation.
4710 * Depending on input parameter ignoreGlobalOcspFailureSetting, 4943 * Depending on input parameter ignoreGlobalOcspFailureSetting,
4711 * a soft failure might be converted into *rvOcsp=SECSuccess. 4944 * a soft failure might be converted into *rvOcsp=SECSuccess.
4712 * If the cached attempt to obtain OCSP information had resulted 4945 * If the cached attempt to obtain OCSP information had resulted
4713 * in a failure, missingResponseError shows the error code of 4946 * in a failure, missingResponseError shows the error code of
4714 * that failure. 4947 * that failure.
4948 * cacheFreshness is ocspMissing if no entry was found,
4949 * ocspFresh if a fresh entry was found, or
4950 * ocspStale if a stale entry was found.
4715 */ 4951 */
4716 SECStatus 4952 SECStatus
4717 ocsp_GetCachedOCSPResponseStatusIfFresh(CERTOCSPCertID *certID, 4953 ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID,
4718 PRTime time, 4954 PRTime time,
4719 PRBool ignoreGlobalOcspFailureSetting, 4955 PRBool ignoreGlobalOcspFailureSetting,
4720 SECStatus *rvOcsp, 4956 SECStatus *rvOcsp,
4721 SECErrorCodes *missingResponseError) 4957 SECErrorCodes *missingResponseError,
4958 OCSPFreshness *cacheFreshness)
4722 { 4959 {
4723 OCSPCacheItem *cacheItem = NULL; 4960 OCSPCacheItem *cacheItem = NULL;
4724 SECStatus rv = SECFailure;
4725 4961
4726 if (!certID || !missingResponseError || !rvOcsp) { 4962 if (!certID || !missingResponseError || !rvOcsp || !cacheFreshness) {
4727 PORT_SetError(SEC_ERROR_INVALID_ARGS); 4963 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4728 return SECFailure; 4964 return SECFailure;
4729 } 4965 }
4730 *rvOcsp = SECFailure; 4966 *rvOcsp = SECFailure;
4731 *missingResponseError = 0; 4967 *missingResponseError = 0;
4968 *cacheFreshness = ocspMissing;
4732 4969
4733 PR_EnterMonitor(OCSP_Global.monitor); 4970 PR_EnterMonitor(OCSP_Global.monitor);
4734 cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID); 4971 cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID);
4735 if (cacheItem && ocsp_IsCacheItemFresh(cacheItem)) { 4972 if (cacheItem) {
4973 *cacheFreshness = ocsp_IsCacheItemFresh(cacheItem) ? ocspFresh
4974 : ocspStale;
4736 /* having an arena means, we have a cached certStatus */ 4975 /* having an arena means, we have a cached certStatus */
4737 if (cacheItem->certStatusArena) { 4976 if (cacheItem->certStatusArena) {
4738 *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time); 4977 *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
4739 if (*rvOcsp != SECSuccess) { 4978 if (*rvOcsp != SECSuccess) {
4740 *missingResponseError = PORT_GetError(); 4979 *missingResponseError = PORT_GetError();
4741 } 4980 }
4742 rv = SECSuccess;
4743 } else { 4981 } else {
4744 /* 4982 /*
4745 * No status cached, the previous attempt failed. 4983 * No status cached, the previous attempt failed.
4746 * If OCSP is required, we never decide based on a failed attempt 4984 * If OCSP is required, we never decide based on a failed attempt
4747 * However, if OCSP is optional, a recent OCSP failure is 4985 * However, if OCSP is optional, a recent OCSP failure is
4748 * an allowed good state. 4986 * an allowed good state.
4749 */ 4987 */
4750 if (!ignoreGlobalOcspFailureSetting && 4988 if (*cacheFreshness == ocspFresh &&
4989 !ignoreGlobalOcspFailureSetting &&
4751 OCSP_Global.ocspFailureMode == 4990 OCSP_Global.ocspFailureMode ==
4752 ocspMode_FailureIsNotAVerificationFailure) { 4991 ocspMode_FailureIsNotAVerificationFailure) {
4753 rv = SECSuccess;
4754 *rvOcsp = SECSuccess; 4992 *rvOcsp = SECSuccess;
4755 } 4993 }
4756 *missingResponseError = cacheItem->missingResponseError; 4994 *missingResponseError = cacheItem->missingResponseError;
4757 } 4995 }
4758 } 4996 }
4759 PR_ExitMonitor(OCSP_Global.monitor); 4997 PR_ExitMonitor(OCSP_Global.monitor);
4760 return rv; 4998 return SECSuccess;
4761 } 4999 }
4762 5000
4763 PRBool 5001 PRBool
4764 ocsp_FetchingFailureIsVerificationFailure(void) 5002 ocsp_FetchingFailureIsVerificationFailure(void)
4765 { 5003 {
4766 PRBool isFailure; 5004 PRBool isFailure;
4767 5005
4768 PR_EnterMonitor(OCSP_Global.monitor); 5006 PR_EnterMonitor(OCSP_Global.monitor);
4769 isFailure = 5007 isFailure =
4770 OCSP_Global.ocspFailureMode == ocspMode_FailureIsVerificationFailure; 5008 OCSP_Global.ocspFailureMode == ocspMode_FailureIsVerificationFailure;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4821 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when 5059 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
4822 * verifying the signer's cert, or low-level problems (error allocating 5060 * verifying the signer's cert, or low-level problems (error allocating
4823 * memory, error performing ASN.1 decoding, etc.). 5061 * memory, error performing ASN.1 decoding, etc.).
4824 */ 5062 */
4825 SECStatus 5063 SECStatus
4826 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, 5064 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
4827 PRTime time, void *pwArg) 5065 PRTime time, void *pwArg)
4828 { 5066 {
4829 CERTOCSPCertID *certID; 5067 CERTOCSPCertID *certID;
4830 PRBool certIDWasConsumed = PR_FALSE; 5068 PRBool certIDWasConsumed = PR_FALSE;
4831 SECStatus rv = SECFailure; 5069 SECStatus rv;
4832 SECStatus rvOcsp; 5070 SECStatus rvOcsp;
4833 SECErrorCodes dummy_error_code; /* we ignore this */ 5071 SECErrorCodes cachedErrorCode;
5072 OCSPFreshness cachedResponseFreshness;
4834 5073
4835 OCSP_TRACE_CERT(cert); 5074 OCSP_TRACE_CERT(cert);
4836 OCSP_TRACE_TIME("## requested validity time:", time); 5075 OCSP_TRACE_TIME("## requested validity time:", time);
4837 5076
4838 certID = CERT_CreateOCSPCertID(cert, time); 5077 certID = CERT_CreateOCSPCertID(cert, time);
4839 if (!certID) 5078 if (!certID)
4840 return SECFailure; 5079 return SECFailure;
4841 rv = ocsp_GetCachedOCSPResponseStatusIfFresh( 5080 rv = ocsp_GetCachedOCSPResponseStatus(
4842 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ 5081 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
4843 &rvOcsp, &dummy_error_code); 5082 &rvOcsp, &cachedErrorCode, &cachedResponseFreshness);
4844 if (rv == SECSuccess) { 5083 if (rv != SECSuccess) {
5084 CERT_DestroyOCSPCertID(certID);
5085 return SECFailure;
5086 }
5087 if (cachedResponseFreshness == ocspFresh) {
4845 CERT_DestroyOCSPCertID(certID); 5088 CERT_DestroyOCSPCertID(certID);
4846 return rvOcsp; 5089 return rvOcsp;
4847 } 5090 }
4848 rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, 5091
5092 rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg,
4849 &certIDWasConsumed, 5093 &certIDWasConsumed,
4850 &rvOcsp); 5094 &rvOcsp);
4851 if (rv != SECSuccess) { 5095 if (rv != SECSuccess) {
4852 /* we were unable to obtain ocsp status. Check if we should 5096 PRErrorCode err = PORT_GetError();
4853 * return cert status revoked. */ 5097 if (ocsp_FetchingFailureIsVerificationFailure()) {
4854 rvOcsp = ocsp_FetchingFailureIsVerificationFailure() ? 5098 PORT_SetError(err);
4855 SECFailure : SECSuccess; 5099 rvOcsp = SECFailure;
5100 } else if (cachedResponseFreshness == ocspStale &&
5101 (cachedErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT ||
5102 cachedErrorCode == SEC_ERROR_REVOKED_CERTIFICATE)) {
5103 /* If we couldn't get a response for a certificate that the OCSP
5104 * responder previously told us was bad, then assume it is still
5105 * bad until we hear otherwise, as it is very unlikely that the
5106 * certificate status has changed from "revoked" to "good" and it
5107 * is also unlikely that the certificate status has changed from
5108 * "unknown" to "good", except for some buggy OCSP responders.
5109 */
5110 PORT_SetError(cachedErrorCode);
5111 rvOcsp = SECFailure;
5112 } else {
5113 rvOcsp = SECSuccess;
5114 }
4856 } 5115 }
4857 if (!certIDWasConsumed) { 5116 if (!certIDWasConsumed) {
4858 CERT_DestroyOCSPCertID(certID); 5117 CERT_DestroyOCSPCertID(certID);
4859 } 5118 }
4860 return rvOcsp; 5119 return rvOcsp;
4861 } 5120 }
4862 5121
4863 /* 5122 /*
4864 * FUNCTION: CERT_CacheOCSPResponseFromSideChannel 5123 * FUNCTION: CERT_CacheOCSPResponseFromSideChannel
4865 * First, this function checks the OCSP cache to see if a good response 5124 * First, this function checks the OCSP cache to see if a good response
(...skipping 25 matching lines...) Expand all
4891 SECStatus 5150 SECStatus
4892 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, 5151 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle,
4893 CERTCertificate *cert, 5152 CERTCertificate *cert,
4894 PRTime time, 5153 PRTime time,
4895 const SECItem *encodedResponse, 5154 const SECItem *encodedResponse,
4896 void *pwArg) 5155 void *pwArg)
4897 { 5156 {
4898 CERTOCSPCertID *certID = NULL; 5157 CERTOCSPCertID *certID = NULL;
4899 PRBool certIDWasConsumed = PR_FALSE; 5158 PRBool certIDWasConsumed = PR_FALSE;
4900 SECStatus rv = SECFailure; 5159 SECStatus rv = SECFailure;
4901 SECStatus rvOcsp; 5160 SECStatus rvOcsp = SECFailure;
4902 SECErrorCodes dummy_error_code; /* we ignore this */ 5161 SECErrorCodes dummy_error_code; /* we ignore this */
5162 CERTOCSPResponse *decodedResponse = NULL;
5163 CERTOCSPSingleResponse *singleResponse = NULL;
5164 OCSPFreshness freshness;
4903 5165
4904 /* The OCSP cache can be in three states regarding this certificate: 5166 /* The OCSP cache can be in three states regarding this certificate:
4905 * + Good (cached, timely, 'good' response, or revoked in the future) 5167 * + Good (cached, timely, 'good' response, or revoked in the future)
4906 * + Revoked (cached, timely, but doesn't fit in the last category) 5168 * + Revoked (cached, timely, but doesn't fit in the last category)
4907 * + Miss (no knowledge) 5169 * + Miss (no knowledge)
4908 * 5170 *
4909 * Likewise, the side-channel information can be 5171 * Likewise, the side-channel information can be
4910 * + Good (timely, 'good' response, or revoked in the future) 5172 * + Good (timely, 'good' response, or revoked in the future)
4911 * + Revoked (timely, but doesn't fit in the last category) 5173 * + Revoked (timely, but doesn't fit in the last category)
4912 * + Invalid (bad syntax, bad signature, not timely etc) 5174 * + Invalid (bad syntax, bad signature, not timely etc)
(...skipping 20 matching lines...) Expand all
4933 * e | 5195 * e |
4934 * l | 5196 * l |
4935 * 5197 *
4936 * When we fetch from the network we might choose to cache a negative 5198 * When we fetch from the network we might choose to cache a negative
4937 * result when the response is invalid. This saves us hammering, uselessly, 5199 * result when the response is invalid. This saves us hammering, uselessly,
4938 * at a broken responder. However, side channels are commonly attacker 5200 * at a broken responder. However, side channels are commonly attacker
4939 * controlled and so we must not cache a negative result for an Invalid 5201 * controlled and so we must not cache a negative result for an Invalid
4940 * side channel. 5202 * side channel.
4941 */ 5203 */
4942 5204
4943 if (!cert) { 5205 if (!cert || !encodedResponse) {
4944 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5206 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4945 return SECFailure; 5207 return SECFailure;
4946 } 5208 }
4947 certID = CERT_CreateOCSPCertID(cert, time); 5209 certID = CERT_CreateOCSPCertID(cert, time);
4948 if (!certID) 5210 if (!certID)
4949 return SECFailure; 5211 return SECFailure;
4950 rv = ocsp_GetCachedOCSPResponseStatusIfFresh( 5212
4951 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ 5213 /* We pass PR_TRUE for ignoreGlobalOcspFailureSetting so that a cached
4952 &rvOcsp, &dummy_error_code); 5214 * error entry is not interpreted as being a 'Good' entry here.
4953 if (rv == SECSuccess && rvOcsp == SECSuccess) { 5215 */
5216 rv = ocsp_GetCachedOCSPResponseStatus(
5217 certID, time, PR_TRUE, /* ignoreGlobalOcspFailureSetting */
5218 &rvOcsp, &dummy_error_code, &freshness);
5219 if (rv == SECSuccess && rvOcsp == SECSuccess && freshness == ocspFresh) {
4954 /* The cached value is good. We don't want to waste time validating 5220 /* The cached value is good. We don't want to waste time validating
4955 * this OCSP response. This is the first column in the table above. */ 5221 * this OCSP response. This is the first column in the table above. */
4956 CERT_DestroyOCSPCertID(certID); 5222 CERT_DestroyOCSPCertID(certID);
4957 return rv; 5223 return rv;
4958 } 5224 }
4959 5225
4960 /* The logic for caching the more recent response is handled in 5226 /* The logic for caching the more recent response is handled in
4961 * ocsp_CreateOrUpdateCacheEntry, which is called by this function. */ 5227 * ocsp_CacheSingleResponse. */
4962 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, 5228
4963 pwArg, encodedResponse, 5229 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert,
4964 PR_FALSE /* don't cache if invalid */, 5230 » » » » » » time, pwArg,
4965 &certIDWasConsumed, 5231 » » » » » » encodedResponse,
4966 &rvOcsp); 5232 » » » » » » &decodedResponse,
5233 » » » » » » &singleResponse);
5234 if (rv == SECSuccess) {
5235 » rvOcsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time);
5236 » /* Cache any valid singleResponse, regardless of status. */
5237 » ocsp_CacheSingleResponse(certID, singleResponse, &certIDWasConsumed);
5238 }
5239 if (decodedResponse) {
5240 » CERT_DestroyOCSPResponse(decodedResponse);
5241 }
4967 if (!certIDWasConsumed) { 5242 if (!certIDWasConsumed) {
4968 CERT_DestroyOCSPCertID(certID); 5243 CERT_DestroyOCSPCertID(certID);
4969 } 5244 }
4970 return rv == SECSuccess ? rvOcsp : rv; 5245 return rv == SECSuccess ? rvOcsp : rv;
4971 } 5246 }
4972 5247
4973 /* 5248 /*
4974 * Status in *certIDWasConsumed will always be correct, regardless of 5249 * Status in *certIDWasConsumed will always be correct, regardless of
4975 * return value. 5250 * return value.
4976 */ 5251 */
4977 static SECStatus 5252 static SECStatus
4978 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 5253 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
4979 CERTOCSPCertID *certID, 5254 CERTOCSPCertID *certID,
4980 CERTCertificate *cert, 5255 CERTCertificate *cert,
4981 PRTime time, 5256 PRTime time,
4982 void *pwArg, 5257 void *pwArg,
4983 PRBool *certIDWasConsumed, 5258 PRBool *certIDWasConsumed,
4984 SECStatus *rv_ocsp) 5259 SECStatus *rv_ocsp)
4985 { 5260 {
4986 char *location = NULL; 5261 char *location = NULL;
4987 PRBool locationIsDefault; 5262 PRBool locationIsDefault;
4988 SECItem *encodedResponse = NULL; 5263 SECItem *encodedResponse = NULL;
4989 CERTOCSPRequest *request = NULL; 5264 CERTOCSPRequest *request = NULL;
4990 SECStatus rv = SECFailure; 5265 SECStatus rv = SECFailure;
4991 5266
5267 CERTOCSPResponse *decodedResponse = NULL;
5268 CERTOCSPSingleResponse *singleResponse = NULL;
5269 enum { stageGET, stagePOST } currentStage;
5270 PRBool retry = PR_FALSE;
5271
4992 if (!certIDWasConsumed || !rv_ocsp) { 5272 if (!certIDWasConsumed || !rv_ocsp) {
4993 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5273 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4994 return SECFailure; 5274 return SECFailure;
4995 } 5275 }
4996 *certIDWasConsumed = PR_FALSE; 5276 *certIDWasConsumed = PR_FALSE;
4997 *rv_ocsp = SECFailure; 5277 *rv_ocsp = SECFailure;
4998 5278
5279 if (!OCSP_Global.monitor) {
5280 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
5281 return SECFailure;
5282 }
5283 PR_EnterMonitor(OCSP_Global.monitor);
5284 if (OCSP_Global.forcePost) {
5285 currentStage = stagePOST;
5286 } else {
5287 currentStage = stageGET;
5288 }
5289 PR_ExitMonitor(OCSP_Global.monitor);
5290
4999 /* 5291 /*
5000 * The first thing we need to do is find the location of the responder. 5292 * The first thing we need to do is find the location of the responder.
5001 * This will be the value of the default responder (if enabled), else 5293 * This will be the value of the default responder (if enabled), else
5002 * it will come out of the AIA extension in the cert (if present). 5294 * it will come out of the AIA extension in the cert (if present).
5003 * If we have no such location, then this cert does not "deserve" to 5295 * If we have no such location, then this cert does not "deserve" to
5004 * be checked -- that is, we consider it a success and just return. 5296 * be checked -- that is, we consider it a success and just return.
5005 * The way we tell that is by looking at the error number to see if 5297 * The way we tell that is by looking at the error number to see if
5006 * the problem was no AIA extension was found; any other error was 5298 * the problem was no AIA extension was found; any other error was
5007 * a true failure that we unfortunately have to treat as an overall 5299 * a true failure that we unfortunately have to treat as an overall
5008 * failure here. 5300 * failure here.
(...skipping 25 matching lines...) Expand all
5034 * because each issuer is different. Carefully read the OCSP spec 5326 * because each issuer is different. Carefully read the OCSP spec
5035 * if you do not understand this.) 5327 * if you do not understand this.)
5036 */ 5328 */
5037 5329
5038 /* 5330 /*
5039 * XXX If/when signing of requests is supported, that second NULL 5331 * XXX If/when signing of requests is supported, that second NULL
5040 * should be changed to be the signer certificate. Not sure if that 5332 * should be changed to be the signer certificate. Not sure if that
5041 * should be passed into this function or retrieved via some operation 5333 * should be passed into this function or retrieved via some operation
5042 * on the handle/context. 5334 * on the handle/context.
5043 */ 5335 */
5044 encodedResponse =
5045 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location,
5046 time, locationIsDefault,
5047 pwArg, &request);
5048 if (encodedResponse == NULL) {
5049 goto loser;
5050 }
5051 5336
5052 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg, 5337 do {
5053 encodedResponse, 5338 » const char *method;
5054 PR_TRUE /* cache if invalid */, 5339 » PRBool validResponseWithAccurateInfo = PR_FALSE;
5055 certIDWasConsumed, rv_ocsp); 5340 » retry = PR_FALSE;
5341 » *rv_ocsp = SECFailure;
5056 5342
5057 loser: 5343 » if (currentStage == stageGET) {
5058 if (request != NULL) 5344 » method = "GET";
5059 » CERT_DestroyOCSPRequest(request); 5345 » } else {
5060 if (encodedResponse != NULL) 5346 » PORT_Assert(currentStage == stagePOST);
5061 » SECITEM_FreeItem(encodedResponse, PR_TRUE); 5347 » method = "POST";
5062 if (location != NULL) 5348 » }
5063 » PORT_Free(location);
5064 5349
5350 encodedResponse =
5351 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert,
5352 location, method,
5353 time, locationIsDefault,
5354 pwArg, &request);
5355
5356 if (encodedResponse) {
5357 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert ,
5358 time, pwArg,
5359 encodedResponse,
5360 &decodedResponse,
5361 &singleResponse);
5362 if (rv == SECSuccess) {
5363 switch (singleResponse->certStatus->certStatusType) {
5364 case ocspCertStatus_good:
5365 case ocspCertStatus_revoked:
5366 validResponseWithAccurateInfo = PR_TRUE;
5367 break;
5368 default:
5369 break;
5370 }
5371 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time);
5372 }
5373 }
5374
5375 if (currentStage == stageGET) {
5376 /* only accept GET response if good or revoked */
5377 if (validResponseWithAccurateInfo) {
5378 ocsp_CacheSingleResponse(certID, singleResponse,
5379 certIDWasConsumed);
5380 } else {
5381 retry = PR_TRUE;
5382 currentStage = stagePOST;
5383 }
5384 } else {
5385 /* cache the POST respone, regardless of status */
5386 if (!singleResponse) {
5387 cert_RememberOCSPProcessingFailure(certID, certIDWasConsumed);
5388 } else {
5389 ocsp_CacheSingleResponse(certID, singleResponse,
5390 certIDWasConsumed);
5391 }
5392 }
5393
5394 if (encodedResponse) {
5395 SECITEM_FreeItem(encodedResponse, PR_TRUE);
5396 encodedResponse = NULL;
5397 }
5398 if (request) {
5399 CERT_DestroyOCSPRequest(request);
5400 request = NULL;
5401 }
5402 if (decodedResponse) {
5403 CERT_DestroyOCSPResponse(decodedResponse);
5404 decodedResponse = NULL;
5405 }
5406 singleResponse = NULL;
5407
5408 } while (retry);
5409
5410 PORT_Free(location);
5065 return rv; 5411 return rv;
5066 } 5412 }
5067 5413
5068 /* 5414 /*
5069 * FUNCTION: ocsp_CacheEncodedOCSPResponse 5415 * FUNCTION: ocsp_GetDecodedVerifiedSingleResponseForID
5070 * This function decodes an OCSP response and checks for a valid response 5416 * This function decodes an OCSP response and checks for a valid response
5071 * concerning the given certificate. If such a response is not found 5417 * concerning the given certificate.
5072 * then nothing is cached. Otherwise, if it is a good response, or if
5073 * cacheNegative is true, the results are stored in the OCSP cache.
5074 * 5418 *
5075 * Note: a 'valid' response is one that parses successfully, is not an OCSP 5419 * Note: a 'valid' response is one that parses successfully, is not an OCSP
5076 * exception (see RFC 2560 Section 2.3), is correctly signed and is current. 5420 * exception (see RFC 2560 Section 2.3), is correctly signed and is current.
5077 * A 'good' response is a valid response that attests that the certificate 5421 * A 'good' response is a valid response that attests that the certificate
5078 * is not currently revoked (see RFC 2560 Section 2.2). 5422 * is not currently revoked (see RFC 2560 Section 2.2).
5079 * 5423 *
5080 * INPUTS: 5424 * INPUTS:
5081 * CERTCertDBHandle *handle 5425 * CERTCertDBHandle *handle
5082 * certificate DB of the cert that is being checked 5426 * certificate DB of the cert that is being checked
5083 * CERTOCSPCertID *certID 5427 * CERTOCSPCertID *certID
5084 * the cert ID corresponding to |cert| 5428 * the cert ID corresponding to |cert|
5085 * CERTCertificate *cert 5429 * CERTCertificate *cert
5086 * the certificate being checked 5430 * the certificate being checked
5087 * PRTime time 5431 * PRTime time
5088 * time for which status is to be determined 5432 * time for which status is to be determined
5089 * void *pwArg 5433 * void *pwArg
5090 * the opaque argument to the password prompting function. 5434 * the opaque argument to the password prompting function.
5091 * SECItem *encodedResponse 5435 * SECItem *encodedResponse
5092 * the DER encoded bytes of the OCSP response 5436 * the DER encoded bytes of the OCSP response
5093 * PRBool cacheInvalid 5437 * CERTOCSPResponse **pDecodedResponse
5094 * If true then invalid responses will cause a negative cache entry to be 5438 * (output) The caller must ALWAYS check for this output parameter,
5095 * created. (Invalid means bad syntax, bad signature etc) 5439 * and if it's non-null, must destroy it using CERT_DestroyOCSPResponse.
5096 * PRBool *certIDWasConsumed 5440 * CERTOCSPSingleResponse **pSingle
5097 * (output) on return, this is true iff |certID| was consumed by this 5441 * (output) on success, this points to the single response that corresponds
5098 * function. 5442 * to the certID parameter. Points to the inside of pDecodedResponse.
5099 * SECStatus *rv_ocsp 5443 * It isn't a copy, don't free it.
5100 * (output) on return, this is SECSuccess iff the response is good (see
5101 * definition of 'good' above).
5102 * RETURN: 5444 * RETURN:
5103 * SECSuccess iff the response is valid. 5445 * SECSuccess iff the response is valid.
5104 */ 5446 */
5105 static SECStatus 5447 static SECStatus
5106 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, 5448 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle,
5107 » » » CERTOCSPCertID *certID, 5449 » » » » » CERTOCSPCertID *certID,
5108 » » » CERTCertificate *cert, 5450 » » » » » CERTCertificate *cert,
5109 » » » PRTime time, 5451 » » » » » PRTime time,
5110 » » » void *pwArg, 5452 » » » » » void *pwArg,
5111 » » » const SECItem *encodedResponse, 5453 » » » » » const SECItem *encodedResponse,
5112 PRBool cacheInvalid, 5454 » » » » » CERTOCSPResponse **pDecodedResponse,
5113 » » » PRBool *certIDWasConsumed, 5455 » » » » » CERTOCSPSingleResponse **pSingle)
5114 » » » SECStatus *rv_ocsp)
5115 { 5456 {
5116 CERTOCSPResponse *response = NULL;
5117 CERTCertificate *signerCert = NULL; 5457 CERTCertificate *signerCert = NULL;
5118 CERTCertificate *issuerCert = NULL; 5458 CERTCertificate *issuerCert = NULL;
5119 CERTOCSPSingleResponse *single = NULL;
5120 SECStatus rv = SECFailure; 5459 SECStatus rv = SECFailure;
5121 5460
5122 *certIDWasConsumed = PR_FALSE; 5461 if (!pSingle || !pDecodedResponse) {
5123 *rv_ocsp = SECFailure; 5462 » return SECFailure;
5124 5463 }
5125 response = CERT_DecodeOCSPResponse(encodedResponse); 5464 *pSingle = NULL;
5126 if (response == NULL) { 5465 *pDecodedResponse = CERT_DecodeOCSPResponse(encodedResponse);
5127 » goto loser; 5466 if (!*pDecodedResponse) {
5467 » return SECFailure;
5128 } 5468 }
5129 5469
5130 /* 5470 /*
5131 * Okay, we at least have a response that *looks* like a response! 5471 * Okay, we at least have a response that *looks* like a response!
5132 * Now see if the overall response status value is good or not. 5472 * Now see if the overall response status value is good or not.
5133 * If not, we set an error and give up. (It means that either the 5473 * If not, we set an error and give up. (It means that either the
5134 * server had a problem, or it didn't like something about our 5474 * server had a problem, or it didn't like something about our
5135 * request. Either way there is nothing to do but give up.) 5475 * request. Either way there is nothing to do but give up.)
5136 * Otherwise, we continue to find the actual per-cert status 5476 * Otherwise, we continue to find the actual per-cert status
5137 * in the response. 5477 * in the response.
5138 */ 5478 */
5139 if (CERT_GetOCSPResponseStatus(response) != SECSuccess) { 5479 if (CERT_GetOCSPResponseStatus(*pDecodedResponse) != SECSuccess) {
5140 goto loser; 5480 goto loser;
5141 } 5481 }
5142 5482
5143 /* 5483 /*
5144 * If we've made it this far, we expect a response with a good signature. 5484 * If we've made it this far, we expect a response with a good signature.
5145 * So, check for that. 5485 * So, check for that.
5146 */ 5486 */
5147 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); 5487 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
5148 rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert, 5488 rv = CERT_VerifyOCSPResponseSignature(*pDecodedResponse, handle, pwArg,
5149 » » » issuerCert); 5489 &signerCert, issuerCert);
5150 if (rv != SECSuccess) 5490 if (rv != SECSuccess) {
5151 goto loser; 5491 goto loser;
5492 }
5152 5493
5153 PORT_Assert(signerCert != NULL); /* internal consistency check */ 5494 PORT_Assert(signerCert != NULL); /* internal consistency check */
5154 /* XXX probably should set error, return failure if signerCert is null */ 5495 /* XXX probably should set error, return failure if signerCert is null */
5155 5496
5156
5157 /* 5497 /*
5158 * Again, we are only doing one request for one cert. 5498 * Again, we are only doing one request for one cert.
5159 * XXX When we handle cert chains, the following code will obviously 5499 * XXX When we handle cert chains, the following code will obviously
5160 * have to be modified, in coordation with the code above that will 5500 * have to be modified, in coordation with the code above that will
5161 * have to determine how to make multiple requests, etc. 5501 * have to determine how to make multiple requests, etc.
5162 */ 5502 */
5503 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, *pDecodedResponse, cert ID,
5504 signerCert, time, pSingle);
5505 loser:
5506 if (issuerCert != NULL)
5507 CERT_DestroyCertificate(issuerCert);
5508 if (signerCert != NULL)
5509 CERT_DestroyCertificate(signerCert);
5510 return rv;
5511 }
5163 5512
5164 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 5513 /*
5165 signerCert, time, &single); 5514 * FUNCTION: ocsp_CacheSingleResponse
5166 if (rv != SECSuccess) 5515 * This function requires that the caller has checked that the response
5167 goto loser; 5516 * is valid and verified.
5168 5517 * The (positive or negative) valid response will be used to update the cache.
5169 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time); 5518 * INPUTS:
5170 5519 * CERTOCSPCertID *certID
5171 loser: 5520 * the cert ID corresponding to |cert|
5172 /* If single == NULL here then the response was invalid. */ 5521 * PRBool *certIDWasConsumed
5173 if (single != NULL || cacheInvalid) { 5522 * (output) on return, this is true iff |certID| was consumed by this
5523 * function.
5524 */
5525 void
5526 ocsp_CacheSingleResponse(CERTOCSPCertID *certID,
5527 » » » CERTOCSPSingleResponse *single,
5528 » » » PRBool *certIDWasConsumed)
5529 {
5530 if (single != NULL) {
5174 PR_EnterMonitor(OCSP_Global.monitor); 5531 PR_EnterMonitor(OCSP_Global.monitor);
5175 if (OCSP_Global.maxCacheEntries >= 0) { 5532 if (OCSP_Global.maxCacheEntries >= 0) {
5176 /* single == NULL means: remember response failure */
5177 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, 5533 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
5178 certIDWasConsumed); 5534 certIDWasConsumed);
5179 /* ignore cache update failures */ 5535 /* ignore cache update failures */
5180 } 5536 }
5181 PR_ExitMonitor(OCSP_Global.monitor); 5537 PR_ExitMonitor(OCSP_Global.monitor);
5182 } 5538 }
5183
5184 /* 'single' points within the response so there's no need to free it. */
5185
5186 if (issuerCert != NULL)
5187 CERT_DestroyCertificate(issuerCert);
5188 if (signerCert != NULL)
5189 CERT_DestroyCertificate(signerCert);
5190 if (response != NULL)
5191 CERT_DestroyOCSPResponse(response);
5192 return rv;
5193 } 5539 }
5194 5540
5195 static SECStatus 5541 SECStatus
5196 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, 5542 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
5197 CERTOCSPResponse *response, 5543 CERTOCSPResponse *response,
5198 CERTOCSPCertID *certID, 5544 CERTOCSPCertID *certID,
5199 CERTCertificate *signerCert, 5545 CERTCertificate *signerCert,
5200 PRTime time, 5546 PRTime time,
5201 CERTOCSPSingleResponse 5547 CERTOCSPSingleResponse
5202 **pSingleResponse) 5548 **pSingleResponse)
5203 { 5549 {
5204 SECStatus rv; 5550 SECStatus rv;
5205 ocspResponseData *responseData; 5551 ocspResponseData *responseData;
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
5778 CERT_ClearOCSPCache(); 6124 CERT_ClearOCSPCache();
5779 } 6125 }
5780 6126
5781 /* 6127 /*
5782 * Finally, record the fact. 6128 * Finally, record the fact.
5783 */ 6129 */
5784 statusContext->useDefaultResponder = PR_FALSE; 6130 statusContext->useDefaultResponder = PR_FALSE;
5785 return SECSuccess; 6131 return SECSuccess;
5786 } 6132 }
5787 6133
6134 SECStatus
6135 CERT_ForcePostMethodForOCSP(PRBool forcePost)
6136 {
6137 if (!OCSP_Global.monitor) {
6138 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
6139 return SECFailure;
6140 }
6141
6142 PR_EnterMonitor(OCSP_Global.monitor);
6143 OCSP_Global.forcePost = forcePost;
6144 PR_ExitMonitor(OCSP_Global.monitor);
6145
6146 return SECSuccess;
6147 }
5788 6148
5789 SECStatus 6149 SECStatus
5790 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response) 6150 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response)
5791 { 6151 {
5792 PORT_Assert(response); 6152 PORT_Assert(response);
5793 if (response->statusValue == ocspResponse_successful) 6153 if (response->statusValue == ocspResponse_successful)
5794 return SECSuccess; 6154 return SECSuccess;
5795 6155
5796 switch (response->statusValue) { 6156 switch (response->statusValue) {
5797 case ocspResponse_malformedRequest: 6157 case ocspResponse_malformedRequest:
(...skipping 12 matching lines...) Expand all
5810 case ocspResponse_unauthorized: 6170 case ocspResponse_unauthorized:
5811 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); 6171 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
5812 break; 6172 break;
5813 case ocspResponse_unused: 6173 case ocspResponse_unused:
5814 default: 6174 default:
5815 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); 6175 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
5816 break; 6176 break;
5817 } 6177 }
5818 return SECFailure; 6178 return SECFailure;
5819 } 6179 }
OLDNEW
« no previous file with comments | « nss/lib/certhigh/ocsp.h ('k') | nss/lib/certhigh/ocspi.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698