浏览代码

Merge pull request #2856 from AFNetworking/simplified_security

Removed Certificate Chain Validation
Kevin Harwood 10 年之前
父节点
当前提交
36bccffd5d

+ 1 - 6
AFNetworking/AFSecurityPolicy.h

@@ -44,12 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode;
 
 /**
- Whether to evaluate an entire SSL certificate chain, or just the leaf certificate. Defaults to `YES`.
- */
-@property (nonatomic, assign) BOOL validatesCertificateChain;
-
-/**
- The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. Note that if you create an array with duplicate certificates, the duplicate certificates will be removed.
+ The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. Note that if you create an array with duplicate certificates, the duplicate certificates will be removed. Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches.
  */
 @property (nonatomic, strong, nullable) NSArray *pinnedCertificates;
 

+ 17 - 14
AFNetworking/AFSecurityPolicy.m

@@ -196,7 +196,6 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
         return nil;
     }
 
-    self.validatesCertificateChain = YES;
     self.validatesDomainName = YES;
 
     return self;
@@ -204,7 +203,7 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
 
 - (void)setPinnedCertificates:(NSArray *)pinnedCertificates {
     _pinnedCertificates = [[NSOrderedSet orderedSetWithArray:pinnedCertificates] array];
-    
+
     if (self.pinnedCertificates) {
         NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]];
         for (NSData *certificate in self.pinnedCertificates) {
@@ -229,6 +228,19 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
 - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
                   forDomain:(NSString *)domain
 {
+    if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {
+        // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html
+        //  According to the docs, you should only trust your provided certs for evaluation.
+        //  Pinned certificates are added to the trust. Without pinned certificates,
+        //  there is nothing to evaluate against.
+        //
+        //  From Apple Docs:
+        //          "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).
+        //           Instead, add your own (self-signed) CA certificate to the list of trusted anchors."
+        NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning.");
+        return NO;
+    }
+
     NSMutableArray *policies = [NSMutableArray array];
     if (self.validatesDomainName) {
         [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
@@ -264,25 +276,17 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
                 return NO;
             }
 
-            if (!self.validatesCertificateChain) {
-                return YES;
-            }
-
             NSUInteger trustedCertificateCount = 0;
             for (NSData *trustChainCertificate in serverCertificates) {
                 if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
                     trustedCertificateCount++;
                 }
             }
-
-            return trustedCertificateCount == [serverCertificates count];
+            return trustedCertificateCount > 0;
         }
         case AFSSLPinningModePublicKey: {
             NSUInteger trustedPublicKeyCount = 0;
             NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
-            if (!self.validatesCertificateChain && [publicKeys count] > 0) {
-                publicKeys = @[[publicKeys firstObject]];
-            }
 
             for (id trustChainPublicKey in publicKeys) {
                 for (id pinnedPublicKey in self.pinnedPublicKeys) {
@@ -291,11 +295,10 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
                     }
                 }
             }
-
-            return trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1));
+            return trustedPublicKeyCount > 0;
         }
     }
-
+    
     return NO;
 }
 

+ 6 - 6
Tests/AFNetworking Tests.xcodeproj/project.pbxproj

@@ -23,16 +23,16 @@
 		29CBFC3D17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */; };
 		29CBFC3F17DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3E17DF58000021AB75 /* AFHTTPRequestSerializationTests.m */; };
 		29CBFC4017DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3E17DF58000021AB75 /* AFHTTPRequestSerializationTests.m */; };
-		29CBFC5A17DF61B30021AB75 /* AFSecurityPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC5917DF61B30021AB75 /* AFSecurityPolicyTests.m */; };
 		29CBFC7617DF697C0021AB75 /* HTTPBinOrgServerTrustChain in Resources */ = {isa = PBXBuildFile; fileRef = 29CBFC7517DF697C0021AB75 /* HTTPBinOrgServerTrustChain */; };
 		29CBFC7717DF697C0021AB75 /* HTTPBinOrgServerTrustChain in Resources */ = {isa = PBXBuildFile; fileRef = 29CBFC7517DF697C0021AB75 /* HTTPBinOrgServerTrustChain */; };
 		29CBFC8717DF74C60021AB75 /* ADNNetServerTrustChain in Resources */ = {isa = PBXBuildFile; fileRef = 29CBFC8617DF74C60021AB75 /* ADNNetServerTrustChain */; };
 		29CBFC8817DF74C60021AB75 /* ADNNetServerTrustChain in Resources */ = {isa = PBXBuildFile; fileRef = 29CBFC8617DF74C60021AB75 /* ADNNetServerTrustChain */; };
 		29EAB0D71AFC148200C2C460 /* AFURLSessionManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 943B1F40192E406C00304316 /* AFURLSessionManagerTests.m */; };
