From 9ba8dea6a0c846f48dfdaaa6b8fe205eddd0c790 Mon Sep 17 00:00:00 2001 From: Kaidul Islam Date: Sun, 14 Dec 2014 19:40:28 +0600 Subject: [PATCH] CA-signed certificate verification added --- Classes/ASIHTTPRequest.h | 6 ++++ Classes/ASIHTTPRequest.m | 66 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/Classes/ASIHTTPRequest.h b/Classes/ASIHTTPRequest.h index 31582b23..5eacaccc 100644 --- a/Classes/ASIHTTPRequest.h +++ b/Classes/ASIHTTPRequest.h @@ -175,6 +175,9 @@ typedef void (^ASIDataBlock)(NSData *data); NSOutputStream *inflatedFileDownloadOutputStream; + // True if the certificate verification is done + BOOL certificateVerified; + // When the request fails or completes successfully, complete will be true BOOL complete; @@ -703,6 +706,8 @@ typedef void (^ASIDataBlock)(NSData *data); - (BOOL)showProxyAuthenticationDialog; - (BOOL)showAuthenticationDialog; +- (BOOL) VerifyCertificate; + // Construct a basic authentication header from the username and password supplied, and add it to the request headers // Used when shouldPresentCredentialsBeforeChallenge is YES - (void)addBasicAuthenticationHeaderWithUsername:(NSString *)theUsername andPassword:(NSString *)thePassword; @@ -934,6 +939,7 @@ typedef void (^ASIDataBlock)(NSData *data); @property (atomic, retain,readonly) NSString *authenticationRealm; @property (atomic, retain,readonly) NSString *proxyAuthenticationRealm; @property (atomic, retain) NSError *error; +@property (atomic, assign) BOOL certificateVerified; @property (atomic, assign,readonly) BOOL complete; @property (atomic, retain) NSDictionary *responseHeaders; @property (atomic, retain) NSMutableDictionary *requestHeaders; diff --git a/Classes/ASIHTTPRequest.m b/Classes/ASIHTTPRequest.m index cb6bbeea..295c3b15 100644 --- a/Classes/ASIHTTPRequest.m +++ b/Classes/ASIHTTPRequest.m @@ -1153,7 +1153,7 @@ - (void)startRequest if ([self lastBytesSent] > 0) { [self removeUploadProgressSoFar]; } - + [self setCertificateVerified:NO]; [self setLastBytesSent:0]; [self setContentLength:0]; [self setResponseHeaders:nil]; @@ -1219,13 +1219,26 @@ - (void)startRequest [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot, [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain, kCFNull,kCFStreamSSLPeerName, + @"kCFStreamSocketSecurityLevelTLSv1_0SSLv3", kCFStreamSSLLevel, nil]; CFReadStreamSetProperty((CFReadStreamRef)[self readStream], kCFStreamPropertySSLSettings, (CFTypeRef)sslProperties); [sslProperties release]; - } + } else { ++ NSDictionary *sslProperties = [[NSDictionary alloc] initWithObjectsAndKeys: ++ [NSNumber numberWithBool:NO], kCFStreamSSLAllowsExpiredCertificates, ++ [NSNumber numberWithBool:NO], kCFStreamSSLAllowsAnyRoot, ++ [NSNumber numberWithBool:YES], kCFStreamSSLValidatesCertificateChain, ++ @"kCFStreamSocketSecurityLevelTLSv1_0SSLv3", kCFStreamSSLLevel, ++ nil]; ++ ++ CFReadStreamSetProperty((CFReadStreamRef)[self readStream], ++ kCFStreamPropertySSLSettings, ++ (CFTypeRef)sslProperties); ++ [sslProperties release]; ++ } // Tell CFNetwork to use a client certificate if (clientCertificateIdentity) { @@ -3243,8 +3256,56 @@ - (BOOL)willAskDelegateToConfirmRedirect return false; } +-(BOOL) VerifyCertificate +{ + NSData *trustedCertData = nil; + BOOL result = NO; + SecTrustRef trustRef = NULL; + + NSString *root_certificate_name = @"philips_trusted_cert"; + NSString *root_certificate_extension = @"der"; + + /** Reading root cetificate **/ + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + trustedCertData = [NSData dataWithContentsOfFile:[bundle pathForResource: root_certificate_name ofType: root_certificate_extension]]; + NS_ASSERT(trustedCertData != nil, @"trustedCertData failed."); + + /** Reading server cetificate **/ + trustRef = (__bridge SecTrustRef)[readStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust]; + NS_ASSERT(trustRef != NULL, @"Could not create a trust management object!"); + + /* Check which certificate is identical to root certificate */ + NSInteger numCerts = SecTrustGetCertificateCount(trustRef); + for (NSInteger i = 0; i < numCerts; i++) { + SecCertificateRef secCertRef = SecTrustGetCertificateAtIndex(trustRef, i); + NSData *certData = CFBridgingRelease(SecCertificateCopyData(secCertRef)); + if ([trustedCertData isEqualToData: certData]) { + result = YES; + break; + } + } + + if (!result) { + [self cancelLoad]; + [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIConnectionFailureErrorType + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Certificate verification failed"], NSLocalizedDescriptionKey,nil]]]; + } + + return result; +} + - (void)handleBytesAvailable { + if(![self certificateVerified]) { + [self setCertificateVerified:YES]; + if([self VerifyCertificate]) { + NSLog(@"Certificate Verification Success."); + } else + { + NSLog(@"Certificate Verification Failed."); + return; + } + } if (![self responseHeaders]) { [self readResponseHeaders]; } @@ -5037,6 +5098,7 @@ - (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock @synthesize didReceiveDataSelector; @synthesize authenticationRealm; @synthesize proxyAuthenticationRealm; +@synthesize certificateVerified; @synthesize error; @synthesize complete; @synthesize requestHeaders;