mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-02 14:16:16 -04:00
Merge pull request #188 from csoler/v0.6-SecuredTunnelService
V0.6 secured tunnel service. Please reports bugs to me (I have tested with valgrind and as many configurations as possible, but the multi-service gathering into GXS tunnels shared for each GXS id pair is not a totally simple thing, so I expect to have missed a few issues).
This commit is contained in:
commit
0ac76d621e
40 changed files with 3394 additions and 1458 deletions
File diff suppressed because it is too large
Load diff
|
@ -25,35 +25,38 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <turtle/turtleclientservice.h>
|
||||
#include <chat/rschatitems.h>
|
||||
#include <retroshare/rsmsgs.h>
|
||||
#include <retroshare/rsgxstunnel.h>
|
||||
|
||||
class RsGixs ;
|
||||
|
||||
static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ;
|
||||
|
||||
class DistantChatService: public RsTurtleClientService
|
||||
class DistantChatService: public RsGxsTunnelService::RsGxsTunnelClientService
|
||||
{
|
||||
public:
|
||||
DistantChatService(RsGixs *pids)
|
||||
: mGixs(pids), mDistantChatMtx("distant chat")
|
||||
// So, public interface only uses DistandChatPeerId, but internally, this is converted into a RsGxsTunnelService::RsGxsTunnelId
|
||||
|
||||
|
||||
DistantChatService() : mDistantChatMtx("distant chat")
|
||||
{
|
||||
mTurtle = NULL ;
|
||||
mGxsTunnels = NULL ;
|
||||
}
|
||||
|
||||
void flush() ;
|
||||
|
||||
virtual void connectToTurtleRouter(p3turtle *) ;
|
||||
// Overloaded methods from RsGxsTunnelClientService
|
||||
|
||||
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ;
|
||||
|
||||
// Creates the invite if the public key of the distant peer is available.
|
||||
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
|
||||
//
|
||||
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId &from_gxs_id, uint32_t &error_code) ;
|
||||
bool closeDistantChatConnexion(const RsGxsId& pid) ;
|
||||
virtual bool getDistantChatStatus(const RsGxsId &gxs_id,uint32_t &status, RsGxsId *from_gxs_id=NULL) ;
|
||||
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ;
|
||||
bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ;
|
||||
|
||||
virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ;
|
||||
|
||||
// derived in p3ChatService
|
||||
// derived in p3ChatService, so as to pass down some info
|
||||
virtual void handleIncomingItem(RsItem *) = 0;
|
||||
virtual bool handleRecvChatMsgItem(RsChatMsgItem *ci)=0 ;
|
||||
|
||||
|
@ -62,78 +65,25 @@ public:
|
|||
void handleRecvChatStatusItem(RsChatStatusItem *cs) ;
|
||||
|
||||
private:
|
||||
class DistantChatPeerInfo
|
||||
struct DistantChatContact
|
||||
{
|
||||
public:
|
||||
DistantChatPeerInfo() : last_contact(0), last_keep_alive_sent(0), status(0), direction(0)
|
||||
{
|
||||
memset(aes_key, 0, DISTANT_CHAT_AES_KEY_SIZE);
|
||||
}
|
||||
|
||||
time_t last_contact ; // used to keep track of working connexion
|
||||
time_t last_keep_alive_sent ; // last time we sent a keep alive packet.
|
||||
|
||||
unsigned char aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
|
||||
uint32_t status ; // info: do we have a tunnel ?
|
||||
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
|
||||
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
||||
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
||||
RsGxsId from_id ;
|
||||
RsGxsId to_id ;
|
||||
};
|
||||
|
||||
class DistantChatDHInfo
|
||||
{
|
||||
public:
|
||||
DistantChatDHInfo() : dh(0), direction(0), status(0) {}
|
||||
|
||||
DH *dh ;
|
||||
RsGxsId gxs_id ;
|
||||
RsTurtleGenericTunnelItem::Direction direction ;
|
||||
uint32_t status ;
|
||||
TurtleFileHash hash ;
|
||||
};
|
||||
|
||||
// This maps contains the current peers to talk to with distant chat.
|
||||
//
|
||||
std::map<RsGxsId, DistantChatPeerInfo> _distant_chat_contacts ; // current peers we can talk to
|
||||
std::map<RsPeerId,DistantChatDHInfo> _distant_chat_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc.
|
||||
std::map<DistantChatPeerId, DistantChatContact> mDistantChatContacts ; // current peers we can talk to
|
||||
|
||||
// List of items to be sent asap. Used to store items that we cannot pass directly to
|
||||
// sendTurtleData(), because of Mutex protection.
|
||||
// Overloaded from RsGxsTunnelClientService
|
||||
|
||||
virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ;
|
||||
virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ;
|
||||
|
||||
std::list<RsChatItem*> pendingDistantChatItems ;
|
||||
// Utility functions.
|
||||
|
||||
void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ;
|
||||
|
||||
// Overloaded from RsTurtleClientService
|
||||
|
||||
virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) ;
|
||||
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
|
||||
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
|
||||
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
|
||||
void markDistantChatAsClosed(const RsGxsId &gxs_id) ;
|
||||
void startClientDistantChatConnection(const RsGxsId &to_gxs_id,const RsGxsId& from_gxs_id) ;
|
||||
void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ;
|
||||
|
||||
//bool getHashFromVirtualPeerId(const TurtleVirtualPeerId& pid,RsFileHash& hash) ;
|
||||
|
||||
static TurtleFileHash hashFromGxsId(const RsGxsId& destination) ;
|
||||
static RsGxsId gxsIdFromHash(const TurtleFileHash& sum) ;
|
||||
|
||||
void handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) ;
|
||||
bool locked_sendDHPublicKey(const DH *dh, const RsGxsId &own_gxs_id, const RsPeerId &virtual_peer_id) ;
|
||||
bool locked_initDHSessionKey(DH *&dh);
|
||||
DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
|
||||
|
||||
|
||||
// Utility functions
|
||||
|
||||
void sendTurtleData(RsChatItem *) ;
|
||||
void sendEncryptedTurtleData(const uint8_t *buff,uint32_t rssize,const RsGxsId &gxs_id) ;
|
||||
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
|
||||
|
||||
static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside
|
||||
|
||||
p3turtle *mTurtle ;
|
||||
RsGixs *mGixs ;
|
||||
RsGxsTunnelService *mGxsTunnels ;
|
||||
|
||||
RsMutex mDistantChatMtx ;
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@ static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size
|
|||
// Images are 96x96, which makes approx. 27000 bytes uncompressed.
|
||||
|
||||
p3ChatService::p3ChatService(p3ServiceControl *sc,p3IdService *pids, p3LinkMgr *lm, p3HistoryMgr *historyMgr)
|
||||
:DistantChatService(pids),DistributedChatService(getServiceInfo().mServiceType,sc,historyMgr,pids), mChatMtx("p3ChatService"),mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
||||
: DistributedChatService(getServiceInfo().mServiceType,sc,historyMgr,pids), mChatMtx("p3ChatService"),mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
||||
{
|
||||
_serializer = new RsChatSerialiser() ;
|
||||
|
||||
|
@ -86,7 +86,7 @@ int p3ChatService::tick()
|
|||
receiveChatQueue();
|
||||
|
||||
DistributedChatService::flush() ;
|
||||
DistantChatService::flush() ;
|
||||
//DistantChatService::flush() ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -217,24 +217,25 @@ void p3ChatService::sendStatusString(const ChatId& id , const std::string& statu
|
|||
sendLobbyStatusString(id.toLobbyId(),status_string) ;
|
||||
else if(id.isBroadcast())
|
||||
sendGroupChatStatusString(status_string);
|
||||
else if(id.isPeerId() || id.isGxsId())
|
||||
{
|
||||
RsChatStatusItem *cs = new RsChatStatusItem ;
|
||||
else if(id.isPeerId() || id.isDistantChatId())
|
||||
{
|
||||
RsChatStatusItem *cs = new RsChatStatusItem ;
|
||||
|
||||
cs->status_string = status_string ;
|
||||
cs->flags = RS_CHAT_FLAG_PRIVATE ;
|
||||
RsPeerId vpid;
|
||||
if(id.isGxsId())
|
||||
vpid = RsPeerId(id.toGxsId());
|
||||
else
|
||||
vpid = id.toPeerId();
|
||||
cs->PeerId(vpid);
|
||||
cs->status_string = status_string ;
|
||||
cs->flags = RS_CHAT_FLAG_PRIVATE ;
|
||||
RsPeerId vpid;
|
||||
if(id.isDistantChatId())
|
||||
vpid = RsPeerId(id.toDistantChatId());
|
||||
else
|
||||
vpid = id.toPeerId();
|
||||
|
||||
cs->PeerId(vpid);
|
||||
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "sending chat status packet:" << std::endl ;
|
||||
cs->print(std::cerr) ;
|
||||
std::cerr << "sending chat status packet:" << std::endl ;
|
||||
cs->print(std::cerr) ;
|
||||
#endif
|
||||
sendChatItem(cs);
|
||||
sendChatItem(cs);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -284,12 +285,14 @@ void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg)
|
|||
|
||||
bool p3ChatService::isOnline(const RsPeerId& pid)
|
||||
{
|
||||
// check if the id is a tunnel id or a peer id.
|
||||
uint32_t status ;
|
||||
if(getDistantChatStatus(RsGxsId(pid),status))
|
||||
return status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||
// check if the id is a tunnel id or a peer id.
|
||||
|
||||
DistantChatPeerInfo dcpinfo;
|
||||
|
||||
if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo))
|
||||
return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||
else
|
||||
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
|
||||
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
|
||||
}
|
||||
|
||||
bool p3ChatService::sendChat(ChatId destination, std::string msg)
|
||||
|
@ -301,7 +304,7 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
|
|||
sendPublicChat(msg);
|
||||
return true;
|
||||
}
|
||||
else if(destination.isPeerId()==false && destination.isGxsId()==false)
|
||||
else if(destination.isPeerId()==false && destination.isDistantChatId()==false)
|
||||
{
|
||||
std::cerr << "p3ChatService::sendChat() Error: chat id type not handled. Is it empty?" << std::endl;
|
||||
return false;
|
||||
|
@ -313,8 +316,8 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
|
|||
#endif
|
||||
|
||||
RsPeerId vpid;
|
||||
if(destination.isGxsId())
|
||||
vpid = RsPeerId(destination.toGxsId()); // convert to virtual peer id
|
||||
if(destination.isDistantChatId())
|
||||
vpid = RsPeerId(destination.toDistantChatId()); // convert to virtual peer id
|
||||
else
|
||||
vpid = destination.toPeerId();
|
||||
|
||||
|
@ -378,7 +381,12 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
|
|||
#endif
|
||||
|
||||
RsServer::notify()->notifyChatMessage(message);
|
||||
mHistoryMgr->addMessage(message);
|
||||
|
||||
// cyril: history is temporarily diabled for distant chat, since we need to store the full tunnel ID, but then
|
||||
// at loading time, the ID is not known so that chat window shows 00000000 as a peer.
|
||||
|
||||
if(!message.chat_id.isDistantChatId())
|
||||
mHistoryMgr->addMessage(message);
|
||||
|
||||
checkSizeAndSendMessage(ci);
|
||||
|
||||
|
@ -497,11 +505,11 @@ void p3ChatService::handleIncomingItem(RsItem *item)
|
|||
return ; // don't delete! It's handled by handleRecvChatMsgItem in some specific cases only.
|
||||
}
|
||||
|
||||
if(DistantChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
|
||||
{
|
||||
delete item ;
|
||||
return ;
|
||||
}
|
||||
// if(DistantChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
|
||||
// {
|
||||
// delete item ;
|
||||
// return ;
|
||||
// }
|
||||
|
||||
if(DistributedChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
|
||||
{
|
||||
|
@ -749,7 +757,13 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci)
|
|||
cm.incoming = true;
|
||||
cm.online = true;
|
||||
RsServer::notify()->notifyChatMessage(cm);
|
||||
mHistoryMgr->addMessage(cm);
|
||||
|
||||
// cyril: history is temporarily diabled for distant chat, since we need to store the full tunnel ID, but then
|
||||
// at loading time, the ID is not known so that chat window shows 00000000 as a peer.
|
||||
|
||||
if(!cm.chat_id.isDistantChatId())
|
||||
mHistoryMgr->addMessage(cm);
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -766,7 +780,7 @@ void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
|||
std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ;
|
||||
#endif
|
||||
|
||||
uint32_t status;
|
||||
DistantChatPeerInfo dcpinfo;
|
||||
|
||||
if(cs->flags & RS_CHAT_FLAG_REQUEST_CUSTOM_STATE) // no state here just a request.
|
||||
sendCustomState(cs->PeerId()) ;
|
||||
|
@ -782,9 +796,9 @@ void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
|||
#endif
|
||||
sendCustomStateRequest(cs->PeerId()) ;
|
||||
}
|
||||
else if(DistantChatService::getDistantChatStatus(RsGxsId(cs->PeerId()), status))
|
||||
else if(DistantChatService::getDistantChatStatus(DistantChatPeerId(cs->PeerId()), dcpinfo))
|
||||
{
|
||||
RsServer::notify()->notifyChatStatus(ChatId(RsGxsId(cs->PeerId())), cs->status_string) ;
|
||||
RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())), cs->status_string) ;
|
||||
}
|
||||
else if(cs->flags & RS_CHAT_FLAG_PRIVATE)
|
||||
{
|
||||
|
@ -816,9 +830,9 @@ void p3ChatService::initChatMessage(RsChatMsgItem *c, ChatMessage &m)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t status;
|
||||
if(DistantChatService::getDistantChatStatus(RsGxsId(c->PeerId()), status))
|
||||
m.chat_id = ChatId(RsGxsId(c->PeerId()));
|
||||
DistantChatPeerInfo dcpinfo;
|
||||
if(DistantChatService::getDistantChatStatus(DistantChatPeerId(c->PeerId()), dcpinfo))
|
||||
m.chat_id = ChatId(DistantChatPeerId(c->PeerId()));
|
||||
|
||||
if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE)
|
||||
m.chatflags |= RS_CHAT_PRIVATE;
|
||||
|
|
|
@ -51,18 +51,6 @@ std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent)
|
|||
printRsItemEnd(out, "RsChatMsgItem", indent);
|
||||
return out;
|
||||
}
|
||||
std::ostream& RsChatDHPublicKeyItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsChatDHPublicKeyItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
printIndent(out, int_Indent);
|
||||
out << " Signature Key ID: " << signature.keyId << std::endl ;
|
||||
out << " Public Key ID: " << gxs_key.keyId << std::endl ;
|
||||
|
||||
printRsItemEnd(out, "RsChatMsgItem", indent);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& RsChatLobbyListItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
|
@ -277,7 +265,6 @@ RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize)
|
|||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: return new RsChatLobbyListRequestItem(data,*pktsize) ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: return new RsChatLobbyListItem(data,*pktsize) ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG: return new RsChatLobbyConfigItem(data,*pktsize) ;
|
||||
case RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY: return new RsChatDHPublicKeyItem(data,*pktsize) ;
|
||||
default:
|
||||
std::cerr << "Unknown packet type in chat!" << std::endl ;
|
||||
return NULL ;
|
||||
|
@ -437,17 +424,6 @@ uint32_t RsChatLobbyConfigItem::serial_size()
|
|||
return s;
|
||||
}
|
||||
|
||||
uint32_t RsChatDHPublicKeyItem::serial_size()
|
||||
{
|
||||
uint32_t s = 8 ; // header
|
||||
s += 4 ; // BN size
|
||||
s += BN_num_bytes(public_key) ; // public_key
|
||||
s += signature.TlvSize() ; // signature
|
||||
s += gxs_key.TlvSize() ; // gxs_key
|
||||
|
||||
return s ;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
RsChatAvatarItem::~RsChatAvatarItem()
|
||||
|
@ -459,41 +435,6 @@ RsChatAvatarItem::~RsChatAvatarItem()
|
|||
}
|
||||
}
|
||||
|
||||
bool RsChatDHPublicKeyItem::serialise(void *data,uint32_t& pktsize)
|
||||
{
|
||||
uint32_t tlvsize = serial_size() ;
|
||||
uint32_t offset = 0;
|
||||
|
||||
if (pktsize < tlvsize)
|
||||
return false; /* not enough space */
|
||||
|
||||
pktsize = tlvsize;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
|
||||
|
||||
/* skip the header */
|
||||
offset += 8;
|
||||
|
||||
uint32_t s = BN_num_bytes(public_key) ;
|
||||
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, s);
|
||||
|
||||
BN_bn2bin(public_key,&((unsigned char *)data)[offset]) ;
|
||||
offset += s ;
|
||||
|
||||
ok &= signature.SetTlv(data, tlvsize, &offset);
|
||||
ok &= gxs_key.SetTlv(data, tlvsize, &offset);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
ok = false;
|
||||
std::cerr << "RsChatDHPublicKeyItem::serialiseItem() Size Error! offset=" << offset << ", tlvsize=" << tlvsize << std::endl;
|
||||
}
|
||||
return ok ;
|
||||
}
|
||||
|
||||
/* serialise the data to the buffer */
|
||||
bool RsChatMsgItem::serialise(void *data, uint32_t& pktsize)
|
||||
{
|
||||
|
@ -995,28 +936,6 @@ bool RsChatLobbyConfigItem::serialise(void *data, uint32_t& pktsize)
|
|||
return ok;
|
||||
}
|
||||
|
||||
RsChatDHPublicKeyItem::RsChatDHPublicKeyItem(void *data,uint32_t /*size*/)
|
||||
: RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY)
|
||||
{
|
||||
uint32_t offset = 8; // skip the header
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
bool ok = true ;
|
||||
|
||||
uint32_t s=0 ;
|
||||
/* get mandatory parts first */
|
||||
ok &= getRawUInt32(data, rssize, &offset, &s);
|
||||
|
||||
public_key = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ;
|
||||
offset += s ;
|
||||
|
||||
ok &= signature.GetTlv(data, rssize, &offset) ;
|
||||
ok &= gxs_key.GetTlv(data, rssize, &offset) ;
|
||||
|
||||
if (offset != rssize)
|
||||
std::cerr << "RsChatDHPublicKeyItem::() Size error while deserializing." << std::endl ;
|
||||
if (!ok)
|
||||
std::cerr << "RsChatDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
|
||||
}
|
||||
RsChatMsgItem::RsChatMsgItem(void *data,uint32_t /*size*/,uint8_t subtype)
|
||||
: RsChatItem(subtype)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue