diff options
author | rbrunner7 <rbrunner@dreamshare.ch> | 2020-05-04 11:31:46 +0200 |
---|---|---|
committer | rbrunner7 <rbrunner@dreamshare.ch> | 2020-05-24 10:23:55 +0200 |
commit | 7d0b7e83efff1a29f730dfb65fa79cb72cc92d48 (patch) | |
tree | c0b8ec30241db2514f78017bd05ffe641ae6e9db /src/wallet | |
parent | easylogging++: sanitize log payload (diff) | |
download | monero-7d0b7e83efff1a29f730dfb65fa79cb72cc92d48.tar.xz |
[master] MMS: New 'config_checksum' subcommand
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/message_store.cpp | 101 | ||||
-rw-r--r-- | src/wallet/message_store.h | 3 |
2 files changed, 79 insertions, 25 deletions
diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp index 25a8bd4ef..fb07b42f0 100644 --- a/src/wallet/message_store.cpp +++ b/src/wallet/message_store.cpp @@ -39,6 +39,7 @@ #include "serialization/binary_utils.h" #include "common/base58.h" #include "common/util.h" +#include "common/utf8.h" #include "string_tools.h" @@ -129,18 +130,18 @@ void message_store::set_signer(const multisig_wallet_state &state, authorized_signer &m = m_signers[index]; if (label) { - m.label = label.get(); + m.label = get_sanitized_text(label.get(), 50); } if (transport_address) { - m.transport_address = transport_address.get(); + m.transport_address = get_sanitized_text(transport_address.get(), 200); } if (monero_address) { m.monero_address_known = true; m.monero_address = monero_address.get(); } - // Save to minimize the chance to loose that info (at least while in beta) + // Save to minimize the chance to loose that info save(state); } @@ -202,6 +203,13 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con } uint32_t num_signers = (uint32_t)signers.size(); THROW_WALLET_EXCEPTION_IF(num_signers != m_num_authorized_signers, tools::error::wallet_internal_error, "Wrong number of signers in config: " + std::to_string(num_signers)); + for (uint32_t i = 0; i < num_signers; ++i) + { + authorized_signer &m = signers[i]; + m.label = get_sanitized_text(m.label, 50); + m.transport_address = get_sanitized_text(m.transport_address, 200); + m.auto_config_token = get_sanitized_text(m.auto_config_token, 20); + } } void message_store::process_signer_config(const multisig_wallet_state &state, const std::string &signer_config) @@ -242,10 +250,10 @@ void message_store::process_signer_config(const multisig_wallet_state &state, co } } authorized_signer &modify = m_signers[take_index]; - modify.label = m.label; // ALWAYS set label, see comments above + modify.label = get_sanitized_text(m.label, 50); // ALWAYS set label, see comments above if (!modify.me) { - modify.transport_address = m.transport_address; + modify.transport_address = get_sanitized_text(m.transport_address, 200); modify.monero_address_known = m.monero_address_known; if (m.monero_address_known) { @@ -392,6 +400,45 @@ void message_store::process_auto_config_data_message(uint32_t id) signer.auto_config_running = false; } +void add_hash(crypto::hash &sum, const crypto::hash &summand) +{ + for (uint32_t i = 0; i < crypto::HASH_SIZE; ++i) + { + uint32_t x = (uint32_t)sum.data[i]; + uint32_t y = (uint32_t)summand.data[i]; + sum.data[i] = (char)((x + y) % 256); + } +} + +// Calculate a checksum that allows signers to make sure they work with an identical signer config +// by exchanging and comparing checksums out-of-band i.e. not using the MMS; +// Because different signers have a different order of signers in the config work with "adding" +// individual hashes because that operation is commutative +std::string message_store::get_config_checksum() const +{ + crypto::hash sum = crypto::null_hash; + uint32_t num = SWAP32LE(m_num_authorized_signers); + add_hash(sum, crypto::cn_fast_hash(&num, sizeof(num))); + num = SWAP32LE(m_num_required_signers); + add_hash(sum, crypto::cn_fast_hash(&num, sizeof(num))); + for (uint32_t i = 0; i < m_num_authorized_signers; ++i) + { + const authorized_signer &m = m_signers[i]; + add_hash(sum, crypto::cn_fast_hash(m.transport_address.data(), m.transport_address.size())); + if (m.monero_address_known) + { + add_hash(sum, crypto::cn_fast_hash(&m.monero_address.m_spend_public_key, sizeof(m.monero_address.m_spend_public_key))); + add_hash(sum, crypto::cn_fast_hash(&m.monero_address.m_view_public_key, sizeof(m.monero_address.m_view_public_key))); + } + } + std::string checksum_bytes; + checksum_bytes += sum.data[0]; + checksum_bytes += sum.data[1]; + checksum_bytes += sum.data[2]; + checksum_bytes += sum.data[3]; + return epee::string_tools::buff_to_hex_nodelimer(checksum_bytes); +} + void message_store::stop_auto_config() { for (uint32_t i = 0; i < m_num_authorized_signers; ++i) @@ -661,32 +708,38 @@ void message_store::delete_all_messages() m_messages.clear(); } -// Make a message text, which is "attacker controlled data", reasonably safe to display +// Make a text, which is "attacker controlled data", reasonably safe to display // This is mostly geared towards the safe display of notes sent by "mms note" with a "mms show" command -void message_store::get_sanitized_message_text(const message &m, std::string &sanitized_text) const +std::string message_store::get_sanitized_text(const std::string &text, size_t max_length) { - sanitized_text.clear(); - // Restrict the size to fend of DOS-style attacks with heaps of data - size_t length = std::min(m.content.length(), (size_t)1000); + size_t length = std::min(text.length(), max_length); + std::string sanitized_text = text.substr(0, length); - for (size_t i = 0; i < length; ++i) + try { - char c = m.content[i]; - if ((int)c < 32) + sanitized_text = tools::utf8canonical(sanitized_text, [](wint_t c) { - // Strip out any controls, especially ESC for getting rid of potentially dangerous - // ANSI escape sequences that a console window might interpret - c = ' '; - } - else if ((c == '<') || (c == '>')) - { - // Make XML or HTML impossible that e.g. might contain scripts that Qt might execute - // when displayed in the GUI wallet - c = ' '; - } - sanitized_text += c; + if ((c < 0x20) || (c == 0x7f) || (c >= 0x80 && c <= 0x9f)) + { + // Strip out any controls, especially ESC for getting rid of potentially dangerous + // ANSI escape sequences that a console window might interpret + c = '?'; + } + else if ((c == '<') || (c == '>')) + { + // Make XML or HTML impossible that e.g. might contain scripts that Qt might execute + // when displayed in the GUI wallet + c = '?'; + } + return c; + }); + } + catch (const std::exception &e) + { + sanitized_text = "(Illegal UTF-8 string)"; } + return sanitized_text; } void message_store::write_to_file(const multisig_wallet_state &state, const std::string &filename) diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h index d40daf186..9055fd776 100644 --- a/src/wallet/message_store.h +++ b/src/wallet/message_store.h @@ -242,6 +242,7 @@ namespace mms size_t add_auto_config_data_message(const multisig_wallet_state &state, const std::string &auto_config_token); void process_auto_config_data_message(uint32_t id); + std::string get_config_checksum() const; void stop_auto_config(); // Process data just created by "me" i.e. the own local wallet, e.g. as the result of a "prepare_multisig" command @@ -275,7 +276,7 @@ namespace mms void set_message_processed_or_sent(uint32_t id); void delete_message(uint32_t id); void delete_all_messages(); - void get_sanitized_message_text(const message &m, std::string &sanitized_text) const; + static std::string get_sanitized_text(const std::string &text, size_t max_length); void send_message(const multisig_wallet_state &state, uint32_t id); bool check_for_messages(const multisig_wallet_state &state, std::vector<message> &messages); |