Skip to content

Commit 9efc087

Browse files
committed
Got HTTPS tests working, fixed testStressGetHttpsSSLError for TS.
Added temporary code to disable certificate verification if required Fixed testStressGetHttpsSSLError() for TS: Need to check for Network.framework specific errors. Maybe NIOTransportServices should be translating these into an NIO error. (The Network.framework errors are not super unfriendly).
1 parent 9074ebe commit 9efc087

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

Sources/AsyncHTTPClient/Utils.swift

+43-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import Foundation
16+
import Network
1517
import NIO
1618
import NIOHTTP1
1719
import NIOHTTPCompression
@@ -63,7 +65,46 @@ extension ClientBootstrap {
6365
}
6466
}
6567

68+
// Used by temporary code below
69+
let tlsDispatchQueue = DispatchQueue(label: "TLSDispatch")
70+
6671
extension NIOClientTCPBootstrap {
72+
73+
// TEMPORARY: This is temporary code and an extended version of this should really be in NIOTransportServices. But this allows us to run tests and get results back
74+
// for the TLS tests
75+
#if canImport(Network)
76+
@available (macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
77+
fileprivate static func getTLSOptions(tlsConfiguration: TLSConfiguration?, queue: DispatchQueue) -> NWProtocolTLS.Options {
78+
guard let tlsConfiguration = tlsConfiguration else { return .init() }
79+
let options = NWProtocolTLS.Options()
80+
81+
sec_protocol_options_set_verify_block(options.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in
82+
let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
83+
84+
var error: CFError?
85+
if SecTrustEvaluateWithError(trust, &error) {
86+
sec_protocol_verify_complete(true)
87+
} else {
88+
// check error
89+
var errorCode: CFIndex = 0
90+
if let userInfo = CFErrorCopyUserInfo(error) {
91+
let userInfoDictionary = userInfo as NSDictionary
92+
let underlyingError = userInfoDictionary[kCFErrorUnderlyingErrorKey!] as! CFError
93+
errorCode = CFErrorGetCode(underlyingError)
94+
}
95+
if tlsConfiguration.certificateVerification == .none ||
96+
(tlsConfiguration.certificateVerification == .noHostnameVerification && errorCode == errSecNotTrusted) {
97+
sec_protocol_verify_complete(true)
98+
} else {
99+
sec_protocol_verify_complete(false)
100+
}
101+
}
102+
}, queue)
103+
104+
return options
105+
}
106+
#endif
107+
67108
/// create a TCP Bootstrap based off what type of `EventLoop` has been passed to the function.
68109
fileprivate static func makeBootstrap(
69110
on eventLoop: EventLoop,
@@ -80,7 +121,8 @@ extension NIOClientTCPBootstrap {
80121
let hostname = (!requiresTLS || host.isIPAddress) ? nil : host
81122
bootstrap = try NIOClientTCPBootstrap(NIOTSConnectionBootstrap(group: eventLoop), tls: NIOSSLClientTLSProvider(context: sslContext, serverHostname: hostname))
82123
} else {
83-
let tlsProvider = NIOTSClientTLSProvider(tlsOptions: .init())
124+
let parameters = NIOClientTCPBootstrap.getTLSOptions(tlsConfiguration: configuration.tlsConfiguration, queue: tlsDispatchQueue)
125+
let tlsProvider = NIOTSClientTLSProvider(tlsOptions: parameters)
84126
bootstrap = NIOClientTCPBootstrap(NIOTSConnectionBootstrap(group: eventLoop), tls: tlsProvider)
85127
}
86128
} else {

Tests/AsyncHTTPClientTests/HTTPClientTests.swift

+15
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
@testable import AsyncHTTPClient
16+
#if canImport(Network)
17+
import Network
18+
#endif
1619
import NIO
1720
import NIOConcurrencyHelpers
1821
import NIOFoundationCompat
@@ -1014,6 +1017,18 @@ class HTTPClientTests: XCTestCase {
10141017
XCTFail("Shouldn't succeed")
10151018
continue
10161019
case .failure(let error):
1020+
#if canImport(Network)
1021+
if isTestingNIOTS() {
1022+
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) {
1023+
guard let clientError = error as? NWError, case NWError.tls(let status) = clientError else {
1024+
XCTFail("Unexpected error: \(error)")
1025+
continue
1026+
}
1027+
XCTAssertEqual(status, errSSLHandshakeFail)
1028+
}
1029+
continue
1030+
}
1031+
#endif
10171032
guard let clientError = error as? NIOSSLError, case NIOSSLError.handshakeFailed = clientError else {
10181033
XCTFail("Unexpected error: \(error)")
10191034
continue

0 commit comments

Comments
 (0)