aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee
diff options
context:
space:
mode:
authorLee Clagett <code@leeclagett.com>2017-02-05 17:48:03 -0500
committerLee Clagett <code@leeclagett.com>2017-02-06 01:15:41 -0500
commitce7fcbb4aea884bb4bf433cf419ffa267f859c87 (patch)
treee8fb644b62006d78f801d739fbebad50f2c2409d /contrib/epee
parentMerge pull request #1669 (diff)
downloadmonero-ce7fcbb4aea884bb4bf433cf419ffa267f859c87.tar.xz
Add server auth to monerod, and client auth to wallet-cli and wallet-rpc
Diffstat (limited to 'contrib/epee')
-rw-r--r--contrib/epee/include/net/http_base.h12
-rw-r--r--contrib/epee/include/net/http_client.h95
-rw-r--r--contrib/epee/include/net/http_protocol_handler.h1
-rw-r--r--contrib/epee/include/net/http_protocol_handler.inl7
-rw-r--r--contrib/epee/include/net/http_server_impl_base.h4
-rw-r--r--contrib/epee/include/storages/http_abstract_invoke.h11
-rw-r--r--contrib/epee/src/http_auth.cpp2
7 files changed, 86 insertions, 46 deletions
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
index d8e31521f..e5aa06cb4 100644
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -29,6 +29,9 @@
#pragma once
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
+#include <boost/utility/string_ref.hpp>
+#include <string>
+#include <utility>
#include "string_tools.h"
@@ -90,6 +93,15 @@ namespace net_utils
return std::string();
}
+ static inline void add_field(std::string& out, const boost::string_ref name, const boost::string_ref value)
+ {
+ out.append(name.data(), name.size()).append(": ");
+ out.append(value.data(), value.size()).append("\r\n");
+ }
+ static inline void add_field(std::string& out, const std::pair<std::string, std::string>& field)
+ {
+ add_field(out, field.first, field.second);
+ }
struct http_header_info
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index c5aeb9251..3d8c759cd 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -30,6 +30,8 @@
#include <boost/shared_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/utility/string_ref.hpp>
//#include <mbstring.h>
#include <algorithm>
#include <cctype>
@@ -45,6 +47,7 @@
#include "string_tools.h"
#include "reg_exp_definer.h"
#include "http_base.h"
+#include "http_auth.h"
#include "to_nonconst_iterator.h"
#include "net_parse_helpers.h"
@@ -236,9 +239,6 @@ using namespace std;
class http_simple_client: public i_target_handler
{
- public:
-
-
private:
enum reciev_machine_state
{
@@ -263,6 +263,7 @@ using namespace std;
blocked_mode_client m_net_client;
std::string m_host_buff;
std::string m_port;
+ http_client_auth m_auth;
std::string m_header_cache;
http_response_info m_response_info;
size_t m_len_in_summary;
@@ -280,6 +281,7 @@ using namespace std;
, m_net_client()
, m_host_buff()
, m_port()
+ , m_auth()
, m_header_cache()
, m_response_info()
, m_len_in_summary(0)
@@ -291,21 +293,22 @@ using namespace std;
, m_lock()
{}
- bool set_server(const std::string& address)
+ bool set_server(const std::string& address, boost::optional<login> user)
{
http::url_content parsed{};
const bool r = parse_url(address, parsed);
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
- set_server(std::move(parsed.host), std::to_string(parsed.port));
+ set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user));
return true;
}
- void set_server(std::string host, std::string port)
+ void set_server(std::string host, std::string port, boost::optional<login> user)
{
CRITICAL_REGION_LOCAL(m_lock);
disconnect();
m_host_buff = std::move(host);
m_port = std::move(port);
+ m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{};
}
bool connect(std::chrono::milliseconds timeout)
@@ -335,14 +338,14 @@ using namespace std;
}
//---------------------------------------------------------------------------
inline
- bool invoke_get(const std::string& uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params);
}
//---------------------------------------------------------------------------
- inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
if(!is_connected())
@@ -354,32 +357,64 @@ using namespace std;
return false;
}
}
- m_response_info.clear();
- std::string req_buff = method + " ";
- req_buff += uri + " HTTP/1.1\r\n" +
- "Host: "+ m_host_buff +"\r\n" + "Content-Length: " + boost::lexical_cast<std::string>(body.size()) + "\r\n";
+ std::string req_buff{};
+ req_buff.reserve(2048);
+ req_buff.append(method.data(), method.size()).append(" ").append(uri.data(), uri.size()).append(" HTTP/1.1\r\n");
+ add_field(req_buff, "Host", m_host_buff);
+ add_field(req_buff, "Content-Length", std::to_string(body.size()));
//handle "additional_params"
- for(fields_list::const_iterator it = additional_params.begin(); it!=additional_params.end(); it++)
- req_buff += it->first + ": " + it->second + "\r\n";
- req_buff += "\r\n";
- //--
-
- bool res = m_net_client.send(req_buff, timeout);
- CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
- if(body.size())
- res = m_net_client.send(body, timeout);
- CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
-
- if(ppresponse_info)
- *ppresponse_info = &m_response_info;
-
- m_state = reciev_machine_state_header;
- return handle_reciev(timeout);
+ for(const auto& field : additional_params)
+ add_field(req_buff, field);
+
+ for (unsigned sends = 0; sends < 2; ++sends)
+ {
+ const std::size_t initial_size = req_buff.size();
+ const auto auth = m_auth.get_auth_field(method, uri);
+ if (auth)
+ add_field(req_buff, *auth);
+
+ req_buff += "\r\n";
+ //--
+
+ bool res = m_net_client.send(req_buff, timeout);
+ CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
+ if(body.size())
+ res = m_net_client.send(body, timeout);
+ CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
+
+
+ m_response_info.clear();
+ m_state = reciev_machine_state_header;
+ if (!handle_reciev(timeout))
+ return false;
+ if (m_response_info.m_response_code != 401)
+ {
+ if(ppresponse_info)
+ *ppresponse_info = std::addressof(m_response_info);
+ return true;
+ }
+
+ switch (m_auth.handle_401(m_response_info))
+ {
+ case http_client_auth::kSuccess:
+ break;
+ case http_client_auth::kBadPassword:
+ sends = 2;
+ break;
+ default:
+ case http_client_auth::kParseFailure:
+ LOG_ERROR("Bad server response for authentication");
+ return false;
+ }
+ req_buff.resize(initial_size); // rollback for new auth generation
+ }
+ LOG_ERROR("Client has incorrect username/password for server requiring authentication");
+ return false;
}
//---------------------------------------------------------------------------
- inline bool invoke_post(const std::string& uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
@@ -730,7 +765,7 @@ using namespace std;
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!)
- {;}
+ body_info.m_etc_fields.emplace_back(result[11], 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 c2e44c536..babe49ad7 100644
--- a/contrib/epee/include/net/http_protocol_handler.h
+++ b/contrib/epee/include/net/http_protocol_handler.h
@@ -54,7 +54,6 @@ namespace net_utils
struct http_server_config
{
std::string m_folder;
- std::string m_required_user_agent;
boost::optional<login> m_user;
critical_section m_lock;
};
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index 5bfaf4767..d9eca2479 100644
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -390,13 +390,6 @@ namespace net_utils
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);
std::string req_command_str = m_query_info.m_full_request_str;
diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
index f2a580167..2a762b3ca 100644
--- a/contrib/epee/include/net/http_server_impl_base.h
+++ b/contrib/epee/include/net/http_server_impl_base.h
@@ -56,7 +56,7 @@ namespace epee
{}
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0",
- std::string user_agent = "", boost::optional<net_utils::http::login> user = boost::none)
+ boost::optional<net_utils::http::login> user = boost::none)
{
//set self as callback handler
@@ -65,8 +65,6 @@ namespace epee
//here set folder for hosting reqests
m_net_server.get_config_object().m_folder = "";
- // workaround till we get auth/encryption
- m_net_server.get_config_object().m_required_user_agent = std::move(user_agent);
m_net_server.get_config_object().m_user = std::move(user);
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h
index 36177c7e0..47981acb3 100644
--- a/contrib/epee/include/storages/http_abstract_invoke.h
+++ b/contrib/epee/include/storages/http_abstract_invoke.h
@@ -26,6 +26,9 @@
//
#pragma once
+#include <boost/utility/string_ref.hpp>
+#include <chrono>
+#include <string>
#include "portable_storage_template_helper.h"
#include "net/http_base.h"
#include "net/http_server_handlers_map2.h"
@@ -35,7 +38,7 @@ namespace epee
namespace net_utils
{
template<class t_request, class t_response, class t_transport>
- bool invoke_http_json(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
+ bool invoke_http_json(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref method = "GET")
{
std::string req_param;
if(!serialization::store_t_to_json(out_struct, req_param))
@@ -66,7 +69,7 @@ namespace epee
template<class t_request, class t_response, class t_transport>
- bool invoke_http_bin(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
+ bool invoke_http_bin(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref method = "GET")
{
std::string req_param;
if(!serialization::store_t_to_binary(out_struct, req_param))
@@ -95,7 +98,7 @@ namespace epee
}
template<class t_request, class t_response, class t_transport>
- bool invoke_http_json_rpc(const std::string& uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
+ bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
{
epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t);
req_t.jsonrpc = "2.0";
@@ -117,7 +120,7 @@ namespace epee
}
template<class t_command, class t_transport>
- bool invoke_http_json_rpc(const std::string& uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
+ bool invoke_http_json_rpc(const boost::string_ref uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
{
return invoke_http_json_rpc(uri, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id);
}
diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp
index 7fd32dabc..4d2523e1f 100644
--- a/contrib/epee/src/http_auth.cpp
+++ b/contrib/epee/src/http_auth.cpp
@@ -362,7 +362,7 @@ namespace
server_parameters best{};
- const std::list<field>& fields = response.m_additional_fields;
+ const std::list<field>& fields = response.m_header_info.m_etc_fields;
auto current = fields.begin();
const auto end = fields.end();
while (true)