Added validatesSecureCertificate property to turn off SSL cert validation for te…
…sting with self-signed certs
Showing
4 changed files
with
49 additions
and
2 deletions
| @@ -217,6 +217,9 @@ extern NSString* const NetworkRequestErrorDomain; | @@ -217,6 +217,9 @@ extern NSString* const NetworkRequestErrorDomain; | ||
| 217 | 217 | ||
| 218 | // When YES, requests will automatically redirect when they get a HTTP 30x header (defaults to YES) | 218 | // When YES, requests will automatically redirect when they get a HTTP 30x header (defaults to YES) |
| 219 | BOOL shouldRedirect; | 219 | BOOL shouldRedirect; |
| 220 | + | ||
| 221 | + // When NO, requests will not check the secure certificate is valid (use for self-signed cerficates during development, DO NOT USE IN PRODUCTION) Default is YES | ||
| 222 | + BOOL validatesSecureCertificate; | ||
| 220 | 223 | ||
| 221 | } | 224 | } |
| 222 | 225 | ||
| @@ -401,4 +404,5 @@ extern NSString* const NetworkRequestErrorDomain; | @@ -401,4 +404,5 @@ extern NSString* const NetworkRequestErrorDomain; | ||
| 401 | @property (assign) BOOL useHTTPVersionOne; | 404 | @property (assign) BOOL useHTTPVersionOne; |
| 402 | @property (assign, readonly) unsigned long long partialDownloadSize; | 405 | @property (assign, readonly) unsigned long long partialDownloadSize; |
| 403 | @property (assign) BOOL shouldRedirect; | 406 | @property (assign) BOOL shouldRedirect; |
| 407 | +@property (assign) BOOL validatesSecureCertificate; | ||
| 404 | @end | 408 | @end |
| @@ -97,6 +97,7 @@ static NSError *ASIUnableToCreateRequestError; | @@ -97,6 +97,7 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 97 | [self setTimeOutSeconds:10]; | 97 | [self setTimeOutSeconds:10]; |
| 98 | [self setUseSessionPersistance:YES]; | 98 | [self setUseSessionPersistance:YES]; |
| 99 | [self setUseCookiePersistance:YES]; | 99 | [self setUseCookiePersistance:YES]; |
| 100 | + [self setValidatesSecureCertificate:YES]; | ||
| 100 | [self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]]; | 101 | [self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]]; |
| 101 | [self setDidFinishSelector:@selector(requestFinished:)]; | 102 | [self setDidFinishSelector:@selector(requestFinished:)]; |
| 102 | [self setDidFailSelector:@selector(requestFailed:)]; | 103 | [self setDidFailSelector:@selector(requestFailed:)]; |
| @@ -434,6 +435,11 @@ static NSError *ASIUnableToCreateRequestError; | @@ -434,6 +435,11 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 434 | // Tell CFNetwork to automatically redirect for 30x status codes | 435 | // Tell CFNetwork to automatically redirect for 30x status codes |
| 435 | CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPShouldAutoredirect, [self shouldRedirect] ? kCFBooleanTrue : kCFBooleanFalse); | 436 | CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPShouldAutoredirect, [self shouldRedirect] ? kCFBooleanTrue : kCFBooleanFalse); |
| 436 | 437 | ||
| 438 | + // Tell CFNetwork not to validate SSL certificates | ||
| 439 | + if (!validatesSecureCertificate) { | ||
| 440 | + CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, [NSMutableDictionary dictionaryWithObject:(NSString *)kCFBooleanFalse forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]); | ||
| 441 | + } | ||
| 442 | + | ||
| 437 | // Set the client | 443 | // Set the client |
| 438 | CFStreamClientContext ctxt = {0, self, NULL, NULL, NULL}; | 444 | CFStreamClientContext ctxt = {0, self, NULL, NULL, NULL}; |
| 439 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { | 445 | if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) { |
| @@ -1350,12 +1356,28 @@ static NSError *ASIUnableToCreateRequestError; | @@ -1350,12 +1356,28 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 1350 | { | 1356 | { |
| 1351 | NSError *underlyingError = [(NSError *)CFReadStreamCopyError(readStream) autorelease]; | 1357 | NSError *underlyingError = [(NSError *)CFReadStreamCopyError(readStream) autorelease]; |
| 1352 | 1358 | ||
| 1359 | + | ||
| 1360 | + | ||
| 1353 | [self cancelLoad]; | 1361 | [self cancelLoad]; |
| 1354 | [self setComplete:YES]; | 1362 | [self setComplete:YES]; |
| 1355 | 1363 | ||
| 1356 | if (![self error]) { // We may already have handled this error | 1364 | if (![self error]) { // We may already have handled this error |
| 1357 | 1365 | ||
| 1358 | - [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIConnectionFailureErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"A connection failure occurred",NSLocalizedDescriptionKey,underlyingError,NSUnderlyingErrorKey,nil]]]; | 1366 | + |
| 1367 | + NSString *reason = @"A connection failure occurred"; | ||
| 1368 | + | ||
| 1369 | + // We'll use a custom error message for common SSL errors, but you should always check underlying error if you want more details | ||
| 1370 | + if ([[underlyingError domain] isEqualToString:NSOSStatusErrorDomain]) { | ||
| 1371 | + if ([underlyingError code] == errSSLUnknownRootCert) { | ||
| 1372 | + reason = [NSString stringWithFormat:@"%@: Secure certificate had an untrusted root",reason]; | ||
| 1373 | + } else if ([underlyingError code] == errSSLCertExpired) { | ||
| 1374 | + reason = [NSString stringWithFormat:@"%@: Secure certificate expired",reason]; | ||
| 1375 | + } else if ([underlyingError code] >= -9807 || [underlyingError code] <= -9818) { | ||
| 1376 | + reason = [NSString stringWithFormat:@"%@: SSL problem (probably a bad certificate)",reason]; | ||
| 1377 | + } | ||
| 1378 | + } | ||
| 1379 | + | ||
| 1380 | + [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIConnectionFailureErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:reason,NSLocalizedDescriptionKey,underlyingError,NSUnderlyingErrorKey,nil]]]; | ||
| 1359 | } | 1381 | } |
| 1360 | [super cancel]; | 1382 | [super cancel]; |
| 1361 | } | 1383 | } |
| @@ -1640,4 +1662,5 @@ static NSError *ASIUnableToCreateRequestError; | @@ -1640,4 +1662,5 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 1640 | @synthesize authenticationRetryCount; | 1662 | @synthesize authenticationRetryCount; |
| 1641 | @synthesize updatedProgress; | 1663 | @synthesize updatedProgress; |
| 1642 | @synthesize shouldRedirect; | 1664 | @synthesize shouldRedirect; |
| 1665 | +@synthesize validatesSecureCertificate; | ||
| 1643 | @end | 1666 | @end |
| @@ -32,5 +32,5 @@ | @@ -32,5 +32,5 @@ | ||
| 32 | - (void)testCharacterEncoding; | 32 | - (void)testCharacterEncoding; |
| 33 | - (void)testCompressedResponse; | 33 | - (void)testCompressedResponse; |
| 34 | - (void)testCompressedResponseDownloadToFile; | 34 | - (void)testCompressedResponseDownloadToFile; |
| 35 | - | 35 | +- (void)testSSL; |
| 36 | @end | 36 | @end |
| @@ -616,4 +616,24 @@ | @@ -616,4 +616,24 @@ | ||
| 616 | GHAssertTrue(success,@"Failed to correctly display increment progress for a partial download"); | 616 | GHAssertTrue(success,@"Failed to correctly display increment progress for a partial download"); |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | +- (void)testSSL | ||
| 620 | +{ | ||
| 621 | + NSURL *url = [NSURL URLWithString:@"https://selfsigned.allseeing-i.com"]; | ||
| 622 | + ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; | ||
| 623 | + [request start]; | ||
| 624 | + | ||
| 625 | + GHAssertNotNil([request error],@"Failed to generate an error for a self-signed certificate"); | ||
| 626 | + | ||
| 627 | + // Just for testing the request generated a custom error description - don't do this! You should look at the domain / code of the underlyingError in your own programs. | ||
| 628 | + BOOL success = ([[[request error] localizedDescription] isEqualToString:@"A connection failure occurred: Secure certificate had an untrusted root"]); | ||
| 629 | + GHAssertTrue(success,@"Basic synchronous request failed"); | ||
| 630 | + | ||
| 631 | + // Turn off certificate validation, and try again | ||
| 632 | + request = [ASIHTTPRequest requestWithURL:url]; | ||
| 633 | + [request setValidatesSecureCertificate:NO]; | ||
| 634 | + [request start]; | ||
| 635 | + | ||
| 636 | + GHAssertNil([request error],@"Failed to accept a self-signed certificate"); | ||
| 637 | +} | ||
| 638 | + | ||
| 619 | @end | 639 | @end |
-
Please register or login to post a comment