10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
- import _Concurrency
14
13
import Dispatch
15
14
import Foundation
16
15
@@ -53,66 +52,58 @@ protocol CertificatePolicy {
53
52
/// Validates the given certificate chain.
54
53
///
55
54
/// - Parameters:
56
- /// - certChainPaths: Paths to each certificate in the chain. The certificate being verified must be the first
57
- /// element of the array, with its issuer the next element and so on, and the root CA
58
- /// certificate is last.
55
+ /// - certChain: The certificate being verified must be the first element of the array, with its issuer the next
56
+ /// element and so on, and the root CA certificate is last.
59
57
/// - validationTime: Overrides the timestamp used for checking certificate expiry (e.g., for testing).
60
58
/// By default the current time is used.
61
- /// - callback: The callback to invoke when the result is available.
62
- func validate( certChain: [ Certificate ] , validationTime: Date , callback: @escaping ( Result < Void , Error > ) -> Void )
59
+ func validate( certChain: [ Certificate ] , validationTime: Date ) async throws
63
60
}
64
61
65
62
extension CertificatePolicy {
66
63
/// Validates the given certificate chain.
67
64
///
68
65
/// - Parameters:
69
- /// - certChainPaths: Paths to each certificate in the chain. The certificate being verified must be the first
70
- /// element of the array, with its issuer the next element and so on, and the root CA
71
- /// certificate is last.
72
- /// - callback: The callback to invoke when the result is available.
73
- func validate( certChain: [ Certificate ] , callback: @escaping ( Result < Void , Error > ) -> Void ) {
74
- self . validate ( certChain: certChain, validationTime: Date ( ) , callback: callback)
66
+ /// - certChain: The certificate being verified must be the first element of the array, with its issuer the next
67
+ /// element and so on, and the root CA certificate is last.
68
+ func validate( certChain: [ Certificate ] ) async throws {
69
+ try await self . validate ( certChain: certChain, validationTime: Date ( ) )
75
70
}
76
71
77
72
func verify(
78
73
certChain: [ Certificate ] ,
79
74
trustedRoots: [ Certificate ] ? ,
80
75
@PolicyBuilder policies: ( ) -> some VerifierPolicy ,
81
- observabilityScope: ObservabilityScope ,
82
- callbackQueue: DispatchQueue ,
83
- callback: @escaping ( Result < Void , Error > ) -> Void
84
- ) {
85
- let wrappedCallback : ( Result < Void , Error > ) -> Void = { result in callbackQueue. async { callback ( result) } }
86
-
76
+ observabilityScope: ObservabilityScope
77
+ ) async throws {
87
78
guard !certChain. isEmpty else {
88
- return wrappedCallback ( . failure ( CertificatePolicyError . emptyCertChain) )
79
+ throw CertificatePolicyError . emptyCertChain
89
80
}
81
+
90
82
let policies = policies ( )
91
- Task {
92
- var trustStore = CertificateStores . defaultTrustRoots
93
- if let trustedRoots {
94
- trustStore. append ( contentsOf: trustedRoots)
95
- }
96
83
97
- guard !trustStore. isEmpty else {
98
- return wrappedCallback ( . failure( CertificatePolicyError . noTrustedRootCertsConfigured) )
99
- }
84
+ var trustStore = CertificateStores . defaultTrustRoots
85
+ if let trustedRoots {
86
+ trustStore. append ( contentsOf: trustedRoots)
87
+ }
100
88
101
- var verifier = Verifier ( rootCertificates: CertificateStore ( trustStore) ) {
102
- policies
103
- }
104
- let result = await verifier. validate (
105
- leafCertificate: certChain [ 0 ] ,
106
- intermediates: CertificateStore ( certChain)
107
- )
89
+ guard !trustStore. isEmpty else {
90
+ throw CertificatePolicyError . noTrustedRootCertsConfigured
91
+ }
108
92
109
- switch result {
110
- case . validCertificate:
111
- wrappedCallback ( . success( ( ) ) )
112
- case . couldNotValidate( let failures) :
113
- observabilityScope. emit ( error: " Failed to validate certificate chain \( certChain) : \( failures) " )
114
- wrappedCallback ( . failure( CertificatePolicyError . invalidCertChain) )
115
- }
93
+ var verifier = Verifier ( rootCertificates: CertificateStore ( trustStore) ) {
94
+ policies
95
+ }
96
+ let result = await verifier. validate (
97
+ leafCertificate: certChain [ 0 ] ,
98
+ intermediates: CertificateStore ( certChain)
99
+ )
100
+
101
+ switch result {
102
+ case . validCertificate:
103
+ return
104
+ case . couldNotValidate( let failures) :
105
+ observabilityScope. emit ( error: " Failed to validate certificate chain \( certChain) : \( failures) " )
106
+ throw CertificatePolicyError . invalidCertChain
116
107
}
117
108
}
118
109
}
@@ -136,7 +127,6 @@ struct DefaultCertificatePolicy: CertificatePolicy {
136
127
let expectedSubjectUserID : String ?
137
128
let expectedSubjectOrganizationalUnit : String ?
138
129
139
- private let callbackQueue : DispatchQueue
140
130
private let httpClient : HTTPClient
141
131
private let observabilityScope : ObservabilityScope
142
132
@@ -150,14 +140,12 @@ struct DefaultCertificatePolicy: CertificatePolicy {
150
140
/// user configured and dynamic, while this is configured by SwiftPM and static.
151
141
/// - expectedSubjectUserID: The subject user ID that must match if specified.
152
142
/// - expectedSubjectOrganizationalUnit: The subject organizational unit name that must match if specified.
153
- /// - callbackQueue: The `DispatchQueue` to use for callbacks.
154
143
init (
155
144
trustedRootCertsDir: URL ? ,
156
145
additionalTrustedRootCerts: [ Certificate ] ? ,
157
146
expectedSubjectUserID: String ? = nil ,
158
147
expectedSubjectOrganizationalUnit: String ? = nil ,
159
- observabilityScope: ObservabilityScope ,
160
- callbackQueue: DispatchQueue
148
+ observabilityScope: ObservabilityScope
161
149
) {
162
150
var trustedRoots = [ Certificate] ( )
163
151
if let trustedRootCertsDir {
@@ -170,19 +158,16 @@ struct DefaultCertificatePolicy: CertificatePolicy {
170
158
self . trustedRoots = trustedRoots
171
159
self . expectedSubjectUserID = expectedSubjectUserID
172
160
self . expectedSubjectOrganizationalUnit = expectedSubjectOrganizationalUnit
173
- self . callbackQueue = callbackQueue
174
161
self . httpClient = HTTPClient . makeDefault ( )
175
162
self . observabilityScope = observabilityScope
176
163
}
177
164
178
- func validate( certChain: [ Certificate ] , validationTime: Date , callback: @escaping ( Result < Void , Error > ) -> Void ) {
179
- let wrappedCallback : ( Result < Void , Error > ) -> Void = { result in self . callbackQueue. async { callback ( result) } }
180
-
165
+ func validate( certChain: [ Certificate ] , validationTime: Date ) async throws {
181
166
guard !certChain. isEmpty else {
182
- return wrappedCallback ( . failure ( CertificatePolicyError . emptyCertChain) )
167
+ throw CertificatePolicyError . emptyCertChain
183
168
}
184
169
185
- self . verify (
170
+ try await self . verify (
186
171
certChain: certChain,
187
172
trustedRoots: self . trustedRoots,
188
173
policies: {
@@ -202,9 +187,7 @@ struct DefaultCertificatePolicy: CertificatePolicy {
202
187
validationTime: validationTime
203
188
)
204
189
} ,
205
- observabilityScope: self . observabilityScope,
206
- callbackQueue: self . callbackQueue,
207
- callback: callback
190
+ observabilityScope: self . observabilityScope
208
191
)
209
192
}
210
193
}
@@ -218,7 +201,6 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy {
218
201
let expectedSubjectUserID : String ?
219
202
let expectedSubjectOrganizationalUnit : String ?
220
203
221
- private let callbackQueue : DispatchQueue
222
204
private let httpClient : HTTPClient
223
205
private let observabilityScope : ObservabilityScope
224
206
@@ -232,14 +214,12 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy {
232
214
/// user configured and dynamic, while this is configured by SwiftPM and static.
233
215
/// - expectedSubjectUserID: The subject user ID that must match if specified.
234
216
/// - expectedSubjectOrganizationalUnit: The subject organizational unit name that must match if specified.
235
- /// - callbackQueue: The `DispatchQueue` to use for callbacks.
236
217
init (
237
218
trustedRootCertsDir: URL ? ,
238
219
additionalTrustedRootCerts: [ Certificate ] ? ,
239
220
expectedSubjectUserID: String ? = nil ,
240
221
expectedSubjectOrganizationalUnit: String ? = nil ,
241
- observabilityScope: ObservabilityScope ,
242
- callbackQueue: DispatchQueue
222
+ observabilityScope: ObservabilityScope
243
223
) {
244
224
var trustedRoots = [ Certificate] ( )
245
225
if let trustedRootCertsDir {
@@ -252,19 +232,16 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy {
252
232
self . trustedRoots = trustedRoots
253
233
self . expectedSubjectUserID = expectedSubjectUserID
254
234
self . expectedSubjectOrganizationalUnit = expectedSubjectOrganizationalUnit
255
- self . callbackQueue = callbackQueue
256
235
self . httpClient = HTTPClient . makeDefault ( )
257
236
self . observabilityScope = observabilityScope
258
237
}
259
238
260
- func validate( certChain: [ Certificate ] , validationTime: Date , callback: @escaping ( Result < Void , Error > ) -> Void ) {
261
- let wrappedCallback : ( Result < Void , Error > ) -> Void = { result in self . callbackQueue. async { callback ( result) } }
262
-
239
+ func validate( certChain: [ Certificate ] , validationTime: Date ) async throws {
263
240
guard !certChain. isEmpty else {
264
- return wrappedCallback ( . failure ( CertificatePolicyError . emptyCertChain) )
241
+ throw CertificatePolicyError . emptyCertChain
265
242
}
266
243
267
- self . verify (
244
+ try await self . verify (
268
245
certChain: certChain,
269
246
trustedRoots: self . trustedRoots,
270
247
policies: {
@@ -286,9 +263,7 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy {
286
263
validationTime: validationTime
287
264
)
288
265
} ,
289
- observabilityScope: self . observabilityScope,
290
- callbackQueue: self . callbackQueue,
291
- callback: callback
266
+ observabilityScope: self . observabilityScope
292
267
)
293
268
}
294
269
}
@@ -302,7 +277,6 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy {
302
277
let expectedSubjectUserID : String ?
303
278
let expectedSubjectOrganizationalUnit : String ?
304
279
305
- private let callbackQueue : DispatchQueue
306
280
private let httpClient : HTTPClient
307
281
private let observabilityScope : ObservabilityScope
308
282
@@ -316,14 +290,12 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy {
316
290
/// user configured and dynamic, while this is configured by SwiftPM and static.
317
291
/// - expectedSubjectUserID: The subject user ID that must match if specified.
318
292
/// - expectedSubjectOrganizationalUnit: The subject organizational unit name that must match if specified.
319
- /// - callbackQueue: The `DispatchQueue` to use for callbacks.
320
293
init (
321
294
trustedRootCertsDir: URL ? ,
322
295
additionalTrustedRootCerts: [ Certificate ] ? ,
323
296
expectedSubjectUserID: String ? = nil ,
324
297
expectedSubjectOrganizationalUnit: String ? = nil ,
325
- observabilityScope: ObservabilityScope ,
326
- callbackQueue: DispatchQueue
298
+ observabilityScope: ObservabilityScope
327
299
) {
328
300
var trustedRoots = [ Certificate] ( )
329
301
if let trustedRootCertsDir {
@@ -336,19 +308,16 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy {
336
308
self . trustedRoots = trustedRoots
337
309
self . expectedSubjectUserID = expectedSubjectUserID
338
310
self . expectedSubjectOrganizationalUnit = expectedSubjectOrganizationalUnit
339
- self . callbackQueue = callbackQueue
340
311
self . httpClient = HTTPClient . makeDefault ( )
341
312
self . observabilityScope = observabilityScope
342
313
}
343
314
344
- func validate( certChain: [ Certificate ] , validationTime: Date , callback: @escaping ( Result < Void , Error > ) -> Void ) {
345
- let wrappedCallback : ( Result < Void , Error > ) -> Void = { result in self . callbackQueue. async { callback ( result) } }
346
-
315
+ func validate( certChain: [ Certificate ] , validationTime: Date ) async throws {
347
316
guard !certChain. isEmpty else {
348
- return wrappedCallback ( . failure ( CertificatePolicyError . emptyCertChain) )
317
+ throw CertificatePolicyError . emptyCertChain
349
318
}
350
319
351
- self . verify (
320
+ try await self . verify (
352
321
certChain: certChain,
353
322
trustedRoots: self . trustedRoots,
354
323
policies: {
@@ -370,9 +339,7 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy {
370
339
validationTime: validationTime
371
340
)
372
341
} ,
373
- observabilityScope: self . observabilityScope,
374
- callbackQueue: self . callbackQueue,
375
- callback: callback
342
+ observabilityScope: self . observabilityScope
376
343
)
377
344
}
378
345
}
0 commit comments