From 0abd3e538eb92259e52c3d330e46dac7aa0be332 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 22 Jan 2015 10:15:31 -0500 Subject: [PATCH] cmake: Use a default CA path when not using system curl When using system curl, we trust it to be configured with desired CA certs. When using our own build of curl, we use os-configured CA certs on Windows and OS X. On other systems, try to achieve this by searching for common CA cert locations. According to a brief investigation, the curl packages on popular Linux distros are currently configured as: * Arch: /etc/ssl/certs/ca-certificates.crt * Debian with OpenSSL: /etc/ssl/certs * Debian with GNU TLS: /etc/ssl/certs/ca-certificates.crt * Debian with NSS: /etc/ssl/certs/ca-certificates.crt * Fedora: /etc/pki/tls/certs/ca-bundle.crt * Gentoo with OpenSSL: /etc/ssl/certs * Gentoo without OpenSSL: /etc/ssl/certs/ca-certificates.crt Teach CMake and CTest to look for these paths and use them as a CA path or bundle when no other os-configured or user-specified CAs are available. --- Help/release/dev/curl-default-cainfo.rst | 8 +++ Source/CMakeLists.txt | 8 +++ Source/CTest/cmCTestSubmitHandler.cxx | 3 +- Source/cmCTest.cxx | 3 +- Source/cmCurl.cxx | 64 ++++++++++++++++++++++++ Source/cmCurl.h | 21 ++++++++ Source/cmFileCommand.cxx | 9 ++-- 7 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/curl-default-cainfo.rst create mode 100644 Source/cmCurl.cxx create mode 100644 Source/cmCurl.h diff --git a/Help/release/dev/curl-default-cainfo.rst b/Help/release/dev/curl-default-cainfo.rst new file mode 100644 index 000000000..ed45d36e3 --- /dev/null +++ b/Help/release/dev/curl-default-cainfo.rst @@ -0,0 +1,8 @@ +curl-default-cainfo +------------------- + +* When CMake is built with OpenSSL on systems other than Windows + and OS X, commands supporting network communication via ``https``, + such as :command:`file(DOWNLOAD)`, :command:`file(UPLOAD)`, and + :command:`ctest_submit`, now search for OS-configured certificate + authorities in a few ``/etc`` paths to be trusted automatically. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c04cf9abc..07839f342 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -175,6 +175,8 @@ set(SRCS cmCPackPropertiesGenerator.cxx cmCryptoHash.cxx cmCryptoHash.h + cmCurl.cxx + cmCurl.h cmCustomCommand.cxx cmCustomCommand.h cmCustomCommandGenerator.cxx @@ -497,6 +499,12 @@ if(WIN32 AND NOT CYGWIN) install(TARGETS cmcldeps DESTINATION bin) endif() +foreach(v CURL_CA_BUNDLE CURL_CA_PATH) + if(${v}) + set_property(SOURCE cmCurl.cxx APPEND PROPERTY COMPILE_DEFINITIONS ${v}="${${v}}") + endif() +endforeach() + # create a library used by the command line and the GUI add_library(CMakeLib ${SRCS}) target_link_libraries(CMakeLib cmsys diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 11e334385..3d9545f55 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -26,7 +26,7 @@ #include // For curl submission -#include "cm_curl.h" +#include "cmCurl.h" #include "cmCTestCurl.h" #include @@ -366,6 +366,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, curl = curl_easy_init(); if(curl) { + cmCurlSetCAInfo(curl); if(verifyPeerOff) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 1ef4c9240..f08b87c9c 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -9,7 +9,7 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ -#include "cm_curl.h" +#include "cmCurl.h" // include before anything that includes windows.h #include "cmCTest.h" #include "cmake.h" @@ -192,6 +192,7 @@ int cmCTest::HTTPRequest(std::string url, HTTPMethod method, FILE* file; ::curl_global_init(CURL_GLOBAL_ALL); curl = ::curl_easy_init(); + cmCurlSetCAInfo(curl); //set request options based on method switch(method) diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx new file mode 100644 index 000000000..96d3547e3 --- /dev/null +++ b/Source/cmCurl.cxx @@ -0,0 +1,64 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmCurl.h" +#include "cmSystemTools.h" + +#define check_curl_result(result, errstr) \ + if (result != CURLE_OK) \ + { \ + e += e.empty()? "" : "\n"; \ + e += errstr; \ + e += ::curl_easy_strerror(result); \ + } + +//---------------------------------------------------------------------------- +std::string cmCurlSetCAInfo(::CURL *curl, const char* cafile) +{ + std::string e; + if(cafile && *cafile) + { + ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } +#if !defined(CMAKE_USE_SYSTEM_CURL) && \ + !defined(_WIN32) && !defined(__APPLE__) && \ + !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH) +# define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt" + else if(cmSystemTools::FileExists(CMAKE_CAFILE_FEDORA, true)) + { + ::CURLcode res = + ::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_FEDORA); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } +# undef CMAKE_CAFILE_FEDORA + else + { +# define CMAKE_CAFILE_COMMON "/etc/ssl/certs/ca-certificates.crt" + if(cmSystemTools::FileExists(CMAKE_CAFILE_COMMON, true)) + { + ::CURLcode res = + ::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_COMMON); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } +# undef CMAKE_CAFILE_COMMON +# define CMAKE_CAPATH_COMMON "/etc/ssl/certs" + if(cmSystemTools::FileIsDirectory(CMAKE_CAPATH_COMMON)) + { + ::CURLcode res = + ::curl_easy_setopt(curl, CURLOPT_CAPATH, CMAKE_CAPATH_COMMON); + check_curl_result(res, "Unable to set TLS/SSL Verify CAPATH: "); + } +# undef CMAKE_CAPATH_COMMON + } +#endif + return e; +} diff --git a/Source/cmCurl.h b/Source/cmCurl.h new file mode 100644 index 000000000..0c5609ca7 --- /dev/null +++ b/Source/cmCurl.h @@ -0,0 +1,21 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCurl_h +#define cmCurl_h + +#include +#include "cm_curl.h" +#include "cmStandardIncludes.h" + +std::string cmCurlSetCAInfo(::CURL *curl, const char* cafile = 0); + +#endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 2c92db247..f12529215 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -20,7 +20,7 @@ #include "cmTimestamp.h" #if defined(CMAKE_BUILD_WITH_CMAKE) -#include "cm_curl.h" +#include "cmCurl.h" #include "cmFileLockResult.h" #endif @@ -3068,10 +3068,11 @@ cmFileCommand::HandleDownloadCommand(std::vector const& args) } // check to see if a CAINFO file has been specified // command arg comes first - if(cainfo && *cainfo) + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); + if (!cainfo_err.empty()) { - res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo); - check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + this->SetError(cainfo_err); + return false; } cmFileCommandVectorOfChar chunkDebug;