snej@0
|
1 |
//
|
snej@0
|
2 |
// MYCertificate.m
|
snej@0
|
3 |
// MYCrypto
|
snej@0
|
4 |
//
|
snej@0
|
5 |
// Created by Jens Alfke on 3/26/09.
|
snej@0
|
6 |
// Copyright 2009 Jens Alfke. All rights reserved.
|
snej@0
|
7 |
//
|
snej@0
|
8 |
|
snej@0
|
9 |
#import "MYCertificate.h"
|
snej@0
|
10 |
#import "MYCrypto_Private.h"
|
jens@16
|
11 |
#import "MYIdentity.h"
|
snej@8
|
12 |
#import "MYDigest.h"
|
jens@21
|
13 |
#import "MYCertificateInfo.h"
|
snej@8
|
14 |
#import "MYErrorUtils.h"
|
snej@0
|
15 |
|
snej@0
|
16 |
|
snej@0
|
17 |
@implementation MYCertificate
|
snej@0
|
18 |
|
snej@0
|
19 |
|
snej@0
|
20 |
/** Creates a MYCertificate object for an existing Keychain certificate reference. */
|
snej@0
|
21 |
- (id) initWithCertificateRef: (SecCertificateRef)certificateRef {
|
snej@0
|
22 |
self = [super initWithKeychainItemRef: (SecKeychainItemRef)certificateRef];
|
snej@0
|
23 |
if (self) {
|
snej@0
|
24 |
_certificateRef = certificateRef; // superclass has already CFRetained it
|
snej@0
|
25 |
}
|
snej@0
|
26 |
return self;
|
snej@0
|
27 |
}
|
snej@0
|
28 |
|
snej@8
|
29 |
+ (MYCertificate*) certificateWithCertificateRef: (SecCertificateRef)certificateRef {
|
snej@8
|
30 |
return [[[self alloc] initWithCertificateRef: certificateRef] autorelease];
|
snej@8
|
31 |
}
|
snej@8
|
32 |
|
snej@0
|
33 |
/** Creates a MYCertificate object from exported key data, but does not add it to any keychain. */
|
snej@0
|
34 |
- (id) initWithCertificateData: (NSData*)data
|
jens@24
|
35 |
#if !MYCRYPTO_USE_IPHONE_API
|
snej@0
|
36 |
type: (CSSM_CERT_TYPE) type
|
snej@0
|
37 |
encoding: (CSSM_CERT_ENCODING) encoding
|
jens@24
|
38 |
#endif
|
snej@0
|
39 |
{
|
snej@0
|
40 |
Assert(data);
|
jens@24
|
41 |
SecCertificateRef certificateRef = NULL;
|
jens@24
|
42 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
43 |
certificateRef = SecCertificateCreateWithData(NULL, (CFDataRef)data);
|
jens@24
|
44 |
#else
|
snej@0
|
45 |
CSSM_DATA cssmData = {.Data=(void*)data.bytes, .Length=data.length};
|
snej@0
|
46 |
if (!check(SecCertificateCreateFromData(&cssmData, type, encoding, &certificateRef),
|
jens@24
|
47 |
@"SecCertificateCreateFromData"))
|
jens@24
|
48 |
certificateRef = NULL;
|
jens@24
|
49 |
#endif
|
jens@24
|
50 |
if (!certificateRef) {
|
snej@0
|
51 |
[self release];
|
snej@0
|
52 |
return nil;
|
snej@0
|
53 |
}
|
snej@0
|
54 |
self = [self initWithCertificateRef: certificateRef];
|
snej@0
|
55 |
CFRelease(certificateRef);
|
jens@24
|
56 |
|
jens@24
|
57 |
// If the cert is self-signed, verify its signature. Apple's frameworks don't do this,
|
jens@24
|
58 |
// even the SecTrust API; if the signature doesn't verify, they just assume it could be
|
jens@24
|
59 |
// signed by a different cert. Seems like a bad decision to me, so I'll add the check:
|
jens@24
|
60 |
MYCertificateInfo *info = self.info;
|
jens@24
|
61 |
if (info.isRoot) {
|
jens@24
|
62 |
Log(@"Verifying self-signed certificate %@ ...", self);
|
jens@24
|
63 |
if (![info verifySignatureWithKey: self.publicKey]) {
|
jens@24
|
64 |
Log(@"Self-signed cert failed signature verification (%@)", self);
|
jens@24
|
65 |
[self release];
|
jens@24
|
66 |
return nil;
|
jens@24
|
67 |
}
|
jens@24
|
68 |
}
|
jens@24
|
69 |
|
snej@0
|
70 |
return self;
|
snej@0
|
71 |
}
|
snej@0
|
72 |
|
jens@24
|
73 |
#if !MYCRYPTO_USE_IPHONE_API
|
snej@0
|
74 |
- (id) initWithCertificateData: (NSData*)data {
|
snej@0
|
75 |
return [self initWithCertificateData: data
|
snej@0
|
76 |
type: CSSM_CERT_X_509v3
|
snej@0
|
77 |
encoding: CSSM_CERT_ENCODING_BER];
|
snej@0
|
78 |
}
|
jens@24
|
79 |
#endif
|
jens@21
|
80 |
- (void) dealloc
|
jens@21
|
81 |
{
|
jens@21
|
82 |
[_info release];
|
jens@21
|
83 |
[super dealloc];
|
jens@21
|
84 |
}
|
jens@21
|
85 |
|
jens@21
|
86 |
|
snej@8
|
87 |
|
snej@8
|
88 |
- (NSString*) description {
|
snej@8
|
89 |
return $sprintf(@"%@[%@ %@/%p]",
|
snej@8
|
90 |
[self class],
|
snej@8
|
91 |
self.commonName,
|
snej@8
|
92 |
self.certificateData.my_SHA1Digest.abbreviatedHexString,
|
snej@8
|
93 |
_certificateRef);
|
snej@8
|
94 |
}
|
snej@8
|
95 |
|
snej@8
|
96 |
|
snej@8
|
97 |
- (BOOL)isEqualToCertificate:(MYCertificate*)cert {
|
snej@8
|
98 |
return [self isEqual: cert] || [self.certificateData isEqual: cert.certificateData];
|
snej@8
|
99 |
}
|
snej@8
|
100 |
|
snej@8
|
101 |
|
jens@24
|
102 |
#if !TARGET_OS_IPHONE
|
snej@0
|
103 |
+ (MYCertificate*) preferredCertificateForName: (NSString*)name {
|
snej@0
|
104 |
SecCertificateRef certRef = NULL;
|
snej@0
|
105 |
if (!check(SecCertificateCopyPreference((CFStringRef)name, 0, &certRef),
|
snej@0
|
106 |
@"SecCertificateCopyPreference"))
|
snej@0
|
107 |
return nil;
|
snej@0
|
108 |
return [[[MYCertificate alloc] initWithCertificateRef: certRef] autorelease];
|
snej@0
|
109 |
}
|
snej@0
|
110 |
|
snej@0
|
111 |
- (BOOL) setPreferredCertificateForName: (NSString*)name {
|
snej@0
|
112 |
return check(SecCertificateSetPreference(_certificateRef, (CFStringRef)name, 0, NULL),
|
snej@0
|
113 |
@"SecCertificateSetPreference");
|
snej@0
|
114 |
}
|
jens@24
|
115 |
#endif TARGET_OS_IPHONE
|
snej@0
|
116 |
|
snej@8
|
117 |
|
snej@0
|
118 |
@synthesize certificateRef=_certificateRef;
|
snej@0
|
119 |
|
snej@0
|
120 |
- (NSData*) certificateData {
|
jens@24
|
121 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
122 |
CFDataRef data = SecCertificateCopyData(_certificateRef);
|
jens@24
|
123 |
return data ?[(id)CFMakeCollectable(data) autorelease] :nil;
|
jens@24
|
124 |
#else
|
snej@0
|
125 |
CSSM_DATA cssmData;
|
snej@0
|
126 |
if (!check(SecCertificateGetData(_certificateRef, &cssmData),
|
snej@0
|
127 |
@"SecCertificateGetData"))
|
snej@0
|
128 |
return nil;
|
snej@0
|
129 |
return [NSData dataWithBytes: cssmData.Data length: cssmData.Length];
|
jens@24
|
130 |
#endif
|
snej@0
|
131 |
}
|
snej@0
|
132 |
|
snej@0
|
133 |
- (MYPublicKey*) publicKey {
|
snej@0
|
134 |
SecKeyRef keyRef = NULL;
|
jens@24
|
135 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
136 |
SecTrustRef trust = NULL;
|
jens@24
|
137 |
SecPolicyRef policy = SecPolicyCreateBasicX509();
|
jens@24
|
138 |
OSStatus err = SecTrustCreateWithCertificates((CFArrayRef)$array((id)_certificateRef),
|
jens@24
|
139 |
policy,
|
jens@24
|
140 |
&trust);
|
jens@24
|
141 |
CFRelease(policy);
|
jens@24
|
142 |
if (!check(err,@"SecTrustCreateWithCertificates"))
|
jens@24
|
143 |
return nil;
|
jens@24
|
144 |
SecTrustResultType result;
|
jens@24
|
145 |
if (!check(SecTrustEvaluate(trust, &result), @"SecTrustEvaluate")) {
|
jens@24
|
146 |
CFRelease(trust);
|
jens@24
|
147 |
return nil;
|
jens@24
|
148 |
}
|
jens@24
|
149 |
keyRef = SecTrustCopyPublicKey(trust);
|
jens@24
|
150 |
CFRelease(trust);
|
jens@24
|
151 |
#else
|
snej@0
|
152 |
if (!check(SecCertificateCopyPublicKey(_certificateRef, &keyRef),
|
snej@0
|
153 |
@"SecCertificateCopyPublicKey") || !keyRef)
|
snej@0
|
154 |
return nil;
|
jens@24
|
155 |
#endif
|
jens@24
|
156 |
if (!keyRef)
|
jens@24
|
157 |
return nil;
|
snej@0
|
158 |
MYPublicKey *key = [[[MYPublicKey alloc] initWithKeyRef: keyRef] autorelease];
|
snej@0
|
159 |
CFRelease(keyRef);
|
snej@0
|
160 |
return key;
|
snej@0
|
161 |
}
|
snej@0
|
162 |
|
jens@16
|
163 |
- (MYIdentity*) identity {
|
jens@16
|
164 |
return [[[MYIdentity alloc] initWithCertificateRef: _certificateRef] autorelease];
|
jens@16
|
165 |
}
|
jens@16
|
166 |
|
jens@21
|
167 |
- (MYCertificateInfo*) info {
|
jens@21
|
168 |
if (!_info) {
|
jens@21
|
169 |
NSError *error;
|
jens@21
|
170 |
_info = [[MYCertificateInfo alloc] initWithCertificateData: self.certificateData
|
jens@21
|
171 |
error: &error];
|
jens@21
|
172 |
if (!_info)
|
jens@21
|
173 |
Warn(@"Couldn't parse certificate %@: %@", self, error);
|
jens@21
|
174 |
}
|
jens@21
|
175 |
return _info;
|
jens@21
|
176 |
}
|
jens@21
|
177 |
|
snej@0
|
178 |
- (NSString*) commonName {
|
snej@0
|
179 |
CFStringRef name = NULL;
|
jens@24
|
180 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
181 |
name = SecCertificateCopySubjectSummary(_certificateRef);
|
jens@24
|
182 |
#else
|
snej@0
|
183 |
if (!check(SecCertificateCopyCommonName(_certificateRef, &name),
|
jens@24
|
184 |
@"SecCertificateCopyCommonName"))
|
snej@0
|
185 |
return nil;
|
jens@24
|
186 |
#endif
|
jens@24
|
187 |
return name ?[NSMakeCollectable(name) autorelease] :nil;
|
snej@0
|
188 |
}
|
snej@0
|
189 |
|
snej@0
|
190 |
- (NSArray*) emailAddresses {
|
jens@24
|
191 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
192 |
NSString *email = self.info.subject.emailAddress;
|
jens@24
|
193 |
return email ?$array(email) :nil;
|
jens@24
|
194 |
#else
|
snej@0
|
195 |
CFArrayRef addrs = NULL;
|
snej@0
|
196 |
if (!check(SecCertificateCopyEmailAddresses(_certificateRef, &addrs),
|
snej@0
|
197 |
@"SecCertificateCopyEmailAddresses") || !addrs)
|
snej@0
|
198 |
return nil;
|
snej@0
|
199 |
return [(id)CFMakeCollectable(addrs) autorelease];
|
jens@24
|
200 |
#endif
|
snej@0
|
201 |
}
|
snej@0
|
202 |
|
snej@0
|
203 |
|
snej@8
|
204 |
#pragma mark -
|
snej@8
|
205 |
#pragma mark TRUST/POLICY STUFF:
|
snej@8
|
206 |
|
snej@8
|
207 |
|
jens@24
|
208 |
- (SecTrustResultType) evaluateTrustWithPolicy: (SecPolicyRef)policy {
|
jens@24
|
209 |
SecTrustRef trust;
|
jens@24
|
210 |
if (!check(SecTrustCreateWithCertificates((CFArrayRef)$array((id)_certificateRef), policy, &trust),
|
jens@24
|
211 |
@"SecTrustCreateWithCertificates"))
|
jens@24
|
212 |
return kSecTrustResultOtherError;
|
jens@24
|
213 |
SecTrustResultType result;
|
jens@24
|
214 |
if (!check(SecTrustEvaluate(trust, &result), @"SecTrustEvaluate"))
|
jens@24
|
215 |
result = kSecTrustResultOtherError;
|
jens@24
|
216 |
|
jens@24
|
217 |
#if 0
|
jens@24
|
218 |
// This is just to log details:
|
jens@24
|
219 |
CSSM_TP_APPLE_EVIDENCE_INFO *status;
|
jens@24
|
220 |
CFArrayRef certChain;
|
jens@24
|
221 |
if (check(SecTrustGetResult(trust, &result, &certChain, &status), @"SecTrustGetResult")) {
|
jens@24
|
222 |
Log(@"evaluateTrust: result=%@, bits=%X, certChain=%@", MYTrustResultDescribe(result),status->StatusBits, certChain);
|
jens@24
|
223 |
for (unsigned i=0; i<status->NumStatusCodes; i++)
|
jens@24
|
224 |
Log(@" #%i: %X", i, status->StatusCodes[i]);
|
jens@24
|
225 |
CFRelease(certChain);
|
jens@24
|
226 |
}
|
jens@24
|
227 |
#endif
|
jens@24
|
228 |
|
jens@24
|
229 |
CFRelease(trust);
|
jens@24
|
230 |
return result;
|
jens@24
|
231 |
}
|
jens@24
|
232 |
|
jens@24
|
233 |
- (SecTrustResultType) evaluateTrust {
|
jens@24
|
234 |
return [self evaluateTrustWithPolicy: [[self class] X509Policy]];
|
jens@24
|
235 |
}
|
jens@24
|
236 |
|
jens@24
|
237 |
|
jens@24
|
238 |
#if !MYCRYPTO_USE_IPHONE_API
|
snej@8
|
239 |
+ (SecPolicyRef) policyForOID: (CSSM_OID) policyOID {
|
snej@8
|
240 |
SecPolicySearchRef search;
|
snej@8
|
241 |
if (!check(SecPolicySearchCreate(CSSM_CERT_X_509v3, &policyOID, NULL, &search),
|
snej@8
|
242 |
@"SecPolicySearchCreate"))
|
snej@8
|
243 |
return nil;
|
snej@8
|
244 |
SecPolicyRef policy = NULL;
|
snej@8
|
245 |
if (!check(SecPolicySearchCopyNext(search, &policy), @"SecPolicySearchCopyNext"))
|
snej@8
|
246 |
policy = NULL;
|
snej@8
|
247 |
CFRelease(search);
|
snej@8
|
248 |
return policy;
|
snej@8
|
249 |
}
|
jens@24
|
250 |
#endif
|
snej@8
|
251 |
|
snej@8
|
252 |
+ (SecPolicyRef) X509Policy {
|
snej@8
|
253 |
static SecPolicyRef sX509Policy = NULL;
|
jens@24
|
254 |
if (!sX509Policy) {
|
jens@24
|
255 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
256 |
sX509Policy = SecPolicyCreateBasicX509();
|
jens@24
|
257 |
#else
|
snej@8
|
258 |
sX509Policy = [self policyForOID: CSSMOID_APPLE_X509_BASIC];
|
jens@24
|
259 |
#endif
|
jens@24
|
260 |
}
|
snej@8
|
261 |
return sX509Policy;
|
snej@8
|
262 |
}
|
snej@8
|
263 |
|
snej@8
|
264 |
+ (SecPolicyRef) SSLPolicy {
|
snej@8
|
265 |
static SecPolicyRef sSSLPolicy = NULL;
|
jens@24
|
266 |
if (!sSSLPolicy) {
|
jens@24
|
267 |
#if MYCRYPTO_USE_IPHONE_API
|
jens@24
|
268 |
sSSLPolicy = SecPolicyCreateSSL(NO,NULL);
|
jens@24
|
269 |
#else
|
snej@8
|
270 |
sSSLPolicy = [self policyForOID: CSSMOID_APPLE_TP_SSL];
|
jens@24
|
271 |
#endif
|
jens@24
|
272 |
}
|
snej@8
|
273 |
return sSSLPolicy;
|
snej@8
|
274 |
}
|
snej@8
|
275 |
|
jens@24
|
276 |
#if !TARGET_OS_IPHONE
|
snej@8
|
277 |
+ (SecPolicyRef) SMIMEPolicy {
|
snej@8
|
278 |
static SecPolicyRef sSMIMEPolicy = NULL;
|
jens@24
|
279 |
if (!sSMIMEPolicy) {
|
snej@8
|
280 |
sSMIMEPolicy = [self policyForOID: CSSMOID_APPLE_TP_SMIME];
|
jens@24
|
281 |
}
|
snej@8
|
282 |
return sSMIMEPolicy;
|
snej@8
|
283 |
}
|
snej@8
|
284 |
|
snej@8
|
285 |
- (CSSM_CERT_TYPE) certificateType {
|
snej@8
|
286 |
CSSM_CERT_TYPE type = CSSM_CERT_UNKNOWN;
|
snej@8
|
287 |
if (!check(SecCertificateGetType(_certificateRef, &type), @"SecCertificateGetType"))
|
snej@8
|
288 |
type = CSSM_CERT_UNKNOWN;
|
snej@8
|
289 |
return type;
|
snej@8
|
290 |
}
|
snej@8
|
291 |
|
snej@8
|
292 |
- (NSArray*) trustSettings {
|
snej@8
|
293 |
CFArrayRef settings = NULL;
|
snej@8
|
294 |
OSStatus err = SecTrustSettingsCopyTrustSettings(_certificateRef, kSecTrustSettingsDomainUser,
|
snej@8
|
295 |
&settings);
|
snej@8
|
296 |
if (err == errSecItemNotFound || !check(err,@"SecTrustSettingsCopyTrustSettings") || !settings)
|
snej@8
|
297 |
return nil;
|
snej@8
|
298 |
return [(id)CFMakeCollectable(settings) autorelease];
|
snej@8
|
299 |
}
|
snej@8
|
300 |
|
snej@8
|
301 |
|
snej@8
|
302 |
- (BOOL) setUserTrust: (SecTrustUserSetting)trustSetting
|
snej@8
|
303 |
{
|
snej@8
|
304 |
if (trustSetting == kSecTrustResultProceed) {
|
snej@8
|
305 |
return check(SecTrustSettingsSetTrustSettings(_certificateRef,
|
snej@8
|
306 |
kSecTrustSettingsDomainUser, nil),
|
snej@8
|
307 |
@"SecTrustSettingsSetTrustSettings");
|
snej@8
|
308 |
} else if (trustSetting == kSecTrustResultDeny) {
|
snej@8
|
309 |
OSStatus err = SecTrustSettingsRemoveTrustSettings(_certificateRef,
|
snej@8
|
310 |
kSecTrustSettingsDomainUser);
|
snej@8
|
311 |
return err == errSecItemNotFound || check(err, @"SecTrustSettingsRemoveTrustSettings");
|
snej@8
|
312 |
} else
|
snej@8
|
313 |
return paramErr;
|
snej@8
|
314 |
}
|
jens@24
|
315 |
#endif
|
snej@8
|
316 |
|
snej@8
|
317 |
|
snej@0
|
318 |
@end
|
snej@0
|
319 |
|
snej@0
|
320 |
|
snej@8
|
321 |
NSString* MYTrustResultDescribe( SecTrustResultType result ) {
|
snej@8
|
322 |
static NSString* const kTrustResultNames[kSecTrustResultOtherError+1] = {
|
snej@8
|
323 |
@"Invalid",
|
snej@8
|
324 |
@"Proceed",
|
snej@8
|
325 |
@"Confirm",
|
snej@8
|
326 |
@"Deny",
|
snej@8
|
327 |
@"Unspecified",
|
snej@8
|
328 |
@"RecoverableTrustFailure",
|
snej@8
|
329 |
@"FatalTrustFailure",
|
snej@8
|
330 |
@"OtherError"
|
snej@8
|
331 |
};
|
snej@8
|
332 |
if (result>=0 && result <=kSecTrustResultOtherError)
|
snej@8
|
333 |
return kTrustResultNames[result];
|
snej@8
|
334 |
else
|
snej@8
|
335 |
return $sprintf(@"(Unknown trust result %i)", result);
|
snej@8
|
336 |
}
|
snej@8
|
337 |
|
snej@8
|
338 |
|
jens@24
|
339 |
#if !TARGET_OS_IPHONE
|
jens@24
|
340 |
NSString* MYPolicyGetName( SecPolicyRef policy ) {
|
jens@24
|
341 |
if (!policy)
|
jens@24
|
342 |
return @"(null)";
|
jens@24
|
343 |
CSSM_OID oid = {};
|
jens@24
|
344 |
SecPolicyGetOID(policy, &oid);
|
jens@24
|
345 |
return $sprintf(@"SecPolicy[%@]", OIDAsString(oid));
|
jens@24
|
346 |
}
|
jens@24
|
347 |
|
snej@8
|
348 |
NSString* MYTrustDescribe( SecTrustRef trust ) {
|
snej@8
|
349 |
SecTrustResultType result;
|
snej@8
|
350 |
CFArrayRef certChain=NULL;
|
snej@8
|
351 |
CSSM_TP_APPLE_EVIDENCE_INFO* statusChain;
|
snej@8
|
352 |
OSStatus err = SecTrustGetResult(trust, &result, &certChain, &statusChain);
|
snej@8
|
353 |
NSString *desc;
|
snej@8
|
354 |
if (err)
|
snej@8
|
355 |
desc = $sprintf(@"SecTrust[%p, err=%@]", trust, MYErrorName(NSOSStatusErrorDomain, err));
|
snej@8
|
356 |
else
|
snej@8
|
357 |
desc = $sprintf(@"SecTrust[%@, %u in chain]",
|
snej@8
|
358 |
MYTrustResultDescribe(result),
|
snej@8
|
359 |
CFArrayGetCount(certChain));
|
snej@8
|
360 |
if (certChain) CFRelease(certChain);
|
snej@8
|
361 |
return desc;
|
snej@8
|
362 |
}
|
snej@8
|
363 |
|
snej@8
|
364 |
|
snej@12
|
365 |
// Taken from Keychain.framework
|
snej@12
|
366 |
NSString* OIDAsString(const CSSM_OID oid) {
|
snej@12
|
367 |
if ((NULL == oid.Data) || (0 >= oid.Length)) {
|
snej@12
|
368 |
return nil;
|
snej@12
|
369 |
} else {
|
snej@12
|
370 |
NSMutableString *result = [NSMutableString stringWithCapacity:(4 * oid.Length)];
|
snej@12
|
371 |
unsigned int i;
|
snej@12
|
372 |
|
snej@12
|
373 |
for (i = 0; i < oid.Length; ++i) {
|
snej@12
|
374 |
[result appendFormat:@"%s%hhu", ((0 == i) ? "" : ", "), oid.Data[i]];
|
snej@12
|
375 |
}
|
snej@12
|
376 |
|
snej@12
|
377 |
return result;
|
snej@12
|
378 |
}
|
snej@12
|
379 |
}
|
jens@24
|
380 |
#endif
|
snej@12
|
381 |
|
snej@12
|
382 |
|
jens@24
|
383 |
#if !TARGET_OS_IPHONE
|
snej@8
|
384 |
TestCase(Trust) {
|
snej@8
|
385 |
Log(@"X.509 policy = %@", MYPolicyGetName([MYCertificate X509Policy]));
|
snej@8
|
386 |
Log(@" SSL policy = %@", MYPolicyGetName([MYCertificate SSLPolicy]));
|
snej@8
|
387 |
Log(@"SMIME policy = %@", MYPolicyGetName([MYCertificate SMIMEPolicy]));
|
snej@8
|
388 |
for (MYCertificate *cert in [[MYKeychain defaultKeychain] enumerateCertificates]) {
|
snej@8
|
389 |
NSArray *settings = cert.trustSettings;
|
snej@8
|
390 |
if (settings)
|
snej@8
|
391 |
Log(@"---- %@ = %@", cert, settings);
|
snej@8
|
392 |
}
|
snej@8
|
393 |
}
|
jens@24
|
394 |
#endif
|
snej@14
|
395 |
|
snej@14
|
396 |
|
snej@14
|
397 |
|
snej@14
|
398 |
/*
|
snej@14
|
399 |
Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
|
snej@14
|
400 |
|
snej@14
|
401 |
Redistribution and use in source and binary forms, with or without modification, are permitted
|
snej@14
|
402 |
provided that the following conditions are met:
|
snej@14
|
403 |
|
snej@14
|
404 |
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
snej@14
|
405 |
and the following disclaimer.
|
snej@14
|
406 |
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
snej@14
|
407 |
and the following disclaimer in the documentation and/or other materials provided with the
|
snej@14
|
408 |
distribution.
|
snej@14
|
409 |
|
snej@14
|
410 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
snej@14
|
411 |
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
snej@14
|
412 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
|
snej@14
|
413 |
BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
snej@14
|
414 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
snej@14
|
415 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
snej@14
|
416 |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
snej@14
|
417 |
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
snej@14
|
418 |
*/
|