rbac3 - tx auth verify changes

This commit is contained in:
satyakoneru 2020-05-27 11:36:57 +00:00
parent c74e83d088
commit f376503ac6
9 changed files with 105 additions and 13 deletions

View file

@ -1934,6 +1934,8 @@ bool database_api_impl::verify_authority( const signed_transaction& trx )const
trx.verify_authority( _db.get_chain_id(),
[this]( account_id_type id ){ return &id(_db).active; },
[this]( account_id_type id ){ return &id(_db).owner; },
[this]( account_id_type id, const operation& op ) {
return _db.get_account_custom_authorities(id, op); },
_db.get_global_properties().parameters.max_authority_depth );
return true;
}

View file

@ -790,7 +790,10 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
{
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
trx.verify_authority( chain_id, get_active, get_owner, get_global_properties().parameters.max_authority_depth );
auto get_custom = [&]( account_id_type id, const operation& op ) {
return get_account_custom_authorities(id, op);
};
trx.verify_authority( chain_id, get_active, get_owner, get_custom, get_global_properties().parameters.max_authority_depth );
}
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is

View file

@ -27,6 +27,8 @@
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/chain_property_object.hpp>
#include <graphene/chain/global_property_object.hpp>
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/custom_account_authority_object.hpp>
#include <fc/smart_ref_impl.hpp>
@ -159,4 +161,24 @@ const witness_schedule_object& database::get_witness_schedule_object()const
return *_p_witness_schedule_obj;
}
vector<authority> database::get_account_custom_authorities(account_id_type account, const operation& op)const
{
const auto& pindex = get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
const auto& cindex = get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
auto prange = pindex.equal_range(boost::make_tuple(account));
time_point_sec now = head_block_time();
vector<authority> custom_auths;
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
{
auto crange = cindex.equal_range(boost::make_tuple(pobj.id, op.which()));
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
{
if(now >= cobj.valid_from && now < cobj.valid_to)
{
custom_auths.push_back(pobj.auth);
}
}
}
return custom_auths;
}
} }

View file

@ -294,6 +294,7 @@ namespace graphene { namespace chain {
uint32_t last_non_undoable_block_num() const;
vector<authority> get_account_custom_authorities(account_id_type account, const operation& op)const;
//////////////////// db_init.cpp ////////////////////
void initialize_evaluators();

View file

@ -148,6 +148,7 @@ namespace graphene { namespace chain {
const chain_id_type& chain_id,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH )const;
/**
@ -162,6 +163,7 @@ namespace graphene { namespace chain {
const flat_set<public_key_type>& available_keys,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
) const;
@ -194,6 +196,7 @@ namespace graphene { namespace chain {
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH,
bool allow_committe = false,
const flat_set<account_id_type>& active_aprovals = flat_set<account_id_type>(),

View file

@ -132,6 +132,30 @@ struct proposal_operation_hardfork_visitor
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
}
void operator()(const custom_permission_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_create_operation not allowed yet!" );
}
void operator()(const custom_permission_update_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_update_operation not allowed yet!" );
}
void operator()(const custom_permission_delete_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_delete_operation not allowed yet!" );
}
void operator()(const custom_account_authority_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_create_operation not allowed yet!" );
}
void operator()(const custom_account_authority_update_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_update_operation not allowed yet!" );
}
void operator()(const custom_account_authority_delete_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_delete_operation not allowed yet!" );
}
// loop and self visit in proposals
void operator()(const proposal_create_operation &v) const {
for (const op_wrapper &op : v.proposed_ops)

View file

@ -36,6 +36,8 @@ bool proposal_object::is_authorized_to_execute(database& db) const
available_key_approvals,
[&]( account_id_type id ){ return &id(db).active; },
[&]( account_id_type id ){ return &id(db).owner; },
[&]( account_id_type id, const operation& op ){
return db.get_account_custom_authorities(id, op); },
db.get_global_properties().parameters.max_authority_depth,
true, /* allow committee */
available_active_approvals,

View file

@ -248,6 +248,7 @@ struct sign_state
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion_depth,
bool allow_committe,
const flat_set<account_id_type>& active_aprovals,
@ -257,13 +258,6 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
flat_set<account_id_type> required_owner;
vector<authority> other;
for( const auto& op : ops )
operation_get_required_authorities( op, required_active, required_owner, other );
if( !allow_committe )
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
invalid_committee_approval, "Committee account may only propose transactions" );
sign_state s(sigs,get_active);
s.max_recursion = max_recursion_depth;
for( auto& id : active_aprovals )
@ -271,6 +265,37 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
for( auto& id : owner_approvals )
s.approved_by.insert( id );
auto approved_by_custom_authority = [&s, &get_custom](
account_id_type account,
operation op ) mutable {
auto custom_auths = get_custom( account, op );
for( const auto& auth : custom_auths )
if( s.check_authority( &auth ) ) return true;
return false;
};
for( const auto& op : ops )
operation_get_required_authorities( op, required_active, required_owner, other );
for( const auto& op : ops ) {
flat_set<account_id_type> operation_required_active;
operation_get_required_authorities( op, operation_required_active, required_owner, other );
auto itr = operation_required_active.begin();
while ( itr != operation_required_active.end() ) {
if ( approved_by_custom_authority( *itr, op ) )
itr = operation_required_active.erase( itr );
else
++itr;
}
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
}
if( !allow_committe )
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
invalid_committee_approval, "Committee account may only propose transactions" );
for( const auto& auth : other )
{
GRAPHENE_ASSERT( s.check_authority(&auth), tx_missing_other_auth, "Missing Authority", ("auth",auth)("sigs",sigs) );
@ -359,6 +384,7 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
const flat_set<public_key_type>& available_keys,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion
) const
{
@ -370,7 +396,7 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
result.erase( k );
try
{
graphene::chain::verify_authority( operations, result, get_active, get_owner, max_recursion );
graphene::chain::verify_authority( operations, result, get_active, get_owner, get_custom, max_recursion );
continue; // element stays erased if verify_authority is ok
}
catch( const tx_missing_owner_auth& e ) {}
@ -385,9 +411,10 @@ void signed_transaction::verify_authority(
const chain_id_type& chain_id,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
uint32_t max_recursion )const
{ try {
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, max_recursion );
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, get_custom, max_recursion );
} FC_CAPTURE_AND_RETHROW( (*this) ) }
} } // graphene::chain

View file

@ -1303,6 +1303,14 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
return &(aid(db).owner);
} ;
auto get_custom = [&](
account_id_type id,
const operation& op
) -> vector<authority>
{
return db.get_account_custom_authorities(id, op);
} ;
auto chk = [&](
const signed_transaction& tx,
flat_set<public_key_type> available_keys,
@ -1322,7 +1330,7 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
) -> bool
{
//wdump( (tx)(available_keys) );
set<public_key_type> result_set = tx.minimize_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner );
set<public_key_type> result_set = tx.minimize_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
//wdump( (result_set)(ref_set) );
return result_set == ref_set;
} ;
@ -1341,9 +1349,9 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
BOOST_CHECK( chk( tx, { alice_public_key, bob_public_key }, { alice_public_key, bob_public_key } ) );
BOOST_CHECK( chk_min( tx, { alice_public_key, bob_public_key }, { alice_public_key } ) );
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner ), fc::exception );
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom ), fc::exception );
sign( tx, alice_private_key );
tx.verify_authority( db.get_chain_id(), get_active, get_owner );
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom );
}
catch(fc::exception& e)
{