From a2883dddc054cb30c7c853867078c0968b0f0006 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 20 Apr 2015 14:28:32 -0500 Subject: [PATCH 1/7] #1306 - Adding api_mapbox_com.der (public key) and nsurlconnection checking infrastructure --- common/api_mapbox_com.der | Bin 0 -> 1969 bytes gyp/certificates.gypi | 2 +- include/mbgl/ios/MGLMapboxEvents.h | 2 +- platform/ios/MGLMapboxEvents.m | 56 +++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 common/api_mapbox_com.der diff --git a/common/api_mapbox_com.der b/common/api_mapbox_com.der new file mode 100644 index 0000000000000000000000000000000000000000..116144bc0ccb71925a4354b5bb2d98f98d8ef35c GIT binary patch literal 1969 zcmXqLVqa^}#5Q#SGZP~dlYm;9_(>P`_E=qm_4##0|2`VlPTyrC1Q%h6JD1#;k_O_)f=nVDE~z<*<%vb9hO!3IAY1u`MFNU4%Mwdc75t0R6Z0~w5=%1k^9%(H z_(0OE!tAC-=Ei2mhNNpi@jTQz4iOQT%;J)w%;XY<{4@pU{G8Iw(s>i*SV} z7H4GUrI!HRAZj2C4lofO-^7BX{0bdNc!?W`g2PLMFR>s~FBdGOmz>Ac;zIX!Ndl2eb6q{;Wf zi>l8mE^(M1S*afN>s0moTlqmiQ>WRvnq|GTs}u#4{7Orl{V$r z2b+ZHo@*Yx$v>@?emnC2T$5>6Ta2>}?XFw8vgtf|mvX7?`ULYug65o(e-5}dSZ~!jbl@n^L{dqgc0Gb01z;wI*+22IQt4H{1ZLs3?crSYIaY>J2lRy%NNHT^<3c3g%swv=HCM(Rs zWWWGUwzB+;jQ?3!n3-4?7-)lhDbJ!}pk$!1KyHCdn^ZsSu?AbVgd{$O=CPp!1kTJzTbIQxh z_0m)GOF$VKY*tZfaeir0a%!=DQEEYcab`(=QKf!PYIE zH9(CqU~Cgc4Vn~iu2O?5V8Ro2CBR%(%fi`&~ zVz9OD2Chts41awmnan%JuCRKi|Ac?1Ip&$(#SLHYnatN!EU*&fd*g&$^Z{!hVA03OaQxqqIlq@) zshf45>20;I%+;$qKF93pF`MKh=(hAhE_>tG*q2;lKa*CR4KOjVf$NrXKa&-*7OSInh>C1}v$L&Qm)CQSr}Kf-XLsDzPM5xOB_MoC zs>CZjAOEc^cM}A39O4R3-Chx-wQEr;M_q&QmV%qsUnkpTFdlG@ntN5M`^wTX_wY$S z%6G0(DDFw@bvACvIIG-yLxoAxa>u-;l{JY;&NYSqIJDf{^<6`*wYOa4iPAdaayRet ztNi`_6ZUJSpUPiUf9PA+tHSyPyCb;8C-X#pKC=AogPe{xd#0RkF|Ay2R?PlzkN=A~ Hi>?9yu%5e9 literal 0 HcmV?d00001 diff --git a/gyp/certificates.gypi b/gyp/certificates.gypi index 1d0c2acf8..fdd818b8d 100644 --- a/gyp/certificates.gypi +++ b/gyp/certificates.gypi @@ -4,7 +4,7 @@ 'type': 'none', 'hard_dependency': 1, 'copies': [{ - 'files': [ '../common/ca-bundle.crt' ], + 'files': [ '../common/api_mapbox_com.der', '../common/ca-bundle.crt' ], 'destination': '<(PRODUCT_DIR)' }], }, diff --git a/include/mbgl/ios/MGLMapboxEvents.h b/include/mbgl/ios/MGLMapboxEvents.h index b68b9b1b3..2c6f8151b 100644 --- a/include/mbgl/ios/MGLMapboxEvents.h +++ b/include/mbgl/ios/MGLMapboxEvents.h @@ -25,7 +25,7 @@ extern NSString *const MGLEventGesturePanStart; extern NSString *const MGLEventGesturePinchStart; extern NSString *const MGLEventGestureRotateStart; -@interface MGLMapboxEvents : NSObject +@interface MGLMapboxEvents : NSObject // You must call these methods from the main thread. // diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index e4014d494..62d4d73fb 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -395,9 +395,12 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; [request setHTTPBody:jsonData]; // Send non blocking HTTP Request to server - [NSURLConnection sendAsynchronousRequest:request - queue:nil - completionHandler:nil]; + NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:weakSelf]; + [conn start]; + +// [NSURLConnection sendAsynchronousRequest:request +// queue:nil +// completionHandler:nil]; } }); } @@ -638,4 +641,51 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; return result; } +#pragma mark NSURLConnectionDelegate +- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { + + // Load Local Copy of Server's Public Key + // NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"b.ssl.fastly.net" ofType:@"der"]; + NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; + NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; + + // Get Server's Public Key + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + + SecTrustResultType trustResult; + SecTrustEvaluate(serverTrust, &trustResult); + switch (trustResult) { + case kSecTrustResultProceed: + break; + case kSecTrustResultConfirm: + break; + case kSecTrustResultUnspecified: + break; + default: + [[challenge sender] cancelAuthenticationChallenge:challenge]; + return; + } + + long numKeys = SecTrustGetCertificateCount(serverTrust); + NSLog(@"Number of certificaties presented: %ld", numKeys); + + BOOL found = false; + for (int lc = 0; lc < numKeys; lc++) { + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc); + NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); + + // Compare Remote Key With Local Version + if ([remoteCertificateData isEqualToData:localCertData]) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + found = true; + break; + } + } + + if (!found) { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + } +} + @end From fbd610695a9be3248533c0c8130069209aa58994 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 20 Apr 2015 14:55:39 -0500 Subject: [PATCH 2/7] #1306 - Trying strongSelf / weakSelf pattern for delegate --- platform/ios/MGLMapboxEvents.m | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 62d4d73fb..67108bff4 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -382,10 +382,13 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; __weak MGLMapboxEvents *weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + MGLMapboxEvents *strongSelf = weakSelf; + if (!strongSelf) return; + // Setup URL Request - NSString *url = [NSString stringWithFormat:@"%@/events/v1?access_token=%@", MGLMapboxEventsAPIBase, weakSelf.token]; + NSString *url = [NSString stringWithFormat:@"%@/events/v1?access_token=%@", MGLMapboxEventsAPIBase, strongSelf.token]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]]; - [request setValue:[weakSelf getUserAgent] forHTTPHeaderField:@"User-Agent"]; + [request setValue:[strongSelf getUserAgent] forHTTPHeaderField:@"User-Agent"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPMethod:@"POST"]; @@ -395,7 +398,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; [request setHTTPBody:jsonData]; // Send non blocking HTTP Request to server - NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:weakSelf]; + NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:strongSelf]; [conn start]; // [NSURLConnection sendAsynchronousRequest:request From 96a6371fa006b908ef70123b6c632f9b0ad47eb2 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 20 Apr 2015 18:56:42 -0500 Subject: [PATCH 3/7] #1306 - Explicitly scheduling NSURLConnections in mainRunLoop so that delegates and connections stay connected. --- platform/ios/MGLMapboxEvents.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 67108bff4..e4b422fe8 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -398,8 +398,9 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; [request setHTTPBody:jsonData]; // Send non blocking HTTP Request to server - NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:strongSelf]; - [conn start]; + NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:strongSelf startImmediately:NO]; + [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + [connection start]; // [NSURLConnection sendAsynchronousRequest:request // queue:nil From 6f9bcd86af506cd8774eac1c1380e9b50eb72947 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 20 Apr 2015 19:47:24 -0500 Subject: [PATCH 4/7] #1306 - Moving api_mapbox_com.der to iOS Resources directory so that it can be accessed via GL Framework --- gyp/certificates.gypi | 2 +- platform/ios/MGLMapboxEvents.m | 18 +++++++++++++++--- .../ios/resources}/api_mapbox_com.der | Bin 3 files changed, 16 insertions(+), 4 deletions(-) rename {common => platform/ios/resources}/api_mapbox_com.der (100%) diff --git a/gyp/certificates.gypi b/gyp/certificates.gypi index fdd818b8d..1d0c2acf8 100644 --- a/gyp/certificates.gypi +++ b/gyp/certificates.gypi @@ -4,7 +4,7 @@ 'type': 'none', 'hard_dependency': 1, 'copies': [{ - 'files': [ '../common/api_mapbox_com.der', '../common/ca-bundle.crt' ], + 'files': [ '../common/ca-bundle.crt' ], 'destination': '<(PRODUCT_DIR)' }], }, diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index e4b422fe8..90cddba45 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -649,8 +649,21 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { // Load Local Copy of Server's Public Key - // NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"b.ssl.fastly.net" ofType:@"der"]; - NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; + NSString *cerPath = nil; + NSArray *bundles = [NSBundle allFrameworks]; + for (int lc = 0; lc < bundles.count; lc++) { + NSBundle *b = [bundles objectAtIndex:lc]; + cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; + if (cerPath != nil) { + break; + } + } + if (cerPath == nil) { + NSLog(@"cerPath not found."); + return; + } + +// NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; // Get Server's Public Key @@ -671,7 +684,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; } long numKeys = SecTrustGetCertificateCount(serverTrust); - NSLog(@"Number of certificaties presented: %ld", numKeys); BOOL found = false; for (int lc = 0; lc < numKeys; lc++) { diff --git a/common/api_mapbox_com.der b/platform/ios/resources/api_mapbox_com.der similarity index 100% rename from common/api_mapbox_com.der rename to platform/ios/resources/api_mapbox_com.der From 736bdca81e44cc988dfe659ef1e2e26866f9fa42 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 20 Apr 2015 19:59:28 -0500 Subject: [PATCH 5/7] #1306 - Renaming certificate to include geotrust name for easier tracking --- platform/ios/MGLMapboxEvents.m | 7 +------ ...i_mapbox_com.der => api_mapbox_com-geotrust.der} | Bin 2 files changed, 1 insertion(+), 6 deletions(-) rename platform/ios/resources/{api_mapbox_com.der => api_mapbox_com-geotrust.der} (100%) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 90cddba45..b9a138268 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -401,10 +401,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:strongSelf startImmediately:NO]; [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; [connection start]; - -// [NSURLConnection sendAsynchronousRequest:request -// queue:nil -// completionHandler:nil]; } }); } @@ -653,7 +649,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; NSArray *bundles = [NSBundle allFrameworks]; for (int lc = 0; lc < bundles.count; lc++) { NSBundle *b = [bundles objectAtIndex:lc]; - cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; + cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com-geotrust" ofType:@"der"]; if (cerPath != nil) { break; } @@ -663,7 +659,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; return; } -// NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com" ofType:@"der"]; NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; // Get Server's Public Key diff --git a/platform/ios/resources/api_mapbox_com.der b/platform/ios/resources/api_mapbox_com-geotrust.der similarity index 100% rename from platform/ios/resources/api_mapbox_com.der rename to platform/ios/resources/api_mapbox_com-geotrust.der From a9512295916b8ea70cbd7b5c6cb609f9ec96c82d Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 21 Apr 2015 11:09:22 -0500 Subject: [PATCH 6/7] #1306 - Moving local geoTrustCert to one time setup and cache in immutable NSData object --- platform/ios/MGLMapboxEvents.m | 37 ++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index b9a138268..b4148d067 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -73,6 +73,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; @property (atomic) NSUInteger flushAt; @property (atomic) NSDateFormatter *rfc3339DateFormatter; @property (atomic) CGFloat scale; +@property (atomic) NSData *geoTrustCert; // The isPaused state tracker is only ever accessed from the main thread. @@ -132,11 +133,29 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; _serialQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@.%@.events.serial", _appBundleId, uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL); // Configure Events Infrastructure + // =============================== + + // Load Local Copy of Server's Public Key + NSString *cerPath = nil; + NSArray *bundles = [NSBundle allFrameworks]; + for (int lc = 0; lc < bundles.count; lc++) { + NSBundle *b = [bundles objectAtIndex:lc]; + cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com-geotrust" ofType:@"der"]; + if (cerPath != nil) { + break; + } + } + if (cerPath != nil) { + _geoTrustCert = [NSData dataWithContentsOfFile:cerPath]; + } + + // Events Control _eventQueue = [[NSMutableArray alloc] init]; _flushAt = 20; _flushAfter = 60; _token = nil; _instanceID = [[NSUUID UUID] UUIDString]; + // Dynamic detection of ASIdentifierManager from Mixpanel // https://github.com/mixpanel/mixpanel-iphone/blob/master/LICENSE _advertiserId = @""; @@ -644,23 +663,11 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; #pragma mark NSURLConnectionDelegate - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { - // Load Local Copy of Server's Public Key - NSString *cerPath = nil; - NSArray *bundles = [NSBundle allFrameworks]; - for (int lc = 0; lc < bundles.count; lc++) { - NSBundle *b = [bundles objectAtIndex:lc]; - cerPath = [[NSBundle mainBundle] pathForResource:@"api_mapbox_com-geotrust" ofType:@"der"]; - if (cerPath != nil) { - break; - } - } - if (cerPath == nil) { - NSLog(@"cerPath not found."); + if (_geoTrustCert == nil) { + [[challenge sender] cancelAuthenticationChallenge:challenge]; return; } - NSData *localCertData = [NSData dataWithContentsOfFile:cerPath]; - // Get Server's Public Key SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; @@ -686,7 +693,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); // Compare Remote Key With Local Version - if ([remoteCertificateData isEqualToData:localCertData]) { + if ([remoteCertificateData isEqualToData:_geoTrustCert]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; found = true; From d4add0bfdb9932ac5030c0fcf76383a1ba5673d0 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 21 Apr 2015 11:15:31 -0500 Subject: [PATCH 7/7] #1306 - Removing kSecTrustResultConfirm as it's deprecated --- platform/ios/MGLMapboxEvents.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index b4148d067..4b010463d 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -676,8 +676,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; switch (trustResult) { case kSecTrustResultProceed: break; - case kSecTrustResultConfirm: - break; case kSecTrustResultUnspecified: break; default: