Skip to content

Commit

Permalink
FoundationNetworking/URLSessionConfiguration: Add URLCredential
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviermartin committed May 9, 2024
1 parent a61d54a commit bf338c8
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 6 deletions.
4 changes: 4 additions & 0 deletions Sources/FoundationNetworking/URLSession/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ internal extension URLSession {
let shouldUseExtendedBackgroundIdleMode: Bool

let protocolClasses: [AnyClass]?

/// The credentials to use for connecting to servers
let clientCredential: URLCredential?
}
}
internal extension URLSession._Configuration {
Expand All @@ -100,6 +103,7 @@ internal extension URLSession._Configuration {
urlCache = config.urlCache
shouldUseExtendedBackgroundIdleMode = config.shouldUseExtendedBackgroundIdleMode
protocolClasses = config.protocolClasses
clientCredential = config.clientCredential
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,14 @@ internal class _HTTPURLProtocol: _NativeProtocol {
}
let session = task?.session as! URLSession
let _config = session._configuration
easyHandle.set(sessionConfig: _config)
do {
try easyHandle.set(sessionConfig: _config)
} catch {
self.internalState = .transferFailed
let nsError = error as? NSError ?? NSError(domain: NSURLErrorDomain, code: NSURLErrorUserAuthenticationRequired)
failWith(error: nsError, request: request)
return
}
easyHandle.setAllowedProtocolsToHTTPAndHTTPS()
easyHandle.set(preferredReceiveBufferSize: Int.max)
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ open class URLSessionConfiguration : NSObject, NSCopying {
urlCredentialStorage: .shared,
urlCache: .shared,
shouldUseExtendedBackgroundIdleMode: false,
protocolClasses: [_HTTPURLProtocol.self, _FTPURLProtocol.self, _WebSocketURLProtocol.self])
protocolClasses: [_HTTPURLProtocol.self, _FTPURLProtocol.self, _WebSocketURLProtocol.self],
clientCredential: nil)
}

private init(identifier: String?,
requestCachePolicy: URLRequest.CachePolicy,
timeoutIntervalForRequest: TimeInterval,
Expand All @@ -95,7 +96,8 @@ open class URLSessionConfiguration : NSObject, NSCopying {
urlCredentialStorage: URLCredentialStorage?,
urlCache: URLCache?,
shouldUseExtendedBackgroundIdleMode: Bool,
protocolClasses: [AnyClass]?)
protocolClasses: [AnyClass]?,
clientCredential: URLCredential?)
{
self.identifier = identifier
self.requestCachePolicy = requestCachePolicy
Expand All @@ -115,6 +117,7 @@ open class URLSessionConfiguration : NSObject, NSCopying {
self.urlCache = urlCache
self.shouldUseExtendedBackgroundIdleMode = shouldUseExtendedBackgroundIdleMode
self.protocolClasses = protocolClasses
self.clientCredential = clientCredential
}

open override func copy() -> Any {
Expand All @@ -140,7 +143,8 @@ open class URLSessionConfiguration : NSObject, NSCopying {
urlCredentialStorage: urlCredentialStorage,
urlCache: urlCache,
shouldUseExtendedBackgroundIdleMode: shouldUseExtendedBackgroundIdleMode,
protocolClasses: protocolClasses)
protocolClasses: protocolClasses,
clientCredential: clientCredential)
}

open class var `default`: URLSessionConfiguration {
Expand Down Expand Up @@ -258,6 +262,8 @@ open class URLSessionConfiguration : NSObject, NSCopying {
@available(*, unavailable, message: "Not available on non-Darwin platforms")
open var multipathServiceType: URLSessionConfiguration.MultipathServiceType { NSUnsupported() }

/* Optional client credential to be used when connecting to servers */
open var clientCredential: URLCredential?
}

@available(*, unavailable, message: "Not available on non-Darwin platforms")
Expand Down
49 changes: 48 additions & 1 deletion Sources/FoundationNetworking/URLSession/libcurl/EasyHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,55 @@ extension _EasyHandle {
}
}

func set(sessionConfig config: URLSession._Configuration) {
func set(sessionConfig config: URLSession._Configuration) throws {
_config = config
if let c = _config, let clientCredential = c.clientCredential {
// For TLS client certificate authentication
if var privateClientKey = clientCredential.privateClientKey,
var privateClientCertificate = clientCredential.privateClientCertificate {
// Key and certificate are expected to be in DER format
"DER".withCString {
let mutablePointer = UnsafeMutablePointer(mutating: $0)
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSSLKEYTYPE, mutablePointer).asError()
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSSLCERTTYPE, mutablePointer).asError()
}

#if !NS_CURL_MISSING_CURLINFO_SSLKEY_BLOB
privateClientKey.withUnsafeMutableBytes {
if let baseAddress = $0.baseAddress {
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLKEY_BLOB,
baseAddress, $0.count).asError()
}
}
#endif // !NS_CURL_MISSING_CURLINFO_SSLKEY_BLOB

#if !NS_CURL_MISSING_CURLINFO_SSLCERT_BLOB
privateClientCertificate.withUnsafeMutableBytes {
if let baseAddress = $0.baseAddress {
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLCERT_BLOB,
baseAddress, $0.count).asError()
}
}
#endif // !NS_CURL_MISSING_CURLINFO_SSLCERT_BLOB
} else if let tlsAuthUsername = clientCredential.user,
let tlsAuthPassword = clientCredential.password {
"SRP".withCString {
let mutablePointer = UnsafeMutablePointer(mutating: $0)
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_TYPE, mutablePointer).asError()
}
tlsAuthUsername.withCString {
let mutablePointer = UnsafeMutablePointer(mutating: $0)
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_USERNAME, mutablePointer).asError()
}
tlsAuthPassword.withCString {
let mutablePointer = UnsafeMutablePointer(mutating: $0)
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_PASSWORD, mutablePointer).asError()
}
} else {
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorUserAuthenticationRequired,
userInfo: [NSLocalizedDescriptionKey: "Client credentials from URLSessionConfiguration is incomplete."])
}
}
}

/// Set the CA bundle path automatically if it isn't set
Expand Down

0 comments on commit bf338c8

Please sign in to comment.