OLD | NEW |
---|---|
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 * $Id$ | 9 * $Id$ |
10 */ | 10 */ |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 void *pwArg, | 117 void *pwArg, |
118 PRBool *certIDWasConsumed, | 118 PRBool *certIDWasConsumed, |
119 SECStatus *rv_ocsp); | 119 SECStatus *rv_ocsp); |
120 | 120 |
121 static SECStatus | 121 static SECStatus |
122 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, | 122 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, |
123 CERTOCSPCertID *certID, | 123 CERTOCSPCertID *certID, |
124 CERTCertificate *cert, | 124 CERTCertificate *cert, |
125 int64 time, | 125 int64 time, |
126 void *pwArg, | 126 void *pwArg, |
127 » » » SECItem *encodedResponse, | 127 » » » const SECItem *encodedResponse, |
128 » » » PRBool cacheInvalid, | |
128 PRBool *certIDWasConsumed, | 129 PRBool *certIDWasConsumed, |
129 PRBool cacheNegative, | |
130 SECStatus *rv_ocsp); | 130 SECStatus *rv_ocsp); |
131 | 131 |
132 static SECStatus | 132 static SECStatus |
133 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, | 133 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, |
134 CERTOCSPResponse *response, | 134 CERTOCSPResponse *response, |
135 CERTOCSPCertID *certID, | 135 CERTOCSPCertID *certID, |
136 CERTCertificate *signerCert, | 136 CERTCertificate *signerCert, |
137 int64 time, | 137 int64 time, |
138 CERTOCSPSingleResponse **pSingleResponse ); | 138 CERTOCSPSingleResponse **pSingleResponse ); |
139 | 139 |
140 static SECStatus | 140 static SECStatus |
141 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time); | 141 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time); |
142 | 142 |
143 static CERTOCSPCertID * | |
144 cert_DupOCSPCertID(CERTOCSPCertID *src); | |
wtc
2013/04/24 22:49:45
The argument should be 'const'.
| |
145 | |
143 #ifndef DEBUG | 146 #ifndef DEBUG |
144 #define OCSP_TRACE(msg) | 147 #define OCSP_TRACE(msg) |
145 #define OCSP_TRACE_TIME(msg, time) | 148 #define OCSP_TRACE_TIME(msg, time) |
146 #define OCSP_TRACE_CERT(cert) | 149 #define OCSP_TRACE_CERT(cert) |
147 #define OCSP_TRACE_CERTID(certid) | 150 #define OCSP_TRACE_CERTID(certid) |
148 #else | 151 #else |
149 #define OCSP_TRACE(msg) ocsp_Trace msg | 152 #define OCSP_TRACE(msg) ocsp_Trace msg |
150 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time) | 153 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time) |
151 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert) | 154 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert) |
152 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid) | 155 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid) |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 now = PR_Now(); | 762 now = PR_Now(); |
760 retval = (cacheItem->nextFetchAttemptTime > now); | 763 retval = (cacheItem->nextFetchAttemptTime > now); |
761 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval)); | 764 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval)); |
762 PR_ExitMonitor(OCSP_Global.monitor); | 765 PR_ExitMonitor(OCSP_Global.monitor); |
763 return retval; | 766 return retval; |
764 } | 767 } |
765 | 768 |
766 /* | 769 /* |
767 * Status in *certIDWasConsumed will always be correct, regardless of | 770 * Status in *certIDWasConsumed will always be correct, regardless of |
768 * return value. | 771 * return value. |
772 * If the caller is unable to transfer ownership of certID, | |
773 * then the caller must set certIDWasConsumed to NULL, | |
774 * and this function will potentially duplicate the certID object. | |
769 */ | 775 */ |
770 static SECStatus | 776 static SECStatus |
771 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, | 777 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, |
772 CERTOCSPCertID *certID, | 778 CERTOCSPCertID *certID, |
773 CERTOCSPSingleResponse *single, | 779 CERTOCSPSingleResponse *single, |
774 PRBool *certIDWasConsumed) | 780 PRBool *certIDWasConsumed) |
775 { | 781 { |
776 SECStatus rv; | 782 SECStatus rv; |
777 OCSPCacheItem *cacheItem; | 783 OCSPCacheItem *cacheItem; |
778 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); | 784 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); |
779 | 785 |
780 if (!certIDWasConsumed) { | 786 if (certIDWasConsumed) |
781 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
782 return SECFailure; | |
783 } | |
784 *certIDWasConsumed = PR_FALSE; | 787 *certIDWasConsumed = PR_FALSE; |
wtc
2013/04/24 22:49:45
We should fix the indentation.
| |
785 | 788 |
786 PR_EnterMonitor(OCSP_Global.monitor); | 789 PR_EnterMonitor(OCSP_Global.monitor); |
787 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); | 790 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); |
788 | 791 |
789 cacheItem = ocsp_FindCacheEntry(cache, certID); | 792 cacheItem = ocsp_FindCacheEntry(cache, certID); |
790 if (!cacheItem) { | 793 if (!cacheItem) { |
791 rv = ocsp_CreateCacheItemAndConsumeCertID(cache, certID, | 794 CERTOCSPCertID *myCertID; |
795 if (certIDWasConsumed) { | |
796 myCertID = certID; | |
797 *certIDWasConsumed = PR_TRUE; | |
798 } else { | |
799 myCertID = cert_DupOCSPCertID(certID); | |
800 if (!myCertID) { | |
801 PR_ExitMonitor(OCSP_Global.monitor); | |
802 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); | |
803 return SECFailure; | |
804 } | |
805 } | |
806 | |
807 rv = ocsp_CreateCacheItemAndConsumeCertID(cache, myCertID, | |
792 &cacheItem); | 808 &cacheItem); |
793 if (rv != SECSuccess) { | 809 if (rv != SECSuccess) { |
794 PR_ExitMonitor(OCSP_Global.monitor); | 810 PR_ExitMonitor(OCSP_Global.monitor); |
795 return rv; | 811 return rv; |
796 } | 812 } |
797 *certIDWasConsumed = PR_TRUE; | |
798 } | 813 } |
799 if (single) { | 814 if (single) { |
800 rv = ocsp_SetCacheItemResponse(cacheItem, single); | 815 PRTime thisUpdate; |
801 if (rv != SECSuccess) { | 816 rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate); |
802 ocsp_RemoveCacheItem(cache, cacheItem); | 817 |
803 PR_ExitMonitor(OCSP_Global.monitor); | 818 if (!cacheItem->haveThisUpdate || |
804 return rv; | 819 (rv == SECSuccess && cacheItem->thisUpdate < thisUpdate)) { |
820 rv = ocsp_SetCacheItemResponse(cacheItem, single); | |
821 if (rv != SECSuccess) { | |
822 ocsp_RemoveCacheItem(cache, cacheItem); | |
823 PR_ExitMonitor(OCSP_Global.monitor); | |
824 return rv; | |
825 } | |
826 } else { | |
827 OCSP_TRACE(("Not caching response because the response is not newer than the cache")); | |
wtc
2013/04/24 22:49:45
Fold this long line.
| |
805 } | 828 } |
806 } else { | 829 } else { |
807 cacheItem->missingResponseError = PORT_GetError(); | 830 cacheItem->missingResponseError = PORT_GetError(); |
831 if (cacheItem->certStatusArena) { | |
832 PORT_FreeArena(cacheItem->certStatusArena, PR_FALSE); | |
833 cacheItem->certStatusArena = NULL; | |
834 } | |
808 } | 835 } |
809 ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem); | 836 ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem); |
810 ocsp_CheckCacheSize(cache); | 837 ocsp_CheckCacheSize(cache); |
811 | 838 |
812 PR_ExitMonitor(OCSP_Global.monitor); | 839 PR_ExitMonitor(OCSP_Global.monitor); |
813 return SECSuccess; | 840 return SECSuccess; |
814 } | 841 } |
815 | 842 |
816 extern SECStatus | 843 extern SECStatus |
817 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode) | 844 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode) |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1538 } | 1565 } |
1539 | 1566 |
1540 /* | 1567 /* |
1541 * Digest data using the specified algorithm. | 1568 * Digest data using the specified algorithm. |
1542 * The necessary storage for the digest data is allocated. If "fill" is | 1569 * The necessary storage for the digest data is allocated. If "fill" is |
1543 * non-null, the data is put there, otherwise a SECItem is allocated. | 1570 * non-null, the data is put there, otherwise a SECItem is allocated. |
1544 * Allocation from "arena" if it is non-null, heap otherwise. Any problem | 1571 * Allocation from "arena" if it is non-null, heap otherwise. Any problem |
1545 * results in a NULL being returned (and an appropriate error set). | 1572 * results in a NULL being returned (and an appropriate error set). |
1546 */ | 1573 */ |
1547 | 1574 |
1548 static SECItem * | 1575 SECItem * |
1549 ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg, | 1576 ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg, |
1550 SECItem *fill, const SECItem *src) | 1577 SECItem *fill, const SECItem *src) |
1551 { | 1578 { |
1552 const SECHashObject *digestObject; | 1579 const SECHashObject *digestObject; |
1553 SECItem *result = NULL; | 1580 SECItem *result = NULL; |
1554 void *mark = NULL; | 1581 void *mark = NULL; |
1555 void *digestBuff = NULL; | 1582 void *digestBuff = NULL; |
1556 | 1583 |
1557 if ( arena != NULL ) { | 1584 if ( arena != NULL ) { |
1558 mark = PORT_ArenaMark(arena); | 1585 mark = PORT_ArenaMark(arena); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1745 | 1772 |
1746 certID = ocsp_CreateCertID(arena, cert, time); | 1773 certID = ocsp_CreateCertID(arena, cert, time); |
1747 if (!certID) { | 1774 if (!certID) { |
1748 PORT_FreeArena(arena, PR_FALSE); | 1775 PORT_FreeArena(arena, PR_FALSE); |
1749 return NULL; | 1776 return NULL; |
1750 } | 1777 } |
1751 certID->poolp = arena; | 1778 certID->poolp = arena; |
1752 return certID; | 1779 return certID; |
1753 } | 1780 } |
1754 | 1781 |
1782 static CERTOCSPCertID * | |
1783 cert_DupOCSPCertID(CERTOCSPCertID *src) | |
1784 { | |
1785 CERTOCSPCertID *dest; | |
1786 PRArenaPool *arena = NULL; | |
1787 | |
1788 if (!src) { | |
1789 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1790 return NULL; | |
1791 } | |
1792 | |
1793 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
1794 if (!arena) | |
1795 goto loser; | |
1796 | |
1797 dest = PORT_ArenaZNew(arena, CERTOCSPCertID); | |
1798 if (!dest) | |
wtc
2013/04/24 22:49:45
Fix indentation.
| |
1799 goto loser; | |
1800 | |
1801 #define DUPHELP(element) \ | |
1802 if (src->element.data) { \ | |
1803 if (SECITEM_CopyItem(arena, &dest->element, &src->element) \ | |
1804 != SECSuccess) \ | |
1805 goto loser; \ | |
wtc
2013/04/24 22:49:45
Add curly braces. Combine nested ifs using &&.
| |
1806 } | |
1807 | |
1808 DUPHELP(hashAlgorithm.algorithm) | |
1809 DUPHELP(hashAlgorithm.parameters) | |
1810 DUPHELP(issuerNameHash) | |
1811 DUPHELP(issuerKeyHash) | |
1812 DUPHELP(serialNumber) | |
1813 DUPHELP(issuerSHA1NameHash) | |
1814 DUPHELP(issuerMD5NameHash) | |
1815 DUPHELP(issuerMD2NameHash) | |
1816 DUPHELP(issuerSHA1KeyHash) | |
1817 DUPHELP(issuerMD5KeyHash) | |
1818 DUPHELP(issuerMD2KeyHash) | |
1819 | |
1820 dest->poolp = arena; | |
1821 return dest; | |
1822 | |
1823 loser: | |
1824 if (arena) | |
1825 PORT_FreeArena(arena, PR_FALSE); | |
1826 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); | |
1827 return NULL; | |
1828 } | |
1829 | |
1755 /* | 1830 /* |
1756 * Callback to set Extensions in request object | 1831 * Callback to set Extensions in request object |
1757 */ | 1832 */ |
1758 void SetSingleReqExts(void *object, CERTCertExtension **exts) | 1833 void SetSingleReqExts(void *object, CERTCertExtension **exts) |
1759 { | 1834 { |
1760 ocspSingleRequest *singleRequest = | 1835 ocspSingleRequest *singleRequest = |
1761 (ocspSingleRequest *)object; | 1836 (ocspSingleRequest *)object; |
1762 | 1837 |
1763 singleRequest->singleRequestExtensions = exts; | 1838 singleRequest->singleRequestExtensions = exts; |
1764 } | 1839 } |
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2528 * SECItem *src | 2603 * SECItem *src |
2529 * Pointer to a SECItem holding DER encoded OCSP Response. | 2604 * Pointer to a SECItem holding DER encoded OCSP Response. |
2530 * RETURN: | 2605 * RETURN: |
2531 * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response); | 2606 * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response); |
2532 * the caller is responsible for destroying it. Or NULL if error (either | 2607 * the caller is responsible for destroying it. Or NULL if error (either |
2533 * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE), | 2608 * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE), |
2534 * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), | 2609 * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), |
2535 * or a low-level or internal error occurred). | 2610 * or a low-level or internal error occurred). |
2536 */ | 2611 */ |
2537 CERTOCSPResponse * | 2612 CERTOCSPResponse * |
2538 CERT_DecodeOCSPResponse(SECItem *src) | 2613 CERT_DecodeOCSPResponse(const SECItem *src) |
2539 { | 2614 { |
2540 PRArenaPool *arena = NULL; | 2615 PRArenaPool *arena = NULL; |
2541 CERTOCSPResponse *response = NULL; | 2616 CERTOCSPResponse *response = NULL; |
2542 SECStatus rv = SECFailure; | 2617 SECStatus rv = SECFailure; |
2543 ocspResponseStatus sv; | 2618 ocspResponseStatus sv; |
2544 SECItem newSrc; | 2619 SECItem newSrc; |
2545 | 2620 |
2546 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 2621 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2547 if (arena == NULL) { | 2622 if (arena == NULL) { |
2548 goto loser; | 2623 goto loser; |
(...skipping 2261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4810 * void *pwArg | 4885 * void *pwArg |
4811 * argument for password prompting, if needed | 4886 * argument for password prompting, if needed |
4812 * RETURN: | 4887 * RETURN: |
4813 * SECSuccess if the cert was found in the cache, or if the OCSP response was | 4888 * SECSuccess if the cert was found in the cache, or if the OCSP response was |
4814 * found to be valid and inserted into the cache. SECFailure otherwise. | 4889 * found to be valid and inserted into the cache. SECFailure otherwise. |
4815 */ | 4890 */ |
4816 SECStatus | 4891 SECStatus |
4817 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, | 4892 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, |
4818 CERTCertificate *cert, | 4893 CERTCertificate *cert, |
4819 int64 time, | 4894 int64 time, |
4820 » » » » SECItem *encodedResponse, | 4895 » » » » const SECItem *encodedResponse, |
4821 void *pwArg) | 4896 void *pwArg) |
4822 { | 4897 { |
4823 CERTOCSPCertID *certID; | 4898 CERTOCSPCertID *certID = NULL; |
4824 PRBool certIDWasConsumed = PR_FALSE; | 4899 PRBool certIDWasConsumed = PR_FALSE; |
4825 SECStatus rv = SECFailure; | 4900 SECStatus rv = SECFailure; |
4826 SECStatus rvOcsp; | 4901 SECStatus rvOcsp; |
4827 SECErrorCodes dummy_error_code; /* we ignore this */ | 4902 SECErrorCodes dummy_error_code; /* we ignore this */ |
4828 | 4903 |
4904 /* The OCSP cache can be in three states regarding this certificate: | |
4905 * + Good (cached, timely, 'good' response, or revoked in the future) | |
4906 * + Revoked (cached, timely, but doesn't fit in the last category) | |
4907 * + Miss (no knowledge) | |
4908 * | |
4909 * Likewise, the side-channel information can be | |
4910 * + Good (timely, 'good' response, or revoked in the future) | |
4911 * + Revoked (timely, but doesn't fit in the last category) | |
4912 * + Invalid (bad syntax, bad signature, not timely etc) | |
4913 * | |
4914 * The common case is that the cache result is Good and so is the | |
4915 * side-channel information. We want to save processing time in this case | |
4916 * so we say that any time we see a Good result from the cache we return | |
4917 * early. | |
4918 * | |
4919 * Cache result | |
4920 * | Good Revoked Miss | |
4921 * ---+-------------------------------------------- | |
4922 * G | noop Cache more Cache it | |
4923 * S | recent result | |
4924 * i | | |
4925 * d | | |
4926 * e | | |
4927 * R | noop Cache more Cache it | |
4928 * C | recent result | |
4929 * h | | |
4930 * a | | |
4931 * n | | |
4932 * n I | noop Noop Noop | |
4933 * e | | |
4934 * l | | |
4935 * | |
4936 * 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, | |
4938 * at a broken responder. However, side channels are commonly attacker | |
4939 * controlled and so we must not cache a negative result for an Invalid | |
4940 * side channel. | |
4941 */ | |
4942 | |
4943 if (!cert) { | |
4944 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
4945 return SECFailure; | |
4946 } | |
4829 certID = CERT_CreateOCSPCertID(cert, time); | 4947 certID = CERT_CreateOCSPCertID(cert, time); |
4830 if (!certID) | 4948 if (!certID) |
4831 return SECFailure; | 4949 return SECFailure; |
4832 rv = ocsp_GetCachedOCSPResponseStatusIfFresh( | 4950 rv = ocsp_GetCachedOCSPResponseStatusIfFresh( |
4833 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ | 4951 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ |
4834 &rvOcsp, &dummy_error_code); | 4952 &rvOcsp, &dummy_error_code); |
4835 if (rv == SECSuccess && rvOcsp == SECSuccess) { | 4953 if (rv == SECSuccess && rvOcsp == SECSuccess) { |
4836 » /* The cached value is good. We don't want to waste time validating | 4954 /* The cached value is good. We don't want to waste time validating |
4837 » * this OCSP response. */ | 4955 * this OCSP response. This is the first column in the table above. */ |
4838 CERT_DestroyOCSPCertID(certID); | 4956 CERT_DestroyOCSPCertID(certID); |
4839 return rv; | 4957 return rv; |
4840 } | 4958 } |
4841 | 4959 |
4842 /* Since the OCSP response came from a side channel it is attacker | 4960 /* The logic for caching the more recent response is handled in |
4843 * controlled. The attacker can have chosen any valid OCSP response, | 4961 * ocsp_CreateOrUpdateCacheEntry, which is called by this function. */ |
4844 * including responses from the past. In this case, | 4962 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, |
4845 * ocsp_GetVerifiedSingleResponseForCertID will fail. If we recorded a | 4963 pwArg, encodedResponse, |
4846 * negative cache entry in this case, then the attacker would have | 4964 PR_FALSE /* don't cache if invalid */, |
4847 * 'poisoned' our cache (denial of service), so we don't record negative | 4965 &certIDWasConsumed, |
4848 * results. */ | |
4849 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg, | |
4850 encodedResponse, &certIDWasConsumed, | |
4851 PR_FALSE /* don't cache failures */, | |
4852 &rvOcsp); | 4966 &rvOcsp); |
4853 if (!certIDWasConsumed) { | 4967 if (!certIDWasConsumed) { |
4854 CERT_DestroyOCSPCertID(certID); | 4968 CERT_DestroyOCSPCertID(certID); |
4855 } | 4969 } |
4856 return rv == SECSuccess ? rvOcsp : rv; | 4970 return rv == SECSuccess ? rvOcsp : rv; |
4857 } | 4971 } |
4858 | 4972 |
4859 /* | 4973 /* |
4860 * Status in *certIDWasConsumed will always be correct, regardless of | 4974 * Status in *certIDWasConsumed will always be correct, regardless of |
4861 * return value. | 4975 * return value. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4929 */ | 5043 */ |
4930 encodedResponse = | 5044 encodedResponse = |
4931 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location, | 5045 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location, |
4932 time, locationIsDefault, | 5046 time, locationIsDefault, |
4933 pwArg, &request); | 5047 pwArg, &request); |
4934 if (encodedResponse == NULL) { | 5048 if (encodedResponse == NULL) { |
4935 goto loser; | 5049 goto loser; |
4936 } | 5050 } |
4937 | 5051 |
4938 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg, | 5052 rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg, |
4939 » encodedResponse, certIDWasConsumed, | 5053 encodedResponse, |
4940 » PR_TRUE /* cache failures */, rv_ocsp); | 5054 PR_TRUE /* cache if invalid */, |
5055 certIDWasConsumed, rv_ocsp); | |
4941 | 5056 |
4942 loser: | 5057 loser: |
4943 if (request != NULL) | 5058 if (request != NULL) |
4944 CERT_DestroyOCSPRequest(request); | 5059 CERT_DestroyOCSPRequest(request); |
4945 if (encodedResponse != NULL) | 5060 if (encodedResponse != NULL) |
4946 SECITEM_FreeItem(encodedResponse, PR_TRUE); | 5061 SECITEM_FreeItem(encodedResponse, PR_TRUE); |
4947 if (location != NULL) | 5062 if (location != NULL) |
4948 PORT_Free(location); | 5063 PORT_Free(location); |
4949 | 5064 |
4950 return rv; | 5065 return rv; |
(...skipping 17 matching lines...) Expand all Loading... | |
4968 * CERTOCSPCertID *certID | 5083 * CERTOCSPCertID *certID |
4969 * the cert ID corresponding to |cert| | 5084 * the cert ID corresponding to |cert| |
4970 * CERTCertificate *cert | 5085 * CERTCertificate *cert |
4971 * the certificate being checked | 5086 * the certificate being checked |
4972 * int64 time | 5087 * int64 time |
4973 * time for which status is to be determined | 5088 * time for which status is to be determined |
4974 * void *pwArg | 5089 * void *pwArg |
4975 * the opaque argument to the password prompting function. | 5090 * the opaque argument to the password prompting function. |
4976 * SECItem *encodedResponse | 5091 * SECItem *encodedResponse |
4977 * the DER encoded bytes of the OCSP response | 5092 * the DER encoded bytes of the OCSP response |
5093 * PRBool cacheInvalid | |
5094 * If true then invalid responses will cause a negative cache entry to be | |
5095 * created. (Invalid means bad syntax, bad signature etc) | |
4978 * PRBool *certIDWasConsumed | 5096 * PRBool *certIDWasConsumed |
4979 * (output) on return, this is true iff |certID| was consumed by this | 5097 * (output) on return, this is true iff |certID| was consumed by this |
4980 * function. | 5098 * function. |
4981 * SECStatus *rv_ocsp | 5099 * SECStatus *rv_ocsp |
4982 * (output) on return, this is SECSuccess iff the response is good (see | 5100 * (output) on return, this is SECSuccess iff the response is good (see |
4983 * definition of 'good' above). | 5101 * definition of 'good' above). |
4984 * RETURN: | 5102 * RETURN: |
4985 * SECSuccess iff the response is valid. | 5103 * SECSuccess iff the response is valid. |
4986 */ | 5104 */ |
4987 static SECStatus | 5105 static SECStatus |
4988 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, | 5106 ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle, |
4989 CERTOCSPCertID *certID, | 5107 CERTOCSPCertID *certID, |
4990 CERTCertificate *cert, | 5108 CERTCertificate *cert, |
4991 int64 time, | 5109 int64 time, |
4992 void *pwArg, | 5110 void *pwArg, |
4993 » » » SECItem *encodedResponse, | 5111 » » » const SECItem *encodedResponse, |
5112 PRBool cacheInvalid, | |
4994 PRBool *certIDWasConsumed, | 5113 PRBool *certIDWasConsumed, |
4995 PRBool cacheNegative, | |
4996 SECStatus *rv_ocsp) | 5114 SECStatus *rv_ocsp) |
4997 { | 5115 { |
4998 CERTOCSPResponse *response = NULL; | 5116 CERTOCSPResponse *response = NULL; |
4999 CERTCertificate *signerCert = NULL; | 5117 CERTCertificate *signerCert = NULL; |
5000 CERTCertificate *issuerCert = NULL; | 5118 CERTCertificate *issuerCert = NULL; |
5001 CERTOCSPSingleResponse *single = NULL; | 5119 CERTOCSPSingleResponse *single = NULL; |
5002 SECStatus rv = SECFailure; | 5120 SECStatus rv = SECFailure; |
5003 | 5121 |
5004 *certIDWasConsumed = PR_FALSE; | 5122 *certIDWasConsumed = PR_FALSE; |
5005 *rv_ocsp = SECFailure; | 5123 *rv_ocsp = SECFailure; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5044 */ | 5162 */ |
5045 | 5163 |
5046 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, | 5164 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, |
5047 signerCert, time, &single); | 5165 signerCert, time, &single); |
5048 if (rv != SECSuccess) | 5166 if (rv != SECSuccess) |
5049 goto loser; | 5167 goto loser; |
5050 | 5168 |
5051 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time); | 5169 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time); |
5052 | 5170 |
5053 loser: | 5171 loser: |
5054 if (cacheNegative || *rv_ocsp == SECSuccess) { | 5172 /* If single == NULL here then the response was invalid. */ |
5173 if (single != NULL || cacheInvalid) { | |
5055 PR_EnterMonitor(OCSP_Global.monitor); | 5174 PR_EnterMonitor(OCSP_Global.monitor); |
5056 if (OCSP_Global.maxCacheEntries >= 0) { | 5175 if (OCSP_Global.maxCacheEntries >= 0) { |
5057 /* single == NULL means: remember response failure */ | 5176 /* single == NULL means: remember response failure */ |
5058 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, | 5177 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, |
5059 certIDWasConsumed); | 5178 certIDWasConsumed); |
5060 /* ignore cache update failures */ | 5179 /* ignore cache update failures */ |
5061 } | 5180 } |
5062 PR_ExitMonitor(OCSP_Global.monitor); | 5181 PR_ExitMonitor(OCSP_Global.monitor); |
5063 } | 5182 } |
5064 | 5183 |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5691 case ocspResponse_unauthorized: | 5810 case ocspResponse_unauthorized: |
5692 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); | 5811 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); |
5693 break; | 5812 break; |
5694 case ocspResponse_unused: | 5813 case ocspResponse_unused: |
5695 default: | 5814 default: |
5696 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); | 5815 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); |
5697 break; | 5816 break; |
5698 } | 5817 } |
5699 return SECFailure; | 5818 return SECFailure; |
5700 } | 5819 } |
OLD | NEW |