diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc index d0b3e54be..4ee9604f8 100644 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc +++ b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc @@ -312,9 +312,13 @@ void p3discovery2::sendOwnContactInfo(const RsPeerId &sslid) if (mPeerMgr->getOwnNetStatus(detail)) { RsDiscContactItem *pkt = new RsDiscContactItem(); + /* Cyril: we dont send our own IP to an hidden node. It will not use it - * anyway. */ + * anyway. Furthermore, a Tor node is not supposed to have any mean to send the IPs of his friend nodes + * to other nodes. This would be a very serious security risk. */ + populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); + /* G10h4ck: sending IP information also to hidden nodes has proven very * helpful in the usecase of non hidden nodes, that share a common * hidden trusted node, to discover each other IP. @@ -323,7 +327,6 @@ void p3discovery2::sendOwnContactInfo(const RsPeerId &sslid) * permission matrix. Disabling this instead will make life more * difficult for average user, that moreover whould have no way to * revert an hardcoded policy. */ - //populateContactInfo(detail, pkt, true); pkt->version = RS_HUMAN_READABLE_VERSION; pkt->PeerId(sslid); @@ -406,8 +409,13 @@ void p3discovery2::recvOwnContactInfo(const RsPeerId &fromId, const RsDiscContac // It is important that PGPList is received after the OwnContactItem. // This should happen, but is not enforced by the protocol. - // start peer list exchange. - sendPGPList(fromId); + // Start peer list exchange, if discovery is enabled + + peerState ps; + mPeerMgr->getOwnNetStatus(ps); + + if(ps.vs_disc != RS_VS_DISC_OFF) + sendPGPList(fromId); // Update mDiscStatus. RS_STACK_MUTEX(mDiscMtx); @@ -520,10 +528,17 @@ void p3discovery2::sendPGPList(const RsPeerId &toId) pkt->mode = RsGossipDiscoveryPgpListMode::FRIENDS; - std::map::const_iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) + for(auto it = mFriendList.begin(); it != mFriendList.end(); ++it) { - pkt->pgpIdSet.ids.insert(it->first); + // Check every friend, and only send his PGP key if the friend tells that he wants discovery. Because this info is done on the level of locations, + // we check each location and only send the key if at least one location allows it. + + for(auto it2(it->second.mSslIds.begin());it2!=it->second.mSslIds.end();++it2) + if(it2->second.mDiscStatus != RS_VS_DISC_OFF) + { + pkt->pgpIdSet.ids.insert(it->first); + break; + } } pkt->PeerId(toId); diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h index d7e0270f6..7975df289 100644 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h +++ b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h @@ -22,6 +22,57 @@ *******************************************************************************/ #pragma once +// +// p3GossipDiscovery is reponsible for facilitating the circulation of public keys between friend nodes. +// +// The service locally holds a cache that stores: +// * the list of friend profiles, in each of which the list of locations with their own discovery flag (which means whether they allow discovery or not) +// * the list of friend nodes, with their version number +// +// Data flow +// ========= +// +// statusChange(std::list&) // called by pqiMonitor when peers are added,removed, or recently connected +// | +// +---- sendOwnContactInfo(RsPeerId) // [On connection] sends own PgpId, discovery flag, list of own signed GxsIds +// | | +// | +---->[to friend] +// | +// +---- addFriend() / removeFriend() // [New/Removed friend] updates the list of friends, along with their own discovery flag +// +// tick() +// | +// +------ handleIncoming() +// | +// +-- recvOwnContactInfo(RsPeerId) // update location, IP addresses of a peer. +// | | +// | +------(if the peer has short_invite flag) +// | | | +// | | +---------requestPGPKey()->[to friend] // requests the full PGP public key, so as to be +// | | // able to validate connections. +// | | +// | +------(if disc != RS_VS_DISC_OFF) +// | | +// | +---------sendPgpList()->[to friend] // sends own list of friend profiles for which at least one location +// | // accepts discovery +// +-- processContactInfo(item->PeerId(), contact); +// | +// +-- recvIdentityList(Gxs Identity List) +// | +// +-- recvPGPCertificate(item->PeerId(), pgpkey); +// | +// +-- processPGPList(pgplist->PeerId(), pgplist); +// | +// +-- recvPGPCertificateRequest(pgplist->PeerId(), pgplist); +// +// Notes: +// * Tor nodes never send their own IP, and normal nodes never send their IP to Tor nodes either. +// A Tor node may accidentally know the IP of a normal node when it adds its certificate. However, the IP is dropped and not saved in this case. +// Generally speaking, no IP information should leave or transit through a Tor node. +// +// * the decision to call recvOwnContactInfo() or processContactInfo() depends on whether the item's peer id is the one the info is about. This is +// a bit unsafe. We should probably have to different items here especially if the information is not exactly the same. +// #include #include "retroshare/rsgossipdiscovery.h" @@ -38,7 +89,7 @@ class p3ServiceControl; struct DiscSslInfo { - DiscSslInfo() : mDiscStatus(0) {} + DiscSslInfo() : mDiscStatus(RS_VS_DISC_OFF) {} // default is to not allow discovery, until the peer tells about it uint16_t mDiscStatus; }; @@ -123,7 +174,6 @@ private: void rsEventsHandler(const RsEvent& event); RsEventsHandlerId_t mRsEventsHandle; - p3PeerMgr *mPeerMgr; p3LinkMgr *mLinkMgr; p3NetMgr *mNetMgr;