]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/Security/SecTrustSettings.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / sec / Security / SecTrustSettings.c
diff --git a/OSX/sec/Security/SecTrustSettings.c b/OSX/sec/Security/SecTrustSettings.c
deleted file mode 100644 (file)
index 78f09e6..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (c) 2007-2008,2010,2012-2015 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@
- */
-
-/*
- *  SecTrustSettings.c - Implement trust settings for certificates
- */
-
-#include "SecTrustSettings.h"
-#include "SecTrustSettingsPriv.h"
-#include <Security/SecCertificatePriv.h>
-#include <AssertMacros.h>
-#include <pthread.h>
-#include <utilities/debugging.h>
-#include "SecBasePriv.h"
-#include <Security/SecInternal.h>
-#include <CoreFoundation/CFRuntime.h>
-#include <utilities/SecCFWrappers.h>
-
-#define trustSettingsDbg(args...)              secdebug("trustSettings", ## args)
-#define trustSettingsEvalDbg(args...)  secdebug("trustSettingsEval", ## args)
-
-// MARK: -
-// MARK: Static Functions
-
-/* Return a CFDataRef representation of a (hex)string. */
-static CFDataRef SecCopyDataFromHexString(CFStringRef string) {
-    CFMutableDataRef data;
-    CFIndex ix, length;
-       UInt8 *bytes;
-
-       length = string ? CFStringGetLength(string) : 0;
-       if (length & 1) {
-               secwarning("Odd length string: %@ returning NULL", string);
-               return NULL;
-       }
-
-       data = CFDataCreateMutable(kCFAllocatorDefault, length / 2);
-       CFDataSetLength(data, length / 2);
-       bytes = CFDataGetMutableBytePtr(data);
-
-    CFStringInlineBuffer buf = {};
-       CFRange range = { 0, length };
-       CFStringInitInlineBuffer(string, &buf, range);
-       UInt8 lastv = 0;
-       for (ix = 0; ix < length; ++ix) {
-               UniChar c = CFStringGetCharacterFromInlineBuffer(&buf, ix);
-               UInt8 v;
-               if ('0' <= c && c <= '9')
-                       v = c - '0';
-               else if ('A' <= c && c <= 'F')
-                       v = c = 'A' + 10;
-               else if ('a' <= c && c <= 'a')
-                       v = c = 'a' + 10;
-               else {
-                       secwarning("Non hex string: %@ returning NULL", string);
-                       CFRelease(data);
-                       return NULL;
-               }
-               if (ix & 1) {
-                       *bytes++ = (lastv << 4) + v;
-               } else {
-                       lastv = v;
-               }
-       }
-
-    return data;
-}
-
-#if 0
-/*
- * Obtain a string representing a cert's SHA1 digest. This string is
- * the key used to look up per-cert trust settings in a TrustSettings record.
- */
-static CFStringRef SecTrustSettingsCertHashStrFromCert(
-       SecCertificateRef certRef)
-{
-       if (certRef == NULL) {
-               return NULL;
-       }
-
-       if(certRef == kSecTrustSettingsDefaultRootCertSetting) {
-               /* use this string instead of the cert hash as the dictionary key */
-               secdebug("trustsettings","DefaultSetting");
-               return kSecTrustRecordDefaultRootCert;
-       }
-
-       CFDataRef digest = SecCertificateGetSHA1Digest(certRef);
-       return CFDataCopyHexString(digest);
-}
-#endif
-
-// MARK: -
-// MARK: SecTrustSettings
-/********************************************************
- ************** SecTrustSettings object *****************
- ********************************************************/
-
-struct __SecTrustSettings {
-    CFRuntimeBase              _base;
-
-       /* the overall parsed TrustSettings - may be NULL if this is trimmed */
-       CFDictionaryRef                                 _propList;
-
-       /* and the main thing we work with, the dictionary of per-cert trust settings */
-       CFMutableDictionaryRef                  _trustDict;
-
-       /* version number of mPropDict */
-       SInt32                                                  _dictVersion;
-
-       SecTrustSettingsDomain                  _domain;
-       bool                                                    _dirty;         /* we've changed _trustDict since creation */
-};
-
-static CFStringRef SecTrustSettingsCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
-    SecTrustSettingsRef ts = (SecTrustSettingsRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-                                    CFSTR("<SecTrustSettings: %p>"), ts);
-}
-
-static void SecTrustSettingsDestroy(CFTypeRef cf) {
-       SecTrustSettingsRef ts = (SecTrustSettingsRef) cf;
-       CFReleaseSafe(ts->_propList);
-       CFReleaseSafe(ts->_trustDict);
-}
-
-/* SecTrustSettings API functions. */
-CFGiblisFor(SecTrustSettings)
-
-/* Make sure a presumed CFNumber can be converted to a 32-bit number */
-static bool tsIsGoodCfNum(CFNumberRef cfn, SInt32 *num)
-{
-       /* by convention */
-       if (cfn == NULL) {
-               *num = 0;
-               return true;
-       }
-       require(CFGetTypeID(cfn) == CFNumberGetTypeID(), errOut);
-       return CFNumberGetValue(cfn, kCFNumberSInt32Type, num);
-errOut:
-       return false;
-}
-
-static bool validateUsageConstraint(const void *value) {
-       CFDictionaryRef ucDict = (CFDictionaryRef)value;
-       require(CFGetTypeID(ucDict) == CFDictionaryGetTypeID(), errOut);
-
-       CFDataRef certPolicy = (CFDataRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsPolicy);
-       require(certPolicy && CFGetTypeID(certPolicy) == CFDataGetTypeID(), errOut);
-
-       CFStringRef certApp = (CFStringRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsApplication);
-       require(certApp && CFGetTypeID(certApp) == CFStringGetTypeID(), errOut);
-
-       CFStringRef policyStr = (CFStringRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsPolicyString);
-       require(policyStr && CFGetTypeID(policyStr) == CFStringGetTypeID(), errOut);
-
-       SInt32 dummy;
-       CFNumberRef allowedError = (CFNumberRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsAllowedError);
-       require(tsIsGoodCfNum(allowedError, &dummy), errOut);
-
-       CFNumberRef trustSettingsResult = (CFNumberRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsResult);
-       require(tsIsGoodCfNum(trustSettingsResult, &dummy), errOut);
-
-       CFNumberRef keyUsage = (CFNumberRef)CFDictionaryGetValue(ucDict,
-               kSecTrustSettingsKeyUsage);
-       require(tsIsGoodCfNum(keyUsage, &dummy), errOut);
-
-       return true;
-errOut:
-       return false;
-}
-
-static bool validateTrustSettingsArray(CFArrayRef usageConstraints) {
-       CFIndex ix, numConstraints = CFArrayGetCount(usageConstraints);
-       bool result = true;
-       for (ix = 0; ix < numConstraints; ++ix) {
-               if (!validateUsageConstraint(CFArrayGetValueAtIndex(usageConstraints, ix)))
-                       result = false;
-       }
-       return result;
-}
-
-struct trustListContext {
-       CFMutableDictionaryRef dict;
-       SInt32 version;
-       bool trim;
-       OSStatus status;
-};
-
-static void trustListApplierFunction(const void *key, const void *value, void *context) {
-       CFStringRef digest = (CFStringRef)key;
-       CFDictionaryRef certDict = (CFDictionaryRef)value;
-       struct trustListContext *tlc = (struct trustListContext *)context;
-       CFDataRef newKey = NULL;
-       CFMutableDictionaryRef newDict = NULL;
-
-       /* Get the key. */
-       require(digest && CFGetTypeID(digest) == CFStringGetTypeID(), errOut);
-       /* Convert it to a CFDataRef. */
-       require(newKey = SecCopyDataFromHexString(digest), errOut);
-
-       /* get per-cert dictionary */
-       require(certDict && CFGetTypeID(certDict) == CFDictionaryGetTypeID(), errOut);
-
-       /* Create the to be inserted dictionary. */
-       require(newDict = CFDictionaryCreateMutable(kCFAllocatorDefault,
-               tlc->trim ? 1 : 4, &kCFTypeDictionaryKeyCallBacks,
-               &kCFTypeDictionaryValueCallBacks), errOut);
-
-       /* The certDict dictionary should have exactly four entries.
-          If we're trimming, all we need is the actual trust settings. */
-
-       /* issuer */
-       CFDataRef issuer = (CFDataRef)CFDictionaryGetValue(certDict,
-               kTrustRecordIssuer);
-       require(issuer && CFGetTypeID(issuer) == CFDataGetTypeID(), errOut);
-
-       /* serial number */
-       CFDataRef serial = (CFDataRef)CFDictionaryGetValue(certDict,
-               kTrustRecordSerialNumber);
-       require(serial && CFGetTypeID(serial) == CFDataGetTypeID(), errOut);
-
-       /* modification date */
-       CFDateRef modDate = (CFDateRef)CFDictionaryGetValue(certDict,
-               kTrustRecordModDate);
-       require(modDate && CFGetTypeID(modDate) == CFDateGetTypeID(), errOut);
-
-       /* If we are not trimming we copy these extra values as well. */
-       if (!tlc->trim) {
-               CFDictionaryAddValue(newDict, kTrustRecordIssuer, issuer);
-               CFDictionaryAddValue(newDict, kTrustRecordSerialNumber, serial);
-               CFDictionaryAddValue(newDict, kTrustRecordModDate, modDate);
-       }
-
-       /* The actual trust settings */
-       CFArrayRef trustSettings = (CFArrayRef)CFDictionaryGetValue(certDict,
-                       kTrustRecordTrustSettings);
-       /* optional; this cert's entry is good */
-       if(trustSettings) {
-               require(CFGetTypeID(trustSettings) == CFArrayGetTypeID(), errOut);
-
-               /* Now validate the usageConstraint array contents */
-               require(validateTrustSettingsArray(trustSettings), errOut);
-
-               /* Add the trustSettings to the dict. */
-               CFDictionaryAddValue(newDict, kTrustRecordTrustSettings, trustSettings);
-       }
-
-       CFDictionaryAddValue(tlc->dict, newKey, newDict);
-       CFRelease(newKey);
-       CFRelease(newDict);
-
-       return;
-errOut:
-       CFReleaseSafe(newKey);
-       CFReleaseSafe(newDict);
-       tlc->status = errSecInvalidTrustSettings;
-}
-
-static OSStatus SecTrustSettingsValidate(SecTrustSettingsRef ts, bool trim) {
-       /* top level dictionary */
-       require(ts->_propList, errOut);
-       require(CFGetTypeID(ts->_propList) == CFDictionaryGetTypeID(), errOut);
-
-       /* That dictionary has two entries */
-       CFNumberRef cfVers = (CFNumberRef)CFDictionaryGetValue(ts->_propList, kTrustRecordVersion);
-       require(cfVers != NULL && CFGetTypeID(cfVers) == CFNumberGetTypeID(), errOut);
-       require(CFNumberGetValue(cfVers, kCFNumberSInt32Type, &ts->_dictVersion), errOut);
-       require((ts->_dictVersion <= kSecTrustRecordVersionCurrent) &&
-               (ts->_dictVersion != kSecTrustRecordVersionInvalid), errOut);
-
-       /* other backwards-compatibility handling done later, if needed, per _dictVersion */
-
-       require(ts->_trustDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
-               &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut);
-
-       CFDictionaryRef trustList = (CFDictionaryRef)CFDictionaryGetValue(
-               ts->_propList, kTrustRecordTrustList);
-       require(trustList != NULL &&
-               CFGetTypeID(trustList) == CFDictionaryGetTypeID(), errOut);
-
-       /* Convert the per-cert entries from on disk to in memory format. */
-       struct trustListContext context = {
-               ts->_trustDict, ts->_dictVersion, trim, errSecSuccess
-       };
-       CFDictionaryApplyFunction(trustList, trustListApplierFunction, &context);
-
-       if (trim) {
-               /* we don't need the top-level dictionary any more */
-               CFRelease(ts->_propList);
-               ts->_propList = NULL;
-       }
-
-       return context.status;
-
-errOut:
-       return errSecInvalidTrustSettings;
-}
-
-OSStatus SecTrustSettingsCreateFromExternal(SecTrustSettingsDomain domain,
-    CFDataRef external, SecTrustSettingsRef *ts) {
-    CFAllocatorRef allocator = kCFAllocatorDefault;
-    CFIndex size = sizeof(struct __SecTrustSettings);
-    SecTrustSettingsRef result;
-
-       require(result = (SecTrustSettingsRef)_CFRuntimeCreateInstance(allocator,
-               SecTrustSettingsGetTypeID(), size - sizeof(CFRuntimeBase), 0), errOut);
-
-       CFErrorRef error = NULL;
-       CFPropertyListRef plist = CFPropertyListCreateWithData(kCFAllocatorDefault,
-        external, kCFPropertyListImmutable, NULL, &error);
-       if (!plist) {
-               secwarning("SecTrustSettingsCreateFromExternal: %@", error);
-               CFReleaseSafe(error);
-        CFReleaseSafe(result);
-               goto errOut;
-       }
-
-       result->_propList = plist;
-       result->_trustDict = NULL;
-       SecTrustSettingsValidate(result, false);
-
-       *ts = result;
-
-       return errSecSuccess;
-
-errOut:
-    return errSecInvalidTrustSettings;
-}
-
-SecTrustSettingsRef SecTrustSettingsCreate(SecTrustSettingsDomain domain,
-    bool create, bool trim) {
-    CFAllocatorRef allocator = kCFAllocatorDefault;
-    CFIndex size = sizeof(struct __SecTrustSettings);
-    SecTrustSettingsRef result =
-               (SecTrustSettingsRef)_CFRuntimeCreateInstance(allocator,
-               SecTrustSettingsGetTypeID(), size - sizeof(CFRuntimeBase), 0);
-       if (!result)
-        return NULL;
-
-       //result->_data = NULL;
-
-    return result;
-}
-
-CFDataRef SecTrustSettingsCopyExternal(SecTrustSettingsRef ts) {
-       /* Transform the internal represantation of the trustSettings to an
-          external form. */
-       // @@@ SecTrustSettingsUpdatePropertyList(SecTrustSettingsRef ts);
-       CFDataRef xmlData;
-       verify(xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault,
-               ts->_propList));
-       return xmlData;
-}
-
-void SecTrustSettingsSet(SecCertificateRef certRef,
-    CFTypeRef trustSettingsDictOrArray) {
-}
-
-
-
-// MARK: -
-// MARK: SPI functions
-
-
-/*
- * Fundamental routine used by TP to ascertain status of one cert.
- *
- * Returns true in *foundMatchingEntry if a trust setting matching
- * specific constraints was found for the cert. Returns true in
- * *foundAnyEntry if any entry was found for the cert, even if it
- * did not match the specified constraints. The TP uses this to
- * optimize for the case where a cert is being evaluated for
- * one type of usage, and then later for another type. If
- * foundAnyEntry is false, the second evaluation need not occur.
- *
- * Returns the domain in which a setting was found in *foundDomain.
- *
- * Allowed errors applying to the specified cert evaluation
- * are returned in a mallocd array in *allowedErrors and must
- * be freed by caller.
- *
- * The design of the entire TrustSettings module is centered around
- * optimizing the performance of this routine (security concerns
- * aside, that is). It's why the per-cert dictionaries are stored
- * as a dictionary, keyed off of the cert hash. It's why TrustSettings
- * are cached in memory by tsGetGlobalTrustSettings(), and why those
- * cached TrustSettings objects are 'trimmed' of dictionary fields
- * which are not needed to verify a cert.
- *
- * The API functions which are used to manipulate Trust Settings
- * are called infrequently and need not be particularly fast since
- * they result in user interaction for authentication. Thus they do
- * not use cached TrustSettings as this function does.
- */
-OSStatus SecTrustSettingsEvaluateCertificate(
-       SecCertificateRef certificate,
-       SecPolicyRef policy,
-       SecTrustSettingsKeyUsage        keyUsage,                       /* optional */
-       bool                                            isSelfSignedCert,       /* for checking default setting */
-       /* RETURNED values */
-       SecTrustSettingsDomain          *foundDomain,
-       CFArrayRef                                      *allowedErrors,         /* RETURNED */
-       SecTrustSettingsResult          *resultType,            /* RETURNED */
-       bool                                            *foundMatchingEntry,/* RETURNED */
-       bool                                            *foundAnyEntry)         /* RETURNED */
-{
-#if 0
-       BEGIN_RCSAPI
-
-       StLock<Mutex>   _(sutCacheLock());
-
-       TS_REQUIRED(certHashStr)
-       TS_REQUIRED(foundDomain)
-       TS_REQUIRED(allowedErrors)
-       TS_REQUIRED(numAllowedErrors)
-       TS_REQUIRED(resultType)
-       TS_REQUIRED(foundMatchingEntry)
-       TS_REQUIRED(foundMatchingEntry)
-
-       /* ensure a NULL_terminated string */
-       auto_array<char> polStr;
-       if(policyString != NULL) {
-               polStr.allocate(policyStringLen + 1);
-               memmove(polStr.get(), policyString, policyStringLen);
-               if(policyString[policyStringLen - 1] != '\0') {
-                       (polStr.get())[policyStringLen] = '\0';
-               }
-       }
-
-       /* initial condition - this can grow if we inspect multiple TrustSettings */
-       *allowedErrors = NULL;
-       *numAllowedErrors = 0;
-
-       /*
-        * This loop relies on the ordering of the SecTrustSettingsDomain enum:
-        * search user first, then admin, then system.
-        */
-       assert(kSecTrustSettingsDomainAdmin == (kSecTrustSettingsDomainUser + 1));
-       assert(kSecTrustSettingsDomainSystem == (kSecTrustSettingsDomainAdmin + 1));
-       bool foundAny = false;
-       for(unsigned domain=kSecTrustSettingsDomainUser;
-                            domain<=kSecTrustSettingsDomainSystem;
-                                domain++) {
-               TrustSettings *ts = tsGetGlobalTrustSettings(domain);
-               if(ts == NULL) {
-                       continue;
-               }
-
-               /* validate cert returns true if matching entry was found */
-               bool foundAnyHere = false;
-               bool found = ts->evaluateCert(certHashStr, policyOID,
-                       polStr.get(), keyUsage, isRootCert,
-                       allowedErrors, numAllowedErrors, resultType, &foundAnyHere);
-
-               if(found) {
-                       /*
-                        * Note this, even though we may overwrite it later if this
-                        * is an Unspecified entry and we find a definitive entry
-                        * later
-                        */
-                       *foundDomain = domain;
-               }
-               if(found && (*resultType != kSecTrustSettingsResultUnspecified)) {
-                       trustSettingsDbg("SecTrustSettingsEvaluateCert: found in domain %d", domain);
-                       *foundAnyEntry = true;
-                       *foundMatchingEntry = true;
-                       return errSecSuccess;
-               }
-               foundAny |= foundAnyHere;
-       }
-       trustSettingsDbg("SecTrustSettingsEvaluateCert: NOT FOUND");
-       *foundAnyEntry = foundAny;
-       *foundMatchingEntry = false;
-       return errSecSuccess;
-       END_RCSAPI
-#endif
-       return errSecSuccess;
-}
-
-/*
- * Add a cert's TrustSettings to a non-persistent TrustSettings record.
- * No locking or cache flushing here; it's all local to the TrustSettings
- * we construct here.
- */
-#if SECTRUST_OSX
-// There is already a SecTrustSettingsSetTrustSettingsExternal API on OS X
-// with different arguments, so give this one an _ios extension.
-OSStatus SecTrustSettingsSetTrustSettingsExternal_ios(
-#else
-OSStatus SecTrustSettingsSetTrustSettingsExternal(
-#endif
-       CFDataRef                       settingsIn,                                     /* optional */
-       SecCertificateRef       certRef,                                        /* optional */
-       CFTypeRef                       trustSettingsDictOrArray,       /* optional */
-       CFDataRef                       *settingsOut)                           /* RETURNED */
-{
-    SecTrustSettingsRef ts = NULL;
-    OSStatus status;
-
-    require_noerr(status = SecTrustSettingsCreateFromExternal(
-        kSecTrustSettingsDomainMemory, settingsIn, &ts), errOut);
-    SecTrustSettingsSet(certRef, trustSettingsDictOrArray);
-    *settingsOut = SecTrustSettingsCopyExternal(ts);
-
-errOut:
-    CFReleaseSafe(ts);
-       return status;
-}