mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Improved contract loading validation.
This commit is contained in:
72
src/conf.cpp
72
src/conf.cpp
@@ -97,22 +97,28 @@ int load_config()
|
||||
if (d.ParseStream(isw).HasParseError())
|
||||
{
|
||||
cerr << "Invalid config file format. Parser error at position " << d.GetErrorOffset() << endl;
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
else if (!is_schema_valid(d))
|
||||
{
|
||||
cerr << "Invalid config file format.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Check contract version.
|
||||
string cfgVersion = d["version"].GetString();
|
||||
if (cfgVersion.empty())
|
||||
{
|
||||
cerr << "Contract config version missing.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (version_compare(cfgVersion, _HP_MIN_CONTRACT_VERSION_) == -1)
|
||||
{
|
||||
cerr << "Contract version too old. Minimum "
|
||||
<< _HP_MIN_CONTRACT_VERSION_ << " required. "
|
||||
<< cfgVersion << " found.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg.pubkeyb64 = d["pubkeyb64"].GetString();
|
||||
@@ -135,7 +141,7 @@ int load_config()
|
||||
cfg.pubmaxsize = d["pubmaxsize"].GetInt();
|
||||
cfg.pubmaxcpm = d["pubmaxcpm"].GetInt();
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void save_config()
|
||||
@@ -191,19 +197,33 @@ void set_contract_dir_paths(string basedir)
|
||||
ctx.configFile = ctx.configDir + "/hp.cfg";
|
||||
ctx.histDir = basedir + "/hist";
|
||||
ctx.stateDir = basedir + "/state";
|
||||
ctx.binDir = basedir + "/bin";
|
||||
}
|
||||
|
||||
bool validate_contract_dir_paths()
|
||||
{
|
||||
string dirs[4] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir};
|
||||
|
||||
for (string dir : dirs)
|
||||
{
|
||||
if (!boost::filesystem::exists(dir))
|
||||
{
|
||||
cerr << dir << " does not exist.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int create_contract()
|
||||
{
|
||||
if (boost::filesystem::exists(ctx.contractDir))
|
||||
{
|
||||
cerr << "Contract dir already exists.\n";
|
||||
return 0;
|
||||
cerr << "Contract dir already exists. Cannot create contract at the same location.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
boost::filesystem::create_directories(ctx.configDir);
|
||||
boost::filesystem::create_directories(ctx.binDir);
|
||||
boost::filesystem::create_directories(ctx.histDir);
|
||||
boost::filesystem::create_directories(ctx.stateDir);
|
||||
|
||||
@@ -215,7 +235,13 @@ int create_contract()
|
||||
cfg.pubmaxsize = 65536;
|
||||
cfg.pubmaxcpm = 100;
|
||||
save_config();
|
||||
return 1;
|
||||
|
||||
cout << "Contract directory created at " << ctx.contractDir << endl;
|
||||
|
||||
if (load_config() != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clear_keys()
|
||||
@@ -223,26 +249,32 @@ int clear_keys()
|
||||
cfg.pubkeyb64 = "";
|
||||
cfg.seckeyb64 = "";
|
||||
save_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init(int argc, char **argv)
|
||||
bool validate_config()
|
||||
{
|
||||
if (ctx.command == "new")
|
||||
if (cfg.pubkeyb64.empty() || cfg.seckeyb64.empty() || cfg.binary.empty() || cfg.listenip.empty() ||
|
||||
cfg.peerport == 0 || cfg.roundtime == 0 || cfg.pubport == 0 || cfg.pubmaxsize == 0 || cfg.pubmaxcpm == 0)
|
||||
{
|
||||
if (!create_contract())
|
||||
return 0;
|
||||
cerr << "Required configuration fields missing.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!load_config())
|
||||
return 0;
|
||||
|
||||
if (ctx.command == "rekey")
|
||||
if (!boost::filesystem::exists(cfg.binary))
|
||||
{
|
||||
//Clear the keys. crpyto::init will automatically init the keys.
|
||||
clear_keys();
|
||||
cerr << "Contract binary does not exist: " << cfg.binary << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int init()
|
||||
{
|
||||
if (!validate_contract_dir_paths() || load_config() != 0 || !validate_config())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace conf
|
||||
@@ -24,7 +24,6 @@ struct ContractCtx
|
||||
string contractDir;
|
||||
string histDir;
|
||||
string stateDir;
|
||||
string binDir;
|
||||
string configDir;
|
||||
string configFile;
|
||||
};
|
||||
@@ -58,7 +57,10 @@ struct ContractConfig
|
||||
|
||||
extern ContractCtx ctx;
|
||||
extern ContractConfig cfg;
|
||||
int init(int argc, char **argv);
|
||||
int init();
|
||||
int create_contract();
|
||||
int load_config();
|
||||
int clear_keys();
|
||||
void set_contract_dir_paths(string basedir);
|
||||
void save_config();
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ string sign_b64(string &msg)
|
||||
{
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
crypto_sign_detached(sig, NULL, (unsigned char *)msg.data(), msg.size() + 1, conf::cfg.seckey);
|
||||
return shared::base64_encode(sig, crypto_sign_BYTES);
|
||||
string sigb64;
|
||||
shared::base64_encode(sig, crypto_sign_BYTES, sigb64);
|
||||
return sigb64;
|
||||
}
|
||||
|
||||
bool verify(const unsigned char *msg, unsigned long long msg_len, const unsigned char *sig, const unsigned char *pubkey)
|
||||
@@ -66,13 +68,13 @@ int init()
|
||||
if (conf::cfg.pubkeyb64.empty() || conf::cfg.seckeyb64.empty())
|
||||
{
|
||||
cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Decode b64 keys into bytes and store in memory.
|
||||
if (!b64pair_to_bin())
|
||||
return 0;
|
||||
if (b64pair_to_bin() != 0)
|
||||
return -1;
|
||||
|
||||
//Sign and verify a sample to ensure we have a matching key pair.
|
||||
string msg = "hotpocket";
|
||||
@@ -80,12 +82,12 @@ int init()
|
||||
if (!verify_b64(msg, sigb64, conf::cfg.pubkeyb64))
|
||||
{
|
||||
cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void generate_crypto_keys()
|
||||
@@ -103,8 +105,8 @@ void generate_crypto_keys()
|
||||
|
||||
void binpair_to_b64()
|
||||
{
|
||||
conf::cfg.pubkeyb64 = shared::base64_encode(conf::cfg.pubkey, crypto_sign_PUBLICKEYBYTES);
|
||||
conf::cfg.seckeyb64 = shared::base64_encode(conf::cfg.seckey, crypto_sign_SECRETKEYBYTES);
|
||||
shared::base64_encode(conf::cfg.pubkey, crypto_sign_PUBLICKEYBYTES, conf::cfg.pubkeyb64);
|
||||
shared::base64_encode(conf::cfg.seckey, crypto_sign_SECRETKEYBYTES, conf::cfg.seckeyb64);
|
||||
}
|
||||
|
||||
int b64pair_to_bin()
|
||||
@@ -112,16 +114,16 @@ int b64pair_to_bin()
|
||||
unsigned char *decoded_pubkey = (unsigned char *)malloc(crypto_sign_PUBLICKEYBYTES);
|
||||
unsigned char *decoded_seckey = (unsigned char *)malloc(crypto_sign_SECRETKEYBYTES);
|
||||
|
||||
if (!shared::base64_decode(conf::cfg.pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES))
|
||||
if (shared::base64_decode(conf::cfg.pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES) != 0)
|
||||
{
|
||||
cerr << "Error decoding public key.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!shared::base64_decode(conf::cfg.seckeyb64, decoded_seckey, crypto_sign_SECRETKEYBYTES))
|
||||
if (shared::base64_decode(conf::cfg.seckeyb64, decoded_seckey, crypto_sign_SECRETKEYBYTES) != 0)
|
||||
{
|
||||
cerr << "Error decoding secret key.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conf::cfg.pubkey != NULL)
|
||||
@@ -132,7 +134,7 @@ int b64pair_to_bin()
|
||||
|
||||
conf::cfg.pubkey = decoded_pubkey;
|
||||
conf::cfg.seckey = decoded_seckey;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace crypto
|
||||
33
src/main.cpp
33
src/main.cpp
@@ -8,34 +8,40 @@
|
||||
#include "conf.h"
|
||||
#include "crypto.h"
|
||||
#include "usr/usr.h"
|
||||
#include "proc.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace shared;
|
||||
|
||||
int parse_cmd(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (!parse_cmd(argc, argv))
|
||||
if (parse_cmd(argc, argv) != 0)
|
||||
return -1;
|
||||
|
||||
if (conf::ctx.command == "version")
|
||||
{
|
||||
cout << _HP_VERSION_ << endl;
|
||||
}
|
||||
else if (conf::ctx.command == "new")
|
||||
{
|
||||
if (conf::create_contract() != 0 || crypto::init() != 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool initSuccess = conf::init(argc, argv) && crypto::init();
|
||||
if (!initSuccess)
|
||||
{
|
||||
cerr << "Init error\n";
|
||||
if (conf::init() != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conf::ctx.command == "run")
|
||||
if (conf::ctx.command == "rekey")
|
||||
{
|
||||
usr::init();
|
||||
//Clear the keys. crpyto::init will init the keys.
|
||||
if (conf::clear_keys() != 0 || crypto::init() != 0)
|
||||
return -1;
|
||||
}
|
||||
else if (conf::ctx.command == "run")
|
||||
{
|
||||
if (crypto::init() != 0 || usr::init() != 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +64,14 @@ int parse_cmd(int argc, char **argv)
|
||||
else
|
||||
{
|
||||
conf::set_contract_dir_paths(argv[2]);
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (command == "version")
|
||||
{
|
||||
if (argc == 2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,5 +81,5 @@ int parse_cmd(int argc, char **argv)
|
||||
cout << "hpcore <command> <contract dir> (command = run | new | rekey)\n";
|
||||
cout << "Example: hpcore run ~/mycontract\n";
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ int exec_contract(ContractExecArgs &args)
|
||||
if (is_contract_running())
|
||||
{
|
||||
cerr << "Contract process still running.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
@@ -53,10 +53,10 @@ int exec_contract(ContractExecArgs &args)
|
||||
else
|
||||
{
|
||||
cerr << "fork() failed.\n";
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ using namespace std;
|
||||
namespace shared
|
||||
{
|
||||
|
||||
string base64_encode(unsigned char *bin, size_t bin_len)
|
||||
int base64_encode(unsigned char *bin, size_t bin_len, string &encoded_string)
|
||||
{
|
||||
const size_t base64_max_len = sodium_base64_encoded_len(bin_len, sodium_base64_VARIANT_ORIGINAL);
|
||||
char base64_str[base64_max_len];
|
||||
@@ -17,10 +17,11 @@ string base64_encode(unsigned char *bin, size_t bin_len)
|
||||
sodium_base64_VARIANT_ORIGINAL);
|
||||
|
||||
if (encoded_str_char == NULL)
|
||||
throw "Base64 Error: Failed to encode string";
|
||||
return -1;
|
||||
|
||||
string s(base64_str);
|
||||
return s;
|
||||
encoded_string.clear();
|
||||
encoded_string.append(base64_str, base64_max_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len)
|
||||
@@ -33,10 +34,10 @@ int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len)
|
||||
"", &bin_len, &b64_end,
|
||||
sodium_base64_VARIANT_ORIGINAL))
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace shared
|
||||
@@ -26,7 +26,7 @@ struct ContractUser
|
||||
}
|
||||
};
|
||||
|
||||
string base64_encode(unsigned char *bin, size_t bin_len);
|
||||
int base64_encode(unsigned char *bin, size_t bin_len, string &encoded_string);
|
||||
int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len);
|
||||
|
||||
} // namespace usr
|
||||
|
||||
@@ -28,7 +28,7 @@ void create_user_challenge(string &msg, string &challenge)
|
||||
unsigned char challenge_bytes[USER_CHALLENGE_LEN];
|
||||
randombytes_buf(challenge_bytes, USER_CHALLENGE_LEN);
|
||||
|
||||
challenge = base64_encode(challenge_bytes, USER_CHALLENGE_LEN);
|
||||
base64_encode(challenge_bytes, USER_CHALLENGE_LEN, challenge);
|
||||
|
||||
Document d;
|
||||
d.SetObject();
|
||||
@@ -142,7 +142,7 @@ int read_contract_user_outputs()
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init()
|
||||
|
||||
Reference in New Issue
Block a user