epee: optionally restrict HTTP service to a configurable user agent
This is intended to catch traffic coming from a web browser, so we avoid issues with a web page sending a transfer RPC to the wallet. Requiring a particular user agent can act as a simple password scheme, while we wait for 0MQ and proper authentication to be merged.
This commit is contained in:
parent
68e6678ab7
commit
eeb2bbc0fc
|
@ -98,6 +98,7 @@ namespace net_utils
|
||||||
std::string m_content_encoding; //"Content-Encoding:"
|
std::string m_content_encoding; //"Content-Encoding:"
|
||||||
std::string m_host; //"Host:"
|
std::string m_host; //"Host:"
|
||||||
std::string m_cookie; //"Cookie:"
|
std::string m_cookie; //"Cookie:"
|
||||||
|
std::string m_user_agent; //"User-Agent:"
|
||||||
fields_list m_etc_fields;
|
fields_list m_etc_fields;
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
|
@ -110,6 +111,7 @@ namespace net_utils
|
||||||
m_content_encoding.clear();
|
m_content_encoding.clear();
|
||||||
m_host.clear();
|
m_host.clear();
|
||||||
m_cookie.clear();
|
m_cookie.clear();
|
||||||
|
m_user_agent.clear();
|
||||||
m_etc_fields.clear();
|
m_etc_fields.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -638,10 +638,10 @@ using namespace std;
|
||||||
LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_4);
|
LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_4);
|
||||||
|
|
||||||
STATIC_REGEXP_EXPR_1(rexp_mach_field,
|
STATIC_REGEXP_EXPR_1(rexp_mach_field,
|
||||||
"\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)"
|
"\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)"
|
||||||
// 12 3 4 5 6 7 8 9
|
// 12 3 4 5 6 7 8 9 10
|
||||||
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
|
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
|
||||||
//10 1112 13
|
//11 1213 14
|
||||||
boost::regex::icase | boost::regex::normal);
|
boost::regex::icase | boost::regex::normal);
|
||||||
|
|
||||||
boost::smatch result;
|
boost::smatch result;
|
||||||
|
@ -653,8 +653,8 @@ using namespace std;
|
||||||
//lookup all fields and fill well-known fields
|
//lookup all fields and fill well-known fields
|
||||||
while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
|
while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
|
||||||
{
|
{
|
||||||
const size_t field_val = 12;
|
const size_t field_val = 13;
|
||||||
//const size_t field_etc_name = 10;
|
//const size_t field_etc_name = 11;
|
||||||
|
|
||||||
int i = 2; //start position = 2
|
int i = 2; //start position = 2
|
||||||
if(result[i++].matched)//"Connection"
|
if(result[i++].matched)//"Connection"
|
||||||
|
@ -675,6 +675,8 @@ using namespace std;
|
||||||
}
|
}
|
||||||
else if(result[i++].matched)//"Cookie"
|
else if(result[i++].matched)//"Cookie"
|
||||||
body_info.m_cookie = result[field_val];
|
body_info.m_cookie = result[field_val];
|
||||||
|
else if(result[i++].matched)//"User-Agent"
|
||||||
|
body_info.m_user_agent = result[field_val];
|
||||||
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
|
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
|
||||||
{;}
|
{;}
|
||||||
else
|
else
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace net_utils
|
||||||
struct http_server_config
|
struct http_server_config
|
||||||
{
|
{
|
||||||
std::string m_folder;
|
std::string m_folder;
|
||||||
|
std::string m_required_user_agent;
|
||||||
critical_section m_lock;
|
critical_section m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,8 @@ namespace net_utils
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
analize_cached_request_header_and_invoke_state(pos);
|
if (!analize_cached_request_header_and_invoke_state(pos))
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case http_state_retriving_body:
|
case http_state_retriving_body:
|
||||||
|
@ -387,8 +388,16 @@ namespace net_utils
|
||||||
{
|
{
|
||||||
LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
|
LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
|
||||||
m_state = http_state_error;
|
m_state = http_state_error;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_config.m_required_user_agent.empty() && m_query_info.m_header_info.m_user_agent != m_config.m_required_user_agent)
|
||||||
|
{
|
||||||
|
LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): unexpected user agent: " << m_query_info.m_header_info.m_user_agent);
|
||||||
|
m_state = http_state_error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_cache.erase(0, pos);
|
m_cache.erase(0, pos);
|
||||||
|
|
||||||
std::string req_command_str = m_query_info.m_full_request_str;
|
std::string req_command_str = m_query_info.m_full_request_str;
|
||||||
|
@ -473,10 +482,10 @@ namespace net_utils
|
||||||
LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_3);
|
LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_3);
|
||||||
|
|
||||||
STATIC_REGEXP_EXPR_1(rexp_mach_field,
|
STATIC_REGEXP_EXPR_1(rexp_mach_field,
|
||||||
"\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)"
|
"\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)"
|
||||||
// 12 3 4 5 6 7 8 9
|
// 12 3 4 5 6 7 8 9 10
|
||||||
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
|
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
|
||||||
//10 1112 13
|
//11 1213 14
|
||||||
boost::regex::icase | boost::regex::normal);
|
boost::regex::icase | boost::regex::normal);
|
||||||
|
|
||||||
boost::smatch result;
|
boost::smatch result;
|
||||||
|
@ -488,8 +497,8 @@ namespace net_utils
|
||||||
//lookup all fields and fill well-known fields
|
//lookup all fields and fill well-known fields
|
||||||
while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
|
while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
|
||||||
{
|
{
|
||||||
const size_t field_val = 12;
|
const size_t field_val = 13;
|
||||||
const size_t field_etc_name = 10;
|
const size_t field_etc_name = 11;
|
||||||
|
|
||||||
int i = 2; //start position = 2
|
int i = 2; //start position = 2
|
||||||
if(result[i++].matched)//"Connection"
|
if(result[i++].matched)//"Connection"
|
||||||
|
@ -508,6 +517,8 @@ namespace net_utils
|
||||||
body_info.m_host = result[field_val];
|
body_info.m_host = result[field_val];
|
||||||
else if(result[i++].matched)//"Cookie"
|
else if(result[i++].matched)//"Cookie"
|
||||||
body_info.m_cookie = result[field_val];
|
body_info.m_cookie = result[field_val];
|
||||||
|
else if(result[i++].matched)//"User-Agent"
|
||||||
|
body_info.m_user_agent = result[field_val];
|
||||||
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
|
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
|
||||||
body_info.m_etc_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
|
body_info.m_etc_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
|
||||||
else
|
else
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace epee
|
||||||
: m_net_server(external_io_service)
|
: m_net_server(external_io_service)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0")
|
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", const std::string &user_agent = "")
|
||||||
{
|
{
|
||||||
|
|
||||||
//set self as callback handler
|
//set self as callback handler
|
||||||
|
@ -61,6 +61,9 @@ namespace epee
|
||||||
//here set folder for hosting reqests
|
//here set folder for hosting reqests
|
||||||
m_net_server.get_config_object().m_folder = "";
|
m_net_server.get_config_object().m_folder = "";
|
||||||
|
|
||||||
|
// workaround till we get auth/encryption
|
||||||
|
m_net_server.get_config_object().m_required_user_agent = user_agent;
|
||||||
|
|
||||||
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
|
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
|
||||||
bool res = m_net_server.init_server(bind_port, bind_ip);
|
bool res = m_net_server.init_server(bind_port, bind_ip);
|
||||||
if(!res)
|
if(!res)
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace command_line
|
||||||
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
|
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
|
||||||
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
|
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
|
||||||
const arg_descriptor<std::string> arg_testnet_data_dir = {"testnet-data-dir", "Specify testnet data directory"};
|
const arg_descriptor<std::string> arg_testnet_data_dir = {"testnet-data-dir", "Specify testnet data directory"};
|
||||||
|
const arg_descriptor<std::string> arg_user_agent = {"user-agent", "Restrict RPC use to clients using this user agent"};
|
||||||
const arg_descriptor<bool> arg_test_drop_download = {"test-drop-download", "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"};
|
const arg_descriptor<bool> arg_test_drop_download = {"test-drop-download", "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"};
|
||||||
const arg_descriptor<uint64_t> arg_test_drop_download_height = {"test-drop-download-height", "Like test-drop-download but disards only after around certain height", 0};
|
const arg_descriptor<uint64_t> arg_test_drop_download_height = {"test-drop-download-height", "Like test-drop-download but disards only after around certain height", 0};
|
||||||
const arg_descriptor<int> arg_test_dbg_lock_sleep = {"test-dbg-lock-sleep", "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."};
|
const arg_descriptor<int> arg_test_dbg_lock_sleep = {"test-dbg-lock-sleep", "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."};
|
||||||
|
|
|
@ -204,6 +204,7 @@ namespace command_line
|
||||||
extern const arg_descriptor<bool> arg_version;
|
extern const arg_descriptor<bool> arg_version;
|
||||||
extern const arg_descriptor<std::string> arg_data_dir;
|
extern const arg_descriptor<std::string> arg_data_dir;
|
||||||
extern const arg_descriptor<std::string> arg_testnet_data_dir;
|
extern const arg_descriptor<std::string> arg_testnet_data_dir;
|
||||||
|
extern const arg_descriptor<std::string> arg_user_agent;
|
||||||
extern const arg_descriptor<bool> arg_test_drop_download;
|
extern const arg_descriptor<bool> arg_test_drop_download;
|
||||||
extern const arg_descriptor<uint64_t> arg_test_drop_download_height;
|
extern const arg_descriptor<uint64_t> arg_test_drop_download_height;
|
||||||
extern const arg_descriptor<int> arg_test_dbg_lock_sleep;
|
extern const arg_descriptor<int> arg_test_dbg_lock_sleep;
|
||||||
|
|
|
@ -34,10 +34,11 @@ namespace daemonize {
|
||||||
t_command_parser_executor::t_command_parser_executor(
|
t_command_parser_executor::t_command_parser_executor(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc
|
, bool is_rpc
|
||||||
, cryptonote::core_rpc_server* rpc_server
|
, cryptonote::core_rpc_server* rpc_server
|
||||||
)
|
)
|
||||||
: m_executor(ip, port, is_rpc, rpc_server)
|
: m_executor(ip, port, user_agent, is_rpc, rpc_server)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& args)
|
bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& args)
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
t_command_parser_executor(
|
t_command_parser_executor(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc
|
, bool is_rpc
|
||||||
, cryptonote::core_rpc_server* rpc_server = NULL
|
, cryptonote::core_rpc_server* rpc_server = NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,10 +37,11 @@ namespace p = std::placeholders;
|
||||||
t_command_server::t_command_server(
|
t_command_server::t_command_server(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc
|
, bool is_rpc
|
||||||
, cryptonote::core_rpc_server* rpc_server
|
, cryptonote::core_rpc_server* rpc_server
|
||||||
)
|
)
|
||||||
: m_parser(ip, port, is_rpc, rpc_server)
|
: m_parser(ip, port, user_agent, is_rpc, rpc_server)
|
||||||
, m_command_lookup()
|
, m_command_lookup()
|
||||||
, m_is_rpc(is_rpc)
|
, m_is_rpc(is_rpc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
t_command_server(
|
t_command_server(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc = true
|
, bool is_rpc = true
|
||||||
, cryptonote::core_rpc_server* rpc_server = NULL
|
, cryptonote::core_rpc_server* rpc_server = NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,7 @@ bool t_daemon::run(bool interactive)
|
||||||
|
|
||||||
if (interactive)
|
if (interactive)
|
||||||
{
|
{
|
||||||
rpc_commands = new daemonize::t_command_server(0, 0, false, mp_internals->rpc.get_server());
|
rpc_commands = new daemonize::t_command_server(0, 0, "", false, mp_internals->rpc.get_server());
|
||||||
rpc_commands->start_handling(std::bind(&daemonize::t_daemon::stop_p2p, this));
|
rpc_commands->start_handling(std::bind(&daemonize::t_daemon::stop_p2p, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,7 @@ int main(int argc, char const * argv[])
|
||||||
{
|
{
|
||||||
rpc_port_str = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_testnet_rpc_bind_port);
|
rpc_port_str = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_testnet_rpc_bind_port);
|
||||||
}
|
}
|
||||||
|
auto user_agent = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_user_agent);
|
||||||
|
|
||||||
uint32_t rpc_ip;
|
uint32_t rpc_ip;
|
||||||
uint16_t rpc_port;
|
uint16_t rpc_port;
|
||||||
|
@ -222,7 +223,7 @@ int main(int argc, char const * argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
daemonize::t_command_server rpc_commands{rpc_ip, rpc_port};
|
daemonize::t_command_server rpc_commands{rpc_ip, rpc_port, user_agent};
|
||||||
if (rpc_commands.process_command_vec(command))
|
if (rpc_commands.process_command_vec(command))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace {
|
||||||
t_rpc_command_executor::t_rpc_command_executor(
|
t_rpc_command_executor::t_rpc_command_executor(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc
|
, bool is_rpc
|
||||||
, cryptonote::core_rpc_server* rpc_server
|
, cryptonote::core_rpc_server* rpc_server
|
||||||
)
|
)
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
t_rpc_command_executor(
|
t_rpc_command_executor(
|
||||||
uint32_t ip
|
uint32_t ip
|
||||||
, uint16_t port
|
, uint16_t port
|
||||||
|
, const std::string &user_agent
|
||||||
, bool is_rpc = true
|
, bool is_rpc = true
|
||||||
, cryptonote::core_rpc_server* rpc_server = NULL
|
, cryptonote::core_rpc_server* rpc_server = NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,6 +54,7 @@ namespace cryptonote
|
||||||
command_line::add_arg(desc, arg_rpc_bind_port);
|
command_line::add_arg(desc, arg_rpc_bind_port);
|
||||||
command_line::add_arg(desc, arg_testnet_rpc_bind_port);
|
command_line::add_arg(desc, arg_testnet_rpc_bind_port);
|
||||||
command_line::add_arg(desc, arg_restricted_rpc);
|
command_line::add_arg(desc, arg_restricted_rpc);
|
||||||
|
command_line::add_arg(desc, arg_user_agent);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
core_rpc_server::core_rpc_server(
|
core_rpc_server::core_rpc_server(
|
||||||
|
@ -81,11 +82,12 @@ namespace cryptonote
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
|
m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
|
||||||
|
std::string m_user_agent = command_line::get_arg(vm, command_line::arg_user_agent);
|
||||||
|
|
||||||
m_net_server.set_threads_prefix("RPC");
|
m_net_server.set_threads_prefix("RPC");
|
||||||
bool r = handle_command_line(vm);
|
bool r = handle_command_line(vm);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
||||||
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(m_port, m_bind_ip, m_user_agent);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::check_core_busy()
|
bool core_rpc_server::check_core_busy()
|
||||||
|
@ -1277,4 +1279,10 @@ namespace cryptonote
|
||||||
, false
|
, false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const command_line::arg_descriptor<std::string> core_rpc_server::arg_user_agent = {
|
||||||
|
"user-agent"
|
||||||
|
, "Restrict RPC to clients using this user agent"
|
||||||
|
, ""
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace cryptonote
|
} // namespace cryptonote
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace cryptonote
|
||||||
static const command_line::arg_descriptor<std::string> arg_rpc_bind_port;
|
static const command_line::arg_descriptor<std::string> arg_rpc_bind_port;
|
||||||
static const command_line::arg_descriptor<std::string> arg_testnet_rpc_bind_port;
|
static const command_line::arg_descriptor<std::string> arg_testnet_rpc_bind_port;
|
||||||
static const command_line::arg_descriptor<bool> arg_restricted_rpc;
|
static const command_line::arg_descriptor<bool> arg_restricted_rpc;
|
||||||
|
static const command_line::arg_descriptor<std::string> arg_user_agent;
|
||||||
|
|
||||||
typedef epee::net_utils::connection_context_base connection_context;
|
typedef epee::net_utils::connection_context_base connection_context;
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,13 @@ namespace tools
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_rpc_bind_port = {"rpc-bind-port", "Starts wallet as rpc server for wallet operations, sets bind port for server", "", true};
|
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_rpc_bind_port = {"rpc-bind-port", "Starts wallet as rpc server for wallet operations, sets bind port for server", "", true};
|
||||||
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"};
|
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"};
|
||||||
|
const command_line::arg_descriptor<std::string> wallet_rpc_server::arg_user_agent = {"user-agent", "Restrict RPC to clients using this user agent", ""};
|
||||||
|
|
||||||
void wallet_rpc_server::init_options(boost::program_options::options_description& desc)
|
void wallet_rpc_server::init_options(boost::program_options::options_description& desc)
|
||||||
{
|
{
|
||||||
command_line::add_arg(desc, arg_rpc_bind_ip);
|
command_line::add_arg(desc, arg_rpc_bind_ip);
|
||||||
command_line::add_arg(desc, arg_rpc_bind_port);
|
command_line::add_arg(desc, arg_rpc_bind_port);
|
||||||
|
command_line::add_arg(desc, arg_user_agent);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w)
|
wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w)
|
||||||
|
@ -83,6 +85,7 @@ namespace tools
|
||||||
{
|
{
|
||||||
m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip);
|
m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip);
|
||||||
m_port = command_line::get_arg(vm, arg_rpc_bind_port);
|
m_port = command_line::get_arg(vm, arg_rpc_bind_port);
|
||||||
|
m_user_agent = command_line::get_arg(vm, arg_user_agent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -91,7 +94,7 @@ namespace tools
|
||||||
m_net_server.set_threads_prefix("RPC");
|
m_net_server.set_threads_prefix("RPC");
|
||||||
bool r = handle_command_line(vm);
|
bool r = handle_command_line(vm);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
|
||||||
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(m_port, m_bind_ip, m_user_agent);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er)
|
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er)
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace tools
|
||||||
|
|
||||||
const static command_line::arg_descriptor<std::string> arg_rpc_bind_port;
|
const static command_line::arg_descriptor<std::string> arg_rpc_bind_port;
|
||||||
const static command_line::arg_descriptor<std::string> arg_rpc_bind_ip;
|
const static command_line::arg_descriptor<std::string> arg_rpc_bind_ip;
|
||||||
|
const static command_line::arg_descriptor<std::string> arg_user_agent;
|
||||||
|
|
||||||
|
|
||||||
static void init_options(boost::program_options::options_description& desc);
|
static void init_options(boost::program_options::options_description& desc);
|
||||||
|
@ -120,6 +121,7 @@ namespace tools
|
||||||
wallet2& m_wallet;
|
wallet2& m_wallet;
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
std::string m_bind_ip;
|
std::string m_bind_ip;
|
||||||
|
std::string m_user_agent;
|
||||||
std::atomic<bool> m_stop;
|
std::atomic<bool> m_stop;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue