Skip to content

Commit bf338c8

Browse files
committed
FoundationNetworking/URLSessionConfiguration: Add URLCredential
1 parent a61d54a commit bf338c8

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

Sources/FoundationNetworking/URLSession/Configuration.swift

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ internal extension URLSession {
7878
let shouldUseExtendedBackgroundIdleMode: Bool
7979

8080
let protocolClasses: [AnyClass]?
81+
82+
/// The credentials to use for connecting to servers
83+
let clientCredential: URLCredential?
8184
}
8285
}
8386
internal extension URLSession._Configuration {
@@ -100,6 +103,7 @@ internal extension URLSession._Configuration {
100103
urlCache = config.urlCache
101104
shouldUseExtendedBackgroundIdleMode = config.shouldUseExtendedBackgroundIdleMode
102105
protocolClasses = config.protocolClasses
106+
clientCredential = config.clientCredential
103107
}
104108
}
105109

Sources/FoundationNetworking/URLSession/HTTP/HTTPURLProtocol.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,14 @@ internal class _HTTPURLProtocol: _NativeProtocol {
328328
}
329329
let session = task?.session as! URLSession
330330
let _config = session._configuration
331-
easyHandle.set(sessionConfig: _config)
331+
do {
332+
try easyHandle.set(sessionConfig: _config)
333+
} catch {
334+
self.internalState = .transferFailed
335+
let nsError = error as? NSError ?? NSError(domain: NSURLErrorDomain, code: NSURLErrorUserAuthenticationRequired)
336+
failWith(error: nsError, request: request)
337+
return
338+
}
332339
easyHandle.setAllowedProtocolsToHTTPAndHTTPS()
333340
easyHandle.set(preferredReceiveBufferSize: Int.max)
334341
do {

Sources/FoundationNetworking/URLSession/URLSessionConfiguration.swift

+10-4
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ open class URLSessionConfiguration : NSObject, NSCopying {
7575
urlCredentialStorage: .shared,
7676
urlCache: .shared,
7777
shouldUseExtendedBackgroundIdleMode: false,
78-
protocolClasses: [_HTTPURLProtocol.self, _FTPURLProtocol.self, _WebSocketURLProtocol.self])
78+
protocolClasses: [_HTTPURLProtocol.self, _FTPURLProtocol.self, _WebSocketURLProtocol.self],
79+
clientCredential: nil)
7980
}
80-
81+
8182
private init(identifier: String?,
8283
requestCachePolicy: URLRequest.CachePolicy,
8384
timeoutIntervalForRequest: TimeInterval,
@@ -95,7 +96,8 @@ open class URLSessionConfiguration : NSObject, NSCopying {
9596
urlCredentialStorage: URLCredentialStorage?,
9697
urlCache: URLCache?,
9798
shouldUseExtendedBackgroundIdleMode: Bool,
98-
protocolClasses: [AnyClass]?)
99+
protocolClasses: [AnyClass]?,
100+
clientCredential: URLCredential?)
99101
{
100102
self.identifier = identifier
101103
self.requestCachePolicy = requestCachePolicy
@@ -115,6 +117,7 @@ open class URLSessionConfiguration : NSObject, NSCopying {
115117
self.urlCache = urlCache
116118
self.shouldUseExtendedBackgroundIdleMode = shouldUseExtendedBackgroundIdleMode
117119
self.protocolClasses = protocolClasses
120+
self.clientCredential = clientCredential
118121
}
119122

120123
open override func copy() -> Any {
@@ -140,7 +143,8 @@ open class URLSessionConfiguration : NSObject, NSCopying {
140143
urlCredentialStorage: urlCredentialStorage,
141144
urlCache: urlCache,
142145
shouldUseExtendedBackgroundIdleMode: shouldUseExtendedBackgroundIdleMode,
143-
protocolClasses: protocolClasses)
146+
protocolClasses: protocolClasses,
147+
clientCredential: clientCredential)
144148
}
145149

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

265+
/* Optional client credential to be used when connecting to servers */
266+
open var clientCredential: URLCredential?
261267
}
262268

263269
@available(*, unavailable, message: "Not available on non-Darwin platforms")

Sources/FoundationNetworking/URLSession/libcurl/EasyHandle.swift

+48-1
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,55 @@ extension _EasyHandle {
178178
}
179179
}
180180

181-
func set(sessionConfig config: URLSession._Configuration) {
181+
func set(sessionConfig config: URLSession._Configuration) throws {
182182
_config = config
183+
if let c = _config, let clientCredential = c.clientCredential {
184+
// For TLS client certificate authentication
185+
if var privateClientKey = clientCredential.privateClientKey,
186+
var privateClientCertificate = clientCredential.privateClientCertificate {
187+
// Key and certificate are expected to be in DER format
188+
"DER".withCString {
189+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
190+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSSLKEYTYPE, mutablePointer).asError()
191+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSSLCERTTYPE, mutablePointer).asError()
192+
}
193+
194+
#if !NS_CURL_MISSING_CURLINFO_SSLKEY_BLOB
195+
privateClientKey.withUnsafeMutableBytes {
196+
if let baseAddress = $0.baseAddress {
197+
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLKEY_BLOB,
198+
baseAddress, $0.count).asError()
199+
}
200+
}
201+
#endif // !NS_CURL_MISSING_CURLINFO_SSLKEY_BLOB
202+
203+
#if !NS_CURL_MISSING_CURLINFO_SSLCERT_BLOB
204+
privateClientCertificate.withUnsafeMutableBytes {
205+
if let baseAddress = $0.baseAddress {
206+
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLCERT_BLOB,
207+
baseAddress, $0.count).asError()
208+
}
209+
}
210+
#endif // !NS_CURL_MISSING_CURLINFO_SSLCERT_BLOB
211+
} else if let tlsAuthUsername = clientCredential.user,
212+
let tlsAuthPassword = clientCredential.password {
213+
"SRP".withCString {
214+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
215+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_TYPE, mutablePointer).asError()
216+
}
217+
tlsAuthUsername.withCString {
218+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
219+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_USERNAME, mutablePointer).asError()
220+
}
221+
tlsAuthPassword.withCString {
222+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
223+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_PASSWORD, mutablePointer).asError()
224+
}
225+
} else {
226+
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorUserAuthenticationRequired,
227+
userInfo: [NSLocalizedDescriptionKey: "Client credentials from URLSessionConfiguration is incomplete."])
228+
}
229+
}
183230
}
184231

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

0 commit comments

Comments
 (0)