]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_codesigning/lib/gkoverride.m
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_codesigning / lib / gkoverride.m
diff --git a/Security/libsecurity_codesigning/lib/gkoverride.m b/Security/libsecurity_codesigning/lib/gkoverride.m
new file mode 100644 (file)
index 0000000..47a7066
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#import <Foundation/Foundation.h>
+#import <CrashReporterSupport/CrashReporterSupportPrivate.h>
+#import <sys/utsname.h>
+
+static bool useInternalServer() {
+       struct utsname name;
+       return ((uname(&name) == 0 && strstr(name.version, "DEVELOPMENT") != NULL)
+               && access("/var/db/gkoverride_use_internal", F_OK) == 0);
+}
+
+@interface OverrideClient : NSObject<NSURLConnectionDelegate> {
+       BOOL allow;
+       NSMutableData *buffer;
+       NSURLConnection *connection;
+       int state;
+}
+@property NSString *currentHash;
+@property NSString *opaqueHash;
+@property NSString *bundleID;
+@property NSString *bundleVersion;
+- (NSString *)serverHost;
+- (void)sendQuery;
+- (void)sendReport;
+- (void)abort;
+@end
+
+@implementation OverrideClient
+
+- (NSString *)serverHost {
+       if (useInternalServer())
+               return @"gkq-stg.siri.apple.com";
+       else
+               return @"gkq.apple.com";
+}
+
+- (id)init {
+       self = [super init];
+       allow = NO;
+       buffer = [NSMutableData new];
+       return self;
+}
+
+- (void)sendQuery {
+       state = 1;
+       NSMutableURLRequest *request = [NSMutableURLRequest new];
+       NSString *url = [NSString stringWithFormat:@"https://%@/q/%@/%@", [self serverHost], self.currentHash, self.opaqueHash];
+       [request setURL:[NSURL URLWithString:url]];
+       [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
+       [request setTimeoutInterval:5];
+       connection = [NSURLConnection connectionWithRequest:request delegate:self];
+}
+
+- (void)sendReport {
+       state = 2;
+       NSMutableURLRequest *request = [NSMutableURLRequest new];
+       NSString *body = [NSString stringWithFormat:@"current=%@&bundleid=%@&version=%@",
+               [self.currentHash stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
+               [self.bundleID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
+               [self.bundleVersion stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+       NSString *url = [NSString stringWithFormat:@"https://%@/report", [self serverHost]];
+       [request setURL:[NSURL URLWithString:url]];
+       [request setTimeoutInterval:5];
+       [request setHTTPMethod:@"POST"];
+       [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
+       connection = [NSURLConnection connectionWithRequest:request delegate:self];
+}
+
+- (BOOL)connection:(NSURLConnection *)conn canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
+       SecTrustRef trust = [protectionSpace serverTrust];
+       // abort if untrusted
+       SecTrustResultType trustResult;
+       SecTrustEvaluate(trust, &trustResult);
+       if (trustResult != kSecTrustResultProceed && trustResult != kSecTrustResultUnspecified) {
+               [conn cancel];
+               [self abort];
+               return NO;
+       }
+       // allow if server presented an EV cert
+       NSDictionary *result = CFBridgingRelease(SecTrustCopyResult(trust));
+       if (result) {
+               NSNumber *ev = [result objectForKey:(__bridge id)kSecTrustExtendedValidation];
+               if (ev != NULL && [ev boolValue] == YES) {
+                       return NO;
+               }
+       }
+       // allow if using internal server (EV not required)
+       if (useInternalServer())
+               return NO;
+       // otherwise abort
+       [conn cancel];
+       [self abort];
+       return NO;
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
+       [buffer appendData:data];
+       if ([buffer length] > 100)
+               [self abort];
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
+       if (state == 1) {
+               NSString *verdict = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
+               if ([verdict isEqualToString:@"allow"]) {
+                       allow = YES;
+                       [self abort];
+               } else if (CRIsAutoSubmitEnabled()) {   // "Send diagnostic & usage data to Apple" checked
+                       [self sendReport];
+               }
+       } else {
+               [self abort];   // report sent
+       }
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
+       [self abort];
+}
+
+- (void)abort {
+       if (allow) {
+               printf("allow\n");
+               exit(42);
+       } else {
+               printf("deny\n");
+               exit(1);
+       }
+}
+
+@end
+
+int main(int argc, const char * argv[]) {
+       if (argc != 5) {
+               fprintf(stderr, "usage: %s <current> <opaque> <bundleid> <version>\n", argv[0]);
+               return 1;
+       }
+       @autoreleasepool {
+               OverrideClient *client = [OverrideClient new];
+               client.currentHash = [NSString stringWithUTF8String:argv[1]];
+               client.opaqueHash = [NSString stringWithUTF8String:argv[2]];
+               client.bundleID = [NSString stringWithUTF8String:argv[3]];
+               client.bundleVersion = [NSString stringWithUTF8String:argv[4]];
+               [client sendQuery];
+               [[NSRunLoop currentRunLoop] run];
+       }
+       return 0;
+}