Skip to content

Commit b6d7191

Browse files
committed
Revert "Use CFURLSessionOptionCAPATH instead of CFURLSessionOptionCAINFO"
This reverts commit 52453cb.
1 parent 2179d94 commit b6d7191

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

Sources/FoundationNetworking/URLSession/libcurl/EasyHandle.swift

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,22 +221,65 @@ extension _EasyHandle {
221221
}
222222
return
223223
} else {
224-
// When no certificate file has been specified, check the default Android locations
225-
// like at https://github.com/apple/swift-nio-ssl/blob/main/Sources/NIOSSL/AndroidCABundle.swift
224+
// When no certificate file has been specified, assemble all the certificate files
225+
// from the Android certificate store and writes them to a single `cacerts.pem` file
226+
//
227+
// See https://android.googlesource.com/platform/frameworks/base/+/8b192b19f264a8829eac2cfaf0b73f6fc188d933%5E%21/#F0
228+
229+
// See https://github.com/apple/swift-nio-ssl/blob/d1088ebe0789d9eea231b40741831f37ab654b61/Sources/NIOSSL/AndroidCABundle.swift#L30
226230
let certsFolders = [
227231
"/apex/com.android.conscrypt/cacerts", // >= Android14
228232
"/system/etc/security/cacerts" // < Android14
229233
]
230234

235+
let aggregateCertPath = NSTemporaryDirectory() + "/cacerts-\(UUID().uuidString).pem"
236+
237+
if FileManager.default.createFile(atPath: aggregateCertPath, contents: nil) == false {
238+
return
239+
}
240+
241+
guard let fs = FileHandle(forWritingAtPath: aggregateCertPath) else {
242+
return
243+
}
244+
245+
// write a header
246+
fs.write("""
247+
## Bundle of CA Root Certificates
248+
## Auto-generated on \(Date())
249+
## by aggregating certificates from: \(certsFolders)
250+
251+
""".data(using: .utf8)!)
252+
253+
// Go through each folder and load each certificate file (ending with ".0"),
254+
// and append them together into a single aggreagate file tha curl can load.
255+
// The .0 files will contain some extra metadata, but libcurl only cares about the
256+
// -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- sections,
257+
// so we can naïvely concatenate them all and libcurl will understand the bundle.
231258
for certsFolder in certsFolders {
232-
var isDirectory: ObjCBool = false
233-
if FileManager.default.fileExists(atPath: certsFolder, isDirectory: &isDirectory), isDirectory == true {
234-
certsFolder.withCString { pathPtr in
235-
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAPATH, UnsafeMutablePointer(mutating: pathPtr)).asError()
259+
let certsFolderURL = URL(fileURLWithPath: certsFolder)
260+
if (try? certsFolderURL.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) != true { continue }
261+
let certURLs = try! FileManager.default.contentsOfDirectory(at: certsFolderURL, includingPropertiesForKeys: [.isRegularFileKey, .isReadableKey])
262+
for certURL in certURLs {
263+
// certificate files have names like "53a1b57a.0"
264+
if certURL.pathExtension != "0" { continue }
265+
do {
266+
if try certURL.resourceValues(forKeys: [.isRegularFileKey]).isRegularFile != true { continue }
267+
if try certURL.resourceValues(forKeys: [.isReadableKey]).isReadable != true { continue }
268+
try fs.write(contentsOf: try Data(contentsOf: certURL))
269+
} catch {
270+
// ignore individual errors and soldier on…
271+
//logger.warning("bootstrapSSLCertificates: error reading certificate file \(certURL.path): \(error)")
272+
continue
236273
}
237-
return
238274
}
239275
}
276+
277+
try! fs.close()
278+
279+
aggregateCertPath.withCString { pathPtr in
280+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, UnsafeMutablePointer(mutating: pathPtr)).asError()
281+
}
282+
return
240283
}
241284
#endif
242285

0 commit comments

Comments
 (0)