2 * Copyright (c) 2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 #import <Foundation/Foundation.h>
24 #import <CrashReporterSupport/CrashReporterSupportPrivate.h>
25 #import <sys/utsname.h>
27 static bool useInternalServer() {
29 return ((uname(&name) == 0 && strstr(name.version, "DEVELOPMENT") != NULL)
30 && access("/var/db/gkoverride_use_internal", F_OK) == 0);
33 @interface OverrideClient : NSObject<NSURLConnectionDelegate> {
35 NSMutableData *buffer;
36 NSURLConnection *connection;
39 @property NSString *currentHash;
40 @property NSString *opaqueHash;
41 @property NSString *bundleID;
42 @property NSString *bundleVersion;
43 - (NSString *)serverHost;
49 @implementation OverrideClient
51 - (NSString *)serverHost {
52 if (useInternalServer())
53 return @"gkq-stg.siri.apple.com";
55 return @"gkq.apple.com";
61 buffer = [NSMutableData new];
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];
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];
90 - (BOOL)connection:(NSURLConnection *)conn canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
91 SecTrustRef trust = [protectionSpace serverTrust];
93 SecTrustResultType trustResult;
94 SecTrustEvaluate(trust, &trustResult);
95 if (trustResult != kSecTrustResultProceed && trustResult != kSecTrustResultUnspecified) {
100 // allow if server presented an EV cert
101 NSDictionary *result = CFBridgingRelease(SecTrustCopyResult(trust));
103 NSNumber *ev = [result objectForKey:(__bridge id)kSecTrustExtendedValidation];
104 if (ev != NULL && [ev boolValue] == YES) {
108 // allow if using internal server (EV not required)
109 if (useInternalServer())
117 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
118 [buffer appendData:data];
119 if ([buffer length] > 100)
123 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
125 NSString *verdict = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
126 if ([verdict isEqualToString:@"allow"]) {
129 } else if (CRIsAutoSubmitEnabled()) { // "Send diagnostic & usage data to Apple" checked
133 [self abort]; // report sent
137 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
153 int main(int argc, const char * argv[]) {
155 fprintf(stderr, "usage: %s <current> <opaque> <bundleid> <version>\n", argv[0]);
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]];
165 [[NSRunLoop currentRunLoop] run];