Skip to content

Commit e4ff2fa

Browse files
committed
FoundationNetworking/URLSessionConfiguration: Add URLCredential
1 parent 14d743d commit e4ff2fa

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-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

+40-1
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,47 @@ 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+
privateClientKey.withUnsafeMutableBytes {
195+
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLKEY_BLOB,
196+
$0.baseAddress, $0.count).asError()
197+
}
198+
199+
privateClientCertificate.withUnsafeMutableBytes {
200+
try! CFURLSession_easy_setopt_blob(rawHandle, CFURLSessionOptionSSLCERT_BLOB,
201+
$0.baseAddress, $0.count).asError()
202+
}
203+
} else if let tlsAuthUsername = clientCredential.user,
204+
let tlsAuthPassword = clientCredential.password {
205+
"SRP".withCString {
206+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
207+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_TYPE, mutablePointer).asError()
208+
}
209+
tlsAuthUsername.withCString {
210+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
211+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_USERNAME, mutablePointer).asError()
212+
}
213+
tlsAuthPassword.withCString {
214+
let mutablePointer = UnsafeMutablePointer(mutating: $0)
215+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionTLSAUTH_PASSWORD, mutablePointer).asError()
216+
}
217+
} else {
218+
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorUserAuthenticationRequired,
219+
userInfo: [NSLocalizedDescriptionKey: "Client credentials from URLSessionConfiguration is incomplete."])
220+
}
221+
}
183222
}
184223

185224
/// Set allowed protocols

0 commit comments

Comments
 (0)