From 80a43fe3d59163b7f93092a5589bf1ca4f5897b0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 30 Jun 2018 21:52:25 +0200 Subject: [PATCH] added secure retrieval of distant groups --- libretroshare/src/gxs/rsgxsdataaccess.cc | 17 +++ libretroshare/src/gxs/rsgxsdataaccess.h | 8 ++ libretroshare/src/gxs/rsgxsnetservice.cc | 134 ++++++++++++++++++++++- libretroshare/src/gxs/rsgxsnetservice.h | 7 ++ libretroshare/src/gxs/rsgxsnettunnel.cc | 38 +++++-- libretroshare/src/gxs/rsnxs.h | 4 + 6 files changed, 199 insertions(+), 9 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc index 77c0d05d9..2ba317920 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ b/libretroshare/src/gxs/rsgxsdataaccess.cc @@ -1807,6 +1807,23 @@ bool RsGxsDataAccess::updateGroupData(RsNxsGrp* grp) { return mDataStore->updateGroup(grpM); } +bool RsGxsDataAccess::getGroupData(const RsGxsGroupId& grpId, RsNxsGrp *& grp_data) +{ + RsStackMutex stack(mDataMutex); + + std::map grps ; + + grps[grpId] = NULL ; + + if(mDataStore->retrieveNxsGrps(grps, false, true)) // the false here is very important: it removes the private key parts. + { + grp_data = grps.begin()->second; + return true; + } + else + return false ; +} + bool RsGxsDataAccess::addMsgData(RsNxsMsg* msg) { RsStackMutex stack(mDataMutex); diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h index 77f94137e..da5da3ca6 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ b/libretroshare/src/gxs/rsgxsdataaccess.h @@ -156,6 +156,14 @@ public: */ bool addMsgData(RsNxsMsg* msg); + /*! + * This retrieves a group from the gxs data base, this is a blocking call \n + * @param grp the group to add, memory ownership passed to the callee + * @return false if group cound not be retrieved + */ + bool getGroupData(const RsGxsGroupId& grpId,RsNxsGrp *& grp_data); + + public: diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc index 3c97cf95d..13d2341be 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ b/libretroshare/src/gxs/rsgxsnetservice.cc @@ -254,6 +254,7 @@ #include "retroshare/rsgxscircles.h" #include "retroshare/rspeers.h" #include "pgp/pgpauxutils.h" +#include "crypto/rscrypto.h" #include "util/rsdir.h" #include "util/rstime.h" #include "util/rsmemory.h" @@ -5105,7 +5106,10 @@ bool RsGxsNetService::locked_stampMsgServerUpdateTS(const RsGxsGroupId& gid) TurtleRequestId RsGxsNetService::turtleGroupRequest(const RsGxsGroupId& group_id) { - return mGxsNetTunnel->turtleGroupRequest(group_id,this) ; + TurtleRequestId req = mGxsNetTunnel->turtleGroupRequest(group_id,this) ; + mSearchRequests[req] = group_id; + + return req; } TurtleRequestId RsGxsNetService::turtleSearchRequest(const std::string& match_string) { @@ -5192,6 +5196,58 @@ void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req, const std: } } +void RsGxsNetService::receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len) +{ +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " received encrypted group data for turtle search request " << std::hex << req << std::dec << ": " << RsUtil::BinToHex(encrypted_group_data,encrypted_group_data_len,50) << std::endl; +#endif + auto it = mSearchRequests.find(req); + + if(mSearchRequests.end() == it) + { + std::cerr << "(EE) received search results for unknown request " << std::hex << req << std::dec ; + return; + } + RsGxsGroupId grpId = it->second; + + uint8_t encryption_master_key[32]; + Sha256CheckSum s = RsDirUtil::sha256sum(grpId.toByteArray(),grpId.SIZE_IN_BYTES); + memcpy(encryption_master_key,s.toByteArray(),32); + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " attempting data decryption with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; +#endif + unsigned char *clear_group_data = NULL; + uint32_t clear_group_data_len ; + + if(!librs::crypto::decryptAuthenticateData(encrypted_group_data,encrypted_group_data_len,encryption_master_key,clear_group_data,clear_group_data_len)) + { + std::cerr << "(EE) Could not decrypt data. Something went wrong. Wrong key??" << std::endl; + return ; + } + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " successfuly decrypted data : " << RsUtil::BinToHex(clear_group_data,clear_group_data_len,50) << std::endl; +#endif + RsItem *item = RsNxsSerialiser(mServType).deserialise(clear_group_data,&clear_group_data_len) ; + free(clear_group_data); + clear_group_data = NULL ; + + RsNxsGrp *nxs_grp = dynamic_cast(item) ; + + if(nxs_grp == NULL) + { + std::cerr << "(EE) decrypted item is not a RsNxsGrp. Weird!" << std::endl; + return ; + } + std::vector new_grps(1,nxs_grp); + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " passing the grp data to observer." << std::endl; +#endif + mObserver->receiveNewGroups(new_grps); +} + bool RsGxsNetService::search(const std::string& substring,std::list& group_infos) { RsGxsGrpMetaTemporaryMap grpMetaMap; @@ -5228,4 +5284,80 @@ bool RsGxsNetService::search(const std::string& substring,std::listsecond; + } + else + { + // Now check if the last request was too close in time, in which case, we dont retrieve data. + + if(mLastCacheReloadTS + 60 < time(NULL)) + { + std::cerr << "(WW) Not found in cache, and last cache reload less than 60 secs ago. Returning false. " << std::endl; + return false ; + } + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " reloading group cache information" << std::endl; +#endif + RsNxsGrpDataTemporaryMap grpDataMap; + { + RS_STACK_MUTEX(mNxsMutex) ; + mDataStore->retrieveNxsGrps(grpDataMap, true, true); + } + + for(auto it(grpDataMap.begin());it!=grpDataMap.end();++it) + if(it->second->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) // only cache subscribed groups + { + RsNxsGrp *grp = it->second ; + delete grp->metaData ; // clean private keys + grp->metaData = NULL ; + + Sha1CheckSum hash(RsDirUtil::sha1sum(it->first.toByteArray(),it->first.SIZE_IN_BYTES)); + + mGroupHashCache[hash] = grp ; + + if(hash == hashed_group_id) + grp_data = grp ; + } + } + + if(!grp_data) + { +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " no group found for hash " << hashed_group_id << ": returning false." << std::endl; +#endif + return false ; + } + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " found corresponding group data group id in cache group_id=" << grp_data->grpId << std::endl; +#endif + // Finally, serialize and encrypt the grp data + + uint32_t size = RsNxsSerialiser(mServType).size(grp_data); + RsTemporaryMemory mem(size) ; + + RsNxsSerialiser(mServType).serialise(grp_data,mem,&size) ; + + uint8_t encryption_master_key[32]; + Sha256CheckSum s = RsDirUtil::sha256sum(grp_data->grpId.toByteArray(),grp_data->grpId.SIZE_IN_BYTES); + memcpy(encryption_master_key,s.toByteArray(),32); + +#ifdef NXS_NET_DEBUG_8 + GXSNETDEBUG___ << " sending data encrypted with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; +#endif + return librs::crypto::encryptAuthenticateData(mem,size,encryption_master_key,encrypted_group_data,encrypted_group_data_len); +} diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h index d6496e795..9ab18b4d5 100644 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ b/libretroshare/src/gxs/rsgxsnetservice.h @@ -131,7 +131,10 @@ public: virtual TurtleRequestId turtleSearchRequest(const std::string& match_string); virtual bool search(const std::string& substring,std::list& group_infos) ; + virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len); virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos); + virtual void receiveTurtleSearchResults(TurtleRequestId req,const unsigned char *encrypted_group_data,uint32_t encrypted_group_data_len); + virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &group_infos); virtual bool clearDistantSearchResults(const TurtleRequestId& id); virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&,RsGxsGroupSummary&); @@ -609,6 +612,10 @@ private: uint32_t mDefaultMsgStorePeriod ; uint32_t mDefaultMsgSyncPeriod ; + + std::map mGroupHashCache; + std::map mSearchRequests; + time_t mLastCacheReloadTS ; }; #endif // RSGXSNETSERVICE_H diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc index cce855165..b6bf3c15a 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ b/libretroshare/src/gxs/rsgxsnettunnel.cc @@ -163,6 +163,27 @@ public: RsTypeSerializer::serial_process(j,ctx,group_infos,"group_infos") ; } }; +class RsGxsNetTunnelTurtleSearchGroupDataItem: public RsGxsNetTunnelItem +{ +public: + explicit RsGxsNetTunnelTurtleSearchGroupDataItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA) {} + virtual ~RsGxsNetTunnelTurtleSearchGroupDataItem() {} + + uint16_t service ; + unsigned char *encrypted_group_data ; + uint32_t encrypted_group_data_len ; + + virtual void clear() { free(encrypted_group_data);encrypted_group_data=NULL;encrypted_group_data_len=0; } + + virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) + { + RsTypeSerializer::serial_process(j,ctx,service,"service") ; + + RsTypeSerializer::TlvMemBlock_proxy prox(encrypted_group_data,encrypted_group_data_len) ; + RsTypeSerializer::serial_process(j,ctx,prox,"encrypted_group_data") ; + } +}; + class RsGxsNetTunnelSerializer: public RsServiceSerializer { public: @@ -184,7 +205,7 @@ public: case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING : return new RsGxsNetTunnelTurtleSearchSubstringItem; case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST : return new RsGxsNetTunnelTurtleSearchGroupRequestItem; case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY : return new RsGxsNetTunnelTurtleSearchGroupSummaryItem; - //case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA : return new RsGxsNetTunnelTurtleSearchGroupDataItem; + case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA : return new RsGxsNetTunnelTurtleSearchGroupDataItem; default: GXS_NET_TUNNEL_ERROR() << "type ID " << std::hex << (int)item_subtype << std::dec << " is not handled!" << std::endl; return NULL ; @@ -1033,20 +1054,22 @@ bool RsGxsNetTunnelService::receiveSearchRequest(unsigned char *search_request_d if(substring_gr != NULL) { -#ifdef TODO - auto it = mSearchableGxsServices.find(substring_sr->service) ; + RS_STACK_MUTEX(mGxsNetTunnelMtx); + auto it = mSearchableServices.find(substring_gr->service) ; - RsNxsGrp *grp = NULL ; + unsigned char *encrypted_group_data = NULL ; + uint32_t encrypted_group_data_len = 0 ; - if(it != mSearchableGxsServices.end() && it->second.search(substring_sr->group_id,grp)) + if(it != mSearchableServices.end() && it->second->search(substring_gr->hashed_group_id,encrypted_group_data,encrypted_group_data_len)) { RsGxsNetTunnelTurtleSearchGroupDataItem search_result_item ; search_result_item.service = substring_sr->service ; - search_result_item.group_infos = results ; + search_result_item.encrypted_group_data = encrypted_group_data ; + search_result_item.encrypted_group_data_len = encrypted_group_data_len; search_result_data_size = RsGxsNetTunnelSerializer().size(&search_result_item) ; - search_result_data = (unsigned char*)rs_malloc(size) ; + search_result_data = (unsigned char*)rs_malloc(search_result_data_size) ; if(search_result_data == NULL) return false ; @@ -1055,7 +1078,6 @@ bool RsGxsNetTunnelService::receiveSearchRequest(unsigned char *search_request_d return true ; } -#endif } return false ; diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h index 046b2e80f..7d617ee30 100644 --- a/libretroshare/src/gxs/rsnxs.h +++ b/libretroshare/src/gxs/rsnxs.h @@ -133,6 +133,7 @@ public: virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&,RsGxsGroupSummary&)=0; virtual bool search(const std::string& substring,std::list& group_infos) =0; + virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len)=0; /*! * Initiates a search through the network @@ -152,6 +153,9 @@ public: */ //virtual int searchGrps(RsGxsSearch* search, uint8_t hops = 1, bool retrieve = 0) = 0; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// DATA ACCESS FUNCTIONS /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*! * pauses synchronisation of subscribed groups and request for group id