Permalink
Browse files

Add optional SSL certificate pinning

  • Loading branch information...
1 parent a146a3b commit 07c9f6c35861de64c3ae4ecb8a5aadd568db06cd @dstnbrkr dstnbrkr committed with mattt Dec 22, 2012
Showing with 37 additions and 0 deletions.
  1. +37 −0 AFNetworking/AFURLConnectionOperation.m
@@ -173,6 +173,24 @@ + (NSThread *)networkRequestThread {
return _networkRequestThread;
}
++ (NSArray *)pinnedCertificates {
+ static NSArray *_pinnedCertificates = nil;
+ static dispatch_once_t oncePredicate;
+
+ dispatch_once(&oncePredicate, ^{
+ NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+ NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
+ NSMutableArray *certificates = [NSMutableArray array];
+ for (NSString *path in paths) {
+ NSData *certificateData = [NSData dataWithContentsOfFile:path];
+ [certificates addObject:certificateData];
+ }
+ _pinnedCertificates = [[NSArray alloc] initWithArray:certificates];
+ });
+
+ return _pinnedCertificates;
+}
+
- (id)initWithRequest:(NSURLRequest *)urlRequest {
self = [super init];
if (!self) {
@@ -467,6 +485,25 @@ - (void)cancelConnection {
#pragma mark - NSURLConnectionDelegate
+#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
+-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
+ SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
+ SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
+ NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
+
+ NSArray *pinnedCertificates = [[self class] pinnedCertificates];
+ if ([pinnedCertificates containsObject:remoteCertificateData]) {
+ NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
+ [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
+ } else {
+ [[challenge sender] cancelAuthenticationChallenge:challenge];
@0xced
0xced Dec 26, 2012 Collaborator

Why use cancelAuthenticationChallenge: and not performDefaultHandlingForAuthenticationChallenge: or rejectProtectionSpaceAndContinueWithChallenge: instead?

@dstnbrkr
dstnbrkr Dec 26, 2012 Contributor

The intent is for the check to be more strict than the default system check, so authentication should fail outright if the server certificate doesn't match the bundled certificate.

In the case of a compromised CA this check would fail but performDefaultHandlingForAuthenticationChallenge: would allow it to fall back to the system check, which would pass - because the system only checks for a trusted CA.

+ }
+ }
+}
+#endif
+
- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{

0 comments on commit 07c9f6c

Please sign in to comment.