Added challenge issue and verification for peer connections (#93)

Implemented flatbuffer peer challenge issue and verification messages.
Replaced session flags with challenge status enum.
This commit is contained in:
Ravidu Lashan
2020-04-20 05:55:42 +05:30
committed by GitHub
parent 721daf19f3
commit ef8ec0f51d
12 changed files with 303 additions and 145 deletions

View File

@@ -7,17 +7,11 @@
namespace comm
{
/**
* Set of flags used to mark status information on the session.
* usr and p2p subsystems make use of this to mark status information of user and peer sessions.
* Set flags are stored in 'flags' bitset of comm_session.
*/
enum SESSION_FLAG
enum CHALLENGE_STATUS
{
USER_CHALLENGE_ISSUED,
USER_AUTHED,
PEERID_RESOLVED
CHALLENGE_ISSUED,
CHALLENGE_VERIFIED
};
enum SESSION_STATE
@@ -57,11 +51,7 @@ public:
std::string issued_challenge;
conf::ip_port_pair known_ipport;
SESSION_STATE state;
// The set of SESSION_FLAG enum flags that will be set by user-code of this class.
// We mainly use this to store contexual information about this session based on the use case.
// Setting and reading flags to this is completely managed by user-code.
std::bitset<8> flags;
CHALLENGE_STATUS challenge_status;
comm_session(
std::string_view ip, const int read_fd, const int write_fd, const SESSION_TYPE session_type,

View File

@@ -17,7 +17,6 @@ contract_config cfg;
const static char *MODE_OBSERVER = "observer";
const static char *MODE_PROPOSER = "proposer";
constexpr size_t PEERID_LEN = 16;
/**
* Loads and initializes the contract config for execution. Must be called once during application startup.
@@ -36,12 +35,6 @@ int init()
// Append self peer to peer list.
const std::string portstr = std::to_string(cfg.peerport);
// We calculate the self peer id to be a random string.
// Use libsodium to generate the random challenge bytes.
unsigned char peerid_bytes[PEERID_LEN];
randombytes_buf(peerid_bytes, PEERID_LEN);
util::bin2hex(cfg.self_peerid, peerid_bytes, PEERID_LEN);
cfg.peers.emplace(std::make_pair(SELF_HOST, cfg.peerport));
// Append self pubkey to unl list.

View File

@@ -52,7 +52,6 @@ struct contract_config
std::vector<std::string> runtime_binexec_args; // Contract binary execution args used during runtime.
std::vector<std::string> runtime_appbill_args; // Appbill execution args used during runtime.
OPERATING_MODE current_mode; // Current operating mode of the contract (Observer/Proposer)
std::string self_peerid; // Peer session id of this node. (format: selfip:port)
// Config elements which are loaded from the config file.

View File

@@ -2,8 +2,13 @@
include "common_schema.fbs";
namespace fbschema.p2pmsg;
table PeerId_Notify_Message {
peerid:[ubyte];
table Peer_Challenge_Message {
challenge:[ubyte];
}
table Peer_Challenge_Response_Message {
challenge:[ubyte];
sig:[ubyte];
}
table UserSubmittedMessage {
@@ -16,7 +21,7 @@ table UserSubmittedMessageGroup {
messages:[UserSubmittedMessage];
}
union Message { PeerId_Notify_Message, NonUnl_Proposal_Message, Proposal_Message, Npl_Message, State_Request_Message, State_Response_Message, History_Request_Message, History_Response_Message } //message content type
union Message { Peer_Challenge_Response_Message, Peer_Challenge_Message, NonUnl_Proposal_Message, Proposal_Message, Npl_Message, State_Request_Message, State_Response_Message, History_Request_Message, History_Response_Message } //message content type
table Content {
message:Message;

View File

@@ -11,8 +11,11 @@
namespace fbschema {
namespace p2pmsg {
struct PeerId_Notify_Message;
struct PeerId_Notify_MessageBuilder;
struct Peer_Challenge_Message;
struct Peer_Challenge_MessageBuilder;
struct Peer_Challenge_Response_Message;
struct Peer_Challenge_Response_MessageBuilder;
struct UserSubmittedMessage;
struct UserSubmittedMessageBuilder;
@@ -64,22 +67,24 @@ struct State_FS_Hash_EntryBuilder;
enum Message {
Message_NONE = 0,
Message_PeerId_Notify_Message = 1,
Message_NonUnl_Proposal_Message = 2,
Message_Proposal_Message = 3,
Message_Npl_Message = 4,
Message_State_Request_Message = 5,
Message_State_Response_Message = 6,
Message_History_Request_Message = 7,
Message_History_Response_Message = 8,
Message_Peer_Challenge_Response_Message = 1,
Message_Peer_Challenge_Message = 2,
Message_NonUnl_Proposal_Message = 3,
Message_Proposal_Message = 4,
Message_Npl_Message = 5,
Message_State_Request_Message = 6,
Message_State_Response_Message = 7,
Message_History_Request_Message = 8,
Message_History_Response_Message = 9,
Message_MIN = Message_NONE,
Message_MAX = Message_History_Response_Message
};
inline const Message (&EnumValuesMessage())[9] {
inline const Message (&EnumValuesMessage())[10] {
static const Message values[] = {
Message_NONE,
Message_PeerId_Notify_Message,
Message_Peer_Challenge_Response_Message,
Message_Peer_Challenge_Message,
Message_NonUnl_Proposal_Message,
Message_Proposal_Message,
Message_Npl_Message,
@@ -92,9 +97,10 @@ inline const Message (&EnumValuesMessage())[9] {
}
inline const char * const *EnumNamesMessage() {
static const char * const names[10] = {
static const char * const names[11] = {
"NONE",
"PeerId_Notify_Message",
"Peer_Challenge_Response_Message",
"Peer_Challenge_Message",
"NonUnl_Proposal_Message",
"Proposal_Message",
"Npl_Message",
@@ -117,8 +123,12 @@ template<typename T> struct MessageTraits {
static const Message enum_value = Message_NONE;
};
template<> struct MessageTraits<fbschema::p2pmsg::PeerId_Notify_Message> {
static const Message enum_value = Message_PeerId_Notify_Message;
template<> struct MessageTraits<fbschema::p2pmsg::Peer_Challenge_Response_Message> {
static const Message enum_value = Message_Peer_Challenge_Response_Message;
};
template<> struct MessageTraits<fbschema::p2pmsg::Peer_Challenge_Message> {
static const Message enum_value = Message_Peer_Challenge_Message;
};
template<> struct MessageTraits<fbschema::p2pmsg::NonUnl_Proposal_Message> {
@@ -240,59 +250,129 @@ template<> struct State_ResponseTraits<fbschema::p2pmsg::Fs_Entry_Response> {
bool VerifyState_Response(flatbuffers::Verifier &verifier, const void *obj, State_Response type);
bool VerifyState_ResponseVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
struct PeerId_Notify_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef PeerId_Notify_MessageBuilder Builder;
struct Peer_Challenge_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef Peer_Challenge_MessageBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_PEERID = 4
VT_CHALLENGE = 4
};
const flatbuffers::Vector<uint8_t> *peerid() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_PEERID);
const flatbuffers::Vector<uint8_t> *challenge() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHALLENGE);
}
flatbuffers::Vector<uint8_t> *mutable_peerid() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_PEERID);
flatbuffers::Vector<uint8_t> *mutable_challenge() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_CHALLENGE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_PEERID) &&
verifier.VerifyVector(peerid()) &&
VerifyOffset(verifier, VT_CHALLENGE) &&
verifier.VerifyVector(challenge()) &&
verifier.EndTable();
}
};
struct PeerId_Notify_MessageBuilder {
typedef PeerId_Notify_Message Table;
struct Peer_Challenge_MessageBuilder {
typedef Peer_Challenge_Message Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_peerid(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> peerid) {
fbb_.AddOffset(PeerId_Notify_Message::VT_PEERID, peerid);
void add_challenge(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> challenge) {
fbb_.AddOffset(Peer_Challenge_Message::VT_CHALLENGE, challenge);
}
explicit PeerId_Notify_MessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit Peer_Challenge_MessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
PeerId_Notify_MessageBuilder &operator=(const PeerId_Notify_MessageBuilder &);
flatbuffers::Offset<PeerId_Notify_Message> Finish() {
flatbuffers::Offset<Peer_Challenge_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<PeerId_Notify_Message>(end);
auto o = flatbuffers::Offset<Peer_Challenge_Message>(end);
return o;
}
};
inline flatbuffers::Offset<PeerId_Notify_Message> CreatePeerId_Notify_Message(
inline flatbuffers::Offset<Peer_Challenge_Message> CreatePeer_Challenge_Message(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> peerid = 0) {
PeerId_Notify_MessageBuilder builder_(_fbb);
builder_.add_peerid(peerid);
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> challenge = 0) {
Peer_Challenge_MessageBuilder builder_(_fbb);
builder_.add_challenge(challenge);
return builder_.Finish();
}
inline flatbuffers::Offset<PeerId_Notify_Message> CreatePeerId_Notify_MessageDirect(
inline flatbuffers::Offset<Peer_Challenge_Message> CreatePeer_Challenge_MessageDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<uint8_t> *peerid = nullptr) {
auto peerid__ = peerid ? _fbb.CreateVector<uint8_t>(*peerid) : 0;
return fbschema::p2pmsg::CreatePeerId_Notify_Message(
const std::vector<uint8_t> *challenge = nullptr) {
auto challenge__ = challenge ? _fbb.CreateVector<uint8_t>(*challenge) : 0;
return fbschema::p2pmsg::CreatePeer_Challenge_Message(
_fbb,
peerid__);
challenge__);
}
struct Peer_Challenge_Response_Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef Peer_Challenge_Response_MessageBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_CHALLENGE = 4,
VT_SIG = 6
};
const flatbuffers::Vector<uint8_t> *challenge() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHALLENGE);
}
flatbuffers::Vector<uint8_t> *mutable_challenge() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_CHALLENGE);
}
const flatbuffers::Vector<uint8_t> *sig() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_SIG);
}
flatbuffers::Vector<uint8_t> *mutable_sig() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_SIG);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_CHALLENGE) &&
verifier.VerifyVector(challenge()) &&
VerifyOffset(verifier, VT_SIG) &&
verifier.VerifyVector(sig()) &&
verifier.EndTable();
}
};
struct Peer_Challenge_Response_MessageBuilder {
typedef Peer_Challenge_Response_Message Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_challenge(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> challenge) {
fbb_.AddOffset(Peer_Challenge_Response_Message::VT_CHALLENGE, challenge);
}
void add_sig(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> sig) {
fbb_.AddOffset(Peer_Challenge_Response_Message::VT_SIG, sig);
}
explicit Peer_Challenge_Response_MessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
flatbuffers::Offset<Peer_Challenge_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Peer_Challenge_Response_Message>(end);
return o;
}
};
inline flatbuffers::Offset<Peer_Challenge_Response_Message> CreatePeer_Challenge_Response_Message(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> challenge = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> sig = 0) {
Peer_Challenge_Response_MessageBuilder builder_(_fbb);
builder_.add_sig(sig);
builder_.add_challenge(challenge);
return builder_.Finish();
}
inline flatbuffers::Offset<Peer_Challenge_Response_Message> CreatePeer_Challenge_Response_MessageDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<uint8_t> *challenge = nullptr,
const std::vector<uint8_t> *sig = nullptr) {
auto challenge__ = challenge ? _fbb.CreateVector<uint8_t>(*challenge) : 0;
auto sig__ = sig ? _fbb.CreateVector<uint8_t>(*sig) : 0;
return fbschema::p2pmsg::CreatePeer_Challenge_Response_Message(
_fbb,
challenge__,
sig__);
}
struct UserSubmittedMessage FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -337,7 +417,6 @@ struct UserSubmittedMessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UserSubmittedMessageBuilder &operator=(const UserSubmittedMessageBuilder &);
flatbuffers::Offset<UserSubmittedMessage> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<UserSubmittedMessage>(end);
@@ -410,7 +489,6 @@ struct UserSubmittedMessageGroupBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
UserSubmittedMessageGroupBuilder &operator=(const UserSubmittedMessageGroupBuilder &);
flatbuffers::Offset<UserSubmittedMessageGroup> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<UserSubmittedMessageGroup>(end);
@@ -453,8 +531,11 @@ struct Content FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return GetPointer<const void *>(VT_MESSAGE);
}
template<typename T> const T *message_as() const;
const fbschema::p2pmsg::PeerId_Notify_Message *message_as_PeerId_Notify_Message() const {
return message_type() == fbschema::p2pmsg::Message_PeerId_Notify_Message ? static_cast<const fbschema::p2pmsg::PeerId_Notify_Message *>(message()) : nullptr;
const fbschema::p2pmsg::Peer_Challenge_Response_Message *message_as_Peer_Challenge_Response_Message() const {
return message_type() == fbschema::p2pmsg::Message_Peer_Challenge_Response_Message ? static_cast<const fbschema::p2pmsg::Peer_Challenge_Response_Message *>(message()) : nullptr;
}
const fbschema::p2pmsg::Peer_Challenge_Message *message_as_Peer_Challenge_Message() const {
return message_type() == fbschema::p2pmsg::Message_Peer_Challenge_Message ? static_cast<const fbschema::p2pmsg::Peer_Challenge_Message *>(message()) : nullptr;
}
const fbschema::p2pmsg::NonUnl_Proposal_Message *message_as_NonUnl_Proposal_Message() const {
return message_type() == fbschema::p2pmsg::Message_NonUnl_Proposal_Message ? static_cast<const fbschema::p2pmsg::NonUnl_Proposal_Message *>(message()) : nullptr;
@@ -489,8 +570,12 @@ struct Content FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
};
template<> inline const fbschema::p2pmsg::PeerId_Notify_Message *Content::message_as<fbschema::p2pmsg::PeerId_Notify_Message>() const {
return message_as_PeerId_Notify_Message();
template<> inline const fbschema::p2pmsg::Peer_Challenge_Response_Message *Content::message_as<fbschema::p2pmsg::Peer_Challenge_Response_Message>() const {
return message_as_Peer_Challenge_Response_Message();
}
template<> inline const fbschema::p2pmsg::Peer_Challenge_Message *Content::message_as<fbschema::p2pmsg::Peer_Challenge_Message>() const {
return message_as_Peer_Challenge_Message();
}
template<> inline const fbschema::p2pmsg::NonUnl_Proposal_Message *Content::message_as<fbschema::p2pmsg::NonUnl_Proposal_Message>() const {
@@ -535,7 +620,6 @@ struct ContentBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ContentBuilder &operator=(const ContentBuilder &);
flatbuffers::Offset<Content> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Content>(end);
@@ -584,7 +668,6 @@ struct NonUnl_Proposal_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
NonUnl_Proposal_MessageBuilder &operator=(const NonUnl_Proposal_MessageBuilder &);
flatbuffers::Offset<NonUnl_Proposal_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<NonUnl_Proposal_Message>(end);
@@ -700,7 +783,6 @@ struct Proposal_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Proposal_MessageBuilder &operator=(const Proposal_MessageBuilder &);
flatbuffers::Offset<Proposal_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Proposal_Message>(end);
@@ -778,7 +860,6 @@ struct Npl_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Npl_MessageBuilder &operator=(const Npl_MessageBuilder &);
flatbuffers::Offset<Npl_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Npl_Message>(end);
@@ -845,7 +926,6 @@ struct History_Request_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
History_Request_MessageBuilder &operator=(const History_Request_MessageBuilder &);
flatbuffers::Offset<History_Request_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<History_Request_Message>(end);
@@ -917,7 +997,6 @@ struct History_Response_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
History_Response_MessageBuilder &operator=(const History_Response_MessageBuilder &);
flatbuffers::Offset<History_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<History_Response_Message>(end);
@@ -987,7 +1066,6 @@ struct HistoryLedgerPairBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
HistoryLedgerPairBuilder &operator=(const HistoryLedgerPairBuilder &);
flatbuffers::Offset<HistoryLedgerPair> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<HistoryLedgerPair>(end);
@@ -1059,7 +1137,6 @@ struct HistoryLedgerBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
HistoryLedgerBuilder &operator=(const HistoryLedgerBuilder &);
flatbuffers::Offset<HistoryLedger> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<HistoryLedger>(end);
@@ -1158,7 +1235,6 @@ struct State_Request_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
State_Request_MessageBuilder &operator=(const State_Request_MessageBuilder &);
flatbuffers::Offset<State_Request_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_Request_Message>(end);
@@ -1268,7 +1344,6 @@ struct State_Response_MessageBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
State_Response_MessageBuilder &operator=(const State_Response_MessageBuilder &);
flatbuffers::Offset<State_Response_Message> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_Response_Message>(end);
@@ -1344,7 +1419,6 @@ struct Fs_Entry_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Fs_Entry_ResponseBuilder &operator=(const Fs_Entry_ResponseBuilder &);
flatbuffers::Offset<Fs_Entry_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Fs_Entry_Response>(end);
@@ -1427,7 +1501,6 @@ struct File_HashMap_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
File_HashMap_ResponseBuilder &operator=(const File_HashMap_ResponseBuilder &);
flatbuffers::Offset<File_HashMap_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<File_HashMap_Response>(end);
@@ -1514,7 +1587,6 @@ struct Block_ResponseBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
Block_ResponseBuilder &operator=(const Block_ResponseBuilder &);
flatbuffers::Offset<Block_Response> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Block_Response>(end);
@@ -1601,7 +1673,6 @@ struct State_FS_Hash_EntryBuilder {
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
State_FS_Hash_EntryBuilder &operator=(const State_FS_Hash_EntryBuilder &);
flatbuffers::Offset<State_FS_Hash_Entry> Finish() {
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<State_FS_Hash_Entry>(end);
@@ -1640,8 +1711,12 @@ inline bool VerifyMessage(flatbuffers::Verifier &verifier, const void *obj, Mess
case Message_NONE: {
return true;
}
case Message_PeerId_Notify_Message: {
auto ptr = reinterpret_cast<const fbschema::p2pmsg::PeerId_Notify_Message *>(obj);
case Message_Peer_Challenge_Response_Message: {
auto ptr = reinterpret_cast<const fbschema::p2pmsg::Peer_Challenge_Response_Message *>(obj);
return verifier.VerifyTable(ptr);
}
case Message_Peer_Challenge_Message: {
auto ptr = reinterpret_cast<const fbschema::p2pmsg::Peer_Challenge_Message *>(obj);
return verifier.VerifyTable(ptr);
}
case Message_NonUnl_Proposal_Message: {

View File

@@ -12,6 +12,8 @@
namespace fbschema::p2pmsg
{
constexpr size_t PEERCHALLENGE_LEN = 16;
/**
* This section contains Flatbuffer message reading/writing helpers.
* These helpers are mainly used by peer_session_handler.
@@ -140,9 +142,30 @@ int validate_and_extract_content(const Content **content_ref, const uint8_t *con
//---Message reading helpers---/
std::string_view get_peerid_from_msg(const PeerId_Notify_Message &msg)
/**
* Returns challenge from the peer challenge message.
* @param The Flatbuffer peer challenge message received from the peer.
* @return binary challenge.
*/
const std::string_view get_peer_challenge_from_msg(const Peer_Challenge_Message &msg)
{
return flatbuff_bytes_to_sv(msg.peerid());
return flatbuff_bytes_to_sv(msg.challenge());
}
/**
* Creates a peer challenge response struct from the given peer challenge response message.
* @param The Flatbuffer peer challenge response message received from the peer.
* @return A peer challenge response struct representing the message.
*/
const p2p::peer_challenge_response create_peer_challenge_response_from_msg(const Peer_Challenge_Response_Message &msg, const flatbuffers::Vector<uint8_t> *pubkey)
{
p2p::peer_challenge_response pchalresp;
pchalresp.challenge = flatbuff_bytes_to_sv(msg.challenge());
pchalresp.signature = flatbuff_bytes_to_sv(msg.sig());
pchalresp.pubkey = flatbuff_bytes_to_sv(pubkey);
return pchalresp;
}
/**
@@ -258,21 +281,53 @@ const p2p::block_response create_block_response_from_msg(const Block_Response &m
//---Message creation helpers---//
void create_msg_from_peerid(flatbuffers::FlatBufferBuilder &container_builder, std::string_view peerid)
/**
* Create peer challenge message from the given challenge.
* @param container_builder Flatbuffer builder for the container message.
* @param challenge Challenge message needed to convert to flatbuffer message.
*/
void create_msg_from_peer_challenge(flatbuffers::FlatBufferBuilder &container_builder, std::string &challenge)
{
flatbuffers::FlatBufferBuilder builder(1024);
const flatbuffers::Offset<PeerId_Notify_Message> peerid_msg =
CreatePeerId_Notify_Message(
builder,
sv_to_flatbuff_bytes(builder, peerid));
// We calculate the peer challenge to be a random string.
// Use libsodium to generate the random challenge bytes.
challenge.resize(PEERCHALLENGE_LEN);
randombytes_buf(challenge.data(), PEERCHALLENGE_LEN);
const flatbuffers::Offset<Content> message = CreateContent(builder, Message_PeerId_Notify_Message, peerid_msg.Union());
const flatbuffers::Offset<Peer_Challenge_Message> peer_challenge_msg =
CreatePeer_Challenge_Message(
builder,
sv_to_flatbuff_bytes(builder, challenge));
const flatbuffers::Offset<Content> message = CreateContent(builder, Message_Peer_Challenge_Message, peer_challenge_msg.Union());
builder.Finish(message); // Finished building message content to get serialised content.
// Now that we have built the content message
create_containermsg_from_content(container_builder, builder, nullptr, false);
}
/**
* Create peer challenge response message from the given challenge.
* @param container_builder Flatbuffer builder for the container message.
* @param challenge Message which need to be signed and placed in the container message.
*/
void create_peer_challenge_response_from_challenge(flatbuffers::FlatBufferBuilder &container_builder, const std::string &challenge)
{
flatbuffers::FlatBufferBuilder builder(1024);
const flatbuffers::Offset<Peer_Challenge_Response_Message> challenge_resp_msg =
CreatePeer_Challenge_Response_Message(
builder,
sv_to_flatbuff_bytes(builder, challenge),
sv_to_flatbuff_bytes(builder, crypto::sign(challenge, conf::cfg.seckey)));
const flatbuffers::Offset<Content> message = CreateContent(builder, Message_Peer_Challenge_Response_Message, challenge_resp_msg.Union());
builder.Finish(message); // Finished building message content to get serialised content.
// Now that we have built the content message,
// we need to sign it and place it inside a container message.
create_containermsg_from_content(container_builder, builder, nullptr, false);
create_containermsg_from_content(container_builder, builder, nullptr, true);
}
void create_msg_from_nonunl_proposal(flatbuffers::FlatBufferBuilder &container_builder, const p2p::nonunl_proposal &nup)

View File

@@ -23,7 +23,9 @@ int validate_and_extract_content(const Content **content_ref, const uint8_t *con
//---Message reading helpers---/
std::string_view get_peerid_from_msg(const PeerId_Notify_Message &msg);
const std::string_view get_peer_challenge_from_msg(const Peer_Challenge_Message &msg);
const p2p::peer_challenge_response create_peer_challenge_response_from_msg(const Peer_Challenge_Response_Message &msg, const flatbuffers::Vector<uint8_t> *pubkey);
const p2p::nonunl_proposal create_nonunl_proposal_from_msg(const NonUnl_Proposal_Message &msg, const uint64_t timestamp);
@@ -38,8 +40,9 @@ const p2p::state_request create_state_request_from_msg(const State_Request_Messa
const p2p::block_response create_block_response_from_msg(const Block_Response &msg);
//---Message creation helpers---//
void create_peer_challenge_response_from_challenge(flatbuffers::FlatBufferBuilder &container_builder, const std::string &challenge);
void create_msg_from_peerid(flatbuffers::FlatBufferBuilder &container_builder, std::string_view peerid);
void create_msg_from_peer_challenge(flatbuffers::FlatBufferBuilder &container_builder, std::string &challenge);
void create_msg_from_nonunl_proposal(flatbuffers::FlatBufferBuilder &container_builder, const p2p::nonunl_proposal &nup);
@@ -53,8 +56,8 @@ void create_msg_from_npl_output(flatbuffers::FlatBufferBuilder &container_builde
void create_msg_from_state_request(flatbuffers::FlatBufferBuilder &container_builder, const p2p::state_request &hr, std::string_view lcl);
void create_msg_from_fsentry_response(flatbuffers::FlatBufferBuilder &container_builder, const std::string_view path,
std::unordered_map<std::string, p2p::state_fs_hash_entry> &fs_entries, hasher::B2H expected_hash, std::string_view lcl);
void create_msg_from_fsentry_response(flatbuffers::FlatBufferBuilder &container_builder, const std::string_view path,
std::unordered_map<std::string, p2p::state_fs_hash_entry> &fs_entries, hasher::B2H expected_hash, std::string_view lcl);
void create_msg_from_filehashmap_response(flatbuffers::FlatBufferBuilder &container_builder, std::string_view path, std::vector<uint8_t> &hashmap, std::size_t file_length, hasher::B2H expected_hash, std::string_view lcl);
@@ -79,14 +82,12 @@ flatbuf_historyledgermap_to_historyledgermap(const flatbuffers::Vector<flatbuffe
const flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<HistoryLedgerPair>>>
historyledgermap_to_flatbuf_historyledgermap(flatbuffers::FlatBufferBuilder &builder, const std::map<uint64_t, const p2p::history_ledger> &map);
void
flatbuf_statefshashentry_to_statefshashentry(std::unordered_map<std::string, p2p::state_fs_hash_entry> &fs_entries,
const flatbuffers::Vector<flatbuffers::Offset<State_FS_Hash_Entry>> *fhashes);
void flatbuf_statefshashentry_to_statefshashentry(std::unordered_map<std::string, p2p::state_fs_hash_entry> &fs_entries,
const flatbuffers::Vector<flatbuffers::Offset<State_FS_Hash_Entry>> *fhashes);
void statefilehash_to_flatbuf_statefilehash(flatbuffers::FlatBufferBuilder &builder, std::vector<flatbuffers::Offset<State_FS_Hash_Entry>> &list,
std::string_view full_path, bool is_file, std::string_view hash);
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<State_FS_Hash_Entry>>>
statefshashentry_to_flatbuff_statefshashentry(flatbuffers::FlatBufferBuilder &builder, std::unordered_map<std::string, p2p::state_fs_hash_entry> &fs_entries);

View File

@@ -43,39 +43,60 @@ int start_peer_connections()
return 0;
}
int resolve_session_peerid(comm::comm_session &session, const std::string &peerid)
int resolve_peer_challenge(comm::comm_session &session, const peer_challenge_response &challenge_resp)
{
const int res = peerid.compare(conf::cfg.self_peerid);
// If peerid is same as our (self) peerid, then this is the loopback connection to ourselves.
// Compare the response challenge string with the original issued challenge.
if (session.issued_challenge != challenge_resp.challenge)
{
LOG_DBG << "Peer challenge response, challenge invalid.";
return -1;
}
// Verify the challenge signature.
if (crypto::verify(
challenge_resp.challenge,
challenge_resp.signature,
challenge_resp.pubkey) != 0)
{
LOG_DBG << "Peer challenge response signature verification failed.";
return -1;
}
// Converting the binary pub key into hexa decimal string this will be used as the key in storing peer sessions
std::string pubkeyhex;
util::bin2hex(pubkeyhex, reinterpret_cast<const unsigned char *>(challenge_resp.pubkey.data()), challenge_resp.pubkey.length());
const int res = challenge_resp.pubkey.compare(conf::cfg.pubkey);
// If pub key is same as our (self) pub key, then this is the loopback connection to ourselves.
// Hence we must keep the connection but only one of two sessions must be added to peer_connections.
// If peerid is greater than our id (< 0), then we should give priority to any existing inbound connection
// If pub key is greater than our id (< 0), then we should give priority to any existing inbound connection
// from the same peer and drop the outbound connection.
// If peerid is lower than our id (> 0), then we should give priority to any existing outbound connection
// If pub key is lower than our id (> 0), then we should give priority to any existing outbound connection
// from the same peer and drop the inbound connection.
std::lock_guard<std::mutex> lock(ctx.peer_connections_mutex);
const auto iter = p2p::ctx.peer_connections.find(peerid);
const auto iter = p2p::ctx.peer_connections.find(pubkeyhex);
if (iter == p2p::ctx.peer_connections.end())
{
// Add the new connection straight away, if we haven't seen it before.
session.uniqueid = peerid;
session.flags.set(comm::SESSION_FLAG::PEERID_RESOLVED);
p2p::ctx.peer_connections.try_emplace(peerid, &session);
session.uniqueid.swap(pubkeyhex);
session.challenge_status = comm::CHALLENGE_VERIFIED;
p2p::ctx.peer_connections.try_emplace(session.uniqueid, &session);
return 0;
}
else if (res == 0) // New connection is self (There can be two sessions for self (inbound/outbound))
{
session.is_self = true;
session.uniqueid = peerid;
session.flags.set(comm::SESSION_FLAG::PEERID_RESOLVED);
session.uniqueid.swap(pubkeyhex);
session.challenge_status = comm::CHALLENGE_VERIFIED;
return 0;
}
else // New connection is not self but with same peer id.
else // New connection is not self but with same pub key.
{
comm::comm_session &ex_session = *iter->second;
// We don't allow duplicate connections to the same peer to same direction.
if (ex_session.is_inbound != session.is_inbound)
{
@@ -86,14 +107,14 @@ int resolve_session_peerid(comm::comm_session &session, const std::string &peeri
// If we happen to replace a peer session with known IP, transfer required details to the new session.
if (session.known_ipport.first.empty())
session.known_ipport.swap(ex_session.known_ipport);
session.uniqueid = peerid;
session.flags.set(comm::SESSION_FLAG::PEERID_RESOLVED);
session.uniqueid.swap(pubkeyhex);
session.challenge_status = comm::CHALLENGE_VERIFIED;
ex_session.close(false);
p2p::ctx.peer_connections.erase(iter); // remove existing session.
p2p::ctx.peer_connections.try_emplace(peerid, &session); // add new session.
p2p::ctx.peer_connections.erase(iter); // remove existing session.
p2p::ctx.peer_connections.try_emplace(session.uniqueid, &session); // add new session.
LOG_DBG << "Replacing existing connection [" << peerid << "]";
LOG_DBG << "Replacing existing connection [" << session.uniqueid << "]";
return 0;
}
else if (ex_session.known_ipport.first.empty() || !session.known_ipport.first.empty())
@@ -104,7 +125,7 @@ int resolve_session_peerid(comm::comm_session &session, const std::string &peeri
}
// Reaching this point means we don't need the new session.
LOG_DBG << "Rejecting new peer connection because existing connection takes priority [" << peerid << "]";
LOG_DBG << "Rejecting new peer connection because existing connection takes priority [" << pubkeyhex << "]";
return -1;
}
}
@@ -147,7 +168,7 @@ void send_message_to_self(const flatbuffers::FlatBufferBuilder &fbuf)
std::lock_guard<std::mutex> lock(p2p::ctx.peer_connections_mutex);
// Find the peer session connected to self.
const auto peer_itr = ctx.peer_connections.find(conf::cfg.self_peerid);
const auto peer_itr = ctx.peer_connections.find(conf::cfg.pubkeyhex);
if (peer_itr != ctx.peer_connections.end())
{
std::string_view msg = std::string_view(

View File

@@ -44,6 +44,13 @@ struct history_ledger
std::vector<uint8_t> raw_ledger;
};
struct peer_challenge_response
{
std::string challenge;
std::string signature;
std::string pubkey;
};
enum LEDGER_RESPONSE_ERROR
{
NONE = 0,
@@ -124,7 +131,7 @@ void deinit();
int start_peer_connections();
int resolve_session_peerid(comm::comm_session &session, const std::string &peerid);
int resolve_peer_challenge(comm::comm_session &session, const peer_challenge_response &challenge_resp);
void broadcast_message(const flatbuffers::FlatBufferBuilder &fbuf, const bool send_to_self);

View File

@@ -38,12 +38,14 @@ int peer_session_handler::on_connect(comm::comm_session &session) const
}
}
// Send our peer id.
// Send peer challenge.
flatbuffers::FlatBufferBuilder fbuf(1024);
p2pmsg::create_msg_from_peerid(fbuf, conf::cfg.self_peerid);
p2pmsg::create_msg_from_peer_challenge(fbuf, session.issued_challenge);
std::string_view msg = std::string_view(
reinterpret_cast<const char *>(fbuf.GetBufferPointer()), fbuf.GetSize());
return session.send(msg);
session.send(msg);
session.challenge_status = comm::CHALLENGE_ISSUED;
return 0;
}
//peer session on message callback method
@@ -74,19 +76,30 @@ int peer_session_handler::on_message(comm::comm_session &session, std::string_vi
const p2pmsg::Message content_message_type = content->message_type(); //i.e - proposal, npl, state request, state response, etc
if (content_message_type == p2pmsg::Message_PeerId_Notify_Message) // message is a peer id announcement
if (content_message_type == p2pmsg::Message_Peer_Challenge_Message) // message is a peer challenge announcement
{
// Ignore if Peer ID is already resolved.
if (!session.flags[comm::SESSION_FLAG::PEERID_RESOLVED])
// Sending the challenge response to the respected peer.
const std::string challenge = std::string(p2pmsg::get_peer_challenge_from_msg(*content->message_as_Peer_Challenge_Message()));
flatbuffers::FlatBufferBuilder fbuf(1024);
p2pmsg::create_peer_challenge_response_from_challenge(fbuf, challenge);
std::string_view msg = std::string_view(
reinterpret_cast<const char *>(fbuf.GetBufferPointer()), fbuf.GetSize());
return session.send(msg);
}
if (content_message_type == p2pmsg::Message_Peer_Challenge_Response_Message) // message is a peer challenge response
{
// Ignore if challenge is already resolved.
if (session.challenge_status == comm::CHALLENGE_ISSUED)
{
const std::string peerid = std::string(p2pmsg::get_peerid_from_msg(*content->message_as_PeerId_Notify_Message()));
return p2p::resolve_session_peerid(session, peerid);
const p2p::peer_challenge_response challenge_resp = p2pmsg::create_peer_challenge_response_from_msg(*content->message_as_Peer_Challenge_Response_Message(), container->pubkey());
return p2p::resolve_peer_challenge(session, challenge_resp);
}
}
if (!session.flags[comm::SESSION_FLAG::PEERID_RESOLVED])
if (session.challenge_status != comm::CHALLENGE_VERIFIED)
{
LOG_DBG << "Cannot accept messages. Peer id unresolved. " << session.uniqueid;
LOG_DBG << "Cannot accept messages. Peer challenge unresolved. " << session.uniqueid;
return 0;
}

View File

@@ -29,8 +29,8 @@ int user_session_handler::on_connect(comm::comm_session &session) const
jusrmsg::create_user_challenge(msgstr, session.issued_challenge);
session.send(msgstr);
// Set the challenge-issued flag to help later checks in on_message.
session.flags.set(comm::SESSION_FLAG::USER_CHALLENGE_ISSUED);
// Set the challenge-issued value to true.
session.challenge_status = comm::CHALLENGE_ISSUED;
return 0;
}
@@ -42,13 +42,13 @@ int user_session_handler::on_message(comm::comm_session &session, std::string_vi
{
// First check whether this session is pending challenge.
// Meaning we have previously issued a challenge to the client.
if (session.flags[comm::SESSION_FLAG::USER_CHALLENGE_ISSUED])
if (session.challenge_status == comm::CHALLENGE_ISSUED)
{
if (verify_challenge(message, session) == 0)
return 0;
}
// Check whether this session belongs to an authenticated (challenge-verified) user.
else if (session.flags[comm::SESSION_FLAG::USER_AUTHED])
else if (session.challenge_status == comm::CHALLENGE_VERIFIED)
{
// Check whether this user is among authenticated users
// and perform authenticated msg processing.
@@ -86,7 +86,7 @@ int user_session_handler::on_message(comm::comm_session &session, std::string_vi
void user_session_handler::on_close(const comm::comm_session &session) const
{
// Session belongs to an authed user.
if (session.flags[comm::SESSION_FLAG::USER_AUTHED])
if (session.challenge_status == comm::CHALLENGE_VERIFIED)
remove_user(session.uniqueid);
}

View File

@@ -86,8 +86,7 @@ int verify_challenge(std::string_view message, comm::comm_session &session)
// All good. Unique public key.
// Promote the connection from pending-challenges to authenticated users.
session.flags.reset(comm::SESSION_FLAG::USER_CHALLENGE_ISSUED); // Clear challenge-issued flag
session.flags.set(comm::SESSION_FLAG::USER_AUTHED); // Set the user-authed flag
session.challenge_status = comm::CHALLENGE_VERIFIED; // Set as challenge verified
add_user(session, userpubkey); // Add the user to the global authed user list
session.issued_challenge.clear(); // Remove the stored challenge