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.
This commit is contained in:
Brad King 2015-01-22 10:15:31 -05:00
parent 6ce346c53c
commit 0abd3e538e
7 changed files with 110 additions and 6 deletions

View File

@ -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.

View File

@ -175,6 +175,8 @@ set(SRCS
cmCPackPropertiesGenerator.cxx cmCPackPropertiesGenerator.cxx
cmCryptoHash.cxx cmCryptoHash.cxx
cmCryptoHash.h cmCryptoHash.h
cmCurl.cxx
cmCurl.h
cmCustomCommand.cxx cmCustomCommand.cxx
cmCustomCommand.h cmCustomCommand.h
cmCustomCommandGenerator.cxx cmCustomCommandGenerator.cxx
@ -497,6 +499,12 @@ if(WIN32 AND NOT CYGWIN)
install(TARGETS cmcldeps DESTINATION bin) install(TARGETS cmcldeps DESTINATION bin)
endif() 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 # create a library used by the command line and the GUI
add_library(CMakeLib ${SRCS}) add_library(CMakeLib ${SRCS})
target_link_libraries(CMakeLib cmsys target_link_libraries(CMakeLib cmsys

View File

@ -26,7 +26,7 @@
#include <cm_jsoncpp_reader.h> #include <cm_jsoncpp_reader.h>
// For curl submission // For curl submission
#include "cm_curl.h" #include "cmCurl.h"
#include "cmCTestCurl.h" #include "cmCTestCurl.h"
#include <sys/stat.h> #include <sys/stat.h>
@ -366,6 +366,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
curl = curl_easy_init(); curl = curl_easy_init();
if(curl) if(curl)
{ {
cmCurlSetCAInfo(curl);
if(verifyPeerOff) if(verifyPeerOff)
{ {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,

View File

@ -9,7 +9,7 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information. See the License for more information.
============================================================================*/ ============================================================================*/
#include "cm_curl.h" #include "cmCurl.h" // include before anything that includes windows.h
#include "cmCTest.h" #include "cmCTest.h"
#include "cmake.h" #include "cmake.h"
@ -192,6 +192,7 @@ int cmCTest::HTTPRequest(std::string url, HTTPMethod method,
FILE* file; FILE* file;
::curl_global_init(CURL_GLOBAL_ALL); ::curl_global_init(CURL_GLOBAL_ALL);
curl = ::curl_easy_init(); curl = ::curl_easy_init();
cmCurlSetCAInfo(curl);
//set request options based on method //set request options based on method
switch(method) switch(method)

64
Source/cmCurl.cxx Normal file
View File

@ -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;
}

21
Source/cmCurl.h Normal file
View File

@ -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 <cmsys/Configure.h>
#include "cm_curl.h"
#include "cmStandardIncludes.h"
std::string cmCurlSetCAInfo(::CURL *curl, const char* cafile = 0);
#endif

View File

@ -20,7 +20,7 @@
#include "cmTimestamp.h" #include "cmTimestamp.h"
#if defined(CMAKE_BUILD_WITH_CMAKE) #if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cm_curl.h" #include "cmCurl.h"
#include "cmFileLockResult.h" #include "cmFileLockResult.h"
#endif #endif
@ -3068,10 +3068,11 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
} }
// check to see if a CAINFO file has been specified // check to see if a CAINFO file has been specified
// command arg comes first // 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); this->SetError(cainfo_err);
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); return false;
} }
cmFileCommandVectorOfChar chunkDebug; cmFileCommandVectorOfChar chunkDebug;