| 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); |
| 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; |
| 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")); |
| 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) |
| 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; \ |
| 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 |