/ OSX / libsecurity_keychain / lib / SecPolicy.cpp
SecPolicy.cpp
  1  
  2  /*
  3   * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved.
  4   *
  5   * @APPLE_LICENSE_HEADER_START@
  6   *
  7   * This file contains Original Code and/or Modifications of Original Code
  8   * as defined in and that are subject to the Apple Public Source License
  9   * Version 2.0 (the 'License'). You may not use this file except in
 10   * compliance with the License. Please obtain a copy of the License at
 11   * http://www.opensource.apple.com/apsl/ and read it before using this
 12   * file.
 13   *
 14   * The Original Code and all software distributed under the License are
 15   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 16   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 17   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 18   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 19   * Please see the License for the specific language governing rights and
 20   * limitations under the License.
 21   *
 22   * @APPLE_LICENSE_HEADER_END@
 23   */
 24  
 25  #include <CoreFoundation/CFString.h>
 26  #include <CoreFoundation/CFNumber.h>
 27  #include <CoreFoundation/CFArray.h>
 28  #include <Security/SecItem.h>
 29  #include <Security/SecPolicy.h>
 30  #include <Security/SecPolicyPriv.h>
 31  #include <Security/SecCertificate.h>
 32  #include <Security/SecCertificatePriv.h>
 33  #include <security_keychain/Policies.h>
 34  #include <security_keychain/PolicyCursor.h>
 35  #include "SecBridge.h"
 36  #include "utilities/SecCFRelease.h"
 37  #include <syslog.h>
 38  
 39  
 40  // String constant declarations
 41  
 42  #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
 43  
 44  /* Some of these aren't defined in SecPolicy.c, but used here. */
 45  SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12");
 46  
 47  // Private functions
 48  
 49  extern "C" {
 50  CFDictionaryRef SecPolicyGetOptions(SecPolicyRef policy);
 51  void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value);
 52  }
 53  
 54  // String to CSSM_OID mapping
 55  
 56  struct oidmap_entry_s {
 57  		const CFTypeRef oidstr;
 58  		const SecAsn1Oid *oidptr;
 59  };
 60  typedef struct oidmap_entry_s oidmap_entry_t;
 61  
 62  // policies enumerated by SecPolicySearch (PolicyCursor.cpp)
 63  /*
 64  	static_cast<const CssmOid *>(&CSSMOID_APPLE_ISIGN), // no longer supported
 65  	static_cast<const CssmOid *>(&CSSMOID_APPLE_X509_BASIC),
 66  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_SSL),
 67  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_SMIME),
 68  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_EAP),
 69  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_SW_UPDATE_SIGNING),
 70  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_IP_SEC),
 71  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_ICHAT), // no longer supported
 72  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_RESOURCE_SIGN),
 73  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_PKINIT_CLIENT),
 74  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_PKINIT_SERVER),
 75  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_CODE_SIGNING),
 76  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_PACKAGE_SIGNING),
 77  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_REVOCATION_CRL),
 78  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_REVOCATION_OCSP),
 79  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT),
 80  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_APPLEID_SHARING),
 81  	static_cast<const CssmOid *>(&CSSMOID_APPLE_TP_TIMESTAMPING),
 82  */
 83  
 84  static const size_t OIDMAP_LENGTH = 25;
 85  static const oidmap_entry_t* oidmap_f() {
 86      static const oidmap_entry_t oidmap_array[] = {
 87          { kSecPolicyAppleX509Basic, &CSSMOID_APPLE_X509_BASIC },
 88          { kSecPolicyAppleSSL, &CSSMOID_APPLE_TP_SSL },
 89          { kSecPolicyAppleSMIME, &CSSMOID_APPLE_TP_SMIME },
 90          { kSecPolicyAppleEAP, &CSSMOID_APPLE_TP_EAP },
 91          { kSecPolicyAppleSWUpdateSigning, &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING },
 92          { kSecPolicyAppleIPsec, &CSSMOID_APPLE_TP_IP_SEC },
 93          { kSecPolicyAppleiChat, &CSSMOID_APPLE_TP_ICHAT },
 94          { kSecPolicyApplePKINITClient, &CSSMOID_APPLE_TP_PKINIT_CLIENT },
 95          { kSecPolicyApplePKINITServer, &CSSMOID_APPLE_TP_PKINIT_SERVER },
 96          { kSecPolicyAppleCodeSigning, &CSSMOID_APPLE_TP_CODE_SIGNING },
 97          { kSecPolicyApplePackageSigning, &CSSMOID_APPLE_TP_PACKAGE_SIGNING },
 98          { kSecPolicyAppleIDValidation, &CSSMOID_APPLE_TP_APPLEID_SHARING },
 99          { kSecPolicyMacAppStoreReceipt, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT },
100          { kSecPolicyAppleTimeStamping, &CSSMOID_APPLE_TP_TIMESTAMPING },
101          { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION },
102          { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION_OCSP },
103          { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION_CRL },
104          { kSecPolicyApplePassbookSigning, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING },
105          { kSecPolicyAppleMobileStore, &CSSMOID_APPLE_TP_MOBILE_STORE },
106          { kSecPolicyAppleEscrowService, &CSSMOID_APPLE_TP_ESCROW_SERVICE },
107          { kSecPolicyAppleProfileSigner, &CSSMOID_APPLE_TP_PROFILE_SIGNING },
108          { kSecPolicyAppleQAProfileSigner, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING },
109          { kSecPolicyAppleTestMobileStore, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE },
110          { kSecPolicyApplePCSEscrowService, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE },
111          { kSecPolicyAppleOSXProvisioningProfileSigning, &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING },
112      };
113      static_assert(OIDMAP_LENGTH == (sizeof(oidmap_array)/sizeof(oidmap_entry_t)), "OIDMAP_LENGTH is incorrect; must match oidmap_array");
114  
115      return oidmap_array;
116  };
117  
118  static const size_t OIDMAP_PRIV_LENGTH = 23;
119  static const oidmap_entry_t* oidmap_priv_f() {
120      static const oidmap_entry_t oidmap_priv_array[] = {
121          { CFSTR("basicX509"), &CSSMOID_APPLE_X509_BASIC },
122          { CFSTR("sslServer"), &CSSMOID_APPLE_TP_SSL },
123          { CFSTR("sslClient"), &CSSMOID_APPLE_TP_SSL },
124          { CFSTR("SMIME"), &CSSMOID_APPLE_TP_SMIME },
125          { CFSTR("eapServer"), &CSSMOID_APPLE_TP_EAP },
126          { CFSTR("eapClient"), &CSSMOID_APPLE_TP_EAP },
127          { CFSTR("AppleSWUpdateSigning"), &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING },
128          { CFSTR("ipsecServer"), &CSSMOID_APPLE_TP_IP_SEC },
129          { CFSTR("ipsecClient"), &CSSMOID_APPLE_TP_IP_SEC },
130          { CFSTR("CodeSigning"), &CSSMOID_APPLE_TP_CODE_SIGNING },
131          { CFSTR("PackageSigning"), &CSSMOID_APPLE_TP_PACKAGE_SIGNING },
132          { CFSTR("AppleIDAuthority"), &CSSMOID_APPLE_TP_APPLEID_SHARING },
133          { CFSTR("MacAppStoreReceipt"), &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT },
134          { CFSTR("AppleTimeStamping"), &CSSMOID_APPLE_TP_TIMESTAMPING },
135          { CFSTR("revocation"), &CSSMOID_APPLE_TP_REVOCATION },
136          { CFSTR("ApplePassbook"), &CSSMOID_APPLE_TP_PASSBOOK_SIGNING },
137          { CFSTR("AppleMobileStore"), &CSSMOID_APPLE_TP_MOBILE_STORE },
138          { CFSTR("AppleEscrowService"), &CSSMOID_APPLE_TP_ESCROW_SERVICE },
139          { CFSTR("AppleProfileSigner"), &CSSMOID_APPLE_TP_PROFILE_SIGNING },
140          { CFSTR("AppleQAProfileSigner"), &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING },
141          { CFSTR("AppleTestMobileStore"), &CSSMOID_APPLE_TP_TEST_MOBILE_STORE },
142          { CFSTR("ApplePCSEscrowService"), &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE },
143          { CFSTR("AppleOSXProvisioningProfileSigning"), &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING },
144      };
145      static_assert(OIDMAP_PRIV_LENGTH == (sizeof(oidmap_priv_array)/sizeof(oidmap_entry_t)), "OIDMAP_PRIV_LENGTH is incorrect; must match oidmap_priv_array");
146  
147      return oidmap_priv_array;
148  }
149  
150  //
151  // Sec API bridge functions
152  //
153  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
154  OSStatus
155  SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID* oid)
156  {
157  	/* bridge to support old functionality */
158  	if (!policyRef) {
159  		return errSecParam;
160  	}
161  	CFStringRef oidStr = (CFStringRef) SecPolicyGetOidString(policyRef);
162  	if (!oidStr || !oid) {
163  		return errSecParam; // bad policy ref?
164  	}
165  	CSSM_OID *oidptr = NULL;
166      unsigned int i;
167  	for (i=0; i<OIDMAP_LENGTH; i++) {
168  		CFStringRef str = (CFStringRef) oidmap_f()[i].oidstr;
169  		if (CFStringCompare(str, oidStr, 0) == kCFCompareEqualTo) {
170  			oidptr = (CSSM_OID*)oidmap_f()[i].oidptr;
171  			break;
172  		}
173  	}
174  	if (!oidptr) {
175  		// Check private iOS policy names.
176  
177  		for (i=0; i<OIDMAP_PRIV_LENGTH; i++) {
178  			CFStringRef str = (CFStringRef) oidmap_priv_f()[i].oidstr;
179  			if (CFStringCompare(str, oidStr, 0) == kCFCompareEqualTo) {
180  				oidptr = (CSSM_OID*)oidmap_priv_f()[i].oidptr;
181  				break;
182  			}
183  		}
184  	}
185  	if (oidptr) {
186  		oid->Data = oidptr->Data;
187  		oid->Length = oidptr->Length;
188  		return errSecSuccess;
189  	}
190      CFShow(oidStr);
191  	syslog(LOG_ERR, "WARNING: SecPolicyGetOID failed to return an OID. This function was deprecated in 10.7. Please use SecPolicyCopyProperties instead.");
192  	return errSecServiceNotAvailable;
193  }
194  
195  // TODO: use a version of this function from a utility library
196  static CSSM_BOOL compareOids(
197  	const CSSM_OID *oid1,
198  	const CSSM_OID *oid2)
199  {
200  	if((oid1 == NULL) || (oid2 == NULL)) {
201  		return CSSM_FALSE;
202  	}
203  	if(oid1->Length != oid2->Length) {
204  		return CSSM_FALSE;
205  	}
206  	if(memcmp(oid1->Data, oid2->Data, oid1->Length)) {
207  		return CSSM_FALSE;
208  	}
209  	else {
210  		return CSSM_TRUE;
211  	}
212  }
213  
214  /* OS X only: */
215  CFStringRef SecPolicyGetStringForOID(CSSM_OID* oid)
216  {
217  	if (!oid) {
218  		return NULL;
219  	}
220  	// given a CSSM_OID pointer, return corresponding string in oidmap
221      unsigned int i;
222  	for (i=0; i<OIDMAP_LENGTH; i++) {
223  		CSSM_OID* oidptr = (CSSM_OID*)oidmap_f()[i].oidptr;
224  		if (compareOids(oid, oidptr)) {
225  			return (CFStringRef) oidmap_f()[i].oidstr;
226  		}
227  	}
228  	return NULL;
229  }
230  
231  static bool SecPolicyGetCSSMDataValueForString(SecPolicyRef policyRef, CFStringRef stringRef, CSSM_DATA* value)
232  {
233  	// Old API expects to vend a pointer and length for a policy value.
234  	// The API contract says this pointer is good for the life of the policy.
235  	// However, the new policy values are CF objects, and we need a separate
236  	// buffer to get their UTF8 bytes. This buffer needs to be released when
237  	// the policy object is released.
238  
239  	CFDataRef data = NULL;
240  	CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef), kCFStringEncodingUTF8) + 1;
241  	char* buf = (char*) malloc(maxLength);
242  	if (!buf) {
243  		return false;
244  	}
245  	if (CFStringGetCString(stringRef, buf, (CFIndex)maxLength, kCFStringEncodingUTF8)) {
246  		CFIndex length = strlen(buf);
247  		data = CFDataCreate(NULL, (const UInt8 *)buf, length);
248  	}
249  	free(buf);
250  	if (value) {
251  		value->Data = (uint8*)((data) ? CFDataGetBytePtr(data) : NULL);
252  		value->Length = (CSSM_SIZE)((data) ? CFDataGetLength(data) : 0);
253  	}
254  	if (data) {
255  		// stash this in a place where it will be released when the policy is destroyed
256  		if (policyRef) {
257  			SecPolicySetOptionsValue(policyRef, CFSTR("policy_data"), data);
258  		}
259  		else {
260  			syslog(LOG_ERR, "WARNING: policy dictionary not found to store returned data; will leak!");
261  		}
262  	}
263      CFReleaseNull(data);
264  	return true;
265  }
266  
267  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
268  OSStatus
269  SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA* value)
270  {
271  	/* bridge to support old functionality */
272  #if SECTRUST_DEPRECATION_WARNINGS
273      syslog(LOG_ERR, "WARNING: SecPolicyGetValue was deprecated in 10.7. Please use SecPolicyCopyProperties instead.");
274  #endif
275      if (!(policyRef && value)) {
276  		return errSecParam;
277  	}
278  	CFDictionaryRef options = SecPolicyGetOptions(policyRef);
279  	if (!(options && (CFDictionaryGetTypeID() == CFGetTypeID(options)))) {
280  		return errSecParam;
281  	}
282  	CFTypeRef name = NULL;
283  	do {
284  		if (CFDictionaryGetValueIfPresent(options, CFSTR("SSLHostname") /*kSecPolicyCheckSSLHostname*/,
285  			(const void **)&name) && name) {
286  			break;
287  		}
288  		if (CFDictionaryGetValueIfPresent(options, CFSTR("EAPTrustedServerNames") /*kSecPolicyCheckEAPTrustedServerNames*/,
289  			(const void **)&name) && name) {
290  			break;
291  		}
292  		if (CFDictionaryGetValueIfPresent(options, CFSTR("Email") /*kSecPolicyCheckEmail*/,
293  			(const void **)&name) && name) {
294  			break;
295  		}
296  	} while (0);
297  	if (name) {
298  		CFTypeID typeID = CFGetTypeID(name);
299  		if (CFArrayGetTypeID() == typeID) {
300  			name = (CFStringRef) CFArrayGetValueAtIndex((CFArrayRef)name, 0);
301  		}
302  		SecPolicyGetCSSMDataValueForString(policyRef, (CFStringRef)name, value);
303  	}
304  	else {
305  		value->Data = NULL;
306  		value->Length = 0;
307  	}
308  	return errSecSuccess;
309  }
310  
311  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
312  OSStatus
313  SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value)
314  {
315  	/* bridge to support old functionality */
316  #if SECTRUST_DEPRECATION_WARNINGS
317      syslog(LOG_ERR, "WARNING: SecPolicySetValue was deprecated in 10.7. Please use SecPolicySetProperties instead.");
318  #endif
319  	if (!(policyRef && value)) {
320  		return errSecParam;
321  	}
322  	OSStatus status = errSecSuccess;
323  	CFDataRef data = NULL;
324  	CFStringRef name = NULL;
325  	CFStringRef oid = (CFStringRef) SecPolicyGetOidString(policyRef);
326  	if (!oid) {
327  		syslog(LOG_ERR, "SecPolicySetValue: unknown policy OID");
328  		return errSecParam; // bad policy ref?
329  	}
330  	if (CFEqual(oid, CFSTR("sslServer") /*kSecPolicyOIDSSLServer*/) ||
331  		CFEqual(oid, CFSTR("sslClient") /*kSecPolicyOIDSSLClient*/) ||
332  		CFEqual(oid, CFSTR("ipsecServer") /*kSecPolicyOIDIPSecServer*/) ||
333  		CFEqual(oid, CFSTR("ipsecClient") /*kSecPolicyOIDIPSecClient*/) ||
334  		CFEqual(oid, kSecPolicyAppleSSL) ||
335  		CFEqual(oid, kSecPolicyAppleIPsec) ||
336  		CFEqual(oid, kSecPolicyAppleIDValidation)
337  		) {
338  		CSSM_APPLE_TP_SSL_OPTIONS *opts = (CSSM_APPLE_TP_SSL_OPTIONS *)value->Data;
339  		if (opts->Version == CSSM_APPLE_TP_SSL_OPTS_VERSION) {
340  			if (opts->ServerNameLen > 0) {
341  				data = CFDataCreate(NULL, (const UInt8 *)opts->ServerName, opts->ServerNameLen);
342  				name = (data) ? CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8) : NULL;
343  			}
344  		}
345  		if (name) {
346  			SecPolicySetOptionsValue(policyRef, CFSTR("SSLHostname") /*kSecPolicyCheckSSLHostname*/, name);
347  		}
348  		else {
349  			status = errSecParam;
350  		}
351  	}
352  	else if (CFEqual(oid, CFSTR("eapServer") /*kSecPolicyOIDEAPServer*/) ||
353  			 CFEqual(oid, CFSTR("eapClient") /*kSecPolicyOIDEAPClient*/) ||
354  			 CFEqual(oid, kSecPolicyAppleEAP)
355  		) {
356  		CSSM_APPLE_TP_SSL_OPTIONS *opts = (CSSM_APPLE_TP_SSL_OPTIONS *)value->Data;
357  		if (opts->Version == CSSM_APPLE_TP_SSL_OPTS_VERSION) {
358  			if (opts->ServerNameLen > 0) {
359  				data = CFDataCreate(NULL, (const UInt8 *)opts->ServerName, opts->ServerNameLen);
360  				name = (data) ? CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8) : NULL;
361  			}
362  		}
363  		if (name) {
364  			SecPolicySetOptionsValue(policyRef, CFSTR("EAPTrustedServerNames") /*kSecPolicyCheckEAPTrustedServerNames*/, name);
365  		}
366  		else {
367  			status = errSecParam;
368  		}
369  	}
370  	else if (CFEqual(oid, CFSTR("SMIME") /*kSecPolicyOIDSMIME*/) ||
371  			 CFEqual(oid, CFSTR("AppleShoebox") /*kSecPolicyOIDAppleShoebox*/) ||
372  			 CFEqual(oid, CFSTR("ApplePassbook") /*kSecPolicyOIDApplePassbook*/) ||
373  			 CFEqual(oid, kSecPolicyAppleSMIME) ||
374  			 CFEqual(oid, kSecPolicyApplePassbookSigning)
375  		) {
376  		CSSM_APPLE_TP_SMIME_OPTIONS *opts = (CSSM_APPLE_TP_SMIME_OPTIONS *)value->Data;
377  		if (opts->Version == CSSM_APPLE_TP_SMIME_OPTS_VERSION) {
378              if (opts->SenderEmailLen > 0) {
379  				data = CFDataCreate(NULL, (const UInt8 *)opts->SenderEmail, opts->SenderEmailLen);
380  				name = (data) ? CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8) : NULL;
381  			}
382  		}
383  		if (name) {
384  			SecPolicySetOptionsValue(policyRef, CFSTR("email") /*kSecPolicyCheckEmail*/, name);
385  		}
386  		else {
387  			status = errSecParam;
388  		}
389  	}
390  	else if (CFEqual(oid, CFSTR("revocation") /* kSecPolicyOIDRevocation */) ||
391  			 CFEqual(oid, kSecPolicyAppleRevocation)
392  		) {
393  		CSSM_APPLE_TP_CRL_OPTIONS *opts = (CSSM_APPLE_TP_CRL_OPTIONS *)value->Data;
394  		if (opts->Version == CSSM_APPLE_TP_CRL_OPTS_VERSION) {
395  			CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags = opts->CrlFlags;
396  			if ((crlFlags & CSSM_TP_ACTION_FETCH_CRL_FROM_NET) == 0) {
397  				/* disable network access */
398  				SecPolicySetOptionsValue(policyRef, CFSTR("NoNetworkAccess") /*kSecPolicyCheckNoNetworkAccess*/, kCFBooleanTrue);
399  			}
400  			if ((crlFlags & CSSM_TP_ACTION_CRL_SUFFICIENT) == 0) {
401  				/* if CRL method is not sufficient, must use OCSP */
402  				SecPolicySetOptionsValue(policyRef, CFSTR("Revocation") /*kSecPolicyCheckRevocation*/,
403                                           CFSTR("OCSP")/*kSecPolicyCheckRevocationOCSP*/);
404  			} else {
405  				/* either method is sufficient */
406  				SecPolicySetOptionsValue(policyRef, CFSTR("Revocation") /*kSecPolicyCheckRevocation*/,
407                                           CFSTR("AnyRevocationMethod") /*kSecPolicyCheckRevocationAny*/);
408  			}
409  
410  			if ((crlFlags & CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT) != 0) {
411  				/* require a response */
412  				SecPolicySetOptionsValue(policyRef,
413  										 CFSTR("RevocationResponseRequired") /*kSecPolicyCheckRevocationResponseRequired*/,
414  										 kCFBooleanTrue);
415  			}
416          }
417  	}
418  	else {
419  		syslog(LOG_ERR, "SecPolicySetValue: unrecognized policy OID");
420  		status = errSecParam;
421  	}
422  	if (data) { CFRelease(data); }
423  	if (name) { CFRelease(name); }
424  	return status;
425  }
426  
427  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
428  OSStatus
429  SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle)
430  {
431  	/* this function is unsupported in unified SecTrust */
432  #if SECTRUST_DEPRECATION_WARNINGS
433  	syslog(LOG_ERR, "WARNING: SecPolicyGetTPHandle was deprecated in 10.7, and does nothing in 10.11. Please stop using it.");
434  #endif
435  	return errSecServiceNotAvailable;
436  }
437  
438  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */
439  OSStatus
440  SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy)
441  {
442  	if (!policyOID || !policy) {
443  		return errSecParam;
444  	}
445  
446  	SecPolicySearchRef srchRef = NULL;
447  	OSStatus ortn;
448  
449  	ortn = SecPolicySearchCreate(certificateType, policyOID, NULL, &srchRef);
450  	if(ortn) {
451  		return ortn;
452  	}
453  	ortn = SecPolicySearchCopyNext(srchRef, policy);
454  	CFRelease(srchRef);
455  	return ortn;
456  }
457  
458  /* OS X only: convert a new-world SecPolicyRef to an old-world ItemImpl instance */
459  SecPolicyRef
460  SecPolicyCreateItemImplInstance(SecPolicyRef policy)
461  {
462  	if (!policy) {
463  		return NULL;
464  	}
465  	CSSM_OID oid;
466  	OSStatus status = SecPolicyGetOID(policy, &oid);
467  	if (status) {
468  		return NULL;
469  	}
470  	SecPolicyRef policyRef = NULL;
471  	CFDictionaryRef properties = SecPolicyCopyProperties(policy);
472  	try {
473  		SecPointer<Policy> policyObj;
474  		PolicyCursor::policy(&oid, policyObj);
475  		policyRef = policyObj->handle();
476  		Policy::required(policyRef)->setProperties(properties);
477  	}
478  	catch (...) {
479  		policyRef = NULL;
480  	}
481  	if (properties) {
482  		CFRelease(properties);
483  	}
484  	return policyRef;
485  }
486  
487  static SecPolicyRef
488  _SecPolicyCreateWithOID(CFTypeRef policyOID)
489  {
490  	// for now, we only accept the policy constants that are defined in SecPolicy.h
491  	CFStringRef oidStr = (CFStringRef)policyOID;
492  	CSSM_OID *oidPtr = NULL;
493  	SecPolicyRef policy = NULL;
494  	if (!oidStr) {
495  		return policy;
496  	}
497      unsigned int i;
498  	for (i=0; i<OIDMAP_LENGTH; i++) {
499  		CFStringRef str = (CFStringRef) oidmap_f()[i].oidstr;
500  		if (CFStringCompare(str, oidStr, 0) == kCFCompareEqualTo) {
501  			oidPtr = (CSSM_OID*)oidmap_f()[i].oidptr;
502  			break;
503  		}
504  	}
505  	if (CFEqual(oidStr, kSecPolicyAppleServerAuthentication)) {
506  		return SecPolicyCreateAppleSSLService(NULL);
507  	}
508  	if (oidPtr) {
509  		SecPolicySearchRef policySearch = NULL;
510  		OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, oidPtr, NULL, &policySearch);
511  		if (!status && policySearch) {
512  			status = SecPolicySearchCopyNext(policySearch, &policy);
513  			if (status != errSecSuccess) {
514  				policy = NULL;
515  			}
516  			CFRelease(policySearch);
517  		}
518  		if (!policy && CFEqual(policyOID, kSecPolicyAppleRevocation)) {
519  			policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
520  		}
521  	}
522  	return policy;
523  }
524  
525  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
526  SecPolicyRef
527  SecPolicyCreateWithOID(CFTypeRef policyOID)
528  {
529  	SecPolicyRef policy = _SecPolicyCreateWithOID(policyOID);
530  	if (!policy) {
531  		syslog(LOG_ERR, "WARNING: SecPolicyCreateWithOID was unable to return the requested policy. This function was deprecated in 10.9. Please use supported SecPolicy creation functions instead.");
532  	}
533  	return policy;
534  }
535  
536  /* OS X only: TBD */
537  #include <security_utilities/cfutilities.h>
538  /* New in 10.10 */
539  // Takes the "context" policies to extract the revocation and apply it to timeStamp.
540  CFArrayRef
541  SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray)
542  {
543      CFMutableArrayRef resultPolicyArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
544      if (!resultPolicyArray) {
545          return NULL;
546      }
547      SecPolicyRef tsPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleTimeStamping, NULL);
548      if (tsPolicy) {
549          CFArrayAppendValue(resultPolicyArray, tsPolicy);
550          CFReleaseNull(tsPolicy);
551      }
552  
553      /* check the provided argument for a revocation policy */
554      CFMutableArrayRef policies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
555      if (policies && policyOrArray) {
556          if (CFGetTypeID(policyOrArray) == SecPolicyGetTypeID()) {
557              CFArrayAppendValue(policies, policyOrArray);
558          } else if (CFGetTypeID(policyOrArray) == CFArrayGetTypeID()) {
559              CFIndex arrayLength = CFArrayGetCount((CFArrayRef)policyOrArray);
560              CFArrayAppendArray(policies, (CFArrayRef)policyOrArray, CFRangeMake(0, arrayLength));
561          }
562      }
563      CFIndex numPolicies = (policies) ? CFArrayGetCount(policies) : 0;
564      for (CFIndex index=0; index<numPolicies; index++) {
565          SecPolicyRef policy = (SecPolicyRef)CFArrayGetValueAtIndex(policies, index);
566          CFStringRef policyName = (policy) ? SecPolicyGetName(policy) : NULL;
567          if (policyName && CFEqual(CFSTR("revocation"), policyName)) {
568              CFArrayAppendValue(resultPolicyArray, policy);
569          }
570      }
571      CFReleaseNull(policies);
572      return resultPolicyArray;
573  }
574