diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 67014e179..3af34b166 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -208,6 +208,7 @@ #include "retroshare/rsgxsflags.h" #include "retroshare/rsgxscircles.h" #include "pgp/pgpauxutils.h" +#include "util/rsdir.h" #include "util/rsmemory.h" #include "util/stacktrace.h" @@ -604,6 +605,21 @@ public: std::vector::clear() ; } }; + +RsGxsGroupId RsGxsNetService::hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) +{ + static const uint32_t SIZE = RsGxsGroupId::SIZE_IN_BYTES + RsPeerId::SIZE_IN_BYTES ; + unsigned char tmpmem[SIZE]; + uint32_t offset = 0 ; + + pid.serialise(tmpmem,SIZE,offset) ; + gid.serialise(tmpmem,SIZE,offset) ; + + assert(RsGxsGroupId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ; + + return RsGxsGroupId( RsDirUtil::sha1sum(tmpmem,SIZE).toByteArray() ); +} + void RsGxsNetService::syncWithPeers() { #ifdef NXS_NET_DEBUG_0 @@ -742,45 +758,24 @@ void RsGxsNetService::syncWithPeers() RsNxsSyncMsgReqItem* msg = new RsNxsSyncMsgReqItem(mServType); msg->clear(); msg->PeerId(peerId); - msg->grpId = grpId; msg->updateTS = updateTS; - + if(encrypt_to_this_circle_id.isNull()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(*sit,grpId) << " Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself - in clear " << std::endl; -#endif - sendItem(msg); - } + msg->grpId = grpId; else { + msg->grpId = hashGrpId(grpId,mNetMgr->getOwnId()) ; + msg->flag |= RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID ; + } + #ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(*sit,grpId) << " Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself - encrypted for circle " << encrypt_to_this_circle_id << std::endl; + GXSNETDEBUG_PG(*sit,grpId) << " Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself - in clear " << std::endl; #endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status ; - - if(encryptSingleNxsItem(msg, encrypt_to_this_circle_id, grpId, encrypted_item, status)) - sendItem(encrypted_item) ; -#ifdef NXS_NET_DEBUG_7 - else - GXSNETDEBUG_PG(*sit,grpId) << "(WW) could not encrypt for circle ID " << encrypt_to_this_circle_id << ". Not yet in cache?" << std::endl; -#endif - - delete msg ; - } + sendItem(msg); #ifdef NXS_NET_DEBUG_5 GXSNETDEBUG_PG(*sit,grpId) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself" << std::endl; #endif - //} - //else - //{ - // delete msg ; - //#ifdef NXS_NET_DEBUG_0 - // GXSNETDEBUG_PG(*sit,grpId) << " cancel RsNxsSyncMsg req (last local update TS for group+peer) for grpId=" << grpId << " to peer " << *sit << ": not enough bandwidth." << std::endl; - //#endif - //} } } @@ -4345,28 +4340,57 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs return true; } -bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncMsgReqItem *item) +bool RsGxsNetService::locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item,bool& grp_is_known,bool& item_was_encrypted) { // Do we have new updates for this peer? // Here we compare times in the same clock: the friend's clock, so it should be fine. - ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(item->grpId); + grp_is_known = false ; + if(item->flag & RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID) + { + // Item contains the hashed group ID in order to protect is from friends who don't know it. So we de-hash it using bruteforce over known group IDs for this peer. + // We could save the de-hash result. But the cost is quite light, since the number of encrypted groups per service is usually low. + // + // /!\ item_was_encrypted should only be changed to true when appropriate, but never set to false here, since it can be true already for + // backward compatibility (truly encrypted item, instead of hashed grp id) + + for(ServerMsgMap::const_iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) + if(item->grpId == hashGrpId(it->first,item->PeerId())) + { + item->grpId = it->first ; + item->flag &= ~RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID; +#ifdef NXS_NET_DEBUG_0 + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "(II) de-hashed group ID " << it->first << " from hash " << item->grpId << " and peer id " << item->PeerId() << std::endl; +#endif + grp_is_known = true ; + item_was_encrypted = true ; + + return item->updateTS < it->second->msgUpdateTS ; + } + + return false ; + } + + ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(item->grpId); if(cit != mServerMsgUpdateMap.end()) { - const RsGxsServerMsgUpdateItem *msui = cit->second; + const RsGxsServerMsgUpdateItem *msui = cit->second; #ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - msui->msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < msui->msgUpdateTS) << std::endl; + GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - msui->msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < msui->msgUpdateTS) << std::endl; #endif - return item->updateTS < msui->msgUpdateTS ; + grp_is_known = true ; + return item->updateTS < msui->msgUpdateTS ; } + #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no local time stamp for this grp. "<< std::endl; #endif - + return false; } + void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_was_encrypted) { if (!item) @@ -4375,19 +4399,24 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_ RS_STACK_MUTEX(mNxsMutex) ; const RsPeerId& peer = item->PeerId(); + bool grp_is_known = false; + + bool peer_can_receive_update = locked_CanReceiveUpdate(item, grp_is_known,item_was_encrypted); // Insert the PeerId in suppliers list for this grpId #ifdef NXS_NET_DEBUG_6 GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "RsGxsNetService::handleRecvSyncMessage(): Inserting PeerId " << item->PeerId() << " in suppliers list for group " << item->grpId << std::endl; #endif - RsGroupNetworkStatsRecord& rec(mGroupNetworkStats[item->grpId]) ; // this creates it if needed - rec.suppliers.insert(peer) ; - #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "handleRecvSyncMsg(): Received last update TS of group " << item->grpId << ", for peer " << peer << ", TS = " << time(NULL) - item->updateTS << " secs ago." ; #endif - - if(!locked_CanReceiveUpdate(item)) + + if(grp_is_known) + { + RsGroupNetworkStatsRecord& rec(mGroupNetworkStats[item->grpId]) ; // this creates it if needed. When the grp is unknown (and hashed) this will would create a unused entry + rec.suppliers.insert(peer) ; + } + if(!peer_can_receive_update) { #ifdef NXS_NET_DEBUG_0 GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no update will be sent." << std::endl; diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index e9556701c..5875617dd 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -384,8 +384,10 @@ private: #endif bool locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item); - bool locked_CanReceiveUpdate(const RsNxsSyncMsgReqItem* item); + bool locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item, bool &grp_is_known, bool &item_was_encrypted); + static RsGxsGroupId hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) ; + private: typedef std::vector GrpFragments; diff --git a/libretroshare/src/serialiser/rsnxsitems.cc b/libretroshare/src/serialiser/rsnxsitems.cc index 1a7cf45b4..5f4770efc 100644 --- a/libretroshare/src/serialiser/rsnxsitems.cc +++ b/libretroshare/src/serialiser/rsnxsitems.cc @@ -13,8 +13,10 @@ const uint8_t RsNxsSyncGrpItem::FLAG_RESPONSE = 0x002; const uint8_t RsNxsSyncMsgItem::FLAG_REQUEST = 0x001; const uint8_t RsNxsSyncMsgItem::FLAG_RESPONSE = 0x002; -const uint8_t RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH = 0x001; -const uint8_t RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH = 0x001; +const uint8_t RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH = 0x0001; +const uint8_t RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH = 0x0001; + +const uint8_t RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID = 0x02; /** transaction state **/ const uint16_t RsNxsTransacItem::FLAG_BEGIN_P1 = 0x0001; diff --git a/libretroshare/src/serialiser/rsnxsitems.h b/libretroshare/src/serialiser/rsnxsitems.h index 6be81ecbe..7f5ff2438 100644 --- a/libretroshare/src/serialiser/rsnxsitems.h +++ b/libretroshare/src/serialiser/rsnxsitems.h @@ -348,12 +348,12 @@ public: #ifdef UNUSED_CODE static const uint8_t FLAG_USE_SYNC_HASH; #endif + static const uint8_t FLAG_USE_HASHED_GROUP_ID; RsNxsSyncMsgReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM) { clear(); return; } - virtual bool serialise(void *data,uint32_t& size) const; - virtual uint32_t serial_size() const; - + virtual bool serialise(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; virtual void clear(); virtual std::ostream &print(std::ostream &out, uint16_t indent);