diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/api/wallet.cpp | 2 | ||||
-rw-r--r-- | src/wallet/message_store.cpp | 101 | ||||
-rw-r--r-- | src/wallet/message_store.h | 3 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 22 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 3 |
5 files changed, 100 insertions, 31 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index d89261c64..0badd922a 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -157,7 +157,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback } } - virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time) + virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) { std::string tx_hash = epee::string_tools::pod_to_hex(txid); 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); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 93e522a93..a127e0b93 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -947,7 +947,7 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet) { - shim->get_tx_pub_key_from_received_outs = boost::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, _1); + shim->get_tx_pub_key_from_received_outs = std::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, std::placeholders::_1); } bool get_pruned_tx(const cryptonote::COMMAND_RPC_GET_TRANSACTIONS::entry &entry, cryptonote::transaction &tx, crypto::hash &tx_hash) @@ -1867,6 +1867,20 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has } } //---------------------------------------------------------------------------------------------------- +bool wallet2::spends_one_of_ours(const cryptonote::transaction &tx) const +{ + for (const auto &in: tx.vin) + { + if (in.type() != typeid(cryptonote::txin_to_key)) + continue; + const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in); + auto it = m_key_images.find(in_to_key.k_image); + if (it != m_key_images.end()) + return true; + } + return false; +} +//---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache) { PERF_TIMER(process_new_transaction); @@ -2153,7 +2167,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); if (0 != m_callback) - m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, td.m_tx.unlock_time); + m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time); } total_received_1 += amount; notify = true; @@ -2230,7 +2244,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); if (0 != m_callback) - m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, td.m_tx.unlock_time); + m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time); } total_received_1 += extra_amount; notify = true; @@ -13080,7 +13094,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs) CHECK_AND_ASSERT_THROW_MES(info.size() + 1 <= m_multisig_signers.size() && info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources"); std::vector<std::vector<rct::key>> k; - auto wiper = epee::misc_utils::create_scope_leave_handler([&](){memwipe(k.data(), k.size() * sizeof(k[0]));}); + auto wiper = epee::misc_utils::create_scope_leave_handler([&](){for (auto &v: k) memwipe(v.data(), v.size() * sizeof(v[0]));}); k.reserve(m_transfers.size()); for (const auto &td: m_transfers) k.push_back(td.m_multisig_k); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index eb33713b5..3a14215b3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -131,7 +131,7 @@ private: public: // Full wallet callbacks virtual void on_new_block(uint64_t height, const cryptonote::block& block) {} - virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time) {} + virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) {} virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index) {} virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index) {} virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {} @@ -1517,6 +1517,7 @@ private: void check_rpc_cost(const char *call, uint64_t post_call_credits, uint64_t pre_credits, double expected_cost); bool should_expand(const cryptonote::subaddress_index &index) const; + bool spends_one_of_ours(const cryptonote::transaction &tx) const; cryptonote::account_base m_account; boost::optional<epee::net_utils::http::login> m_daemon_login; |