+		29F570501B62878600B267F7 /* AFSecurityPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29F5704F1B62878600B267F7 /* AFSecurityPolicyTests.m */; };
+		29F570511B62878700B267F7 /* AFSecurityPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29F5704F1B62878600B267F7 /* AFSecurityPolicyTests.m */; };
 		36DE264E18053E930062F4E3 /* adn_0.cer in Resources */ = {isa = PBXBuildFile; fileRef = 36DE264B18053E930062F4E3 /* adn_0.cer */; };
 		36DE264F18053E930062F4E3 /* adn_1.cer in Resources */ = {isa = PBXBuildFile; fileRef = 36DE264C18053E930062F4E3 /* adn_1.cer */; };
 		36DE265018053E930062F4E3 /* adn_2.cer in Resources */ = {isa = PBXBuildFile; fileRef = 36DE264D18053E930062F4E3 /* adn_2.cer */; };
-		36DE26511805445B0062F4E3 /* AFSecurityPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC5917DF61B30021AB75 /* AFSecurityPolicyTests.m */; };
 		36DE2652180544600062F4E3 /* AFHTTPRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CBFC3817DF4F120021AB75 /* AFHTTPRequestOperationTests.m */; };
 		3D56634E3A564CEE86172413 /* libPods-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 96A923755B00464187DEDBAF /* libPods-osx.a */; };
 		6D86BAA5C6174E98AE719CE9 /* libPods-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55E73C267F33406A9F92476C /* libPods-ios.a */; };
@@ -107,9 +107,9 @@
 		29CBFC3817DF4F120021AB75 /* AFHTTPRequestOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationTests.m; sourceTree = "<group>"; };
 		29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFJSONSerializationTests.m; sourceTree = "<group>"; };
 		29CBFC3E17DF58000021AB75 /* AFHTTPRequestSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestSerializationTests.m; sourceTree = "<group>"; };
-		29CBFC5917DF61B30021AB75 /* AFSecurityPolicyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicyTests.m; sourceTree = "<group>"; };
 		29CBFC7517DF697C0021AB75 /* HTTPBinOrgServerTrustChain */ = {isa = PBXFileReference; lastKnownFileType = folder; path = HTTPBinOrgServerTrustChain; sourceTree = "<group>"; };
 		29CBFC8617DF74C60021AB75 /* ADNNetServerTrustChain */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ADNNetServerTrustChain; sourceTree = "<group>"; };
+		29F5704F1B62878600B267F7 /* AFSecurityPolicyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicyTests.m; sourceTree = "<group>"; };
 		2B6D24F8E1B74E10A269E8B3 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		36DE264B18053E930062F4E3 /* adn_0.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = adn_0.cer; path = Resources/ADN.net/ADNNetServerTrustChain/adn_0.cer; sourceTree = "<group>"; };
 		36DE264C18053E930062F4E3 /* adn_1.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = adn_1.cer; path = Resources/ADN.net/ADNNetServerTrustChain/adn_1.cer; sourceTree = "<group>"; };
@@ -277,7 +277,7 @@
 				F837FFAE195744A0009078A0 /* AFHTTPResponseSerializationTests.m */,
 				29CBFC3B17DF541F0021AB75 /* AFJSONSerializationTests.m */,
 				77D65EBB1848A03C004CA024 /* AFPropertyListResponseSerializerTests.m */,
-				29CBFC5917DF61B30021AB75 /* AFSecurityPolicyTests.m */,
+				29F5704F1B62878600B267F7 /* AFSecurityPolicyTests.m */,
 				B6774DC818FBB49E0044DB17 /* AFNetworkActivityManagerTests.m */,
 				943B1F40192E406C00304316 /* AFURLSessionManagerTests.m */,
 				DE533FCD1ACCF34200C62CFB /* AFNetworkReachabilityManagerTests.m */,
@@ -545,8 +545,8 @@
 				943B1F41192E406C00304316 /* AFURLSessionManagerTests.m in Sources */,
 				F837FFAF195744A0009078A0 /* AFHTTPResponseSerializationTests.m in Sources */,
 				2940C00C1B064C3200AFDAC7 /* AFUIRefreshControlTests.m in Sources */,
-				29CBFC5A17DF61B30021AB75 /* AFSecurityPolicyTests.m in Sources */,
 				29CBFC3F17DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */,
+				29F570501B62878600B267F7 /* AFSecurityPolicyTests.m in Sources */,
 				B6774DC918FBB49E0044DB17 /* AFNetworkActivityManagerTests.m in Sources */,
 				DE533FCE1ACCF34200C62CFB /* AFNetworkReachabilityManagerTests.m in Sources */,
 				29CBFC3C17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */,
