From 22b49d93a8b9a807925643fc4a9c5aaf82d2fe90 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 28 Jun 2025 16:02:19 +0400 Subject: [PATCH 1/8] Update LICENSE (fixed #534) Thanks to @Alrighttt to pointing that out --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index fdb74465..171d1de5 100644 --- a/LICENSE +++ b/LICENSE @@ -4,6 +4,6 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ZANO PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Except as contained in this notice, the name of Zano project shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Zano project. \ No newline at end of file +Except as contained in this notice, the name of Zano project shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Zano project. From e232c827a6d885f5a62e47e6a0becf31aa8bb50c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 4 Jul 2025 19:42:08 +0400 Subject: [PATCH 2/8] example of using zano wallet jwt auth --- utils/JS/JWT/example.js | 83 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 utils/JS/JWT/example.js diff --git a/utils/JS/JWT/example.js b/utils/JS/JWT/example.js new file mode 100644 index 00000000..99373359 --- /dev/null +++ b/utils/JS/JWT/example.js @@ -0,0 +1,83 @@ +const axios = require('axios'); +const forge = require('node-forge'); + +// Your shared JWT secret (must match what the server expects) +const JWT_SECRET = 'hiwejkcddkndspo230XASIijksk123i9x5'; + + +const apiCredentials = {token: JWT_SECRET}; + +function createJWSToken(payload, secrete_str) { + const header = { alg: 'HS256', typ: 'JWT' }; + const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64').replace(/=/g, ''); + const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace(/=/g, ''); + + const signature = forge.hmac.create(); + signature.start('sha256', secrete_str); + signature.update(`${encodedHeader}.${encodedPayload}`); + const encodedSignature = forge.util.encode64(signature.digest().getBytes()).replace(/=/g, ''); + + return `${encodedHeader}.${encodedPayload}.${encodedSignature}`; + } + + function generateRandomString(length) { + const bytes = forge.random.getBytesSync(Math.ceil(length / 2)); + const hexString = forge.util.bytesToHex(bytes); + return hexString.substring(0, length); + } + + function generateAccessToken(httpBody) { + + if (!apiCredentials?.token) { + throw new Error("No API credentials found, extension is not connected"); + } + + + const md = forge.md.sha256.create(); + md.update(httpBody); + const bodyHash = md.digest().toHex(); + + // Example payload + const payload = { + body_hash: bodyHash, + user: 'zano_extension', + salt: generateRandomString(64), + exp: Math.floor(Date.now() / 1000) + (60), // Expires in 1 minute + }; + + return createJWSToken(payload, apiCredentials?.token); + } + + +// JSON-RPC 2.0 request body +const requestData = { + jsonrpc: '2.0', + id: 0, + method: 'getbalance', + params: {}, +}; + + +const http_body = JSON.stringify(requestData); + +// Create JWT token +const token = generateAccessToken(http_body); + + +// Send POST request +axios.post('http://127.0.0.1:11111/json_rpc', requestData, { + headers: { + 'Content-Type': 'application/json', + 'Zano-Access-Token': `${token}`, + }, +}) +.then(response => { + console.log('Response:', response.data); +}) +.catch(error => { + if (error.response) { + console.error('Error Response:', error.response.status, error.response.data); + } else { + console.error('Request Error:', error.message); + } +}); From 9fe3f812aa9704cdc0a93798345a86daa7b00e41 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 15 Jul 2025 20:41:46 +0400 Subject: [PATCH 3/8] limitations for rpc cals --- src/common/error_codes.h | 1 + src/rpc/core_rpc_server.cpp | 55 +++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/common/error_codes.h b/src/common/error_codes.h index 910e1e42..3a629d5e 100644 --- a/src/common/error_codes.h +++ b/src/common/error_codes.h @@ -46,3 +46,4 @@ #define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED" #define API_RETURN_CODE_WRAP "WRAP" #define API_RETURN_CODE_MISSING_ZC_INPUTS "MISSING_ZC_INPUTS" +#define API_RETURN_CODE_ARG_OUT_OF_LIMITS "ARG_OUT_OF_LIMITS" diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a498ec18..f4c159ba 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -16,6 +16,23 @@ using namespace epee; #include "crypto/hash.h" #include "core_rpc_server_error_codes.h" +#define CHECK_RPC_LIMITS(var, limit) if(var > limit) {res.status = API_RETURN_CODE_ARG_OUT_OF_LIMITS; return true;} + + +#define RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DIRECT_BLOCK_IDS 4000 +#define RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS 500 +#define RPC_LIMIT_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_TXIDS 100 +#define RPC_LIMIT_COMMAND_RPC_CHECK_KEYIMAGES_IMAGES 1000 +#define RPC_LIMIT_COMMAND_RPC_GET_TRANSACTIONS_TXS_HASHES 5000 +#define RPC_LIMIT_COMMAND_RPC_GET_OFFERS_EX_LIMIT 1000 +#define RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DETAILS_COUNT 4000 +#define RPC_LIMIT_COMMAND_RPC_GET_POOL_TXS_DETAILS_IDS 4000 +#define RPC_LIMIT_COMMAND_RPC_GET_VOTES 4000 +#define RPC_LIMIT_COMMAND_RPC_GET_ASSETS_LIST 1000 +#define RPC_LIMIT_COMMAND_RPC_GET_ALT_BLOCKS_DETAILS_COUNT 100 +#define RPC_LIMIT_COMMAND_RPC_FORCE_RELAY_RAW_TXS 100 +#define RPC_LIMIT_COMMAND_RPC_GET_ALIASES_COUNT 200 + namespace currency @@ -281,6 +298,7 @@ namespace currency bool core_rpc_server::on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.block_ids.size(), RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DIRECT_BLOCK_IDS); if (req.block_ids.back() != m_core.get_blockchain_storage().get_block_id_by_height(0)) { @@ -319,6 +337,7 @@ namespace currency bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.block_ids.size(), RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DIRECT_BLOCK_IDS); LOG_PRINT_L2("[on_get_blocks]: Prevalidating...."); if (req.block_ids.back() != m_core.get_blockchain_storage().get_block_id_by_height(0)) { @@ -369,6 +388,8 @@ namespace currency bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + res.status = API_RETURN_CODE_FAIL; COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req_native = AUTO_VAL_INIT(req_native); @@ -420,6 +441,7 @@ namespace currency bool core_rpc_server::on_get_random_outs1(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); res.status = API_RETURN_CODE_FAIL; if(!m_core.get_random_outs_for_amounts(req, res)) @@ -434,6 +456,12 @@ namespace currency bool core_rpc_server::on_get_random_outs3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + for (const auto& item : req.amounts) + { + CHECK_RPC_LIMITS(item.global_offsets.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + } + res.status = API_RETURN_CODE_FAIL; if (!m_core.get_blockchain_storage().get_random_outs_for_amounts3(req, res)) { @@ -447,6 +475,8 @@ namespace currency bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.txids.size(), RPC_LIMIT_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_TXIDS); + res.tx_global_outs.resize(req.txids.size()); size_t i = 0; for (auto& txid : req.txids) @@ -498,6 +528,8 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_check_keyimages(const COMMAND_RPC_CHECK_KEYIMAGES::request& req, COMMAND_RPC_CHECK_KEYIMAGES::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.images.size(), RPC_LIMIT_COMMAND_RPC_CHECK_KEYIMAGES_IMAGES); + m_core.get_blockchain_storage().check_keyimages(req.images, res.images_stat); res.status = API_RETURN_CODE_OK; return true; @@ -506,6 +538,8 @@ namespace currency bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.txs_hashes.size(), RPC_LIMIT_COMMAND_RPC_GET_TRANSACTIONS_TXS_HASHES); + std::vector vh; for(const auto& tx_hex_str : req.txs_hashes) { @@ -548,6 +582,9 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_offers_ex(const COMMAND_RPC_GET_OFFERS_EX::request& req, COMMAND_RPC_GET_OFFERS_EX::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) { + CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.filter.limit, RPC_LIMIT_COMMAND_RPC_GET_OFFERS_EX_LIMIT); + m_of.get_offers_ex(req.filter, res.offers, res.total_offers, m_core.get_blockchain_storage().get_core_runtime_config().get_core_time()); res.status = API_RETURN_CODE_OK; return true; @@ -624,6 +661,8 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_rpc_get_blocks_details(const COMMAND_RPC_GET_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_BLOCKS_DETAILS::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.count, RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DETAILS_COUNT); + m_core.get_blockchain_storage().get_main_blocks_rpc_details(req.height_start, req.count, req.ignore_transactions, res.blocks); res.status = API_RETURN_CODE_OK; return true; @@ -683,6 +722,9 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_pool_txs_details(const COMMAND_RPC_GET_POOL_TXS_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_DETAILS::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.ids.size(), RPC_LIMIT_COMMAND_RPC_GET_POOL_TXS_DETAILS_IDS); + + if (!req.ids.size()) { m_core.get_tx_pool().get_all_transactions_details(res.txs); @@ -697,6 +739,7 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_pool_txs_brief_details(const COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.ids.size(), RPC_LIMIT_COMMAND_RPC_GET_POOL_TXS_DETAILS_IDS); if (!req.ids.size()) { m_core.get_tx_pool().get_all_transactions_brief_details(res.txs); @@ -730,6 +773,8 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_votes(const COMMAND_RPC_GET_VOTES::request& req, COMMAND_RPC_GET_VOTES::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.h_end - req.h_start, RPC_LIMIT_COMMAND_RPC_GET_VOTES); + if (!m_core.get_blockchain_storage().get_pos_votes(req.h_start, req.h_end, res.votes)) { res.status = API_RETURN_CODE_INTERNAL_ERROR; @@ -754,6 +799,8 @@ namespace currency bool core_rpc_server::on_get_assets_list(const COMMAND_RPC_GET_ASSETS_LIST::request& req, COMMAND_RPC_GET_ASSETS_LIST::response& res, connection_context& cntx) { CHECK_CORE_READY(); + CHECK_RPC_LIMITS(req.count, RPC_LIMIT_COMMAND_RPC_GET_ASSETS_LIST); + if (!m_core.get_blockchain_storage().get_assets(req.offset, req.count, res.assets)) { res.status = API_RETURN_CODE_NOT_FOUND; @@ -857,6 +904,8 @@ namespace currency //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_alt_blocks_details(const COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::response& res, connection_context& cntx) { + CHECK_RPC_LIMITS(req.count, RPC_LIMIT_COMMAND_RPC_GET_ALT_BLOCKS_DETAILS_COUNT); + m_core.get_blockchain_storage().get_alt_blocks_rpc_details(req.offset, req.count, res.blocks); res.status = API_RETURN_CODE_OK; return true; @@ -934,7 +983,8 @@ namespace currency } //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_force_relaey_raw_txs(const COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& req, COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& res, connection_context& cntx) - { + { + CHECK_RPC_LIMITS(req.txs_as_hex.size(), RPC_LIMIT_COMMAND_RPC_FORCE_RELAY_RAW_TXS); CHECK_CORE_READY(); NOTIFY_OR_INVOKE_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); @@ -1371,10 +1421,11 @@ namespace currency res.status = API_RETURN_CODE_OK; return true; } - //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_aliases(const COMMAND_RPC_GET_ALIASES::request& req, COMMAND_RPC_GET_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) { + CHECK_RPC_LIMITS(req.count, RPC_LIMIT_COMMAND_RPC_GET_ALIASES_COUNT); + if(!check_core_ready()) { error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; From 9cce2359312f6d91f2846091e7a1e346431fafc7 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 15 Jul 2025 20:55:20 +0400 Subject: [PATCH 4/8] renamed macro to proper name --- src/rpc/core_rpc_server.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index f4c159ba..ad06ff1e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -20,7 +20,7 @@ using namespace epee; #define RPC_LIMIT_COMMAND_RPC_GET_BLOCKS_DIRECT_BLOCK_IDS 4000 -#define RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS 500 +#define RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS 500 #define RPC_LIMIT_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_TXIDS 100 #define RPC_LIMIT_COMMAND_RPC_CHECK_KEYIMAGES_IMAGES 1000 #define RPC_LIMIT_COMMAND_RPC_GET_TRANSACTIONS_TXS_HASHES 5000 @@ -388,7 +388,7 @@ namespace currency bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::response& res, connection_context& cntx) { CHECK_CORE_READY(); - CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS); res.status = API_RETURN_CODE_FAIL; @@ -441,7 +441,7 @@ namespace currency bool core_rpc_server::on_get_random_outs1(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx) { CHECK_CORE_READY(); - CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS); res.status = API_RETURN_CODE_FAIL; if(!m_core.get_random_outs_for_amounts(req, res)) @@ -456,10 +456,10 @@ namespace currency bool core_rpc_server::on_get_random_outs3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res, connection_context& cntx) { CHECK_CORE_READY(); - CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + CHECK_RPC_LIMITS(req.amounts.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS); for (const auto& item : req.amounts) { - CHECK_RPC_LIMITS(item.global_offsets.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY_AMOUNTS); + CHECK_RPC_LIMITS(item.global_offsets.size(), RPC_LIMIT_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS); } res.status = API_RETURN_CODE_FAIL; From 992ea22294291663c3078c1d32c7ff25a551b80b Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 15 Jul 2025 21:37:50 +0400 Subject: [PATCH 5/8] added warning for binding to 0.0.0.0 --- src/rpc/core_rpc_server.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index ad06ff1e..bf6b6912 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -62,6 +62,13 @@ namespace currency bool core_rpc_server::handle_command_line(const boost::program_options::variables_map& vm) { m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip); + if (m_bind_ip == "0.0.0.0") + { + LOG_PRINT_COLOR("!!!!!!IMPORTANT!!!!!!: We strongly advise against binding the server to 0.0.0.0 and exposing it directly" << ENDL + << "to the public internet. The server is meant solely for internal functionality and lacks the security features" << ENDL + << "required for publicly facing services. If you need to offer a public API, always place it behind secure" << ENDL + << "proxies that are properly configured with security measures—such as rate - limiting—to protect the service.", LOG_LEVEL_0, LOG_COLOR_RED); + } m_port = command_line::get_arg(vm, arg_rpc_bind_port); if (command_line::has_arg(vm, arg_rpc_ignore_offline_status)) { From 695bd88c11879d207753195c2aa829466b114d6c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Tue, 15 Jul 2025 14:30:55 +0400 Subject: [PATCH 6/8] made some of the api optional --- .../include/net/http_server_handlers_map2.h | 20 +++++++++++++++++++ src/rpc/core_rpc_server.cpp | 8 ++++++++ src/rpc/core_rpc_server.h | 8 +++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 05e0b691..5e73df90 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -507,6 +507,26 @@ namespace epee { return true;\ } +#define MAP_JON_RPC_CONDITIONAL(method_name, callback_f, command_type, predicate) \ + else if(predicate && auto_doc(current_zone_json_uri, method_name, true, docs) && callback_name == method_name) \ +{ \ + call_found = true; \ + PREPARE_OBJECTS_FROM_JSON(command_type) \ + if(!callback_f(req.params, resp.result, m_conn_context)) \ + { \ + epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ + fail_resp.jsonrpc = "2.0"; \ + fail_resp.method = req.method; \ + fail_resp.id = req.id; \ + fail_resp.error.code = -32603; \ + fail_resp.error.message = "Internal error"; \ + epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ + return true; \ + } \ + FINALIZE_OBJECTS_TO_JSON(method_name) \ + return true;\ +} + #define MAP_JON_RPC_N(callback_f, command_type) MAP_JON_RPC(command_type::methodname(), callback_f, command_type) #define END_JSON_RPC_MAP() \ diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index bf6b6912..1fb4aacb 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -42,6 +42,7 @@ namespace currency const command_line::arg_descriptor arg_rpc_bind_ip ("rpc-bind-ip", "", "127.0.0.1"); const command_line::arg_descriptor arg_rpc_bind_port ("rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)); const command_line::arg_descriptor arg_rpc_ignore_offline_status ("rpc-ignore-offline", "Let rpc calls despite online/offline status"); + const command_line::arg_descriptor arg_rpc_enable_rpc_api ("rpc-enable-admin-api", "Enable API commands that can alter state of pool or daemon(reset pool, remove txs etc)"); } //----------------------------------------------------------------------------------- void core_rpc_server::init_options(boost::program_options::options_description& desc) @@ -49,6 +50,8 @@ namespace currency 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_ignore_offline_status); + command_line::add_arg(desc, arg_rpc_enable_rpc_api); + } //------------------------------------------------------------------------------------------------------------------------------ core_rpc_server::core_rpc_server(core& cr, nodetool::node_server >& p2p, @@ -74,6 +77,11 @@ namespace currency { m_ignore_offline_status = command_line::get_arg(vm, arg_rpc_ignore_offline_status); } + if (command_line::has_arg(vm, arg_rpc_enable_rpc_api)) + { + m_enabled_admin_api = command_line::get_arg(vm, arg_rpc_enable_rpc_api); + } + return true; } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index fa5313e3..3dc4049d 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -171,9 +171,10 @@ namespace currency MAP_JON_RPC_WE("get_alt_block_details", on_get_alt_block_details, COMMAND_RPC_GET_BLOCK_DETAILS) MAP_JON_RPC ("get_alt_blocks_details", on_get_alt_blocks_details, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS) // - MAP_JON_RPC ("reset_transaction_pool", on_reset_transaction_pool, COMMAND_RPC_RESET_TX_POOL) - MAP_JON_RPC ("remove_tx_from_pool", on_remove_tx_from_pool, COMMAND_RPC_REMOVE_TX_FROM_POOL) - MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) + MAP_JON_RPC_CONDITIONAL("reset_transaction_pool", on_reset_transaction_pool, COMMAND_RPC_RESET_TX_POOL, m_enabled_admin_api) + MAP_JON_RPC_CONDITIONAL("remove_tx_from_pool", on_remove_tx_from_pool, COMMAND_RPC_REMOVE_TX_FROM_POOL, m_enabled_admin_api) + + MAP_JON_RPC("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) // MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX) MAP_JON_RPC_WE("validate_signature", on_validate_signature, COMMAND_VALIDATE_SIGNATURE) @@ -200,6 +201,7 @@ namespace currency std::string m_port; std::string m_bind_ip; bool m_ignore_offline_status; + bool m_enabled_admin_api = false; epee::net_utils::http::i_chain_handler* m_prpc_chain_handler = nullptr; }; } From 573028c764ca4ef26f4e8b341dc3f6f694f48e76 Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 15 Jul 2025 20:57:20 +0300 Subject: [PATCH 7/8] minor improvements --- src/rpc/core_rpc_server.cpp | 10 +++++----- src/rpc/core_rpc_server_commands_defs.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1fb4aacb..121586e6 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -42,7 +42,7 @@ namespace currency const command_line::arg_descriptor arg_rpc_bind_ip ("rpc-bind-ip", "", "127.0.0.1"); const command_line::arg_descriptor arg_rpc_bind_port ("rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)); const command_line::arg_descriptor arg_rpc_ignore_offline_status ("rpc-ignore-offline", "Let rpc calls despite online/offline status"); - const command_line::arg_descriptor arg_rpc_enable_rpc_api ("rpc-enable-admin-api", "Enable API commands that can alter state of pool or daemon(reset pool, remove txs etc)"); + const command_line::arg_descriptor arg_rpc_enable_admin_api ("rpc-enable-admin-api", "Enable API commands that can alter pool or daemon state (reset pool, remove txs, etc.)"); } //----------------------------------------------------------------------------------- void core_rpc_server::init_options(boost::program_options::options_description& desc) @@ -50,7 +50,7 @@ namespace currency 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_ignore_offline_status); - command_line::add_arg(desc, arg_rpc_enable_rpc_api); + command_line::add_arg(desc, arg_rpc_enable_admin_api); } //------------------------------------------------------------------------------------------------------------------------------ @@ -70,16 +70,16 @@ namespace currency LOG_PRINT_COLOR("!!!!!!IMPORTANT!!!!!!: We strongly advise against binding the server to 0.0.0.0 and exposing it directly" << ENDL << "to the public internet. The server is meant solely for internal functionality and lacks the security features" << ENDL << "required for publicly facing services. If you need to offer a public API, always place it behind secure" << ENDL - << "proxies that are properly configured with security measures—such as rate - limiting—to protect the service.", LOG_LEVEL_0, LOG_COLOR_RED); + << "proxies that are properly configured with security measures--such as rate limiting--to protect the service.", LOG_LEVEL_0, LOG_COLOR_RED); } m_port = command_line::get_arg(vm, arg_rpc_bind_port); if (command_line::has_arg(vm, arg_rpc_ignore_offline_status)) { m_ignore_offline_status = command_line::get_arg(vm, arg_rpc_ignore_offline_status); } - if (command_line::has_arg(vm, arg_rpc_enable_rpc_api)) + if (command_line::has_arg(vm, arg_rpc_enable_admin_api)) { - m_enabled_admin_api = command_line::get_arg(vm, arg_rpc_enable_rpc_api); + m_enabled_admin_api = command_line::get_arg(vm, arg_rpc_enable_admin_api); } return true; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 72b2a298..2e571212 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1494,7 +1494,7 @@ namespace currency struct COMMAND_RPC_RESET_TX_POOL { - DOC_COMMAND("Clears transaction pool."); + DOC_COMMAND("Clears transaction pool. (Admin API, requires CLI option, disabled by default)"); struct request { @@ -1516,7 +1516,7 @@ namespace currency struct COMMAND_RPC_REMOVE_TX_FROM_POOL { - DOC_COMMAND("Removes specified transactions from the transaction pool, typically to clear out transactions that are no longer valid or needed."); + DOC_COMMAND("Removes specified transactions from the transaction pool, typically to clear out transactions that are no longer valid or needed. (Admin API, requires CLI option, disabled by default)"); struct request { From eed7d9e3af1ec90ffca147129d8f42917084a5cf Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 15 Jul 2025 22:18:09 +0300 Subject: [PATCH 8/8] === build number: 411 -> 416 === --- src/version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h.in b/src/version.h.in index 69d040b4..d509b997 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -8,6 +8,6 @@ #define PROJECT_REVISION "7" #define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION -#define PROJECT_VERSION_BUILD_NO 411 +#define PROJECT_VERSION_BUILD_NO 416 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"