X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/sec/securityd/SecOCSPCache.c diff --git a/sec/securityd/SecOCSPCache.c b/sec/securityd/SecOCSPCache.c deleted file mode 100644 index 1ae99dbe..00000000 --- a/sec/securityd/SecOCSPCache.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * SecOCSPCache.c - securityd - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "utilities/SecDb.h" -#include "utilities/SecFileLocations.h" -#include "utilities/iOSforOSX.h" - -#define expireSQL CFSTR("DELETE FROM responses WHERE expiresdb = SecOCSPCacheDbCreate(db_name), errOut); - - return this; - -errOut: - if (this) { - CFReleaseSafe(this->db); - free(this); - } - - return NULL; -} - -static CFStringRef SecOCSPCacheCopyPath(void) { - CFStringRef ocspRelPath = kSecOCSPCacheFileName; - CFURLRef ocspURL = SecCopyURLForFileInKeychainDirectory(ocspRelPath); - CFStringRef ocspPath = NULL; - if (ocspURL) { - ocspPath = CFURLCopyFileSystemPath(ocspURL, kCFURLPOSIXPathStyle); - CFRelease(ocspURL); - } - return ocspPath; -} - -static void SecOCSPCacheWith(void(^cacheJob)(SecOCSPCacheRef cache)) { - dispatch_once(&kSecOCSPCacheOnce, ^{ - CFStringRef dbPath = SecOCSPCacheCopyPath(); - if (dbPath) { - kSecOCSPCache = SecOCSPCacheCreate(dbPath); - CFRelease(dbPath); - } - }); - // Do pre job run work here (cancel idle timers etc.) - cacheJob(kSecOCSPCache); - // Do post job run work here (gc timer, etc.) -} - -/* Instance implemenation. */ - -static void _SecOCSPCacheAddResponse(SecOCSPCacheRef this, - SecOCSPResponseRef ocspResponse, CFURLRef localResponderURI) { - secdebug("ocspcache", "adding response from %@", localResponderURI); - /* responses.ocspResponse */ - CFDataRef responseData = SecOCSPResponseGetData(ocspResponse); - __block CFErrorRef localError = NULL; - __block bool ok = true; - ok &= SecDbPerformWrite(this->db, &localError, ^(SecDbConnectionRef dbconn) { - ok &= SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &localError, ^(bool *commit) { - __block sqlite3_int64 responseId; - ok = SecDbWithSQL(dbconn, insertResponseSQL, &localError, ^bool(sqlite3_stmt *insertResponse) { - if (ok) - ok = SecDbBindBlob(insertResponse, 1, - CFDataGetBytePtr(responseData), - CFDataGetLength(responseData), - SQLITE_TRANSIENT, &localError); - - /* responses.responderURI */ - if (ok) { - CFDataRef uriData = NULL; - if (localResponderURI) { - uriData = CFURLCreateData(kCFAllocatorDefault, localResponderURI, - kCFStringEncodingUTF8, false); - } - if (uriData) { - ok = SecDbBindBlob(insertResponse, 2, - CFDataGetBytePtr(uriData), - CFDataGetLength(uriData), - SQLITE_TRANSIENT, &localError); - CFRelease(uriData); - } else { - // Since we use SecDbClearBindings this shouldn't be needed. - //ok = SecDbBindNull(insertResponse, 2, &localError); - } - } - /* responses.expires */ - if (ok) - ok = SecDbBindDouble(insertResponse, 3, - SecOCSPResponseGetExpirationTime(ocspResponse), - &localError); - /* responses.lastUsed */ - if (ok) - ok = SecDbBindDouble(insertResponse, 4, - SecOCSPResponseVerifyTime(ocspResponse), - &localError); - - /* Execute the insert statement. */ - if (ok) - ok = SecDbStep(dbconn, insertResponse, &localError, NULL); - - responseId = sqlite3_last_insert_rowid(SecDbHandle(dbconn)); - return ok; - }); - - /* Now add a link record for every singleResponse in the ocspResponse. */ - if (ok) ok = SecDbWithSQL(dbconn, insertLinkSQL, &localError, ^bool(sqlite3_stmt *insertLink) { - SecAsn1OCSPSingleResponse **responses; - for (responses = ocspResponse->responseData.responses; - *responses; ++responses) { - SecAsn1OCSPSingleResponse *resp = *responses; - SecAsn1OCSPCertID *certId = &resp->certID; - if (ok) ok = SecDbBindBlob(insertLink, 1, - certId->algId.algorithm.Data, - certId->algId.algorithm.Length, - SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(insertLink, 2, - certId->issuerNameHash.Data, - certId->issuerNameHash.Length, - SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(insertLink, 3, - certId->issuerPubKeyHash.Data, - certId->issuerPubKeyHash.Length, - SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(insertLink, 4, - certId->serialNumber.Data, - certId->serialNumber.Length, - SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindInt64(insertLink, 5, responseId, &localError); - - /* Execute the insert statement. */ - if (ok) ok = SecDbStep(dbconn, insertLink, &localError, NULL); - if (ok) ok = SecDbReset(insertLink, &localError); - } - return ok; - }); - if (!ok) - *commit = false; - }); - }); - if (!ok) { - secerror("_SecOCSPCacheAddResponse failed: %@", localError); - } - CFReleaseSafe(localError); -} - -static SecOCSPResponseRef _SecOCSPCacheCopyMatching(SecOCSPCacheRef this, - SecOCSPRequestRef request, CFURLRef responderURI) { - const DERItem *publicKey; - CFDataRef issuer = NULL; - CFDataRef serial = NULL; - __block SecOCSPResponseRef response = NULL; - __block CFErrorRef localError = NULL; - __block bool ok = true; - - require(publicKey = SecCertificateGetPublicKeyData(request->issuer), errOut); - require(issuer = SecCertificateCopyIssuerSequence(request->certificate), errOut); - require(serial = SecCertificateCopySerialNumber(request->certificate), errOut); - - ok &= SecDbPerformRead(this->db, &localError, ^(SecDbConnectionRef dbconn) { - ok &= SecDbWithSQL(dbconn, selectHashAlgorithmSQL, &localError, ^bool(sqlite3_stmt *selectHash) { - ok = SecDbBindBlob(selectHash, 1, CFDataGetBytePtr(serial), CFDataGetLength(serial), SQLITE_TRANSIENT, &localError); - ok &= SecDbStep(dbconn, selectHash, &localError, ^(bool *stopHash) { - SecAsn1Oid algorithm; - algorithm.Data = (uint8_t *)sqlite3_column_blob(selectHash, 0); - algorithm.Length = sqlite3_column_bytes(selectHash, 0); - - /* Calcluate the issuerKey and issuerName digests using the returned - hashAlgorithm. */ - CFDataRef issuerNameHash = SecDigestCreate(kCFAllocatorDefault, - &algorithm, NULL, CFDataGetBytePtr(issuer), CFDataGetLength(issuer)); - CFDataRef issuerPubKeyHash = SecDigestCreate(kCFAllocatorDefault, - &algorithm, NULL, publicKey->data, publicKey->length); - - if (issuerNameHash && issuerPubKeyHash && ok) ok &= SecDbWithSQL(dbconn, selectResponseSQL, &localError, ^bool(sqlite3_stmt *selectResponse) { - /* Now we have the serial, algorithm, issuerNameHash and - issuerPubKeyHash so let's lookup the db entry. */ - if (ok) ok = SecDbBindBlob(selectResponse, 1, CFDataGetBytePtr(issuerNameHash), - CFDataGetLength(issuerNameHash), SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(selectResponse, 2, CFDataGetBytePtr(issuerPubKeyHash), - CFDataGetLength(issuerPubKeyHash), SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(selectResponse, 3, CFDataGetBytePtr(serial), - CFDataGetLength(serial), SQLITE_TRANSIENT, &localError); - if (ok) ok = SecDbBindBlob(selectResponse, 4, algorithm.Data, - algorithm.Length, SQLITE_TRANSIENT, &localError); - if (ok) ok &= SecDbStep(dbconn, selectResponse, &localError, ^(bool *stopResponse) { - /* Found an entry! */ - secdebug("ocspcache", "found cached response"); - CFDataRef resp = CFDataCreate(kCFAllocatorDefault, - sqlite3_column_blob(selectResponse, 0), - sqlite3_column_bytes(selectResponse, 0)); - if (resp) { - response = SecOCSPResponseCreate(resp, NULL_TIME); - CFRelease(resp); - } - if (response) { - //sqlite3_int64 responseId = sqlite3_column_int64(this->selectResponse, 1); - /* @@@ Update the lastUsed field in the db. */ - } - }); - return ok; - }); - - CFReleaseSafe(issuerNameHash); - CFReleaseSafe(issuerPubKeyHash); - }); - return ok; - }); - }); - -errOut: - CFReleaseSafe(serial); - CFReleaseSafe(issuer); - - if (!ok) { - secerror("ocsp cache lookup failed: %@", localError); - if (response) { - SecOCSPResponseFinalize(response); - response = NULL; - } - } - CFReleaseSafe(localError); - - secdebug("ocspcache", "returning %s", (response ? "cached response" : "NULL")); - - return response; -} - -static void _SecOCSPCacheGC(SecOCSPCacheRef this) { - secdebug("ocspcache", "expiring stale responses"); - - __block CFErrorRef localError = NULL; - __block bool ok = true; - ok &= SecDbPerformWrite(this->db, &localError, ^(SecDbConnectionRef dbconn) { - ok &= SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &localError, ^(bool *commit) { - ok &= SecDbWithSQL(dbconn, expireSQL, &localError, ^bool(sqlite3_stmt *expire) { - return SecDbBindDouble(expire, 1, CFAbsoluteTimeGetCurrent(), &localError) && - SecDbStep(dbconn, expire, &localError, NULL); - }); - *commit = ok; - }); - }); - - if (!ok) { - secerror("ocsp cache expire failed: %@", localError); - } - CFReleaseSafe(localError); -} - -static void _SecOCSPCacheFlush(SecOCSPCacheRef this) { - secdebug("ocspcache", "flushing pending changes"); - // NOOP since we use WAL now and commit right away. -} - -/* Public API */ - -void SecOCSPCacheAddResponse(SecOCSPResponseRef response, - CFURLRef localResponderURI) { - SecOCSPCacheWith(^(SecOCSPCacheRef cache) { - _SecOCSPCacheAddResponse(cache, response, localResponderURI); - }); -} - -SecOCSPResponseRef SecOCSPCacheCopyMatching(SecOCSPRequestRef request, - CFURLRef localResponderURI /* may be NULL */) { - __block SecOCSPResponseRef response = NULL; - SecOCSPCacheWith(^(SecOCSPCacheRef cache) { - response = _SecOCSPCacheCopyMatching(cache, request, localResponderURI); - }); - return response; -} - -/* This should be called on a normal non emergency exit. This function - effectively does a SecOCSPCacheFlush. - Currently this is called from our atexit handeler. - This function expires any records that are stale and commits. - - Idea for future cache management policies: - Expire old cache entires from database if: - - The time to do so has arrived based on the nextExpire date in the - policy table. - - If the size of the database exceeds the limit set in the maxSize field - in the policy table, vacuum the db. If the database is still too - big, expire records on a LRU basis. - */ -void SecOCSPCacheGC(void) { - if (kSecOCSPCache) - _SecOCSPCacheGC(kSecOCSPCache); -} - -/* Call this periodically or perhaps when we are exiting due to low memory. */ -void SecOCSPCacheFlush(void) { - if (kSecOCSPCache) - _SecOCSPCacheFlush(kSecOCSPCache); -}