Adds SSLPinningMode to AFURLConnectionOperation and defaultSSLPinMode to AFHTTPClient.
This commit is contained in:
parent
121ef7afa8
commit
b1f9598ed2
4 changed files with 83 additions and 7 deletions
|
|
@ -23,6 +23,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <Availability.h>
|
||||
#import "AFURLConnectionOperation.h"
|
||||
|
||||
/**
|
||||
`AFHTTPClient` captures the common patterns of communicating with an web application over HTTP. It encapsulates information like base URL, authorization credentials, and HTTP headers, and uses them to construct and manage the execution of HTTP request operations.
|
||||
|
|
@ -137,6 +138,13 @@ typedef enum {
|
|||
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
||||
#endif
|
||||
|
||||
/**
|
||||
Default SSL pinning mode for each `AFHTTPRequestOperation` which will be enqueued with `enqueueHTTPRequestOperation:`.
|
||||
*/
|
||||
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinMode;
|
||||
#endif
|
||||
|
||||
///---------------------------------------------
|
||||
/// @name Creating and Initializing HTTP Clients
|
||||
///---------------------------------------------
|
||||
|
|
|
|||
|
|
@ -524,6 +524,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|||
#pragma mark -
|
||||
|
||||
- (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation {
|
||||
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||
operation.SSLPinningMode = self.defaultSSLPinMode;
|
||||
#endif
|
||||
|
||||
[self.operationQueue addOperation:operation];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@
|
|||
|
||||
#import <Availability.h>
|
||||
|
||||
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||
typedef enum {
|
||||
AFURLConnectionOperationSSLPinningModeCertificate = 0,
|
||||
AFURLConnectionOperationSSLPinningModePublicKey
|
||||
} AFURLConnectionOperationSSLPinningMode;
|
||||
#endif
|
||||
|
||||
/**
|
||||
`AFURLConnectionOperation` is a subclass of `NSOperation` that implements `NSURLConnection` delegate methods.
|
||||
|
||||
|
|
@ -124,6 +131,13 @@
|
|||
*/
|
||||
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding;
|
||||
|
||||
/**
|
||||
The pinning mode which will be used for SSL connections.
|
||||
*/
|
||||
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode SSLPinningMode;
|
||||
#endif
|
||||
|
||||
///------------------------
|
||||
/// @name Accessing Streams
|
||||
///------------------------
|
||||
|
|
|
|||
|
|
@ -192,6 +192,36 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
|||
return _pinnedCertificates;
|
||||
}
|
||||
|
||||
+ (NSArray *)pinnedPublicKeys {
|
||||
static NSArray *_pinnedPublicKeys = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSArray *pinnedCertificates = [self pinnedCertificates];
|
||||
NSMutableArray *publicKeys = [NSMutableArray array];
|
||||
|
||||
for (NSData *data in pinnedCertificates) {
|
||||
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
|
||||
NSParameterAssert(allowedCertificate);
|
||||
|
||||
SecPolicyRef policy = SecPolicyCreateBasicX509();
|
||||
SecTrustRef allowedTrust = NULL;
|
||||
OSStatus status = SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust);
|
||||
NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", status);
|
||||
|
||||
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust);
|
||||
[publicKeys addObject:(__bridge_transfer id)allowedPublicKey];
|
||||
|
||||
CFRelease(allowedTrust);
|
||||
CFRelease(allowedCertificate);
|
||||
}
|
||||
|
||||
_pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys];
|
||||
});
|
||||
|
||||
return _pinnedPublicKeys;
|
||||
}
|
||||
|
||||
- (id)initWithRequest:(NSURLRequest *)urlRequest {
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
|
|
@ -499,14 +529,34 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
|
|||
{
|
||||
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
|
||||
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
|
||||
NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(certificate);
|
||||
|
||||
if ([[[self class] pinnedCertificates] containsObject:certificateData]) {
|
||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||
} else {
|
||||
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||
switch (self.SSLPinningMode) {
|
||||
case AFURLConnectionOperationSSLPinningModeCertificate: {
|
||||
SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
|
||||
NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(serverCertificate);
|
||||
|
||||
if ([[[self class] pinnedCertificates] containsObject:certificateData]) {
|
||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||
} else {
|
||||
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||
}
|
||||
break;
|
||||
} case AFURLConnectionOperationSSLPinningModePublicKey: {
|
||||
id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust);
|
||||
|
||||
for (id allowedPublicKey in [self.class pinnedPublicKeys]) {
|
||||
if ([allowedPublicKey isEqual:publicKey]) {
|
||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue