diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/common/boost_serialization_helper.h | 1 | ||||
-rw-r--r-- | src/common/dns_utils.cpp | 2 | ||||
-rw-r--r-- | src/common/download.cpp | 61 | ||||
-rw-r--r-- | src/common/memwipe.c | 106 | ||||
-rw-r--r-- | src/common/memwipe.h | 84 | ||||
-rw-r--r-- | src/common/password.cpp | 39 | ||||
-rw-r--r-- | src/common/password.h | 6 | ||||
-rw-r--r-- | src/common/perf_timer.cpp | 39 | ||||
-rw-r--r-- | src/common/perf_timer.h | 36 | ||||
-rw-r--r-- | src/common/stack_trace.cpp | 1 | ||||
-rw-r--r-- | src/common/updates.cpp | 3 | ||||
-rw-r--r-- | src/common/util.cpp | 21 |
13 files changed, 327 insertions, 78 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 50887e35c..7ad08ea83 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -35,6 +35,7 @@ set(common_sources download.cpp util.cpp i18n.cpp + memwipe.c password.cpp perf_timer.cpp threadpool.cpp @@ -63,6 +64,7 @@ set(common_private_headers util.h varint.h i18n.h + memwipe.h password.h perf_timer.h stack_trace.h @@ -90,5 +92,9 @@ target_link_libraries(common ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) +if(HAVE_C11) +SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11) +endif() + #monero_install_headers(common # ${common_headers}) diff --git a/src/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index 4a503d830..f8b21c52e 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.h @@ -33,6 +33,7 @@ #include <boost/archive/binary_iarchive.hpp> #include <boost/archive/portable_binary_oarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp> +#include <boost/filesystem/operations.hpp> namespace tools diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index f549218cb..d942ae9d0 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -34,6 +34,8 @@ #include "include_base_utils.h" #include <random> #include <boost/filesystem/fstream.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> using namespace epee; namespace bf = boost::filesystem; diff --git a/src/common/download.cpp b/src/common/download.cpp index 28aac5a59..87814fa5e 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -33,6 +33,7 @@ #include <boost/thread/thread.hpp> #include "cryptonote_config.h" #include "include_base_utils.h" +#include "file_io_utils.h" #include "net/http_client.h" #include "download.h" @@ -74,9 +75,20 @@ namespace tools try { boost::unique_lock<boost::mutex> lock(control->mutex); - MINFO("Downloading " << control->uri << " to " << control->path); + std::ios_base::openmode mode = std::ios_base::out | std::ios_base::binary; + uint64_t existing_size = 0; + if (epee::file_io_utils::get_file_size(control->path, existing_size) && existing_size > 0) + { + MINFO("Resuming downloading " << control->uri << " to " << control->path << " from " << existing_size); + mode |= std::ios_base::app; + } + else + { + MINFO("Downloading " << control->uri << " to " << control->path); + mode |= std::ios_base::trunc; + } std::ofstream f; - f.open(control->path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); + f.open(control->path, mode); if (!f.good()) { MERROR("Failed to open file " << control->path); control->result_cb(control->path, control->uri, control->success); @@ -85,11 +97,13 @@ namespace tools class download_client: public epee::net_utils::http::http_simple_client { public: - download_client(download_async_handle control, std::ofstream &f): - control(control), f(f), content_length(-1), total(0) {} + download_client(download_async_handle control, std::ofstream &f, uint64_t offset = 0): + control(control), f(f), content_length(-1), total(0), offset(offset) {} virtual ~download_client() { f.close(); } virtual bool on_header(const epee::net_utils::http::http_response_info &headers) { + for (const auto &kv: headers.m_header_info.m_etc_fields) + MDEBUG("Header: " << kv.first << ": " << kv.second); ssize_t length; if (epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0) { @@ -104,6 +118,26 @@ namespace tools return false; } } + if (offset > 0) + { + // we requested a range, so check if we're getting it, otherwise truncate + bool got_range = false; + const std::string prefix = "bytes=" + std::to_string(offset) + "-"; + for (const auto &kv: headers.m_header_info.m_etc_fields) + { + if (kv.first == "Content-Range" && strncmp(kv.second.c_str(), prefix.c_str(), prefix.size())) + { + got_range = true; + break; + } + } + if (!got_range) + { + MWARNING("We did not get the requested range, downloading from start"); + f.close(); + f.open(control->path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + } + } return true; } virtual bool handle_target_data(std::string &piece_of_transfer) @@ -130,7 +164,8 @@ namespace tools std::ofstream &f; ssize_t content_length; size_t total; - } client(control, f); + uint64_t offset; + } client(control, f, existing_size); epee::net_utils::http::url_content u_c; if (!epee::net_utils::parse_url(control->uri, u_c)) { @@ -147,9 +182,10 @@ namespace tools lock.unlock(); - uint16_t port = u_c.port ? u_c.port : 80; + bool ssl = u_c.schema == "https"; + uint16_t port = u_c.port ? u_c.port : ssl ? 443 : 80; MDEBUG("Connecting to " << u_c.host << ":" << port); - client.set_server(u_c.host, std::to_string(port), boost::none); + client.set_server(u_c.host, std::to_string(port), boost::none, ssl); if (!client.connect(std::chrono::seconds(30))) { boost::lock_guard<boost::mutex> lock(control->mutex); @@ -159,7 +195,14 @@ namespace tools } MDEBUG("GETting " << u_c.uri); const epee::net_utils::http::http_response_info *info = NULL; - if (!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info)) + epee::net_utils::http::fields_list fields; + if (existing_size > 0) + { + const std::string range = "bytes=" + std::to_string(existing_size) + "-"; + MDEBUG("Asking for range: " << range); + fields.push_back(std::make_pair("Range", range)); + } + if (!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info, fields)) { boost::lock_guard<boost::mutex> lock(control->mutex); MERROR("Failed to connect to " << control->uri); @@ -189,7 +232,7 @@ namespace tools MDEBUG("response body: " << info->m_body); for (const auto &f: info->m_additional_fields) MDEBUG("additional field: " << f.first << ": " << f.second); - if (info->m_response_code != 200) + if (info->m_response_code != 200 && info->m_response_code != 206) { boost::lock_guard<boost::mutex> lock(control->mutex); MERROR("Status code " << info->m_response_code); diff --git a/src/common/memwipe.c b/src/common/memwipe.c new file mode 100644 index 000000000..da7e9f346 --- /dev/null +++ b/src/common/memwipe.c @@ -0,0 +1,106 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file Copyright (c) 2009-2015 The Bitcoin Core developers + +#define __STDC_WANT_LIB_EXT1__ 1 +#include <string.h> +#include <stdlib.h> +#ifdef HAVE_EXPLICIT_BZERO +#include <strings.h> +#endif +#include "memwipe.h" + +#if defined(_MSC_VER) +#define SCARECROW \ + __asm; +#else +#define SCARECROW \ + __asm__ __volatile__("" : : "r"(ptr) : "memory"); +#endif + +#ifdef HAVE_MEMSET_S + +void *memwipe(void *ptr, size_t n) +{ + if (memset_s(ptr, n, 0, n)) + { + abort(); + } + SCARECROW // might as well... + return ptr; +} + +#elif defined HAVE_EXPLICIT_BZERO + +void *memwipe(void *ptr, size_t n) +{ + explicit_bzero(ptr, n); + SCARECROW + return ptr; +} + +#else + +/* The memory_cleanse implementation is taken from Bitcoin */ + +/* Compilers have a bad habit of removing "superfluous" memset calls that + * are trying to zero memory. For example, when memset()ing a buffer and + * then free()ing it, the compiler might decide that the memset is + * unobservable and thus can be removed. + * + * Previously we used OpenSSL which tried to stop this by a) implementing + * memset in assembly on x86 and b) putting the function in its own file + * for other platforms. + * + * This change removes those tricks in favour of using asm directives to + * scare the compiler away. As best as our compiler folks can tell, this is + * sufficient and will continue to be so. + * + * Adam Langley <agl@google.com> + * Commit: ad1907fe73334d6c696c8539646c21b11178f20f + * BoringSSL (LICENSE: ISC) + */ +static void memory_cleanse(void *ptr, size_t len) +{ + memset(ptr, 0, len); + + /* As best as we can tell, this is sufficient to break any optimisations that + might try to eliminate "superfluous" memsets. If there's an easy way to + detect memset_s, it would be better to use that. */ + SCARECROW +} + +void *memwipe(void *ptr, size_t n) +{ + memory_cleanse(ptr, n); + SCARECROW + return ptr; +} + +#endif diff --git a/src/common/memwipe.h b/src/common/memwipe.h new file mode 100644 index 000000000..c3b4ce8ab --- /dev/null +++ b/src/common/memwipe.h @@ -0,0 +1,84 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#ifdef __cplusplus +#include <array> + +extern "C" { +#endif + +void *memwipe(void *src, size_t n); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +namespace tools { + + /// Scrubs data in the contained type upon destruction. + /// + /// Primarily useful for making sure that private keys don't stick around in + /// memory after the objects that held them have gone out of scope. + template <class T> + struct scrubbed : public T { + using type = T; + + ~scrubbed() { + scrub(); + } + + /// Destroy the contents of the contained type. + void scrub() { + static_assert(std::is_pod<T>::value, + "T cannot be auto-scrubbed. T must be POD."); + static_assert(std::is_trivially_destructible<T>::value, + "T cannot be auto-scrubbed. T must be trivially destructable."); + memwipe(this, sizeof(T)); + } + }; + + template <class T, size_t N> + using scrubbed_arr = scrubbed<std::array<T, N>>; +} // namespace tools + +// Partial specialization for std::is_pod<tools::scrubbed<T>> so that it can +// pretend to be the containted type in those contexts. +namespace std +{ + template<class t_scrubbee> + struct is_pod<tools::scrubbed<t_scrubbee>> { + static const bool value = is_pod<t_scrubbee>::value; + }; +} + +#endif // __cplusplus diff --git a/src/common/password.cpp b/src/common/password.cpp index 5d56464a5..dc0856160 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -46,6 +46,8 @@ #include "readline_buffer.h" #endif +#include "common/memwipe.h" + namespace { #if defined(_WIN32) @@ -54,7 +56,7 @@ namespace return 0 != _isatty(_fileno(stdin)); } - bool read_from_tty(std::string& pass) + bool read_from_tty(epee::wipeable_string& pass) { static constexpr const char BACKSPACE = 8; @@ -86,8 +88,7 @@ namespace { if (!pass.empty()) { - pass.back() = '\0'; - pass.resize(pass.size() - 1); + pass.pop_back(); } } else @@ -125,7 +126,7 @@ namespace return ch; } - bool read_from_tty(std::string& aPass) + bool read_from_tty(epee::wipeable_string& aPass) { static constexpr const char BACKSPACE = 127; @@ -146,8 +147,7 @@ namespace { if (!aPass.empty()) { - aPass.back() = '\0'; - aPass.resize(aPass.size() - 1); + aPass.pop_back(); } } else @@ -161,14 +161,7 @@ namespace #endif // end !WIN32 - void clear(std::string& pass) noexcept - { - //! TODO Call a memory wipe function that hopefully is not optimized out - pass.replace(0, pass.capacity(), pass.capacity(), '\0'); - pass.clear(); - } - - bool read_from_tty(const bool verify, const char *message, std::string& pass1, std::string& pass2) + bool read_from_tty(const bool verify, const char *message, epee::wipeable_string& pass1, epee::wipeable_string& pass2) { while (true) { @@ -178,14 +171,14 @@ namespace return false; if (verify) { - std::cout << "Confirm Password: "; + std::cout << "Confirm password: "; if (!read_from_tty(pass2)) return false; if(pass1!=pass2) { std::cout << "Passwords do not match! Please try again." << std::endl; - clear(pass1); - clear(pass2); + pass1.clear(); + pass2.clear(); } else //new password matches return true; @@ -198,7 +191,7 @@ namespace return false; } - bool read_from_file(std::string& pass) + bool read_from_file(epee::wipeable_string& pass) { pass.reserve(tools::password_container::max_password_size); for (size_t i = 0; i < tools::password_container::max_password_size; ++i) @@ -233,7 +226,7 @@ namespace tools password_container::~password_container() noexcept { - clear(m_password); + m_password.clear(); } boost::optional<password_container> password_container::prompt(const bool verify, const char *message) @@ -249,9 +242,8 @@ namespace tools boost::optional<login> login::parse(std::string&& userpass, bool verify, const std::function<boost::optional<password_container>(bool)> &prompt) { login out{}; - password_container wipe{std::move(userpass)}; - const auto loc = wipe.password().find(':'); + const auto loc = userpass.find(':'); if (loc == std::string::npos) { auto result = prompt(verify); @@ -262,10 +254,11 @@ namespace tools } else { - out.password = password_container{wipe.password().substr(loc + 1)}; + out.password = password_container{userpass.substr(loc + 1)}; } - out.username = wipe.password().substr(0, loc); + out.username = userpass.substr(0, loc); + password_container wipe{std::move(userpass)}; return {std::move(out)}; } } diff --git a/src/common/password.h b/src/common/password.h index ba1c30a28..01c6bf05a 100644 --- a/src/common/password.h +++ b/src/common/password.h @@ -32,6 +32,7 @@ #include <string> #include <boost/optional/optional.hpp> +#include "wipeable_string.h" namespace tools { @@ -58,11 +59,10 @@ namespace tools password_container& operator=(const password_container&) = delete; password_container& operator=(password_container&&) = default; - const std::string& password() const noexcept { return m_password; } + const epee::wipeable_string &password() const noexcept { return m_password; } private: - //! TODO Custom allocator that locks to RAM? - std::string m_password; + epee::wipeable_string m_password; }; struct login diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index 3b68485d9..4947058d3 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -26,6 +26,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include <vector> +#include "misc_os_dependent.h" #include "perf_timer.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -35,7 +37,8 @@ namespace tools { el::Level performance_timer_log_level = el::Level::Debug; -__thread std::vector<PerformanceTimer*> *performance_timers = NULL; + +static __thread std::vector<PerformanceTimer*> *performance_timers = NULL; void set_performance_timer_log_level(el::Level level) { @@ -48,4 +51,38 @@ void set_performance_timer_log_level(el::Level level) performance_timer_log_level = level; } +PerformanceTimer::PerformanceTimer(const std::string &s, uint64_t unit, el::Level l): name(s), unit(unit), level(l), started(false) +{ + ticks = epee::misc_utils::get_ns_count(); + if (!performance_timers) + { + MLOG(level, "PERF ----------"); + performance_timers = new std::vector<PerformanceTimer*>(); + } + else + { + PerformanceTimer *pt = performance_timers->back(); + if (!pt->started) + { + MLOG(pt->level, "PERF " << std::string((performance_timers->size()-1) * 2, ' ') << " " << pt->name); + pt->started = true; + } + } + performance_timers->push_back(this); +} + +PerformanceTimer::~PerformanceTimer() +{ + performance_timers->pop_back(); + ticks = epee::misc_utils::get_ns_count() - ticks; + char s[12]; + snprintf(s, sizeof(s), "%8llu ", (unsigned long long)ticks / (1000000000 / unit)); + MLOG(level, "PERF " << s << std::string(performance_timers->size() * 2, ' ') << " " << name); + if (performance_timers->empty()) + { + delete performance_timers; + performance_timers = NULL; + } +} + } diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index 4d7d99afb..a1d71609c 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -41,44 +41,12 @@ namespace tools class PerformanceTimer; extern el::Level performance_timer_log_level; -extern __thread std::vector<PerformanceTimer*> *performance_timers; class PerformanceTimer { public: - PerformanceTimer(const std::string &s, uint64_t unit, el::Level l = el::Level::Debug): name(s), unit(unit), level(l), started(false) - { - ticks = epee::misc_utils::get_ns_count(); - if (!performance_timers) - { - MLOG(level, "PERF ----------"); - performance_timers = new std::vector<PerformanceTimer*>(); - } - else - { - PerformanceTimer *pt = performance_timers->back(); - if (!pt->started) - { - MLOG(pt->level, "PERF " << std::string((performance_timers->size()-1) * 2, ' ') << " " << pt->name); - pt->started = true; - } - } - performance_timers->push_back(this); - } - - ~PerformanceTimer() - { - performance_timers->pop_back(); - ticks = epee::misc_utils::get_ns_count() - ticks; - char s[12]; - snprintf(s, sizeof(s), "%8llu ", (unsigned long long)ticks / (1000000000 / unit)); - MLOG(level, "PERF " << s << std::string(performance_timers->size() * 2, ' ') << " " << name); - if (performance_timers->empty()) - { - delete performance_timers; - performance_timers = NULL; - } - } + PerformanceTimer(const std::string &s, uint64_t unit, el::Level l = el::Level::Debug); + ~PerformanceTimer(); private: std::string name; diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp index 6fdf4dd47..bcdf72b60 100644 --- a/src/common/stack_trace.cpp +++ b/src/common/stack_trace.cpp @@ -39,6 +39,7 @@ #ifndef STATICLIB #include <dlfcn.h> #endif +#include <boost/algorithm/string.hpp> #include "common/stack_trace.h" #include "misc_log_ex.h" diff --git a/src/common/updates.cpp b/src/common/updates.cpp index 141330c2c..2d9c2d89c 100644 --- a/src/common/updates.cpp +++ b/src/common/updates.cpp @@ -26,6 +26,7 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include <boost/algorithm/string.hpp> #include "misc_log_ex.h" #include "util.h" #include "dns_utils.h" @@ -98,7 +99,7 @@ namespace tools std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user) { - const char *base = user ? "https://downloads.getmonero.org/" : "http://updates.getmonero.org/"; + const char *base = user ? "https://downloads.getmonero.org/" : "https://updates.getmonero.org/"; #ifdef _WIN32 static const char *extension = strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe"; #else diff --git a/src/common/util.cpp b/src/common/util.cpp index e8ac61815..2a2f50c4f 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -36,9 +36,11 @@ #include "include_base_utils.h" #include "file_io_utils.h" +#include "wipeable_string.h" using namespace epee; #include "util.h" +#include "memwipe.h" #include "cryptonote_config.h" #include "net/http_client.h" // epee::net_utils::... @@ -52,6 +54,7 @@ using namespace epee; #include <sys/stat.h> #endif #include <boost/filesystem.hpp> +#include <boost/algorithm/string.hpp> #include <boost/asio.hpp> #include <openssl/sha.h> @@ -542,6 +545,10 @@ std::string get_nix_version_display_string() } bool on_startup() { + wipeable_string::set_wipe(&memwipe); + + mlog_configure("", true); + sanitize_locale(); #ifdef __GLIBC__ @@ -628,13 +635,13 @@ std::string get_nix_version_display_string() int vercmp(const char *v0, const char *v1) { std::vector<std::string> f0, f1; - boost::split(f0, v0, boost::is_any_of(".")); - boost::split(f1, v1, boost::is_any_of(".")); - while (f0.size() < f1.size()) - f0.push_back("0"); - while (f1.size() < f0.size()) - f1.push_back("0"); - for (size_t i = 0; i < f0.size(); ++i) { + boost::split(f0, v0, boost::is_any_of(".-")); + boost::split(f1, v1, boost::is_any_of(".-")); + for (size_t i = 0; i < std::max(f0.size(), f1.size()); ++i) { + if (i >= f0.size()) + return -1; + if (i >= f1.size()) + return 1; int f0i = atoi(f0[i].c_str()), f1i = atoi(f1[i].c_str()); int n = f0i - f1i; if (n) |