aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_base.h3
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_client.h12
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_protocol_handler.h2
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_protocol_handler.inl55
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_server_handlers_map2.h0
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_server_impl_base.h5
-rwxr-xr-x[-rw-r--r--]src/rpc/core_rpc_server.cpp2
-rwxr-xr-x[-rw-r--r--]src/rpc/rpc_args.cpp18
-rwxr-xr-x[-rw-r--r--]src/rpc/rpc_args.h2
-rwxr-xr-x[-rw-r--r--]src/wallet/wallet_rpc_server.cpp2
10 files changed, 82 insertions, 19 deletions
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
index 144acad9d..a66fb7c23 100644..100755
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -46,6 +46,7 @@ namespace net_utils
{
enum http_method{
+ http_method_options,
http_method_get,
http_method_post,
http_method_put,
@@ -115,6 +116,7 @@ namespace net_utils
std::string m_host; //"Host:"
std::string m_cookie; //"Cookie:"
std::string m_user_agent; //"User-Agent:"
+ std::string m_origin; //"Origin:"
fields_list m_etc_fields;
void clear()
@@ -128,6 +130,7 @@ namespace net_utils
m_host.clear();
m_cookie.clear();
m_user_agent.clear();
+ m_origin.clear();
m_etc_fields.clear();
}
};
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index ed89ca0c7..80a4504e3 100644..100755
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -749,10 +749,10 @@ using namespace std;
MTRACE("http_stream_filter::parse_cached_header(*)");
STATIC_REGEXP_EXPR_1(rexp_mach_field,
- "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)"
- // 12 3 4 5 6 7 8 9 10
+ "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)"
+ // 12 3 4 5 6 7 8 9 10 11
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
- //11 1213 14
+ //12 13 14 15
boost::regex::icase | boost::regex::normal);
boost::smatch result;
@@ -764,7 +764,7 @@ using namespace std;
//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)
{
- const size_t field_val = 13;
+ const size_t field_val = 14;
//const size_t field_etc_name = 11;
int i = 2; //start position = 2
@@ -788,8 +788,10 @@ using namespace std;
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)//"Origin"
+ body_info.m_origin = result[field_val];
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
- body_info.m_etc_fields.emplace_back(result[11], result[field_val]);
+ body_info.m_etc_fields.emplace_back(result[12], result[field_val]);
else
{CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<<m_cache_to_process);}
diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h
index babe49ad7..652d8ff6f 100644..100755
--- a/contrib/epee/include/net/http_protocol_handler.h
+++ b/contrib/epee/include/net/http_protocol_handler.h
@@ -54,6 +54,7 @@ namespace net_utils
struct http_server_config
{
std::string m_folder;
+ std::vector<std::string> m_access_control_origins;
boost::optional<login> m_user;
critical_section m_lock;
};
@@ -193,6 +194,7 @@ namespace net_utils
response.m_response_code = 200;
response.m_response_comment = "OK";
response.m_body.clear();
+
return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context);
}
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index c92a13bcc..c3350bf73 100644..100755
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -316,7 +316,10 @@ namespace net_utils
CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed...");
http_ver_major = boost::lexical_cast<int>(result[11]);
http_ver_minor = boost::lexical_cast<int>(result[12]);
- if(result[4].matched)
+
+ if(result[3].matched)
+ method = http::http_method_options;
+ else if(result[4].matched)
method = http::http_method_get;
else if(result[5].matched)
method = http::http_method_head;
@@ -472,8 +475,8 @@ namespace net_utils
bool simple_http_connection_handler<t_connection_context>::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos)
{
STATIC_REGEXP_EXPR_1(rexp_mach_field,
- "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)"
- // 12 3 4 5 6 7 8 9 10
+ "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)"
+ // 12 3 4 5 6 7 8 9 10 11
"|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
//11 1213 14
boost::regex::icase | boost::regex::normal);
@@ -487,8 +490,8 @@ namespace net_utils
//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)
{
- const size_t field_val = 13;
- const size_t field_etc_name = 11;
+ const size_t field_val = 14;
+ const size_t field_etc_name = 12;
int i = 2; //start position = 2
if(result[i++].matched)//"Connection"
@@ -509,6 +512,8 @@ namespace net_utils
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)//"Origin"
+ body_info.m_origin = result[field_val];
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]));
else
@@ -537,17 +542,27 @@ namespace net_utils
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::handle_request_and_send_response(const http::http_request_info& query_info)
{
- http_response_info response;
- bool res = handle_request(query_info, response);
+ http_response_info response{};
//CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" );
+ bool res = true;
+
+ if (query_info.m_http_method != http::http_method_options)
+ {
+ res = handle_request(query_info, response);
+ }
+ else
+ {
+ response.m_response_code = 200;
+ response.m_response_comment = "OK";
+ }
std::string response_data = get_response_header(response);
-
//LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body);
+
LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data);
m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size());
- if(response.m_body.size() && (query_info.m_http_method != http::http_method_head))
+ if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options))
m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size());
return res;
}
@@ -579,7 +594,6 @@ namespace net_utils
response.m_response_comment = "OK";
response.m_mime_tipe = get_file_mime_tipe(uri_to_path);
-
return true;
}
//-----------------------------------------------------------------------------------
@@ -591,8 +605,12 @@ namespace net_utils
"Server: Epee-based\r\n"
"Content-Length: ";
buf += boost::lexical_cast<std::string>(response.m_body.size()) + "\r\n";
- buf += "Content-Type: ";
- buf += response.m_mime_tipe + "\r\n";
+
+ if(!response.m_mime_tipe.empty())
+ {
+ buf += "Content-Type: ";
+ buf += response.m_mime_tipe + "\r\n";
+ }
buf += "Last-Modified: ";
time_t tm;
@@ -612,6 +630,19 @@ namespace net_utils
m_want_close = true;
}
}
+
+ // Cross-origin resource sharing
+ if(m_query_info.m_header_info.m_origin.size())
+ {
+ if (std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), m_query_info.m_header_info.m_origin))
+ {
+ buf += "Access-Control-Allow-Origin: ";
+ buf += m_query_info.m_header_info.m_origin;
+ buf += "\r\n";
+ buf += "Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS\r\n";
+ }
+ }
+
//add additional fields, if it is
for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++)
buf += it->first + ":" + it->second + "\r\n";
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h
index 429e3e1af..429e3e1af 100644..100755
--- a/contrib/epee/include/net/http_server_handlers_map2.h
+++ b/contrib/epee/include/net/http_server_handlers_map2.h
diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
index acecbb2d4..0788c6a4b 100644..100755
--- a/contrib/epee/include/net/http_server_impl_base.h
+++ b/contrib/epee/include/net/http_server_impl_base.h
@@ -56,6 +56,7 @@ namespace epee
{}
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0",
+ std::vector<std::string> access_control_origins = std::vector<std::string>(),
boost::optional<net_utils::http::login> user = boost::none)
{
@@ -65,6 +66,10 @@ namespace epee
//here set folder for hosting reqests
m_net_server.get_config_object().m_folder = "";
+ //set access control allow origins if configured
+ std::sort(access_control_origins.begin(), access_control_origins.end());
+ m_net_server.get_config_object().m_access_control_origins = std::move(access_control_origins);
+
m_net_server.get_config_object().m_user = std::move(user);
MGINFO("Binding on " << bind_ip << ":" << bind_port);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 9095aacae..b3ce30d0c 100644..100755
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -101,7 +101,7 @@ namespace cryptonote
http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password());
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
- std::move(port), std::move(rpc_config->bind_ip), std::move(http_login)
+ std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
);
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
index 4435f74d1..93309bf3c 100644..100755
--- a/src/rpc/rpc_args.cpp
+++ b/src/rpc/rpc_args.cpp
@@ -28,6 +28,7 @@
//
#include "rpc_args.h"
+#include <boost/algorithm/string.hpp>
#include <boost/asio/ip/address.hpp>
#include "common/command_line.h"
#include "common/i18n.h"
@@ -38,6 +39,7 @@ namespace cryptonote
: rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify ip to bind rpc server"), "127.0.0.1"})
, rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
, confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")})
+ , rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""})
{}
const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); }
@@ -48,6 +50,7 @@ namespace cryptonote
command_line::add_arg(desc, arg.rpc_bind_ip);
command_line::add_arg(desc, arg.rpc_login);
command_line::add_arg(desc, arg.confirm_external_bind);
+ command_line::add_arg(desc, arg.rpc_access_control_origins);
}
boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm)
@@ -91,6 +94,21 @@ namespace cryptonote
}
}
+ auto access_control_origins_input = command_line::get_arg(vm, arg.rpc_access_control_origins);
+ if (!access_control_origins_input.empty())
+ {
+ if (!config.login)
+ {
+ LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RFC server password --") << arg.rpc_login.name << tr(" cannot be empty"));
+ return boost::none;
+ }
+
+ std::vector<std::string> access_control_origins;
+ boost::split(access_control_origins, access_control_origins_input, boost::is_any_of(","));
+ std::for_each(access_control_origins.begin(), access_control_origins.end(), boost::bind(&boost::trim<std::string>, _1, std::locale::classic()));
+ config.access_control_origins = std::move(access_control_origins);
+ }
+
return {std::move(config)};
}
}
diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h
index d6e7bab07..72b5aa706 100644..100755
--- a/src/rpc/rpc_args.h
+++ b/src/rpc/rpc_args.h
@@ -53,6 +53,7 @@ namespace cryptonote
const command_line::arg_descriptor<std::string> rpc_bind_ip;
const command_line::arg_descriptor<std::string> rpc_login;
const command_line::arg_descriptor<bool> confirm_external_bind;
+ const command_line::arg_descriptor<std::string> rpc_access_control_origins;
};
static const char* tr(const char* str);
@@ -62,6 +63,7 @@ namespace cryptonote
static boost::optional<rpc_args> process(const boost::program_options::variables_map& vm);
std::string bind_ip;
+ std::vector<std::string> access_control_origins;
boost::optional<tools::login> login; // currently `boost::none` if unspecified by user
};
}
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index a048a53ae..9ead379e5 100644..100755
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -216,7 +216,7 @@ namespace tools
m_net_server.set_threads_prefix("RPC");
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
- std::move(bind_port), std::move(rpc_config->bind_ip), std::move(http_login)
+ std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
);
}
//------------------------------------------------------------------------------------------------------------------------------