GBA003/External/Harmony/Backends/Dropbox/Carthage/Checkouts/Alamofire/Tests/ServerTrustPolicyTests.swift
2024-05-30 10:22:15 +08:00

1625 lines
60 KiB
Swift

//
// MultipartFormDataTests.swift
//
// Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import Alamofire
import Foundation
import XCTest
private struct TestCertificates {
// Root Certificates
static let rootCA = TestCertificates.certificateWithFileName("alamofire-root-ca")
// Intermediate Certificates
static let intermediateCA1 = TestCertificates.certificateWithFileName("alamofire-signing-ca1")
static let intermediateCA2 = TestCertificates.certificateWithFileName("alamofire-signing-ca2")
// Leaf Certificates - Signed by CA1
static let leafWildcard = TestCertificates.certificateWithFileName("wildcard.alamofire.org")
static let leafMultipleDNSNames = TestCertificates.certificateWithFileName("multiple-dns-names")
static let leafSignedByCA1 = TestCertificates.certificateWithFileName("signed-by-ca1")
static let leafDNSNameAndURI = TestCertificates.certificateWithFileName("test.alamofire.org")
// Leaf Certificates - Signed by CA2
static let leafExpired = TestCertificates.certificateWithFileName("expired")
static let leafMissingDNSNameAndURI = TestCertificates.certificateWithFileName("missing-dns-name-and-uri")
static let leafSignedByCA2 = TestCertificates.certificateWithFileName("signed-by-ca2")
static let leafValidDNSName = TestCertificates.certificateWithFileName("valid-dns-name")
static let leafValidURI = TestCertificates.certificateWithFileName("valid-uri")
static func certificateWithFileName(_ fileName: String) -> SecCertificate {
class Locater {}
let filePath = Bundle(for: Locater.self).path(forResource: fileName, ofType: "cer")!
let data = try! Data(contentsOf: URL(fileURLWithPath: filePath))
let certificate = SecCertificateCreateWithData(nil, data as CFData)!
return certificate
}
}
// MARK: -
private struct TestPublicKeys {
// Root Public Keys
static let rootCA = TestPublicKeys.publicKey(for: TestCertificates.rootCA)
// Intermediate Public Keys
static let intermediateCA1 = TestPublicKeys.publicKey(for: TestCertificates.intermediateCA1)
static let intermediateCA2 = TestPublicKeys.publicKey(for: TestCertificates.intermediateCA2)
// Leaf Public Keys - Signed by CA1
static let leafWildcard = TestPublicKeys.publicKey(for: TestCertificates.leafWildcard)
static let leafMultipleDNSNames = TestPublicKeys.publicKey(for: TestCertificates.leafMultipleDNSNames)
static let leafSignedByCA1 = TestPublicKeys.publicKey(for: TestCertificates.leafSignedByCA1)
static let leafDNSNameAndURI = TestPublicKeys.publicKey(for: TestCertificates.leafDNSNameAndURI)
// Leaf Public Keys - Signed by CA2
static let leafExpired = TestPublicKeys.publicKey(for: TestCertificates.leafExpired)
static let leafMissingDNSNameAndURI = TestPublicKeys.publicKey(for: TestCertificates.leafMissingDNSNameAndURI)
static let leafSignedByCA2 = TestPublicKeys.publicKey(for: TestCertificates.leafSignedByCA2)
static let leafValidDNSName = TestPublicKeys.publicKey(for: TestCertificates.leafValidDNSName)
static let leafValidURI = TestPublicKeys.publicKey(for: TestCertificates.leafValidURI)
static func publicKey(for certificate: SecCertificate) -> SecKey {
let policy = SecPolicyCreateBasicX509()
var trust: SecTrust?
SecTrustCreateWithCertificates(certificate, policy, &trust)
let publicKey = SecTrustCopyPublicKey(trust!)!
return publicKey
}
}
// MARK: -
private enum TestTrusts {
// Leaf Trusts - Signed by CA1
case leafWildcard
case leafMultipleDNSNames
case leafSignedByCA1
case leafDNSNameAndURI
// Leaf Trusts - Signed by CA2
case leafExpired
case leafMissingDNSNameAndURI
case leafSignedByCA2
case leafValidDNSName
case leafValidURI
// Invalid Trusts
case leafValidDNSNameMissingIntermediate
case leafValidDNSNameWithIncorrectIntermediate
var trust: SecTrust {
let trust: SecTrust
switch self {
case .leafWildcard:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafWildcard,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
case .leafMultipleDNSNames:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafMultipleDNSNames,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
case .leafSignedByCA1:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafSignedByCA1,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
case .leafDNSNameAndURI:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafDNSNameAndURI,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
case .leafExpired:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafExpired,
TestCertificates.intermediateCA2,
TestCertificates.rootCA
])
case .leafMissingDNSNameAndURI:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafMissingDNSNameAndURI,
TestCertificates.intermediateCA2,
TestCertificates.rootCA
])
case .leafSignedByCA2:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafSignedByCA2,
TestCertificates.intermediateCA2,
TestCertificates.rootCA
])
case .leafValidDNSName:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA2,
TestCertificates.rootCA
])
case .leafValidURI:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidURI,
TestCertificates.intermediateCA2,
TestCertificates.rootCA
])
case .leafValidDNSNameMissingIntermediate:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.rootCA
])
case .leafValidDNSNameWithIncorrectIntermediate:
trust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
}
return trust
}
static func trustWithCertificates(_ certificates: [SecCertificate]) -> SecTrust {
let policy = SecPolicyCreateBasicX509()
var trust: SecTrust?
SecTrustCreateWithCertificates(certificates as CFTypeRef, policy, &trust)
return trust!
}
}
// MARK: - Basic X509 and SSL Exploration Tests -
class ServerTrustPolicyTestCase: BaseTestCase {
func setRootCertificateAsLoneAnchorCertificateForTrust(_ trust: SecTrust) {
SecTrustSetAnchorCertificates(trust, [TestCertificates.rootCA] as CFArray)
SecTrustSetAnchorCertificatesOnly(trust, true)
}
func trustIsValid(_ trust: SecTrust) -> Bool {
var isValid = false
var result = SecTrustResultType.invalid
let status = SecTrustEvaluate(trust, &result)
if status == errSecSuccess {
let unspecified = SecTrustResultType.unspecified
let proceed = SecTrustResultType.proceed
isValid = result == unspecified || result == proceed
}
return isValid
}
}
// MARK: -
class ServerTrustPolicyExplorationBasicX509PolicyValidationTestCase: ServerTrustPolicyTestCase {
func testThatAnchoredRootCertificatePassesBasicX509ValidationWithRootInTrust() {
// Given
let trust = TestTrusts.trustWithCertificates([
TestCertificates.leafDNSNameAndURI,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateBasicX509()]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatAnchoredRootCertificatePassesBasicX509ValidationWithoutRootInTrust() {
// Given
let trust = TestTrusts.leafDNSNameAndURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateBasicX509()]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatCertificateMissingDNSNamePassesBasicX509Validation() {
// Given
let trust = TestTrusts.leafMissingDNSNameAndURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateBasicX509()]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatExpiredCertificateFailsBasicX509Validation() {
// Given
let trust = TestTrusts.leafExpired.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateBasicX509()]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertFalse(trustIsValid(trust), "trust should not be valid")
}
}
// MARK: -
class ServerTrustPolicyExplorationSSLPolicyValidationTestCase: ServerTrustPolicyTestCase {
func testThatAnchoredRootCertificatePassesSSLValidationWithRootInTrust() {
// Given
let trust = TestTrusts.trustWithCertificates([
TestCertificates.leafDNSNameAndURI,
TestCertificates.intermediateCA1,
TestCertificates.rootCA
])
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatAnchoredRootCertificatePassesSSLValidationWithoutRootInTrust() {
// Given
let trust = TestTrusts.leafDNSNameAndURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatCertificateMissingDNSNameFailsSSLValidation() {
// Given
let trust = TestTrusts.leafMissingDNSNameAndURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertFalse(trustIsValid(trust), "trust should not be valid")
}
func testThatWildcardCertificatePassesSSLValidation() {
// Given
let trust = TestTrusts.leafWildcard.trust // *.alamofire.org
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatDNSNameCertificatePassesSSLValidation() {
// Given
let trust = TestTrusts.leafValidDNSName.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should be valid")
}
func testThatURICertificateFailsSSLValidation() {
// Given
let trust = TestTrusts.leafValidURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertFalse(trustIsValid(trust), "trust should not be valid")
}
func testThatMultipleDNSNamesCertificatePassesSSLValidationForAllEntries() {
// Given
let trust = TestTrusts.leafMultipleDNSNames.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [
SecPolicyCreateSSL(true, "test.alamofire.org" as CFString),
SecPolicyCreateSSL(true, "blog.alamofire.org" as CFString),
SecPolicyCreateSSL(true, "www.alamofire.org" as CFString)
]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should not be valid")
}
func testThatPassingNilForHostParameterAllowsCertificateMissingDNSNameToPassSSLValidation() {
// Given
let trust = TestTrusts.leafMissingDNSNameAndURI.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, nil)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertTrue(trustIsValid(trust), "trust should not be valid")
}
func testThatExpiredCertificateFailsSSLValidation() {
// Given
let trust = TestTrusts.leafExpired.trust
setRootCertificateAsLoneAnchorCertificateForTrust(trust)
// When
let policies = [SecPolicyCreateSSL(true, "test.alamofire.org" as CFString)]
SecTrustSetPolicies(trust, policies as CFTypeRef)
// Then
XCTAssertFalse(trustIsValid(trust), "trust should not be valid")
}
}
// MARK: - Server Trust Policy Tests -
class ServerTrustPolicyPerformDefaultEvaluationTestCase: ServerTrustPolicyTestCase {
// MARK: Do NOT Validate Host
func testThatValidCertificateChainPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: false)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatNonAnchoredRootCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA2
])
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: false)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingDNSNameLeafCertificatePassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafMissingDNSNameAndURI.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: false)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatExpiredCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: false)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingIntermediateCertificateInChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: false)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
// MARK: Validate Host
func testThatValidCertificateChainPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatNonAnchoredRootCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA2
])
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingDNSNameLeafCertificateFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafMissingDNSNameAndURI.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatWildcardedLeafCertificateChainPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafWildcard.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatExpiredCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingIntermediateCertificateInChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyPerformRevokedEvaluationTestCase: ServerTrustPolicyTestCase {
// MARK: Do NOT Validate Host
func testThatValidCertificateChainPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: false,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatNonAnchoredRootCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA2
])
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: false,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingDNSNameLeafCertificatePassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafMissingDNSNameAndURI.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: false,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatExpiredCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: false,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingIntermediateCertificateInChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: false,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
// MARK: Validate Host
func testThatValidCertificateChainPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatNonAnchoredRootCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.trustWithCertificates([
TestCertificates.leafValidDNSName,
TestCertificates.intermediateCA2
])
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingDNSNameLeafCertificateFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafMissingDNSNameAndURI.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatWildcardedLeafCertificateChainPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafWildcard.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatExpiredCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatMissingIntermediateCertificateInChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let serverTrustPolicy = ServerTrustPolicy.performRevokedEvaluation(
validateHost: true,
revocationFlags: kSecRevocationUseAnyAvailableMethod
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyPinCertificatesTestCase: ServerTrustPolicyTestCase {
// MARK: Validate Certificate Chain Without Validating Host
func testThatPinnedLeafCertificatePassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedIntermediateCertificatePassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedRootCertificatePassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningLeafCertificateNotInCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafSignedByCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningIntermediateCertificateNotInCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA1]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningExpiredLeafCertificateFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.leafExpired]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningIntermediateCertificateWithExpiredLeafCertificateFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
// MARK: Validate Certificate Chain and Host
func testThatPinnedLeafCertificatePassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedIntermediateCertificatePassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedRootCertificatePassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningLeafCertificateNotInCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafSignedByCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningIntermediateCertificateNotInCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA1]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningExpiredLeafCertificateFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.leafExpired]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningIntermediateCertificateWithExpiredLeafCertificateFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
// MARK: Do NOT Validate Certificate Chain or Host
func testThatPinnedLeafCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedIntermediateCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinnedRootCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningLeafCertificateNotInCertificateChainWithoutCertificateChainValidationFailsEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.leafSignedByCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningIntermediateCertificateNotInCertificateChainWithoutCertificateChainValidationFailsEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let certificates = [TestCertificates.intermediateCA1]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningExpiredLeafCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.leafExpired]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningIntermediateCertificateWithExpiredLeafCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningRootCertificateWithExpiredLeafCertificateWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [TestCertificates.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningMultipleCertificatesWithoutCertificateChainValidationPassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let certificates = [
TestCertificates.leafMultipleDNSNames, // not in certificate chain
TestCertificates.leafSignedByCA1, // not in certificate chain
TestCertificates.leafExpired, // in certificate chain 👍🏼👍🏼
TestCertificates.leafWildcard, // not in certificate chain
TestCertificates.leafDNSNameAndURI, // not in certificate chain
]
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: false,
validateHost: false
)
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyPinPublicKeysTestCase: ServerTrustPolicyTestCase {
// MARK: Validate Certificate Chain Without Validating Host
func testThatPinningLeafKeyPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningIntermediateKeyPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningRootKeyPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningKeyNotInCertificateChainFailsEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafSignedByCA2]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningBackupKeyPassesEvaluationWithoutHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafSignedByCA1, TestPublicKeys.intermediateCA1, TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
// MARK: Validate Certificate Chain and Host
func testThatPinningLeafKeyPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: true
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningIntermediateKeyPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: true
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningRootKeyPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: true
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningKeyNotInCertificateChainFailsEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafSignedByCA2]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: true
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningBackupKeyPassesEvaluationWithHostValidation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let publicKeys = [TestPublicKeys.leafSignedByCA1, TestPublicKeys.intermediateCA1, TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: true,
validateHost: true
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
// MARK: Do NOT Validate Certificate Chain or Host
func testThatPinningLeafKeyWithoutCertificateChainValidationPassesEvaluationWithMissingIntermediateCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let publicKeys = [TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningRootKeyWithoutCertificateChainValidationFailsEvaluationWithMissingIntermediateCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let publicKeys = [TestPublicKeys.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
func testThatPinningLeafKeyWithoutCertificateChainValidationPassesEvaluationWithIncorrectIntermediateCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameWithIncorrectIntermediate.trust
let publicKeys = [TestPublicKeys.leafValidDNSName]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningLeafKeyWithoutCertificateChainValidationPassesEvaluationWithExpiredLeafCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let publicKeys = [TestPublicKeys.leafExpired]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningIntermediateKeyWithoutCertificateChainValidationPassesEvaluationWithExpiredLeafCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let publicKeys = [TestPublicKeys.intermediateCA2]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatPinningRootKeyWithoutCertificateChainValidationPassesEvaluationWithExpiredLeafCertificate() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let publicKeys = [TestPublicKeys.rootCA]
let serverTrustPolicy = ServerTrustPolicy.pinPublicKeys(
publicKeys: publicKeys,
validateCertificateChain: false,
validateHost: false
)
// When
setRootCertificateAsLoneAnchorCertificateForTrust(serverTrust)
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyDisableEvaluationTestCase: ServerTrustPolicyTestCase {
func testThatCertificateChainMissingIntermediateCertificatePassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSNameMissingIntermediate.trust
let serverTrustPolicy = ServerTrustPolicy.disableEvaluation
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatExpiredLeafCertificatePassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafExpired.trust
let serverTrustPolicy = ServerTrustPolicy.disableEvaluation
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyCustomEvaluationTestCase: ServerTrustPolicyTestCase {
func testThatReturningTrueFromClosurePassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.customEvaluation { _, _ in
return true
}
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertTrue(serverTrustIsValid, "server trust should pass evaluation")
}
func testThatReturningFalseFromClosurePassesEvaluation() {
// Given
let host = "test.alamofire.org"
let serverTrust = TestTrusts.leafValidDNSName.trust
let serverTrustPolicy = ServerTrustPolicy.customEvaluation { _, _ in
return false
}
// When
let serverTrustIsValid = serverTrustPolicy.evaluate(serverTrust, forHost: host)
// Then
XCTAssertFalse(serverTrustIsValid, "server trust should not pass evaluation")
}
}
// MARK: -
class ServerTrustPolicyCertificatesInBundleTestCase: ServerTrustPolicyTestCase {
func testOnlyValidCertificatesAreDetected() {
// Given
// Files present in bundle in the form of type+encoding+extension [key|cert][DER|PEM].[cer|crt|der|key|pem]
// certDER.cer: DER-encoded well-formed certificate
// certDER.crt: DER-encoded well-formed certificate
// certDER.der: DER-encoded well-formed certificate
// certPEM.*: PEM-encoded well-formed certificates, expected to fail: Apple API only handles DER encoding
// devURandomGibberish.crt: Random data, should fail
// keyDER.der: DER-encoded key, not a certificate, should fail
// When
let certificates = ServerTrustPolicy.certificates(
in: Bundle(for: ServerTrustPolicyCertificatesInBundleTestCase.self)
)
// Then
// Expectation: 19 well-formed certificates in the test bundle plus 4 invalid certificates.
#if os(macOS)
// For some reason, macOS is allowing all certificates to be considered valid. Need to file a
// rdar demonstrating this behavior.
if #available(OSX 10.12, *) {
XCTAssertEqual(certificates.count, 19, "Expected 19 well-formed certificates")
} else {
XCTAssertEqual(certificates.count, 23, "Expected 23 well-formed certificates")
}
#else
XCTAssertEqual(certificates.count, 19, "Expected 19 well-formed certificates")
#endif
}
}