1 | Index: Portfile |
---|
2 | =================================================================== |
---|
3 | --- Portfile (revision 117820) |
---|
4 | +++ Portfile (working copy) |
---|
5 | @@ -3,8 +3,7 @@ |
---|
6 | PortSystem 1.0 |
---|
7 | |
---|
8 | name certsync |
---|
9 | -version 1.0.6 |
---|
10 | -revision 3 |
---|
11 | +version 1.0.7 |
---|
12 | categories security |
---|
13 | conflicts curl-ca-bundle |
---|
14 | maintainers landonf openmaintainer |
---|
15 | Index: files/certsync.m |
---|
16 | =================================================================== |
---|
17 | --- files/certsync.m (revision 117820) |
---|
18 | +++ files/certsync.m (working copy) |
---|
19 | @@ -96,6 +96,60 @@ |
---|
20 | } |
---|
21 | |
---|
22 | /** |
---|
23 | + * Verify that the root certificate trusts itself; this filters out certificates that |
---|
24 | + * are still marked as trusted by the OS, but are expired or otherwise unusable. |
---|
25 | + */ |
---|
26 | +static BOOL ValidateSelfTrust (SecCertificateRef cert) { |
---|
27 | + OSStatus err; |
---|
28 | + |
---|
29 | + /* Create a new trust evaluation instance */ |
---|
30 | + SecTrustRef trust; |
---|
31 | + { |
---|
32 | + SecPolicyRef policy = SecPolicyCreateBasicX509(); |
---|
33 | + if ((err = SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust)) != errSecSuccess) { |
---|
34 | + /* Shouldn't happen */ |
---|
35 | + nsfprintf(stderr, @"Failed to create SecTrustRef: %d\n", err); |
---|
36 | + CFRelease(policy); |
---|
37 | + return NO; |
---|
38 | + } |
---|
39 | + CFRelease(policy); |
---|
40 | + } |
---|
41 | + |
---|
42 | + /* Set this certificate as the only (self-)anchor */ |
---|
43 | + { |
---|
44 | + CFArrayRef certs = CFArrayCreate(NULL, (const void **) &cert, 1, &kCFTypeArrayCallBacks); |
---|
45 | + if ((err = SecTrustSetAnchorCertificates(trust, certs)) != errSecSuccess) { |
---|
46 | + nsfprintf(stderr, @"Failed to set anchor certificates on our SecTrustRef: %d\n", err); |
---|
47 | + CFRelease(certs); |
---|
48 | + CFRelease(trust); |
---|
49 | + return NO; |
---|
50 | + } |
---|
51 | + CFRelease(certs); |
---|
52 | + } |
---|
53 | + |
---|
54 | + /* Evaluate the certificate trust */ |
---|
55 | + SecTrustResultType rt; |
---|
56 | + if ((err = SecTrustEvaluate(trust, &rt)) != errSecSuccess) { |
---|
57 | + nsfprintf(stderr, @"SecTrustEvaluate() failed: %d\n", err); |
---|
58 | + CFRelease(trust); |
---|
59 | + } |
---|
60 | + |
---|
61 | + CFRelease(trust); |
---|
62 | + |
---|
63 | + /* Check the result */ |
---|
64 | + switch (rt) { |
---|
65 | + case kSecTrustResultUnspecified: |
---|
66 | + case kSecTrustResultProceed: |
---|
67 | + /* Trusted */ |
---|
68 | + return YES; |
---|
69 | + |
---|
70 | + default: |
---|
71 | + /* Untrusted */ |
---|
72 | + return NO; |
---|
73 | + } |
---|
74 | +} |
---|
75 | + |
---|
76 | +/** |
---|
77 | * Fetch all trusted roots for the given @a domain. |
---|
78 | * |
---|
79 | * @param domain The trust domain to query. |
---|
80 | @@ -105,7 +159,7 @@ |
---|
81 | */ |
---|
82 | static NSArray *certificatesForTrustDomain (SecTrustSettingsDomain domain, NSError **outError) { |
---|
83 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
---|
84 | - NSArray *trusted = nil; |
---|
85 | + NSMutableArray *trusted = nil; |
---|
86 | CFArrayRef certs = nil; |
---|
87 | OSStatus err; |
---|
88 | |
---|
89 | @@ -131,8 +185,7 @@ |
---|
90 | } |
---|
91 | |
---|
92 | /* Extract trusted roots */ |
---|
93 | - NSMutableArray *results = [NSMutableArray arrayWithCapacity: CFArrayGetCount(certs)]; |
---|
94 | - trusted = results; |
---|
95 | + trusted = [NSMutableArray arrayWithCapacity: CFArrayGetCount(certs)]; |
---|
96 | |
---|
97 | NSEnumerator *resultEnumerator = [(NSArray *)certs objectEnumerator]; |
---|
98 | id certObj; |
---|
99 | @@ -152,7 +205,7 @@ |
---|
100 | |
---|
101 | /* If empty, trust for everything (as per the Security Framework documentation) */ |
---|
102 | if (CFArrayGetCount(trustSettings) == 0) { |
---|
103 | - [results addObject: certObj]; |
---|
104 | + [trusted addObject: certObj]; |
---|
105 | } else { |
---|
106 | /* Otherwise, walk the properties and evaluate the trust settings result */ |
---|
107 | NSEnumerator *trustEnumerator = [(NSArray *)trustSettings objectEnumerator]; |
---|
108 | @@ -166,7 +219,7 @@ |
---|
109 | |
---|
110 | /* If a root, add to the result set */ |
---|
111 | if (settingsResult == kSecTrustSettingsResultTrustRoot || settingsResult == kSecTrustSettingsResultTrustAsRoot) { |
---|
112 | - [results addObject: certObj]; |
---|
113 | + [trusted addObject: certObj]; |
---|
114 | break; |
---|
115 | } |
---|
116 | } |
---|
117 | @@ -192,9 +245,31 @@ |
---|
118 | } |
---|
119 | |
---|
120 | /* All certs are trusted */ |
---|
121 | - trusted = (NSArray *) certs; |
---|
122 | + trusted = [[(NSArray *) certs mutableCopy] autorelease]; |
---|
123 | + CFRelease(certs); |
---|
124 | } |
---|
125 | |
---|
126 | + /* |
---|
127 | + * Filter out any trusted certificates that can not actually be used in verification; eg, they are expired. |
---|
128 | + * |
---|
129 | + * There are cases where CAs have issued new certificates using identical public keys, and the expired |
---|
130 | + * and current CA certificates are both included in the list of trusted certificates. In such a case, |
---|
131 | + * OpenSSL will simply use whichever certificate is listed first; if that happens to be the expired |
---|
132 | + * certificate, validation will fail. |
---|
133 | + * |
---|
134 | + * This step ensures that we exclude any expired or known-unusable certificates. |
---|
135 | + * |
---|
136 | + * We enumerate a copy of the array so that we can safely modify the original during enumeration. |
---|
137 | + */ |
---|
138 | + NSEnumerator *trustedEnumerator = [[[trusted copy] autorelease] objectEnumerator]; |
---|
139 | + id certObj; |
---|
140 | + while ((certObj = [trustedEnumerator nextObject]) != nil) { |
---|
141 | + /* If self-trust validation fails, the certificate is expired or otherwise not useable */ |
---|
142 | + if (!ValidateSelfTrust((SecCertificateRef) certObj)) { |
---|
143 | + [trusted removeObject: certObj]; |
---|
144 | + } |
---|
145 | + } |
---|
146 | + |
---|
147 | [trusted retain]; |
---|
148 | [pool release]; |
---|
149 | return [trusted autorelease]; |
---|