When there is a new CryFS version, ask the user to update. Furthermore, check if there is a security warning for the installed CryFS version.

This commit is contained in:
Sebastian Messmer 2015-11-23 17:43:21 +01:00
parent 8e1a0a6361
commit 2796915ffe
6 changed files with 200 additions and 1 deletions

View File

@ -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()

View File

@ -18,6 +18,8 @@
#include <gitversion/version.h>
#include "VersionChecker.h"
#include <pwd.h>
//<limits.h> 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<string> 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<string> securityWarning = versionChecker.securityWarningFor(version::VERSION_STRING);
if (securityWarning != none) {
cout << *securityWarning << endl;
}
cout << endl;
}

50
src/cli/HttpClient.cpp Normal file
View File

@ -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 <sstream>
#include <iostream>
#include <curl/curl.h>
#include <curl/easy.h>
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<string> 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();
}

41
src/cli/HttpClient.h Normal file
View File

@ -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 <string>
#include <boost/optional.hpp>
#include <messmer/cpp-utils/macros.h>
//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<std::string> 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

View File

@ -0,0 +1,65 @@
#include "VersionChecker.h"
#include <sstream>
#include "HttpClient.h"
#include <boost/property_tree/json_parser.hpp>
#include <messmer/cpp-utils/logging/logging.h>
#include <boost/foreach.hpp>
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 <iostream>
namespace cryfs {
VersionChecker::VersionChecker(): _versionInfo(_getVersionInfo()) {
}
optional<string> VersionChecker::newestVersion() const {
if (_versionInfo == none) {
return none;
}
string version = _versionInfo->get("version_info.current", "");
if (version == "") {
return none;
}
return version;
}
optional<string> 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<std::string>();
}
}
return none;
}
optional<ptree> VersionChecker::_getVersionInfo() {
optional<string> 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<ptree> 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;
}
}
}

28
src/cli/VersionChecker.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef MESSMER_CRYFS_SRC_CLI_VERSIONCHECKER_H
#define MESSMER_CRYFS_SRC_CLI_VERSIONCHECKER_H
#include <messmer/cpp-utils/macros.h>
#include <string>
#include <boost/optional.hpp>
#include <boost/property_tree/ptree.hpp>
namespace cryfs {
//TODO Test
class VersionChecker final {
public:
VersionChecker();
boost::optional<std::string> newestVersion() const;
boost::optional<std::string> securityWarningFor(const std::string &version) const;
private:
static boost::optional<boost::property_tree::ptree> _getVersionInfo();
static boost::optional<boost::property_tree::ptree> _parseJson(const std::string &json);
boost::optional<boost::property_tree::ptree> _versionInfo;
DISALLOW_COPY_AND_ASSIGN(VersionChecker);
};
}
#endif