diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 8 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 1 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 34 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 7 | ||||
-rw-r--r-- | src/wallet/wallet2_api.h | 3 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 98 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.h | 3 |
7 files changed, 136 insertions, 18 deletions
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 5a6f02b01..4ee5ab8df 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -352,6 +352,14 @@ double WalletManagerImpl::miningHashRate() const return mres.speed; } +std::string WalletManagerImpl::resolveOpenAlias(const std::string &address, bool &dnssec_valid) const +{ + std::vector<std::string> addresses = tools::wallet2::addresses_from_url(address, dnssec_valid); + if (addresses.empty()) + return ""; + return addresses.front(); +} + ///////////////////// WalletManagerFactory implementation ////////////////////// WalletManager *WalletManagerFactory::getWalletManager() diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index fe9662534..214afc3fa 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -52,6 +52,7 @@ public: uint64_t blockchainTargetHeight() const; uint64_t networkDifficulty() const; double miningHashRate() const; + std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const; private: WalletManagerImpl() {} diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index db4fae557..e58c31156 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -30,8 +30,6 @@ #include <random> #include <tuple> -#include <boost/archive/binary_oarchive.hpp> -#include <boost/archive/binary_iarchive.hpp> #include <boost/format.hpp> #include <boost/optional/optional.hpp> #include <boost/utility/value_init.hpp> @@ -2313,16 +2311,38 @@ void wallet2::load(const std::string& wallet_, const std::string& password) std::stringstream iss; iss << cache_data; - boost::archive::binary_iarchive ar(iss); - ar >> *this; + try { + boost::archive::portable_binary_iarchive ar(iss); + ar >> *this; + } + catch (...) + { + LOG_PRINT_L0("Failed to open portable binary, trying unportable"); + boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists); + iss.str(""); + iss << cache_data; + boost::archive::binary_iarchive ar(iss); + ar >> *this; + } } catch (...) { LOG_PRINT_L1("Failed to load encrypted cache, trying unencrypted"); std::stringstream iss; iss << buf; - boost::archive::binary_iarchive ar(iss); - ar >> *this; + try { + boost::archive::portable_binary_iarchive ar(iss); + ar >> *this; + } + catch (...) + { + LOG_PRINT_L0("Failed to open portable binary, trying unportable"); + boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists); + iss.str(""); + iss << buf; + boost::archive::binary_iarchive ar(iss); + ar >> *this; + } } THROW_WALLET_EXCEPTION_IF( m_account_public_address.m_spend_public_key != m_account.get_keys().m_account_address.m_spend_public_key || @@ -2396,7 +2416,7 @@ void wallet2::store_to(const std::string &path, const std::string &password) } // preparing wallet data std::stringstream oss; - boost::archive::binary_oarchive ar(oss); + boost::archive::portable_binary_oarchive ar(oss); ar << *this; wallet2::cache_file_data cache_file_data = boost::value_initialized<wallet2::cache_file_data>(); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c3381730b..9f4180c0d 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -31,7 +31,6 @@ #pragma once #include <memory> -#include <boost/archive/binary_iarchive.hpp> #include <boost/program_options/options_description.hpp> #include <boost/program_options/variables_map.hpp> @@ -676,11 +675,11 @@ namespace boost namespace serialization { template <class Archive> - inline void initialize_transfer_details(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) + inline typename std::enable_if<!Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) { } - template<> - inline void initialize_transfer_details(boost::archive::binary_iarchive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) + template <class Archive> + inline typename std::enable_if<Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, tools::wallet2::transfer_details &x, const boost::serialization::version_type ver) { if (ver < 1) { diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 6651b876d..2e1d95b58 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -561,6 +561,9 @@ struct WalletManager //! returns current mining hash rate (0 if not mining) virtual double miningHashRate() const = 0; + + //! resolves an OpenAlias address to a monero address + virtual std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const = 0; }; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 7c08bbe4b..c34ce4cf2 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -28,6 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include <boost/asio/ip/address.hpp> +#include <boost/filesystem/operations.hpp> #include <cstdint> #include "include_base_utils.h" using namespace epee; @@ -36,10 +37,12 @@ using namespace epee; #include "wallet/wallet_args.h" #include "common/command_line.h" #include "common/i18n.h" +#include "common/util.h" #include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/account.h" #include "wallet_rpc_server_commands_defs.h" #include "misc_language.h" +#include "string_coding.h" #include "string_tools.h" #include "crypto/hash.h" @@ -47,9 +50,11 @@ namespace { const command_line::arg_descriptor<std::string, true> arg_rpc_bind_port = {"rpc-bind-port", "Sets bind port for server"}; const command_line::arg_descriptor<std::string> arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"}; - const command_line::arg_descriptor<std::string> arg_user_agent = {"user-agent", "Restrict RPC to clients using this user agent", ""}; - + const command_line::arg_descriptor<std::string> arg_rpc_login = {"rpc-login", "Specify username[:password] required for RPC connection"}; + const command_line::arg_descriptor<bool> arg_disable_rpc_login = {"disable-rpc-login", "Disable HTTP authentication for RPC"}; const command_line::arg_descriptor<bool> arg_confirm_external_bind = {"confirm-external-bind", "Confirm rcp-bind-ip value is NOT a loopback (local) IP"}; + + constexpr const char default_rpc_username[] = "monero"; } namespace tools @@ -60,9 +65,19 @@ namespace tools } //------------------------------------------------------------------------------------------------------------------------------ - wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w) + wallet_rpc_server::wallet_rpc_server(wallet2& w):m_wallet(w), rpc_login_filename(), m_stop(false) {} //------------------------------------------------------------------------------------------------------------------------------ + wallet_rpc_server::~wallet_rpc_server() + { + try + { + boost::system::error_code ec{}; + boost::filesystem::remove(rpc_login_filename, ec); + } + catch (...) {} + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::run() { m_stop = false; @@ -110,11 +125,79 @@ namespace tools } } + epee::net_utils::http::http_auth::login login{}; + + const bool disable_auth = command_line::get_arg(vm, arg_disable_rpc_login); + const std::string user_pass = command_line::get_arg(vm, arg_rpc_login); + const std::string bind_port = command_line::get_arg(vm, arg_rpc_bind_port); + + if (disable_auth) + { + if (!user_pass.empty()) + { + LOG_ERROR(tr("Cannot specify --") << arg_disable_rpc_login.name << tr(" and --") << arg_rpc_login.name); + return false; + } + } + else // auth enabled + { + if (user_pass.empty()) + { + login.username = default_rpc_username; + + std::array<std::uint8_t, 16> rand_128bit{{}}; + crypto::rand(rand_128bit.size(), rand_128bit.data()); + login.password = string_encoding::base64_encode(rand_128bit.data(), rand_128bit.size()); + } + else // user password + { + const auto loc = user_pass.find(':'); + login.username = user_pass.substr(0, loc); + if (loc != std::string::npos) + { + login.password = user_pass.substr(loc + 1); + } + else + { + tools::password_container pwd(true); + pwd.read_password("RPC password"); + login.password = pwd.password(); + } + + if (login.username.empty() || login.password.empty()) + { + LOG_ERROR(tr("Blank username or password not permitted for RPC authenticaion")); + return false; + } + } + + assert(!login.username.empty()); + assert(!login.password.empty()); + + std::string temp = "monero-wallet-rpc." + bind_port + ".login"; + const auto cookie = tools::create_private_file(temp); + if (!cookie) + { + LOG_ERROR(tr("Failed to create file ") << temp << tr(". Check permissions or remove file")); + return false; + } + rpc_login_filename.swap(temp); // nothrow guarantee destructor cleanup + temp = rpc_login_filename; + std::fputs(login.username.c_str(), cookie.get()); + std::fputc(':', cookie.get()); + std::fputs(login.password.c_str(), cookie.get()); + std::fflush(cookie.get()); + if (std::ferror(cookie.get())) + { + LOG_ERROR(tr("Error writing to file ") << temp); + return false; + } + LOG_PRINT_L0(tr("RPC username/password is stored in file ") << temp); + } // end auth enabled + m_net_server.set_threads_prefix("RPC"); return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( - command_line::get_arg(vm, arg_rpc_bind_port), - std::move(bind_ip), - command_line::get_arg(vm, arg_user_agent) + std::move(bind_port), std::move(bind_ip), std::string{}, boost::make_optional(!disable_auth, std::move(login)) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -1132,7 +1215,8 @@ int main(int argc, char** argv) { tools::wallet2::init_options(desc_params); command_line::add_arg(desc_params, arg_rpc_bind_ip); command_line::add_arg(desc_params, arg_rpc_bind_port); - command_line::add_arg(desc_params, arg_user_agent); + command_line::add_arg(desc_params, arg_rpc_login); + command_line::add_arg(desc_params, arg_disable_rpc_login); command_line::add_arg(desc_params, arg_confirm_external_bind); command_line::add_arg(desc_params, arg_wallet_file); command_line::add_arg(desc_params, arg_from_json); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 96ca1af04..8701d38cd 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -32,6 +32,7 @@ #include <boost/program_options/options_description.hpp> #include <boost/program_options/variables_map.hpp> +#include <string> #include "net/http_server_impl_base.h" #include "wallet_rpc_server_commands_defs.h" #include "wallet2.h" @@ -48,6 +49,7 @@ namespace tools static const char* tr(const char* str); wallet_rpc_server(wallet2& cr); + ~wallet_rpc_server(); bool init(const boost::program_options::variables_map& vm); bool run(); @@ -118,6 +120,7 @@ namespace tools bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er); wallet2& m_wallet; + std::string rpc_login_filename; std::atomic<bool> m_stop; }; } |