Pinning certificates will now trust all derived certificates.

This commit is contained in:
Oliver Letterer 2013-03-27 11:19:51 +01:00
parent 43b05d7ceb
commit a0f1f83a2b

View file

@ -542,37 +542,52 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
{ {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(certificate);
if ([[[self class] pinnedCertificates] containsObject:certificateData]) { SecPolicyRef policy = SecPolicyCreateBasicX509();
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:certificateCount];
} else {
for (CFIndex i = 0; i < certificateCount; i++) {
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
if (self.SSLPinningMode == AFSSLPinningModeCertificate) {
[trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)];
} else if (self.SSLPinningMode == AFSSLPinningModePublicKey) {
SecTrustRef trust = NULL;
OSStatus status = SecTrustCreateWithCertificates(certificate, policy, &trust);
NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
[trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)];
CFRelease(trust);
}
}
CFRelease(policy);
switch (self.SSLPinningMode) { switch (self.SSLPinningMode) {
case AFSSLPinningModePublicKey: { case AFSSLPinningModePublicKey: {
id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust); for (id publicKey in trustChain) {
if ([[self.class pinnedPublicKeys] containsObject:publicKey]) { if ([[self.class pinnedPublicKeys] containsObject:publicKey]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else { return;
[[challenge sender] cancelAuthenticationChallenge:challenge]; }
} }
[[challenge sender] cancelAuthenticationChallenge:challenge];
break; break;
} }
case AFSSLPinningModeCertificate: { case AFSSLPinningModeCertificate: {
SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0); for (id serverCertificateData in trustChain) {
NSData *serverCertificateData = (__bridge_transfer NSData *)SecCertificateCopyData(serverCertificate); if ([[self.class pinnedCertificates] containsObject:serverCertificateData]) {
if ([[[self class] pinnedCertificates] containsObject:serverCertificateData]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else { return;
[[challenge sender] cancelAuthenticationChallenge:challenge]; }
} }
[[challenge sender] cancelAuthenticationChallenge:challenge];
break; break;
} }
case AFSSLPinningModeNone: { case AFSSLPinningModeNone: {
@ -595,7 +610,6 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
} }
} }
} }
}
} }
#endif #endif