]> git.saurik.com Git - apple/security.git/blob - OSX/regressions/test/testpolicy.m
Security-58286.251.4.tar.gz
[apple/security.git] / OSX / regressions / test / testpolicy.m
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include "testpolicy.h"
26
27 #include <TargetConditionals.h>
28
29 #include <Foundation/Foundation.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <utilities/SecCFWrappers.h>
32 #include <Security/SecCertificate.h>
33 #include <Security/SecCertificatePriv.h>
34 #include <Security/SecPolicyPriv.h>
35 #include <Security/SecTrust.h>
36 #include <Security/SecTrustPriv.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39
40 #include "testmore.h"
41
42
43 /* Those tests were originally written around that date. */
44 CFGiblisGetSingleton(CFDateRef, GetFrozenTime, frozenTime, ^{
45 *frozenTime = CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1);
46 });
47
48 static void runOneLeafTest(SecPolicyRef policy,
49 NSArray* anchors,
50 NSArray* intermediates,
51 NSString* path,
52 bool expectedResult,
53 NSObject* expectations,
54 CFDateRef date)
55 {
56 NSString* fileName = [path lastPathComponent];
57 const char *reason = NULL;
58 SecTrustRef trustRef = NULL;
59 CFStringRef failReason = NULL;
60 NSMutableArray* certArray = NULL;
61 SecCertificateRef certRef = NULL;
62
63 if (expectations) {
64 if ([expectations isKindOfClass: [NSString class]]) {
65 reason = [(NSString *)expectations UTF8String];
66 } else if ([expectations isKindOfClass: [NSDictionary class]]) {
67 NSDictionary *dict = (NSDictionary *)expectations;
68 NSObject *value = [dict valueForKey:@"valid"];
69 if (value) {
70 if ([value isKindOfClass: [NSNumber class]]) {
71 expectedResult = [(NSNumber *)value boolValue];
72 } else {
73 NSLog(@"Unexpected valid value %@ in dict for key %@", value, fileName);
74 }
75 }
76 value = [dict valueForKey:@"reason"];
77 if (value) {
78 if ([value isKindOfClass: [NSString class]]) {
79 reason = [(NSString *)value UTF8String];
80 } else {
81 NSLog(@"Unexpected reason value %@ in dict for key %@", value, fileName);
82 }
83 }
84 } else if ([expectations isKindOfClass: [NSNumber class]]) {
85 expectedResult = [(NSNumber *)expectations boolValue];
86 } else {
87 NSLog(@"Unexpected class %@ value %@ for key %@", [expectations class], expectations, fileName);
88 }
89 }
90
91 certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
92 if (!certRef) {
93 if (reason) {
94 todo(reason);
95 fail("%@ unable to create certificate", fileName);
96 } else {
97 fail("PARSE %@ unable to create certificate", fileName);
98 }
99 goto exit;
100 }
101
102 certArray = [NSMutableArray arrayWithArray:intermediates];
103 [certArray insertObject:(__bridge id)certRef atIndex:0]; //The certificate to be verified must be the first in the array.
104
105 OSStatus err;
106 err = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)(certArray), policy, &trustRef);
107 if (err) {
108 ok_status(err, "SecTrustCreateWithCertificates");
109 goto exit;
110 }
111 if ([anchors count])
112 SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors);
113
114 SecTrustSetVerifyDate(trustRef, date ? date : GetFrozenTime());
115
116 SecTrustResultType evalRes = 0;
117 //NSLog(@"Evaluating: %@",certRef);
118 err = SecTrustEvaluate(trustRef, &evalRes);
119 if (err) {
120 ok_status(err, "SecTrustEvaluate");
121 goto exit;
122 }
123 BOOL isValid = (evalRes == kSecTrustResultProceed || evalRes == kSecTrustResultUnspecified);
124 if (!isValid && expectedResult) {
125 failReason = SecTrustCopyFailureDescription(trustRef);
126 }
127 if (reason) {
128 todo(reason);
129 ok(isValid == expectedResult, "%@%@",
130 fileName,
131 (expectedResult
132 ? (failReason ? failReason : CFSTR(""))
133 : CFSTR(" valid")));
134 } else {
135 ok(isValid == expectedResult, "%s %@%@",
136 expectedResult ? "REGRESSION" : "SECURITY", fileName,
137 failReason ? failReason : CFSTR(""));
138 }
139
140 exit:
141 CFReleaseSafe(failReason);
142 CFReleaseSafe(trustRef);
143 CFReleaseSafe(certRef);
144 }
145
146 // TODO: Export this interface in a better way.
147 static void runCertificateTestFor(SecPolicyRef policy,
148 NSArray* anchors,
149 NSArray* intermediates,
150 NSMutableArray* leafPaths,
151 NSDictionary* expect,
152 CFDateRef date)
153 {
154 /* Sort the tests by name. */
155 [leafPaths sortUsingSelector:@selector(compare:)];
156
157 for (NSString* path in leafPaths) {
158 NSString* fileName = [path lastPathComponent];
159 runOneLeafTest(policy, anchors, intermediates, path, ![fileName hasPrefix:@"Invalid"], [expect objectForKey:fileName], date);
160 }
161 }
162
163 void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFDateRef date)
164 {
165 NSMutableArray* allRoots = [NSMutableArray array];
166 NSMutableArray* allCAs = [NSMutableArray array];
167 NSMutableArray* certTests = [NSMutableArray array];
168 NSDictionary* expect = NULL;
169
170 /* Iterate though the nist-certs resources dir. */
171 NSURL* filesDirectory = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:(__bridge NSString*)resourceSubDirectory];
172 for (NSURL* fileURL in [[NSFileManager defaultManager] contentsOfDirectoryAtURL:filesDirectory includingPropertiesForKeys:[NSArray array] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:nil]) {
173 NSString* path = [fileURL path];
174 if ([path hasSuffix:@"Cert.crt"]) {
175 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
176 [allCAs addObject:(__bridge id)certRef];
177 CFReleaseNull(certRef);
178 } else if ([path hasSuffix:@"RootCertificate.crt"]) {
179 SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
180 [allRoots addObject:(__bridge id)certRef];
181 CFReleaseNull(certRef);
182 } else if ([path hasSuffix:@".crt"]) {
183 [certTests addObject:path];
184 } else if ([path hasSuffix:@".plist"]) {
185 if (expect) {
186 fail("Multiple .plist files found in %@", filesDirectory);
187 } else {
188 expect = [NSDictionary dictionaryWithContentsOfFile:path];
189 }
190 }
191 }
192
193 runCertificateTestFor(policy, allRoots, allCAs, certTests, expect, date);
194 }