/******************************************************************************* * libretroshare/src/rsserver: p3peers.cc * * * * libretroshare: retroshare core library * * * * Copyright (C) 2004-2008 Robert Fernie * * Copyright (C) 2015-2020 Gioacchino Mazzurco * * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #include "pgp/pgpkeyutil.h" #include "rsserver/p3peers.h" #include "rsserver/p3face.h" #include "pqi/p3linkmgr.h" #include "pqi/p3peermgr.h" #include "pqi/p3netmgr.h" #include "pqi/authssl.h" #include "pqi/authgpg.h" #include "retroshare/rsinit.h" #include "retroshare/rsnotify.h" #include "retroshare/rsfiles.h" #include "util/rsurl.h" #include "util/radix64.h" #include "util/rsbase64.h" #include "pgp/rscertificate.h" #include #include //static const int MAX_TIME_KEEP_LOCATION_WITHOUT_CONTACT = 30*24*3600 ; // 30 days. #include "pqi/authssl.h" const RetroshareInviteFlags RsPeers::defaultCertificateFlags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_LOCAL_IP | RetroshareInviteFlags::CURRENT_EXTERNAL_IP; typedef RsCertificate::RsShortInviteFieldType RsShortInviteFieldType; // locally in this file to avoid renaming everything. RsPeers *rsPeers = NULL; /******* * #define P3PEERS_DEBUG 1 *******/ //int ensureExtension(std::string &name, std::string def_ext); std::string RsPeerTrustString(uint32_t trustLvl) { std::string str; switch(trustLvl) { default: case RS_TRUST_LVL_UNKNOWN: str = "VALIDITY_UNKNOWN"; break; case RS_TRUST_LVL_UNDEFINED: str = "VALIDITY_UNDEFINED"; break; case RS_TRUST_LVL_NEVER: str = "VALIDITY_NEVER"; break; case RS_TRUST_LVL_MARGINAL: str = "VALIDITY_MARGINAL"; break; case RS_TRUST_LVL_FULL: str = "VALIDITY_FULL"; break; case RS_TRUST_LVL_ULTIMATE: str = "VALIDITY_ULTIMATE"; break; } return str; } std::string RsPeerNetModeString(uint32_t netModel) { std::string str; if (netModel == RS_NETMODE_EXT) { str = "External Port"; } else if (netModel == RS_NETMODE_UPNP) { str = "Ext (UPnP)"; } else if (netModel == RS_NETMODE_UDP) { str = "UDP Mode"; } else if (netModel == RS_NETMODE_HIDDEN) { str = "Hidden"; } else if (netModel == RS_NETMODE_UNREACHABLE) { str = "UDP Mode (Unreachable)"; } else { str = "Unknown NetMode"; } return str; } p3Peers::p3Peers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm) :mLinkMgr(lm), mPeerMgr(pm), mNetMgr(nm) {} /* Updates ... */ bool p3Peers::FriendsChanged(const RsPeerId& pid,bool add) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::FriendsChanged()" << std::endl; #endif if(rsEvents) { auto ev = std::make_shared(pid); rsEvents->postEvent(ev); } RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, add? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); // this is meant to disappear /* TODO */ return false; } bool p3Peers::OthersChanged() { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::OthersChanged()" << std::endl; #endif /* TODO */ return false; } /* Peer Details (Net & Auth) */ RsPeerId p3Peers::getOwnId() { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getOwnId()" << std::endl; #endif return AuthSSL::getAuthSSL()->OwnId(); } bool p3Peers::getOnlineList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getOnlineList()" << std::endl; #endif /* get from mConnectMgr */ mLinkMgr->getOnlineList(ids); return true; } bool p3Peers::getFriendList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getFriendList()" << std::endl; #endif /* get from mConnectMgr */ mLinkMgr->getFriendList(ids); return true; } //bool p3Peers::getOthersList(std::list &ids) //{ //#ifdef P3PEERS_DEBUG // std::cerr << "p3Peers::getOthersList()"; // std::cerr << std::endl; //#endif // // /* get from mAuthMgr */ // AuthSSL::getAuthSSL()->getAllList(ids); // return true; //} bool p3Peers::getPeersCount( uint32_t& peersCount, uint32_t& onlinePeersCount, bool countLocations ) { peersCount = mPeerMgr->getFriendCount(countLocations, false); onlinePeersCount = mPeerMgr->getFriendCount(countLocations, true); return true; } bool p3Peers::getPeerCount (unsigned int *friendCount, unsigned int *onlineCount, bool ssl) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerCount()" << std::endl; #endif if (friendCount) *friendCount = mPeerMgr->getFriendCount(ssl, false); if (onlineCount) *onlineCount = mPeerMgr->getFriendCount(ssl, true); return true; } bool p3Peers::isOnline(const RsPeerId &id) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::isOnline() " << id << std::endl; #endif /* get from mConnectMgr */ peerConnectState state; if (mLinkMgr->getFriendNetStatus(id, state) && (state.state & RS_PEER_S_CONNECTED)) { return true; } return false; } bool p3Peers::isFriend(const RsPeerId &ssl_id) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::isFriend() " << ssl_id << std::endl; #endif /* get from mConnectMgr */ return mPeerMgr->isFriend(ssl_id); } bool p3Peers::getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) { return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; } bool p3Peers::getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) { return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; } bool p3Peers::setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) { return mPeerMgr->setMaxRates(pid,maxUploadRate,maxDownloadRate) ; } bool p3Peers::haveSecretKey(const RsPgpId& id) { return AuthPGP::haveSecretKey(id); } /* There are too many dependancies of this function * to shift it immeidately */ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerDetails() called for id : " << id << std::endl; #endif RsPeerId sOwnId = AuthSSL::getAuthSSL()->OwnId(); peerState ps; if (id == sOwnId) { mPeerMgr->getOwnNetStatus(ps); ps.gpg_id = AuthPGP::getPgpOwnId(); } else if (!mPeerMgr->getFriendNetStatus(id, ps)) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerDetails() ERROR not an SSL Id: " << id << std::endl; #endif return false; } /* get from gpg (first), to fill in the sign and trust details */ /* don't return now, we've got fill in the ssl and connection info */ if(!getGPGDetails(ps.gpg_id, d)) { if(!ps.skip_pgp_signature_validation) return false; d.gpg_id = ps.gpg_id ; d.skip_pgp_signature_validation = true; } else d.skip_pgp_signature_validation = false; d.isOnlyGPGdetail = false; //get the ssl details d.id = id; d.location = ps.location; d.service_perm_flags = mPeerMgr->servicePermissionFlags(ps.gpg_id); /* generate */ d.authcode = "AUTHCODE"; /* fill from pcs */ d.lastConnect = ps.lastcontact; d.connectPeriod = 0; if (ps.hiddenNode) { d.isHiddenNode = true; d.hiddenNodeAddress = ps.hiddenDomain; d.hiddenNodePort = ps.hiddenPort; d.hiddenType = ps.hiddenType; if(sockaddr_storage_isnull(ps.localaddr)) // that happens if the address is not initialised. { d.localAddr = "INVALID_IP"; d.localPort = 0 ; } else { d.localAddr = sockaddr_storage_iptostring(ps.localaddr); d.localPort = sockaddr_storage_port(ps.localaddr); } d.extAddr = "hidden"; d.extPort = 0; d.dyndns = ""; } else { d.isHiddenNode = false; d.hiddenNodeAddress = ""; d.hiddenNodePort = 0; d.hiddenType = RS_HIDDEN_TYPE_NONE; if(!sockaddr_storage_isnull(ps.localaddr)) { sockaddr_storage_ipv6_to_ipv4(ps.localaddr); d.localAddr = sockaddr_storage_iptostring(ps.localaddr); d.localPort = sockaddr_storage_port(ps.localaddr); } else { d.localAddr = "INVALID_IP"; d.localPort = 0; } if(!sockaddr_storage_isnull(ps.serveraddr)) { sockaddr_storage_ipv6_to_ipv4(ps.serveraddr); d.extAddr = sockaddr_storage_iptostring(ps.serveraddr); d.extPort = sockaddr_storage_port(ps.serveraddr); } else { d.extAddr = "INVALID_IP"; d.extPort = 0; } d.dyndns = ps.dyndns; std::list::iterator it; for(it = ps.ipAddrs.mLocal.mAddrs.begin(); it != ps.ipAddrs.mLocal.mAddrs.end(); ++it) { sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); rs_sprintf_append(toto, " %ld sec loc", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) { sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); rs_sprintf_append(toto, " %ld sec ext", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } } switch(ps.netMode & RS_NET_MODE_ACTUAL) { case RS_NET_MODE_EXT: d.netMode = RS_NETMODE_EXT; break; case RS_NET_MODE_UPNP: d.netMode = RS_NETMODE_UPNP; break; case RS_NET_MODE_UDP: d.netMode = RS_NETMODE_UDP; break; case RS_NET_MODE_HIDDEN: d.netMode = RS_NETMODE_HIDDEN; break; case RS_NET_MODE_UNREACHABLE: case RS_NET_MODE_UNKNOWN: default: d.netMode = RS_NETMODE_UNREACHABLE; break; } d.vs_disc = ps.vs_disc; d.vs_dht = ps.vs_dht; /* Translate */ peerConnectState pcs; if (!mLinkMgr->getFriendNetStatus(id, pcs)) { if(id != sOwnId) std::cerr << "p3Peers::getPeerDetails() ERROR No Link Information : " << id << std::endl; return true; } #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl; #endif if (pcs.state & RS_PEER_S_CONNECTED) { sockaddr_storage_ipv6_to_ipv4(pcs.connectaddr); d.connectAddr = sockaddr_storage_iptostring(pcs.connectaddr); d.connectPort = sockaddr_storage_port(pcs.connectaddr); } else { d.connectAddr = ""; d.connectPort = 0 ; } d.state = 0; if (pcs.state & RS_PEER_S_FRIEND) d.state |= RS_PEER_STATE_FRIEND; if (pcs.state & RS_PEER_S_ONLINE) d.state |= RS_PEER_STATE_ONLINE; if (pcs.state & RS_PEER_S_CONNECTED) d.state |= RS_PEER_STATE_CONNECTED; if (pcs.state & RS_PEER_S_UNREACHABLE) d.state |= RS_PEER_STATE_UNREACHABLE; d.actAsServer = pcs.actAsServer; d.linkType = pcs.linkType; /* Finally determine AutoConnect Status */ d.foundDHT = pcs.dht.found; d.connectState = RS_PEER_CONNECTSTATE_OFFLINE; d.connectStateString.clear(); if (pcs.inConnAttempt) { if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { d.connectState = RS_PEER_CONNECTSTATE_TRYING_TCP; d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); } else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_UDP_ALL) { d.connectState = RS_PEER_CONNECTSTATE_TRYING_UDP; d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); } } else if (pcs.state & RS_PEER_S_CONNECTED) { /* peer is connected - determine how and set proper connectState */ if(mPeerMgr->isHidden()) { uint32_t type; /* hidden location */ /* use connection direction to determine connection type */ if(pcs.actAsServer) { /* incoming connection */ /* use own type to set connectState */ type = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); switch (type) { case RS_HIDDEN_TYPE_TOR: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; break; case RS_HIDDEN_TYPE_I2P: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; break; default: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; break; } } else { /* outgoing connection */ /* use peer hidden type to set connectState */ switch (ps.hiddenType) { case RS_HIDDEN_TYPE_TOR: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; break; case RS_HIDDEN_TYPE_I2P: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; break; default: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; break; } } } else if (ps.hiddenType & RS_HIDDEN_TYPE_MASK) { /* hidden peer */ /* use hidden type to set connectState */ switch (ps.hiddenType) { case RS_HIDDEN_TYPE_TOR: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; break; case RS_HIDDEN_TYPE_I2P: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; break; default: d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; break; } } else { /* peer and we are normal nodes */ /* use normal detection to set connectState */ if (pcs.connecttype == RS_NET_CONN_TCP_ALL) { d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TCP; } else if (pcs.connecttype == RS_NET_CONN_UDP_ALL) { d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UDP; } else { d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; } } } d.wasDeniedConnection = pcs.wasDeniedConnection; d.deniedTS = pcs.deniedTS; return true; } bool p3Peers::isProxyAddress(const uint32_t type, const sockaddr_storage& addr) { uint16_t port ; std::string string_addr; uint32_t status ; if(!getProxyServer(type, string_addr, port, status)) return false ; return sockaddr_storage_iptostring(addr)==string_addr && sockaddr_storage_port(addr)==port ; } bool p3Peers::isKeySupported(const RsPgpId& id) { return AuthPGP::isKeySupported(id); } std::string p3Peers::getGPGName(const RsPgpId &gpg_id) { /* get from mAuthMgr as it should have more peers? */ return AuthPGP::getPgpName(gpg_id); } bool p3Peers::isPgpFriend(const RsPgpId& pgpId) { return AuthPGP::isPGPAccepted(pgpId); } bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId) { bool has_ssl_only_flag = mPeerMgr->isSslOnlyFriend(sslId) ; if(has_ssl_only_flag) { if(isPgpFriend(getGPGId(sslId))) { RsErr() << __PRETTY_FUNCTION__ << ": Peer " << sslId << " has SSL-friend-only flag but his PGP id is in the list of friends. This is inconsistent (Bug in the code). Returning false for security reasons." << std::endl; return false; } return true; } return false; } bool p3Peers::isGPGAccepted(const RsPgpId &gpg_id_is_friend) { return isPgpFriend(gpg_id_is_friend); } std::string p3Peers::getPeerName(const RsPeerId& ssl) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerName() " << ssl_or_gpg_id << std::endl; #endif std::string name; if (ssl == AuthSSL::getAuthSSL()->OwnId()) return AuthPGP::getPgpOwnName(); if (mPeerMgr->getPeerName(ssl, name)) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPeerName() got a ssl id. Name is : " << name << std::endl; #endif return name; } return std::string() ; } bool p3Peers::getGPGAllList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getGPGAllList()" << std::endl; #endif /* get from mAuthMgr */ AuthPGP::getPgpAllList(ids); return true; } bool p3Peers::getGPGValidList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPGPOthersList()" << std::endl; #endif /* get from mAuthMgr */ AuthPGP::getPgpValidList(ids); return true; } bool p3Peers::getGPGSignedList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPGPOthersList()" << std::endl; #endif /* get from mAuthMgr */ AuthPGP::getPgpSignedList(ids); return true; } bool p3Peers::getPgpFriendList(std::vector& pgpIds) { std::list ids; if(AuthPGP::getPgpAcceptedList(ids)) { pgpIds.clear(); std::copy(ids.begin(), ids.end(), std::back_inserter(pgpIds)); return true; } return false; } bool p3Peers::getGPGAcceptedList(std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl; #endif AuthPGP::getPgpAcceptedList(ids); return true; } bool p3Peers::getAssociatedSSLIds(const RsPgpId &gpg_id, std::list &ids) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getAssociatedSSLIds() for id : " << gpg_id << std::endl; #endif return mPeerMgr->getAssociatedPeers(gpg_id, ids); } bool p3Peers::gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason /* = "" */) { return AuthPGP::SignDataBin(data,len,sign,signlen, reason); } RsPgpId p3Peers::pgpIdFromFingerprint(const RsPgpFingerprint& fpr) { return PGPHandler::pgpIdFromFingerprint(fpr); } bool p3Peers::getGPGDetails(const RsPgpId &pgp_id, RsPeerDetails &d) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPgpDetails() called for id : " << pgp_id << std::endl; #endif /* get from mAuthMgr */ bool res = AuthPGP::getPgpDetails(pgp_id, d); d.isOnlyGPGdetail = true ; d.service_perm_flags = mPeerMgr->servicePermissionFlags(pgp_id) ; return res ; } const RsPgpId& p3Peers::getGPGOwnId() { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPGPOwnId()" << std::endl; #endif /* get from mAuthMgr */ return AuthPGP::getPgpOwnId(); } RsPgpId p3Peers::getGPGId(const RsPeerId& sslid) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getPGPId()" << std::endl; #endif /* get from mAuthMgr */ if (sslid == AuthSSL::getAuthSSL()->OwnId()) { return AuthPGP::getPgpOwnId(); } peerState pcs; if (mPeerMgr->getFriendNetStatus(sslid, pcs)) return pcs.gpg_id; return RsPgpId(); } /* These Functions are now the only way to authorize a new gpg user... * if we are passed a ssl_id, then use it... otherwise just auth gpg_id */ /* Add/Remove Friends */ bool p3Peers::addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags perm_flags) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl; #endif if(AuthPGP::isPGPId(gpg_id)) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() Authorising GPG Id: " << gpg_id << std::endl; #endif if (AuthPGP::AllowConnection(gpg_id, true)) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() Authorization OK." << std::endl; #endif } else { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() Authorization FAILED." << std::endl; #endif return false; } } else { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() Bad gpg_id : " << gpg_id << std::endl; #endif return false; } if(ssl_id.isNull()) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addFriend() WARNING id is NULL or gpgId" << std::endl; #endif return true; } FriendsChanged(ssl_id,true); /* otherwise - we install as ssl_id..... * If we are adding an SSL certificate. we flag lastcontact as now. * This will cause the SSL certificate to be retained for 30 days... and give the person a chance to connect! * */ rstime_t now = time(NULL); return mPeerMgr->addFriend(ssl_id, gpg_id, RS_NET_MODE_UDP, RS_VS_DISC_FULL, RS_VS_DHT_FULL, now, perm_flags); } bool p3Peers::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id,const RsPeerDetails& details ) { if( mPeerMgr->addSslOnlyFriend(sslId, pgp_id,details)) { FriendsChanged(sslId,true); return true; } else return false; } bool p3Peers::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) { return AuthPGP::removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; } bool p3Peers::removeFriendLocation(const RsPeerId &sslId) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeFriendLocation() " << sslId << std::endl; #endif //will remove if it's a ssl id mPeerMgr->removeFriend(sslId, false); FriendsChanged(sslId,false); return true; } bool p3Peers::removeFriend(const RsPgpId& gpgId) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeFriend() " << gpgId << std::endl; #endif if (gpgId == AuthPGP::getPgpOwnId()) { std::cerr << "p3Peers::removeFriend() ERROR we're not going to remove our own GPG id." << std::endl; return false; } #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeFriend() Removing GPG Id: " << gpgId << std::endl; #endif if (AuthPGP::AllowConnection(gpgId, false)) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeFriend() OK." << std::endl; #endif mPeerMgr->removeAllFriendLocations(gpgId); return true; } else { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeFriend() FAILED." << std::endl; #endif mPeerMgr->removeAllFriendLocations(gpgId); return false; } } /* Network Stuff */ bool p3Peers::connectAttempt(const RsPeerId &id) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::connectAttempt() " << id << std::endl; #endif return mLinkMgr->retryConnect(id); } void p3Peers::getIPServersList(std::list& ip_servers) { mNetMgr->getIPServersList(ip_servers) ; } void p3Peers::getCurrentExtIPList(std::list& ip_list) { mNetMgr->getCurrentExtIPList(ip_list) ; } bool p3Peers::resetOwnExternalAddressList() { //TODO Phenom 2021-10-30: Need to call something like mNetMgr->netReset(); // to update this addresslist. return mPeerMgr->resetOwnExternalAddressList(); } void p3Peers::allowServerIPDetermination(bool b) { mNetMgr->setIPServersEnabled(b) ; } bool p3Peers::getAllowServerIPDetermination() { return mNetMgr->getIPServersEnabled() ; } bool p3Peers::setLocation(const RsPeerId &ssl_id, const std::string &location) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setLocation() " << ssl_id << std::endl; #endif return mPeerMgr->setLocation(ssl_id, location); } bool splitAddressString(const std::string &addr, std::string &domain, uint16_t &port) { std::cerr << "splitAddressString() Input: " << addr << std::endl; size_t cpos = addr.rfind(':'); if (cpos == std::string::npos) { std::cerr << "splitAddressString Failed to parse (:)"; std::cerr << std::endl; return false; } int lenport = addr.length() - (cpos + 1); // +1 to skip over : char. if (lenport <= 0) { std::cerr << "splitAddressString() Missing Port "; std::cerr << std::endl; return false; } domain = addr.substr(0, cpos); std::string portstr = addr.substr(cpos + 1, std::string::npos); int portint = atoi(portstr.c_str()); if ((portint < 0) || (portint > 65535)) { std::cerr << "splitAddressString() Invalid Port"; std::cerr << std::endl; return false; } port = portint; std::cerr << "splitAddressString() Domain: " << domain << " Port: " << port; std::cerr << std::endl; return true; } bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; #endif std::string domain; uint16_t port; if (!splitAddressString(hidden_node_address, domain, port)) { return false; } mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); mPeerMgr->setHiddenDomainPort(id, domain, port); return true; } bool p3Peers::isHiddenNode(const RsPeerId &id) { return mPeerMgr->isHiddenNode(id) ; } bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; #endif std::cerr << "p3Peers::setHiddenNode() Domain: " << address << " Port: " << port; std::cerr << std::endl; mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); mPeerMgr->setHiddenDomainPort(id, address, port); return true; } bool p3Peers::addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) { return mPeerMgr->addPeerLocator(ssl_id, locator); } bool p3Peers::setLocalAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port) { #ifdef P3PEERS_DEBUG std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " << port << std::endl; #endif sockaddr_storage addr; if (sockaddr_storage_inet_pton(addr, addr_str)) if (sockaddr_storage_setport(addr, port)) return mPeerMgr->setLocalAddress(id, addr); return false; } bool p3Peers::setExtAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port) { #ifdef P3PEERS_DEBUG std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " << port << std::endl; #endif sockaddr_storage addr; if (sockaddr_storage_inet_pton(addr, addr_str)) if (sockaddr_storage_setport(addr, port)) return mPeerMgr->setExtAddress(id, addr); return false; } bool p3Peers::setDynDNS(const RsPeerId &id, const std::string &dyndns) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setDynDNS() called with id: " << id << " dyndns: " << dyndns <setDynDNS(id, dyndns); } bool p3Peers::setNetworkMode(const RsPeerId &id, uint32_t extNetMode) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setNetworkMode() " << id << std::endl; #endif /* translate */ uint32_t netMode = 0; switch(extNetMode) { case RS_NETMODE_EXT: netMode = RS_NET_MODE_EXT; break; case RS_NETMODE_UPNP: netMode = RS_NET_MODE_UPNP; break; case RS_NETMODE_UDP: netMode = RS_NET_MODE_UDP; break; case RS_NETMODE_HIDDEN: netMode = RS_NET_MODE_HIDDEN; break; case RS_NETMODE_UNREACHABLE: netMode = RS_NET_MODE_UNREACHABLE; break; default: break; } return mPeerMgr->setNetworkMode(id, netMode); } bool p3Peers::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setVisState() " << id << std::endl; #endif std::cerr << "p3Peers::setVisState() " << id << " DISC: " << vs_disc; std::cerr << " DHT: " << vs_dht << std::endl; return mPeerMgr->setVisState(id, vs_disc, vs_dht); } bool p3Peers::getProxyServer(const uint32_t type, std::string &addr, uint16_t &port, uint32_t &status) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getProxyServer()" << std::endl; #endif struct sockaddr_storage proxy_addr; mPeerMgr->getProxyServerAddress(type, proxy_addr); addr = sockaddr_storage_iptostring(proxy_addr); port = sockaddr_storage_port(proxy_addr); mPeerMgr->getProxyServerStatus(type, status); return true; } bool p3Peers::setProxyServer(const uint32_t type, const std::string &addr_str, const uint16_t port) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::setProxyServer() " << std::endl; #endif if(port < 1024) { std::cerr << "(EE) attempt to set proxy server address to something not allowed: " << addr_str << ":" << port << std::endl; return false ; } std::cerr << "Setting proxy server address to " << addr_str << ":" << port << std::endl; struct sockaddr_storage addr; struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; addrv4p->sin_family = AF_INET; addrv4p->sin_port = htons(port); int ret = 1; /********************************** WINDOWS/UNIX SPECIFIC PART *******************/ #ifndef WINDOWS_SYS if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr)))) #else addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str()); if (ret) #endif /********************************** WINDOWS/UNIX SPECIFIC PART *******************/ { return mPeerMgr->setProxyServerAddress(type, addr); } else { std::cerr << "p3Peers::setProxyServer() Failed to Parse Address" << std::endl; } return false; } //=========================================================================== /* Auth Stuff */ std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures) { rs_owner_ptr mem_block = nullptr; size_t mem_block_size = 0; if( !AuthPGP::exportPublicKey( RsPgpId(pgp_id), mem_block, mem_block_size, false, include_signatures ) ) { RsErr() << __PRETTY_FUNCTION__ << " Failure retriving certificate for id " << pgp_id << std::endl; return ""; } RsPeerDetails details; if(!getGPGDetails(pgp_id, details)) return ""; auto certPtr = RsCertificate::fromMemoryBlock(details, mem_block, mem_block_size); free(mem_block); if(certPtr) return certPtr->armouredPGPKey(); return ""; } bool p3Peers::GetPGPBase64StringAndCheckSum( const RsPgpId& gpg_id, std::string& gpg_base64_string, std::string& gpg_base64_checksum ) { gpg_base64_string = "" ; gpg_base64_checksum = "" ; rs_owner_ptr mem_block = nullptr; size_t mem_block_size = 0; if(!AuthPGP::exportPublicKey( gpg_id,mem_block,mem_block_size,false,false )) return false; RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false); uint32_t crc = PGPKeyManagement::compute24bitsCRC(mem_block,mem_block_size); free(mem_block); unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ; RsBase64::encode(tmp, 3, gpg_base64_checksum, true, false); return true; } static void addPacketHeader(RsShortInviteFieldType ptag, size_t size, unsigned char *& buf, uint32_t& offset, uint32_t& buf_size) { // Check that the buffer has sufficient size. If not, increase it. while(offset + size + 6 >= buf_size) { unsigned char *newbuf = (unsigned char*)malloc(2*buf_size) ; memcpy(newbuf, buf, buf_size) ; buf_size *= 2 ; free(buf) ; buf = newbuf ; } // Write ptag and size buf[offset] = static_cast(ptag) ; offset += 1 ; offset += PGPKeyParser::write_125Size(&buf[offset],size) ; } bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, RetroshareInviteFlags invite_flags, const std::string& baseUrl ) { RsPeerId sslId = _sslId; if(sslId.isNull()) sslId = getOwnId(); RsPeerDetails tDetails; if(!getPeerDetails(sslId, tDetails)) return false; uint32_t buf_size = 100; uint32_t offset = 0; unsigned char *buf = (unsigned char*)malloc(buf_size); addPacketHeader(RsShortInviteFieldType::SSL_ID,RsPeerId::SIZE_IN_BYTES,buf,offset,buf_size); sslId.serialise(buf,buf_size,offset); addPacketHeader(RsShortInviteFieldType::PGP_FINGERPRINT,RsPgpFingerprint::SIZE_IN_BYTES,buf,offset,buf_size); tDetails.fpr.serialise(buf,buf_size,offset); addPacketHeader(RsShortInviteFieldType::PEER_NAME,tDetails.name.size(),buf,offset,buf_size); memcpy(&buf[offset],tDetails.name.c_str(),tDetails.name.size()); offset += tDetails.name.size(); /* If it is a hidden node, always use hidden address and port as locator */ if(tDetails.isHiddenNode) { addPacketHeader(RsShortInviteFieldType::HIDDEN_LOCATOR,4 + 2 + tDetails.hiddenNodeAddress.size(),buf,offset,buf_size); buf[offset+0] = (uint8_t)((tDetails.hiddenType >> 24) & 0xff); buf[offset+1] = (uint8_t)((tDetails.hiddenType >> 16) & 0xff); buf[offset+2] = (uint8_t)((tDetails.hiddenType >> 8) & 0xff); buf[offset+3] = (uint8_t)((tDetails.hiddenType ) & 0xff); buf[offset+4] = (uint8_t)((tDetails.hiddenNodePort >> 8) & 0xff); buf[offset+5] = (uint8_t)((tDetails.hiddenNodePort ) & 0xff); memcpy(&buf[offset+6],tDetails.hiddenNodeAddress.c_str(),tDetails.hiddenNodeAddress.size()); offset += 4 + 2 + tDetails.hiddenNodeAddress.size(); } if( !!(invite_flags & RetroshareInviteFlags::DNS) && !tDetails.dyndns.empty() && (tDetails.extPort || tDetails.localPort)) { uint16_t tPort = tDetails.extPort ? tDetails.extPort : tDetails.localPort; addPacketHeader(RsShortInviteFieldType::DNS_LOCATOR, 2 + tDetails.dyndns.size(),buf,offset,buf_size); buf[offset+0] = (uint8_t)((tPort >> 8) & 0xff); buf[offset+1] = (uint8_t)((tPort ) & 0xff); memcpy(&buf[offset+2],tDetails.dyndns.c_str(),tDetails.dyndns.size()); offset += 2 + tDetails.dyndns.size(); } if( !!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) && (!tDetails.ipAddressList.empty())) for(auto& s: tDetails.ipAddressList) { const std::string& tLc = s; std::string tLocator = tLc.substr(0, tLc.find_first_of(" ")); addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); offset += tLocator.size(); } else if( !!(invite_flags & (RetroshareInviteFlags::CURRENT_LOCAL_IP | RetroshareInviteFlags::CURRENT_EXTERNAL_IP) )) // only add at least the local and external IPs { #ifdef USE_NEW_LOCATOR_SYSTEM // This new locator system as some advantages, but here it also has major drawbacks: (1) it cannot differentiate local and external addresses, // and (2) it's quite larger than the old system, which tends to make certificates more than 1 line long. sockaddr_storage tLocal; if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && tDetails.localPort ) { addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.localAddr.size(),buf,offset,buf_size); memcpy(&buf[offset],tDetails.localAddr.c_str(),tDetails.localAddr.size()); offset += tDetails.localAddr.size(); } sockaddr_storage tExt; if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && tDetails.extPort ) { addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.extAddr.size(),buf,offset,buf_size); memcpy(&buf[offset],tDetails.extAddr.c_str(),tDetails.extAddr.size()); offset += tDetails.extAddr.size(); } #else if(!!(invite_flags & RetroshareInviteFlags::CURRENT_LOCAL_IP )) { sockaddr_storage tLocal; bool validLoc = sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && tDetails.localPort; bool isLocIpv4 = sockaddr_storage_ipv6_to_ipv4(tLocal); if(validLoc && isLocIpv4) { uint32_t t4Addr = reinterpret_cast(tLocal).sin_addr.s_addr; addPacketHeader(RsShortInviteFieldType::LOC4_LOCATOR, 4 + 2,buf,offset,buf_size); buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); buf[offset+4] = (uint8_t)((tDetails.localPort >> 8) & 0xff); buf[offset+5] = (uint8_t)((tDetails.localPort ) & 0xff); offset += 4+2; } } if(!!(invite_flags & RetroshareInviteFlags::CURRENT_EXTERNAL_IP )) { sockaddr_storage tExt; bool validExt = sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && tDetails.extPort; bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); if(validExt && isExtIpv4) { uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; addPacketHeader(RsShortInviteFieldType::EXT4_LOCATOR, 4 + 2,buf,offset,buf_size); buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); buf[offset+4] = (uint8_t)((tDetails.extPort >> 8) & 0xff); buf[offset+5] = (uint8_t)((tDetails.extPort ) & 0xff); offset += 4+2; } else if(validExt && !isExtIpv4) { // External address is IPv6, save it on LOCATOR sockaddr_storage_setport(tExt,tDetails.extPort); std::string tLocator = sockaddr_storage_tostring(tExt); addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); offset += tLocator.size(); } } #endif } uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,offset) ; // handle endian issues. unsigned char mem[3] ; mem[0] = computed_crc & 0xff ; mem[1] = (computed_crc >> 8 ) & 0xff ; mem[2] = (computed_crc >> 16) & 0xff ; addPacketHeader( RsShortInviteFieldType::CHECKSUM,3,buf,offset,buf_size); memcpy(&buf[offset],mem,3); offset += 3; Radix64::encode(buf, static_cast(offset), invite); if(!(invite_flags & RetroshareInviteFlags::RADIX_FORMAT)) { RsUrl inviteUrl(baseUrl); inviteUrl.setQueryKV("rsInvite", invite); invite = inviteUrl.toString(); } free(buf); return true; } bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& details, uint32_t &err_code ) { if(inviteStrUrl.empty()) { RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" << std::endl; return false; } std::string rsInvite = inviteStrUrl; RsUrl inviteUrl(inviteStrUrl); if(inviteUrl.hasQueryK("rsInvite")) rsInvite = *inviteUrl.getQueryV("rsInvite"); if(!RsCertificate::decodeRadix64ShortInvite(rsInvite, details, err_code)) return false; // Also check if the PGP key is available. If so, add it in the PeerDetails: RsPeerDetails pgp_det ; if(getGPGDetails(PGPHandler::pgpIdFromFingerprint(details.fpr),pgp_det) && pgp_det.fpr == details.fpr) { details.issuer = pgp_det.issuer; details.gpg_id = pgp_det.gpg_id; details.gpgSigners = pgp_det.gpgSigners; details.trustLvl = pgp_det.trustLvl; details.validLvl = pgp_det.validLvl; details.ownsign = pgp_det.ownsign; details.hasSignedMe = pgp_det.hasSignedMe; details.accept_connection = pgp_det.accept_connection; } else details.skip_pgp_signature_validation = true; if(details.gpg_id.isNull()) { err_code = CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT; return false; } err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; return true; } bool p3Peers::acceptInvite( const std::string& invite, ServicePermissionFlags flags ) { if(invite.empty()) return false; const std::string* radixPtr(&invite); RsUrl url(invite); std::map query(url.query()); if(query.find("radix") != query.end()) radixPtr = &query["radix"]; const std::string& radix(*radixPtr); if(radix.empty()) return false; RsPgpId pgpId; RsPeerId sslId; std::string errorString; if(!loadCertificateFromString(radix, sslId, pgpId, errorString)) return false; RsPeerDetails peerDetails; uint32_t errorCode; if(!loadDetailsFromStringCert(radix, peerDetails, errorCode)) return false; if(peerDetails.gpg_id.isNull()) return false; addFriend(peerDetails.id, peerDetails.gpg_id, flags); if (!peerDetails.location.empty()) setLocation(peerDetails.id, peerDetails.location); // Update new address even the peer already existed. if (peerDetails.isHiddenNode) { setHiddenNode( peerDetails.id, peerDetails.hiddenNodeAddress, peerDetails.hiddenNodePort ); } else { //let's check if there is ip adresses in the certificate. if (!peerDetails.extAddr.empty() && peerDetails.extPort) setExtAddress( peerDetails.id, peerDetails.extAddr, peerDetails.extPort ); if (!peerDetails.localAddr.empty() && peerDetails.localPort) setLocalAddress( peerDetails.id, peerDetails.localAddr, peerDetails.localPort ); if (!peerDetails.dyndns.empty()) setDynDNS(peerDetails.id, peerDetails.dyndns); for(auto&& ipr : peerDetails.ipAddressList) addPeerLocator( peerDetails.id, RsUrl(ipr.substr(0, ipr.find(' '))) ); } return true; } std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInviteFlags invite_flags) { #ifdef P3PEERS_DEBUG std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif const RsPeerId& ssl_id(sslId.isNull() ? getOwnId() : sslId); //add the sslid, location, ip local and external address after the signature RsPeerDetails detail; std::string invite; if (getPeerDetails(ssl_id, detail)) { if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) detail.ipAddressList.clear(); //Check if external address is IPv6, then move it to ipAddressList as RsCertificate only allow 4 numbers. sockaddr_storage tExt; bool validExt = sockaddr_storage_inet_pton(tExt, detail.extAddr) && sockaddr_storage_isValidNet(tExt) && detail.extPort; bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) && !detail.isHiddenNode && validExt && !isExtIpv4) { sockaddr_storage_setport(tExt,detail.extPort); detail.ipAddressList.push_front(sockaddr_storage_tostring(tExt) + " "); // Space needed to later parse. detail.extAddr = ""; //Clear it to not trigg error. detail.extPort = 0; } unsigned char *mem_block = nullptr; size_t mem_block_size = 0; if(!AuthPGP::exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) { std::cerr << "Cannot output certificate for id \"" << detail.gpg_id << "\". Sorry." << std::endl; return ""; } RsCertificate cert(detail, mem_block, mem_block_size); free(mem_block); return cert.toStdString(invite_flags); } #ifdef P3PEERS_DEBUG std::cerr << __PRETTY_FUNCTION__ << " returns : \n" << invite << std::endl; #endif return invite; } //=========================================================================== bool p3Peers::loadCertificateFromString( const std::string& cert, RsPeerId& ssl_id, RsPgpId& gpg_id, std::string& error_string ) { uint32_t errNum = 0; auto crt = RsCertificate::fromString(cert, errNum); if(!crt) { error_string = "RsCertificate failed with errno: " + std::to_string(errNum) + " parsing: " + cert; return false; } RsPgpId gpgid; bool res = AuthPGP::LoadCertificateFromString( crt->armouredPGPKey(), gpgid, error_string ); gpg_id = gpgid; ssl_id = crt->sslid(); // now get all friends who declare this key ID to be the one needed to check connections, and clear their "skip_pgp_signature_validation" flag if(res) { mPeerMgr->notifyPgpKeyReceived(gpgid); FriendsChanged(ssl_id,true); } return res; } bool p3Peers::loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string ) { bool res = AuthPGP::LoadPGPKeyFromBinaryData( bin_key_data,bin_key_len, gpg_id, error_string ); if(res) mPeerMgr->notifyPgpKeyReceived(gpg_id); return res; } bool p3Peers::loadDetailsFromStringCert( const std::string &certstr, RsPeerDetails &pd, uint32_t& error_code ) { Dbg3() << __PRETTY_FUNCTION__ << std::endl; auto certPtr = RsCertificate::fromString(certstr, error_code); if(!certPtr) return false; RsCertificate& cert = *certPtr; if(!AuthPGP::getPgpDetailsFromBinaryBlock( cert.pgp_key(), cert.pgp_key_size(), pd.gpg_id, pd.name, pd.gpgSigners )) return false; Dbg4() << __PRETTY_FUNCTION__ << " Parsing cert for sslid, location, ext " << " and local address details. : " << certstr << std::endl; pd.id = cert.sslid(); pd.location = cert.location_name_string(); pd.isOnlyGPGdetail = pd.id.isNull(); pd.service_perm_flags = RS_NODE_PERM_DEFAULT; if (!cert.hidden_node_string().empty()) { pd.isHiddenNode = true; std::string domain; uint16_t port; if (splitAddressString(cert.hidden_node_string(), domain, port)) { pd.hiddenNodeAddress = domain; pd.hiddenNodePort = port; pd.hiddenType = mPeerMgr->hiddenDomainToHiddenType(domain); } } else { pd.isHiddenNode = false; pd.localAddr = cert.loc_ip_string(); pd.localPort = cert.loc_port_us(); pd.extAddr = cert.ext_ip_string(); pd.extPort = cert.ext_port_us(); pd.dyndns = cert.dns_string(); for(const RsUrl& locator : cert.locators()) pd.ipAddressList.push_back(locator.toString()); } return true; } bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,bool& is_short_format,uint32_t& error_code,RsPeerDetails& details) { RsCertificate::Format format ; bool res = RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code,true,details) ; if(format == RsCertificate::RS_CERTIFICATE_RADIX) is_short_format = false; else if(format == RsCertificate::RS_CERTIFICATE_SHORT_RADIX) is_short_format = true; else return false ; return res; } std::string p3Peers::saveCertificateToString(const RsPeerId &id) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::SaveCertificateToString() " << id; std::cerr << std::endl; #endif if (id == AuthSSL::getAuthSSL()->OwnId()) { return AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); } else { return ""; } } bool p3Peers::signGPGCertificate(const RsPgpId &id, const std::string &gpg_passphrase) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::SignCertificate() " << id; std::cerr << std::endl; #endif rsNotify->cachePgpPassphrase(gpg_passphrase); rsNotify->setDisableAskPassword(true); bool res = AuthPGP::SignCertificateLevel0(id); rsNotify->clearPgpPassphrase(); rsNotify->setDisableAskPassword(false); return res; } bool p3Peers::trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::TrustCertificate() " << id; std::cerr << std::endl; #endif return AuthPGP::TrustCertificate(id, trustlvl); } /* Group Stuff */ bool p3Peers::addGroup(RsGroupInfo &groupInfo) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::addGroup()" << std::endl; #endif bool res = mPeerMgr->addGroup(groupInfo); rsFiles->updateSinceGroupPermissionsChanged() ; return res ; } bool p3Peers::editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::editGroup()" << std::endl; #endif bool res = mPeerMgr->editGroup(groupId, groupInfo); rsFiles->updateSinceGroupPermissionsChanged() ; return res ; } bool p3Peers::removeGroup(const RsNodeGroupId &groupId) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::removeGroup()" << std::endl; #endif bool res = mPeerMgr->removeGroup(groupId); rsFiles->updateSinceGroupPermissionsChanged() ; return res ; } bool p3Peers::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getGroupInfo()" << std::endl; #endif return mPeerMgr->getGroupInfoByName(groupName, groupInfo); } bool p3Peers::getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getGroupInfo()" << std::endl; #endif return mPeerMgr->getGroupInfo(groupId, groupInfo); } bool p3Peers::getGroupInfoList(std::list &groupInfoList) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::getGroupInfoList()" << std::endl; #endif return mPeerMgr->getGroupInfoList(groupInfoList); } bool p3Peers::assignPeerToGroup(const RsNodeGroupId &groupId, const RsPgpId& peerId, bool assign) { std::list peerIds; peerIds.push_back(peerId); return assignPeersToGroup(groupId, peerIds, assign); } bool p3Peers::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) { #ifdef P3PEERS_DEBUG std::cerr << "p3Peers::assignPeersToGroup()" << std::endl; #endif bool res = mPeerMgr->assignPeersToGroup(groupId, peerIds, assign); rsFiles->updateSinceGroupPermissionsChanged() ; return res ; } FileSearchFlags p3Peers::computePeerPermissionFlags(const RsPeerId& peer_ssl_id, FileStorageFlags share_flags, const std::list& directory_parent_groups) { // We should be able to do that in O(1), using groups based on packs of bits. // // But for now, because the implementation of groups is not totally decided yet, we revert to this // very simple algorithm. // bool found = directory_parent_groups.empty() ; // by default, empty list means browsable by everyone. RsPgpId pgp_id = getGPGId(peer_ssl_id) ; for(std::list::const_iterator it(directory_parent_groups.begin());it!=directory_parent_groups.end() && !found;++it) { RsGroupInfo info ; if(!getGroupInfo(*it,info)) { std::cerr << "(EE) p3Peers::computePeerPermissionFlags: no group named " << *it << ": cannot get info." << std::endl; continue ; } found = found || (info.peerIds.find(pgp_id) != info.peerIds.end()) ; //for(std::set::const_iterator it2(info.peerIds.begin());it2!=info.peerIds.end() && !found;++it2) // if(*it2 == pgp_id) // found = true ; } bool network_wide = (share_flags & DIR_FLAGS_ANONYMOUS_DOWNLOAD) ;//|| ( (share_flags & DIR_FLAGS_NETWORK_WIDE_GROUPS) && found) ; bool browsable = (share_flags & DIR_FLAGS_BROWSABLE) && found ; bool searchable = (share_flags & DIR_FLAGS_ANONYMOUS_SEARCH) ; FileSearchFlags final_flags ; if(network_wide) final_flags |= RS_FILE_HINTS_NETWORK_WIDE ; if(browsable ) final_flags |= RS_FILE_HINTS_BROWSABLE ; if(searchable ) final_flags |= RS_FILE_HINTS_SEARCHABLE ; return final_flags ; } RsPeerDetails::RsPeerDetails() :isOnlyGPGdetail(false), name(""),email(""),location(""), org(""),authcode(""), trustLvl(0), validLvl(0),skip_pgp_signature_validation(false),ownsign(false), hasSignedMe(false),accept_connection(false), state(0),actAsServer(false), connectPort(0), isHiddenNode(false), hiddenNodePort(0), hiddenType(RS_HIDDEN_TYPE_NONE), localAddr(""),localPort(0),extAddr(""),extPort(0),netMode(0),vs_disc(0), vs_dht(0), lastConnect(0),lastUsed(0),connectState(0),connectStateString(""), connectPeriod(0), foundDHT(false), wasDeniedConnection(false), deniedTS(0), linkType ( RS_NET_CONN_TRANS_TCP_UNKNOWN) {} RsGroupInfo::RsGroupInfo() : flag(0) {} ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPeerId& ssl_id) { return mPeerMgr->servicePermissionFlags(ssl_id) ; } ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPgpId& gpg_id) { return mPeerMgr->servicePermissionFlags(gpg_id) ; } void p3Peers::setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) { mPeerMgr->setServicePermissionFlags(gpg_id,flags) ; } RsPeerStateChangedEvent::RsPeerStateChangedEvent(RsPeerId sslId) : RsEvent(RsEventType::PEER_STATE_CHANGED), mSslId(sslId) {} RsPeers::~RsPeers() = default; RsAuthSslConnectionAutenticationEvent::~RsAuthSslConnectionAutenticationEvent() = default; RsConnectionEvent::~RsConnectionEvent() = default;