@@ -182,17 +182,17 @@ extension _EasyHandle {
182182 _config = config
183183 }
184184
185- /// Set allowed protocols
185+ /// Set the CA bundle path automatically if it isn't set
186186 ///
187- /// - Note: This has security implications. Not limiting this, someone could
188- /// redirect a HTTP request into one of the many other protocols that libcurl
189- /// supports.
190- /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
191- /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_REDIR_PROTOCOLS.html
192- func setAllowedProtocolsToHTTPAndHTTPS ( ) {
193- let protocols = ( CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS )
194- try ! CFURLSession_easy_setopt_long ( rawHandle , CFURLSessionOptionPROTOCOLS , protocols ) . asError ( )
195- try ! CFURLSession_easy_setopt_long ( rawHandle , CFURLSessionOptionREDIR_PROTOCOLS , protocols ) . asError ( )
187+ /// Curl does not necessarily know where to find the CA root bundle,
188+ /// and in that case we need to specify where it is. There was a hack
189+ /// to do this automatically for Android but allowing an environment
190+ /// variable to control the location of the CA root bundle seems like
191+ /// a security issue in general.
192+ ///
193+ /// Rather than doing that, we have a list of places we might expect
194+ /// to find it, and search those until we locate a suitable file.
195+ func setCARootBundlePath ( ) {
196196#if os(Android)
197197 // See https://curl.haxx.se/docs/sslcerts.html
198198 // For SSL on Android you need a "cacert.pem" to be
@@ -205,8 +205,58 @@ extension _EasyHandle {
205205 else {
206206 try ! CFURLSession_easy_setopt_ptr ( rawHandle, CFURLSessionOptionCAINFO, caInfo) . asError ( )
207207 }
208+ return
208209 }
209210#endif
211+
212+ #if !NS_CURL_MISSING_CURLINFO_CAINFO
213+ #if !os(Windows) && !os(macOS) && !os(iOS) && !os(watchOS) && !os(tvOS)
214+ // Check if there is a default path; if there is, it will already
215+ // be set, so leave things alone
216+ var p : UnsafeMutablePointer < Int8 > ? = nil
217+
218+ try ! CFURLSession_easy_getinfo_charp ( rawHandle, CFURLSessionInfoCAINFO, & p) . asError ( )
219+
220+ if p != nil {
221+ return
222+ }
223+
224+ // Otherwise, search a list of known paths
225+ let paths = [
226+ " /etc/ssl/certs/ca-certificates.crt " ,
227+ " /etc/pki/tls/certs/ca-bundle.crt " ,
228+ " /usr/share/ssl/certs/ca-bundle.crt " ,
229+ " /usr/local/share/certs/ca-root-nss.crt " ,
230+ " /etc/ssl/cert.pem "
231+ ]
232+
233+ for path in paths {
234+ var isDirectory : ObjCBool = false
235+ if FileManager . default. fileExists ( atPath: path,
236+ isDirectory: & isDirectory)
237+ && !isDirectory. boolValue {
238+ path. withCString { pathPtr in
239+ try ! CFURLSession_easy_setopt_ptr ( rawHandle, CFURLSessionOptionCAINFO, UnsafeMutablePointer ( mutating: pathPtr) ) . asError ( )
240+ }
241+ return
242+ }
243+ }
244+ #endif // !os(Windows) && !os(macOS) && !os(iOS) && !os(watchOS) && !os(tvOS)
245+ #endif // !NS_CURL_MISSING_CURLINFO_CAINFO
246+ }
247+
248+ /// Set allowed protocols
249+ ///
250+ /// - Note: This has security implications. Not limiting this, someone could
251+ /// redirect a HTTP request into one of the many other protocols that libcurl
252+ /// supports.
253+ /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
254+ /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_REDIR_PROTOCOLS.html
255+ func setAllowedProtocolsToHTTPAndHTTPS( ) {
256+ let protocols = ( CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
257+ try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionPROTOCOLS, protocols) . asError ( )
258+ try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols) . asError ( )
259+ setCARootBundlePath ( )
210260 //TODO: Added in libcurl 7.45.0
211261 //TODO: Set default protocol for schemeless URLs
212262 //CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
@@ -217,6 +267,7 @@ extension _EasyHandle {
217267 let redirectProtocols = ( CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
218268 try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionPROTOCOLS, protocols) . asError ( )
219269 try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, redirectProtocols) . asError ( )
270+ setCARootBundlePath ( )
220271 }
221272
222273 //TODO: Proxy setting, namely CFURLSessionOptionPROXY, CFURLSessionOptionPROXYPORT,
0 commit comments