Skip to content

Commit

Permalink
Merge pull request #70 from nemesis/ssl_pinning_additions
Browse files Browse the repository at this point in the history
Made SSL pinning disableable via SEAPIRequestManager
  • Loading branch information
nemesis authored Aug 2, 2016
2 parents afdc883 + 5d25e06 commit 8d1bdca
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
23 changes: 22 additions & 1 deletion Classes/API/SEAPIRequestManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

typedef void (^SEAPIRequestFailureBlock)(SEError* error);

typedef NS_ENUM(NSUInteger, SEAPIRequestManagerSSLPinningMode) {
SEAPIRequestManagerSSLPinningModeEnabled = 0,
SEAPIRequestManagerSSLPinningModeDisabled
};

/**
SEAPIRequestManager is a class designed to provide convenient methods in communicating with the Salt Edge API.
*/
Expand All @@ -39,6 +44,23 @@ typedef void (^SEAPIRequestFailureBlock)(SEError* error);
*/
+ (instancetype)manager;

/**
Sets the given pinning mode and uses it for all outgoing API requests.
@param mode The mode to set to. This can either be enabled or disabled. The mode is enabled by default.
@see SSLPinningEnabled
*/
+ (void)setSSLPinningMode:(SEAPIRequestManagerSSLPinningMode)mode;

/**
Checks whether SSL pinning for outgoing API requests is enabled.
@return YES if SSL pinning is enabled, NO if SSL pinning is disabled.
@see setSSLPinningMode:
*/

+ (BOOL)SSLPinningEnabled;

/**
Links your Client ID and App Secret to the request manager. All outgoing requests will have the proper app-related HTTP headers set by default.
Expand All @@ -47,7 +69,6 @@ typedef void (^SEAPIRequestFailureBlock)(SEError* error);
*/
+ (void)linkClientId:(NSString*)clientId appSecret:(NSString*)appSecret;


/**
Links your Customer Secret to the request manager. All outgoing requests related to logins will have the proper customer-related HTTP headers set by default.
Expand Down
19 changes: 19 additions & 0 deletions Classes/API/SEAPIRequestManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

/* HTTP Session config */
static NSDictionary* sessionHeaders;
static SEAPIRequestManagerSSLPinningMode sslPinningMode;

/* Login polling */
static CGFloat const kLoginPollDelayTime = 5.0f;
Expand Down Expand Up @@ -76,6 +77,16 @@ + (instancetype)manager
return manager;
}

+ (void)setSSLPinningMode:(SEAPIRequestManagerSSLPinningMode)mode
{
sslPinningMode = mode;
}

+ (BOOL)SSLPinningEnabled
{
return sslPinningMode == SEAPIRequestManagerSSLPinningModeEnabled;
}

+ (void)linkClientId:(NSString *)clientId appSecret:(NSString *)appSecret
{
NSAssert(sessionHeaders == nil, @"Session headers are already set up.");
Expand Down Expand Up @@ -584,6 +595,14 @@ - (void)requestRefreshTokenForLoginSecret:(NSString*)loginSecret
#pragma mark -
#pragma mark - Private API

+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sslPinningMode = SEAPIRequestManagerSSLPinningModeEnabled;
});
}

- (instancetype)init
{
if (self = [super init]) {
Expand Down
19 changes: 15 additions & 4 deletions Classes/API/SERequestHandlerURLSessionDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import "SERequestHandlerURLSessionDelegate.h"
#import "SEAPIRequestManager.h"

@implementation SERequestHandlerURLSessionDelegate

Expand All @@ -19,7 +20,7 @@ + (instancetype)sharedInstance
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
NSString* cerPath = [[NSBundle mainBundle] pathForResource:@"saltedge.com" ofType:@"cer"];
NSAssert(cerPath != nil, @"The saltedge.com SSL certificate could not be located in the app bundle.");
NSAssert(cerPath != nil, @"The saltedge.com SSL certificate could not be located in the app bundle. SSL pinning will not be possible without it.");
});
return _sharedInstance;
}
Expand All @@ -29,15 +30,25 @@ + (instancetype)sharedInstance
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;

void (^useChallengeCredential)() = ^{
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
};

if (![SEAPIRequestManager SSLPinningEnabled]) {
useChallengeCredential();
return;
}

SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData* remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSString* cerPath = [[NSBundle mainBundle] pathForResource:@"saltedge.com" ofType:@"cer"];
NSData* localCertificateData = [NSData dataWithContentsOfFile:cerPath];

if ([remoteCertificateData isEqualToData:localCertificateData]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
useChallengeCredential();
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
Expand Down
1 change: 1 addition & 0 deletions Salt Edge API Demo/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return YES;
}
[SEAPIRequestManager linkClientId:clientId appSecret:appSecret];
[SEAPIRequestManager setSSLPinningMode:SEAPIRequestManagerSSLPinningModeEnabled]; // No need to actually write this since SSL pinning is enabled by default.

void (^setWindowRootViewController)() = ^() {
self.tabBar = [[TabBarVC alloc] init];
Expand Down

0 comments on commit 8d1bdca

Please sign in to comment.