mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-26 01:31:30 -05:00
added nonce system for safe peer removal
This commit is contained in:
parent
b7c7c4c3f5
commit
6b6d556e98
@ -76,10 +76,23 @@ class RsFriendServerClientRemoveItem: public RsFriendServerItem
|
|||||||
public:
|
public:
|
||||||
RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {}
|
RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {}
|
||||||
|
|
||||||
void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */)
|
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||||
{
|
{
|
||||||
|
RS_SERIAL_PROCESS(peer_id);
|
||||||
|
RS_SERIAL_PROCESS(nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peer ID for the peer to remove.
|
||||||
|
|
||||||
|
RsPeerId peer_id;
|
||||||
|
|
||||||
|
// Nonce that was returned by the server after the last client request. Should match in order to proceed. This prevents
|
||||||
|
// a malicious actor from removing peers from the server. Since the nonce is sent through Tor tunnels, it cannot be known by
|
||||||
|
// anyone else than the client.
|
||||||
|
|
||||||
|
uint64_t nonce;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RsFriendServerEncryptedServerResponseItem: public RsFriendServerItem
|
class RsFriendServerEncryptedServerResponseItem: public RsFriendServerItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -66,21 +66,44 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RsDbg() << "Received a client publish item from " << item->PeerId() ;
|
RsDbg() << "Received a client publish item from " << item->PeerId() << ":";
|
||||||
RsDbg() << *item ;
|
RsDbg() << *item ;
|
||||||
|
|
||||||
// First of all, read PGP key and short invites, parse them, and check that they contain the same information
|
// First of all, read PGP key and short invites, parse them, and check that they contain the same information
|
||||||
|
|
||||||
|
FriendServer::handleIncomingClientData(item->pgp_public_key_b64,item->short_invite);
|
||||||
|
|
||||||
|
// Respond with a list of potential friends
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(std::exception& e)
|
||||||
|
{
|
||||||
|
RsErr() << "ERROR: " << e.what() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close client connection from server side, to tell the client that nothing more is coming.
|
||||||
|
|
||||||
|
RsDbg() << "Closing client connection." ;
|
||||||
|
|
||||||
|
mni->closeConnection(item->PeerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FriendServer::handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64)
|
||||||
|
{
|
||||||
RsDbg() << " Checking item data...";
|
RsDbg() << " Checking item data...";
|
||||||
|
|
||||||
std::string error_string;
|
std::string error_string;
|
||||||
RsPgpId pgp_id ;
|
RsPgpId pgp_id ;
|
||||||
std::vector<uint8_t> key_binary_data ;
|
std::vector<uint8_t> key_binary_data ;
|
||||||
|
|
||||||
key_binary_data = Radix64::decode(item->pgp_public_key_b64);
|
key_binary_data = Radix64::decode(pgp_public_key_b64);
|
||||||
|
|
||||||
if(key_binary_data.empty())
|
if(key_binary_data.empty())
|
||||||
throw std::runtime_error(" Cannot decode client pgp public key: \"" + item->pgp_public_key_b64 + "\". Wrong format??");
|
throw std::runtime_error(" Cannot decode client pgp public key: \"" + pgp_public_key_b64 + "\". Wrong format??");
|
||||||
|
|
||||||
|
// Apparently RsBase64 doesn't work correctly.
|
||||||
|
//
|
||||||
// if(!RsBase64::decode(item->pgp_public_key_b64,key_binary_data))
|
// if(!RsBase64::decode(item->pgp_public_key_b64,key_binary_data))
|
||||||
// throw std::runtime_error(" Cannot decode client pgp public key: \"" + item->pgp_public_key_b64 + "\". Wrong format??");
|
// throw std::runtime_error(" Cannot decode client pgp public key: \"" + item->pgp_public_key_b64 + "\". Wrong format??");
|
||||||
|
|
||||||
@ -94,7 +117,7 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
|||||||
RsPeerDetails shortInviteDetails;
|
RsPeerDetails shortInviteDetails;
|
||||||
uint32_t errorCode = 0;
|
uint32_t errorCode = 0;
|
||||||
|
|
||||||
if(item->short_invite.empty() || !RsCertificate::decodeRadix64ShortInvite(item->short_invite, shortInviteDetails,errorCode ))
|
if(short_invite_b64.empty() || !RsCertificate::decodeRadix64ShortInvite(short_invite_b64, shortInviteDetails,errorCode ))
|
||||||
throw std::runtime_error("Could not parse short certificate. Error = " + RsUtil::NumberToString(errorCode));
|
throw std::runtime_error("Could not parse short certificate. Error = " + RsUtil::NumberToString(errorCode));
|
||||||
|
|
||||||
RsDbg() << " Short invite is fine. PGP fingerprint: " << shortInviteDetails.fpr ;
|
RsDbg() << " Short invite is fine. PGP fingerprint: " << shortInviteDetails.fpr ;
|
||||||
@ -107,37 +130,52 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
|||||||
throw std::runtime_error("Cannot get fingerprint from keyring for client public key. Something's really wrong.") ;
|
throw std::runtime_error("Cannot get fingerprint from keyring for client public key. Something's really wrong.") ;
|
||||||
|
|
||||||
RsDbg() << " Short invite PGP fingerprint matches the public key fingerprint.";
|
RsDbg() << " Short invite PGP fingerprint matches the public key fingerprint.";
|
||||||
|
RsDbg() << " Sync-ing the PGP keyring on disk";
|
||||||
|
|
||||||
// Check the item's data signature
|
mPgpHandler->syncDatabase();
|
||||||
|
|
||||||
|
// Check the item's data signature. Is that needed? Not sure, since the data is sent PGP-encrypted, so only the owner
|
||||||
|
// of the secret PGP key can actually use it.
|
||||||
|
#warning TODO
|
||||||
|
|
||||||
// All good.
|
// All good.
|
||||||
#warning TODO
|
|
||||||
|
|
||||||
// Store/update the peer info
|
// Store/update the peer info
|
||||||
|
|
||||||
auto& pi(mCurrentClientPeers[shortInviteDetails.id]);
|
auto& pi(mCurrentClientPeers[shortInviteDetails.id]);
|
||||||
|
|
||||||
pi.short_certificate = item->short_invite;
|
pi.short_certificate = short_invite_b64;
|
||||||
pi.last_connection_TS = time(nullptr);
|
pi.last_connection_TS = time(nullptr);
|
||||||
|
pi.last_nonce = RsRandom::random_u64();
|
||||||
|
|
||||||
// Respond with a list of potential friends
|
return true;
|
||||||
}
|
|
||||||
catch(std::exception& e)
|
|
||||||
{
|
|
||||||
RsErr() << e.what() ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close client connection from server side, to tell the client that nothing more is coming.
|
|
||||||
|
|
||||||
RsDbg() << "Closing client connection." ;
|
|
||||||
|
|
||||||
mni->closeConnection(item->PeerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item)
|
void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item)
|
||||||
{
|
{
|
||||||
RsDbg() << "Received a client remove item:" << *item ;
|
RsDbg() << "Received a client remove item:" << *item ;
|
||||||
|
|
||||||
|
auto it = mCurrentClientPeers.find(item->peer_id);
|
||||||
|
|
||||||
|
if(it == mCurrentClientPeers.end())
|
||||||
|
{
|
||||||
|
RsErr() << " ERROR: Client " << item->peer_id << " is not known to the server." ;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(it->second.last_nonce != item->nonce)
|
||||||
|
{
|
||||||
|
RsErr() << " ERROR: Client supplied a nonce " << std::hex << item->nonce << std::dec << " that is not correct (expected "
|
||||||
|
<< std::hex << it->second.last_nonce << std::dec << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsDbg() << " Nonce is correct: " << std::hex << item->nonce << std::dec << ". Removing peer " << item->peer_id ;
|
||||||
|
|
||||||
|
mCurrentClientPeers.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
FriendServer::FriendServer(const std::string& base_dir)
|
FriendServer::FriendServer(const std::string& base_dir)
|
||||||
{
|
{
|
||||||
RsDbg() << "Creating friend server." ;
|
RsDbg() << "Creating friend server." ;
|
||||||
@ -191,7 +229,7 @@ void FriendServer::debugPrint()
|
|||||||
rstime_t now = time(nullptr);
|
rstime_t now = time(nullptr);
|
||||||
|
|
||||||
for(auto& it:mCurrentClientPeers)
|
for(auto& it:mCurrentClientPeers)
|
||||||
RsDbg() << " " << it.first << ": " << "last contact: " << now - it.second.last_connection_TS;
|
RsDbg() << " " << it.first << ": nonce=" << std::hex << it.second.last_nonce << std::dec << ", last contact: " << now - it.second.last_connection_TS << " secs ago.";
|
||||||
|
|
||||||
RsDbg() << "===============================================";
|
RsDbg() << "===============================================";
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ struct PeerInfo
|
|||||||
{
|
{
|
||||||
std::string short_certificate;
|
std::string short_certificate;
|
||||||
rstime_t last_connection_TS;
|
rstime_t last_connection_TS;
|
||||||
|
uint64_t last_nonce;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FriendServer : public RsTickingThread
|
class FriendServer : public RsTickingThread
|
||||||
@ -52,6 +53,8 @@ private:
|
|||||||
void handleClientRemove(const RsFriendServerClientRemoveItem *item);
|
void handleClientRemove(const RsFriendServerClientRemoveItem *item);
|
||||||
void handleClientPublish(const RsFriendServerClientPublishItem *item);
|
void handleClientPublish(const RsFriendServerClientPublishItem *item);
|
||||||
|
|
||||||
|
bool handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64);
|
||||||
|
|
||||||
void autoWash();
|
void autoWash();
|
||||||
void debugPrint();
|
void debugPrint();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user