+++ /dev/null
-/*
- * Copyright (c) 2002-2004,2011-2012,2014 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@
- */
-
-/*
-* TrustRevocation.cpp - private revocation policy manipulation
-*/
-
-#include <security_keychain/Trust.h>
-#include <security_utilities/cfutilities.h>
-#include <security_utilities/simpleprefs.h>
-#include <CoreFoundation/CFData.h>
-#include "SecBridge.h"
-#include <Security/cssmapplePriv.h>
-#include <Security/oidsalg.h>
-
-/*
- * These may go into an SPI header for the SecTrust object.
- */
-typedef enum {
- /* this revocation policy disabled */
- kSecDisabled,
- /* try, but tolerate inability to complete */
- kSecBestAttempt,
- /* require successful revocation check if certificate indicates
- * the policy is supported */
- kSecRequireIfPresentInCertificate,
- /* require for every cert */
- kSecRequireForAllCertificates
-} SecRevocationPolicyStyle;
-
-using namespace KeychainCore;
-
-/*
- * Given an app-specified array of Policies, determine if at least one of them
- * matches the given policy OID.
- */
-bool Trust::policySpecified(CFArrayRef policies, const CSSM_OID &inOid)
-{
- if(policies == NULL) {
- return false;
- }
- CFIndex numPolicies = CFArrayGetCount(policies);
- for(CFIndex dex=0; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
- SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- const CssmOid &oid = pol->oid();
- if(oid == CssmOid::overlay(inOid)) {
- return true;
- }
- }
- return false;
-}
-
-/*
- * Given an app-specified array of Policies, determine if at least one of them
- * is an explicit revocation policy.
- */
-bool Trust::revocationPolicySpecified(CFArrayRef policies)
-{
- if(policies == NULL) {
- return false;
- }
- CFIndex numPolicies = CFArrayGetCount(policies);
- for(CFIndex dex=0; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
- SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- const CssmOid &oid = pol->oid();
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
- return true;
- }
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
- return true;
- }
- }
- return false;
-}
-
-/*
- * Replace a unified revocation policy instance in the mPolicies array
- * with specific instances of the OCSP and/or CRL policies which the TP
- * module understands. Returns a (possibly) modified copy of the mPolicies
- * array, which the caller is responsible for releasing.
- */
-CFMutableArrayRef Trust::convertRevocationPolicy(
- uint32 &numAdded,
- Allocator &alloc)
-{
- numAdded = 0;
- if (!mPolicies) {
- return NULL;
- }
- CFIndex numPolicies = CFArrayGetCount(mPolicies);
- CFAllocatorRef allocator = CFGetAllocator(mPolicies);
- CFMutableArrayRef policies = CFArrayCreateMutableCopy(allocator, numPolicies, mPolicies);
- SecPolicyRef revPolicy = NULL;
- for(CFIndex dex=0; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
- SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- const CssmOid &oid = pol->oid();
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION)) {
- CFRetain(secPol);
- if (revPolicy)
- CFRelease(revPolicy);
- revPolicy = secPol;
- CFArrayRemoveValueAtIndex(policies, dex--);
- numPolicies--;
- }
- }
- if(!revPolicy) {
- CFRelease(policies);
- return NULL;
- }
-
- SecPointer<Policy> ocspPolicy;
- SecPointer<Policy> crlPolicy;
-
- // fetch policy value
- CFOptionFlags policyFlags = kSecRevocationUseAnyAvailableMethod;
- CSSM_DATA policyValue = { 0, NULL };
- try {
- policyValue = Policy::required(revPolicy)->value();
- }
- catch (...) {
- policyValue.Data = NULL;
- }
- if (policyValue.Data) {
- policyFlags = (CFOptionFlags) *((CFOptionFlags*)policyValue.Data);
- }
- if (mNetworkPolicy == useNetworkDisabled) {
- policyFlags = 0 | kSecRevocationNetworkAccessDisabled;
- }
- CFRelease(revPolicy); // all done with this policy reference
-
- if (policyFlags & kSecRevocationOCSPMethod) {
- /* cook up a new Policy object */
- ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP));
- CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
- if (policyFlags & kSecRevocationRequirePositiveResponse) {
- ocspFlags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
- }
- CSSM_APPLE_TP_OCSP_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
- opts.Flags = ocspFlags;
-
- /* Policy manages its own copy of this data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- ocspPolicy->value() = optData;
-
- /* Policies array retains the Policy object */
- CFArrayAppendValue(policies, ocspPolicy->handle(false));
- numAdded++;
- }
- if (policyFlags & kSecRevocationCRLMethod) {
- /* cook up a new Policy object */
- crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL));
- CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags = 0;
- if (policyFlags & kSecRevocationRequirePositiveResponse) {
- crlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
- }
- CSSM_APPLE_TP_CRL_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
- opts.CrlFlags = crlFlags;
-
- /* Policy manages its own copy of this data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- crlPolicy->value() = optData;
-
- /* Policies array retains the Policy object */
- CFArrayAppendValue(policies, crlPolicy->handle(false));
- numAdded++;
- }
- return policies;
-}
-
-static SecRevocationPolicyStyle parseRevStyle(CFStringRef val)
-{
- if(CFEqual(val, kSecRevocationOff)) {
- return kSecDisabled;
- }
- else if(CFEqual(val, kSecRevocationBestAttempt)) {
- return kSecBestAttempt;
- }
- else if(CFEqual(val, kSecRevocationRequireIfPresent)) {
- return kSecRequireIfPresentInCertificate;
- }
- else if(CFEqual(val, kSecRevocationRequireForAll)) {
- return kSecRequireForAllCertificates;
- }
- else {
- return kSecDisabled;
- }
-}
-
-CFDictionaryRef Trust::defaultRevocationSettings()
-{
- /*
- defaults read ~/Library/Preferences/com.apple.security.revocation
- {
- CRLStyle = BestAttempt;
- CRLSufficientPerCert = 1;
- OCSPStyle = BestAttempt;
- OCSPSufficientPerCert = 1;
- RevocationFirst = OCSP;
- }
- */
- const void *keys[] = {
- kSecRevocationCrlStyle,
- kSecRevocationCRLSufficientPerCert,
- kSecRevocationOcspStyle,
- kSecRevocationOCSPSufficientPerCert,
- kSecRevocationWhichFirst
- };
- const void *values[] = {
- kSecRevocationBestAttempt,
- kCFBooleanTrue,
- kSecRevocationBestAttempt,
- kCFBooleanTrue,
- kSecRevocationOcspFirst
- };
-
- return CFDictionaryCreate(kCFAllocatorDefault, keys,
- values, sizeof(keys) / sizeof(*keys),
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-}
-
-CFMutableArrayRef Trust::addPreferenceRevocationPolicies(
- bool ocspEnabledOnBestAttempt,
- bool crlEnabledOnBestAttempt,
- uint32 &numAdded,
- Allocator &alloc)
-{
- numAdded = 0;
-
- /* any per-user prefs? */
- Dictionary* pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
- if (pd)
- {
- if (!pd->dict()) {
- delete pd;
- pd = NULL;
- }
- }
-
- if(pd == NULL)
- {
- pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true);
- if (!pd->dict()) {
- delete pd;
- pd = NULL;
- }
- }
-
- if(pd == NULL)
- {
- CFDictionaryRef tempDict = defaultRevocationSettings();
- if (tempDict == NULL)
- return NULL;
-
- pd = new Dictionary(tempDict);
- CFRelease(tempDict);
- }
-
- auto_ptr<Dictionary> prefsDict(pd);
-
- bool doOcsp = false;
- bool doCrl = false;
- CFStringRef val;
- SecRevocationPolicyStyle ocspStyle = kSecBestAttempt;
- SecRevocationPolicyStyle crlStyle = kSecBestAttempt;
- SecPointer<Policy> ocspPolicy;
- SecPointer<Policy> crlPolicy;
-
- /* Are any revocation policies enabled? */
- val = prefsDict->getStringValue(kSecRevocationOcspStyle);
- if(val != NULL) {
- ocspStyle = parseRevStyle(val);
- if(ocspStyle != kSecDisabled) {
- doOcsp = true;
- }
- if(ocspStyle == kSecBestAttempt) {
- doOcsp = ocspEnabledOnBestAttempt;
- }
- }
- val = prefsDict->getStringValue(kSecRevocationCrlStyle);
- if(val != NULL) {
- crlStyle = parseRevStyle(val);
- if(crlStyle != kSecDisabled) {
- doCrl = true;
- }
- if(crlStyle == kSecBestAttempt) {
- doCrl = crlEnabledOnBestAttempt;
- }
- }
-
- if(!doCrl && !doOcsp) {
- return NULL;
- }
-
- /* which policy first? */
- bool ocspFirst = true; // default if both present
- if(doCrl && doOcsp) {
- val = prefsDict->getStringValue(kSecRevocationWhichFirst);
- if((val != NULL) && CFEqual(val, kSecRevocationCrlFirst)) {
- ocspFirst = false;
- }
- }
-
- /* Must have at least one caller-specified policy
- * (if they didn't specify any, it's a no-op evaluation, and if they wanted
- * revocation checking only, that policy would already be in mPolicies) */
- if (!mPolicies || !CFArrayGetCount(mPolicies))
- return NULL;
-
- /* We're adding something to mPolicies, so make a copy we can work with */
- CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies);
- if(policies == NULL) {
- throw std::bad_alloc();
- }
-
- if(doOcsp) {
- /* Cook up a new Policy object */
- ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP));
- CSSM_APPLE_TP_OCSP_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
-
- /* Now fill in the OCSP-related blanks */
- switch(ocspStyle) {
- case kSecDisabled:
- assert(0);
- break;
- case kSecBestAttempt:
- /* default, nothing to set */
- break;
- case kSecRequireIfPresentInCertificate:
- opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
- break;
- case kSecRequireForAllCertificates:
- opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT;
- break;
- }
-
- if(prefsDict->getBoolValue(kSecRevocationOCSPSufficientPerCert)) {
- opts.Flags |= CSSM_TP_ACTION_OCSP_SUFFICIENT;
- }
-
- val = prefsDict->getStringValue(kSecOCSPLocalResponder);
- if(val != NULL) {
- CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
- val, kCFStringEncodingUTF8, 0);
- CFIndex len = CFDataGetLength(cfData);
- opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
- opts.LocalResponder->Data = (uint8 *)alloc.malloc(len);
- opts.LocalResponder->Length = len;
- memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len);
- CFRelease(cfData);
- }
-
- /* Policy manages its own copy of this data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- ocspPolicy->value() = optData;
- numAdded++;
- }
-
- if(doCrl) {
- /* Cook up a new Policy object */
- crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL));
- CSSM_APPLE_TP_CRL_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
-
- /* Now fill in the CRL-related blanks */
- opts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; // default true
- switch(crlStyle) {
- case kSecDisabled:
- assert(0);
- break;
- case kSecBestAttempt:
- /* default, nothing to set */
- break;
- case kSecRequireIfPresentInCertificate:
- opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
- break;
- case kSecRequireForAllCertificates:
- opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT;
- break;
- }
- if(prefsDict->getBoolValue(kSecRevocationCRLSufficientPerCert)) {
- opts.CrlFlags |= CSSM_TP_ACTION_CRL_SUFFICIENT;
- }
-
- /* Policy manages its own copy of this data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- crlPolicy->value() = optData;
- numAdded++;
- }
-
- /* append in order */
- if(doOcsp) {
- if(doCrl) {
- if(ocspFirst) {
- /* these SecCFObject go away when the policies array does */
- CFArrayAppendValue(policies, ocspPolicy->handle(false));
- CFArrayAppendValue(policies, crlPolicy->handle(false));
- }
- else {
- CFArrayAppendValue(policies, crlPolicy->handle(false));
- CFArrayAppendValue(policies, ocspPolicy->handle(false));
- }
- }
- else {
- CFArrayAppendValue(policies, ocspPolicy->handle(false));
- }
-
- }
- else if(doCrl) {
- CFArrayAppendValue(policies, crlPolicy->handle(false));
- }
- return policies;
-}
-
-/*
- * Called when we created the last numAdded Policies in the specified Policy array
- * (only frees the policy data associated with the extra policies that we inserted;
- * this does not free the policies array itself.)
- */
-void Trust::freeAddedRevocationPolicyData(
- CFArrayRef policies,
- uint32 numAdded,
- Allocator &alloc)
-{
- uint32 numPolicies = (uint32)CFArrayGetCount(policies);
- if(numPolicies < numAdded) {
- /* should never happen - throw? */
- assert(0);
- return;
- }
- for(unsigned dex=numPolicies-numAdded; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
- //SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- Policy *pol = Policy::required(secPol);
- const CssmOid &oid = pol->oid(); // required
- const CssmData &optData = pol->value(); // optional
-
- if(optData.Data) {
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
- /* currently no CRL-specific policy data */
- }
- else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
- CSSM_APPLE_TP_OCSP_OPTIONS *opts = (CSSM_APPLE_TP_OCSP_OPTIONS *)optData.Data;
- if(opts->LocalResponder != NULL) {
- if(opts->LocalResponder->Data != NULL) {
- alloc.free(opts->LocalResponder->Data);
- }
- alloc.free(opts->LocalResponder);
- }
- }
- // managed by Policy alloc.free(optData.Data);
- }
- }
-}
-
-/*
- * Comparator function to correctly order revocation policies.
- */
-static CFComparisonResult compareRevocationPolicies(
- const void *policy1,
- const void *policy2,
- void *context)
-{
- SecPointer<Policy> pol1 = Policy::required(SecPolicyRef(policy1));
- SecPointer<Policy> pol2 = Policy::required(SecPolicyRef(policy2));
- const CssmOid &oid1 = pol1->oid();
- const CssmOid &oid2 = pol2->oid();
- if(oid1 == oid2) {
- return kCFCompareEqualTo;
- }
- bool ocspFirst = true;
- if(context != NULL && CFEqual((CFBooleanRef)context, kCFBooleanFalse)) {
- ocspFirst = false;
- }
- const CssmOid lastRevocationOid = (ocspFirst) ?
- CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL) :
- CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP);
- const CssmOid firstRevocationOid = (ocspFirst) ?
- CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP) :
- CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL);
- if(oid1 == lastRevocationOid) {
- /* should be ordered last, after all other policies */
- return kCFCompareGreaterThan;
- }
- if(oid1 == firstRevocationOid) {
- /* should be ordered after any policy except lastRevocationOid */
- if(oid2 == lastRevocationOid) {
- return kCFCompareLessThan;
- }
- return kCFCompareGreaterThan;
- }
- /* normal policy in first position, anything else in second position */
- return kCFCompareLessThan;
-}
-
-/*
- * This method reorders any revocation policies which may be present
- * in the provided array so they are at the end and evaluated last.
- */
-void Trust::orderRevocationPolicies(
- CFMutableArrayRef policies)
-{
- if(!policies || CFGetTypeID(policies) != CFArrayGetTypeID()) {
- return;
- }
- /* check revocation prefs to determine which policy goes first */
- CFBooleanRef ocspFirst = kCFBooleanTrue;
- Dictionary* pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
- if (pd) {
- if (!pd->dict()) {
- delete pd;
- } else {
- auto_ptr<Dictionary> prefsDict(pd);
- CFStringRef val = prefsDict->getStringValue(kSecRevocationWhichFirst);
- if((val != NULL) && CFEqual(val, kSecRevocationCrlFirst)) {
- ocspFirst = kCFBooleanFalse;
- }
- }
- }
-#if POLICIES_DEBUG
- CFShow(policies); // before sort
- CFArraySortValues(policies, CFRangeMake(0, CFArrayGetCount(policies)), compareRevocationPolicies, (void*)ocspFirst);
- CFShow(policies); // after sort, to see what changed
- // check that policy order is what we expect
- CFIndex numPolicies = CFArrayGetCount(policies);
- for(CFIndex dex=0; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
- SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- const CssmOid &oid = pol->oid();
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
- CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = OCSP"), dex);
- CFShow(s);
- CFRelease(s);
- }
- else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
- CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = CRL"), dex);
- CFShow(s);
- CFRelease(s);
- }
- else {
- CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = normal"), dex);
- CFShow(s);
- CFRelease(s);
- }
- }
-#else
- CFArraySortValues(policies, CFRangeMake(0, CFArrayGetCount(policies)), compareRevocationPolicies, (void*)ocspFirst);
-#endif
-}
-
-/*
- * This method returns a copy of the mPolicies array which ensures that
- * revocation checking (preferably OCSP, otherwise CRL) will be attempted.
- *
- * If OCSP is already in the mPolicies array, this makes sure the
- * CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT and CSSM_TP_ACTION_OCSP_SUFFICIENT
- * flags are set. If it's not already in the array, a new policy object is added.
- *
- * If CRL is already in the mPolicies array, this makes sure the
- * CSSM_TP_ACTION_FETCH_CRL_FROM_NET and CSSM_TP_ACTION_CRL_SUFFICIENT flags are
- * set. If it's not already in the array, a new policy object is added.
- *
- * Caller is responsible for releasing the returned policies array.
- */
-CFMutableArrayRef Trust::forceRevocationPolicies(
- bool ocspEnabled,
- bool crlEnabled,
- uint32 &numAdded,
- Allocator &alloc,
- bool requirePerCert)
-{
- SecPointer<Policy> ocspPolicy;
- SecPointer<Policy> crlPolicy;
- CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags;
- CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags;
- bool hasOcspPolicy = false;
- bool hasCrlPolicy = false;
- numAdded = 0;
-
- ocspFlags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
- crlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET | CSSM_TP_ACTION_CRL_SUFFICIENT;
- if (requirePerCert) {
- ocspFlags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
- crlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
- }
-
- CFIndex numPolicies = (mPolicies) ? CFArrayGetCount(mPolicies) : 0;
- for(CFIndex dex=0; dex<numPolicies; dex++) {
- SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(mPolicies, dex);
- SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
- const CssmOid &oid = pol->oid();
- const CssmData &optData = pol->value();
- if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
- // make sure OCSP options are set correctly
- CSSM_APPLE_TP_OCSP_OPTIONS *opts = (CSSM_APPLE_TP_OCSP_OPTIONS *)optData.Data;
- if (opts) {
- opts->Flags |= ocspFlags;
- } else {
- CSSM_APPLE_TP_OCSP_OPTIONS newOpts;
- memset(&newOpts, 0, sizeof(newOpts));
- newOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
- newOpts.Flags = ocspFlags;
- CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts};
- pol->value() = optData;
- }
- hasOcspPolicy = true;
- }
- else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
- // make sure CRL options are set correctly
- CSSM_APPLE_TP_CRL_OPTIONS *opts = (CSSM_APPLE_TP_CRL_OPTIONS *)optData.Data;
- if (opts) {
- opts->CrlFlags |= crlFlags;
- } else {
- CSSM_APPLE_TP_CRL_OPTIONS newOpts;
- memset(&newOpts, 0, sizeof(newOpts));
- newOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
- newOpts.CrlFlags = crlFlags;
- CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts};
- pol->value() = optData;
- }
- hasCrlPolicy = true;
- }
- }
-
- /* We're potentially adding something to mPolicies, so make a copy we can work with */
- CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies);
- if(policies == NULL) {
- throw std::bad_alloc();
- }
-
- if(!hasOcspPolicy && ocspEnabled) {
- /* Cook up a new Policy object */
- ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP));
- CSSM_APPLE_TP_OCSP_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
- opts.Flags = ocspFlags;
-
- /* Check prefs dict for local responder info */
- Dictionary *prefsDict = NULL;
- try { /* per-user prefs */
- prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
- if (!prefsDict->dict()) {
- delete prefsDict;
- prefsDict = NULL;
- }
- }
- catch(...) {}
- if(prefsDict == NULL) {
- try { /* system prefs */
- prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true);
- if (!prefsDict->dict()) {
- delete prefsDict;
- prefsDict = NULL;
- }
- }
- catch(...) {}
- }
- if(prefsDict != NULL) {
- CFStringRef val = prefsDict->getStringValue(kSecOCSPLocalResponder);
- if(val != NULL) {
- CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
- val, kCFStringEncodingUTF8, 0);
- CFIndex len = CFDataGetLength(cfData);
- opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
- opts.LocalResponder->Data = (uint8 *)alloc.malloc(len);
- opts.LocalResponder->Length = len;
- memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len);
- CFRelease(cfData);
- }
- }
-
- /* Policy manages its own copy of the options data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- ocspPolicy->value() = optData;
-
- /* Policies array retains the Policy object */
- CFArrayAppendValue(policies, ocspPolicy->handle(false));
- numAdded++;
-
- if(prefsDict != NULL)
- delete prefsDict;
- }
-
- if(!hasCrlPolicy && crlEnabled) {
- /* Cook up a new Policy object */
- crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL));
- CSSM_APPLE_TP_CRL_OPTIONS opts;
- memset(&opts, 0, sizeof(opts));
- opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
- opts.CrlFlags = crlFlags;
-
- /* Policy manages its own copy of this data */
- CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
- crlPolicy->value() = optData;
-
- /* Policies array retains the Policy object */
- CFArrayAppendValue(policies, crlPolicy->handle(false));
- numAdded++;
- }
-
- return policies;
-}