@@ -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,56 @@ extension _EasyHandle {
205205 else {
206206 try ! CFURLSession_easy_setopt_ptr ( rawHandle, CFURLSessionOptionCAINFO, caInfo) . asError ( )
207207 }
208+ return
209+ }
210+ #endif
211+
212+ #if !os(Windows) && !os(macOS) && !os(iOS) && !os(watchOS) && !os(tvOS)
213+ // Check if there is a default path; if there is, it will already
214+ // be set, so leave things alone
215+ var p : UnsafeMutablePointer < Int8 > ? = nil
216+
217+ try ! CFURLSession_easy_getinfo_charp ( rawHandle, CFURLSessionInfoCAINFO, & p) . asError ( )
218+
219+ if p != nil {
220+ return
221+ }
222+
223+ // Otherwise, search a list of known paths
224+ let paths = [
225+ " /etc/ssl/certs/ca-certificates.crt " ,
226+ " /etc/pki/tls/certs/ca-bundle.crt " ,
227+ " /usr/share/ssl/certs/ca-bundle.crt " ,
228+ " /usr/local/share/certs/ca-root-nss.crt " ,
229+ " /etc/ssl/cert.pem "
230+ ]
231+
232+ for path in paths {
233+ var isDirectory : ObjCBool = false
234+ if FileManager . default. fileExists ( atPath: path,
235+ isDirectory: & isDirectory)
236+ && !isDirectory. boolValue {
237+ path. withCString { pathPtr in
238+ try ! CFURLSession_easy_setopt_ptr ( rawHandle, CFURLSessionOptionCAINFO, UnsafeMutablePointer ( mutating: pathPtr) ) . asError ( )
239+ }
240+ return
241+ }
208242 }
209243#endif
244+ }
245+
246+ /// Set allowed protocols
247+ ///
248+ /// - Note: This has security implications. Not limiting this, someone could
249+ /// redirect a HTTP request into one of the many other protocols that libcurl
250+ /// supports.
251+ /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
252+ /// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_REDIR_PROTOCOLS.html
253+ func setAllowedProtocolsToHTTPAndHTTPS( ) {
254+ let protocols = ( CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
255+ try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionPROTOCOLS, protocols) . asError ( )
256+ try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols) . asError ( )
257+ setCARootBundlePath ( )
210258 //TODO: Added in libcurl 7.45.0
211259 //TODO: Set default protocol for schemeless URLs
212260 //CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
@@ -217,6 +265,7 @@ extension _EasyHandle {
217265 let redirectProtocols = ( CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
218266 try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionPROTOCOLS, protocols) . asError ( )
219267 try ! CFURLSession_easy_setopt_long ( rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, redirectProtocols) . asError ( )
268+ setCARootBundlePath ( )
220269 }
221270
222271 //TODO: Proxy setting, namely CFURLSessionOptionPROXY, CFURLSessionOptionPROXYPORT,
0 commit comments