From ff867d0fe546eeb0160df35987d5679f408fe904 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 18 Apr 2013 21:41:13 +0000 Subject: [PATCH] most of the protocol for distant chat works! Still needs some testing. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-GenericTunneling@6315 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pgp/pgphandler.cc | 21 ++++++-- libretroshare/src/pgp/pgphandler.h | 6 ++- libretroshare/src/retroshare/rsmsgs.h | 16 +++--- libretroshare/src/rsserver/p3msgs.cc | 4 ++ libretroshare/src/services/p3chatservice.cc | 49 ++++++++++++------- libretroshare/src/services/p3chatservice.h | 2 + libretroshare/src/turtle/p3turtle.cc | 2 + retroshare-gui/src/gui/RetroShareLink.cpp | 22 +++++++-- retroshare-gui/src/gui/chat/ChatDialog.cpp | 9 ++-- .../src/gui/chat/PopupDistantChatDialog.cpp | 26 ++++++++++ .../src/gui/chat/PopupDistantChatDialog.h | 2 +- 11 files changed, 118 insertions(+), 41 deletions(-) diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc index 2b0472476..2bec4851f 100644 --- a/libretroshare/src/pgp/pgphandler.cc +++ b/libretroshare/src/pgp/pgphandler.cc @@ -982,7 +982,7 @@ bool PGPHandler::encryptDataBin(const PGPIdType& key_id,const void *data, const int tlen = ops_memory_get_length(buf) ; bool res ; - if(*encrypted_data_len >= tlen) + if( (int)*encrypted_data_len >= tlen) { memcpy(encrypted_data,ops_memory_get_data(buf),tlen) ; *encrypted_data_len = tlen ; @@ -1000,10 +1000,23 @@ bool PGPHandler::encryptDataBin(const PGPIdType& key_id,const void *data, const return res ; } -bool PGPHandler::decryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) +bool PGPHandler::decryptDataBin(const PGPIdType& key_id,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len) { - throw std::runtime_error("Not implemented!") ; - return false ; + int out_length ; + unsigned char *out ; + ops_boolean_t res = ops_decrypt_memory((const unsigned char *)encrypted_data,encrypted_len,&out,&out_length,_secring,ops_false,cb_get_passphrase) ; + + if(*data_len < out_length) + { + std::cerr << "Not enough room to store decrypted data! Please give more."<< std::endl; + return false ; + } + + *data_len = out_length ; + memcpy(data,out,out_length) ; + free(out) ; + + return (bool)res ; } bool PGPHandler::decryptTextFromFile(const PGPIdType&,std::string& text,const std::string& inputfile) diff --git a/libretroshare/src/pgp/pgphandler.h b/libretroshare/src/pgp/pgphandler.h index 72870de91..a24186593 100644 --- a/libretroshare/src/pgp/pgphandler.h +++ b/libretroshare/src/pgp/pgphandler.h @@ -92,8 +92,10 @@ class PGPHandler bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ; bool privateSignCertificate(const PGPIdType& own_id,const PGPIdType& id_of_key_to_sign) ; - bool encryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) ; - bool decryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) ; + // The client should supply a memory chunk to store the data. The length will be updated to the real length of the data. + // + bool encryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) ; + bool decryptDataBin(const PGPIdType& key_id,const void *data, const uint32_t len, unsigned char *decrypted_data, unsigned int *decrypted_data_len) ; bool encryptTextToFile(const PGPIdType& key_id,const std::string& text,const std::string& outfile) ; bool decryptTextFromFile(const PGPIdType& key_id,std::string& text,const std::string& inputfile) ; diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index d035f4e39..f875af0b4 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -144,15 +144,15 @@ public: #define RS_CHAT_PRIVATE 0x0002 #define RS_CHAT_AVATAR_AVAILABLE 0x0004 -#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0001 -#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0002 -#define RS_DISTANT_CHAT_STATUS_TUNNEL_OK 0x0003 -#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0004 +#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000 +#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001 +#define RS_DISTANT_CHAT_STATUS_TUNNEL_OK 0x0002 +#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0003 -#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000 ; -#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001 ; -#define RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH 0x0002 ; -#define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003 ; +#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000 +#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001 +#define RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH 0x0002 +#define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003 class ChatInfo { diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index d6f4a87bb..b69b9f280 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -342,4 +342,8 @@ bool p3Msgs::initiateDistantChatConnexion(const std::string& encrypted_str,std:: { return mChatSrv->initiateDistantChatConnexion(encrypted_str,hash,error_code) ; } +uint32_t p3Msgs::getDistantChatStatus(const std::string& hash) +{ + return mChatSrv->getDistantChatStatus(hash) ; +} diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index ecc816577..a6fddba57 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -2783,26 +2783,26 @@ void p3ChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtua { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _distant_chat_invites.find(hash) ; + std::map::iterator it = _distant_chat_peers.find(hash) ; - if(it == _distant_chat_invites.end()) + if(it == _distant_chat_peers.end()) { std::cerr << "(EE) Cannot add virtual peer for hash " << hash << ": no chat invite found for that hash." << std::endl; return ; } - memcpy(_distant_chat_peers[virtual_peer_id].aes_key,it->second.aes_key,8) ; +// memcpy(_distant_chat_peers[virtual_peer_id].aes_key,it->second.aes_key,8) ; time_t now = time(NULL) ; - _distant_chat_peers[virtual_peer_id].last_contact = now ; - it->second.last_hit_time = now ; + it->second.last_contact = now ; + it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ; } void p3ChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _distant_chat_peers.find(virtual_peer_id) ; + std::map::iterator it = _distant_chat_peers.find(hash) ; if(it == _distant_chat_peers.end()) { @@ -2810,7 +2810,7 @@ void p3ChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVir return ; } - _distant_chat_peers.erase(it) ; + it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ; } void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const std::string& hash, const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) @@ -2834,7 +2834,7 @@ void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const st { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _distant_chat_peers.find(virtual_peer_id) ; + std::map::iterator it = _distant_chat_peers.find(hash) ; if(it == _distant_chat_peers.end()) { @@ -2882,7 +2882,7 @@ void p3ChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const st handleIncomingItem(citem) ; // Treats the item, and deletes it } -void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& virtual_peer_id) +void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& hash) { uint32_t rssize = item->serial_size(); uint8_t *buff = new uint8_t[rssize] ; @@ -2895,10 +2895,11 @@ void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& virtual_ } uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ; + std::string virtual_peer_id ; { RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _distant_chat_peers.find(virtual_peer_id) ; + std::map::iterator it = _distant_chat_peers.find(hash) ; if(it == _distant_chat_peers.end()) { @@ -2907,6 +2908,7 @@ void p3ChatService::sendTurtleData(RsChatItem *item, const std::string& virtual_ return ; } it->second.last_contact = time(NULL) ; + virtual_peer_id = it->second.virtual_peer_id ; memcpy(aes_key,it->second.aes_key,8) ; } // Now encrypt this data using AES. @@ -2985,12 +2987,11 @@ bool p3ChatService::createDistantChatInvite(const std::string& pgp_id,time_t tim uint32_t header_size = DISTANT_CHAT_AES_KEY_SIZE + DISTANT_CHAT_HASH_SIZE + KEY_ID_SIZE; unsigned char *data = new unsigned char[header_size+400] ; - PGPFingerprintType fingerprint ; - AuthGPG::getAuthGPG()->getKeyFingerprint( PGPIdType(AuthGPG::getAuthGPG()->getGPGOwnId()),fingerprint ) ; + PGPIdType OwnId(AuthGPG::getAuthGPG()->getGPGOwnId()); - memcpy(data ,hash_bytes ,DISTANT_CHAT_HASH_SIZE) ; - memcpy(data+DISTANT_CHAT_HASH_SIZE ,invite.aes_key ,DISTANT_CHAT_AES_KEY_SIZE) ; - memcpy(data+DISTANT_CHAT_HASH_SIZE+DISTANT_CHAT_AES_KEY_SIZE,fingerprint.toByteArray(),KEY_ID_SIZE) ; + memcpy(data ,hash_bytes ,DISTANT_CHAT_HASH_SIZE) ; + memcpy(data+DISTANT_CHAT_HASH_SIZE ,invite.aes_key ,DISTANT_CHAT_AES_KEY_SIZE) ; + memcpy(data+DISTANT_CHAT_HASH_SIZE+DISTANT_CHAT_AES_KEY_SIZE,OwnId.toByteArray(),KEY_ID_SIZE) ; std::cerr << "Performing signature " << std::endl; uint32_t signlen = 400; @@ -3037,8 +3038,8 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st // Decrypt it. // - unsigned char *data = NULL ; - uint32_t data_size ; + uint32_t data_size = encrypted_data_len+1000; + unsigned char *data = new unsigned char[data_size] ; if(!AuthGPG::getAuthGPG()->decryptDataBin((unsigned char *)encrypted_data_bin,encrypted_data_len,data,&data_size)) { @@ -3053,6 +3054,8 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st PGPIdType pgp_id( data + DISTANT_CHAT_HASH_SIZE + DISTANT_CHAT_AES_KEY_SIZE ) ; + std::cerr << "Got this PGP id: " << pgp_id.toStdString() << std::endl; + PGPFingerprintType fingerprint ; if(!AuthGPG::getAuthGPG()->getKeyFingerprint(pgp_id,fingerprint)) { @@ -3067,10 +3070,11 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st } std::cerr << "Signature successfuly verified!" << std::endl; - hash = t_RsGenericIdType(data).toStdString() ; + hash = t_RsGenericIdType(data).toStdString(false) ; DistantChatPeerInfo info ; info.last_contact = time(NULL) ; + info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ; memcpy(info.aes_key,data+DISTANT_CHAT_HASH_SIZE,DISTANT_CHAT_AES_KEY_SIZE) ; _distant_chat_peers[hash] = info ; @@ -3131,6 +3135,15 @@ bool p3ChatService::getDistantChatInviteList(std::vector& return true ; } +uint32_t p3ChatService::getDistantChatStatus(const std::string& hash) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if(_distant_chat_peers.find(hash) != _distant_chat_peers.end()) + return 1 ; + + return 0 ; +} diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index 8b9bfebba..64863a830 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -328,6 +328,8 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi { time_t last_contact ; // used to send keep alive packets unsigned char aes_key[16] ; // key to encrypt packets + uint32_t status ; // info: do we have a tunnel ? + std::string virtual_peer_id; // given by the turtle router. Identifies the tunnel. }; // This map contains the ongoing invites. This is the list where to look to diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index 36d9e1a8f..fbf1e5f15 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -1122,6 +1122,8 @@ bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,std::string& vpid,s } service = it->second.service ; + + return true ; } // Send a data request into the correct tunnel for the given file hash // diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 7b1290568..fa4d96957 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -41,6 +41,7 @@ #include "gui/connect/ConfCertDialog.h" #include +#include #include #include #include @@ -1202,17 +1203,30 @@ static void processList(const QStringList &list, const QString &textSingular, co if(link._time_stamp < time(NULL)) { - QMessageBox::information(NULL,tr("Chat link is expired"),tr("This chat link is expired. The destination peer will not answer.")) ; + QMessageBox::information(NULL,QObject::tr("Chat link is expired"),QObject::tr("This chat link is expired. The destination peer will not answer.")) ; break ; } if(link._GPGid.toStdString() != rsPeers->getGPGOwnId()) { - QMessageBox::information(NULL,tr("Chat link cannot be decrypted"),tr("This chat link is encrypted with a key that is not yours. You can't used it. Key ID = ")+link._GPGId) ; + QMessageBox::information(NULL,QObject::tr("Chat link cannot be decrypted"),QObject::tr("This chat link is encrypted with a key that is not yours. You can't used it. Key ID = ")+link._GPGid) ; break ; } - if(!rsMsgs->initiateDistantChatConnexion(link._encrypted_chat_info.toStdString())) - QMessageBox::information(NULL,tr("Chat connexion is not possible"),tr("The distant chat connexion cannot be openned. Sorry.")) ; + std::string hash ; + uint32_t error_code ; + + if(!rsMsgs->initiateDistantChatConnexion(link._encrypted_chat_info.toStdString(),hash,error_code)) + { + QString error_msg ; + switch(error_code) + { + default: + case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED: error_msg = QObject::tr("The link could not be decrypted.") ; break ; + case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH: error_msg = QObject::tr("The link signature cannot be checked.") ; break ; + case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY: error_msg = QObject::tr("The link is signed by an unknown key.") ; break ; + } + QMessageBox::information(NULL,QObject::tr("Chat connexion is not possible"),error_msg) ; + } } break ; diff --git a/retroshare-gui/src/gui/chat/ChatDialog.cpp b/retroshare-gui/src/gui/chat/ChatDialog.cpp index bee901e1d..22721e84c 100644 --- a/retroshare-gui/src/gui/chat/ChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatDialog.cpp @@ -98,9 +98,10 @@ void ChatDialog::init(const std::string &peerId, const QString &title) if (rsMsgs->isLobbyId(peerId, lobby_id)) { chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags } - std::string distant_pgp_id = "" ; - if(distant_peer = rsMsgs->isDistantId(peerId,distant_pgp_id)) { + uint32_t distant_peer_status ; + + if(distant_peer_status = rsMsgs->getDistantChatStatus(peerId)) { chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags } @@ -116,10 +117,10 @@ void ChatDialog::init(const std::string &peerId, const QString &title) cd->init(peerId, QString::fromUtf8((*it).lobby_name.c_str())); } } - } else if(distant_peer) { + } else if(distant_peer_status > 0) { cd = new PopupDistantChatDialog(); chatDialogs[peerId] = cd; - cd->init(peerId, tr("Distant peer (PGP id=%1)").arg(distant_pgp_id)); + cd->init(peerId, tr("Distant peer (PGP id=%1)")) ; } else { RsPeerDetails sslDetails; if (rsPeers->getPeerDetails(peerId, sslDetails)) { diff --git a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp index a6f2b6ff6..68655998e 100644 --- a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.cpp @@ -1,6 +1,32 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2013, Cyril Soler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + #include #include "PopupDistantChatDialog.h" +PopupDistantChatDialog::~PopupDistantChatDialog() +{ + delete _tunnel_check_timer ; +} + PopupDistantChatDialog::PopupDistantChatDialog(QWidget *parent, Qt::WFlags flags) : PopupChatDialog(parent,flags) { diff --git a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.h b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.h index ef03d2c42..468b11383 100644 --- a/retroshare-gui/src/gui/chat/PopupDistantChatDialog.h +++ b/retroshare-gui/src/gui/chat/PopupDistantChatDialog.h @@ -2,7 +2,7 @@ /**************************************************************** * RetroShare is distributed under the following license: * - * Copyright (C) 2006, crypton + * Copyright (C) 2013, Cyril Soler * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License