@@ -563,7 +563,7 @@
 				F837FFB0195744A0009078A0 /* AFHTTPResponseSerializationTests.m in Sources */,
 				36DE2652180544600062F4E3 /* AFHTTPRequestOperationTests.m in Sources */,
 				29EAB0D71AFC148200C2C460 /* AFURLSessionManagerTests.m in Sources */,
-				36DE26511805445B0062F4E3 /* AFSecurityPolicyTests.m in Sources */,
+				29F570511B62878700B267F7 /* AFSecurityPolicyTests.m in Sources */,
 				29CBFC4017DF58000021AB75 /* AFHTTPRequestSerializationTests.m in Sources */,
 				29CBFC3D17DF541F0021AB75 /* AFJSONSerializationTests.m in Sources */,
 				77D65EBD1848A03C004CA024 /* AFPropertyListResponseSerializerTests.m in Sources */,

+ 262 - 347
Tests/Tests/AFSecurityPolicyTests.m

@@ -20,10 +20,10 @@
 // THE SOFTWARE.
 
 #import "AFTestCase.h"
-
 #import "AFSecurityPolicy.h"
 
 @interface AFSecurityPolicyTests : AFTestCase
+
 @end
 
 static SecTrustRef AFUTTrustChainForCertsInDirectory(NSString *directoryPath) {
@@ -136,288 +136,192 @@ static SecTrustRef AFUTTrustWithCertificate(SecCertificateRef certificate) {
     return trust;
 }
 
-#pragma mark -
-
 @implementation AFSecurityPolicyTests
 
-- (void)testLeafPublicKeyPinningIsEnforcedForHTTPBinOrgPinnedCertificateAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-
-    SecCertificateRef addtrustRootCertificate = AFUTAddTrustExternalRootCertificate();
-    SecCertificateRef comodoRsaCACertificate = AFUTCOMODORSACertificate();
-    SecCertificateRef comodoRsaDomainValidationCertificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
-    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
-
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(addtrustRootCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaCACertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaDomainValidationCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
+#pragma mark - Default Policy Tests
+#pragma mark Default Values Test
 
-    CFRelease(addtrustRootCertificate);
-    CFRelease(comodoRsaCACertificate);
-    CFRelease(comodoRsaDomainValidationCertificate);
-    CFRelease(httpBinCertificate);
+- (void)testDefaultPolicyPinningModeIsSetToNone {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertTrue(policy.SSLPinningMode == AFSSLPinningModeNone, @"Pinning Mode should be set to by default");
+}
 
-    [policy setValidatesCertificateChain:NO];
+- (void)testDefaultPolicyHasInvalidCertificatesAreDisabledByDefault {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertFalse(policy.allowInvalidCertificates, @"Invalid Certificates Should Be Disabled by Default");
+}
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+- (void)testDefaultPolicyHasDomainNamesAreValidatedByDefault {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertTrue(policy.validatesDomainName, @"Domain names should be validated by default");
 }
 
-- (void)testPublicKeyChainPinningIsEnforcedForHTTPBinOrgPinnedCertificateAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
+- (void)testDefaultPolicyHasNoPinnedCertificates {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertTrue(policy.pinnedCertificates.count == 0, @"The default policy should not have any pinned certificates");
+}
 
-    SecTrustRef clientTrust = AFUTHTTPBinOrgServerTrust();
-    NSArray * certificates = AFCertificateTrustChainForServerTrust(clientTrust);
-    CFRelease(clientTrust);
-    [policy setPinnedCertificates:certificates];
+#pragma mark Positive Server Trust Evaluation Tests
 
+- (void)testDefaultPolicyDoesAllowHTTPBinOrgCertificate {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
     SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:nil], @"Valid Certificate should be allowed by default.");
 }
 
-- (void)testLeafCertificatePinningIsEnforcedForHTTPBinOrgPinnedCertificateAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-
-    SecCertificateRef addtrustRootCertificate = AFUTAddTrustExternalRootCertificate();
-    SecCertificateRef comodoRsaCACertificate = AFUTCOMODORSACertificate();
-    SecCertificateRef comodoRsaDomainValidationCertificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
-    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
-
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(addtrustRootCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaCACertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaDomainValidationCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
-
-    CFRelease(addtrustRootCertificate);
-    CFRelease(comodoRsaCACertificate);
-    CFRelease(comodoRsaDomainValidationCertificate);
-    CFRelease(httpBinCertificate);
-
-    [policy setValidatesCertificateChain:NO];
-
+- (void)testDefaultPolicyDoesAllowHTTPBinOrgCertificateForValidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
     SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"Valid Certificate should be allowed by default.");
 }
 
