mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 00:19:25 -05:00
- implemented DH protocol for PFS encryption in distant chat between GXS ids.
- changed format of keyId in rstlvkeys.{h,cc}, but kept the serialisation for backward compatibility (A #define needs to be removed to fix it for good). Updated rsrecogn, rsmsgitems, gxssecurity accordingly - added "chat peer" in IdDialog to help testing distant chat. Distant chat works and is now encrypted. The GUI still needs some smoothing: display of correct peer names in chat window, remove the need to add a message in p3chatservice.cc:3217 to force poping up the chat window. - added MsgAddress class to handle generic address types while keeping type separation in Messages. Not used yet. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7403 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
114352c0d6
commit
80f4401e88
@ -33,7 +33,7 @@
|
||||
* #define GXS_SECURITY_DEBUG 1
|
||||
***/
|
||||
|
||||
static std::string getRsaKeyFingerprint(RSA *pubkey)
|
||||
static RsGxsId getRsaKeyFingerprint(RSA *pubkey)
|
||||
{
|
||||
int lenn = BN_num_bytes(pubkey -> n);
|
||||
int lene = BN_num_bytes(pubkey -> e);
|
||||
@ -51,7 +51,7 @@ static std::string getRsaKeyFingerprint(RSA *pubkey)
|
||||
|
||||
assert(Sha1CheckSum::SIZE_IN_BYTES >= CERTSIGNLEN) ;
|
||||
|
||||
return s.toStdString().substr(0,2*CERTSIGNLEN);
|
||||
return RsGxsId(s.toStdString().substr(0,2*CERTSIGNLEN));
|
||||
}
|
||||
|
||||
static RSA *extractPublicKey(const RsTlvSecurityKey& key)
|
||||
@ -151,7 +151,7 @@ bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvS
|
||||
|
||||
if(!rsa_pub)
|
||||
{
|
||||
std::cerr << "GxsSecurity::validateSignature(): Cannot validate signature. Keydata is incomplete." << std::endl;
|
||||
std::cerr << "GxsSecurity::getSignature(): Cannot create signature. Keydata is incomplete." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
EVP_PKEY *key_pub = EVP_PKEY_new();
|
||||
@ -171,7 +171,7 @@ bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvS
|
||||
EVP_PKEY_free(key_pub);
|
||||
|
||||
sign.signData.setBinData(sigbuf, siglen);
|
||||
sign.keyId = privKey.keyId;
|
||||
sign.keyId = RsGxsId(privKey.keyId);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@ -183,6 +183,7 @@ bool GxsSecurity::validateSignature(const char *data, uint32_t data_len, const R
|
||||
if(!rsakey)
|
||||
{
|
||||
std::cerr << "GxsSecurity::validateSignature(): Cannot validate signature. Keydata is incomplete." << std::endl;
|
||||
key.print(std::cerr,0) ;
|
||||
return false ;
|
||||
}
|
||||
EVP_PKEY *signKey = EVP_PKEY_new();
|
||||
|
@ -268,7 +268,7 @@ void RsGenExchange::generatePublicFromPrivateKeys(const RsTlvSecurityKeySet &pri
|
||||
publickeySet = RsTlvSecurityKeySet() ;
|
||||
RsTlvSecurityKey pubkey ;
|
||||
|
||||
for(std::map<std::string, RsTlvSecurityKey>::const_iterator cit=privatekeySet.keys.begin(); cit != privatekeySet.keys.end(); ++cit)
|
||||
for(std::map<RsGxsId, RsTlvSecurityKey>::const_iterator cit=privatekeySet.keys.begin(); cit != privatekeySet.keys.end(); ++cit)
|
||||
if(GxsSecurity::extractPublicKey(cit->second,pubkey))
|
||||
publickeySet.keys.insert(std::make_pair(pubkey.keyId, pubkey));
|
||||
}
|
||||
@ -284,7 +284,7 @@ uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& privateKe
|
||||
|
||||
// find private admin key
|
||||
RsTlvSecurityKey privAdminKey;
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator mit = privateKeySet.keys.begin();
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator mit = privateKeySet.keys.begin();
|
||||
|
||||
bool privKeyFound = false; // private admin key
|
||||
for(; mit != privateKeySet.keys.end(); mit++)
|
||||
@ -497,7 +497,7 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar
|
||||
RsTlvSecurityKeySet& keys = grpMeta.keys;
|
||||
RsTlvSecurityKey* pubKey;
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator mit =
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator mit =
|
||||
keys.keys.begin(), mit_end = keys.keys.end();
|
||||
bool pub_key_found = false;
|
||||
for(; mit != mit_end; mit++)
|
||||
@ -704,10 +704,10 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu
|
||||
{
|
||||
RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH];
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>& keys = grpKeySet.keys;
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator mit = keys.begin();
|
||||
std::map<RsGxsId, RsTlvSecurityKey>& keys = grpKeySet.keys;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator mit = keys.begin();
|
||||
|
||||
std::string keyId;
|
||||
RsGxsId keyId;
|
||||
for(; mit != keys.end() ; mit++)
|
||||
{
|
||||
RsTlvSecurityKey& key = mit->second;
|
||||
@ -719,7 +719,7 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu
|
||||
}
|
||||
}
|
||||
|
||||
if(!keyId.empty())
|
||||
if(!keyId.isNull())
|
||||
{
|
||||
RsTlvSecurityKey& key = keys[keyId];
|
||||
publishValidate &= GxsSecurity::validateNxsMsg(*msg, sign, key);
|
||||
@ -1940,7 +1940,7 @@ void RsGenExchange::processGroupDelete()
|
||||
bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet)
|
||||
{
|
||||
|
||||
typedef std::map<std::string, RsTlvSecurityKey> keyMap;
|
||||
typedef std::map<RsGxsId, RsTlvSecurityKey> keyMap;
|
||||
const keyMap& allKeys = keySet.keys;
|
||||
keyMap::const_iterator cit = allKeys.begin();
|
||||
bool adminFound = false, publishFound = false;
|
||||
@ -2011,7 +2011,7 @@ void RsGenExchange::publishGrps()
|
||||
|
||||
// find private admin key
|
||||
RsTlvSecurityKey privAdminKey;
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator mit_keys = privatekeySet.keys.begin();
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator mit_keys = privatekeySet.keys.begin();
|
||||
|
||||
bool privKeyFound = false;
|
||||
for(; mit_keys != privatekeySet.keys.end(); mit_keys++)
|
||||
@ -2569,8 +2569,8 @@ bool RsGenExchange::updateValid(RsGxsGrpMetaData& oldGrpMeta, RsNxsGrp& newGrp)
|
||||
|
||||
RsTlvKeySignature adminSign = mit->second;
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>& keys = oldGrpMeta.keys.keys;
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator keyMit = keys.find(oldGrpMeta.mGroupId.toStdString());
|
||||
std::map<RsGxsId, RsTlvSecurityKey>& keys = oldGrpMeta.keys.keys;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator keyMit = keys.find(RsGxsId(oldGrpMeta.mGroupId));
|
||||
|
||||
if(keyMit == keys.end())
|
||||
{
|
||||
|
@ -295,7 +295,7 @@ int pqissludp::Initiate_Connection()
|
||||
*/
|
||||
#define UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR (0.7)
|
||||
|
||||
parent()->setRateCap( UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0,
|
||||
parent()->setRateCap( UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0,
|
||||
UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0); // Set RateCap.
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <assert.h>
|
||||
|
||||
#include "rstypes.h"
|
||||
#include "rsgxsifacetypes.h"
|
||||
@ -86,12 +87,77 @@ const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE( 0x00000001 ) ;
|
||||
|
||||
typedef uint64_t ChatLobbyId ;
|
||||
typedef uint64_t ChatLobbyMsgId ;
|
||||
typedef std::string ChatLobbyNickName ;
|
||||
typedef std::string ChatLobbyNickName ;
|
||||
|
||||
typedef RsPeerId DistantChatPeerId ;
|
||||
typedef GRouterKeyIdType DistantMsgPeerId ;
|
||||
|
||||
class MessageInfo
|
||||
typedef uint64_t MessageId ;
|
||||
|
||||
class MsgAddress
|
||||
{
|
||||
public:
|
||||
typedef enum { MSG_ADDRESS_TYPE_UNKNOWN = 0x00,
|
||||
MSG_ADDRESS_TYPE_RSPEERID = 0x01,
|
||||
MSG_ADDRESS_TYPE_RSGXSID = 0x02,
|
||||
MSG_ADDRESS_TYPE_EMAIL = 0x03 } AddressType;
|
||||
|
||||
typedef enum { MSG_ADDRESS_MODE_UNKNOWN = 0x00,
|
||||
MSG_ADDRESS_MODE_TO = 0x01,
|
||||
MSG_ADDRESS_MODE_CC = 0x02,
|
||||
MSG_ADDRESS_MODE_BCC = 0x03 } AddressMode;
|
||||
|
||||
explicit MsgAddress(const RsGxsId& gid, MsgAddress::AddressMode mmode)
|
||||
: _type(MSG_ADDRESS_TYPE_RSGXSID), _mode(mmode), _addr_string(gid.toStdString()){}
|
||||
|
||||
explicit MsgAddress(const RsPeerId& pid, MsgAddress::AddressMode mmode)
|
||||
: _type(MSG_ADDRESS_TYPE_RSPEERID), _mode(mmode), _addr_string(pid.toStdString()){}
|
||||
|
||||
explicit MsgAddress(const std::string& email, MsgAddress::AddressMode mmode)
|
||||
: _type(MSG_ADDRESS_TYPE_EMAIL), _mode(mmode), _addr_string(email){}
|
||||
|
||||
MsgAddress::AddressType type() { return _type ;}
|
||||
MsgAddress::AddressMode mode() { return _mode ;}
|
||||
|
||||
RsGxsId toGxsId() const { assert(_type==MSG_ADDRESS_TYPE_RSGXSID );return RsGxsId (_addr_string);}
|
||||
RsPeerId toRsPeerId() const { assert(_type==MSG_ADDRESS_TYPE_RSPEERID);return RsPeerId(_addr_string);}
|
||||
std::string toEmail() const { assert(_type==MSG_ADDRESS_TYPE_EMAIL );return _addr_string ;}
|
||||
|
||||
private:
|
||||
AddressType _type ;
|
||||
AddressMode _mode ;
|
||||
std::string _addr_string ;
|
||||
};
|
||||
|
||||
class MessageInfo_v2
|
||||
{
|
||||
public:
|
||||
//MessageInfo_v2() {}
|
||||
|
||||
unsigned int msgflags;
|
||||
|
||||
//RsMessageId msgId;
|
||||
MsgAddress from ;
|
||||
|
||||
std::list<MsgAddress> rcpt ;
|
||||
|
||||
// Headers
|
||||
//
|
||||
std::string subject;
|
||||
std::string msg;
|
||||
time_t time_stamp ;
|
||||
|
||||
//std::list<MessageHeader> headers ;
|
||||
|
||||
std::string attach_title;
|
||||
std::string attach_comment;
|
||||
std::list<FileInfo> files;
|
||||
|
||||
int size; /* total of files */
|
||||
int count; /* file count */
|
||||
};
|
||||
|
||||
class MessageInfo
|
||||
{
|
||||
public:
|
||||
MessageInfo() {}
|
||||
@ -127,6 +193,7 @@ public:
|
||||
int ts;
|
||||
};
|
||||
|
||||
|
||||
class MsgInfoSummary
|
||||
{
|
||||
public:
|
||||
@ -171,6 +238,7 @@ public:
|
||||
#define RS_DISTANT_CHAT_STATUS_TUNNEL_OK 0x0002
|
||||
#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0003
|
||||
#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0004
|
||||
#define RS_DISTANT_CHAT_STATUS_WAITING_DH 0x0005
|
||||
|
||||
#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000
|
||||
#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001
|
||||
@ -356,7 +424,7 @@ virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const std::str
|
||||
/* Distant chat */
|
||||
/****************************************/
|
||||
|
||||
virtual bool initiateDistantChatConnexion(const RsGxsId& pid,DistantChatPeerId& id,uint32_t& error_code) = 0;
|
||||
virtual bool initiateDistantChatConnexion(const RsGxsId& pid,uint32_t& error_code) = 0;
|
||||
virtual bool getDistantChatStatus(const DistantChatPeerId& pid,RsGxsId& gxs_id,uint32_t& status) = 0;
|
||||
virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid) = 0;
|
||||
|
||||
|
@ -359,9 +359,9 @@ void p3Msgs::getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites)
|
||||
{
|
||||
mChatSrv->getPendingChatLobbyInvites(invites) ;
|
||||
}
|
||||
bool p3Msgs::initiateDistantChatConnexion(const RsGxsId& gxs_id,DistantChatPeerId& pid,uint32_t& error_code)
|
||||
bool p3Msgs::initiateDistantChatConnexion(const RsGxsId& gxs_id,uint32_t& error_code)
|
||||
{
|
||||
return mChatSrv->initiateDistantChatConnexion(gxs_id,pid,error_code) ;
|
||||
return mChatSrv->initiateDistantChatConnexion(gxs_id,error_code) ;
|
||||
}
|
||||
bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,RsGxsId& gxs_id,uint32_t& status)
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ class p3Msgs: public RsMsgs
|
||||
virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id);
|
||||
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const std::string& lobby_topic,const std::list<RsPeerId>& invited_friends,uint32_t privacy_type) ;
|
||||
|
||||
virtual bool initiateDistantChatConnexion(const RsGxsId& gxs_id,DistantChatPeerId& pid,uint32_t& error_code) ;
|
||||
virtual bool initiateDistantChatConnexion(const RsGxsId& gxs_id,uint32_t& error_code) ;
|
||||
virtual bool getDistantChatStatus(const DistantChatPeerId& pid,RsGxsId& gxs_id,uint32_t& status) ;
|
||||
virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid) ;
|
||||
|
||||
|
@ -1455,7 +1455,7 @@ int RsServer::StartupRetroShare()
|
||||
mDisc = new p3discovery2(mPeerMgr, mLinkMgr, mNetMgr, serviceCtrl);
|
||||
mHeart = new p3heartbeat(serviceCtrl, pqih);
|
||||
msgSrv = new p3MsgService(serviceCtrl,mGxsIdService);
|
||||
chatSrv = new p3ChatService(serviceCtrl, mLinkMgr, mHistoryMgr);
|
||||
chatSrv = new p3ChatService(serviceCtrl,mGxsIdService, mLinkMgr, mHistoryMgr);
|
||||
mStatusSrv = new p3StatusService(serviceCtrl);
|
||||
|
||||
#ifdef ENABLE_GROUTER
|
||||
|
@ -57,6 +57,19 @@ 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_deprecated2::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsChatLobbyListItem_deprecated2", indent);
|
||||
@ -296,6 +309,7 @@ RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize)
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated: return new RsChatLobbyListItem_deprecated(data,*pktsize) ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2:return new RsChatLobbyListItem_deprecated2(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 ;
|
||||
@ -466,6 +480,17 @@ 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()
|
||||
@ -477,6 +502,41 @@ 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)
|
||||
{
|
||||
@ -981,6 +1041,28 @@ 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)
|
||||
{
|
||||
|
@ -28,7 +28,10 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "openssl/bn.h"
|
||||
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "serialiser/rstlvkeys.h"
|
||||
#include "serialiser/rsserviceids.h"
|
||||
#include "serialiser/rsserial.h"
|
||||
|
||||
@ -76,6 +79,7 @@ const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2 = 0x11 ; // to be remov
|
||||
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST = 0x12 ;
|
||||
const uint8_t RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG = 0x13 ;
|
||||
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG = 0x15 ;
|
||||
const uint8_t RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY = 0x16 ;
|
||||
|
||||
// for defining tags themselves and msg tags
|
||||
const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03;
|
||||
@ -87,6 +91,7 @@ const uint8_t RS_PKT_SUBTYPE_MSG_INVITE = 0x07;
|
||||
typedef uint64_t ChatLobbyId ;
|
||||
typedef uint64_t ChatLobbyMsgId ;
|
||||
typedef std::string ChatLobbyNickName ;
|
||||
typedef uint64_t DistantChatDHSessionId ;
|
||||
|
||||
class RsChatItem: public RsItem
|
||||
{
|
||||
@ -402,6 +407,32 @@ class RsChatAvatarItem: public RsChatItem
|
||||
unsigned char *image_data ; // image
|
||||
};
|
||||
|
||||
// This class contains the public Diffie-Hellman parameters to be sent
|
||||
// when performing a DH agreement over a distant chat tunnel.
|
||||
//
|
||||
class RsChatDHPublicKeyItem: public RsChatItem
|
||||
{
|
||||
public:
|
||||
RsChatDHPublicKeyItem() :RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY) {setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ;}
|
||||
RsChatDHPublicKeyItem(void *data,uint32_t size) ; // deserialization
|
||||
|
||||
virtual ~RsChatDHPublicKeyItem() { BN_free(public_key) ; }
|
||||
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
|
||||
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
|
||||
|
||||
// Private data to DH public key item
|
||||
//
|
||||
BIGNUM *public_key ;
|
||||
|
||||
RsTlvKeySignature signature ; // signs the public key in a row.
|
||||
RsTlvSecurityKey gxs_key ; // public key of the signer
|
||||
|
||||
private:
|
||||
RsChatDHPublicKeyItem(const RsChatDHPublicKeyItem&) : RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY) {} // make the object non copy-able
|
||||
const RsChatDHPublicKeyItem& operator=(const RsChatDHPublicKeyItem&) { return *this ;}
|
||||
};
|
||||
|
||||
class RsChatSerialiser: public RsSerialType
|
||||
{
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
#define TLV_DEBUG 1
|
||||
|
||||
// This should be removed eventually, but will break backward compatibility
|
||||
#define KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
|
||||
/************************************* RsTlvSecurityKey ************************************/
|
||||
|
||||
RsTlvSecurityKey::RsTlvSecurityKey()
|
||||
@ -67,7 +70,11 @@ uint32_t RsTlvSecurityKey::TlvSize() const
|
||||
|
||||
/* now add comment and title length of this tlv object */
|
||||
|
||||
s += GetTlvStringSize(keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
s += GetTlvStringSize(keyId.toStdString()) ;
|
||||
#else
|
||||
s += keyId.serial_size();
|
||||
#endif
|
||||
s += 4;
|
||||
s += 4;
|
||||
s += 4;
|
||||
@ -85,10 +92,10 @@ bool RsTlvSecurityKey::SetTlv(void *data, uint32_t size, uint32_t *offset) cons
|
||||
|
||||
if (size < tlvend)
|
||||
{
|
||||
#ifdef TLV_DEBUG
|
||||
//#ifdef TLV_DEBUG
|
||||
std::cerr << "RsTlvSecurityKey::SetTlv() Failed not enough space";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
//#endif
|
||||
return false; /* not enough space */
|
||||
}
|
||||
|
||||
@ -99,7 +106,11 @@ bool RsTlvSecurityKey::SetTlv(void *data, uint32_t size, uint32_t *offset) cons
|
||||
|
||||
ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITYKEY, tlvsize);
|
||||
|
||||
ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString());
|
||||
#else
|
||||
ok &= keyId.serialise(data, tlvend, *offset) ;
|
||||
#endif
|
||||
ok &= setRawUInt32(data, tlvend, offset, keyFlags);
|
||||
ok &= setRawUInt32(data, tlvend, offset, startTS);
|
||||
ok &= setRawUInt32(data, tlvend, offset, endTS);
|
||||
@ -145,7 +156,13 @@ bool RsTlvSecurityKey::GetTlv(void *data, uint32_t size, uint32_t *offset)
|
||||
/* skip the header */
|
||||
(*offset) += TLV_HEADER_SIZE;
|
||||
|
||||
ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
std::string s ;
|
||||
ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s);
|
||||
keyId = RsGxsId(s) ;
|
||||
#else
|
||||
ok &= keyId.deserialise(data, tlvend, *offset) ;
|
||||
#endif
|
||||
ok &= getRawUInt32(data, tlvend, offset, &(keyFlags));
|
||||
ok &= getRawUInt32(data, tlvend, offset, &(startTS));
|
||||
ok &= getRawUInt32(data, tlvend, offset, &(endTS));
|
||||
@ -224,7 +241,7 @@ uint32_t RsTlvSecurityKeySet::TlvSize() const
|
||||
|
||||
uint32_t s = TLV_HEADER_SIZE; /* header */
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>::const_iterator it;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::const_iterator it;
|
||||
|
||||
s += GetTlvStringSize(groupId);
|
||||
|
||||
@ -264,7 +281,7 @@ bool RsTlvSecurityKeySet::SetTlv(void *data, uint32_t size, uint32_t *offset) c
|
||||
|
||||
if(!keys.empty())
|
||||
{
|
||||
std::map<std::string, RsTlvSecurityKey>::const_iterator it;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::const_iterator it;
|
||||
|
||||
for(it = keys.begin(); it != keys.end() ; ++it)
|
||||
ok &= (it->second).SetTlv(data, size, offset);
|
||||
@ -361,7 +378,7 @@ std::ostream &RsTlvSecurityKeySet::print(std::ostream &out, uint16_t indent) con
|
||||
out << "GroupId: " << groupId;
|
||||
out << std::endl;
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>::const_iterator it;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::const_iterator it;
|
||||
for(it = keys.begin(); it != keys.end() ; ++it)
|
||||
(it->second).print(out, int_Indent);
|
||||
|
||||
@ -396,7 +413,11 @@ uint32_t RsTlvKeySignature::TlvSize() const
|
||||
{
|
||||
uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */
|
||||
|
||||
s += GetTlvStringSize(keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
s += GetTlvStringSize(keyId.toStdString()) ;
|
||||
#else
|
||||
s += keyId.serial_size() ;
|
||||
#endif
|
||||
s += signData.TlvSize();
|
||||
return s;
|
||||
|
||||
@ -424,7 +445,11 @@ bool RsTlvKeySignature::SetTlv(void *data, uint32_t size, uint32_t *offset) con
|
||||
|
||||
ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURE, tlvsize);
|
||||
|
||||
ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString());
|
||||
#else
|
||||
ok &= keyId.serialise(data, tlvend, *offset) ;
|
||||
#endif
|
||||
ok &= signData.SetTlv(data, tlvend, offset);
|
||||
|
||||
if (!ok)
|
||||
@ -475,7 +500,13 @@ bool RsTlvKeySignature::GetTlv(void *data, uint32_t size, uint32_t *offset)
|
||||
/* skip the header */
|
||||
(*offset) += TLV_HEADER_SIZE;
|
||||
|
||||
ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId);
|
||||
#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT
|
||||
std::string s ;
|
||||
ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s);
|
||||
keyId = RsGxsId(s) ;
|
||||
#else
|
||||
ok &= keyId.deserialise(data, tlvend, *offset) ;
|
||||
#endif
|
||||
ok &= signData.GetTlv(data, tlvend, offset);
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "serialiser/rstlvitem.h"
|
||||
#include "serialiser/rstlvbinary.h"
|
||||
#include "retroshare/rsgxsifacetypes.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -48,22 +49,23 @@ const uint32_t RSTLV_KEY_DISTRIB_IDENTITY = 0x0080;
|
||||
class RsTlvSecurityKey: public RsTlvItem
|
||||
{
|
||||
public:
|
||||
RsTlvSecurityKey();
|
||||
virtual ~RsTlvSecurityKey() { return; }
|
||||
virtual uint32_t TlvSize() const;
|
||||
virtual void TlvClear();
|
||||
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
|
||||
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent) const;
|
||||
RsTlvSecurityKey();
|
||||
virtual ~RsTlvSecurityKey() {}
|
||||
|
||||
/* clears KeyData - but doesn't delete - to transfer ownership */
|
||||
void ShallowClear();
|
||||
virtual uint32_t TlvSize() const;
|
||||
virtual void TlvClear();
|
||||
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
|
||||
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent) const;
|
||||
|
||||
std::string keyId; // Mandatory :
|
||||
uint32_t keyFlags; // Mandatory ;
|
||||
uint32_t startTS; // Mandatory :
|
||||
uint32_t endTS; // Mandatory :
|
||||
RsTlvBinaryData keyData; // Mandatory :
|
||||
/* clears KeyData - but doesn't delete - to transfer ownership */
|
||||
void ShallowClear();
|
||||
|
||||
RsGxsId keyId; // Mandatory :
|
||||
uint32_t keyFlags; // Mandatory ;
|
||||
uint32_t startTS; // Mandatory :
|
||||
uint32_t endTS; // Mandatory :
|
||||
RsTlvBinaryData keyData; // Mandatory :
|
||||
};
|
||||
|
||||
class RsTlvSecurityKeySet: public RsTlvItem
|
||||
@ -78,26 +80,25 @@ virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent) const;
|
||||
|
||||
std::string groupId; // Mandatory :
|
||||
std::map<std::string, RsTlvSecurityKey> keys; // Mandatory :
|
||||
std::map<RsGxsId, RsTlvSecurityKey> keys; // Mandatory :
|
||||
};
|
||||
|
||||
|
||||
class RsTlvKeySignature: public RsTlvItem
|
||||
{
|
||||
public:
|
||||
RsTlvKeySignature();
|
||||
virtual ~RsTlvKeySignature() { return; }
|
||||
virtual uint32_t TlvSize() const;
|
||||
virtual void TlvClear();
|
||||
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
|
||||
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent) const;
|
||||
RsTlvKeySignature();
|
||||
virtual ~RsTlvKeySignature() { return; }
|
||||
virtual uint32_t TlvSize() const;
|
||||
virtual void TlvClear();
|
||||
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
|
||||
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent) const;
|
||||
|
||||
void ShallowClear(); /* clears signData - but doesn't delete */
|
||||
void ShallowClear(); /* clears signData - but doesn't delete */
|
||||
|
||||
std::string keyId; // Mandatory :
|
||||
RsTlvBinaryData signData; // Mandatory :
|
||||
// NO Certificates in Signatures... add as separate data type.
|
||||
RsGxsId keyId; // Mandatory :
|
||||
RsTlvBinaryData signData; // Mandatory :
|
||||
};
|
||||
|
||||
typedef uint32_t SignType;
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "openssl/rand.h"
|
||||
#include "openssl/dh.h"
|
||||
#include "openssl/err.h"
|
||||
|
||||
#include "gxs/gxssecurity.h"
|
||||
#include "pgp/rscertificate.h"
|
||||
#include "pqi/authgpg.h"
|
||||
#include "util/rsdir.h"
|
||||
@ -43,6 +47,7 @@
|
||||
#include "pqi/p3linkmgr.h"
|
||||
#include "pqi/p3historymgr.h"
|
||||
#include "rsserver/p3face.h"
|
||||
#include "services/p3idservice.h"
|
||||
|
||||
#include "services/p3chatservice.h"
|
||||
#include "serialiser/rsconfigitems.h"
|
||||
@ -51,7 +56,8 @@
|
||||
* #define CHAT_DEBUG 1
|
||||
* #define DEBUG_DISTANT_CHAT 1
|
||||
****/
|
||||
//#define DEBUG_DISTANT_CHAT 1
|
||||
#define DEBUG_DISTANT_CHAT 1
|
||||
//#define CHAT_DEBUG 1
|
||||
|
||||
static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connection challenge every 20 messages
|
||||
static const time_t CONNECTION_CHALLENGE_MAX_MSG_AGE = 30 ; // maximum age of a message to be used in a connection challenge
|
||||
@ -67,7 +73,6 @@ static const time_t LOBBY_LIST_AUTO_UPDATE_TIME = 121 ; // regularly as
|
||||
|
||||
static const time_t DISTANT_CHAT_CLEANING_PERIOD = 60 ; // clean distant chat caches every 60 secs (remove old invites)
|
||||
static const time_t DISTANT_CHAT_KEEP_ALIVE_PERIOD = 10 ; // sens keep alive distant chat packets every 10 secs.
|
||||
static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; // size of AES encryption key for distant chat.
|
||||
static const uint32_t DISTANT_CHAT_HASH_SIZE = Sha1CheckSum::SIZE_IN_BYTES ; // This is sha1 size in bytes.
|
||||
|
||||
static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size in bytes for an avatar. Too large packets
|
||||
@ -77,8 +82,8 @@ static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ;
|
||||
static const uint32_t MAX_MESSAGES_PER_SECONDS_NUMBER = 5 ; // max number of messages from a given peer in a window for duration below
|
||||
static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration window for max number of messages before messages get dropped.
|
||||
|
||||
p3ChatService::p3ChatService(p3ServiceControl *sc, p3LinkMgr *lm, p3HistoryMgr *historyMgr)
|
||||
:p3Service(), p3Config(), mChatMtx("p3ChatService"), mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
||||
p3ChatService::p3ChatService(p3ServiceControl *sc,p3IdService *pids, p3LinkMgr *lm, p3HistoryMgr *historyMgr)
|
||||
:p3Service(), p3Config(), mChatMtx("p3ChatService"), mIdService(pids),mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
|
||||
{
|
||||
_serializer = new RsChatSerialiser() ;
|
||||
_own_avatar = NULL ;
|
||||
@ -311,25 +316,19 @@ bool p3ChatService::getHashFromVirtualPeerId(const TurtleVirtualPeerId& vpid,Tur
|
||||
|
||||
void p3ChatService::sendPrivateChatItem(RsChatItem *item)
|
||||
{
|
||||
TurtleFileHash hash = hashFromDistantChatPeerId(item->PeerId());
|
||||
|
||||
std::map<RsFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
if(it != _distant_chat_peers.end())
|
||||
{
|
||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it=_distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
||||
if( it->second.virtual_peer_id == item->PeerId())
|
||||
{
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "p3ChatService::sendPrivateChatItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
|
||||
std::cerr << "p3ChatService::sendPrivateChatItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
|
||||
#endif
|
||||
item->PeerId(it->second.virtual_peer_id) ;
|
||||
sendTurtleData(item) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
sendTurtleData(item) ;
|
||||
return ;
|
||||
}
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "p3ChatService::sendPrivateChatItem(): sending to " << item->PeerId() << ": interpreted as friend peer id." << std::endl;
|
||||
std::cerr << "p3ChatService::sendPrivateChatItem(): sending to " << item->PeerId() << ": interpreted as friend peer id." << std::endl;
|
||||
#endif
|
||||
sendItem(item) ;
|
||||
}
|
||||
sendItem(item) ;
|
||||
}
|
||||
|
||||
void p3ChatService::checkSizeAndSendMessage_deprecated(RsChatMsgItem *msg)
|
||||
@ -495,7 +494,7 @@ bool p3ChatService::isOnline(const DistantChatPeerId& pid)
|
||||
|
||||
std::string hash ;
|
||||
if(getDistantChatStatus(pid,gxs_id,status))
|
||||
return true ;
|
||||
return status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||
else
|
||||
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
|
||||
}
|
||||
@ -834,14 +833,15 @@ void p3ChatService::handleIncomingItem(RsItem *item)
|
||||
|
||||
switch(item->PacketSubType())
|
||||
{
|
||||
case RS_PKT_SUBTYPE_CHAT_STATUS: handleRecvChatStatusItem (dynamic_cast<RsChatStatusItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_AVATAR: handleRecvChatAvatarItem (dynamic_cast<RsChatAvatarItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: handleRecvLobbyInvite (dynamic_cast<RsChatLobbyInviteItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: handleConnectionChallenge (dynamic_cast<RsChatLobbyConnectChallengeItem*>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT: handleRecvChatLobbyEventItem (dynamic_cast<RsChatLobbyEventItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: handleFriendUnsubscribeLobby (dynamic_cast<RsChatLobbyUnsubscribeItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: handleRecvChatLobbyListRequest(dynamic_cast<RsChatLobbyListRequestItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: handleRecvChatLobbyList (dynamic_cast<RsChatLobbyListItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_STATUS: handleRecvChatStatusItem (dynamic_cast<RsChatStatusItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_AVATAR: handleRecvChatAvatarItem (dynamic_cast<RsChatAvatarItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: handleRecvLobbyInvite (dynamic_cast<RsChatLobbyInviteItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: handleConnectionChallenge (dynamic_cast<RsChatLobbyConnectChallengeItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT: handleRecvChatLobbyEventItem (dynamic_cast<RsChatLobbyEventItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: handleFriendUnsubscribeLobby (dynamic_cast<RsChatLobbyUnsubscribeItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: handleRecvChatLobbyListRequest (dynamic_cast<RsChatLobbyListRequestItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: handleRecvChatLobbyList (dynamic_cast<RsChatLobbyListItem *>(item)) ; break ;
|
||||
case RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY: handleRecvDHPublicKey(dynamic_cast<RsChatDHPublicKeyItem*>(item)) ; break ;
|
||||
|
||||
default:
|
||||
{
|
||||
@ -1348,13 +1348,13 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci)
|
||||
|
||||
if (ci->chatFlags & RS_CHAT_FLAG_PRIVATE) {
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "Adding msg 0x" << std::hex << (void*)ci << std::dec << " to private chat incoming list." << std::endl;
|
||||
std::cerr << "Adding msg " << std::hex << (void*)ci << std::dec << " to private chat incoming list from " << ci->PeerId() << "." << std::endl;
|
||||
#endif
|
||||
privateChanged = true;
|
||||
privateIncomingList.push_back(ci); // don't delete the item !!
|
||||
} else {
|
||||
#ifdef CHAT_DEBUG
|
||||
std::cerr << "Adding msg 0x" << std::hex << (void*)ci << std::dec << " to public chat incoming list." << std::endl;
|
||||
std::cerr << "Adding msg " << std::hex << (void*)ci << std::dec << " to public chat incoming list." << std::endl;
|
||||
#endif
|
||||
publicChanged = true;
|
||||
publicList.push_back(ci); // don't delete the item !!
|
||||
@ -1810,6 +1810,9 @@ void p3ChatService::getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& d
|
||||
|
||||
void p3ChatService::sendAvatarRequest(const RsPeerId& peer_id)
|
||||
{
|
||||
if(!isOnline(peer_id))
|
||||
return ;
|
||||
|
||||
// Doesn't have avatar. Request it.
|
||||
//
|
||||
RsChatMsgItem *ci = new RsChatMsgItem();
|
||||
@ -1829,6 +1832,9 @@ void p3ChatService::sendAvatarRequest(const RsPeerId& peer_id)
|
||||
|
||||
void p3ChatService::sendCustomStateRequest(const RsPeerId& peer_id){
|
||||
|
||||
if(!isOnline(peer_id))
|
||||
return ;
|
||||
|
||||
RsChatStatusItem* cs = new RsChatStatusItem;
|
||||
|
||||
cs->PeerId(peer_id);
|
||||
@ -3108,7 +3114,7 @@ bool p3ChatService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /
|
||||
#endif
|
||||
|
||||
for(std::list<RsGxsId>::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it)
|
||||
if(hashFromDistantChatPeerId(DistantChatPeerId(*it)) == hash)
|
||||
if(hashFromGxsId(*it) == hash)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " answering true!" << std::endl;
|
||||
@ -3128,11 +3134,10 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua
|
||||
|
||||
if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
||||
{
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << " Side is in direction to server." << std::endl;
|
||||
#endif
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
@ -3146,6 +3151,8 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua
|
||||
it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
|
||||
it->second.virtual_peer_id = virtual_peer_id ;
|
||||
it->second.direction = dir ;
|
||||
it->second.dh = NULL ;
|
||||
memset(it->second.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "(II) Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
|
||||
@ -3160,6 +3167,21 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua
|
||||
std::cerr << " Side is in direction to client." << std::endl;
|
||||
std::cerr << " Initing encryption parameters from existing distant chat invites." << std::endl;
|
||||
#endif
|
||||
RsGxsId own_gxs_id ;
|
||||
std::list<RsGxsId> own_id_list ;
|
||||
rsIdentity->getOwnIds(own_id_list) ;
|
||||
|
||||
for(std::list<RsGxsId>::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it)
|
||||
if(hashFromGxsId(*it) == hash)
|
||||
{
|
||||
own_gxs_id = *it ;
|
||||
break ;
|
||||
}
|
||||
if(own_gxs_id.isNull())
|
||||
{
|
||||
std::cerr << "p3ChatService::addVirtualPeer(): cannot find GXS id for hash " << hash << ". This is probably a bug" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
DistantChatPeerInfo info ;
|
||||
info.last_contact = now ;
|
||||
@ -3167,33 +3189,43 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua
|
||||
info.virtual_peer_id = virtual_peer_id ;
|
||||
info.gxs_id.clear() ; // unknown yet!
|
||||
info.direction = dir ;
|
||||
|
||||
#warning Unfinished code here causes serious security defect.
|
||||
info.own_gxs_id = own_gxs_id ;
|
||||
info.dh = NULL ;
|
||||
memset(info.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
_distant_chat_peers[hash] = info ;
|
||||
}
|
||||
|
||||
// then we send an ACK packet to notify that the tunnel works. That's useful
|
||||
// because it makes the peer at the other end of the tunnel know that all
|
||||
// intermediate peer in the tunnel are able to transmit the data.
|
||||
// However, it is not possible here to call sendTurtleData(), without dead-locking
|
||||
// the turtle router, so we store the item is a list of items to be sent.
|
||||
|
||||
RsChatStatusItem *cs = new RsChatStatusItem ;
|
||||
|
||||
cs->status_string = "Tunnel is working. You can talk!" ;
|
||||
cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_ACK_DISTANT_CONNECTION;
|
||||
cs->PeerId(virtual_peer_id);
|
||||
|
||||
{
|
||||
// Start a new DH session for this tunnel
|
||||
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
pendingDistantChatItems.push_back(cs) ;
|
||||
DistantChatPeerInfo& info(_distant_chat_peers[hash]) ;
|
||||
|
||||
std::cerr << " Starting new DH session." << std::endl;
|
||||
|
||||
if(!locked_initDHSessionKey(info))
|
||||
std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl;
|
||||
|
||||
if(!locked_sendDHPublicKey(info))
|
||||
std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl;
|
||||
|
||||
info.status = RS_DISTANT_CHAT_STATUS_WAITING_DH ;
|
||||
}
|
||||
|
||||
RsChatMsgItem *item = new RsChatMsgItem;
|
||||
item->message = std::string("Tunnel is secured") ;
|
||||
item->PeerId(virtual_peer_id) ;
|
||||
item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
|
||||
|
||||
privateIncomingList.push_back(item) ;
|
||||
|
||||
if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
||||
RsServer::notify()->AddPopupMessage(RS_POPUP_CHAT, virtual_peer_id.toStdString(), "Distant peer", "Conversation starts...");
|
||||
|
||||
// Notify the GUI that the tunnel is up.
|
||||
//
|
||||
RsServer::notify()->notifyChatStatus(virtual_peer_id.toStdString(),"tunnel is up again!",true) ;
|
||||
RsServer::notify()->notifyChatStatus(virtual_peer_id.toStdString(),"tunnel is up again!",true) ;
|
||||
}
|
||||
|
||||
void p3ChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
|
||||
@ -3319,6 +3351,227 @@ void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const Rs
|
||||
handleIncomingItem(citem) ; // Treats the item, and deletes it
|
||||
}
|
||||
|
||||
void p3ChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||
{
|
||||
std::cerr << "p3ChatService: Received DH public key." << std::endl;
|
||||
item->print(std::cerr, 0) ;
|
||||
|
||||
// Look for the current state of the key agreement.
|
||||
|
||||
TurtleVirtualPeerId vpid = item->PeerId() ;
|
||||
TurtleFileHash hash ;
|
||||
|
||||
if(getHashFromVirtualPeerId(vpid,hash))
|
||||
std::cerr << " hash = " << hash << std::endl;
|
||||
else
|
||||
{
|
||||
std::cerr << " (EE) Cannot get hash from virtual peer id " << vpid << ". Probably a bug!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
if(it == _distant_chat_peers.end())
|
||||
{
|
||||
std::cerr << " (EE) Cannot find hash in distant chat peer list!!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// Now check the signature of the DH public key item.
|
||||
|
||||
std::cerr << " Checking signature. " << std::endl;
|
||||
|
||||
uint32_t pubkey_size = BN_num_bytes(item->public_key) ;
|
||||
unsigned char *data = (unsigned char *)malloc(pubkey_size) ;
|
||||
BN_bn2bin(item->public_key, data) ;
|
||||
|
||||
RsTlvSecurityKey signature_key ;
|
||||
|
||||
// We need to get the key of the sender, but if the key is not cached, we
|
||||
// need to get it first. So we let the system work for 2-3 seconds before
|
||||
// giving up. Normally this would only cause a delay for uncached keys,
|
||||
// which is rare. To force the system to cache the key, we first call for
|
||||
// getIdDetails().
|
||||
//
|
||||
RsIdentityDetails details ;
|
||||
RsGxsId senders_id( item->signature.keyId ) ;
|
||||
|
||||
mIdService->getIdDetails(senders_id,details);
|
||||
|
||||
for(int i=0;i<6;++i)
|
||||
if(!mIdService->getKey(senders_id,signature_key) || signature_key.keyData.bin_data == NULL)
|
||||
{
|
||||
std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl;
|
||||
usleep(500000) ; // sleep for 500 msec.
|
||||
}
|
||||
else
|
||||
break ;
|
||||
|
||||
if(signature_key.keyData.bin_data == NULL)
|
||||
{
|
||||
std::cerr << " (EE) Key unknown for checking signature from " << senders_id << ", can't verify signature." << std::endl;
|
||||
std::cerr << " Using key provided in DH packet." << std::endl;
|
||||
|
||||
signature_key = item->gxs_key ;
|
||||
|
||||
#warning At this point, we should check that the key Ids match!!
|
||||
}
|
||||
|
||||
if(!GxsSecurity::validateSignature((char*)data,pubkey_size,signature_key,item->signature))
|
||||
{
|
||||
std::cerr << " (EE) Signature was verified and it doesn't check! This is a security issue!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
std::cerr << " Signature checks!" << std::endl;
|
||||
std::cerr << " Computing AES key" << std::endl;
|
||||
|
||||
// gets current key params. By default, should contain all null pointers.
|
||||
//
|
||||
it->second.gxs_id = senders_id ;
|
||||
|
||||
// Looks for the DH params. If not there yet, create them.
|
||||
//
|
||||
bool should_send = false ;
|
||||
|
||||
int size = DH_size(it->second.dh) ;
|
||||
unsigned char *key_buff = new unsigned char[size] ;
|
||||
|
||||
if(size == DH_compute_key(key_buff,item->public_key,it->second.dh))
|
||||
std::cerr << " DH key computation successed. New key in place." << std::endl;
|
||||
else
|
||||
{
|
||||
std::cerr << " (EE) DH computation failed. Probably a bug. Error code=" << ERR_get_error() << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// Now hash the key buffer into a 16 bytes key.
|
||||
|
||||
assert(DISTANT_CHAT_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ;
|
||||
memcpy(it->second.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
delete[] key_buff ;
|
||||
|
||||
std::cerr << " DH key computed. Tunnel is now secured!" << std::endl;
|
||||
std::cerr << " Key computed: " ; printBinaryData(it->second.aes_key,16) ; std::cerr << std::endl;
|
||||
std::cerr << " Sending a ACK packet." << std::endl;
|
||||
|
||||
// then we send an ACK packet to notify that the tunnel works. That's useful
|
||||
// because it makes the peer at the other end of the tunnel know that all
|
||||
// intermediate peer in the tunnel are able to transmit the data.
|
||||
// However, it is not possible here to call sendTurtleData(), without dead-locking
|
||||
// the turtle router, so we store the item is a list of items to be sent.
|
||||
|
||||
RsChatStatusItem *cs = new RsChatStatusItem ;
|
||||
|
||||
cs->status_string = "Tunnel is secured with PFS session. You can talk!" ;
|
||||
cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_ACK_DISTANT_CONNECTION;
|
||||
cs->PeerId(vpid);
|
||||
|
||||
pendingDistantChatItems.push_back(cs) ;
|
||||
|
||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD);
|
||||
}
|
||||
|
||||
bool p3ChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo)
|
||||
{
|
||||
RsChatDHPublicKeyItem *dhitem = new RsChatDHPublicKeyItem ;
|
||||
|
||||
if(pinfo.dh == NULL)
|
||||
{
|
||||
std::cerr << " (EE) DH struct is not initialised! Error." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
dhitem->public_key = BN_dup(pinfo.dh->pub_key) ;
|
||||
|
||||
// we should also sign the data and check the signature on the other end.
|
||||
//
|
||||
RsTlvKeySignature signature ;
|
||||
RsTlvSecurityKey signature_key ;
|
||||
RsTlvSecurityKey signature_key_public ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_MSG
|
||||
std::cerr << " Getting key material for signature with GXS id " << pingo.own_gxs_id << std::endl;
|
||||
#endif
|
||||
// The following code is only here to force caching the keys.
|
||||
//
|
||||
RsIdentityDetails details ;
|
||||
mIdService->getIdDetails(pinfo.own_gxs_id,details);
|
||||
|
||||
for(int i=0;i<6;++i)
|
||||
if(!mIdService->getPrivateKey(pinfo.own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL)
|
||||
{
|
||||
std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl;
|
||||
usleep(500000) ; // sleep for 500 msec.
|
||||
}
|
||||
else
|
||||
break ;
|
||||
|
||||
GxsSecurity::extractPublicKey(signature_key,signature_key_public) ;
|
||||
|
||||
assert(!(signature_key_public.keyFlags & RSTLV_KEY_TYPE_FULL)) ;
|
||||
|
||||
#ifdef DEBUG_DISTANT_MSG
|
||||
std::cerr << " Signing..." << std::endl;
|
||||
#endif
|
||||
uint32_t size = BN_num_bytes(dhitem->public_key) ;
|
||||
unsigned char *data = (unsigned char *)malloc(size) ;
|
||||
BN_bn2bin(dhitem->public_key, data) ;
|
||||
|
||||
if(!GxsSecurity::getSignature((char *)data,size,signature_key,signature))
|
||||
{
|
||||
std::cerr << " (EE) Cannot sign for id " << pinfo.own_gxs_id << ". Signature call failed." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
free(data) ;
|
||||
|
||||
dhitem->signature = signature ;
|
||||
dhitem->gxs_key = signature_key_public ;
|
||||
dhitem->PeerId(pinfo.virtual_peer_id) ;
|
||||
|
||||
pendingDistantChatItems.push_back(dhitem) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool p3ChatService::locked_initDHSessionKey(DistantChatPeerInfo& pinfo)
|
||||
{
|
||||
static const std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ;
|
||||
|
||||
if(pinfo.dh != NULL)
|
||||
{
|
||||
DH_free(pinfo.dh) ;
|
||||
pinfo.dh = NULL ;
|
||||
}
|
||||
|
||||
pinfo.dh = DH_new() ;
|
||||
|
||||
if(!pinfo.dh)
|
||||
{
|
||||
std::cerr << " (EE) DH_new() failed." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
BN_hex2bn(&pinfo.dh->p,dh_prime_2048_hex.c_str()) ;
|
||||
BN_hex2bn(&pinfo.dh->g,"5") ;
|
||||
|
||||
int codes = 0 ;
|
||||
|
||||
if(!DH_check(pinfo.dh, &codes) || codes != 0)
|
||||
{
|
||||
std::cerr << " (EE) DH check failed!" << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
if(!DH_generate_key(pinfo.dh))
|
||||
{
|
||||
std::cerr << " (EE) DH generate_key() failed! Error code = " << ERR_get_error() << std::endl;
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
void p3ChatService::sendTurtleData(RsChatItem *item)
|
||||
{
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
@ -3413,34 +3666,41 @@ void p3ChatService::sendTurtleData(RsChatItem *item)
|
||||
mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
|
||||
}
|
||||
|
||||
bool p3ChatService::initiateDistantChatConnexion(const RsGxsId& gxs_id,DistantChatPeerId& pid,uint32_t& error_code)
|
||||
bool p3ChatService::initiateDistantChatConnexion(const RsGxsId& gxs_id,uint32_t& error_code)
|
||||
{
|
||||
pid = DistantChatPeerId(gxs_id) ; // the two ids have the same size. Still, I prefer to have 2 different types.
|
||||
//pid = DistantChatPeerId(gxs_id) ; // the two ids have the same size. Still, I prefer to have 2 different types.
|
||||
TurtleFileHash hash = hashFromGxsId(gxs_id) ;
|
||||
|
||||
unsigned char aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||
// should be a parameter.
|
||||
|
||||
std::list<RsGxsId> lst ;
|
||||
mIdService->getOwnIds(lst) ;
|
||||
|
||||
TurtleFileHash hash = hashFromDistantChatPeerId(pid) ;
|
||||
if(lst.empty())
|
||||
{
|
||||
std::cerr << " (EE) Cannot start distant chat, since no GXS id is available." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
RsGxsId own_gxs_id = lst.front() ;
|
||||
|
||||
#warning Unfinished code here causes serious security defect.
|
||||
memset(aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
startClientDistantChatConnection(hash,gxs_id,aes_key) ;
|
||||
|
||||
RsServer::notify()->AddPopupMessage(RS_POPUP_CHAT, pid.toStdString(), "Distant peer", "Conversation starts...");
|
||||
//
|
||||
startClientDistantChatConnection(hash,gxs_id,own_gxs_id) ;
|
||||
|
||||
error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
void p3ChatService::startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& gxs_id,const unsigned char *aes_key_buf)
|
||||
void p3ChatService::startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id)
|
||||
{
|
||||
DistantChatPeerInfo info ;
|
||||
|
||||
info.last_contact = time(NULL) ;
|
||||
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
|
||||
info.gxs_id = gxs_id ;
|
||||
info.gxs_id = to_gxs_id ;
|
||||
info.own_gxs_id = from_gxs_id ;
|
||||
info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ;
|
||||
memcpy(info.aes_key,aes_key_buf,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
info.dh = NULL ;
|
||||
memset(info.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
@ -3450,6 +3710,7 @@ void p3ChatService::startClientDistantChatConnection(const RsFileHash& hash,cons
|
||||
// Now ask the turtle router to manage a tunnel for that hash.
|
||||
|
||||
#ifdef DEBUG_DISTANT_CHAT
|
||||
std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl;
|
||||
std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl;
|
||||
#endif
|
||||
|
||||
@ -3458,19 +3719,26 @@ void p3ChatService::startClientDistantChatConnection(const RsFileHash& hash,cons
|
||||
|
||||
DistantChatPeerId p3ChatService::virtualPeerIdFromHash(const TurtleFileHash& hash)
|
||||
{
|
||||
if(DistantChatPeerId::SIZE_IN_BYTES > Sha1CheckSum::SIZE_IN_BYTES)
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": Serious inconsistency error." << std::endl;
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
return DistantChatPeerId(hash.toByteArray()) ;
|
||||
std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
if(it == _distant_chat_peers.end())
|
||||
{
|
||||
std::cerr << " (EE) Cannot find hash " << hash << " in distant peers list. Virtual peer id cannot be returned." << std::endl;
|
||||
return DistantChatPeerId() ;
|
||||
}
|
||||
else
|
||||
return it->second.virtual_peer_id ;
|
||||
}
|
||||
TurtleFileHash p3ChatService::hashFromDistantChatPeerId(const DistantChatPeerId& pid)
|
||||
TurtleFileHash p3ChatService::hashFromGxsId(const RsGxsId& gid)
|
||||
{
|
||||
if(DistantChatPeerId::SIZE_IN_BYTES > Sha1CheckSum::SIZE_IN_BYTES)
|
||||
std::cerr << __PRETTY_FUNCTION__ << ": Serious inconsistency error." << std::endl;
|
||||
|
||||
unsigned char tmp[Sha1CheckSum::SIZE_IN_BYTES] ;
|
||||
memset(tmp,0,Sha1CheckSum::SIZE_IN_BYTES) ;
|
||||
memcpy(tmp,pid.toByteArray(),DistantChatPeerId::SIZE_IN_BYTES) ;
|
||||
memcpy(tmp,gid.toByteArray(),DistantChatPeerId::SIZE_IN_BYTES) ;
|
||||
|
||||
return Sha1CheckSum(tmp);
|
||||
}
|
||||
@ -3479,45 +3747,48 @@ bool p3ChatService::getDistantChatStatus(const DistantChatPeerId& pid,RsGxsId& g
|
||||
{
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
TurtleFileHash hash = hashFromDistantChatPeerId(pid) ;
|
||||
std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
if(it == _distant_chat_peers.end())
|
||||
{
|
||||
status = RS_DISTANT_CHAT_STATUS_UNKNOWN ;
|
||||
return false ;
|
||||
}
|
||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.begin() ; it != _distant_chat_peers.end();++it)
|
||||
if(it->second.virtual_peer_id == pid)
|
||||
{
|
||||
status = it->second.status ;
|
||||
gxs_id = it->second.gxs_id ;
|
||||
|
||||
status = it->second.status ;
|
||||
gxs_id = it->second.gxs_id ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
status = RS_DISTANT_CHAT_STATUS_UNKNOWN ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
bool p3ChatService::closeDistantChatConnexion(const DistantChatPeerId& pid)
|
||||
{
|
||||
// two cases:
|
||||
// - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files
|
||||
// - server needs to only close the window and let the tunnel die. But the window should only open if a message arrives.
|
||||
|
||||
TurtleFileHash hash = hashFromDistantChatPeerId(pid) ;
|
||||
// - server needs to only close the window and let the tunnel die. But the window should only open
|
||||
// if a message arrives.
|
||||
|
||||
bool is_client = false ;
|
||||
TurtleFileHash hash ;
|
||||
|
||||
RsPeerId virtual_peer_id ;
|
||||
{
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.begin() ; it != _distant_chat_peers.end();++it)
|
||||
if(it->second.virtual_peer_id == pid)
|
||||
{
|
||||
if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
||||
is_client = true ;
|
||||
|
||||
if(it == _distant_chat_peers.end()) // server side. Nothing to do.
|
||||
virtual_peer_id = it->second.virtual_peer_id ;
|
||||
hash = it->first ;
|
||||
}
|
||||
|
||||
if(virtual_peer_id.isNull())
|
||||
{
|
||||
std::cerr << "Cannot close chat associated to hash " << hash << ": not found." << std::endl;
|
||||
std::cerr << "Cannot close chat associated to virtual peer id " << pid << ": not found." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
||||
is_client = true ;
|
||||
|
||||
virtual_peer_id = it->second.virtual_peer_id ;
|
||||
}
|
||||
|
||||
if(is_client)
|
||||
@ -3546,26 +3817,21 @@ bool p3ChatService::closeDistantChatConnexion(const DistantChatPeerId& pid)
|
||||
mTurtle->stopMonitoringTunnels(hash) ;
|
||||
|
||||
// and remove hash from list of current peers.
|
||||
|
||||
DH_free(it->second.dh) ;
|
||||
_distant_chat_peers.erase(it) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
void p3ChatService::markDistantChatAsClosed(const DistantChatPeerId& pid)
|
||||
void p3ChatService::markDistantChatAsClosed(const TurtleVirtualPeerId& vpid)
|
||||
{
|
||||
RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
TurtleFileHash hash = hashFromDistantChatPeerId(pid) ;
|
||||
std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
||||
|
||||
if(it == _distant_chat_peers.end()) // server side. Nothing to do.
|
||||
{
|
||||
std::cerr << "Cannot mask distant chat as closed for hash " << hash << ": not found." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
|
||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
||||
if(it->second.virtual_peer_id == vpid)
|
||||
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,6 +45,8 @@ class p3turtle ;
|
||||
|
||||
typedef RsPeerId ChatLobbyVirtualPeerId ;
|
||||
|
||||
static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ;
|
||||
|
||||
//!The basic Chat service.
|
||||
/**
|
||||
*
|
||||
@ -55,7 +57,7 @@ typedef RsPeerId ChatLobbyVirtualPeerId ;
|
||||
class p3ChatService: public p3Service, public p3Config, public pqiServiceMonitor, public RsTurtleClientService
|
||||
{
|
||||
public:
|
||||
p3ChatService(p3ServiceControl *cs, p3LinkMgr *cm, p3HistoryMgr *historyMgr);
|
||||
p3ChatService(p3ServiceControl *cs, p3IdService *pids,p3LinkMgr *cm, p3HistoryMgr *historyMgr);
|
||||
|
||||
virtual RsServiceInfo getServiceInfo();
|
||||
|
||||
@ -332,18 +334,26 @@ class p3ChatService: public p3Service, public p3Config, public pqiServiceMonitor
|
||||
// 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& gxs_id,DistantChatPeerId& pid,uint32_t& error_code) ;
|
||||
bool initiateDistantChatConnexion(const RsGxsId& gxs_id,uint32_t& error_code) ;
|
||||
bool closeDistantChatConnexion(const DistantChatPeerId& pid) ;
|
||||
virtual bool getDistantChatStatus(const DistantChatPeerId& hash,RsGxsId& gxs_id,uint32_t& status) ;
|
||||
|
||||
private:
|
||||
struct DistantChatPeerInfo
|
||||
class DistantChatPeerInfo
|
||||
{
|
||||
public:
|
||||
DistantChatPeerInfo() { dh = NULL; }
|
||||
|
||||
time_t last_contact ; // used to send keep alive packets
|
||||
unsigned char aes_key[16] ; // key to encrypt packets
|
||||
|
||||
DH *dh ;
|
||||
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 gxs_id ; // pgp id of the peer we're talking to.
|
||||
RsGxsId gxs_id ; // gxs id of the peer we're talking to.
|
||||
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
||||
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
||||
};
|
||||
|
||||
@ -363,9 +373,15 @@ class p3ChatService: public p3Service, public p3Config, public pqiServiceMonitor
|
||||
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
|
||||
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
|
||||
void markDistantChatAsClosed(const TurtleVirtualPeerId& vpid) ;
|
||||
void startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& gxs_id,const unsigned char *aes_key_buf) ;
|
||||
void startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id) ;
|
||||
bool getHashFromVirtualPeerId(const TurtleVirtualPeerId& pid,RsFileHash& hash) ;
|
||||
TurtleFileHash hashFromDistantChatPeerId(const DistantChatPeerId& pid) ;
|
||||
TurtleFileHash hashFromGxsId(const RsGxsId& pid) ;
|
||||
|
||||
void handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) ;
|
||||
bool locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo) ;
|
||||
bool locked_initDHSessionKey(DistantChatPeerInfo& pinfo);
|
||||
DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
|
||||
|
||||
|
||||
// Utility functions
|
||||
|
||||
@ -373,9 +389,9 @@ class p3ChatService: public p3Service, public p3Config, public pqiServiceMonitor
|
||||
void sendPrivateChatItem(RsChatItem *) ;
|
||||
|
||||
static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside
|
||||
static DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
|
||||
|
||||
p3turtle *mTurtle ;
|
||||
p3IdService *mIdService ;
|
||||
};
|
||||
|
||||
class p3ChatService::StateStringInfo
|
||||
|
@ -386,7 +386,7 @@ bool p3IdService::parseRecognTag(const RsGxsId &id, const std::string &nickname,
|
||||
details.valid_to = tagitem->valid_to;
|
||||
details.tag_class = tagitem->tag_class;
|
||||
details.tag_type = tagitem->tag_type;
|
||||
details.signer = tagitem->sign.keyId;
|
||||
details.signer = tagitem->sign.keyId.toStdString();
|
||||
|
||||
details.is_valid = isValid;
|
||||
details.is_pending = isPending;
|
||||
@ -1519,7 +1519,7 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator kit;
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator kit;
|
||||
|
||||
//std::cerr << "p3IdService::cache_store() KeySet is:";
|
||||
//keySet.print(std::cerr, 10);
|
||||
@ -2137,7 +2137,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||
|
||||
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
|
||||
// find private admin key
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator mit = keySet.keys.begin();
|
||||
std::map<RsGxsId, RsTlvSecurityKey>::iterator mit = keySet.keys.begin();
|
||||
for(; mit != keySet.keys.end(); mit++)
|
||||
{
|
||||
RsTlvSecurityKey& pk = mit->second;
|
||||
@ -2989,7 +2989,7 @@ bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname
|
||||
RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
|
||||
std::map<std::string, RsGxsRecognSignerItem *>::iterator it;
|
||||
std::map<RsGxsId, RsGxsRecognSignerItem *>::iterator it;
|
||||
it = mRecognSignKeys.find(item->sign.keyId);
|
||||
if (it == mRecognSignKeys.end())
|
||||
{
|
||||
|
@ -427,8 +427,8 @@ virtual void handle_event(uint32_t event_type, const std::string &elabel);
|
||||
|
||||
std::list<RsGxsGroupId> mRecognGroupIds;
|
||||
std::list<RsGxsIdGroupItem *> mRecognGroupsToProcess;
|
||||
std::map<std::string, RsGxsRecognSignerItem *> mRecognSignKeys;
|
||||
std::map<std::string, uint32_t> mRecognOldSignKeys;
|
||||
std::map<RsGxsId, RsGxsRecognSignerItem *> mRecognSignKeys;
|
||||
std::map<RsGxsId, uint32_t> mRecognOldSignKeys;
|
||||
|
||||
/************************************************************************
|
||||
* Below is the background task for processing opinions => reputations
|
||||
|
@ -1977,7 +1977,7 @@ bool p3MsgService::decryptMessage(const std::string& mId)
|
||||
offset += tmp_data - old_data ;
|
||||
|
||||
RsTlvKeySignature signature ;
|
||||
signature.keyId = senders_id.toStdString() ;
|
||||
signature.keyId = senders_id;
|
||||
signature.signData.bin_len = signature_size ;
|
||||
signature.signData.bin_data = malloc(signature_size) ;
|
||||
memcpy(signature.signData.bin_data,&decrypted_data[offset],signature_size) ;
|
||||
|
@ -85,7 +85,7 @@ EVP_PKEY *RsRecogn::loadMasterKey()
|
||||
}
|
||||
|
||||
|
||||
bool RsRecogn::loadSigningKeys(std::map<std::string, RsGxsRecognSignerItem *> &signMap)
|
||||
bool RsRecogn::loadSigningKeys(std::map<RsGxsId, RsGxsRecognSignerItem *> &signMap)
|
||||
{
|
||||
|
||||
EVP_PKEY *signKey = loadMasterKey();
|
||||
@ -176,7 +176,7 @@ bool RsRecogn::loadSigningKeys(std::map<std::string, RsGxsRecognSignerItem *> &s
|
||||
std::cerr << "RsRecogn::loadSigningKeys() signature ok";
|
||||
std::cerr << std::endl;
|
||||
#endif // DEBUG_RECOGN
|
||||
std::string signerId = item->key.keyId;
|
||||
RsGxsId signerId = item->key.keyId;
|
||||
signMap[signerId] = item;
|
||||
}
|
||||
}
|
||||
@ -367,7 +367,7 @@ bool RsRecogn::signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item)
|
||||
|
||||
/* save signature */
|
||||
item->sign.signData.setBinData(sigbuf, siglen);
|
||||
item->sign.keyId = signId;
|
||||
item->sign.keyId = RsGxsId(signId);
|
||||
|
||||
/* clean up */
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
@ -422,7 +422,7 @@ bool RsRecogn::signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item)
|
||||
|
||||
/* save signature */
|
||||
item->sign.signData.setBinData(sigbuf, siglen);
|
||||
item->sign.keyId = signId;
|
||||
item->sign.keyId = RsGxsId(signId);
|
||||
|
||||
/* clean up */
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
@ -472,7 +472,7 @@ bool RsRecogn::signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item)
|
||||
|
||||
/* save signature */
|
||||
item->sign.signData.setBinData(sigbuf, siglen);
|
||||
item->sign.keyId = signId;
|
||||
item->sign.keyId = RsGxsId(signId);
|
||||
|
||||
/* clean up */
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
|
@ -39,7 +39,7 @@
|
||||
namespace RsRecogn {
|
||||
|
||||
EVP_PKEY * loadMasterKey();
|
||||
bool loadSigningKeys(std::map<std::string, RsGxsRecognSignerItem *> &signMap);
|
||||
bool loadSigningKeys(std::map<RsGxsId, RsGxsRecognSignerItem *> &signMap);
|
||||
bool validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item);
|
||||
|
||||
bool signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item);
|
||||
|
@ -27,10 +27,12 @@
|
||||
#include "IdDialog.h"
|
||||
#include "gui/gxs/GxsIdTreeWidgetItem.h"
|
||||
#include "gui/common/UIStateHelper.h"
|
||||
#include "gui/chat/ChatDialog.h"
|
||||
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsidentity.h>
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rsmsgs.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -131,6 +133,7 @@ IdDialog::IdDialog(QWidget *parent)
|
||||
connect(ui.toolButton_EditId, SIGNAL(clicked()), this, SLOT(editIdentity()));
|
||||
connect(ui.removeIdentity, SIGNAL(triggered()), this, SLOT(removeIdentity()));
|
||||
connect(ui.editIdentity, SIGNAL(triggered()), this, SLOT(editIdentity()));
|
||||
connect(ui.chatIdentity, SIGNAL(triggered()), this, SLOT(chatIdentity()));
|
||||
|
||||
connect(ui.treeWidget_IdList, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelection()));
|
||||
connect(ui.treeWidget_IdList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint)));
|
||||
@ -505,6 +508,7 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
mStateHelper->setWidgetEnabled(ui.toolButton_EditId, true);
|
||||
ui.editIdentity->setEnabled(true);
|
||||
ui.removeIdentity->setEnabled(true);
|
||||
ui.chatIdentity->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -514,6 +518,7 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
mStateHelper->setWidgetEnabled(ui.toolButton_EditId, false);
|
||||
ui.editIdentity->setEnabled(false);
|
||||
ui.removeIdentity->setEnabled(false);
|
||||
ui.chatIdentity->setEnabled(true);
|
||||
}
|
||||
|
||||
/* now fill in the reputation information */
|
||||
@ -779,7 +784,31 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
|
||||
QMenu contextMnu( this );
|
||||
|
||||
contextMnu.addAction(ui.editIdentity);
|
||||
contextMnu.addAction(ui.removeIdentity);
|
||||
contextMnu.addAction(ui.removeIdentity);
|
||||
contextMnu.addAction(ui.chatIdentity);
|
||||
|
||||
contextMnu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void IdDialog::chatIdentity()
|
||||
{
|
||||
QTreeWidgetItem *item = ui.treeWidget_IdList->currentItem();
|
||||
if (!item)
|
||||
{
|
||||
std::cerr << "IdDialog::editIdentity() Invalid item";
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string keyId = item->text(RSID_COL_KEYID).toStdString();
|
||||
|
||||
DistantChatPeerId virtual_peer_id ;
|
||||
uint32_t error_code ;
|
||||
|
||||
if(!rsMsgs->initiateDistantChatConnexion(RsGxsId(keyId), virtual_peer_id, error_code))
|
||||
QMessageBox::information(NULL,"Distant cannot work","Distant chat refused with this peer. Reason: "+QString::number(error_code)) ;
|
||||
else
|
||||
ChatDialog::chatFriend(virtual_peer_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,6 +61,7 @@ private slots:
|
||||
void addIdentity();
|
||||
void removeIdentity();
|
||||
void editIdentity();
|
||||
void chatIdentity();
|
||||
|
||||
void updateSelection();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<height>442</height>
|
||||
<height>497</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -676,6 +676,18 @@
|
||||
<string>Delete Identity</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="chatIdentity">
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/toaster/chat.png</normaloff>:/images/toaster/chat.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Chat with this peer</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Launches a distant chat with this peer</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
Loading…
Reference in New Issue
Block a user