diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index 964d00266..e2c195984 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -59,6 +59,8 @@ #define RS_MSG_FRIEND_RECOMMENDATION 0x0800 /* friend recommendation */ #define RS_MSG_SYSTEM (RS_MSG_USER_REQUEST | RS_MSG_FRIEND_RECOMMENDATION) #define RS_MSG_ENCRYPTED 0x1000 /* message is encrypted */ +#define RS_MSG_SIGNATURE_CHECKS 0x2000 /* message was signed, and signature checked */ +#define RS_MSG_SIGNED 0x4000 /* message was signed and signature didn't check */ #define RS_CHAT_LOBBY_EVENT_PEER_LEFT 0x01 #define RS_CHAT_LOBBY_EVENT_PEER_STATUS 0x02 diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index 5fed960c6..07e214e71 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -412,23 +412,25 @@ class RsChatSerialiser: public RsSerialType /**************************************************************************/ -const uint32_t RS_MSG_FLAGS_OUTGOING = 0x0001; -const uint32_t RS_MSG_FLAGS_PENDING = 0x0002; -const uint32_t RS_MSG_FLAGS_DRAFT = 0x0004; -const uint32_t RS_MSG_FLAGS_NEW = 0x0010; -const uint32_t RS_MSG_FLAGS_TRASH = 0x0020; -const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x0040; -const uint32_t RS_MSG_FLAGS_REPLIED = 0x0080; -const uint32_t RS_MSG_FLAGS_FORWARDED = 0x0100; -const uint32_t RS_MSG_FLAGS_STAR = 0x0200; -const uint32_t RS_MSG_FLAGS_PARTIAL = 0x0400; +const uint32_t RS_MSG_FLAGS_OUTGOING = 0x00000001; +const uint32_t RS_MSG_FLAGS_PENDING = 0x00000002; +const uint32_t RS_MSG_FLAGS_DRAFT = 0x00000004; +const uint32_t RS_MSG_FLAGS_NEW = 0x00000010; +const uint32_t RS_MSG_FLAGS_TRASH = 0x00000020; +const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x00000040; +const uint32_t RS_MSG_FLAGS_REPLIED = 0x00000080; +const uint32_t RS_MSG_FLAGS_FORWARDED = 0x00000100; +const uint32_t RS_MSG_FLAGS_STAR = 0x00000200; +const uint32_t RS_MSG_FLAGS_PARTIAL = 0x00000400; // system message -const uint32_t RS_MSG_FLAGS_USER_REQUEST = 0x0800; -const uint32_t RS_MSG_FLAGS_FRIEND_RECOMMENDATION = 0x1000; +const uint32_t RS_MSG_FLAGS_USER_REQUEST = 0x00000800; +const uint32_t RS_MSG_FLAGS_FRIEND_RECOMMENDATION = 0x00001000; const uint32_t RS_MSG_FLAGS_SYSTEM = RS_MSG_FLAGS_USER_REQUEST | RS_MSG_FLAGS_FRIEND_RECOMMENDATION; -const uint32_t RS_MSG_FLAGS_RETURN_RECEPT = 0x2000; -const uint32_t RS_MSG_FLAGS_ENCRYPTED = 0x4000; -const uint32_t RS_MSG_FLAGS_DISTANT = 0x8000; +const uint32_t RS_MSG_FLAGS_RETURN_RECEPT = 0x00002000; +const uint32_t RS_MSG_FLAGS_ENCRYPTED = 0x00004000; +const uint32_t RS_MSG_FLAGS_DISTANT = 0x00008000; +const uint32_t RS_MSG_FLAGS_SIGNATURE_CHECKS = 0x00010000; +const uint32_t RS_MSG_FLAGS_SIGNED = 0x00020000; class RsMsgItem: public RsItem { diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index dd9a5caf6..d251a83e1 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -54,6 +54,8 @@ static const uint32_t RS_DISTANT_MSG_STATUS_TUNNEL_OK = 0x0001 ; static const uint32_t RS_DISTANT_MSG_STATUS_TUNNEL_DN = 0x0000 ; static const uint32_t DISTANT_MSG_HASH_SIZE = 20 ; +static const uint8_t ENCRYPTED_MSG_PROTOCOL_VERSION_01 = 0x37 ; + /* Another little hack ..... unique message Ids * will be handled in this class..... * These are unique within this run of the server, @@ -1400,6 +1402,12 @@ void p3MsgService::initRsMI(RsMsgItem *msg, MessageInfo &mi) mi.msgflags |= RS_MSG_NEW; } + if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) + mi.msgflags |= RS_MSG_SIGNED ; + + if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) + mi.msgflags |= RS_MSG_SIGNATURE_CHECKS ; + if (msg->msgFlags & RS_MSG_FLAGS_ENCRYPTED) mi.msgflags |= RS_MSG_ENCRYPTED ; @@ -1491,6 +1499,12 @@ void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis) if (msg->msgFlags & RS_MSG_FLAGS_ENCRYPTED) mis.msgflags |= RS_MSG_ENCRYPTED ; + if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) + mis.msgflags |= RS_MSG_SIGNED ; + + if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) + mis.msgflags |= RS_MSG_SIGNATURE_CHECKS ; + /* translate flags, if we sent it... outgoing */ if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) /*|| (msg->PeerId() == mLinkMgr->getOwnId())*/) @@ -1609,6 +1623,9 @@ RsMsgItem *p3MsgService::initMIRsMsg(MessageInfo &info, const std::string &to) if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION) msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; + if (info.msgflags & RS_MSG_SIGNED) + msg->msgFlags |= RS_MSG_FLAGS_SIGNED; + // See if we need to encrypt this message. If so, we replace the msg text // by the whole message serialized and binary encrypted, so as to obfuscate // all its content. @@ -1628,32 +1645,96 @@ bool p3MsgService::encryptMessage(const std::string& pgp_id,RsMsgItem *item) std::cerr << "Encrypting message with public key " << pgp_id << " in place." << std::endl; #endif - // 1 - serialise the whole message item into a binary chunk. + // 0 - happend own id to the data. // uint32_t rssize = _serialiser->size(item) ; - unsigned char *data = new unsigned char[rssize] ; + unsigned char *data = (unsigned char *)malloc(1+rssize+KEY_ID_SIZE) ; + + // -1 - setup protocol version + // +#ifdef DEBUG_DISTANT_MSG + std::cerr << " adding protocol version TAG = " << std::hex << (int)ENCRYPTED_MSG_PROTOCOL_VERSION_01 << std::dec << std::endl; +#endif + data[0] = ENCRYPTED_MSG_PROTOCOL_VERSION_01 ; + +#ifdef DEBUG_DISTANT_MSG + std::cerr << " adding own key ID " << AuthGPG::getAuthGPG()->getGPGOwnId() << std::endl; +#endif + memcpy(&data[1], PGPIdType(AuthGPG::getAuthGPG()->getGPGOwnId()).toByteArray(), KEY_ID_SIZE) ; - if(!_serialiser->serialise(item,data,&rssize)) + // 1 - serialise the whole message item into a binary chunk. + // + +#ifdef DEBUG_DISTANT_MSG + std::cerr << " serialising item..." << std::endl; +#endif + if(!_serialiser->serialise(item,&data[1+KEY_ID_SIZE],&rssize)) { std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; - delete[] data ; + free(data) ; return false; } - // 2 - pgp-encrypt the chunk with the user-supplied public key. + // 2 - now sign the data, if necessary, and put the signature up front + + uint32_t signature_length = 0 ; + unsigned char *signature_data = NULL ; + + if(item->msgFlags & RS_MSG_FLAGS_SIGNED) + { +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Signing the message..." << std::endl; +#endif + signature_length = 2000 ; + signature_data = new unsigned char[signature_length] ; + + if(!AuthGPG::getAuthGPG()->SignDataBin(data,1+rssize+KEY_ID_SIZE,signature_data,&signature_length)) + { + free(data) ; + std::cerr << "Signature failed!" << std::endl; + return false; + } +#ifdef DEBUG_DISTANT_MSG + std::cerr << " After signature: signature size = " << signature_length << std::endl; +#endif + } +#ifdef DEBUG_DISTANT_MSG + std::cerr << " total decrypted size = " << KEY_ID_SIZE + 1 + rssize + signature_length << std::endl; +#endif + // 3 - happend the signature to the serialized data. + + if(signature_length > 0) + { +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Appending signature." << std::endl; +#endif + data = (uint8_t*)realloc(data,1+rssize+signature_length+KEY_ID_SIZE) ; + memcpy(&data[1+rssize+KEY_ID_SIZE],signature_data,signature_length) ; + } + + // 2 - pgp-encrypt the whole chunk with the user-supplied public key. // - uint32_t encrypted_size = rssize + 1000 ; + uint32_t encrypted_size = 1+rssize + KEY_ID_SIZE + signature_length + 1000 ; unsigned char *encrypted_data = new unsigned char[encrypted_size] ; - if(!AuthGPG::getAuthGPG()->encryptDataBin(pgp_id,data,rssize,encrypted_data,&encrypted_size)) +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Encrypting for Key ID " << pgp_id << std::endl; +#endif + if(!AuthGPG::getAuthGPG()->encryptDataBin(pgp_id,data,1+rssize+signature_length+KEY_ID_SIZE,encrypted_data,&encrypted_size)) { - delete[] data ; + free(data) ; delete[] encrypted_data ; std::cerr << "Encryption failed!" << std::endl; return false; } - delete[] data ; + free(data) ; +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Decrypted size = " << 1+rssize+signature_length+KEY_ID_SIZE << std::endl; + std::cerr << " Encrypted size = " << encrypted_size << std::endl; + std::cerr << " First bytes of encrypted data: " << std::hex << (int)encrypted_data[0] << " " << (int)encrypted_data[1] << " " << (int)encrypted_data[2] << std::dec << std::endl; + std::cerr << " Encrypted data hash = " << RsDirUtil::sha1sum(encrypted_data,encrypted_size).toStdString() << std::endl; +#endif // Now turn the binary encrypted chunk into a readable radix string. // std::string armoured_data ; @@ -1662,6 +1743,9 @@ bool p3MsgService::encryptMessage(const std::string& pgp_id,RsMsgItem *item) std::wstring encrypted_msg ; +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Converting to radix64" << std::endl; +#endif if(!librs::util::ConvertUtf8ToUtf16(armoured_data,encrypted_msg)) return false; @@ -1675,6 +1759,9 @@ bool p3MsgService::encryptMessage(const std::string& pgp_id,RsMsgItem *item) item->msgFlags |= RS_MSG_FLAGS_ENCRYPTED ; item->attachment.TlvClear() ; +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Done" << std::endl; +#endif return true ; } @@ -1704,12 +1791,17 @@ bool p3MsgService::decryptMessage(const std::string& mId) Radix64::decode(encrypted_string,encrypted_data,encrypted_size) ; #ifdef DEBUG_DISTANT_MSG - std::cerr << "Message has been radix64 decoded." << std::endl; + std::cerr << " Message has been radix64 decoded." << std::endl; #endif uint32_t decrypted_size = encrypted_size + 500 ; unsigned char *decrypted_data = new unsigned char[decrypted_size] ; +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Calling decryption. Encrypted data size = " << encrypted_size << ", Allocated size = " << decrypted_size << std::endl; + std::cerr << " First bytes of encrypted data: " << std::hex << (int)((unsigned char*)encrypted_data)[0] << " " << (int)((unsigned char*)encrypted_data)[1] << " " << (int)((unsigned char*)encrypted_data)[2] << std::dec << std::endl; + std::cerr << " Encrypted data hash = " << RsDirUtil::sha1sum((uint8_t*)encrypted_data,encrypted_size).toStdString() << std::endl; +#endif if(!AuthGPG::getAuthGPG()->decryptDataBin(encrypted_data,encrypted_size,decrypted_data,&decrypted_size)) { delete[] encrypted_data ; @@ -1718,10 +1810,36 @@ bool p3MsgService::decryptMessage(const std::string& mId) return false; } #ifdef DEBUG_DISTANT_MSG - std::cerr << "Message has succesfully decrypted." << std::endl; + std::cerr << " Message has succesfully decrypted. Decrypted size = " << decrypted_size << std::endl; #endif - RsMsgItem *item = dynamic_cast(_serialiser->deserialise(decrypted_data,&decrypted_size)) ; + // 1 - get the sender's id + + unsigned char protocol_version = decrypted_data[0] ; + +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Read protocol version number " << std::hex << (int)protocol_version << std::dec << std::endl; +#endif + if(protocol_version != ENCRYPTED_MSG_PROTOCOL_VERSION_01) + { + std::cerr << "Bad version number " << std::hex << (int)protocol_version << std::dec << " => packet is dropped." << std::endl; + delete[] encrypted_data ; + delete[] decrypted_data ; + return false; + } + + PGPIdType senders_id(&decrypted_data[1]) ; + +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Sender's ID: " << senders_id.toStdString() << std::endl; +#endif + // 2 - deserialize the item + +#ifdef DEBUG_DISTANT_MSG + std::cerr << " Deserializing..." << std::endl; +#endif + uint32_t item_size = decrypted_size ; // just needs to be larger than the actual size. + RsMsgItem *item = dynamic_cast(_serialiser->deserialise(&decrypted_data[1+KEY_ID_SIZE],&item_size)) ; if(item == NULL) { @@ -1729,8 +1847,40 @@ bool p3MsgService::decryptMessage(const std::string& mId) return false ; } + // 3 - check signature + + bool signature_present = false ; + bool signature_ok = false ; + + if(1+item_size + KEY_ID_SIZE < decrypted_size) + { + std::cerr << " Signature is present. Verifying it..." << std::endl; + + PGPFingerprintType fingerprint ; + if(!AuthGPG::getAuthGPG()->getKeyFingerprint(senders_id,fingerprint)) + { + std::cerr << "Cannot get fingerprint" << std::endl; + return false ; + } + std::cerr << " Fingerprint = " << fingerprint.toStdString() << std::endl; + + signature_present = true ; + signature_ok = AuthGPG::getAuthGPG()->VerifySignBin(decrypted_data, 1+KEY_ID_SIZE+item_size, &decrypted_data[1+KEY_ID_SIZE+item_size], decrypted_size - KEY_ID_SIZE - item_size - 1, fingerprint.toStdString()) ; + } + else if(1 + item_size + KEY_ID_SIZE == decrypted_size) + std::cerr << " No signature in this packet" << std::endl; + else + { + std::cerr << "Structural error in packet: sizes do not match. Dropping the message." << std::endl; + return false ; + } + + delete[] decrypted_data ; + + // 4 - replace the item with the decrypted data, and update flags + #ifdef DEBUG_DISTANT_MSG - std::cerr << "Decrypted message was succesfully deserialized. New message:" << std::endl; + std::cerr << " Decrypted message was succesfully deserialized. New message:" << std::endl; item->print(std::cerr,0) ; #endif { @@ -1742,6 +1892,17 @@ bool p3MsgService::decryptMessage(const std::string& mId) msgi = *item ; // copy everything msgi.msgId = msgId ; // restore the correct message id, to make it consistent msgi.msgFlags &= ~RS_MSG_FLAGS_ENCRYPTED ; // just in case. + msgi.PeerId(senders_id.toStdString()) ; + + if(signature_present) + { + msgi.msgFlags |= RS_MSG_FLAGS_SIGNED ; + + if(signature_ok) + msgi.msgFlags |= RS_MSG_FLAGS_SIGNATURE_CHECKS ; // just in case. + else + msgi.msgFlags &= ~RS_MSG_FLAGS_SIGNATURE_CHECKS ; // just in case. + } } delete item ; @@ -1972,7 +2133,7 @@ void p3MsgService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVir remove_tunnel = true ; } - if(remove_tunnel) + if(remove_tunnel) // We do that whenever we're client or server. But normally, we should only do it when we're client. { #ifdef DEBUG_DISTANT_MSG std::cerr << "Also removing tunnel, since pending messages have been sent." << std::endl; @@ -1997,22 +2158,23 @@ void p3MsgService::sendTurtleData(const std::string& hash,RsMsgItem *msgitem) { // The item is serialized and turned into a generic turtle item. - uint32_t rssize = _serialiser->size(msgitem) ; - unsigned char *data = new unsigned char[rssize] ; + uint32_t msg_serialized_rssize = _serialiser->size(msgitem) ; + unsigned char *msg_serialized_data = new unsigned char[msg_serialized_rssize] ; - if(!_serialiser->serialise(msgitem,data,&rssize)) + if(!_serialiser->serialise(msgitem,msg_serialized_data,&msg_serialized_rssize)) { std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; - delete[] data ; + delete[] msg_serialized_data ; return ; } RsTurtleGenericDataItem *item = new RsTurtleGenericDataItem ; - item->data_bytes = malloc(rssize) ; - item->data_size = rssize ; - memcpy(item->data_bytes,data,rssize) ; - delete[] data ; + item->data_bytes = malloc(msg_serialized_rssize) ; + item->data_size = msg_serialized_rssize ; + memcpy(item->data_bytes,msg_serialized_data,msg_serialized_rssize) ; + + delete[] msg_serialized_data ; #ifdef DEBUG_DISTANT_MSG printBinaryData(item->data_bytes,item->data_size) ; @@ -2030,7 +2192,7 @@ void p3MsgService::sendTurtleData(const std::string& hash,RsMsgItem *msgitem) if(it == _messenging_contacts.end()) { std::cerr << "(EE) p3MsgService::sendTurtleData(): Can't find hash " << hash << " in recorded contact list." << std::endl; - delete[] data ; + delete[] msg_serialized_data ; return ; } diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp index 4b7e78112..5898fa328 100644 --- a/retroshare-gui/src/gui/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -36,6 +36,7 @@ #include "common/PeerDefs.h" #include "common/RSItemDelegate.h" #include "util/DateTime.h" +#include "util/RsProtectedTimer.h" #include #include @@ -49,15 +50,16 @@ #define IMAGE_STAR_OFF ":/images/star-off-16.png" #define IMAGE_SYSTEM ":/images/user/user_request16.png" -#define COLUMN_COUNT 8 #define COLUMN_STAR 0 #define COLUMN_ATTACHEMENTS 1 #define COLUMN_SUBJECT 2 #define COLUMN_UNREAD 3 #define COLUMN_FROM 4 -#define COLUMN_DATE 5 -#define COLUMN_CONTENT 6 -#define COLUMN_TAGS 7 +#define COLUMN_SIGNATURE 5 +#define COLUMN_DATE 6 +#define COLUMN_CONTENT 7 +#define COLUMN_TAGS 8 +#define COLUMN_COUNT 9 #define COLUMN_DATA 0 // column for storing the userdata like msgid and srcid @@ -155,6 +157,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) MessagesModel->setHeaderData(COLUMN_SUBJECT, Qt::Horizontal, tr("Subject")); MessagesModel->setHeaderData(COLUMN_UNREAD, Qt::Horizontal, QIcon(":/images/message-state-header.png"), Qt::DecorationRole); MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("From")); + MessagesModel->setHeaderData(COLUMN_SIGNATURE, Qt::Horizontal, QIcon(":/images/signature.png"),Qt::DecorationRole); MessagesModel->setHeaderData(COLUMN_DATE, Qt::Horizontal, tr("Date")); MessagesModel->setHeaderData(COLUMN_TAGS, Qt::Horizontal, tr("Tags")); MessagesModel->setHeaderData(COLUMN_CONTENT, Qt::Horizontal, tr("Content")); @@ -164,6 +167,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) MessagesModel->setHeaderData(COLUMN_SUBJECT, Qt::Horizontal, tr("Click to sort by subject"), Qt::ToolTipRole); MessagesModel->setHeaderData(COLUMN_UNREAD, Qt::Horizontal, tr("Click to sort by read"), Qt::ToolTipRole); MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("Click to sort by from"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_SIGNATURE, Qt::Horizontal, tr("Click to sort by signature"), Qt::ToolTipRole); MessagesModel->setHeaderData(COLUMN_DATE, Qt::Horizontal, tr("Click to sort by date"), Qt::ToolTipRole); MessagesModel->setHeaderData(COLUMN_TAGS, Qt::Horizontal, tr("Click to sort by tags"), Qt::ToolTipRole); MessagesModel->setHeaderData(COLUMN_STAR, Qt::Horizontal, tr("Click to sort by star"), Qt::ToolTipRole); @@ -201,6 +205,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) msgwheader->resizeSection (COLUMN_SUBJECT, 250); msgwheader->resizeSection (COLUMN_UNREAD, 16); msgwheader->resizeSection (COLUMN_FROM, 140); + msgwheader->resizeSection (COLUMN_SIGNATURE, 16); msgwheader->resizeSection (COLUMN_DATE, 140); msgwheader->resizeSection (COLUMN_STAR, 16); @@ -240,7 +245,9 @@ MessagesDialog::MessagesDialog(QWidget *parent) msgwheader->setResizeMode (COLUMN_ATTACHEMENTS, QHeaderView::Fixed); msgwheader->setResizeMode (COLUMN_DATE, QHeaderView::Interactive); msgwheader->setResizeMode (COLUMN_UNREAD, QHeaderView::Fixed); + msgwheader->setResizeMode (COLUMN_SIGNATURE, QHeaderView::Fixed); msgwheader->resizeSection (COLUMN_UNREAD, 24); + msgwheader->resizeSection (COLUMN_SIGNATURE, 16); msgwheader->resizeSection (COLUMN_STAR, 24); msgwheader->setResizeMode (COLUMN_STAR, QHeaderView::Fixed); msgwheader->setStretchLastSection(false); @@ -261,7 +268,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) fillQuickView(); // create timer for navigation - timer = new QTimer(this); + timer = new RsProtectedTimer(this); timer->setInterval(300); timer->setSingleShot(true); connect(timer, SIGNAL(timeout()), this, SLOT(updateCurrentMessage())); @@ -1207,7 +1214,18 @@ void MessagesDialog::insertMessages() } } - if (bInsert) { + if(it->msgflags & RS_MSG_ENCRYPTED) + item[COLUMN_SIGNATURE]->setIcon(QIcon(":/images/blue_lock.png")) ; + else + if(it->msgflags & RS_MSG_SIGNED) + if(it->msgflags & RS_MSG_SIGNATURE_CHECKS) + item[COLUMN_SIGNATURE]->setIcon(QIcon(":/images/stock_signature_ok.png")) ; + else + item[COLUMN_SIGNATURE]->setIcon(QIcon(":/images/stock_signature_bad.png")) ; + else + item[COLUMN_SIGNATURE]->setIcon(QIcon()) ; + + if (bInsert) { /* add to the list */ QList itemList; for (int i = 0; i < COLUMN_COUNT; i++) { diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 0051dd5e3..f18d2223c 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -1287,6 +1287,7 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox) return false; // Don't send with no recipient } mi.encryption_keys = _distant_peers ; + mi.msgflags |= RS_MSG_SIGNED ; if (rsMsgs->MessageSend(mi) == false) { return false;