-- (void)testCertificateChainPinningIsEnforcedForHTTPBinOrgPinnedCertificateAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    SecTrustRef clientTrust = AFUTHTTPBinOrgServerTrust();
-    NSArray * certificates = AFCertificateTrustChainForServerTrust(clientTrust);
-    CFRelease(clientTrust);
-    [policy setPinnedCertificates:certificates];
+#pragma mark Negative Server Trust Evaluation Tests
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+- (void)testDefaultPolicyDoesNotAllowInvalidCertificate {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithoutDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:nil], @"Invalid Certificates should not be allowed");
 }
 
-- (void)testNoPinningIsEnforcedForHTTPBinOrgPinnedCertificateAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+- (void)testDefaultPolicyDoesNotAllowCertificateWithInvalidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:@"apple.com"], @"Certificate should not be allowed because the domain names do not match.");
+}
 
-    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
-    CFRelease(certificate);
-    [policy setAllowInvalidCertificates:YES];
+#pragma mark - Public Key Pinning Tests
+#pragma mark Default Values Tests
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Pinning should not have been enforced");
-    CFRelease(trust);
+- (void)testPolicyWithPublicKeyPinningModeHasPinnedCertificates {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
+    XCTAssertTrue(policy.pinnedCertificates > 0, @"Policy should contain default pinned certificates");
 }
 
-- (void)testPublicKeyPinningFailsForHTTPBinOrgIfNoCertificateIsPinned {
+- (void)testPolicyWithPublicKeyPinningModeHasHTTPBinOrgPinnedCertificate {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    [policy setPinnedCertificates:@[]];
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"] == NO, @"HTTPBin.org Public Key Pinning Should have failed with no pinned certificate");
-    CFRelease(trust);
-}
+    SecCertificateRef cert = AFUTHTTPBinOrgCertificate();
+    NSData *certData = (__bridge NSData *)(SecCertificateCopyData(cert));
+    CFRelease(cert);
+    NSInteger index = [policy.pinnedCertificates indexOfObjectPassingTest:^BOOL(NSData *data, NSUInteger idx, BOOL *stop) {
+        return [data isEqualToData:certData];
+    }];
 
-- (void)testSettingDuplicateCertificatesProperlyRemovesTheDuplicate {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    
-    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
-    
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
-    
-    CFRelease(httpBinCertificate);
-    XCTAssertTrue([policy.pinnedCertificates count] == 1, @"Duplicate Certificates not removed");
+    XCTAssertTrue(index!=NSNotFound, @"HTTPBin.org certificate not found in the default certificates");
 }
 
-- (void)testPublicKeyPinningFailsForValidatingCertificateChainHTTPBinOrgServerTrustWithFourSameCertificates {
+#pragma mark Positive Server Trust Evaluation Tests
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    
-    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
-    
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
-    
-    CFRelease(httpBinCertificate);
-    
-    [policy setValidatesCertificateChain:YES];
-    
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:nil], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningIsEnforcedForHTTPBinOrgPinnedCertificateWithDomainNameValidationAgainstHTTPBinOrgServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgIntermediate1CertificatePinned {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    SecCertificateRef addtrustRootCertificate = AFUTAddTrustExternalRootCertificate();
-    SecCertificateRef comodoRsaCACertificate = AFUTCOMODORSACertificate();
-    SecCertificateRef comodoRsaDomainValidationCertificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
-    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef certificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
+}
 
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(addtrustRootCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaCACertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaDomainValidationCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgIntermediate2CertificatePinned {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    CFRelease(addtrustRootCertificate);
-    CFRelease(comodoRsaCACertificate);
-    CFRelease(comodoRsaDomainValidationCertificate);
-    CFRelease(httpBinCertificate);
+    SecCertificateRef certificate = AFUTCOMODORSACertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
+}
 
-    policy.validatesDomainName = YES;
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgRootCertificatePinned {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+    SecCertificateRef certificate = AFUTAddTrustExternalRootCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningIsEnforcedForHTTPBinOrgPinnedCertificateWithCaseInsensitiveDomainNameValidationAgainstHTTPBinOrgServerTrust {
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithEntireCertificateChainPinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    SecCertificateRef addtrustRootCertificate = AFUTAddTrustExternalRootCertificate();
-    SecCertificateRef comodoRsaCACertificate = AFUTCOMODORSACertificate();
-    SecCertificateRef comodoRsaDomainValidationCertificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
     SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef intermedaite1Certificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
+    SecCertificateRef intermedaite2Certificate = AFUTCOMODORSACertificate();
+    SecCertificateRef rootCertificate = AFUTAddTrustExternalRootCertificate();
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(intermedaite1Certificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(intermedaite2Certificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(rootCertificate)]];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow HTTPBinOrg server trust because at least one of the pinned certificates is valid");
 
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(addtrustRootCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaCACertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaDomainValidationCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
-
-    CFRelease(addtrustRootCertificate);
-    CFRelease(comodoRsaCACertificate);
-    CFRelease(comodoRsaDomainValidationCertificate);
-    CFRelease(httpBinCertificate);
-
-    policy.validatesDomainName = YES;
-
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpBin.org"], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
 }
 
-- (void)testCertificatePinningIsEnforcedForHTTPBinOrgPinnedPublicKeyWithDomainNameValidationAgainstHTTPBinOrgServerTrust {
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBirnOrgServerTrustWithHTTPbinOrgPinnedCertificateAndAdditionalPinnedCertificates {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    SecCertificateRef addtrustRootCertificate = AFUTAddTrustExternalRootCertificate();
-    SecCertificateRef comodoRsaCACertificate = AFUTCOMODORSACertificate();
-    SecCertificateRef comodoRsaDomainValidationCertificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
     SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef selfSignedCertificate = AFUTSelfSignedCertificateWithCommonNameDomain();
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(selfSignedCertificate)]];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow HTTPBinOrg server trust because at least one of the pinned certificates is valid");
+}
 
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(addtrustRootCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaCACertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(comodoRsaDomainValidationCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
+- (void)testPolicyWithPublicKeyPinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinnedAndValidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    CFRelease(addtrustRootCertificate);
-    CFRelease(comodoRsaCACertificate);
-    CFRelease(comodoRsaDomainValidationCertificate);
-    CFRelease(httpBinCertificate);
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"httpbin.org"], @"Policy should allow server trust");
+}
 
-    policy.validatesDomainName = YES;
+#pragma mark Negative Server Trust Evaluation Tests
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Public Key Pinning Mode Failed");
-    CFRelease(trust);
+- (void)testPolicyWithPublicKeyPinningAndNoPinnedCertificatesDoesNotAllowHTTPBinOrgServerTrust {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
+    policy.pinnedCertificates = @[];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should not allow server trust because the policy is set to public key pinning and it does not contain any pinned certificates.");
 }
 
-- (void)testCertificatePinningFailsForHTTPBinOrgIfNoCertificateIsPinned {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    [policy setPinnedCertificates:@[]];
+- (void)testPolicyWithPublicKeyPinningDoesNotAllowADNServerTrustWithHTTPBinOrgPinnedCertificate {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"] == NO, @"HTTPBin.org Certificate Pinning Should have failed with no pinned certificate");
-    CFRelease(trust);
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTADNNetServerTrust() forDomain:nil], @"Policy should not allow ADN server trust for pinned HTTPBin.org certificate");
 }
 
-- (void)testCertificatePinningFailsForHTTPBinOrgIfDomainNameDoesntMatch {
+- (void)testPolicyWithPublicKeyPinningDoesNotAllowHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinnedAndInvalidDomainName {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
-    CFRelease(certificate);
-    policy.validatesDomainName = YES;
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"www.httpbin.org"] == NO, @"HTTPBin.org Certificate Pinning Should have failed with no pinned certificate");
-    CFRelease(trust);
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"invaliddomainname.com"], @"Policy should not allow server trust");
 }
 
