[master] MMS: New 'config_checksum' subcommand

This commit is contained in:
rbrunner7
2020-05-04 11:31:46 +02:00
parent 82d21f5b3c
commit 7d0b7e83ef
4 changed files with 121 additions and 27 deletions

View File

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