Electroneum
Loading...
Searching...
No Matches
rpc_args.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30#include "rpc_args.h"
31
32#include <boost/algorithm/string.hpp>
33#include <boost/asio/ip/address.hpp>
34#include <functional>
35#include "common/command_line.h"
36#include "common/i18n.h"
37#include "hex.h"
38
39namespace cryptonote
40{
41 namespace
42 {
43 boost::optional<epee::net_utils::ssl_options_t> do_process_ssl(const boost::program_options::variables_map& vm, const rpc_args::descriptors& arg, const bool any_cert_option)
44 {
45 bool ssl_required = false;
46 epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled;
47 if (any_cert_option && command_line::get_arg(vm, arg.rpc_ssl_allow_any_cert))
49 else
50 {
51 std::string ssl_ca_file = command_line::get_arg(vm, arg.rpc_ssl_ca_certificates);
52 const std::vector<std::string> ssl_allowed_fingerprints = command_line::get_arg(vm, arg.rpc_ssl_allowed_fingerprints);
53
54 std::vector<std::vector<uint8_t>> allowed_fingerprints{ ssl_allowed_fingerprints.size() };
55 std::transform(ssl_allowed_fingerprints.begin(), ssl_allowed_fingerprints.end(), allowed_fingerprints.begin(), epee::from_hex::vector);
56 for (const auto &fpr: allowed_fingerprints)
57 {
58 if (fpr.size() != SSL_FINGERPRINT_SIZE)
59 {
60 MERROR("SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long.");
61 return boost::none;
62 }
63 }
64
65 if (!allowed_fingerprints.empty() || !ssl_ca_file.empty())
66 {
67 ssl_required = true;
68 ssl_options = epee::net_utils::ssl_options_t{
69 std::move(allowed_fingerprints), std::move(ssl_ca_file)
70 };
71
72 if (command_line::get_arg(vm, arg.rpc_ssl_allow_chained))
74 }
75 }
76
77 // user specified CA file or fingeprints implies enabled SSL by default
78 if (!ssl_required && !epee::net_utils::ssl_support_from_string(ssl_options.support, command_line::get_arg(vm, arg.rpc_ssl)))
79 {
80 MERROR("Invalid argument for " << std::string(arg.rpc_ssl.name));
81 return boost::none;
82 }
83
84 ssl_options.auth = epee::net_utils::ssl_authentication_t{
85 command_line::get_arg(vm, arg.rpc_ssl_private_key), command_line::get_arg(vm, arg.rpc_ssl_certificate)
86 };
87
88 return {std::move(ssl_options)};
89 }
90 } // anonymous
91
93 : rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"})
94 , rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
95 , confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")})
96 , rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""})
97 , rpc_ssl({"rpc-ssl", rpc_args::tr("Enable SSL on RPC connections: enabled|disabled|autodetect"), "autodetect"})
98 , rpc_ssl_private_key({"rpc-ssl-private-key", rpc_args::tr("Path to a PEM format private key"), ""})
99 , rpc_ssl_certificate({"rpc-ssl-certificate", rpc_args::tr("Path to a PEM format certificate"), ""})
100 , rpc_ssl_ca_certificates({"rpc-ssl-ca-certificates", rpc_args::tr("Path to file containing concatenated PEM format certificate(s) to replace system CA(s)."), ""})
101 , rpc_ssl_allowed_fingerprints({"rpc-ssl-allowed-fingerprints", rpc_args::tr("List of certificate fingerprints to allow")})
102 , rpc_ssl_allow_chained({"rpc-ssl-allow-chained", rpc_args::tr("Allow user (via --rpc-ssl-certificates) chain certificates"), false})
103 , rpc_ssl_allow_any_cert({"rpc-ssl-allow-any-cert", rpc_args::tr("Allow any peer certificate"), false})
104 {}
105
106 const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); }
107
108 void rpc_args::init_options(boost::program_options::options_description& desc, const bool any_cert_option)
109 {
110 const descriptors arg{};
121 if (any_cert_option)
123 }
124
125 boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm, const bool any_cert_option)
126 {
127 const descriptors arg{};
129
130 config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip);
131 if (!config.bind_ip.empty())
132 {
133 // always parse IP here for error consistency
134 boost::system::error_code ec{};
135 const auto parsed_ip = boost::asio::ip::address::from_string(config.bind_ip, ec);
136 if (ec)
137 {
138 LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_bind_ip.name);
139 return boost::none;
140 }
141
142 if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg.confirm_external_bind))
143 {
144 LOG_ERROR(
145 "--" << arg.rpc_bind_ip.name <<
146 tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --") <<
147 arg.confirm_external_bind.name
148 );
149 return boost::none;
150 }
151 }
152
153 const char *env_rpc_login = nullptr;
154 const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login);
155 const bool use_rpc_env = !has_rpc_arg && (env_rpc_login = getenv("RPC_LOGIN")) != nullptr && strlen(env_rpc_login) > 0;
156 boost::optional<tools::login> login{};
157 if (has_rpc_arg || use_rpc_env)
158 {
160 has_rpc_arg ? command_line::get_arg(vm, arg.rpc_login) : std::string(env_rpc_login), true, [](bool verify) {
161 return tools::password_container::prompt(verify, "RPC server password");
162 });
163
164 if (!config.login)
165 return boost::none;
166
167 if (config.login->username.empty())
168 {
169 LOG_ERROR(tr("Username specified with --") << arg.rpc_login.name << tr(" cannot be empty"));
170 return boost::none;
171 }
172 }
173
174 auto access_control_origins_input = command_line::get_arg(vm, arg.rpc_access_control_origins);
175 if (!access_control_origins_input.empty())
176 {
177 if (!config.login)
178 {
179 LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RPC server password --") << arg.rpc_login.name << tr(" cannot be empty"));
180 return boost::none;
181 }
182
183 std::vector<std::string> access_control_origins;
184 boost::split(access_control_origins, access_control_origins_input, boost::is_any_of(","));
185 std::for_each(access_control_origins.begin(), access_control_origins.end(), std::bind(&boost::trim<std::string>, std::placeholders::_1, std::locale::classic()));
186 config.access_control_origins = std::move(access_control_origins);
187 }
188
189 auto ssl_options = do_process_ssl(vm, arg, any_cert_option);
190 if (!ssl_options)
191 return boost::none;
192 config.ssl_options = std::move(*ssl_options);
193
194 return {std::move(config)};
195 }
196
197 boost::optional<epee::net_utils::ssl_options_t> rpc_args::process_ssl(const boost::program_options::variables_map& vm, const bool any_cert_option)
198 {
199 const descriptors arg{};
200 return do_process_ssl(vm, arg, any_cert_option);
201 }
202}
ssl_verification_t verification
Definition net_ssl.h:82
ssl_authentication_t auth
Definition net_ssl.h:80
#define tr(x)
const char * i18n_translate(const char *s, const std::string &context)
Definition i18n.cpp:323
#define MERROR(x)
Definition misc_log_ex.h:73
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
std::enable_if<!std::is_same< T, bool >::value, bool >::type has_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
@ none
Do not verify peer.
Definition net_ssl.h:54
@ user_ca
Verify peer via specific (possibly chain) certificate(s) only.
Definition net_ssl.h:57
bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s)
Definition net_ssl.cpp:516
#define SSL_FINGERPRINT_SIZE
Definition net_ssl.h:40
const command_line::arg_descriptor< bool > rpc_ssl_allow_any_cert
Definition rpc_args.h:65
const command_line::arg_descriptor< std::string > rpc_ssl_private_key
Definition rpc_args.h:60
const command_line::arg_descriptor< bool > rpc_ssl_allow_chained
Definition rpc_args.h:64
const command_line::arg_descriptor< std::string > rpc_access_control_origins
Definition rpc_args.h:58
const command_line::arg_descriptor< std::string > rpc_ssl_certificate
Definition rpc_args.h:61
const command_line::arg_descriptor< std::string > rpc_login
Definition rpc_args.h:56
const command_line::arg_descriptor< std::string > rpc_ssl
Definition rpc_args.h:59
const command_line::arg_descriptor< std::string > rpc_ssl_ca_certificates
Definition rpc_args.h:62
const command_line::arg_descriptor< std::string > rpc_bind_ip
Definition rpc_args.h:55
const command_line::arg_descriptor< bool > confirm_external_bind
Definition rpc_args.h:57
const command_line::arg_descriptor< std::vector< std::string > > rpc_ssl_allowed_fingerprints
Definition rpc_args.h:63
Processes command line arguments related to server-side RPC.
Definition rpc_args.h:45
epee::net_utils::ssl_options_t ssl_options
Definition rpc_args.h:82
std::vector< std::string > access_control_origins
Definition rpc_args.h:80
static boost::optional< rpc_args > process(const boost::program_options::variables_map &vm, const bool any_cert_option=false)
Definition rpc_args.cpp:125
static const char * tr(const char *str)
Definition rpc_args.cpp:106
boost::optional< tools::login > login
Definition rpc_args.h:81
static boost::optional< epee::net_utils::ssl_options_t > process_ssl(const boost::program_options::variables_map &vm, const bool any_cert_option=false)
Definition rpc_args.cpp:197
static void init_options(boost::program_options::options_description &desc, const bool any_cert_option=false)
Definition rpc_args.cpp:108
static std::vector< uint8_t > vector(boost::string_ref src)
Definition hex.cpp:88
static boost::optional< login > parse(std::string &&userpass, bool verify, const std::function< boost::optional< password_container >(bool)> &prompt)
Definition password.cpp:268