-- (void)testCertificatePinningFailsForValidatingHTTPBinOrgServerTrustWithFourSameCertificates {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    
+- (void)testPolicyWithPublicKeyPinningDoesNotAllowADNServerTrustWithMultipleInvalidPinnedCertificates {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
+
     SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
-    
+    SecCertificateRef selfSignedCertificate = AFUTSelfSignedCertificateWithCommonNameDomain();
     [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
-                                    (__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate)]];
-    
-    CFRelease(httpBinCertificate);
-    
-    [policy setValidatesCertificateChain:YES];
-    
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:nil], @"HTTPBin.org Certificate Pinning Mode Failed");
-    CFRelease(trust);
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(selfSignedCertificate)]];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTADNNetServerTrust() forDomain:nil], @"Policy should not allow ADN server trust because there are no matching pinned certificates");
 }
 
-- (void)testNoPinningIsEnforcedForHTTPBinOrgIfNoCertificateIsPinned {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
-    [policy setPinnedCertificates:@[]];
-
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"], @"HTTPBin.org Pinning should not have been enforced");
-    CFRelease(trust);
-}
-
-- (void)testPublicKeyPinningForHTTPBinOrgFailsWhenPinnedAgainstADNServerTrust {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
-    [policy setValidatesCertificateChain:NO];
+#pragma mark - Certificate Pinning Tests
+#pragma mark Default Values Tests
 
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"] == NO, @"HTTPBin.org Public Key Pinning Should have failed against ADN");
-    CFRelease(trust);
+- (void)testPolicyWithCertificatePinningModeHasPinnedCertificates {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+    XCTAssertTrue(policy.pinnedCertificates > 0, @"Policy should contain default pinned certificates");
 }
 
-- (void)testCertificatePinningForHTTPBinOrgFailsWhenPinnedAgainstADNServerTrust {
+- (void)testPolicyWithCertificatePinningModeHasHTTPBinOrgPinnedCertificate {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
-    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
-    [policy setValidatesCertificateChain:NO];
 
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"] == NO, @"HTTPBin.org Certificate Pinning Should have failed against ADN");
-    CFRelease(trust);
-}
-
-- (void)testDefaultPolicyContainsHTTPBinOrgCertificate {
-    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
     SecCertificateRef cert = AFUTHTTPBinOrgCertificate();
     NSData *certData = (__bridge NSData *)(SecCertificateCopyData(cert));
     CFRelease(cert);
@@ -425,204 +329,215 @@ static SecTrustRef AFUTTrustWithCertificate(SecCertificateRef certificate) {
         return [data isEqualToData:certData];
     }];
 
-    XCTAssert(index!=NSNotFound, @"HTTPBin.org certificate not found in the default certificates");
+    XCTAssertTrue(index!=NSNotFound, @"HTTPBin.org certificate not found in the default certificates");
 }
 
-- (void)testCertificatePinningIsEnforcedWhenPinningSelfSignedCertificateWithoutDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithoutDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
-
+#pragma mark Positive Server Trust Evaluation Tests
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    policy.validatesDomainName = NO;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foo.bar"], @"Certificate should be trusted");
 
-    CFRelease(trust);
-    CFRelease(certificate);
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningWhenPinningSelfSignedCertificateWithoutDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithoutDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
-
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgIntermediate1CertificatePinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foo.bar"] == NO, @"Certificate should not be trusted");
 
-    CFRelease(trust);
-    CFRelease(certificate);
+    SecCertificateRef certificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningIsEnforcedWhenPinningSelfSignedCertificateWithCommonNameDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithCommonNameDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
-
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgIntermediate2CertificatePinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Certificate should be trusted");
 
-    CFRelease(trust);
-    CFRelease(certificate);
+    SecCertificateRef certificate = AFUTCOMODORSACertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningWhenPinningSelfSignedCertificateWithCommonNameDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithCommonNameDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgRootCertificatePinned {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
 
+    SecCertificateRef certificate = AFUTAddTrustExternalRootCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow server trust");
+}
+
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithEntireCertificateChainPinned {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foo.bar"] == NO, @"Certificate should not be trusted");
 
-    CFRelease(trust);
-    CFRelease(certificate);
+    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef intermedaite1Certificate = AFUTCOMODORSADomainValidationSecureServerCertificate();
+    SecCertificateRef intermedaite2Certificate = AFUTCOMODORSACertificate();
+    SecCertificateRef rootCertificate = AFUTAddTrustExternalRootCertificate();
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(intermedaite1Certificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(intermedaite2Certificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(rootCertificate)]];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow HTTPBinOrg server trust because at least one of the pinned certificates is valid");
+
 }
 
-- (void)testCertificatePinningIsEnforcedWhenPinningSelfSignedCertificateWithDNSNameDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+- (void)testPolicyWithCertificatePinningAllowsHTTPBirnOrgServerTrustWithHTTPbinOrgPinnedCertificateAndAdditionalPinnedCertificates {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
 
+    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef selfSignedCertificate = AFUTSelfSignedCertificateWithCommonNameDomain();
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(selfSignedCertificate)]];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should allow HTTPBinOrg server trust because at least one of the pinned certificates is valid");
+}
+
+- (void)testPolicyWithCertificatePinningAllowsHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinnedAndValidDomainName {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Certificate should be trusted");
 
-    CFRelease(trust);
-    CFRelease(certificate);
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"httpbin.org"], @"Policy should allow server trust");
 }
 
