From 8fdcd8f107ead90e82be9f1959cee749b3471ac7 Mon Sep 17 00:00:00 2001 From: dimfred Date: Mon, 22 Jul 2019 16:14:25 +0200 Subject: [PATCH] fixed pull request things added original_referrer --- api_access.json | 2 + libraries/app/api.cpp | 55 ++++++++++++++----- libraries/app/application.cpp | 4 +- .../app/include/graphene/app/api_access.hpp | 3 +- libraries/chain/account_evaluator.cpp | 3 +- .../include/graphene/chain/account_object.hpp | 5 +- tests/tests/login_signed_tests.cpp | 33 ++++++++++- 7 files changed, 86 insertions(+), 19 deletions(-) diff --git a/api_access.json b/api_access.json index 6af7b6abcc..e25a8d319d 100644 --- a/api_access.json +++ b/api_access.json @@ -38,6 +38,7 @@ { "required_lifetime_member": false, "required_registrar": "registrar_name1", + "required_referrer": "", "allowed_apis": [ "database_api", @@ -49,6 +50,7 @@ { "required_lifetime_member": true, "required_registrar": "registrar_name2", + "required_referrer": "", "allowed_apis": [ "database_api", diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 69875c1a83..c07cbabf1d 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -102,18 +102,22 @@ namespace graphene { namespace app { auto op = trx.operations[0]; if( op.which() != operation::tag::value ) // only transfer op for validation return false; + const auto acc_id = op.get().from; + const auto to = op.get().to; + if( acc_id != to ) // prevent MITM attacks + return false; const auto& signature_keys = trx.get_signature_keys( db->get_chain_id() ); if( signature_keys.empty() ) return false; - + const auto& public_key = *signature_keys.begin(); - + auto key_refs = (*_database_api)->get_key_references( {public_key} )[0]; if( std::find( key_refs.begin(), key_refs.end(), acc_id ) == key_refs.end() ) return false; - + const auto& acc = acc_id(*db); optional< api_access_info_signed_variant > api_access_info_var = _app.get_api_access_info_signed( acc.name ); if( !api_access_info_var ) @@ -123,7 +127,7 @@ namespace graphene { namespace app { { const auto& api_access_info = api_access_info_var->get(); if( !verify_api_access_info_signed( acc, api_access_info ) ) - return false; // TODO or try default login then??? + return false; for( const auto& api : api_access_info.allowed_apis ) enable_api( api ); @@ -150,23 +154,48 @@ namespace graphene { namespace app { bool login_api::verify_api_access_info_signed( const account_object& acc, const api_access_info_signed& api_access_info ) { + auto db = _app.chain_database(); + if( api_access_info.required_lifetime_member && !acc.is_lifetime_member() ) return false; const auto& required_registrar_name = api_access_info.required_registrar; - if( required_registrar_name == "" ) + bool registrar_required = required_registrar_name != "" ? true : false; + + const auto& required_referrer_name = api_access_info.required_referrer; + bool referrer_required = required_referrer_name != "" ? true : false; + + if( !referrer_required && !registrar_required ) return true; - auto db = _app.chain_database(); - const string account_registrar_name = acc.registrar(*db).name; - string account_original_registrar_name; - if( acc.original_registrar ) - account_original_registrar_name = (*acc.original_registrar)(*db).name; - bool has_required_registrar = required_registrar_name == account_registrar_name - || required_registrar_name == account_original_registrar_name; + bool has_required_registrar = true; + if( registrar_required ) + { + const string acc_registrar_name = acc.registrar(*db).name; + + string acc_original_registrar_name; + if( acc.original_registrar ) + acc_original_registrar_name = (*acc.original_registrar)(*db).name; + + has_required_registrar = required_registrar_name == acc_registrar_name + || required_registrar_name == acc_original_registrar_name; + } + + bool has_required_referrer = true; + if( referrer_required ) + { + const string acc_referrer_name = acc.referrer(*db).name; + + string acc_original_referrer_name; + if( acc.original_referrer ) + acc_original_referrer_name = (*acc.original_registrar)(*db).name; + + has_required_referrer = required_referrer_name == acc_referrer_name + || required_referrer_name == acc_original_referrer_name; + } - return has_required_registrar; + return has_required_registrar && has_required_referrer; } void login_api::enable_api( const std::string& api_name ) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 13ae3adbb2..07d4140eb7 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -231,11 +231,11 @@ void application_impl::new_connection( const fc::http::websocket_connection_ptr& auto wsc = std::make_shared(c, GRAPHENE_NET_MAX_NESTED_OBJECTS); auto login = std::make_shared( std::ref(*_self) ); login->enable_api("database_api"); - + wsc->register_api(login->database()); wsc->register_api(fc::api(login)); c->set_session_data( wsc ); - + std::string username = "*"; std::string password = "*"; // Try to extract login information from "Authorization" header if present diff --git a/libraries/app/include/graphene/app/api_access.hpp b/libraries/app/include/graphene/app/api_access.hpp index 9e69d26b54..ff83bf211f 100644 --- a/libraries/app/include/graphene/app/api_access.hpp +++ b/libraries/app/include/graphene/app/api_access.hpp @@ -43,6 +43,7 @@ struct api_access_info_signed { bool required_lifetime_member; std::string required_registrar; + std::string required_referrer; std::vector< std::string > allowed_apis; }; @@ -58,7 +59,6 @@ typedef fc::static_variant< std::vector< api_access_info_signed > > api_access_info_signed_variant; - } } // graphene::app FC_REFLECT( graphene::app::api_access_info, @@ -70,6 +70,7 @@ FC_REFLECT( graphene::app::api_access_info, FC_REFLECT( graphene::app::api_access_info_signed, (required_lifetime_member) (required_registrar) + (required_referrer) (allowed_apis) ) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 9000823386..ed35e4f515 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -185,6 +185,7 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio { obj.registrar = o.registrar; obj.referrer = o.referrer; + obj.original_referrer = o.referrer; obj.lifetime_referrer = o.referrer(d).lifetime_referrer; const auto& params = global_properties.parameters; @@ -417,7 +418,7 @@ void_result account_upgrade_evaluator::do_evaluate(const account_upgrade_evaluat void_result account_upgrade_evaluator::do_apply(const account_upgrade_evaluator::operation_type& o) { try { database& d = db(); - + d.modify(*account, [&](account_object& a) { if( o.upgrade_to_lifetime_member ) { diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index c5d803d825..9fa45843f0 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -173,6 +173,8 @@ namespace graphene { namespace chain { account_id_type lifetime_referrer; /// The original registrar of this account, this value is set when account_upgrade_operation is performed optional original_registrar; + /// The original referrer of this account, this value is set when account_upgrade_operation is performed + optional original_referrer; /// Percentage of fee which should go to network. uint16_t network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; @@ -184,7 +186,7 @@ namespace graphene { namespace chain { /// The account's name. This name must be unique among all account names on the graph. May not be empty. string name; - + /** * The owner authority represents absolute control over the account. Usually the keys in this authority will * be kept in cold storage, as they should not be needed very often and compromise of these keys constitutes @@ -456,6 +458,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_object, (top_n_control_flags) (allowed_assets) (original_registrar) + (original_referrer) ) FC_REFLECT_DERIVED( graphene::chain::account_balance_object, diff --git a/tests/tests/login_signed_tests.cpp b/tests/tests/login_signed_tests.cpp index c73db524db..6fc1ddc420 100644 --- a/tests/tests/login_signed_tests.cpp +++ b/tests/tests/login_signed_tests.cpp @@ -52,6 +52,7 @@ BOOST_AUTO_TEST_CASE( fail_with_timestamp_too_fresh ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -74,6 +75,7 @@ BOOST_AUTO_TEST_CASE( fail_with_timestamp_too_old ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -89,13 +91,35 @@ BOOST_AUTO_TEST_CASE( fail_with_timestamp_too_old ) } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE( fail_with_from_neq_to ) +{ try { + + ACTORS( (alice) (bob) ); + transfer_operation op; + op.from = alice_id; + op.to = bob_id; + + signed_transaction trx; + trx.operations.push_back( op ); + trx.expiration = db.head_block_time() + 60; // too far in the past + trx.sign( alice_private_key, db.get_chain_id() ); + + auto json = fc::json::to_string( trx ); + auto encoded = fc::base64_encode( json ); + + login_api login_api( app ); + bool logged_in = login_api.login_signed( encoded ); + BOOST_CHECK( !logged_in ); + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_CASE( fail_with_not_transfer_op_in_trx ) { try { ACTOR( alice ); account_update_operation op; op.account = alice_id; - + signed_transaction trx; trx.operations.push_back( op ); trx.expiration = db.head_block_time() + 60; @@ -116,6 +140,7 @@ BOOST_AUTO_TEST_CASE( fail_with_empty_signature_keys ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -136,6 +161,7 @@ BOOST_AUTO_TEST_CASE( fail_with_wrong_signature ) ACTORS( (alice) (bob) ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -165,6 +191,7 @@ BOOST_AUTO_TEST_CASE( fail_as_default_user_no_lifetime_member ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -194,6 +221,7 @@ BOOST_AUTO_TEST_CASE( fail_as_default_user_no_required_registrar ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -223,6 +251,7 @@ BOOST_AUTO_TEST_CASE( pass_as_default_user_no_specials ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -256,6 +285,7 @@ BOOST_AUTO_TEST_CASE( pass_as_default_user_with_lifetime_member ) transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op ); @@ -285,6 +315,7 @@ BOOST_AUTO_TEST_CASE( pass_as_special_user ) ACTOR( alice ); transfer_operation op; op.from = alice_id; + op.to = alice_id; signed_transaction trx; trx.operations.push_back( op );