diff options
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r-- | Source/cmFileCommand.cxx | 150 |
1 files changed, 109 insertions, 41 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 5da5a0181..8de24b358 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -10,6 +10,7 @@ See the License for more information. ============================================================================*/ #include "cmFileCommand.h" +#include "cmCryptoHash.h" #include "cmake.h" #include "cmHexFileConverter.h" #include "cmInstallType.h" @@ -271,7 +272,7 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) // Open the specified file. #if defined(_WIN32) || defined(__CYGWIN__) - std::ifstream file(fileName.c_str(), std::ios::in | + std::ifstream file(fileName.c_str(), std::ios::in | (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in)); #else std::ifstream file(fileName.c_str(), std::ios::in); @@ -2621,17 +2622,17 @@ namespace { ::curl_easy_cleanup(this->Easy); } } - - inline void release(void) + + inline void release(void) { this->Easy = 0; return; } - + private: ::CURL * Easy; }; - + } #endif @@ -2666,7 +2667,11 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) long inactivity_timeout = 0; std::string verboseLog; std::string statusVar; - std::string expectedMD5sum; + bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY"); + const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO"); + std::string expectedHash; + std::string hashMatchMSG; + cmsys::auto_ptr<cmCryptoHash> hash; bool showProgress = false; while(i != args.end()) @@ -2717,6 +2722,32 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } statusVar = *i; } + else if(*i == "TLS_VERIFY") + { + ++i; + if(i != args.end()) + { + tls_verify = cmSystemTools::IsOn(i->c_str()); + } + else + { + this->SetError("TLS_VERIFY missing bool value."); + return false; + } + } + else if(*i == "TLS_CAINFO") + { + ++i; + if(i != args.end()) + { + cainfo = i->c_str(); + } + else + { + this->SetError("TLS_CAFILE missing file value."); + return false; + } + } else if(*i == "EXPECTED_MD5") { ++i; @@ -2725,48 +2756,68 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5."); return false; } - expectedMD5sum = cmSystemTools::LowerCase(*i); + hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New("MD5")); + hashMatchMSG = "MD5 sum"; + expectedHash = cmSystemTools::LowerCase(*i); } else if(*i == "SHOW_PROGRESS") { showProgress = true; } + else if(*i == "EXPECTED_HASH") + { + ++i; + if(i == args.end()) + { + this->SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH."); + return false; + } + std::string::size_type pos = i->find("="); + if(pos == std::string::npos) + { + std::string err = + "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: "; + err += *i; + this->SetError(err.c_str()); + return false; + } + std::string algo = i->substr(0, pos); + expectedHash = cmSystemTools::LowerCase(i->substr(pos+1)); + hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New(algo.c_str())); + if(!hash.get()) + { + std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: "; + err += algo; + this->SetError(err.c_str()); + return false; + } + hashMatchMSG = algo + " hash"; + } ++i; } - - // If file exists already, and caller specified an expected md5 sum, - // and the existing file already has the expected md5 sum, then simply + // If file exists already, and caller specified an expected md5 or sha, + // and the existing file already has the expected hash, then simply // return. // - if(cmSystemTools::FileExists(file.c_str()) && - !expectedMD5sum.empty()) + if(cmSystemTools::FileExists(file.c_str()) && hash.get()) { - char computedMD5[32]; - - if (!cmSystemTools::ComputeFileMD5(file.c_str(), computedMD5)) - { - this->SetError("DOWNLOAD cannot compute MD5 sum on pre-existing file"); - return false; - } - - std::string actualMD5sum = cmSystemTools::LowerCase( - std::string(computedMD5, 32)); - - if (expectedMD5sum == actualMD5sum) + std::string msg; + std::string actualHash = hash->HashFile(file.c_str()); + if(actualHash == expectedHash) { + msg = "returning early; file already exists with expected "; + msg += hashMatchMSG; + msg += "\""; if(statusVar.size()) { cmOStringStream result; - result << (int)0 << ";\"" - "returning early: file already exists with expected MD5 sum\""; + result << (int)0 << ";\"" << msg; this->Makefile->AddDefinition(statusVar.c_str(), result.str().c_str()); } - return true; } } - // Make sure parent directory exists so we can write to the file // as we receive downloaded bits from curl... // @@ -2798,7 +2849,6 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } cURLEasyGuard g_curl(curl); - ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); check_curl_result(res, "DOWNLOAD cannot set url: "); @@ -2806,6 +2856,9 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) res = ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); check_curl_result(res, "DOWNLOAD cannot set http failure option: "); + res = ::curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/" LIBCURL_VERSION); + check_curl_result(res, "DOWNLOAD cannot set user agent option: "); + res = ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cmWriteToFileCallback); check_curl_result(res, "DOWNLOAD cannot set write function: "); @@ -2814,6 +2867,25 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) cmFileCommandCurlDebugCallback); check_curl_result(res, "DOWNLOAD cannot set debug function: "); + // check to see if TLS verification is requested + if(tls_verify) + { + res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1); + check_curl_result(res, "Unable to set TLS/SSL Verify on: "); + } + else + { + res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + check_curl_result(res, "Unable to set TLS/SSL Verify off: "); + } + // check to see if a CAINFO file has been specified + // command arg comes first + if(cainfo && *cainfo) + { + res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } + cmFileCommandVectorOfChar chunkDebug; res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&fout); @@ -2888,26 +2960,22 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) // Verify MD5 sum if requested: // - if (!expectedMD5sum.empty()) + if (hash.get()) { - char computedMD5[32]; - - if (!cmSystemTools::ComputeFileMD5(file.c_str(), computedMD5)) + std::string actualHash = hash->HashFile(file.c_str()); + if (actualHash.size() == 0) { - this->SetError("DOWNLOAD cannot compute MD5 sum on downloaded file"); + this->SetError("DOWNLOAD cannot compute hash on downloaded file"); return false; } - std::string actualMD5sum = cmSystemTools::LowerCase( - std::string(computedMD5, 32)); - - if (expectedMD5sum != actualMD5sum) + if (expectedHash != actualHash) { cmOStringStream oss; - oss << "DOWNLOAD MD5 mismatch" << std::endl + oss << "DOWNLOAD HASH mismatch" << std::endl << " for file: [" << file << "]" << std::endl - << " expected MD5 sum: [" << expectedMD5sum << "]" << std::endl - << " actual MD5 sum: [" << actualMD5sum << "]" << std::endl + << " expected hash: [" << expectedHash << "]" << std::endl + << " actual hash: [" << actualHash << "]" << std::endl ; this->SetError(oss.str().c_str()); return false; |