mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-12 07:59:29 -05:00
fixed a few bugs in distant chat protocol (allow re-negociation of DH parameters if decryption fails, correct passing of own gxs id for server side), making the system more reactive. Also fixed the issue of avatar not showing up. Changed the tunnel naming system to something specific to distant chat. WARNING: this version cannot distant chat with previous versions.
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7943 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
7575ee8c31
commit
6e8e5efb90
4
TODO.txt
4
TODO.txt
@ -37,8 +37,8 @@ List of fixes/improvements before 0.6
|
||||
Chat
|
||||
[X] Distant chat window should show GXS avatars
|
||||
[ ] Distant chat should work with shared identities
|
||||
[ ] Distant chat fails (tunnel bullet never gets green) when re-openning a distant chat window after closing a tunnel
|
||||
[ ] Distant chat fails (chat window never appears) when re-openning a distant chat window after closing a tunnel
|
||||
[X] Distant chat fails (tunnel bullet never gets green) when re-openning a distant chat window after closing a tunnel
|
||||
[X] Distant chat fails (chat window never appears) when re-openning a distant chat window after closing a tunnel
|
||||
[X] You should not be enabled to distant-chat yourself!
|
||||
|
||||
Identities:
|
||||
|
@ -45,10 +45,14 @@
|
||||
#include <retroshare/rsids.h>
|
||||
#include "distantchat.h"
|
||||
|
||||
//#define DEBUG_DISTANT_CHAT
|
||||
#define DEBUG_DISTANT_CHAT
|
||||
|
||||
static const uint32_t DISTANT_CHAT_KEEP_ALIVE_TIMEOUT = 15 ; // send keep alive packet so as to avoid tunnel breaks.
|
||||
|
||||
static const uint32_t RS_DISTANT_CHAT_DH_STATUS_UNINITIALIZED = 0x0000 ;
|
||||
static const uint32_t RS_DISTANT_CHAT_DH_STATUS_HALF_KEY_DONE = 0x0001 ;
|
||||
static const uint32_t RS_DISTANT_CHAT_DH_STATUS_KEY_AVAILABLE = 0x0002 ;
|
||||
|
||||
void DistantChatService::connectToTurtleRouter(p3turtle *tr)
|
||||
{
|
||||
mTurtle = tr ;
|
||||
@ -161,6 +165,9 @@ bool DistantChatService::handleTunnelRequest(const RsFileHash& hash,const RsPeer
|
||||
std::list<RsGxsId> own_id_list ;
|
||||
rsIdentity->getOwnIds(own_id_list) ;
|
||||
|
||||
// re-computing the hash from the GXS id allows to dynamically change the hash. That will allow
|
||||
// the use of a contact passphrase, if needed.
|
||||
|
||||
for(std::list<RsGxsId>::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it)
|
||||
if(hashFromGxsId(*it) == hash)
|
||||
{
|
||||
@ -184,11 +191,22 @@ void DistantChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleV
|
||||
{
|
||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
if( _distant_chat_virtual_peer_ids.find(virtual_peer_id) != _distant_chat_virtual_peer_ids.end())
|
||||
{
|
||||
std::cerr << " Tunnel already registered for " << hash << " and virtual peer " << virtual_peer_id << ". Doing nothing." << std::endl;
|
||||
return ;
|
||||
}
|
||||
DistantChatDHInfo& dhinfo( _distant_chat_virtual_peer_ids[virtual_peer_id] ) ;
|
||||
dhinfo.gxs_id.clear() ;
|
||||
|
||||
if(dhinfo.dh != NULL)
|
||||
DH_free(dhinfo.dh) ;
|
||||
|
||||
dhinfo.dh = NULL ;
|
||||
dhinfo.direction = dir ;
|
||||
dhinfo.hash = hash ;
|
||||
dhinfo.status = RS_DISTANT_CHAT_DH_STATUS_UNINITIALIZED ;
|
||||
|
||||
// if( _distant_chat_virtual_peer_ids.find(virtual_peer_id) != _distant_chat_virtual_peer_ids.end())
|
||||
// {
|
||||
// std::cerr << " Tunnel already registered for " << hash << " and virtual peer " << virtual_peer_id << ". Doing nothing." << std::endl;
|
||||
// return ;
|
||||
// }
|
||||
|
||||
if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
||||
{
|
||||
@ -217,12 +235,10 @@ void DistantChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleV
|
||||
own_gxs_id = it->second.own_gxs_id ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Creating new virtual peer ID entry and empty DH session key." << std::endl;
|
||||
#endif
|
||||
|
||||
DistantChatDHInfo& dhinfo( _distant_chat_virtual_peer_ids[virtual_peer_id] ) ;
|
||||
dhinfo.gxs_id.clear() ;
|
||||
dhinfo.dh = NULL ;
|
||||
dhinfo.direction = dir ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
@ -232,23 +248,27 @@ void DistantChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleV
|
||||
// Start a new DH session for this tunnel
|
||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
DH *& dh(_distant_chat_virtual_peer_ids[virtual_peer_id].dh) ;
|
||||
locked_restartDHSession(virtual_peer_id,own_gxs_id) ;
|
||||
}
|
||||
|
||||
void DistantChatService::locked_restartDHSession(const RsPeerId& virtual_peer_id,const RsGxsId& own_gxs_id)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Starting new DH session." << std::endl;
|
||||
std::cerr << "Starting new DH session." << std::endl;
|
||||
#endif
|
||||
DistantChatDHInfo& dhinfo = _distant_chat_virtual_peer_ids[virtual_peer_id] ;
|
||||
|
||||
if(!locked_initDHSessionKey(dh))
|
||||
dhinfo.status = RS_DISTANT_CHAT_DH_STATUS_UNINITIALIZED ;
|
||||
|
||||
if(!locked_initDHSessionKey(dhinfo.dh))
|
||||
{
|
||||
std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl;
|
||||
return ;
|
||||
}
|
||||
dhinfo.status = RS_DISTANT_CHAT_DH_STATUS_HALF_KEY_DONE ;
|
||||
|
||||
if(!locked_sendDHPublicKey(dh,own_gxs_id,virtual_peer_id))
|
||||
{
|
||||
if(!locked_sendDHPublicKey(dhinfo.dh,own_gxs_id,virtual_peer_id))
|
||||
std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
void DistantChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
|
||||
@ -332,17 +352,6 @@ void DistantChatService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
|
||||
std::cerr << "(EE) item is not a data item. That is an error." << std::endl;
|
||||
return ;
|
||||
}
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " size = " << item->data_size << std::endl;
|
||||
std::cerr << " data = " << (void*)item->data_bytes << std::endl;
|
||||
std::cerr << " IV = " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
|
||||
std::cerr << " data = " ;
|
||||
|
||||
printBinaryData(item->data_bytes,item->data_size) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
// Call the AES crypto module
|
||||
// - the IV is the first 8 bytes of item->data_bytes
|
||||
|
||||
@ -351,72 +360,21 @@ void DistantChatService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
|
||||
std::cerr << "(EE) item encrypted data stream is too small: size = " << item->data_size << std::endl;
|
||||
return ;
|
||||
}
|
||||
uint32_t decrypted_size = RsAES::get_buffer_size(item->data_size-8);
|
||||
uint8_t *decrypted_data = new uint8_t[decrypted_size];
|
||||
bool decrypted = false ;
|
||||
|
||||
unsigned char no_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
memset(no_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
if(RsAES::aes_decrypt_8_16((uint8_t*)item->data_bytes+8,item->data_size-8,no_key,(uint8_t*)item->data_bytes,decrypted_data,decrypted_size))
|
||||
if(*((uint64_t*)item->data_bytes) != 0)
|
||||
{
|
||||
decrypted = true ;
|
||||
std::cerr << " Item is encrypted." << std::endl;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Data is not encrypted. Probably a DH session key." << std::endl;
|
||||
#endif
|
||||
// if cannot decrypt, it means the key is wrong. We need to re-negociate a new key.
|
||||
|
||||
handleEncryptedData((uint8_t*)item->data_bytes,item->data_size,hash,virtual_peer_id) ;
|
||||
}
|
||||
RsGxsId gxs_id ;
|
||||
|
||||
if(!decrypted)
|
||||
else
|
||||
{
|
||||
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
{
|
||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
std::map<RsPeerId,DistantChatDHInfo>::const_iterator it = _distant_chat_virtual_peer_ids.find(virtual_peer_id) ;
|
||||
|
||||
if(it == _distant_chat_virtual_peer_ids.end())
|
||||
{
|
||||
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
gxs_id = it->second.gxs_id ;
|
||||
std::map<RsGxsId,DistantChatPeerInfo>::iterator it2 = _distant_chat_contacts.find(gxs_id) ;
|
||||
|
||||
if(it2 == _distant_chat_contacts.end())
|
||||
{
|
||||
std::cerr << "(EE) no GXS id data for ID=" << gxs_id << ". This is a bug." << std::endl;
|
||||
return ;
|
||||
}
|
||||
memcpy(aes_key,it2->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Using IV: " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
|
||||
std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl;
|
||||
std::cerr << " key : " ; printBinaryData(aes_key,16) ; std::cerr << std::endl;
|
||||
std::cerr << " data : " ; printBinaryData(item->data_bytes,item->data_size) ; std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if(!RsAES::aes_decrypt_8_16((uint8_t*)item->data_bytes+8,item->data_size-8,aes_key,(uint8_t*)item->data_bytes,decrypted_data,decrypted_size))
|
||||
{
|
||||
std::cerr << "(EE) packet decryption failed." << std::endl;
|
||||
delete[] decrypted_data ;
|
||||
return ;
|
||||
}
|
||||
it2->second.status = RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||
it2->second.last_contact = time(NULL) ;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "(II) Decrypted data: size=" << decrypted_size << std::endl;
|
||||
#endif
|
||||
std::cerr << " Item is not encrypted." << std::endl;
|
||||
|
||||
// Now try deserialise the decrypted data to make an RsItem out of it.
|
||||
//
|
||||
RsItem *citem = RsChatSerialiser().deserialise(decrypted_data,&decrypted_size) ;
|
||||
delete[] decrypted_data ;
|
||||
RsItem *citem = RsChatSerialiser().deserialise(&((uint8_t*)item->data_bytes)[8],&item->data_size) ;
|
||||
|
||||
if(citem == NULL)
|
||||
{
|
||||
@ -428,14 +386,104 @@ void DistantChatService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,cons
|
||||
// case only.
|
||||
|
||||
if(dynamic_cast<RsChatDHPublicKeyItem*>(citem) != NULL)
|
||||
{
|
||||
citem->PeerId(virtual_peer_id) ;
|
||||
handleIncomingItem(citem) ;
|
||||
}
|
||||
else
|
||||
std::cerr << "(EE) Deserialiased item has unexpected type." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DistantChatService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "handleEncryptedDataItem()" << std::endl;
|
||||
std::cerr << " size = " << data_size << std::endl;
|
||||
std::cerr << " data = " << (void*)data_bytes << std::endl;
|
||||
std::cerr << " IV = " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl;
|
||||
std::cerr << " data = " ;
|
||||
|
||||
printBinaryData((uint8_t*)data_bytes,data_size) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
RsItem *citem = NULL;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
uint32_t decrypted_size = RsAES::get_buffer_size(data_size-8);
|
||||
uint8_t *decrypted_data = new uint8_t[decrypted_size];
|
||||
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
|
||||
std::map<RsPeerId,DistantChatDHInfo>::iterator it = _distant_chat_virtual_peer_ids.find(virtual_peer_id) ;
|
||||
|
||||
if(it == _distant_chat_virtual_peer_ids.end())
|
||||
{
|
||||
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl;
|
||||
return true ;
|
||||
}
|
||||
|
||||
RsGxsId gxs_id = it->second.gxs_id ;
|
||||
std::map<RsGxsId,DistantChatPeerInfo>::iterator it2 = _distant_chat_contacts.find(gxs_id) ;
|
||||
|
||||
if(it2 == _distant_chat_contacts.end())
|
||||
{
|
||||
std::cerr << "(EE) no GXS id data for ID=" << gxs_id << ". This is a bug." << std::endl;
|
||||
return true ;
|
||||
}
|
||||
memcpy(aes_key,it2->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Using IV: " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl;
|
||||
std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl;
|
||||
std::cerr << " key : " ; printBinaryData(aes_key,16) ; std::cerr << std::endl;
|
||||
std::cerr << " data : " ; printBinaryData((uint8_t*)data_bytes,data_size) ; std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if(!RsAES::aes_decrypt_8_16((uint8_t*)data_bytes+8,data_size-8,aes_key,(uint8_t*)data_bytes,decrypted_data,decrypted_size))
|
||||
{
|
||||
std::cerr << "(EE) packet decryption failed." << std::endl;
|
||||
std::cerr << "(EE) resetting new DH session." << std::endl;
|
||||
|
||||
delete[] decrypted_data ;
|
||||
|
||||
locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
it2->second.status = RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||
it2->second.last_contact = time(NULL) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "(II) Decrypted data: size=" << decrypted_size << std::endl;
|
||||
#endif
|
||||
|
||||
// Now try deserialise the decrypted data to make an RsItem out of it.
|
||||
//
|
||||
citem = RsChatSerialiser().deserialise(decrypted_data,&decrypted_size) ;
|
||||
delete[] decrypted_data ;
|
||||
|
||||
if(citem == NULL)
|
||||
{
|
||||
std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// DH key items are sent even before we know who we speak to, so the virtual peer id is used in this
|
||||
// case only.
|
||||
|
||||
citem->PeerId(RsPeerId(gxs_id)) ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "(II) Setting peer id to " << citem->PeerId() << std::endl;
|
||||
#endif
|
||||
handleIncomingItem(citem) ; // Treats the item, and deletes it
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
@ -448,7 +496,6 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
// Look for the current state of the key agreement.
|
||||
|
||||
TurtleVirtualPeerId vpid = item->PeerId() ;
|
||||
TurtleFileHash hash ;
|
||||
|
||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
@ -524,6 +571,15 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
std::cerr << " (EE) no DH information for that peer. This is an error." << std::endl;
|
||||
return ;
|
||||
}
|
||||
if(it->second.status == RS_DISTANT_CHAT_DH_STATUS_KEY_AVAILABLE)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " DH Session already set for this tunnel. Re-initing a new session!" << std::endl;
|
||||
#endif
|
||||
|
||||
locked_restartDHSession(vpid,_distant_chat_contacts[senders_id].own_gxs_id) ;
|
||||
}
|
||||
|
||||
// gets current key params. By default, should contain all null pointers.
|
||||
//
|
||||
it->second.gxs_id = senders_id ;
|
||||
@ -538,10 +594,11 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
std::cerr << " (EE) DH computation failed. Probably a bug. Error code=" << ERR_get_error() << std::endl;
|
||||
return ;
|
||||
}
|
||||
it->second.status == RS_DISTANT_CHAT_DH_STATUS_KEY_AVAILABLE ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " DH key computation successed. New key in place." << std::endl;
|
||||
#endif
|
||||
|
||||
DistantChatPeerInfo& pinfo(_distant_chat_contacts[senders_id]) ;
|
||||
|
||||
// Now hash the key buffer into a 16 bytes key.
|
||||
@ -556,6 +613,9 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
pinfo.virtual_peer_id = vpid ;
|
||||
pinfo.direction = it->second.direction ;
|
||||
|
||||
if(pinfo.direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
||||
pinfo.own_gxs_id = gxsIdFromHash(it->second.hash) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " DH key computed. Tunnel is now secured!" << std::endl;
|
||||
std::cerr << " Key computed: " ; printBinaryData(pinfo.aes_key,16) ; std::cerr << std::endl;
|
||||
@ -703,62 +763,84 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||
std::cerr << "DistantChatService::sendTurtleData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl;
|
||||
#endif
|
||||
|
||||
if(dynamic_cast<RsChatDHPublicKeyItem*>(item) != NULL)
|
||||
{
|
||||
// make a TurtleGenericData item out of it, and send it in clear.
|
||||
//
|
||||
RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ;
|
||||
|
||||
uint32_t rssize = item->serial_size() ;
|
||||
|
||||
gitem->data_size = rssize + 8 ;
|
||||
gitem->data_bytes = malloc(rssize+8) ;
|
||||
|
||||
memset(gitem->data_bytes,0,8) ;
|
||||
|
||||
if(!item->serialise(&((uint8_t*)gitem->data_bytes)[8],rssize))
|
||||
{
|
||||
std::cerr << "(EE) Could not serialise item!!!" << std::endl;
|
||||
delete gitem ;
|
||||
delete item ;
|
||||
return ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " DistantChatService::sendTurtleData(): Sending clear data to virtual peer: " << item->PeerId() << std::endl;
|
||||
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
|
||||
std::cerr << " data = " ;
|
||||
printBinaryData(gitem->data_bytes,gitem->data_size) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
mTurtle->sendTurtleData(item->PeerId(),gitem) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t rssize = item->serial_size();
|
||||
uint8_t *buff = new uint8_t[rssize] ;
|
||||
uint8_t *buff = (uint8_t*)malloc(rssize) ;
|
||||
|
||||
if(!item->serialise(buff,rssize))
|
||||
{
|
||||
std::cerr << "(EE) DistantChatService::sendTurtleData(): Could not serialise item!" << std::endl;
|
||||
delete[] buff ;
|
||||
delete item ;
|
||||
return ;
|
||||
}
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Serialized item has size " << rssize << std::endl;
|
||||
#endif
|
||||
|
||||
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
uint64_t IV ;
|
||||
TurtleVirtualPeerId virtual_peer_id ;
|
||||
sendEncryptedTurtleData(buff,rssize,RsGxsId(item->PeerId())) ;
|
||||
|
||||
if(dynamic_cast<RsChatDHPublicKeyItem*>(item))
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Packet is a DH session key. Using Peer Id " << item->PeerId() << " as virtual peer id" << std::endl;
|
||||
#endif
|
||||
virtual_peer_id = item->PeerId() ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Special item DH session key --> will be sent unencrypted." << std::endl ;
|
||||
#endif
|
||||
memset(aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
IV = 0 ;
|
||||
free(buff) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete item ;
|
||||
}
|
||||
|
||||
void DistantChatService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rssize,const RsGxsId& gxs_id)
|
||||
{
|
||||
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
uint64_t IV = 0;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Packet is a normal chat message. Sending to GXS id " << item->PeerId() << std::endl;
|
||||
std::cerr << "Sending encrypted data to virtual gxs id " << gxs_id << std::endl;
|
||||
#endif
|
||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsGxsId,DistantChatPeerInfo>::iterator it = _distant_chat_contacts.find(RsGxsId(item->PeerId())) ;
|
||||
std::map<RsGxsId,DistantChatPeerInfo>::iterator it = _distant_chat_contacts.find(gxs_id) ;
|
||||
|
||||
if(it == _distant_chat_contacts.end())
|
||||
{
|
||||
std::cerr << "(EE) Cannot find contact key info for ID " << item->PeerId() << ". Cannot send message!" << std::endl;
|
||||
delete[] buff ;
|
||||
std::cerr << "(EE) Cannot find contact key info for ID " << gxs_id << ". Cannot send message!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
if(it->second.status != RS_DISTANT_CHAT_STATUS_CAN_TALK)
|
||||
{
|
||||
std::cerr << "(EE) Cannot talk to " << item->PeerId() << ". Tunnel status is: " << it->second.status << std::endl;
|
||||
delete[] buff ;
|
||||
std::cerr << "(EE) Cannot talk to " << gxs_id << ". Tunnel status is: " << it->second.status << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
virtual_peer_id = it->second.virtual_peer_id ;
|
||||
IV = RSRandom::random_u64() ; // make a random 8 bytes IV
|
||||
}
|
||||
RsPeerId virtual_peer_id = it->second.virtual_peer_id ;
|
||||
|
||||
while(IV == 0) IV = RSRandom::random_u64() ; // make a random 8 bytes IV, that is not 0
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "DistantChatService::sendTurtleData(): tunnel found. Encrypting data." << std::endl;
|
||||
#endif
|
||||
@ -776,10 +858,8 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||
{
|
||||
std::cerr << "(EE) packet encryption failed." << std::endl;
|
||||
delete[] encrypted_data ;
|
||||
delete[] buff ;
|
||||
return ;
|
||||
}
|
||||
delete[] buff ;
|
||||
|
||||
// make a TurtleGenericData item out of it:
|
||||
//
|
||||
@ -792,10 +872,9 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||
memcpy(& (((uint8_t*)gitem->data_bytes)[8]),encrypted_data,encrypted_size) ;
|
||||
|
||||
delete[] encrypted_data ;
|
||||
delete item ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "DistantChatService::sendTurtleData(): Sending through virtual peer: " << virtual_peer_id << std::endl;
|
||||
std::cerr << "DistantChatService::sendTurtleData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl;
|
||||
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
|
||||
std::cerr << " data = " ;
|
||||
|
||||
@ -882,28 +961,39 @@ void DistantChatService::startClientDistantChatConnection(const RsGxsId& to_gxs_
|
||||
handleRecvChatMsgItem(item) ;
|
||||
|
||||
}
|
||||
|
||||
TurtleFileHash DistantChatService::hashFromGxsId(const RsGxsId& gid)
|
||||
TurtleFileHash DistantChatService::hashFromGxsId(const RsGxsId& destination)
|
||||
{
|
||||
if(RsGxsId::SIZE_IN_BYTES > Sha1CheckSum::SIZE_IN_BYTES)
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": Serious inconsistency error." << std::endl;
|
||||
// This is in prevision for the "secured GXS tunnel" service, which will need a service ID to register,
|
||||
// just like GRouter does.
|
||||
|
||||
assert(Sha1CheckSum::SIZE_IN_BYTES >= RsGxsId::SIZE_IN_BYTES) ;
|
||||
static const uint32_t client = RS_SERVICE_TYPE_DISTANT_CHAT ;
|
||||
|
||||
unsigned char tmp[Sha1CheckSum::SIZE_IN_BYTES] ;
|
||||
memset(tmp,0,Sha1CheckSum::SIZE_IN_BYTES) ;
|
||||
memcpy(tmp,gid.toByteArray(),RsGxsId::SIZE_IN_BYTES) ;
|
||||
assert( destination.SIZE_IN_BYTES == 16) ;
|
||||
assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ;
|
||||
|
||||
return Sha1CheckSum(tmp);
|
||||
uint8_t bytes[20] ;
|
||||
memcpy(bytes,destination.toByteArray(),16) ;
|
||||
bytes[16] = 0 ;
|
||||
bytes[17] = 0 ;
|
||||
bytes[18] = (client >> 8) & 0xff ;
|
||||
bytes[19] = client & 0xff ;
|
||||
|
||||
// We could rehash this, with a secret key to get a HMAC. That would allow to publish secret distant chat
|
||||
// passphrases. I'll do this later if needed.
|
||||
|
||||
return Sha1CheckSum(bytes) ;
|
||||
}
|
||||
RsGxsId DistantChatService::gxsIdFromHash(const TurtleFileHash& hash)
|
||||
RsGxsId DistantChatService::gxsIdFromHash(const TurtleFileHash& sum)
|
||||
{
|
||||
if(RsGxsId::SIZE_IN_BYTES > Sha1CheckSum::SIZE_IN_BYTES)
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": Serious inconsistency error." << std::endl;
|
||||
assert( RsGxsId::SIZE_IN_BYTES == 16) ;
|
||||
assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ;
|
||||
|
||||
assert(Sha1CheckSum::SIZE_IN_BYTES >= RsGxsId::SIZE_IN_BYTES) ;
|
||||
uint32_t client_id = sum.toByteArray()[19] + (sum.toByteArray()[18] << 8) ;
|
||||
|
||||
return RsGxsId(hash.toByteArray());
|
||||
if(client_id != RS_SERVICE_TYPE_DISTANT_CHAT)
|
||||
std::cerr << "WARNING: DistantChatService::gxsIdFromHash(). Hash is not a distant file hash. This should not happen." << std::endl;
|
||||
|
||||
return RsGxsId(sum.toByteArray());// takes the first 16 bytes
|
||||
}
|
||||
bool DistantChatService::getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& status, RsGxsId *from_gxs_id)
|
||||
{
|
||||
@ -978,19 +1068,9 @@ bool DistantChatService::closeDistantChatConnexion(const RsGxsId& gxs_id)
|
||||
return false ;
|
||||
}
|
||||
|
||||
// remove virtual peer from list
|
||||
std::map<RsPeerId,DistantChatDHInfo>::iterator it2 = _distant_chat_virtual_peer_ids.find(it->second.virtual_peer_id) ;
|
||||
|
||||
if(it2 == _distant_chat_virtual_peer_ids.end())
|
||||
{
|
||||
std::cerr << "(WW) Cannot remove virtual peer id " << it->second.virtual_peer_id << ": unknown! Weird situation." << std::endl;
|
||||
return true ;
|
||||
}
|
||||
|
||||
DH_free(it2->second.dh) ;
|
||||
|
||||
_distant_chat_virtual_peer_ids.erase(it2) ;
|
||||
_distant_chat_contacts.erase(it) ;
|
||||
|
||||
// DistantChatService::removeVirtualPeerId() will be called by the turtle service.
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@ -1008,6 +1088,11 @@ void DistantChatService::markDistantChatAsClosed(const RsGxsId& gxs_id)
|
||||
}
|
||||
|
||||
if(it->second.direction == RsTurtleGenericDataItem::DIRECTION_CLIENT)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " This is server side. Marking distant chat as remotely closed for GXS id " << gxs_id << std::endl;
|
||||
#endif
|
||||
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,8 @@ private:
|
||||
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.
|
||||
@ -105,10 +107,12 @@ private:
|
||||
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& pid) ;
|
||||
static RsGxsId gxsIdFromHash(const TurtleFileHash& pid) ;
|
||||
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) ;
|
||||
@ -119,6 +123,8 @@ private:
|
||||
// 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
|
||||
|
||||
|
@ -59,6 +59,7 @@ const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL = 0x0023;
|
||||
const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL = 0x0024;
|
||||
const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL = 0x0025;
|
||||
const uint16_t RS_SERVICE_TYPE_SERVICE_CONTROL= 0x0026;
|
||||
const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = 0x0027;
|
||||
|
||||
// Non essential services.
|
||||
const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101;
|
||||
|
@ -66,8 +66,11 @@ void PopupDistantChatDialog::init(const RsGxsId &gxs_id,const QString & title)
|
||||
RsGxsId own_gxs_id ;
|
||||
uint32_t status ;
|
||||
|
||||
// do not use setOwnId, because we don't want the user to change the GXS avatar from the chat window
|
||||
// it will not be transmitted.
|
||||
|
||||
if(rsMsgs->getDistantChatStatus(gxs_id,status,&own_gxs_id))
|
||||
ui.ownAvatarWidget->setOwnId(own_gxs_id);
|
||||
ui.ownAvatarWidget->setId(ChatId(own_gxs_id));
|
||||
}
|
||||
|
||||
void PopupDistantChatDialog::updateDisplay()
|
||||
@ -85,6 +88,8 @@ void PopupDistantChatDialog::updateDisplay()
|
||||
uint32_t status= RS_DISTANT_CHAT_STATUS_UNKNOWN;
|
||||
rsMsgs->getDistantChatStatus(_pid,status) ;
|
||||
|
||||
ui.avatarWidget->setId(ChatId(_pid));
|
||||
|
||||
QString msg;
|
||||
switch(status)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user