-- (void)testCertificatePinningWhenPinningSelfSignedCertificateWithDNSNameDomain {
-    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
-    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+#pragma mark Negative Server Trust Evaluation Tests
 
+- (void)testPolicyWithCertificatePinningAndNoPinnedCertificatesDoesNotAllowHTTPBinOrgServerTrust {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate) ];
-    policy.allowInvalidCertificates = YES;
-    XCTAssert([policy evaluateServerTrust:trust forDomain:@"foo.bar"] == NO, @"Certificate should not be trusted");
+    policy.pinnedCertificates = @[];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:nil], @"Policy should not allow server trust because the policy does not contain any pinned certificates.");
+}
 
-    CFRelease(trust);
-    CFRelease(certificate);
+- (void)testPolicyWithCertificatePinningDoesNotAllowADNServerTrustWithHTTPBinOrgPinnedCertificate {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTADNNetServerTrust() forDomain:nil], @"Policy should not allow ADN server trust for pinned HTTPBin.org certificate");
 }
 
-- (void)testDefaultPolicySetToCertificateChain {
+- (void)testPolicyWithCertificatePinningDoesNotAllowHTTPBinOrgServerTrustWithHTTPBinOrgLeafCertificatePinnedAndInvalidDomainName {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"Pinning with Default Certficiate Chain Failed");
-    CFRelease(trust);
+
+    SecCertificateRef certificate = AFUTHTTPBinOrgCertificate();
+    policy.pinnedCertificates = @[ (__bridge_transfer id)SecCertificateCopyData(certificate)];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"invaliddomainname.com"], @"Policy should not allow server trust");
 }
 
