@ -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
{
sanitized_text = tools : : utf8canonical ( sanitized_text , [ ] ( wint_t c )
{
char c = m . content [ i ] ;
if ( ( int ) c < 32 )
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 = ' ' ;
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 = ' ' ;
c = ' ? ' ;
}
return c ;
} ) ;
}
sanitized_text + = 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 )