diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index a7193cdb9..fdaa88525 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -163,6 +163,9 @@ public: #define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003 #define RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH 0x0004 +#define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001 +#define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002 + class ChatInfo { public: @@ -220,6 +223,7 @@ struct DistantChatInviteInfo std::string encrypted_radix64_string ; // encrypted radix string used to for the chat link std::string destination_pgp_id ; // pgp is of the destination of the chat link time_t time_of_validity ; // time when te invite becomes unusable + uint32_t invite_flags ; // used to keep track of wether signature was ok or not. }; std::ostream &operator<<(std::ostream &out, const MessageInfo &info); diff --git a/libretroshare/src/serialiser/rsmsgitems.cc b/libretroshare/src/serialiser/rsmsgitems.cc index 5e0c5131b..a86252269 100644 --- a/libretroshare/src/serialiser/rsmsgitems.cc +++ b/libretroshare/src/serialiser/rsmsgitems.cc @@ -208,6 +208,9 @@ std::ostream& RsPrivateChatDistantInviteConfigItem::print(std::ostream &out, uin printIndent(out, int_Indent); out << "time of last hit: " << last_hit_time << std::endl; + printIndent(out, int_Indent); + out << "flags: " << flags << std::endl; + printRsItemEnd(out, "RsPrivateChatDistantInviteConfigItem", indent); return out; } @@ -432,6 +435,7 @@ uint32_t RsPrivateChatDistantInviteConfigItem::serial_size() s += 16; /* aes_key */ s += 4; /* time_of_validity */ s += 4; /* last_hit_time */ + s += 4; /* flags */ return s; } @@ -849,6 +853,7 @@ bool RsPrivateChatDistantInviteConfigItem::serialise(void *data, uint32_t& pktsi ok &= setRawUInt32(data, tlvsize, &offset, time_of_validity); ok &= setRawUInt32(data, tlvsize, &offset, last_hit_time); + ok &= setRawUInt32(data, tlvsize, &offset, flags); if (offset != tlvsize) { @@ -1256,6 +1261,11 @@ RsPrivateChatDistantInviteConfigItem::RsPrivateChatDistantInviteConfigItem(void ok &= getRawUInt32(data, rssize, &offset, &time_of_validity); ok &= getRawUInt32(data, rssize, &offset, &last_hit_time); + if(offset+4 == rssize) // flags are optional for retro-compatibility. + ok &= getRawUInt32(data, rssize, &offset, &flags); + else + flags = 0 ; + #ifdef CHAT_DEBUG std::cerr << "Building new chat msg config item." << std::endl ; #endif diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index d0616b393..70924c7f5 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -338,6 +338,7 @@ class RsPrivateChatDistantInviteConfigItem: public RsChatItem std::string destination_pgp_id ; uint32_t time_of_validity ; uint32_t last_hit_time ; + uint32_t flags ; }; class RsChatLobbyConfigItem: public RsChatItem { diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index e42c58b5a..fb88adbe5 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -1989,6 +1989,7 @@ bool p3ChatService::loadList(std::list& load) invite.destination_pgp_id = ditem->destination_pgp_id ; invite.time_of_validity = ditem->time_of_validity ; invite.last_hit_time = ditem->last_hit_time ; + invite.flags = ditem->flags ; _distant_chat_invites[ditem->hash] = invite ; @@ -2075,6 +2076,7 @@ bool p3ChatService::saveList(bool& cleanup, std::list& list) ei->destination_pgp_id = it->second.destination_pgp_id ; ei->time_of_validity = it->second.time_of_validity ; ei->last_hit_time = it->second.last_hit_time ; + ei->flags = it->second.flags ; list.push_back(ei) ; } @@ -3573,11 +3575,8 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st return false ; } - if(!AuthGPG::getAuthGPG()->VerifySignBin(data,header_size,data+header_size,data_size-header_size,fingerprint.toStdString())) - { - error_code = RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH ; - return false ; - } + bool signature_checked = AuthGPG::getAuthGPG()->VerifySignBin(data,header_size,data+header_size,data_size-header_size,fingerprint.toStdString()) ; + #ifdef DEBUG_DISTANT_CHAT std::cerr << "Signature successfuly verified!" << std::endl; #endif @@ -3593,6 +3592,7 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st dinvite.destination_pgp_id = pgp_id.toStdString() ; dinvite.time_of_validity = time_of_validity ; dinvite.last_hit_time = time(NULL) ; + dinvite.flags = RS_DISTANT_CHAT_FLAG_SIGNED | (signature_checked ? RS_DISTANT_CHAT_FLAG_SIGNATURE_OK : 0) ; memcpy(dinvite.aes_key,data+DISTANT_CHAT_HASH_SIZE,DISTANT_CHAT_AES_KEY_SIZE) ; { @@ -3610,7 +3610,8 @@ bool p3ChatService::initiateDistantChatConnexion(const std::string& encrypted_st // And notify about chatting. - error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ; + error_code = signature_checked ? RS_DISTANT_CHAT_ERROR_NO_ERROR : RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY; + getPqiNotify()->AddPopupMessage(RS_POPUP_CHAT, hash, "Distant peer", "Conversation starts..."); // Save config, since a new invite was added. @@ -3713,6 +3714,7 @@ bool p3ChatService::getDistantChatInviteList(std::vector& info.encrypted_radix64_string = it->second.encrypted_radix64_string ; info.time_of_validity = it->second.time_of_validity ; info.destination_pgp_id = it->second.destination_pgp_id ; + info.invite_flags = it->second.flags ; invites.push_back(info); } diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h index b21ced51c..7aab8d30c 100644 --- a/libretroshare/src/services/p3chatservice.h +++ b/libretroshare/src/services/p3chatservice.h @@ -344,6 +344,7 @@ class p3ChatService: public p3Service, public p3Config, public pqiMonitor, publi std::string destination_pgp_id ; time_t time_of_validity ; time_t last_hit_time ; + uint32_t flags ; }; struct DistantChatPeerInfo { diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 945f680d1..fc35c2fbc 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -1274,7 +1274,12 @@ static void processList(const QStringList &list, const QString &textSingular, co QMessageBox::information(NULL,QObject::tr("Chat connection is not possible"),error_msg) ; } else + { + if(error_code == RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY) + QMessageBox::information(NULL,QObject::tr("Chat connection is unauthentified"),QObject::tr("Signature check failed!\nMake sure you know who you're talking to.")) ; + ChatDialog::chatFriend(hash); + } } break ; diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index 7c7e88d48..82832b17e 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -9,6 +9,8 @@ images/edit_24.png images/stock_signature_bad.png images/stock_signature_ok.png + images/stock_signature_missing.png + images/stock_signature_unverified.png images/anonymous_128_blue.png images/browsable_128_green.png images/browsable_128_blue.png diff --git a/retroshare-gui/src/gui/images/stock_signature_missing.png b/retroshare-gui/src/gui/images/stock_signature_missing.png new file mode 100644 index 000000000..66c03a4e6 Binary files /dev/null and b/retroshare-gui/src/gui/images/stock_signature_missing.png differ diff --git a/retroshare-gui/src/gui/images/stock_signature_unverified.png b/retroshare-gui/src/gui/images/stock_signature_unverified.png new file mode 100644 index 000000000..aae661fa6 Binary files /dev/null and b/retroshare-gui/src/gui/images/stock_signature_unverified.png differ diff --git a/retroshare-gui/src/gui/settings/ChatPage.cpp b/retroshare-gui/src/gui/settings/ChatPage.cpp index d9ec376c4..072ee1ca3 100644 --- a/retroshare-gui/src/gui/settings/ChatPage.cpp +++ b/retroshare-gui/src/gui/settings/ChatPage.cpp @@ -402,8 +402,32 @@ ChatPage::load() if(invites[i].encrypted_radix64_string.empty()) { QListWidgetItem *item = new QListWidgetItem; - item->setData(Qt::DisplayRole,tr("Private chat invite from ")+QString::fromStdString(detail.name)+" ("+QString::fromStdString(invites[i].destination_pgp_id)+", " + QString::fromStdString(detail.name) + ", valid until " + QDateTime::fromTime_t(invites[i].time_of_validity).toString() + ")") ; + item->setData(Qt::DisplayRole,tr("Private chat invite from ")+QString::fromUtf8(detail.name.c_str())) ; + + QString tt ; + tt += tr("Name : ") + QString::fromStdString(detail.name) ; + tt += "\n" + QString("PGP id : ") + QString::fromStdString(invites[i].destination_pgp_id) ; + tt += "\n" + QString("Valid until : ") + QDateTime::fromTime_t(invites[i].time_of_validity).toString() ; + + if(invites[i].invite_flags & RS_DISTANT_CHAT_FLAG_SIGNED) + if(invites[i].invite_flags & RS_DISTANT_CHAT_FLAG_SIGNATURE_OK) + { + tt += "\n"+tr("Authentified signature") ; + item->setIcon(QIcon(":images/stock_signature_ok.png")) ; + } + else + { + tt += "\n"+tr("Signed with key not in keyring") ; + item->setIcon(QIcon(":images/stock_signature_unverified.png")) ; + } + else + { + tt += "\n"+tr("Not signed.") ; + item->setIcon(QIcon(":images/stock_signature_missing.png")) ; + } + item->setData(Qt::UserRole,QString::fromStdString(invites[i].hash)) ; + item->setToolTip(tt) ; ui._collected_contacts_LW->insertItem(0,item) ; }