From 25e4f48b144eae82a3a38d91c9edfd2666e9e5f3 Mon Sep 17 00:00:00 2001 From: Joerg Platte Date: Mon, 29 Oct 2012 17:29:25 +0100 Subject: [PATCH] https support --- Classes/BuschJaegerConfiguration.h | 6 +- Classes/BuschJaegerConfiguration.m | 144 +++++++++++++++++++--- Classes/BuschJaegerHistoryDetailsView.xib | 22 ++-- Classes/BuschJaegerSettingsView.m | 7 ++ Classes/LinphoneUI/UIRemoteImageView.h | 2 +- Classes/LinphoneUI/UIRemoteImageView.m | 18 ++- 6 files changed, 168 insertions(+), 31 deletions(-) diff --git a/Classes/BuschJaegerConfiguration.h b/Classes/BuschJaegerConfiguration.h index 06b855ab4..7d20c40c6 100644 --- a/Classes/BuschJaegerConfiguration.h +++ b/Classes/BuschJaegerConfiguration.h @@ -45,7 +45,7 @@ typedef enum _BuschJaegerConfigurationRequestType{ @property (readonly) NSMutableSet *outdoorStations; @property (readonly) Network *network; @property (readonly) LevelPushButton *levelPushButton; -@property (readonly) CFArrayRef certificates; +@property (readonly) SecCertificateRef certificate; - (void)reset; @@ -62,6 +62,10 @@ typedef enum _BuschJaegerConfigurationRequestType{ - (NSString*)getGateway:(BuschJaegerConfigurationRequestType)type; +- (BOOL)canHandleAuthChallenge : (NSURLConnection*)connection : (NSURLProtectionSpace*)protectionSpace; + +- (void)handleAuthChallenge:(NSURLConnection*)conn : (NSURLAuthenticationChallenge*)challenge; + + (NSString*)getRegexValue:(NSString*)regexString data:(NSString*)data; @end diff --git a/Classes/BuschJaegerConfiguration.m b/Classes/BuschJaegerConfiguration.m index 14c7c1ea1..0450ff7ce 100644 --- a/Classes/BuschJaegerConfiguration.m +++ b/Classes/BuschJaegerConfiguration.m @@ -29,7 +29,7 @@ @synthesize network; @synthesize history; @synthesize levelPushButton; -@synthesize certificates; +@synthesize certificate; /******** [outdoorstation_0] @@ -96,7 +96,7 @@ history = [[NSMutableSet alloc] init]; network = [[Network alloc] init]; levelPushButton = [[LevelPushButton alloc] init]; - certificates = NULL; + certificate = NULL; [self reloadCertificates]; } return self; @@ -108,8 +108,8 @@ [history release]; [network release]; [levelPushButton release]; - if(certificates != NULL) { - CFRelease(certificates); + if(certificate != NULL) { + CFRelease(certificate); } [super dealloc]; } @@ -201,7 +201,7 @@ NSURL *derUrl = [NSURL URLWithString:network.derCertificate]; if(pemUrl != nil && derUrl != nil) { NSURLRequest *pemRequest = [NSURLRequest requestWithURL:pemUrl cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5]; - NSURLRequest *derRequest = [NSURLRequest requestWithURL:pemUrl cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5]; + NSURLRequest *derRequest = [NSURLRequest requestWithURL:derUrl cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5]; if(pemRequest != nil && derRequest != nil) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) { NSURLResponse *response = nil; @@ -286,16 +286,14 @@ - (void)loadCertificates { - if(certificates != NULL) { - CFRelease(certificates); - certificates = NULL; + if(certificate != NULL) { + CFRelease(certificate); + certificate = NULL; } NSData *data = [NSData dataWithContentsOfFile:[LinphoneManager documentFile:kLinphoneDERPath]]; if(data != NULL) { - SecCertificateRef rootcert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)data); - if(rootcert) { - const void *certs[] = { rootcert }; - certificates = CFArrayCreate(NULL, (const void**)certs, sizeof(certs) / sizeof(certs[0]), &kCFTypeArrayCallBacks); + certificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)data); + if(certificate) { [LinphoneLogger log:LinphoneLoggerLog format:@"Certificates loaded"]; } else { [LinphoneLogger log:LinphoneLoggerError format:@"Can't load certificates"]; @@ -406,9 +404,14 @@ - (BOOL)loadHistory:(BuschJaegerConfigurationRequestType)type delegate:(id)delegate { [history removeAllObjects]; - NSString *url = (type == BuschJaegerConfigurationRequestType_Local)? network.localHistory: network.globalHistory; + + NSString *domain = (type == BuschJaegerConfigurationRequestType_Local)? network.localHistory: network.globalHistory; + domain = [self addUserNameAndPasswordToUrl:domain]; + NSString* url = [NSString stringWithFormat:@"%@", domain]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5]; if(request != nil) { + //[NSURLConnection connectionWithRequest:request delegate:self]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) { NSURLResponse *response = nil; NSError *error = nil; @@ -440,6 +443,89 @@ return FALSE; } +- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace +{ + return [self canHandleAuthChallenge:connection:protectionSpace]; +} +- (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + [self handleAuthChallenge:conn:challenge]; +} +- (BOOL)canHandleAuthChallenge:(NSURLConnection*)connection : (NSURLProtectionSpace*)protectionSpace +{ + return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; +} +- (void)handleAuthChallenge:(NSURLConnection*)conn : (NSURLAuthenticationChallenge*)challenge +{ + OSStatus err; + SecCertificateRef cert = [self certificate]; + NSURLProtectionSpace* protectionSpace = [challenge protectionSpace]; + SecTrustRef trust = [protectionSpace serverTrust]; + + + // recreate trust since our hostname does not match the hostname in the certifcate + SecTrustRef newTrust; + SecPolicyRef newSecPolicy = SecPolicyCreateSSL(false, nil); + if (!newSecPolicy) + { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + return; + } + + NSMutableArray* certificates = [NSMutableArray array]; + + CFIndex certCount = SecTrustGetCertificateCount(trust); + CFIndex certIndex; + for (certIndex = 0; certIndex < certCount; certIndex++) + { + SecCertificateRef thisCertificate; + thisCertificate = SecTrustGetCertificateAtIndex(trust, certIndex); + [certificates addObject:(id)thisCertificate]; + } + err = SecTrustCreateWithCertificates((CFArrayRef) certificates, + newSecPolicy, + &newTrust + ); + + if (err != errSecSuccess) + { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + return; + } + + // setup our .der certificate as anchor certificate + NSArray * arr = [NSArray arrayWithObject:(id)cert]; + err = SecTrustSetAnchorCertificates(newTrust, (CFArrayRef)arr); + if (err != errSecSuccess) + { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + return; + } + SecTrustSetAnchorCertificatesOnly(newTrust, YES); + + // FINALLY: check the certificates! + SecTrustResultType trustResult; + err = SecTrustEvaluate(newTrust, &trustResult); + BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified)); + + NSURLCredential* credential = nil; + if (trusted) + { + credential = [NSURLCredential credentialForTrust:trust]; + } + + if (credential == nil) + { + [[challenge sender] cancelAuthenticationChallenge:challenge]; + } + else + { + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + } + +} + + - (BOOL)removeHistory:(BuschJaegerConfigurationRequestType)type history:(History*)ahistory delegate:(id)delegate { NSString *url = [NSString stringWithFormat:@"%@/adduser.cgi?type=delhistory&id=%d", [self getGateway:type], ahistory.ID]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5]; @@ -471,18 +557,44 @@ return FALSE; } +- (NSString*)addUserNameAndPasswordToUrl:(NSString*)url +{ + NSString *username = [[NSUserDefaults standardUserDefaults] stringForKey:@"username_preference"]; + NSString *password = [[NSUserDefaults standardUserDefaults] stringForKey:@"password_preference"]; + + // add username and password + NSString* domain; + NSString* proto; + NSRange range = [url rangeOfString:@"https"]; + if (range.location == 0) + { + proto = @"https://"; + domain = [url substringFromIndex:8]; + } + else + { + proto = @"http://"; + domain = [url substringFromIndex:7]; + } + + return [NSString stringWithFormat:@"%@%@:%@@%@", proto, username, password, domain]; +} - (NSString*)getGateway:(BuschJaegerConfigurationRequestType)type { NSString *gateway = nil; NSString *urlString = (type == BuschJaegerConfigurationRequestType_Local)? network.localHistory: network.globalHistory; + NSURL *url = [NSURL URLWithString:urlString]; NSRange range = [urlString rangeOfString:[url relativePath]]; if(range.location != NSNotFound) { gateway = [urlString substringToIndex:range.location]; } + + gateway= [self addUserNameAndPasswordToUrl:gateway]; return gateway; } + - (NSString*)getImageUrl:(BuschJaegerConfigurationRequestType)type image:(NSString *)image { return [NSString stringWithFormat:@"%@/%@", [self getGateway:type], image]; } @@ -502,7 +614,7 @@ #pragma mark - NSURLConnectionDelegate Function - +/* - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } @@ -510,7 +622,7 @@ - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { SecTrustRef trust = [challenge.protectionSpace serverTrust]; - NSArray *anchors = (NSArray*)certificates; + SecCertificateRef cert = (NSArray*)certificate; if(anchors == nil) { anchors = [NSArray array]; } @@ -530,6 +642,6 @@ } else { [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; } -} +}*/ @end diff --git a/Classes/BuschJaegerHistoryDetailsView.xib b/Classes/BuschJaegerHistoryDetailsView.xib index ac8f886a6..8b9058df3 100644 --- a/Classes/BuschJaegerHistoryDetailsView.xib +++ b/Classes/BuschJaegerHistoryDetailsView.xib @@ -1,14 +1,14 @@ - 1296 - 11E53 - 2549 - 1138.47 - 569.00 + 1536 + 12C60 + 2843 + 1187.34 + 625.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1498 + 1929 IBProxyObject @@ -400,7 +400,7 @@ NSArray - NO + YES 31 @@ -410,7 +410,7 @@ NSArray - NO + YES 25 @@ -420,7 +420,7 @@ NSArray - NO + YES 30 @@ -716,7 +716,7 @@ IBCocoaTouchFramework com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - + YES 3 @@ -724,6 +724,6 @@ {34, 35} {26, 26} - 1498 + 1929 diff --git a/Classes/BuschJaegerSettingsView.m b/Classes/BuschJaegerSettingsView.m index 173c436d8..61f4abd72 100644 --- a/Classes/BuschJaegerSettingsView.m +++ b/Classes/BuschJaegerSettingsView.m @@ -105,6 +105,13 @@ #pragma mark - - (void)setConfiguration:(NSString*)address username:(NSString*)username password:(NSString*)password { + + NSRange range = [address rangeOfString:@"http://"]; + if (range.location == NSNotFound) + { + address = [@"http://" stringByAppendingString:address]; + } + NSString *dataString = [NSString stringWithFormat:@"URL=%@/config.ini USER=%@ PW=%@", address, username, password]; if([[[LinphoneManager instance] configuration] parseQRCode:dataString delegate:self]) { [waitView setHidden:FALSE]; diff --git a/Classes/LinphoneUI/UIRemoteImageView.h b/Classes/LinphoneUI/UIRemoteImageView.h index bfc0e46f6..a2190af67 100644 --- a/Classes/LinphoneUI/UIRemoteImageView.h +++ b/Classes/LinphoneUI/UIRemoteImageView.h @@ -20,7 +20,7 @@ #import -@interface UIRemoteImageView : UIImageView +@interface UIRemoteImageView : UIImageView @property (retain) UIActivityIndicatorView *waitIndicatorView; diff --git a/Classes/LinphoneUI/UIRemoteImageView.m b/Classes/LinphoneUI/UIRemoteImageView.m index e74168140..568cd52dd 100644 --- a/Classes/LinphoneUI/UIRemoteImageView.m +++ b/Classes/LinphoneUI/UIRemoteImageView.m @@ -18,6 +18,9 @@ */ #import "UIRemoteImageView.h" +#import "BuschJaegerConfiguration.h" +#import "LinphoneManager.h" +#import "NSURLConnection+SynchronousDelegate.h" @implementation UIRemoteImageView @@ -90,7 +93,9 @@ NSURLResponse *response = nil; NSError *error = nil; NSData *data = nil; - data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; + + + data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error delegate:self]; if(data != nil) { UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -106,5 +111,14 @@ } } - +- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace +{ + BuschJaegerConfiguration* conf = [[LinphoneManager instance] configuration]; + return [conf canHandleAuthChallenge:connection:protectionSpace]; +} +- (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + BuschJaegerConfiguration* conf = [[LinphoneManager instance] configuration]; + [conf handleAuthChallenge:conn:challenge]; +} @end