mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Added allowed user pubkey list for hpsh
This commit is contained in:
@@ -126,7 +126,10 @@ async function main() {
|
||||
else if (inp.startsWith("hpsh ")) {
|
||||
hpc.submitHpshRequest(inp.substr(5)).then(id => {
|
||||
hpc.on(id, (reply) => {
|
||||
console.log(reply);
|
||||
if (reply.data)
|
||||
console.log(reply.data);
|
||||
else
|
||||
console.error(reply.error);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
20
src/conf.cpp
20
src/conf.cpp
@@ -528,6 +528,20 @@ namespace conf
|
||||
std::cerr << "Invalid format for hpsh run as config (\"uid>0:gid>0\" expected).\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
jpath = "hpsh.users";
|
||||
cfg.hpsh.users.clear();
|
||||
for (auto &userpk : hpsh["users"].array_range())
|
||||
{
|
||||
// Convert the public key hex of each node to binary and store it.
|
||||
const std::string bin_pubkey = util::to_bin(userpk.as<std::string_view>());
|
||||
if (bin_pubkey.empty())
|
||||
{
|
||||
std::cerr << "Error decoding user pubkey list.\n";
|
||||
return -1;
|
||||
}
|
||||
cfg.hpsh.users.emplace(bin_pubkey);
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -653,6 +667,12 @@ namespace conf
|
||||
jsoncons::ojson hpsh_config;
|
||||
hpsh_config.insert_or_assign("enabled", cfg.hpsh.enabled);
|
||||
hpsh_config.insert_or_assign("run_as", cfg.hpsh.run_as.to_string());
|
||||
jsoncons::ojson users(jsoncons::json_array_arg);
|
||||
for (const auto &userpk : cfg.hpsh.users)
|
||||
{
|
||||
users.push_back(util::to_hex(userpk));
|
||||
}
|
||||
hpsh_config.insert_or_assign("users", users);
|
||||
d.insert_or_assign("hpsh", hpsh_config);
|
||||
}
|
||||
|
||||
|
||||
@@ -210,8 +210,9 @@ namespace conf
|
||||
|
||||
struct hpsh_config
|
||||
{
|
||||
bool enabled = false; // Whether or not to enable hpsh.
|
||||
ugid run_as; // The user/groups id to execute the hpsh as.
|
||||
bool enabled = false; // Whether or not to enable hpsh.
|
||||
ugid run_as; // The user/groups id to execute the hpsh as.
|
||||
std::set<std::string> users; // List of users who are allowed to perform hpsh (list of binary public keys).
|
||||
};
|
||||
|
||||
struct user_config
|
||||
@@ -327,11 +328,11 @@ namespace conf
|
||||
};
|
||||
|
||||
// Global contract context struct exposed to the application.
|
||||
// Other modeuls will access context values via this.
|
||||
// Other modules will access context values via this.
|
||||
extern contract_ctx ctx;
|
||||
|
||||
// Global configuration struct exposed to the application.
|
||||
// Other modeuls will access config values via this.
|
||||
// Other modules will access config values via this.
|
||||
extern hp_config cfg;
|
||||
|
||||
int init();
|
||||
|
||||
@@ -174,6 +174,12 @@ namespace hpsh
|
||||
if (ctx.is_shutting_down)
|
||||
return -1;
|
||||
|
||||
if (conf::cfg.hpsh.users.find(std::string(user_pubkey)) == conf::cfg.hpsh.users.end())
|
||||
{
|
||||
LOG_ERROR << "This user is not allowed to perform hpsh operations.";
|
||||
return -2;
|
||||
}
|
||||
|
||||
// Send the hpsh request header.
|
||||
if (write(ctx.control_fds[1], HPSH_CTR_SH, 3) < 0)
|
||||
{
|
||||
@@ -248,6 +254,7 @@ namespace hpsh
|
||||
|
||||
while (!ctx.is_shutting_down)
|
||||
{
|
||||
// Iterate through received commands and check for outputs.
|
||||
if (ctx.commands.size() > 0)
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(ctx.command_mutex);
|
||||
@@ -290,9 +297,7 @@ namespace hpsh
|
||||
{
|
||||
const usr::connected_user &user = user_itr->second;
|
||||
msg::usrmsg::usrmsg_parser parser(user.protocol);
|
||||
std::vector<uint8_t> msg;
|
||||
parser.create_hpsh_response_container(msg, itr->id, response);
|
||||
user.session.send(msg);
|
||||
usr::send_hpsh_response(std::move(parser), user.session, itr->id, msg::usrmsg::STATUS_ACCEPTED, response);
|
||||
response.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../pchheader.hpp"
|
||||
#include "../conf.hpp"
|
||||
#include "../usr/usr.hpp"
|
||||
#include "../msg/usrmsg_common.hpp"
|
||||
|
||||
namespace hpsh
|
||||
{
|
||||
|
||||
@@ -168,11 +168,13 @@ namespace msg::usrmsg::bson
|
||||
* {
|
||||
* "type": "hpsh_response",
|
||||
* "reply_for": "<corresponding request id>",
|
||||
* "content": <contract output>
|
||||
* "status": "<accepted|rejected>",
|
||||
* "content": "<response>"
|
||||
* "reason": "<reason>",
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content)
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason)
|
||||
{
|
||||
jsoncons::bson::bson_bytes_encoder encoder(msg);
|
||||
encoder.begin_object();
|
||||
@@ -180,8 +182,18 @@ namespace msg::usrmsg::bson
|
||||
encoder.string_value(msg::usrmsg::MSGTYPE_HPSH_RESPONSE);
|
||||
encoder.key(msg::usrmsg::FLD_REPLY_FOR);
|
||||
encoder.string_value(reply_for);
|
||||
encoder.key(msg::usrmsg::FLD_STATUS);
|
||||
encoder.string_value(status);
|
||||
encoder.key(msg::usrmsg::FLD_CONTENT);
|
||||
encoder.byte_string_value(content);
|
||||
|
||||
// Reject reason is only included for rejected inputs.
|
||||
if (!reason.empty())
|
||||
{
|
||||
encoder.key(msg::usrmsg::FLD_REASON);
|
||||
encoder.string_value(reason);
|
||||
}
|
||||
|
||||
encoder.end_object();
|
||||
encoder.flush();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace msg::usrmsg::bson
|
||||
void create_contract_input_status(std::vector<uint8_t> &msg, std::string_view status, std::string_view reason,
|
||||
std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash);
|
||||
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content);
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason);
|
||||
|
||||
void create_contract_read_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content);
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ namespace msg::usrmsg::json
|
||||
* {
|
||||
* "type": "contract_input_status",
|
||||
* "status": "<accepted|rejected>",
|
||||
* "reason": "<reson>",
|
||||
* "reason": "<reason>",
|
||||
* "input_hash": "<hex hash of original input signature>",
|
||||
* "ledger_seq_no": <sequence no of the ledger that the input got included in>,
|
||||
* "ledger_hash": "<hex hash no of the ledger that the input got included in>"
|
||||
@@ -332,11 +332,13 @@ namespace msg::usrmsg::json
|
||||
* {
|
||||
* "type": "hpsh_response",
|
||||
* "reply_for": "<corresponding request id>",
|
||||
* "content": "<response string>"
|
||||
* "status": "<accepted|rejected>",
|
||||
* "content": "<response>"
|
||||
* "reason": "<reason>",
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content)
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason)
|
||||
{
|
||||
msg.reserve(content.size() + 256);
|
||||
msg += "{\"";
|
||||
@@ -348,6 +350,10 @@ namespace msg::usrmsg::json
|
||||
msg += SEP_COLON;
|
||||
msg += reply_for;
|
||||
msg += SEP_COMMA;
|
||||
msg += msg::usrmsg::FLD_STATUS;
|
||||
msg += SEP_COLON;
|
||||
msg += status;
|
||||
msg += SEP_COMMA;
|
||||
msg += msg::usrmsg::FLD_CONTENT;
|
||||
msg += SEP_COLON_NOQUOTE;
|
||||
|
||||
@@ -368,6 +374,16 @@ namespace msg::usrmsg::json
|
||||
msg += content;
|
||||
}
|
||||
|
||||
// Reject reason is only included for rejected inputs.
|
||||
if (!reason.empty())
|
||||
{
|
||||
msg += SEP_COMMA_NOQUOTE;
|
||||
msg += msg::usrmsg::FLD_REASON;
|
||||
msg += SEP_COLON;
|
||||
msg += reason;
|
||||
msg += DOUBLE_QUOTE;
|
||||
}
|
||||
|
||||
msg += "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace msg::usrmsg::json
|
||||
void create_contract_input_status(std::vector<uint8_t> &msg, std::string_view status, std::string_view reason,
|
||||
std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash);
|
||||
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content);
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason);
|
||||
|
||||
void create_contract_read_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content);
|
||||
|
||||
|
||||
@@ -108,6 +108,9 @@ namespace msg::usrmsg
|
||||
constexpr const char *REASON_NONCE_EXPIRED = "nonce_expired";
|
||||
constexpr const char *REASON_ALREADY_SUBMITTED = "already_submitted";
|
||||
constexpr const char *REASON_ROUND_INPUTS_OVERFLOW = "round_inputs_overflow";
|
||||
constexpr const char *REASON_USER_NOT_ALLOWED = "user_not_allowed";
|
||||
constexpr const char *REASON_NOT_INITIALIZED = "not_initialized";
|
||||
constexpr const char *REASON_INTERNAL_ERROR = "internal_error";
|
||||
constexpr const char *QUERY_FILTER_BY_SEQ_NO = "seq_no";
|
||||
constexpr const char *STR_TRUE = "true";
|
||||
constexpr const char *STR_FALSE = "false";
|
||||
|
||||
@@ -38,12 +38,12 @@ namespace msg::usrmsg
|
||||
busrmsg::create_contract_input_status(msg, status, reason, input_hash, ledger_seq_no, ledger_hash);
|
||||
}
|
||||
|
||||
void usrmsg_parser::create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content) const
|
||||
void usrmsg_parser::create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const
|
||||
{
|
||||
if (protocol == util::PROTOCOL::JSON)
|
||||
jusrmsg::create_hpsh_response_container(msg, reply_for, content);
|
||||
jusrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason);
|
||||
else
|
||||
busrmsg::create_hpsh_response_container(msg, reply_for, content);
|
||||
busrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason);
|
||||
}
|
||||
|
||||
void usrmsg_parser::create_contract_read_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content) const
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace msg::usrmsg
|
||||
void create_contract_input_status(std::vector<uint8_t> &msg, std::string_view status, std::string_view reason,
|
||||
std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash) const;
|
||||
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content) const;
|
||||
void create_hpsh_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const;
|
||||
|
||||
void create_contract_read_response_container(std::vector<uint8_t> &msg, std::string_view reply_for, std::string_view content) const;
|
||||
|
||||
|
||||
@@ -276,18 +276,33 @@ namespace usr
|
||||
else if (msg_type == msg::usrmsg::MSGTYPE_HPSH_REQUEST)
|
||||
{
|
||||
std::string id, content;
|
||||
if (hpsh::ctx.is_initialized && parser.extract_hpsh_request(id, content) != -1)
|
||||
{
|
||||
if (hpsh::execute(id, user.pubkey, content) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if (parser.extract_hpsh_request(id, content) == -1)
|
||||
{
|
||||
send_input_status(parser, user.session, msg::usrmsg::STATUS_REJECTED, msg::usrmsg::REASON_BAD_MSG_FORMAT, "");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If hpsh is initialized, send status reject.
|
||||
if (!hpsh::ctx.is_initialized)
|
||||
{
|
||||
send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_NOT_INITIALIZED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int res = hpsh::execute(id, user.pubkey, content);
|
||||
// Send user npt allowed status if not allowed.
|
||||
if (res == -1)
|
||||
{
|
||||
send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
else if (res == -2)
|
||||
{
|
||||
send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_USER_NOT_ALLOWED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,6 +365,17 @@ namespace usr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the specified hpsh request status result via the provided session.
|
||||
*/
|
||||
void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for,
|
||||
std::string_view status, std::string_view content, std::string_view reason)
|
||||
{
|
||||
std::vector<uint8_t> msg;
|
||||
parser.create_hpsh_response_container(msg, reply_for, status, content, reason);
|
||||
session.send(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the specified contract input status result via the provided session.
|
||||
*/
|
||||
|
||||
@@ -95,6 +95,9 @@ namespace usr
|
||||
void send_input_status_responses(const std::unordered_map<std::string, std::vector<input_status_response>> &responses,
|
||||
const uint64_t ledger_seq_no = 0, const util::h32 &ledger_hash = util::h32_empty);
|
||||
|
||||
void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for,
|
||||
std::string_view status, std::string_view content, std::string_view reason = "");
|
||||
|
||||
void send_input_status(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session,
|
||||
std::string_view status, std::string_view reason, std::string_view input_hash,
|
||||
const uint64_t ledger_seq_no = 0, const util::h32 &ledger_hash = util::h32_empty);
|
||||
|
||||
Reference in New Issue
Block a user