diff -r 8982b8fada63 -r aa5eb3fd6ebf MYCertificate.m --- a/MYCertificate.m Tue Apr 07 10:56:58 2009 -0700 +++ b/MYCertificate.m Sun Apr 12 22:16:14 2009 -0700 @@ -8,6 +8,8 @@ #import "MYCertificate.h" #import "MYCrypto_Private.h" +#import "MYDigest.h" +#import "MYErrorUtils.h" #if !MYCRYPTO_USE_IPHONE_API @@ -24,6 +26,10 @@ return self; } ++ (MYCertificate*) certificateWithCertificateRef: (SecCertificateRef)certificateRef { + return [[[self alloc] initWithCertificateRef: certificateRef] autorelease]; +} + /** Creates a MYCertificate object from exported key data, but does not add it to any keychain. */ - (id) initWithCertificateData: (NSData*)data type: (CSSM_CERT_TYPE) type @@ -48,6 +54,21 @@ encoding: CSSM_CERT_ENCODING_BER]; } + +- (NSString*) description { + return $sprintf(@"%@[%@ %@/%p]", + [self class], + self.commonName, + self.certificateData.my_SHA1Digest.abbreviatedHexString, + _certificateRef); +} + + +- (BOOL)isEqualToCertificate:(MYCertificate*)cert { + return [self isEqual: cert] || [self.certificateData isEqual: cert.certificateData]; +} + + + (MYCertificate*) preferredCertificateForName: (NSString*)name { SecCertificateRef certRef = NULL; if (!check(SecCertificateCopyPreference((CFStringRef)name, 0, &certRef), @@ -61,6 +82,7 @@ @"SecCertificateSetPreference"); } + @synthesize certificateRef=_certificateRef; - (NSData*) certificateData { @@ -98,7 +120,133 @@ } +#pragma mark - +#pragma mark TRUST/POLICY STUFF: + + ++ (SecPolicyRef) policyForOID: (CSSM_OID) policyOID { + SecPolicySearchRef search; + if (!check(SecPolicySearchCreate(CSSM_CERT_X_509v3, &policyOID, NULL, &search), + @"SecPolicySearchCreate")) + return nil; + SecPolicyRef policy = NULL; + if (!check(SecPolicySearchCopyNext(search, &policy), @"SecPolicySearchCopyNext")) + policy = NULL; + CFRelease(search); + return policy; +} + ++ (SecPolicyRef) X509Policy { + static SecPolicyRef sX509Policy = NULL; + if (!sX509Policy) + sX509Policy = [self policyForOID: CSSMOID_APPLE_X509_BASIC]; + return sX509Policy; +} + ++ (SecPolicyRef) SSLPolicy { + static SecPolicyRef sSSLPolicy = NULL; + if (!sSSLPolicy) + sSSLPolicy = [self policyForOID: CSSMOID_APPLE_TP_SSL]; + return sSSLPolicy; +} + ++ (SecPolicyRef) SMIMEPolicy { + static SecPolicyRef sSMIMEPolicy = NULL; + if (!sSMIMEPolicy) + sSMIMEPolicy = [self policyForOID: CSSMOID_APPLE_TP_SMIME]; + return sSMIMEPolicy; +} + + +- (CSSM_CERT_TYPE) certificateType { + CSSM_CERT_TYPE type = CSSM_CERT_UNKNOWN; + if (!check(SecCertificateGetType(_certificateRef, &type), @"SecCertificateGetType")) + type = CSSM_CERT_UNKNOWN; + return type; +} + +- (NSArray*) trustSettings { + CFArrayRef settings = NULL; + OSStatus err = SecTrustSettingsCopyTrustSettings(_certificateRef, kSecTrustSettingsDomainUser, + &settings); + if (err == errSecItemNotFound || !check(err,@"SecTrustSettingsCopyTrustSettings") || !settings) + return nil; + return [(id)CFMakeCollectable(settings) autorelease]; +} + + +- (BOOL) setUserTrust: (SecTrustUserSetting)trustSetting +{ + if (trustSetting == kSecTrustResultProceed) { + return check(SecTrustSettingsSetTrustSettings(_certificateRef, + kSecTrustSettingsDomainUser, nil), + @"SecTrustSettingsSetTrustSettings"); + } else if (trustSetting == kSecTrustResultDeny) { + OSStatus err = SecTrustSettingsRemoveTrustSettings(_certificateRef, + kSecTrustSettingsDomainUser); + return err == errSecItemNotFound || check(err, @"SecTrustSettingsRemoveTrustSettings"); + } else + return paramErr; +} + + @end +NSString* MYPolicyGetName( SecPolicyRef policy ) { + if (!policy) + return @"(null)"; + CSSM_OID oid = {}; + SecPolicyGetOID(policy, &oid); + return $sprintf(@"SecPolicy[%@]", OIDAsString(oid)); +} + +NSString* MYTrustResultDescribe( SecTrustResultType result ) { + static NSString* const kTrustResultNames[kSecTrustResultOtherError+1] = { + @"Invalid", + @"Proceed", + @"Confirm", + @"Deny", + @"Unspecified", + @"RecoverableTrustFailure", + @"FatalTrustFailure", + @"OtherError" + }; + if (result>=0 && result <=kSecTrustResultOtherError) + return kTrustResultNames[result]; + else + return $sprintf(@"(Unknown trust result %i)", result); +} + + +NSString* MYTrustDescribe( SecTrustRef trust ) { + SecTrustResultType result; + CFArrayRef certChain=NULL; + CSSM_TP_APPLE_EVIDENCE_INFO* statusChain; + OSStatus err = SecTrustGetResult(trust, &result, &certChain, &statusChain); + NSString *desc; + if (err) + desc = $sprintf(@"SecTrust[%p, err=%@]", trust, MYErrorName(NSOSStatusErrorDomain, err)); + else + desc = $sprintf(@"SecTrust[%@, %u in chain]", + MYTrustResultDescribe(result), + CFArrayGetCount(certChain)); + if (certChain) CFRelease(certChain); + return desc; +} + + + +TestCase(Trust) { + Log(@"X.509 policy = %@", MYPolicyGetName([MYCertificate X509Policy])); + Log(@" SSL policy = %@", MYPolicyGetName([MYCertificate SSLPolicy])); + Log(@"SMIME policy = %@", MYPolicyGetName([MYCertificate SMIMEPolicy])); + for (MYCertificate *cert in [[MYKeychain defaultKeychain] enumerateCertificates]) { + NSArray *settings = cert.trustSettings; + if (settings) + Log(@"---- %@ = %@", cert, settings); + } +} + + #endif !MYCRYPTO_USE_IPHONE_API