-- (void)testDefaultPolicySetToLeafCertificate {
+- (void)testPolicyWithCertificatePinningDoesNotAllowADNServerTrustWithMultipleInvalidPinnedCertificates {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
-    [policy setValidatesCertificateChain:NO];
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"Pinning with Default Leaf Certficiate Failed");
-    CFRelease(trust);
+
+    SecCertificateRef httpBinCertificate = AFUTHTTPBinOrgCertificate();
+    SecCertificateRef selfSignedCertificate = AFUTSelfSignedCertificateWithCommonNameDomain();
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(httpBinCertificate),
+                                    (__bridge_transfer NSData *)SecCertificateCopyData(selfSignedCertificate)]];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTADNNetServerTrust() forDomain:nil], @"Policy should not allow ADN server trust because there are no matching pinned certificates");
 }
 
-- (void)testDefaultPolicySetToPublicKeyChain {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"Pinning with Default Public Key Chain Failed");
-    CFRelease(trust);
+#pragma mark - Domain Name Validation Tests
+#pragma mark Positive Evaluation Tests
+
+- (void)testThatPolicyWithoutDomainNameValidationAllowsServerTrustWithInvalidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    [policy setValidatesDomainName:NO];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"invalid.org"], @"Policy should allow server trust because domain name validation is disabled");
 }
 
-- (void)testDefaultPolicySetToLeafPublicKey {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    [policy setValidatesCertificateChain:NO];
-    SecTrustRef trust = AFUTADNNetServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil], @"Pinning with Default Leaf Public Key Failed");
-    CFRelease(trust);
+- (void)testThatPolicyWithDomainNameValidationAllowsServerTrustWithValidWildcardDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertTrue([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"test.httpbin.org"], @"Policy should allow server trust");
 }
 
-- (void)testDefaultPolicySetToCertificateChainFailsWithMissingChain {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+- (void)testThatPolicyWithDomainNameValidationAndSelfSignedCommonNameCertificateAllowsServerTrust {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    // By default the cer files are picked up from the bundle, this forces them to be cleared to emulate having none available
-    [policy setPinnedCertificates:@[]];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithCommonNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
+    [policy setAllowInvalidCertificates:YES];
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil] == NO, @"Pinning with Certificate Chain Mode and Missing Chain should have failed");
-    CFRelease(trust);
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should allow server trust");
 }
 
