Added allowed user pubkey list for hpsh

This commit is contained in:
chalith
2023-11-01 18:27:05 +05:30
parent c4c304a106
commit 0f0df53913
14 changed files with 117 additions and 27 deletions

View File

@@ -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);
})
});
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -4,6 +4,7 @@
#include "../pchheader.hpp"
#include "../conf.hpp"
#include "../usr/usr.hpp"
#include "../msg/usrmsg_common.hpp"
namespace hpsh
{

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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 += "}";
}

View File

@@ -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);

View File

@@ -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";

View File

@@ -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

View File

@@ -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;

View File

@@ -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.
*/

View File

@@ -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);