TLSEvaluationTests.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. // TLSEvaluationTests.swift
  2. //
  3. // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. import Alamofire
  23. import Foundation
  24. import XCTest
  25. private struct TestCertificates {
  26. static let RootCA = TestCertificates.certificateWithFileName("root-ca-disig")
  27. static let IntermediateCA = TestCertificates.certificateWithFileName("intermediate-ca-disig")
  28. static let Leaf = TestCertificates.certificateWithFileName("testssl-expire.disig.sk")
  29. static func certificateWithFileName(fileName: String) -> SecCertificate {
  30. class Bundle {}
  31. let filePath = NSBundle(forClass: Bundle.self).pathForResource(fileName, ofType: "cer")!
  32. let data = NSData(contentsOfFile: filePath)!
  33. let certificate = SecCertificateCreateWithData(nil, data)!
  34. return certificate
  35. }
  36. }
  37. // MARK: -
  38. private struct TestPublicKeys {
  39. static let RootCA = TestPublicKeys.publicKeyForCertificate(TestCertificates.RootCA)
  40. static let IntermediateCA = TestPublicKeys.publicKeyForCertificate(TestCertificates.IntermediateCA)
  41. static let Leaf = TestPublicKeys.publicKeyForCertificate(TestCertificates.Leaf)
  42. static func publicKeyForCertificate(certificate: SecCertificate) -> SecKey {
  43. let policy = SecPolicyCreateBasicX509()
  44. var trust: SecTrust?
  45. SecTrustCreateWithCertificates(certificate, policy, &trust)
  46. let publicKey = SecTrustCopyPublicKey(trust!)!
  47. return publicKey
  48. }
  49. }
  50. // MARK: -
  51. class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
  52. let URL = "https://testssl-expire.disig.sk/"
  53. let host = "testssl-expire.disig.sk"
  54. var configuration: NSURLSessionConfiguration!
  55. // MARK: Setup and Teardown
  56. override func setUp() {
  57. super.setUp()
  58. configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
  59. }
  60. // MARK: Default Behavior Tests
  61. func testThatExpiredCertificateRequestFailsWithNoServerTrustPolicy() {
  62. // Given
  63. weak var expectation = expectationWithDescription("\(URL)")
  64. let manager = Manager(configuration: configuration)
  65. var error: NSError?
  66. // When
  67. manager.request(.GET, URL)
  68. .response { _, _, _, responseError in
  69. error = responseError
  70. expectation?.fulfill()
  71. }
  72. waitForExpectationsWithTimeout(timeout, handler: nil)
  73. // Then
  74. XCTAssertNotNil(error, "error should not be nil")
  75. if let code = error?.code {
  76. XCTAssertEqual(code, NSURLErrorServerCertificateUntrusted, "code should be untrusted server certficate")
  77. } else {
  78. XCTFail("error should be an NSError")
  79. }
  80. }
  81. // MARK: Server Trust Policy - Perform Default Tests
  82. func testThatExpiredCertificateRequestFailsWithDefaultServerTrustPolicy() {
  83. // Given
  84. let policies = [host: ServerTrustPolicy.PerformDefaultEvaluation(validateHost: true)]
  85. let manager = Manager(
  86. configuration: configuration,
  87. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  88. )
  89. weak var expectation = expectationWithDescription("\(URL)")
  90. var error: NSError?
  91. // When
  92. manager.request(.GET, URL)
  93. .response { _, _, _, responseError in
  94. error = responseError
  95. expectation?.fulfill()
  96. }
  97. waitForExpectationsWithTimeout(timeout, handler: nil)
  98. // Then
  99. XCTAssertNotNil(error, "error should not be nil")
  100. if let code = error?.code {
  101. XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
  102. } else {
  103. XCTFail("error should be an NSError")
  104. }
  105. }
  106. // MARK: Server Trust Policy - Certificate Pinning Tests
  107. func testThatExpiredCertificateRequestFailsWhenPinningLeafCertificateWithCertificateChainValidation() {
  108. // Given
  109. let certificates = [TestCertificates.Leaf]
  110. let policies: [String: ServerTrustPolicy] = [
  111. host: .PinCertificates(certificates: certificates, validateCertificateChain: true, validateHost: true)
  112. ]
  113. let manager = Manager(
  114. configuration: configuration,
  115. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  116. )
  117. weak var expectation = expectationWithDescription("\(URL)")
  118. var error: NSError?
  119. // When
  120. manager.request(.GET, URL)
  121. .response { _, _, _, responseError in
  122. error = responseError
  123. expectation?.fulfill()
  124. }
  125. waitForExpectationsWithTimeout(timeout, handler: nil)
  126. // Then
  127. XCTAssertNotNil(error, "error should not be nil")
  128. if let code = error?.code {
  129. XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
  130. } else {
  131. XCTFail("error should be an NSError")
  132. }
  133. }
  134. func testThatExpiredCertificateRequestFailsWhenPinningAllCertificatesWithCertificateChainValidation() {
  135. // Given
  136. let certificates = [TestCertificates.Leaf, TestCertificates.IntermediateCA, TestCertificates.RootCA]
  137. let policies: [String: ServerTrustPolicy] = [
  138. host: .PinCertificates(certificates: certificates, validateCertificateChain: true, validateHost: true)
  139. ]
  140. let manager = Manager(
  141. configuration: configuration,
  142. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  143. )
  144. weak var expectation = expectationWithDescription("\(URL)")
  145. var error: NSError?
  146. // When
  147. manager.request(.GET, URL)
  148. .response { _, _, _, responseError in
  149. error = responseError
  150. expectation?.fulfill()
  151. }
  152. waitForExpectationsWithTimeout(timeout, handler: nil)
  153. // Then
  154. XCTAssertNotNil(error, "error should not be nil")
  155. if let code = error?.code {
  156. XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
  157. } else {
  158. XCTFail("error should be an NSError")
  159. }
  160. }
  161. func testThatExpiredCertificateRequestSucceedsWhenPinningLeafCertificateWithoutCertificateChainValidation() {
  162. // Given
  163. let certificates = [TestCertificates.Leaf]
  164. let policies: [String: ServerTrustPolicy] = [
  165. host: .PinCertificates(certificates: certificates, validateCertificateChain: false, validateHost: true)
  166. ]
  167. let manager = Manager(
  168. configuration: configuration,
  169. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  170. )
  171. weak var expectation = expectationWithDescription("\(URL)")
  172. var error: NSError?
  173. // When
  174. manager.request(.GET, URL)
  175. .response { _, _, _, responseError in
  176. error = responseError
  177. expectation?.fulfill()
  178. }
  179. waitForExpectationsWithTimeout(timeout, handler: nil)
  180. // Then
  181. XCTAssertNil(error, "error should be nil")
  182. }
  183. func testThatExpiredCertificateRequestSucceedsWhenPinningIntermediateCACertificateWithoutCertificateChainValidation() {
  184. // Given
  185. let certificates = [TestCertificates.IntermediateCA]
  186. let policies: [String: ServerTrustPolicy] = [
  187. host: .PinCertificates(certificates: certificates, validateCertificateChain: false, validateHost: true)
  188. ]
  189. let manager = Manager(
  190. configuration: configuration,
  191. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  192. )
  193. weak var expectation = expectationWithDescription("\(URL)")
  194. var error: NSError?
  195. // When
  196. manager.request(.GET, URL)
  197. .response { _, _, _, responseError in
  198. error = responseError
  199. expectation?.fulfill()
  200. }
  201. waitForExpectationsWithTimeout(timeout, handler: nil)
  202. // Then
  203. XCTAssertNil(error, "error should be nil")
  204. }
  205. func testThatExpiredCertificateRequestSucceedsWhenPinningRootCACertificateWithoutCertificateChainValidation() {
  206. // Given
  207. let certificates = [TestCertificates.RootCA]
  208. let policies: [String: ServerTrustPolicy] = [
  209. host: .PinCertificates(certificates: certificates, validateCertificateChain: false, validateHost: true)
  210. ]
  211. let manager = Manager(
  212. configuration: configuration,
  213. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  214. )
  215. weak var expectation = expectationWithDescription("\(URL)")
  216. var error: NSError?
  217. // When
  218. manager.request(.GET, URL)
  219. .response { _, _, _, responseError in
  220. error = responseError
  221. expectation?.fulfill()
  222. }
  223. waitForExpectationsWithTimeout(timeout, handler: nil)
  224. // Then
  225. XCTAssertNil(error, "error should be nil")
  226. }
  227. // MARK: Server Trust Policy - Public Key Pinning Tests
  228. func testThatExpiredCertificateRequestFailsWhenPinningLeafPublicKeyWithCertificateChainValidation() {
  229. // Given
  230. let publicKeys = [TestPublicKeys.Leaf]
  231. let policies: [String: ServerTrustPolicy] = [
  232. host: .PinPublicKeys(publicKeys: publicKeys, validateCertificateChain: true, validateHost: true)
  233. ]
  234. let manager = Manager(
  235. configuration: configuration,
  236. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  237. )
  238. weak var expectation = expectationWithDescription("\(URL)")
  239. var error: NSError?
  240. // When
  241. manager.request(.GET, URL)
  242. .response { _, _, _, responseError in
  243. error = responseError
  244. expectation?.fulfill()
  245. }
  246. waitForExpectationsWithTimeout(timeout, handler: nil)
  247. // Then
  248. XCTAssertNotNil(error, "error should not be nil")
  249. if let code = error?.code {
  250. XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
  251. } else {
  252. XCTFail("error should be an NSError")
  253. }
  254. }
  255. func testThatExpiredCertificateRequestSucceedsWhenPinningLeafPublicKeyWithoutCertificateChainValidation() {
  256. // Given
  257. let publicKeys = [TestPublicKeys.Leaf]
  258. let policies: [String: ServerTrustPolicy] = [
  259. host: .PinPublicKeys(publicKeys: publicKeys, validateCertificateChain: false, validateHost: true)
  260. ]
  261. let manager = Manager(
  262. configuration: configuration,
  263. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  264. )
  265. weak var expectation = expectationWithDescription("\(URL)")
  266. var error: NSError?
  267. // When
  268. manager.request(.GET, URL)
  269. .response { _, _, _, responseError in
  270. error = responseError
  271. expectation?.fulfill()
  272. }
  273. waitForExpectationsWithTimeout(timeout, handler: nil)
  274. // Then
  275. XCTAssertNil(error, "error should be nil")
  276. }
  277. func testThatExpiredCertificateRequestSucceedsWhenPinningIntermediateCAPublicKeyWithoutCertificateChainValidation() {
  278. // Given
  279. let publicKeys = [TestPublicKeys.IntermediateCA]
  280. let policies: [String: ServerTrustPolicy] = [
  281. host: .PinPublicKeys(publicKeys: publicKeys, validateCertificateChain: false, validateHost: true)
  282. ]
  283. let manager = Manager(
  284. configuration: configuration,
  285. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  286. )
  287. weak var expectation = expectationWithDescription("\(URL)")
  288. var error: NSError?
  289. // When
  290. manager.request(.GET, URL)
  291. .response { _, _, _, responseError in
  292. error = responseError
  293. expectation?.fulfill()
  294. }
  295. waitForExpectationsWithTimeout(timeout, handler: nil)
  296. // Then
  297. XCTAssertNil(error, "error should be nil")
  298. }
  299. func testThatExpiredCertificateRequestSucceedsWhenPinningRootCAPublicKeyWithoutCertificateChainValidation() {
  300. // Given
  301. let publicKeys = [TestPublicKeys.RootCA]
  302. let policies: [String: ServerTrustPolicy] = [
  303. host: .PinPublicKeys(publicKeys: publicKeys, validateCertificateChain: false, validateHost: true)
  304. ]
  305. let manager = Manager(
  306. configuration: configuration,
  307. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  308. )
  309. weak var expectation = expectationWithDescription("\(URL)")
  310. var error: NSError?
  311. // When
  312. manager.request(.GET, URL)
  313. .response { _, _, _, responseError in
  314. error = responseError
  315. expectation?.fulfill()
  316. }
  317. waitForExpectationsWithTimeout(timeout, handler: nil)
  318. // Then
  319. XCTAssertNil(error, "error should be nil")
  320. }
  321. // MARK: Server Trust Policy - Disabling Evaluation Tests
  322. func testThatExpiredCertificateRequestSucceedsWhenDisablingEvaluation() {
  323. // Given
  324. let policies = [host: ServerTrustPolicy.DisableEvaluation]
  325. let manager = Manager(
  326. configuration: configuration,
  327. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  328. )
  329. weak var expectation = expectationWithDescription("\(URL)")
  330. var error: NSError?
  331. // When
  332. manager.request(.GET, URL)
  333. .response { _, _, _, responseError in
  334. error = responseError
  335. expectation?.fulfill()
  336. }
  337. waitForExpectationsWithTimeout(timeout, handler: nil)
  338. // Then
  339. XCTAssertNil(error, "error should be nil")
  340. }
  341. // MARK: Server Trust Policy - Custom Evaluation Tests
  342. func testThatExpiredCertificateRequestSucceedsWhenCustomEvaluationReturnsTrue() {
  343. // Given
  344. let policies = [
  345. host: ServerTrustPolicy.CustomEvaluation { _, _ in
  346. // Implement a custom evaluation routine here...
  347. return true
  348. }
  349. ]
  350. let manager = Manager(
  351. configuration: configuration,
  352. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  353. )
  354. weak var expectation = expectationWithDescription("\(URL)")
  355. var error: NSError?
  356. // When
  357. manager.request(.GET, URL)
  358. .response { _, _, _, responseError in
  359. error = responseError
  360. expectation?.fulfill()
  361. }
  362. waitForExpectationsWithTimeout(timeout, handler: nil)
  363. // Then
  364. XCTAssertNil(error, "error should be nil")
  365. }
  366. func testThatExpiredCertificateRequestFailsWhenCustomEvaluationReturnsFalse() {
  367. // Given
  368. let policies = [
  369. host: ServerTrustPolicy.CustomEvaluation { _, _ in
  370. // Implement a custom evaluation routine here...
  371. return false
  372. }
  373. ]
  374. let manager = Manager(
  375. configuration: configuration,
  376. serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
  377. )
  378. weak var expectation = expectationWithDescription("\(URL)")
  379. var error: NSError?
  380. // When
  381. manager.request(.GET, URL)
  382. .response { _, _, _, responseError in
  383. error = responseError
  384. expectation?.fulfill()
  385. }
  386. waitForExpectationsWithTimeout(timeout, handler: nil)
  387. // Then
  388. XCTAssertNotNil(error, "error should not be nil")
  389. if let code = error?.code {
  390. XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
  391. } else {
  392. XCTFail("error should be an NSError")
  393. }
  394. }
  395. }