-- (void)testDefaultPolicySetToPublicKeyChainFailsWithMissingChain {
+- (void)testThatPolicyWithDomainNameValidationAndSelfSignedDNSCertificateAllowsServerTrust {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
 
-    // By default the cer files are picked up from the bundle, this forces them to be cleared to emulate having none available
-    [policy setPinnedCertificates:@[]];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
+    [policy setAllowInvalidCertificates:YES];
 
-    SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-    XCTAssert([policy evaluateServerTrust:trust forDomain:nil] == NO, @"Pinning with Public Key Chain Mode and Missing Chain should have failed");
-    CFRelease(trust);
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should allow server trust");
 }
 
-- (void)testDefaultPolicyIsSetToAFSSLPinningModeNone {
-    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+#pragma mark Negative Evaluation Tests
 
-    XCTAssert(policy.SSLPinningMode==AFSSLPinningModeNone, @"Default policy is not set to AFSSLPinningModeNone.");
+- (void)testThatPolicyWithDomainNameValidationDoesNotAllowServerTrustWithInvalidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    XCTAssertFalse([policy evaluateServerTrust:AFUTHTTPBinOrgServerTrust() forDomain:@"invalid.org"], @"Policy should not allow allow server trust");
 }
 
-- (void)testDefaultPolicyMatchesTrustedCertificateWithMatchingHostnameAndRejectsOthers {
-    {
-        //check non-trusted certificate, incorrect domain
-        AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
-        SecTrustRef trust = AFUTTrustWithCertificate(AFUTSelfSignedCertificateWithCommonNameDomain());
-        XCTAssert([policy evaluateServerTrust:trust forDomain:@"different.foobar.com"] == NO, @"Invalid certificate with mismatching domain should fail");
-        CFRelease(trust);
-    }
-    {
-        //check non-trusted certificate, correct domain
-        AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
-        SecTrustRef trust = AFUTTrustWithCertificate(AFUTSelfSignedCertificateWithCommonNameDomain());
-        XCTAssert([policy evaluateServerTrust:trust forDomain:@"foobar.com"] == NO, @"Invalid certificate with matching domain should fail");
-        CFRelease(trust);
-    }
-    {
-        //check trusted certificate, wrong domain
-        AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
-        SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-        XCTAssert([policy evaluateServerTrust:trust forDomain:@"nothttpbin.org"] == NO, @"Valid certificate with mismatching domain should fail");
-        CFRelease(trust);
-    }
-    {
-        //check trusted certificate, correct domain
-        AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
-        SecTrustRef trust = AFUTHTTPBinOrgServerTrust();
-        XCTAssert([policy evaluateServerTrust:trust forDomain:@"httpbin.org"] == YES, @"Valid certificate with matching domain should pass");
-        CFRelease(trust);
-    }
+- (void)testThatPolicyWithDomainNameValidationAndSelfSignedNoDomainCertificateDoesNotAllowServerTrust {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithoutDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
+    [policy setAllowInvalidCertificates:YES];
+
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should not allow server trust");
 }
 
-- (void)testDefaultPolicyIsSetToNotAllowInvalidSSLCertificates {
+#pragma mark - Self Signed Certificate Tests
+#pragma mark Positive Test Cases
+
+- (void)testThatPolicyWithInvalidCertificatesAllowedAllowsSelfSignedServerTrust {
     AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+    [policy setAllowInvalidCertificates:YES];
+
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
 
-    XCTAssert(policy.allowInvalidCertificates == NO, @"Default policy should not allow invalid ssl certificates");
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:nil], @"Policy should allow server trust because invalid certificaftes are allowed");
 }
 
-- (void)testPolicyWithPinningModeIsSetToNotAllowInvalidSSLCertificates {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+- (void)testThatPolicyWithInvalidCertificatesAllowedAndValidPinnedCertificatesDoesAllowSelfSignedServerTrustForValidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
+    [policy setAllowInvalidCertificates:YES];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
 
-    XCTAssert(policy.allowInvalidCertificates == NO, @"policyWithPinningMode: should not allow invalid ssl certificates by default.");
+    XCTAssertTrue([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should allow server trust because invalid certificaftes are not allowed");
 }
 
-- (void)testPolicyWithPinningModeIsSetToValidatesDomainName {
-    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+#pragma mark Negative Test Cases
+
+- (void)testThatPolicyWithInvalidCertificatesDisabledDoesNotAllowSelfSignedServerTrust {
+    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
 
-    XCTAssert(policy.validatesDomainName == YES, @"policyWithPinningMode: should validate domain names by default.");
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:nil], @"Policy should not allow server trust because invalid certificaftes are not allowed");
 }
 
-- (void)testThatSSLPinningPolicyClassMethodContainsDefaultCertificates{
+- (void)testThatPolicyWithInvalidCertificatesAllowedAndNoPinnedCertificatesAndPublicKeyPinningModeDoesNotAllowSelfSignedServerTrustForValidDomainName {
     AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
-    [policy setValidatesCertificateChain:NO];
-    XCTAssertNotNil(policy.pinnedCertificates, @"Default certificate array should not be empty for SSL pinning mode policy");
+    [policy setAllowInvalidCertificates:YES];
+    [policy setPinnedCertificates:@[]];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should not allow server trust because invalid certificaftes are allowed but there are no pinned certificates");
 }
 
-- (void)testThatDefaultPinningPolicyClassMethodContainsNoDefaultCertificates{
-    AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
-    XCTAssertNil(policy.pinnedCertificates, @"Default certificate array should be empty for default policy.");
+- (void)testThatPolicyWithInvalidCertificatesAllowedAndValidPinnedCertificatesAndNoPinningModeDoesNotAllowSelfSignedServerTrustForValidDomainName {
+    AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+    [policy setAllowInvalidCertificates:YES];
+    SecCertificateRef certificate = AFUTSelfSignedCertificateWithDNSNameDomain();
+    SecTrustRef trust = AFUTTrustWithCertificate(certificate);
+    [policy setPinnedCertificates:@[(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]];
+
+    XCTAssertFalse([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should not allow server trust because invalid certificaftes are allowed but there are no pinned certificates");
 }
 
 @end