diff --git a/CMakeLists.txt b/CMakeLists.txt index dafabe51..29f7f065 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ ADD_BOOST(program_options chrono) ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64) +TARGET_LINK_LIBRARIES(${BII_BLOCK_TARGET} INTERFACE curl) + GIT_VERSION_INIT() ENABLE_STYLE_WARNINGS() diff --git a/src/cli/Cli.cpp b/src/cli/Cli.cpp index c7f384c9..0eb485d7 100644 --- a/src/cli/Cli.cpp +++ b/src/cli/Cli.cpp @@ -18,6 +18,8 @@ #include +#include "VersionChecker.h" + #include // needed for libc to define PASS_MAX @@ -79,12 +81,23 @@ namespace cryfs { } else if (!version::IS_STABLE_VERSION) { cout << "WARNING! This is an experimental version. Please backup your data frequently!" << endl; } else { - //TODO This is shown for stable version numbers like 0.8 - remove once we reach 1.0 + //TODO This is even shown for stable version numbers like 0.8 - remove once we reach 1.0 cout << "WARNING! This version is not considered stable. Please backup your data frequently!" << endl; } #ifndef NDEBUG cout << "WARNING! This is a debug build. Performance might be slow." << endl; #endif + VersionChecker versionChecker; + optional newestVersion = versionChecker.newestVersion(); + if (newestVersion == none) { + cout << "Could not connect to cryfs.org to check for updates." << endl; + } else if (*newestVersion != version::VERSION_STRING) { + cout << "CryFS " << *newestVersion << " is released. Please update." << endl; + } + optional securityWarning = versionChecker.securityWarningFor(version::VERSION_STRING); + if (securityWarning != none) { + cout << *securityWarning << endl; + } cout << endl; } diff --git a/src/cli/HttpClient.cpp b/src/cli/HttpClient.cpp new file mode 100644 index 00000000..91f5b6d2 --- /dev/null +++ b/src/cli/HttpClient.cpp @@ -0,0 +1,50 @@ +// Base version taken from https://techoverflow.net/blog/2013/03/15/c-simple-http-download-using-libcurl-easy-api/ +/** + * HTTPDownloader.cpp + * + * A simple C++ wrapper for the libcurl easy API. + * + * Written by Uli Köhler (techoverflow.net) + * Published under CC0 1.0 Universal (public domain) + */ +#include "HttpClient.h" +#include +#include +#include +#include + +using boost::none; +using boost::optional; +using std::string; +using std::ostringstream; + +size_t HttpClient::write_data(void *ptr, size_t size, size_t nmemb, ostringstream *stream) { + stream->write((const char*)ptr, size*nmemb); + return size * nmemb; +} + +HttpClient::HttpClient() { + curl = curl_easy_init(); +} + +HttpClient::~HttpClient() { + curl_easy_cleanup(curl); +} + +optional HttpClient::get(const string& url) { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + // example.com is redirected, so we tell libcurl to follow redirection + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Prevent "longjmp causes uninitialized stack frame" bug + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate"); + ostringstream out; + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &HttpClient::write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out); + // Perform the request, res will get the return code + CURLcode res = curl_easy_perform(curl); + // Check for errors + if (res != CURLE_OK) { + return none; + } + return out.str(); +} diff --git a/src/cli/HttpClient.h b/src/cli/HttpClient.h new file mode 100644 index 00000000..6de266f8 --- /dev/null +++ b/src/cli/HttpClient.h @@ -0,0 +1,41 @@ +// Base version taken from https://techoverflow.net/blog/2013/03/15/c-simple-http-download-using-libcurl-easy-api/ +/** + * HTTPDownloader.hpp + * + * A simple C++ wrapper for the libcurl easy API. + * + * Written by Uli Köhler (techoverflow.net) + * Published under CC0 1.0 Universal (public domain) + */ +#pragma once +#ifndef MESSMER_CRYFS_SRC_CLI_HTTPCLIENT_HPP +#define MESSMER_CRYFS_SRC_CLI_HTTPCLIENT_HPP + +#include +#include +#include + +//TODO Test + +/** + * A non-threadsafe simple libcURL-easy based HTTP downloader + */ +class HttpClient final { +public: + HttpClient(); + ~HttpClient(); + /** + * Download a file using HTTP GET and store in in a std::string + * @param url The URL to download + * @return The download result + */ + boost::optional get(const std::string& url); +private: + void* curl; + + static size_t write_data(void *ptr, size_t size, size_t nmemb, std::ostringstream *stream); + + DISALLOW_COPY_AND_ASSIGN(HttpClient); +}; + +#endif \ No newline at end of file diff --git a/src/cli/VersionChecker.cpp b/src/cli/VersionChecker.cpp new file mode 100644 index 00000000..c23eb45d --- /dev/null +++ b/src/cli/VersionChecker.cpp @@ -0,0 +1,65 @@ +#include "VersionChecker.h" +#include +#include "HttpClient.h" +#include +#include +#include + +using boost::optional; +using boost::none; +using std::string; +using boost::property_tree::ptree; +using boost::property_tree::json_parser_error; +using namespace cpputils::logging; + +#include +namespace cryfs { + + VersionChecker::VersionChecker(): _versionInfo(_getVersionInfo()) { + } + + optional VersionChecker::newestVersion() const { + if (_versionInfo == none) { + return none; + } + string version = _versionInfo->get("version_info.current", ""); + if (version == "") { + return none; + } + return version; + } + + optional VersionChecker::securityWarningFor(const string &version) const { + if (_versionInfo == none) { + return none; + } + BOOST_FOREACH(const ptree::value_type &v, _versionInfo->get_child("warnings")) { + if(v.first == version) { + return v.second.get_value(); + } + } + return none; + } + + optional VersionChecker::_getVersionInfo() { + optional response = HttpClient().get("http://www.cryfs.org/version_info.json"); + if (response == none) { + std::cout << "no response" << std::endl; + return none; + } + return _parseJson(*response); + } + + optional VersionChecker::_parseJson(const string &json) { + try { + ptree pt; + std::istringstream input(json); + read_json(input, pt); + return pt; + } catch (const json_parser_error &e) { + LOG(WARN) << "Error parsing version information json object"; + return none; + } + } + +} diff --git a/src/cli/VersionChecker.h b/src/cli/VersionChecker.h new file mode 100644 index 00000000..7a2cba10 --- /dev/null +++ b/src/cli/VersionChecker.h @@ -0,0 +1,28 @@ +#ifndef MESSMER_CRYFS_SRC_CLI_VERSIONCHECKER_H +#define MESSMER_CRYFS_SRC_CLI_VERSIONCHECKER_H + +#include +#include +#include +#include + +namespace cryfs { + //TODO Test + + class VersionChecker final { + public: + VersionChecker(); + + boost::optional newestVersion() const; + boost::optional securityWarningFor(const std::string &version) const; + private: + static boost::optional _getVersionInfo(); + static boost::optional _parseJson(const std::string &json); + + boost::optional _versionInfo; + + DISALLOW_COPY_AND_ASSIGN(VersionChecker); + }; +} + +#endif