mirror of
https://github.com/swift-server/async-http-client.git
synced 2026-06-02 07:37:34 +00:00
SwiftFormat --ifdef no-indent (#494)
* SwiftFormat --ifdef no-indent * update `generate_linux_tests.rb` to use new indention rule
This commit is contained in:
@@ -21,7 +21,7 @@ import NIOSOCKS
|
||||
import NIOSSL
|
||||
import NIOTLS
|
||||
#if canImport(Network)
|
||||
import NIOTransportServices
|
||||
import NIOTransportServices
|
||||
#endif
|
||||
|
||||
extension HTTPConnectionPool {
|
||||
@@ -341,18 +341,18 @@ extension HTTPConnectionPool.ConnectionFactory {
|
||||
|
||||
private func makePlainBootstrap(deadline: NIODeadline, eventLoop: EventLoop) -> NIOClientTCPBootstrapProtocol {
|
||||
#if canImport(Network)
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
|
||||
return tsBootstrap
|
||||
.connectTimeout(deadline - NIODeadline.now())
|
||||
.channelInitializer { channel in
|
||||
do {
|
||||
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
|
||||
return channel.eventLoop.makeSucceededVoidFuture()
|
||||
} catch {
|
||||
return channel.eventLoop.makeFailedFuture(error)
|
||||
}
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
|
||||
return tsBootstrap
|
||||
.connectTimeout(deadline - NIODeadline.now())
|
||||
.channelInitializer { channel in
|
||||
do {
|
||||
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
|
||||
return channel.eventLoop.makeSucceededVoidFuture()
|
||||
} catch {
|
||||
return channel.eventLoop.makeFailedFuture(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if let nioBootstrap = ClientBootstrap(validatingGroup: eventLoop) {
|
||||
@@ -392,10 +392,10 @@ extension HTTPConnectionPool.ConnectionFactory {
|
||||
}
|
||||
|
||||
#if canImport(Network)
|
||||
// If NIOTransportSecurity is used, we want to map NWErrors into NWPOsixErrors or NWTLSError.
|
||||
channelFuture = channelFuture.flatMapErrorThrowing { error in
|
||||
throw HTTPClient.NWErrorHandler.translateError(error)
|
||||
}
|
||||
// If NIOTransportSecurity is used, we want to map NWErrors into NWPOsixErrors or NWTLSError.
|
||||
channelFuture = channelFuture.flatMapErrorThrowing { error in
|
||||
throw HTTPClient.NWErrorHandler.translateError(error)
|
||||
}
|
||||
#endif
|
||||
|
||||
return channelFuture
|
||||
@@ -416,29 +416,29 @@ extension HTTPConnectionPool.ConnectionFactory {
|
||||
}
|
||||
|
||||
#if canImport(Network)
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
|
||||
// create NIOClientTCPBootstrap with NIOTS TLS provider
|
||||
let bootstrapFuture = tlsConfig.getNWProtocolTLSOptions(on: eventLoop).map {
|
||||
options -> NIOClientTCPBootstrapProtocol in
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *), let tsBootstrap = NIOTSConnectionBootstrap(validatingGroup: eventLoop) {
|
||||
// create NIOClientTCPBootstrap with NIOTS TLS provider
|
||||
let bootstrapFuture = tlsConfig.getNWProtocolTLSOptions(on: eventLoop).map {
|
||||
options -> NIOClientTCPBootstrapProtocol in
|
||||
|
||||
tsBootstrap
|
||||
.connectTimeout(deadline - NIODeadline.now())
|
||||
.tlsOptions(options)
|
||||
.channelInitializer { channel in
|
||||
do {
|
||||
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
|
||||
// we don't need to set a TLS deadline for NIOTS connections, since the
|
||||
// TLS handshake is part of the TS connection bootstrap. If the TLS
|
||||
// handshake times out the complete connection creation will be failed.
|
||||
try channel.pipeline.syncOperations.addHandler(TLSEventsHandler(deadline: nil))
|
||||
return channel.eventLoop.makeSucceededVoidFuture()
|
||||
} catch {
|
||||
return channel.eventLoop.makeFailedFuture(error)
|
||||
}
|
||||
} as NIOClientTCPBootstrapProtocol
|
||||
}
|
||||
return bootstrapFuture
|
||||
tsBootstrap
|
||||
.connectTimeout(deadline - NIODeadline.now())
|
||||
.tlsOptions(options)
|
||||
.channelInitializer { channel in
|
||||
do {
|
||||
try channel.pipeline.syncOperations.addHandler(HTTPClient.NWErrorHandler())
|
||||
// we don't need to set a TLS deadline for NIOTS connections, since the
|
||||
// TLS handshake is part of the TS connection bootstrap. If the TLS
|
||||
// handshake times out the complete connection creation will be failed.
|
||||
try channel.pipeline.syncOperations.addHandler(TLSEventsHandler(deadline: nil))
|
||||
return channel.eventLoop.makeSucceededVoidFuture()
|
||||
} catch {
|
||||
return channel.eventLoop.makeFailedFuture(error)
|
||||
}
|
||||
} as NIOClientTCPBootstrapProtocol
|
||||
}
|
||||
return bootstrapFuture
|
||||
}
|
||||
#endif
|
||||
|
||||
let host = self.key.host
|
||||
|
||||
+2
-2
@@ -14,9 +14,9 @@
|
||||
|
||||
import NIOCore
|
||||
#if canImport(Darwin)
|
||||
import func Darwin.pow
|
||||
import func Darwin.pow
|
||||
#else
|
||||
import func Glibc.pow
|
||||
import func Glibc.pow
|
||||
#endif
|
||||
|
||||
extension HTTPConnectionPool {
|
||||
|
||||
@@ -99,13 +99,13 @@ public class HTTPClient {
|
||||
self.eventLoopGroup = group
|
||||
case .createNew:
|
||||
#if canImport(Network)
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) {
|
||||
self.eventLoopGroup = NIOTSEventLoopGroup()
|
||||
} else {
|
||||
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||
}
|
||||
#else
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) {
|
||||
self.eventLoopGroup = NIOTSEventLoopGroup()
|
||||
} else {
|
||||
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||
}
|
||||
#else
|
||||
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||
#endif
|
||||
}
|
||||
self.configuration = configuration
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if canImport(Network)
|
||||
import Network
|
||||
import Network
|
||||
#endif
|
||||
import NIOCore
|
||||
import NIOHTTP1
|
||||
@@ -21,43 +21,43 @@ import NIOTransportServices
|
||||
|
||||
extension HTTPClient {
|
||||
#if canImport(Network)
|
||||
public struct NWPOSIXError: Error, CustomStringConvertible {
|
||||
/// POSIX error code (enum)
|
||||
public let errorCode: POSIXErrorCode
|
||||
public struct NWPOSIXError: Error, CustomStringConvertible {
|
||||
/// POSIX error code (enum)
|
||||
public let errorCode: POSIXErrorCode
|
||||
|
||||
/// actual reason, in human readable form
|
||||
private let reason: String
|
||||
/// actual reason, in human readable form
|
||||
private let reason: String
|
||||
|
||||
/// Initialise a NWPOSIXError
|
||||
/// - Parameters:
|
||||
/// - errorType: posix error type
|
||||
/// - reason: String describing reason for error
|
||||
public init(_ errorCode: POSIXErrorCode, reason: String) {
|
||||
self.errorCode = errorCode
|
||||
self.reason = reason
|
||||
}
|
||||
|
||||
public var description: String { return self.reason }
|
||||
/// Initialise a NWPOSIXError
|
||||
/// - Parameters:
|
||||
/// - errorType: posix error type
|
||||
/// - reason: String describing reason for error
|
||||
public init(_ errorCode: POSIXErrorCode, reason: String) {
|
||||
self.errorCode = errorCode
|
||||
self.reason = reason
|
||||
}
|
||||
|
||||
public struct NWTLSError: Error, CustomStringConvertible {
|
||||
/// TLS error status. List of TLS errors can be found in <Security/SecureTransport.h>
|
||||
public let status: OSStatus
|
||||
public var description: String { return self.reason }
|
||||
}
|
||||
|
||||
/// actual reason, in human readable form
|
||||
private let reason: String
|
||||
public struct NWTLSError: Error, CustomStringConvertible {
|
||||
/// TLS error status. List of TLS errors can be found in <Security/SecureTransport.h>
|
||||
public let status: OSStatus
|
||||
|
||||
/// initialise a NWTLSError
|
||||
/// - Parameters:
|
||||
/// - status: TLS status
|
||||
/// - reason: String describing reason for error
|
||||
public init(_ status: OSStatus, reason: String) {
|
||||
self.status = status
|
||||
self.reason = reason
|
||||
}
|
||||
/// actual reason, in human readable form
|
||||
private let reason: String
|
||||
|
||||
public var description: String { return self.reason }
|
||||
/// initialise a NWTLSError
|
||||
/// - Parameters:
|
||||
/// - status: TLS status
|
||||
/// - reason: String describing reason for error
|
||||
public init(_ status: OSStatus, reason: String) {
|
||||
self.status = status
|
||||
self.reason = reason
|
||||
}
|
||||
|
||||
public var description: String { return self.reason }
|
||||
}
|
||||
#endif
|
||||
|
||||
class NWErrorHandler: ChannelInboundHandler {
|
||||
@@ -69,23 +69,23 @@ extension HTTPClient {
|
||||
|
||||
static func translateError(_ error: Error) -> Error {
|
||||
#if canImport(Network)
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) {
|
||||
if let error = error as? NWError {
|
||||
switch error {
|
||||
case .tls(let status):
|
||||
return NWTLSError(status, reason: error.localizedDescription)
|
||||
case .posix(let errorCode):
|
||||
return NWPOSIXError(errorCode, reason: error.localizedDescription)
|
||||
default:
|
||||
return error
|
||||
}
|
||||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) {
|
||||
if let error = error as? NWError {
|
||||
switch error {
|
||||
case .tls(let status):
|
||||
return NWTLSError(status, reason: error.localizedDescription)
|
||||
case .posix(let errorCode):
|
||||
return NWPOSIXError(errorCode, reason: error.localizedDescription)
|
||||
default:
|
||||
return error
|
||||
}
|
||||
return error
|
||||
} else {
|
||||
preconditionFailure("\(self) used on a non-NIOTS Channel")
|
||||
}
|
||||
#else
|
||||
return error
|
||||
} else {
|
||||
preconditionFailure("\(self) used on a non-NIOTS Channel")
|
||||
}
|
||||
#else
|
||||
preconditionFailure("\(self) used on a non-NIOTS Channel")
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,188 +14,188 @@
|
||||
|
||||
#if canImport(Network)
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
import NIOCore
|
||||
import NIOSSL
|
||||
import NIOTransportServices
|
||||
import Foundation
|
||||
import Network
|
||||
import NIOCore
|
||||
import NIOSSL
|
||||
import NIOTransportServices
|
||||
|
||||
extension TLSVersion {
|
||||
/// return Network framework TLS protocol version
|
||||
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
var nwTLSProtocolVersion: tls_protocol_version_t {
|
||||
switch self {
|
||||
case .tlsv1:
|
||||
return .TLSv10
|
||||
case .tlsv11:
|
||||
return .TLSv11
|
||||
case .tlsv12:
|
||||
return .TLSv12
|
||||
case .tlsv13:
|
||||
return .TLSv13
|
||||
}
|
||||
extension TLSVersion {
|
||||
/// return Network framework TLS protocol version
|
||||
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
var nwTLSProtocolVersion: tls_protocol_version_t {
|
||||
switch self {
|
||||
case .tlsv1:
|
||||
return .TLSv10
|
||||
case .tlsv11:
|
||||
return .TLSv11
|
||||
case .tlsv12:
|
||||
return .TLSv12
|
||||
case .tlsv13:
|
||||
return .TLSv13
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TLSVersion {
|
||||
/// return as SSL protocol
|
||||
var sslProtocol: SSLProtocol {
|
||||
switch self {
|
||||
case .tlsv1:
|
||||
return .tlsProtocol1
|
||||
case .tlsv11:
|
||||
return .tlsProtocol11
|
||||
case .tlsv12:
|
||||
return .tlsProtocol12
|
||||
case .tlsv13:
|
||||
return .tlsProtocol13
|
||||
}
|
||||
extension TLSVersion {
|
||||
/// return as SSL protocol
|
||||
var sslProtocol: SSLProtocol {
|
||||
switch self {
|
||||
case .tlsv1:
|
||||
return .tlsProtocol1
|
||||
case .tlsv11:
|
||||
return .tlsProtocol11
|
||||
case .tlsv12:
|
||||
return .tlsProtocol12
|
||||
case .tlsv13:
|
||||
return .tlsProtocol13
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
|
||||
extension TLSConfiguration {
|
||||
/// Dispatch queue used by Network framework TLS to control certificate verification
|
||||
static var tlsDispatchQueue = DispatchQueue(label: "TLSDispatch")
|
||||
@available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
|
||||
extension TLSConfiguration {
|
||||
/// Dispatch queue used by Network framework TLS to control certificate verification
|
||||
static var tlsDispatchQueue = DispatchQueue(label: "TLSDispatch")
|
||||
|
||||
/// create NWProtocolTLS.Options for use with NIOTransportServices from the NIOSSL TLSConfiguration
|
||||
///
|
||||
/// - Parameter eventLoop: EventLoop to wait for creation of options on
|
||||
/// - Returns: Future holding NWProtocolTLS Options
|
||||
func getNWProtocolTLSOptions(on eventLoop: EventLoop) -> EventLoopFuture<NWProtocolTLS.Options> {
|
||||
let promise = eventLoop.makePromise(of: NWProtocolTLS.Options.self)
|
||||
Self.tlsDispatchQueue.async {
|
||||
do {
|
||||
let options = try self.getNWProtocolTLSOptions()
|
||||
promise.succeed(options)
|
||||
} catch {
|
||||
promise.fail(error)
|
||||
}
|
||||
/// create NWProtocolTLS.Options for use with NIOTransportServices from the NIOSSL TLSConfiguration
|
||||
///
|
||||
/// - Parameter eventLoop: EventLoop to wait for creation of options on
|
||||
/// - Returns: Future holding NWProtocolTLS Options
|
||||
func getNWProtocolTLSOptions(on eventLoop: EventLoop) -> EventLoopFuture<NWProtocolTLS.Options> {
|
||||
let promise = eventLoop.makePromise(of: NWProtocolTLS.Options.self)
|
||||
Self.tlsDispatchQueue.async {
|
||||
do {
|
||||
let options = try self.getNWProtocolTLSOptions()
|
||||
promise.succeed(options)
|
||||
} catch {
|
||||
promise.fail(error)
|
||||
}
|
||||
return promise.futureResult
|
||||
}
|
||||
return promise.futureResult
|
||||
}
|
||||
|
||||
/// create NWProtocolTLS.Options for use with NIOTransportServices from the NIOSSL TLSConfiguration
|
||||
///
|
||||
/// - Returns: Equivalent NWProtocolTLS Options
|
||||
func getNWProtocolTLSOptions() throws -> NWProtocolTLS.Options {
|
||||
let options = NWProtocolTLS.Options()
|
||||
|
||||
let useMTELGExplainer = """
|
||||
You can still use this configuration option on macOS if you initialize HTTPClient \
|
||||
with a MultiThreadedEventLoopGroup. Please note that using MultiThreadedEventLoopGroup \
|
||||
will make AsyncHTTPClient use NIO on BSD Sockets and not Network.framework (which is the preferred \
|
||||
platform networking stack).
|
||||
"""
|
||||
|
||||
// minimum TLS protocol
|
||||
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, self.minimumTLSVersion.nwTLSProtocolVersion)
|
||||
} else {
|
||||
sec_protocol_options_set_tls_min_version(options.securityProtocolOptions, self.minimumTLSVersion.sslProtocol)
|
||||
}
|
||||
|
||||
/// create NWProtocolTLS.Options for use with NIOTransportServices from the NIOSSL TLSConfiguration
|
||||
///
|
||||
/// - Returns: Equivalent NWProtocolTLS Options
|
||||
func getNWProtocolTLSOptions() throws -> NWProtocolTLS.Options {
|
||||
let options = NWProtocolTLS.Options()
|
||||
|
||||
let useMTELGExplainer = """
|
||||
You can still use this configuration option on macOS if you initialize HTTPClient \
|
||||
with a MultiThreadedEventLoopGroup. Please note that using MultiThreadedEventLoopGroup \
|
||||
will make AsyncHTTPClient use NIO on BSD Sockets and not Network.framework (which is the preferred \
|
||||
platform networking stack).
|
||||
"""
|
||||
|
||||
// minimum TLS protocol
|
||||
// maximum TLS protocol
|
||||
if let maximumTLSVersion = self.maximumTLSVersion {
|
||||
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
sec_protocol_options_set_min_tls_protocol_version(options.securityProtocolOptions, self.minimumTLSVersion.nwTLSProtocolVersion)
|
||||
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, maximumTLSVersion.nwTLSProtocolVersion)
|
||||
} else {
|
||||
sec_protocol_options_set_tls_min_version(options.securityProtocolOptions, self.minimumTLSVersion.sslProtocol)
|
||||
sec_protocol_options_set_tls_max_version(options.securityProtocolOptions, maximumTLSVersion.sslProtocol)
|
||||
}
|
||||
|
||||
// maximum TLS protocol
|
||||
if let maximumTLSVersion = self.maximumTLSVersion {
|
||||
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
sec_protocol_options_set_max_tls_protocol_version(options.securityProtocolOptions, maximumTLSVersion.nwTLSProtocolVersion)
|
||||
} else {
|
||||
sec_protocol_options_set_tls_max_version(options.securityProtocolOptions, maximumTLSVersion.sslProtocol)
|
||||
}
|
||||
}
|
||||
|
||||
// application protocols
|
||||
for applicationProtocol in self.applicationProtocols {
|
||||
applicationProtocol.withCString { buffer in
|
||||
sec_protocol_options_add_tls_application_protocol(options.securityProtocolOptions, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
// the certificate chain
|
||||
if self.certificateChain.count > 0 {
|
||||
preconditionFailure("TLSConfiguration.certificateChain is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// cipher suites
|
||||
if self.cipherSuites.count > 0 {
|
||||
// TODO: Requires NIOSSL to provide list of cipher values before we can continue
|
||||
// https://github.com/apple/swift-nio-ssl/issues/207
|
||||
}
|
||||
|
||||
// key log callback
|
||||
if self.keyLogCallback != nil {
|
||||
preconditionFailure("TLSConfiguration.keyLogCallback is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// the certificate chain
|
||||
if self.certificateChain.count > 0 {
|
||||
preconditionFailure("TLSConfiguration.certificateChain is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// private key
|
||||
if self.privateKey != nil {
|
||||
preconditionFailure("TLSConfiguration.privateKey is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// renegotiation support key is unsupported
|
||||
|
||||
// trust roots
|
||||
var secTrustRoots: [SecCertificate]?
|
||||
switch trustRoots {
|
||||
case .some(.certificates(let certificates)):
|
||||
secTrustRoots = try certificates.compactMap { certificate in
|
||||
try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData)
|
||||
}
|
||||
case .some(.file(let file)):
|
||||
let certificates = try NIOSSLCertificate.fromPEMFile(file)
|
||||
secTrustRoots = try certificates.compactMap { certificate in
|
||||
try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData)
|
||||
}
|
||||
|
||||
case .some(.default), .none:
|
||||
break
|
||||
}
|
||||
|
||||
precondition(self.certificateVerification != .noHostnameVerification,
|
||||
"TLSConfiguration.certificateVerification = .noHostnameVerification is not supported. \(useMTELGExplainer)")
|
||||
|
||||
if certificateVerification != .fullVerification || trustRoots != nil {
|
||||
// add verify block to control certificate verification
|
||||
sec_protocol_options_set_verify_block(
|
||||
options.securityProtocolOptions,
|
||||
{ _, sec_trust, sec_protocol_verify_complete in
|
||||
guard self.certificateVerification != .none else {
|
||||
sec_protocol_verify_complete(true)
|
||||
return
|
||||
}
|
||||
|
||||
let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
|
||||
if let trustRootCertificates = secTrustRoots {
|
||||
SecTrustSetAnchorCertificates(trust, trustRootCertificates as CFArray)
|
||||
}
|
||||
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
dispatchPrecondition(condition: .onQueue(Self.tlsDispatchQueue))
|
||||
SecTrustEvaluateAsyncWithError(trust, Self.tlsDispatchQueue) { _, result, error in
|
||||
if let error = error {
|
||||
print("Trust failed: \(error.localizedDescription)")
|
||||
}
|
||||
sec_protocol_verify_complete(result)
|
||||
}
|
||||
} else {
|
||||
SecTrustEvaluateAsync(trust, Self.tlsDispatchQueue) { _, result in
|
||||
switch result {
|
||||
case .proceed, .unspecified:
|
||||
sec_protocol_verify_complete(true)
|
||||
default:
|
||||
sec_protocol_verify_complete(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Self.tlsDispatchQueue
|
||||
)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// application protocols
|
||||
for applicationProtocol in self.applicationProtocols {
|
||||
applicationProtocol.withCString { buffer in
|
||||
sec_protocol_options_add_tls_application_protocol(options.securityProtocolOptions, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
// the certificate chain
|
||||
if self.certificateChain.count > 0 {
|
||||
preconditionFailure("TLSConfiguration.certificateChain is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// cipher suites
|
||||
if self.cipherSuites.count > 0 {
|
||||
// TODO: Requires NIOSSL to provide list of cipher values before we can continue
|
||||
// https://github.com/apple/swift-nio-ssl/issues/207
|
||||
}
|
||||
|
||||
// key log callback
|
||||
if self.keyLogCallback != nil {
|
||||
preconditionFailure("TLSConfiguration.keyLogCallback is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// the certificate chain
|
||||
if self.certificateChain.count > 0 {
|
||||
preconditionFailure("TLSConfiguration.certificateChain is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// private key
|
||||
if self.privateKey != nil {
|
||||
preconditionFailure("TLSConfiguration.privateKey is not supported. \(useMTELGExplainer)")
|
||||
}
|
||||
|
||||
// renegotiation support key is unsupported
|
||||
|
||||
// trust roots
|
||||
var secTrustRoots: [SecCertificate]?
|
||||
switch trustRoots {
|
||||
case .some(.certificates(let certificates)):
|
||||
secTrustRoots = try certificates.compactMap { certificate in
|
||||
try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData)
|
||||
}
|
||||
case .some(.file(let file)):
|
||||
let certificates = try NIOSSLCertificate.fromPEMFile(file)
|
||||
secTrustRoots = try certificates.compactMap { certificate in
|
||||
try SecCertificateCreateWithData(nil, Data(certificate.toDERBytes()) as CFData)
|
||||
}
|
||||
|
||||
case .some(.default), .none:
|
||||
break
|
||||
}
|
||||
|
||||
precondition(self.certificateVerification != .noHostnameVerification,
|
||||
"TLSConfiguration.certificateVerification = .noHostnameVerification is not supported. \(useMTELGExplainer)")
|
||||
|
||||
if certificateVerification != .fullVerification || trustRoots != nil {
|
||||
// add verify block to control certificate verification
|
||||
sec_protocol_options_set_verify_block(
|
||||
options.securityProtocolOptions,
|
||||
{ _, sec_trust, sec_protocol_verify_complete in
|
||||
guard self.certificateVerification != .none else {
|
||||
sec_protocol_verify_complete(true)
|
||||
return
|
||||
}
|
||||
|
||||
let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
|
||||
if let trustRootCertificates = secTrustRoots {
|
||||
SecTrustSetAnchorCertificates(trust, trustRootCertificates as CFArray)
|
||||
}
|
||||
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
dispatchPrecondition(condition: .onQueue(Self.tlsDispatchQueue))
|
||||
SecTrustEvaluateAsyncWithError(trust, Self.tlsDispatchQueue) { _, result, error in
|
||||
if let error = error {
|
||||
print("Trust failed: \(error.localizedDescription)")
|
||||
}
|
||||
sec_protocol_verify_complete(result)
|
||||
}
|
||||
} else {
|
||||
SecTrustEvaluateAsync(trust, Self.tlsDispatchQueue) { _, result in
|
||||
switch result {
|
||||
case .proceed, .unspecified:
|
||||
sec_protocol_verify_complete(true)
|
||||
default:
|
||||
sec_protocol_verify_complete(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Self.tlsDispatchQueue
|
||||
)
|
||||
}
|
||||
return options
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user