]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_codesigning/lib/gkoverride.m
47a7066e7c4ed2a81d294abb8898ec5645849c9e
[apple/security.git] / Security / libsecurity_codesigning / lib / gkoverride.m
1 /*
2 * Copyright (c) 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 #import <Foundation/Foundation.h>
24 #import <CrashReporterSupport/CrashReporterSupportPrivate.h>
25 #import <sys/utsname.h>
26
27 static bool useInternalServer() {
28 struct utsname name;
29 return ((uname(&name) == 0 && strstr(name.version, "DEVELOPMENT") != NULL)
30 && access("/var/db/gkoverride_use_internal", F_OK) == 0);
31 }
32
33 @interface OverrideClient : NSObject<NSURLConnectionDelegate> {
34 BOOL allow;
35 NSMutableData *buffer;
36 NSURLConnection *connection;
37 int state;
38 }
39 @property NSString *currentHash;
40 @property NSString *opaqueHash;
41 @property NSString *bundleID;
42 @property NSString *bundleVersion;
43 - (NSString *)serverHost;
44 - (void)sendQuery;
45 - (void)sendReport;
46 - (void)abort;
47 @end
48
49 @implementation OverrideClient
50
51 - (NSString *)serverHost {
52 if (useInternalServer())
53 return @"gkq-stg.siri.apple.com";
54 else
55 return @"gkq.apple.com";
56 }
57
58 - (id)init {
59 self = [super init];
60 allow = NO;
61 buffer = [NSMutableData new];
62 return self;
63 }
64
65 - (void)sendQuery {
66 state = 1;
67 NSMutableURLRequest *request = [NSMutableURLRequest new];
68 NSString *url = [NSString stringWithFormat:@"https://%@/q/%@/%@", [self serverHost], self.currentHash, self.opaqueHash];
69 [request setURL:[NSURL URLWithString:url]];
70 [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
71 [request setTimeoutInterval:5];
72 connection = [NSURLConnection connectionWithRequest:request delegate:self];
73 }
74
75 - (void)sendReport {
76 state = 2;
77 NSMutableURLRequest *request = [NSMutableURLRequest new];
78 NSString *body = [NSString stringWithFormat:@"current=%@&bundleid=%@&version=%@",
79 [self.currentHash stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
80 [self.bundleID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
81 [self.bundleVersion stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
82 NSString *url = [NSString stringWithFormat:@"https://%@/report", [self serverHost]];
83 [request setURL:[NSURL URLWithString:url]];
84 [request setTimeoutInterval:5];
85 [request setHTTPMethod:@"POST"];
86 [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
87 connection = [NSURLConnection connectionWithRequest:request delegate:self];
88 }
89
90 - (BOOL)connection:(NSURLConnection *)conn canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
91 SecTrustRef trust = [protectionSpace serverTrust];
92 // abort if untrusted
93 SecTrustResultType trustResult;
94 SecTrustEvaluate(trust, &trustResult);
95 if (trustResult != kSecTrustResultProceed && trustResult != kSecTrustResultUnspecified) {
96 [conn cancel];
97 [self abort];
98 return NO;
99 }
100 // allow if server presented an EV cert
101 NSDictionary *result = CFBridgingRelease(SecTrustCopyResult(trust));
102 if (result) {
103 NSNumber *ev = [result objectForKey:(__bridge id)kSecTrustExtendedValidation];
104 if (ev != NULL && [ev boolValue] == YES) {
105 return NO;
106 }
107 }
108 // allow if using internal server (EV not required)
109 if (useInternalServer())
110 return NO;
111 // otherwise abort
112 [conn cancel];
113 [self abort];
114 return NO;
115 }
116
117 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
118 [buffer appendData:data];
119 if ([buffer length] > 100)
120 [self abort];
121 }
122
123 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
124 if (state == 1) {
125 NSString *verdict = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
126 if ([verdict isEqualToString:@"allow"]) {
127 allow = YES;
128 [self abort];
129 } else if (CRIsAutoSubmitEnabled()) { // "Send diagnostic & usage data to Apple" checked
130 [self sendReport];
131 }
132 } else {
133 [self abort]; // report sent
134 }
135 }
136
137 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
138 [self abort];
139 }
140
141 - (void)abort {
142 if (allow) {
143 printf("allow\n");
144 exit(42);
145 } else {
146 printf("deny\n");
147 exit(1);
148 }
149 }
150
151 @end
152
153 int main(int argc, const char * argv[]) {
154 if (argc != 5) {
155 fprintf(stderr, "usage: %s <current> <opaque> <bundleid> <version>\n", argv[0]);
156 return 1;
157 }
158 @autoreleasepool {
159 OverrideClient *client = [OverrideClient new];
160 client.currentHash = [NSString stringWithUTF8String:argv[1]];
161 client.opaqueHash = [NSString stringWithUTF8String:argv[2]];
162 client.bundleID = [NSString stringWithUTF8String:argv[3]];
163 client.bundleVersion = [NSString stringWithUTF8String:argv[4]];
164 [client sendQuery];
165 [[NSRunLoop currentRunLoop] run];
166 }
167 return 0;
168 }