From 48ea291d9520489fd4acb81a3dd31ca1671cb33c Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 14 Mar 2015 14:33:23 +0000 Subject: [PATCH] moved signature validation and encryption one level up into p3IdService. Added timestamp for GXS identities and auto-removal after 7 days. Updated display in IdDialog git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8015 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/chat/distantchat.cc | 63 ++- libretroshare/src/chat/distantchat.h | 9 +- libretroshare/src/chat/distributedchat.cc | 81 +++- libretroshare/src/chat/distributedchat.h | 5 +- libretroshare/src/grouter/p3grouter.cc | 64 ++- libretroshare/src/grouter/p3grouter.h | 6 +- libretroshare/src/gxs/gxssecurity.cc | 6 +- libretroshare/src/gxs/gxssecurity.h | 4 +- libretroshare/src/gxs/rsgenexchange.cc | 7 +- libretroshare/src/gxs/rsgixs.h | 50 ++- libretroshare/src/retroshare/rsidentity.h | 34 +- libretroshare/src/rsserver/rsinit.cc | 3 +- .../src/serialiser/rsgxscircleitems.cc | 5 +- libretroshare/src/serialiser/rsgxsiditems.cc | 407 ++++++++++-------- libretroshare/src/serialiser/rsgxsiditems.h | 97 +++-- libretroshare/src/serialiser/rsserial.cc | 3 +- libretroshare/src/serialiser/rsserial.h | 3 +- libretroshare/src/serialiser/rstlvstring.cc | 4 +- libretroshare/src/serialiser/rstlvstring.h | 4 +- libretroshare/src/services/p3idservice.cc | 318 ++++++++++++-- libretroshare/src/services/p3idservice.h | 74 ++-- retroshare-gui/src/gui/Identity/IdDialog.cpp | 33 +- retroshare-gui/src/gui/Identity/IdDialog.ui | 78 ++-- retroshare-gui/src/gui/chat/ChatWidget.cpp | 1 - 24 files changed, 944 insertions(+), 415 deletions(-) diff --git a/libretroshare/src/chat/distantchat.cc b/libretroshare/src/chat/distantchat.cc index 3ce9b2ba0..cc402b6fe 100644 --- a/libretroshare/src/chat/distantchat.cc +++ b/libretroshare/src/chat/distantchat.cc @@ -528,10 +528,8 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) 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) + if(!mGixs->getKey(senders_id,signature_key) || signature_key.keyData.bin_data == NULL) { #ifdef DEBUG_DISTANT_CHAT std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; @@ -561,6 +559,28 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) std::cerr << " (EE) Signature was verified and it doesn't check! This is a security issue!" << std::endl; return ; } +#ifdef SUSPENDED + if(signature_key.keyId != item->gxs_key.keyId) + { + std::cerr << "(EE) DH session key is signed by an ID that is not the ID of the key provided inthe packet. Refusing distant chat with this peer." << std::endl; + return; + } + uint32_t error_status ; + + if(!mGixs->validateData((unsigned char*)data,pubkey_size,item->signature,true,error_status)) + { + switch(error_status) + { + case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot verify." << std::endl; + break ; + case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/MITM?." << std::endl; + break ; + default: break ; + } + return ; + } +#endif + #ifdef DEBUG_DISTANT_CHAT std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl; std::cerr << " Computing AES key" << std::endl; @@ -652,12 +672,38 @@ bool DistantChatService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_ dhitem->public_key = BN_dup(dh->pub_key) ; - // we should also sign the data and check the signature on the other end. + // we should also sign the data and check the signature on the other end. // RsTlvKeySignature signature ; RsTlvSecurityKey signature_key ; RsTlvSecurityKey signature_key_public ; + uint32_t error_status ; + + uint32_t size = BN_num_bytes(dhitem->public_key) ; + unsigned char *data = (unsigned char *)malloc(size) ; + BN_bn2bin(dhitem->public_key, data) ; + + if(!mGixs->signData((unsigned char*)data,size,own_gxs_id,signature,error_status)) + { + switch(error_status) + { + case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot sign." << std::endl; + break ; + default: std::cerr << "(EE) Unknown error when signing" << std::endl; + break ; + } + free(data) ; + return false; + } + free(data) ; + + if(!mGixs->getKey(own_gxs_id,signature_key_public)) + { + std::cerr << " (EE) Could not retrieve own public key for ID = " << own_gxs_id << ". Giging up sending DH session params." << std::endl; + return false ; + } +#ifdef SUSPENDED #ifdef DEBUG_DISTANT_CHAT std::cerr << " Getting key material for signature with GXS id " << own_gxs_id << std::endl; #endif @@ -699,11 +745,12 @@ bool DistantChatService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_ { std::cerr << " (EE) Cannot sign for id " << own_gxs_id << ". Signature call failed." << std::endl; return false ; - } + } +#endif - free(data) ; + assert(!(signature_key_public.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - dhitem->signature = signature ; + dhitem->signature = signature ; dhitem->gxs_key = signature_key_public ; dhitem->PeerId(RsPeerId(virtual_peer_id)) ; // special case for DH items @@ -890,7 +937,7 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,c // should be a parameter. std::list lst ; - mIdService->getOwnIds(lst) ; + mGixs->getOwnIds(lst) ; bool found = false ; for(std::list::const_iterator it = lst.begin();it!=lst.end();++it) diff --git a/libretroshare/src/chat/distantchat.h b/libretroshare/src/chat/distantchat.h index 56b0e1ac9..a347ab9ba 100644 --- a/libretroshare/src/chat/distantchat.h +++ b/libretroshare/src/chat/distantchat.h @@ -29,16 +29,15 @@ #include #include - -class p3IdService ; +class RsGixs ; static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; class DistantChatService: public RsTurtleClientService { public: - DistantChatService(p3IdService *pids) - : mIdService(pids), mDistantChatMtx("distant chat") + DistantChatService(RsGixs *pids) + : mGixs(pids), mDistantChatMtx("distant chat") { mTurtle = NULL ; } @@ -129,7 +128,7 @@ private: static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside p3turtle *mTurtle ; - p3IdService *mIdService ; + RsGixs *mGixs ; RsMutex mDistantChatMtx ; }; diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc index ed9ae6b6f..752df3345 100644 --- a/libretroshare/src/chat/distributedchat.cc +++ b/libretroshare/src/chat/distributedchat.cc @@ -35,7 +35,7 @@ #include "retroshare/rsiface.h" #include "retroshare/rsidentity.h" #include "rsserver/p3face.h" -#include "gxs/gxssecurity.h" +#include "gxs/rsgixs.h" #include "services/p3idservice.h" //#define DEBUG_CHAT_LOBBIES 1 @@ -62,8 +62,8 @@ static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration win #define EXTRACT_PRIVACY_FLAGS(flags) (ChatLobbyFlags(flags.toUInt32()) & RS_CHAT_LOBBY_FLAGS_PUBLIC) -DistributedChatService::DistributedChatService(uint32_t serv_type,p3ServiceControl *sc,p3HistoryMgr *hm, p3IdService *is) - : mServType(serv_type),mDistributedChatMtx("Distributed Chat"), mServControl(sc), mHistMgr(hm),mIdService(is) +DistributedChatService::DistributedChatService(uint32_t serv_type,p3ServiceControl *sc,p3HistoryMgr *hm, RsGixs *is) + : mServType(serv_type),mDistributedChatMtx("Distributed Chat"), mServControl(sc), mHistMgr(hm),mGixs(is) { _time_shift_average = 0.0f ; _should_reset_lobby_counts = false ; @@ -80,7 +80,21 @@ void DistributedChatService::flush() if(last_clean_time_lobby + LOBBY_CACHE_CLEANING_PERIOD < now) { cleanLobbyCaches() ; - last_clean_time_lobby = now ; + last_clean_time_lobby = now ; + + // also make sure that the default identity is not null + + if(_default_identity.isNull()) + { + std::list ids ; + mGixs->getOwnIds(ids) ; + + if(!ids.empty()) + { + _default_identity = ids.front() ; + triggerConfigSave() ; + } + } } if(last_req_chat_lobby_list + LOBBY_LIST_AUTO_UPDATE_TIME < now) { @@ -156,7 +170,7 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const // network pre-request key to allow message authentication. - mIdService->requestKey(obj->signature.keyId,peer_list); + mGixs->requestKey(obj->signature.keyId,peer_list); uint32_t size = obj->signed_serial_size() ; unsigned char *memory = (unsigned char *)malloc(size) ; @@ -173,11 +187,29 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const return false ; } + uint32_t error_status ; + + if(!mGixs->validateData(memory,obj->signed_serial_size(),obj->signature,false,error_status)) + { + switch(error_status) + { + case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot verify." << std::endl; + break ; + case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/MITM?." << std::endl; + break ; + default: break ; + } + free(memory) ; + return false; + } + free(memory) ; + +#ifdef SUSPENDED RsTlvSecurityKey signature_public_key ; if(!mIdService->getKey(obj->signature.keyId,signature_public_key) || signature_public_key.keyData.bin_data == NULL) { - std::cerr << " (EE) Could not retrieve public key for ID = " << obj->signature.keyId << ". Giging up sending signed lobby message." << std::endl; + std::cerr << " (EE) Could not retrieve public key for ID = " << obj->signature.keyId << ". Lobby message is not authenticated." << std::endl; free(memory) ; // no public key. We continue. If the lobby has strict authentication, we should return false. @@ -200,6 +232,7 @@ bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const return false ; } free(memory) ; +#endif #ifdef DEBUG_CHAT_LOBBIES std::cerr << " signature: CHECKS" << std::endl; @@ -898,6 +931,22 @@ bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId& return false ; } + uint32_t error_status ; + + if(!mGixs->signData(memory,size,lobby.gxs_id,item.signature,error_status)) + { + switch(error_status) + { + case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Cannot sign item: key not available for ID " << lobby.gxs_id << std::endl; + break ; + default: std::cerr << "(EE) Cannot sign item: unknown error" << std::endl; + break ; + } + free(memory) ; + return false ; + } + +#ifdef SUSPENDED RsTlvSecurityKey signature_private_key ; int i ; @@ -930,22 +979,22 @@ bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId& std::cerr << "(EE) Cannot sign message item. " << std::endl; return false ; } +#endif + #ifdef DEBUG_CHAT_LOBBIES std::cerr << " signature done." << std::endl; // check signature - RsTlvSecurityKey public_key ; - GxsSecurity::extractPublicKey(signature_private_key,public_key) ; - - if(!GxsSecurity::validateSignature((const char *)memory,item.signed_serial_size(),public_key,item.signature)) + if(!mGixs->validateSignature((const char *)memory,item.signed_serial_size(),lobby.gxs_id,item.signature,true,error_status)) { - std::cerr << "(EE) Cannot sign message item. " << std::endl; + std::cerr << "(EE) Cannot check message item. " << std::endl; return false ; } std::cerr << " signature checks!" << std::endl; std::cerr << " Item dump:" << std::endl; item.print(std::cerr,2) ; #endif + free(memory) ; } return true ; @@ -1272,6 +1321,7 @@ bool DistributedChatService::acceptLobbyInvite(const ChatLobbyId& lobby_id,const return true ; } +#ifdef SUSPENDED RsIdentityDetails details ; // This is our own identity. We force the loading from the cache. @@ -1281,6 +1331,7 @@ bool DistributedChatService::acceptLobbyInvite(const ChatLobbyId& lobby_id,const break ; else usleep(500*1000) ; +#endif #ifdef DEBUG_CHAT_LOBBIES std::cerr << " Creating new Lobby entry." << std::endl; @@ -1364,6 +1415,7 @@ void DistributedChatService::denyLobbyInvite(const ChatLobbyId& lobby_id) bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& gxs_id) { +#ifdef SUSPENDED RsIdentityDetails details ; // This is our own identity. We force the loading from the cache. @@ -1379,6 +1431,13 @@ bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,co std::cerr << "(EE) Cannot lobby using gxs id " << gxs_id << std::endl; return false ; } +#endif + if(!mGixs->isOwnId(gxs_id)) + { + std::cerr << "(EE) Cannot lobby using gxs id " << gxs_id << std::endl; + return false ; + } + #ifdef DEBUG_CHAT_LOBBIES std::cerr << "Joining public chat lobby " << std::hex << lobby_id << std::dec << std::endl; #endif diff --git a/libretroshare/src/chat/distributedchat.h b/libretroshare/src/chat/distributedchat.h index ce06d5397..526e1e65c 100644 --- a/libretroshare/src/chat/distributedchat.h +++ b/libretroshare/src/chat/distributedchat.h @@ -46,11 +46,12 @@ class RsChatLobbyUnsubscribeItem ; class RsChatItem ; class RsChatMsgItem ; +class RsGixs ; class DistributedChatService { public: - DistributedChatService(uint32_t service_type,p3ServiceControl *sc,p3HistoryMgr *hm,p3IdService *is) ; + DistributedChatService(uint32_t service_type,p3ServiceControl *sc,p3HistoryMgr *hm,RsGixs *is) ; virtual ~DistributedChatService() {} @@ -164,5 +165,5 @@ class DistributedChatService p3ServiceControl *mServControl; p3HistoryMgr *mHistMgr; - p3IdService *mIdService ; + RsGixs *mGixs ; }; diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc index 94e5c1ae5..1f7f73da1 100644 --- a/libretroshare/src/grouter/p3grouter.cc +++ b/libretroshare/src/grouter/p3grouter.cc @@ -186,8 +186,8 @@ #include "util/rsprint.h" #include "serialiser/rsconfigitems.h" #include "services/p3idservice.h" -#include "gxs/gxssecurity.h" #include "turtle/p3turtle.h" +#include "gxs/rsgixs.h" #include "p3grouter.h" #include "grouteritems.h" @@ -207,8 +207,8 @@ static const uint32_t MAX_RECEIPT_WAIT_TIME = 20 ; // wait for at const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ; -p3GRouter::p3GRouter(p3ServiceControl *sc, p3IdService *is) - : p3Service(), p3Config(), mServiceControl(sc), mIdService(is), grMtx("GRouter") +p3GRouter::p3GRouter(p3ServiceControl *sc, RsGixs *is) + : p3Service(), p3Config(), mServiceControl(sc), mGixs(is), grMtx("GRouter") { addSerialType(new RsGRouterSerialiser()) ; @@ -1211,6 +1211,8 @@ bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& de std::cerr << " Encrypting data for key " << destination_key << std::endl; std::cerr << " Decrypted size = " << item->data_size << std::endl; #endif + +#ifdef SUSPENDED RsTlvSecurityKey encryption_key ; // get the key, and let the cache find it. @@ -1234,6 +1236,19 @@ bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& de std::cerr << " (EE) Encryption failed." << std::endl; return false ; } +#endif + uint8_t *encrypted_data =NULL; + uint32_t encrypted_size =0; + uint32_t error_status ; + + if(!mGixs->encryptData(item->data_bytes,item->data_size,encrypted_data,encrypted_size,destination_key,true,error_status)) + { + std::cerr << "(EE) Cannot encrypt: " ; + if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) std::cerr << " key not available for ID = " << destination_key << std::endl; + if(error_status == RsGixs::RS_GIXS_ERROR_UNKNOWN ) std::cerr << " unknown error for ID = " << destination_key << std::endl; + + return false ; + } free(item->data_bytes) ; item->data_bytes = encrypted_data ; @@ -1255,6 +1270,19 @@ bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) std::cerr << " decrypting data for key " << item->destination_key << std::endl; std::cerr << " encrypted size = " << item->data_size << std::endl; #endif + + uint8_t *decrypted_data =NULL; + uint32_t decrypted_size =0; + uint32_t error_status ; + + if(mGixs->decryptData(item->data_bytes,item->data_size,decrypted_data,decrypted_size,item->destination_key,error_status)) + { + if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) + std::cerr << "(EE) Cannot decrypt incoming message. Key " << item->destination_key << " unknown." << std::endl; + else + std::cerr << "(EE) Cannot decrypt incoming message. Unknown error. " << std::endl; + } +#ifdef SUSPENDED RsTlvSecurityKey encryption_key ; // get the key, and let the cache find it. @@ -1278,6 +1306,7 @@ bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) std::cerr << " (EE) Decryption failed." << std::endl; return false ; } +#endif free(item->data_bytes) ; item->data_bytes = decrypted_data ; @@ -1303,12 +1332,12 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi uint32_t data_size = item->signed_data_size() ; uint8_t *data = (uint8_t*)malloc(data_size) ; - if(!item->serialise_signed_data(data,data_size)) - throw std::runtime_error("Cannot serialise signed data.") ; - if(data == NULL) throw std::runtime_error("Cannot allocate memory for signing data.") ; + if(!item->serialise_signed_data(data,data_size)) + throw std::runtime_error("Cannot serialise signed data.") ; +#ifdef SUSPENDED if(!mIdService->getPrivateKey(signing_id,signature_key)) throw std::runtime_error("Cannot get signature key for id " + signing_id.toStdString()) ; @@ -1319,6 +1348,11 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi if(!GxsSecurity::getSignature((char *)data,data_size,signature_key,item->signature)) throw std::runtime_error("Cannot sign for id " + signing_id.toStdString() + ". Signature call failed.") ; +#endif + uint32_t error_status ; + + if(!mGixs->signData(data,data_size,signing_id,item->signature,error_status)) + throw std::runtime_error("Cannot sign for id " + signing_id.toStdString() + ". Signature call failed.") ; #ifdef GROUTER_DEBUG std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl; @@ -1331,6 +1365,7 @@ bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signi std::cerr << " signing failed. Error: " << e.what() << std::endl; if(data != NULL) free(data) ; + item->signature.TlvClear() ; return false ; } @@ -1349,6 +1384,7 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item) if(!item->serialise_signed_data(data,data_size)) throw std::runtime_error("Cannot serialise signed data.") ; +#ifdef SUSPENDED for(int i=0;i<6;++i) if(!mIdService->getKey(item->signature.keyId,signature_key) || signature_key.keyData.bin_data == NULL) { @@ -1368,6 +1404,22 @@ bool p3GRouter::verifySignedDataItem(RsGRouterAbstractMsgItem *item) if(!GxsSecurity::validateSignature((char*)data,data_size,signature_key,item->signature)) throw std::runtime_error("Signature was verified and it doesn't check! This is a security issue!") ; +#endif + uint32_t error_status ; + + if(!mGixs->validateData(data,data_size,item->signature,true,error_status)) + { + switch(error_status) + { + case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot verify." << std::endl; + break ; + case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/Corrupted/MITM?." << std::endl; + break ; + default: break ; + } + free(data) ; + return false; + } free(data) ; return true ; diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h index c821f1b28..ca61ec63d 100644 --- a/libretroshare/src/grouter/p3grouter.h +++ b/libretroshare/src/grouter/p3grouter.h @@ -49,7 +49,7 @@ static const uint32_t RS_GROUTER_DATA_FLAGS_ENCRYPTED = 0x0001 ; class p3LinkMgr ; class p3turtle ; -class p3IdService ; +class RsGixs ; class RsGRouterItem ; class RsGRouterGenericDataItem ; class RsGRouterTransactionChunkItem ; @@ -79,7 +79,7 @@ public: class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config { public: - p3GRouter(p3ServiceControl *sc,p3IdService *is) ; + p3GRouter(p3ServiceControl *sc,RsGixs *is) ; //===================================================// // Router clients business // @@ -298,7 +298,7 @@ private: // p3ServiceControl *mServiceControl ; p3turtle *mTurtle ; - p3IdService *mIdService ; + RsGixs *mGixs ; // Multi-thread protection mutex. // diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc index 818c1d1c9..63a6ebac2 100644 --- a/libretroshare/src/gxs/gxssecurity.cc +++ b/libretroshare/src/gxs/gxssecurity.cc @@ -338,7 +338,7 @@ bool GxsSecurity::validateNxsMsg(RsNxsMsg& msg, RsTlvKeySignature& sign, RsTlvSe return false; } -bool GxsSecurity::encrypt(uint8_t *& out, int & outlen, const uint8_t *in, int inlen, const RsTlvSecurityKey& key) +bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) { #ifdef DISTRIB_DEBUG std::cerr << "GxsSecurity::encrypt() " << std::endl; @@ -441,7 +441,7 @@ bool GxsSecurity::encrypt(uint8_t *& out, int & outlen, const uint8_t *in, int i } -bool GxsSecurity::decrypt(uint8_t *& out, int & outlen, const uint8_t *in, int inlen, const RsTlvSecurityKey& key) +bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) { #ifdef DISTRIB_DEBUG @@ -519,7 +519,7 @@ bool GxsSecurity::decrypt(uint8_t *& out, int & outlen, const uint8_t *in, int i return false; } - outlen += out_currOffset; + outlen = out_currOffset; if(!EVP_OpenFinal(&ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) { diff --git a/libretroshare/src/gxs/gxssecurity.h b/libretroshare/src/gxs/gxssecurity.h index c40f6bb5b..f4e37ab17 100644 --- a/libretroshare/src/gxs/gxssecurity.h +++ b/libretroshare/src/gxs/gxssecurity.h @@ -63,7 +63,7 @@ class GxsSecurity *@param in *@param inlen */ - static bool encrypt(uint8_t *&out, int &outlen, const uint8_t *in, int inlen, const RsTlvSecurityKey& key) ; + static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ; /** * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) @@ -74,7 +74,7 @@ class GxsSecurity * @param inlen * @return false if encryption failed */ - static bool decrypt(uint8_t *&out, int &outlen, const uint8_t *in, int inlen, const RsTlvSecurityKey& key) ; + static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ; /*! * uses grp signature to check if group has been diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index fbece7319..697c47c72 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -919,7 +919,9 @@ int RsGenExchange::validateGrp(RsNxsGrp* grp) { RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY]; - idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey); + idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey); + + mGixs->timeStampKey(metaData.mAuthorId) ; } else { @@ -2887,7 +2889,8 @@ bool RsGenExchange::updateValid(RsGxsGrpMetaData& oldGrpMeta, RsNxsGrp& newGrp) // also check this is the latest published group bool latest = newGrp.metaData->mPublishTs > oldGrpMeta.mPublishTs; - return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest; + mGixs->timeStampKey(newGrp.metaData->mAuthorId) ; + return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest; } void RsGenExchange::setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h index f29095274..0a99d11dc 100644 --- a/libretroshare/src/gxs/rsgixs.h +++ b/libretroshare/src/gxs/rsgixs.h @@ -99,30 +99,39 @@ typedef RsPeerId PeerId; // SHOULD BE REMOVED => RsPeerId (SSLID) typedef PGPIdType RsPgpId; -// -//// External Interface - -//class RsIdentityService -//{ -// enum IdentityType { Pseudonym, Signed, Anonymous }; -// -// virtual bool loadId(const GxsId &id) = 0; -// -// virtual bool getNickname(const GxsId &id, std::string &nickname) = 0; -// -// virtual bool createKey(RsGixsProfile& profile, uint32_t type) = 0; /* fills in mKeyId, and signature */ -// -// virtual RsGixsProfile* getProfile(const KeyRef& keyref) = 0; -// -// // modify reputation. -// -//}; - - /* Identity Interface for GXS Message Verification. */ class RsGixs { public: + + static const uint32_t RS_GIXS_ERROR_NO_ERROR = 0x0000 ; + static const uint32_t RS_GIXS_ERROR_UNKNOWN = 0x0001 ; + static const uint32_t RS_GIXS_ERROR_KEY_NOT_AVAILABLE = 0x0002 ; + static const uint32_t RS_GIXS_ERROR_SIGNATURE_MISMATCH = 0x0003 ; + + /* Performs/validate a signature with the given key ID. The key must be available, otherwise the signature error + * will report it. Each time a key is used to validate a signature, its usage timestamp is updated. + * + * If force_load is true, the key will be forced loaded from the cache. If not, uncached keys will return + * with error_status=RS_GIXS_SIGNATURE_ERROR_KEY_NOT_AVAILABLE, but will likely be cached on the next call. + */ + + virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) = 0 ; + virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error) = 0 ; + + virtual bool encryptData(const uint8_t *clear_data,uint32_t clear_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) = 0 ; + virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& clear_data,uint32_t& clear_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) = 0 ; + +// virtual bool getPublicKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; + + virtual void getOwnIds(std::list& ids) = 0; + virtual bool isOwnId(const RsGxsId& key_id) = 0 ; + + virtual void timeStampKey(const RsGxsId& key_id) = 0 ; + + // virtual void networkRequestPublicKey(const RsGxsId& key_id,const std::list& peer_ids) = 0 ; + // Key related interface - used for validating msgs and groups. /*! * Use to query a whether given key is available by its key reference @@ -157,7 +166,8 @@ public: */ virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; // For signing outgoing messages. - +#ifdef SUSPENDED +#endif }; diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 9e290372d..53f66dec8 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -109,6 +109,7 @@ class RsGxsIdGroup // Avatar RsGxsImage mImage ; + time_t mLastUsageTS ; // Not Serialised - for GUI's benefit. bool mPgpKnown; @@ -153,30 +154,33 @@ class RsRecognTagDetails class RsIdentityDetails { - public: - RsIdentityDetails() - :mIsOwnId(false), mPgpLinked(false), mPgpKnown(false), - mReputation() { return; } +public: + RsIdentityDetails() + :mIsOwnId(false), mPgpLinked(false), mPgpKnown(false), + mReputation() { return; } - RsGxsId mId; + RsGxsId mId; - // identity details. - std::string mNickname; - bool mIsOwnId; + // identity details. + std::string mNickname; + bool mIsOwnId; - // PGP Stuff. - bool mPgpLinked; - bool mPgpKnown; - RsPgpId mPgpId; + // PGP Stuff. + bool mPgpLinked; + bool mPgpKnown; + RsPgpId mPgpId; - // Recogn details. - std::list mRecognTags; + // Recogn details. + std::list mRecognTags; - // reputation details. + // reputation details. GxsReputation mReputation; // avatar RsGxsImage mAvatar ; + + // last usage + time_t mLastUsageTS ; }; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index f3300d1b5..b75b3a923 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1476,7 +1476,7 @@ int RsServer::StartupRetroShare() pqih -> addService(mDisc,true); pqih -> addService(msgSrv,true); pqih -> addService(chatSrv,true); - pqih ->addService(mStatusSrv,true); + pqih -> addService(mStatusSrv,true); // set interfaces for plugins @@ -1592,6 +1592,7 @@ int RsServer::StartupRetroShare() #ifdef ENABLE_GROUTER mConfigMgr->addConfiguration("grouter.cfg", gr); #endif + mConfigMgr->addConfiguration("identity.cfg", mGxsIdService); #ifdef RS_USE_BITDHT mConfigMgr->addConfiguration("bitdht.cfg", mBitDht); diff --git a/libretroshare/src/serialiser/rsgxscircleitems.cc b/libretroshare/src/serialiser/rsgxscircleitems.cc index b2d52f79f..c9011091e 100644 --- a/libretroshare/src/serialiser/rsgxscircleitems.cc +++ b/libretroshare/src/serialiser/rsgxscircleitems.cc @@ -44,8 +44,9 @@ uint32_t RsGxsCircleSerialiser::size(RsItem *item) else if((snap_item = dynamic_cast(item)) != NULL) { return sizeGxsCircleMsgItem(snap_item); - } - return NULL; + } + else + return 0 ; } bool RsGxsCircleSerialiser::serialise(RsItem *item, void *data, uint32_t *size) diff --git a/libretroshare/src/serialiser/rsgxsiditems.cc b/libretroshare/src/serialiser/rsgxsiditems.cc index ae7c548b9..997517743 100644 --- a/libretroshare/src/serialiser/rsgxsiditems.cc +++ b/libretroshare/src/serialiser/rsgxsiditems.cc @@ -33,102 +33,61 @@ #define GXSID_DEBUG 1 - -uint32_t RsGxsIdSerialiser::size(RsItem *item) -{ - RsGxsIdGroupItem* grp_item = NULL; -#if 0 - RsGxsIdOpinionItem* op_item = NULL; - RsGxsIdCommentItem* com_item = NULL; -#endif - - if((grp_item = dynamic_cast(item)) != NULL) - { - return sizeGxsIdGroupItem(grp_item); - } -#if 0 - else if((op_item = dynamic_cast(item)) != NULL) - { - return sizeGxsIdOpinionItem(op_item); - } - else if((com_item = dynamic_cast(item)) != NULL) - { - return sizeGxsIdCommentItem(com_item); - } -#endif - std::cerr << "RsGxsIdSerialiser::size() ERROR invalid item" << std::endl; - return 0; -} - -bool RsGxsIdSerialiser::serialise(RsItem *item, void *data, uint32_t *size) -{ - RsGxsIdGroupItem* grp_item = NULL; -#if 0 - RsGxsIdOpinionItem* op_item = NULL; - RsGxsIdCommentItem* com_item = NULL; -#endif - - if((grp_item = dynamic_cast(item)) != NULL) - { - return serialiseGxsIdGroupItem(grp_item, data, size); - } -#if 0 - else if((op_item = dynamic_cast(item)) != NULL) - { - return serialiseGxsIdOpinionItem(op_item, data, size); - } - else if((com_item = dynamic_cast(item)) != NULL) - { - return serialiseGxsIdCommentItem(com_item, data, size); - } -#endif - std::cerr << "RsGxsIdSerialiser::serialise() ERROR invalid item" << std::endl; - return false; -} - RsItem* RsGxsIdSerialiser::deserialise(void* data, uint32_t* size) { - - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_GXS_TYPE_GXSID != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - - case RS_PKT_SUBTYPE_GXSID_GROUP_ITEM: - return deserialiseGxsIdGroupItem(data, size); - break; + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_GXS_TYPE_GXSID != getRsItemService(rstype))) + return NULL; /* wrong type */ + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_GXSID_GROUP_ITEM: return deserialise_GxsIdGroupItem(data, size); + case RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM: return deserialise_GxsIdLocalInfoItem(data, size); #if 0 - case RS_PKT_SUBTYPE_GXSID_OPINION_ITEM: - return deserialiseGxsIdOpinionItem(data, size); - break; - case RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM: - return deserialiseGxsIdCommentItem(data, size); - break; + case RS_PKT_SUBTYPE_GXSID_OPINION_ITEM: return deserialise_GxsIdOpinionItem(data, size); + case RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM: return deserialise_GxsIdCommentItem(data, size); #endif - default: + default: #ifdef GXSID_DEBUG - std::cerr << "RsGxsIdSerialiser::deserialise(): unknown subtype"; - std::cerr << std::endl; + std::cerr << "RsGxsIdSerialiser::deserialise(): unknown subtype"; + std::cerr << std::endl; #endif - break; - } - return NULL; + break; + } + return NULL; } +bool RsGxsIdItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) +{ + tlvsize = serial_size() ; + offset = 0; + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + if(!setRsItemHeader(data, tlvsize, PacketId(), tlvsize)) + { + std::cerr << "RsItem::serialise_header(): ERROR. Not enough size!" << std::endl; + return false ; + } + offset += 8; + + return true ; +} /*****************************************************************************************/ /*****************************************************************************************/ /*****************************************************************************************/ +void RsGxsIdLocalInfoItem::clear() +{ + mTimeStamps.clear() ; +} void RsGxsIdGroupItem::clear() { mPgpIdHash.clear(); @@ -137,7 +96,27 @@ void RsGxsIdGroupItem::clear() mRecognTags.clear(); mImage.TlvClear(); } +uint32_t RsGxsIdLocalInfoItem::serial_size() +{ + uint32_t s = 8 ; // header + s += 4 ; // number of items + s += mTimeStamps.size() * (RsGxsId::SIZE_IN_BYTES + 8) ; + return s; +} + +std::ostream& RsGxsIdLocalInfoItem::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsIdLocalInfoItem", indent); + uint16_t int_Indent = indent + 2; + + // convert from binary to hex. + for(std::map::const_iterator it(mTimeStamps.begin());it!=mTimeStamps.end();++it) + out << it->first << " : " << it->second << std::endl; + + printRsItemEnd(out ,"RsGxsIdLocalInfoItem", indent); + return out; +} std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) { printRsItemBase(out, "RsGxsIdGroupItem", indent); @@ -167,71 +146,88 @@ std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) } -uint32_t RsGxsIdSerialiser::sizeGxsIdGroupItem(RsGxsIdGroupItem *item) +uint32_t RsGxsIdGroupItem::serial_size() { uint32_t s = 8; // header s += Sha1CheckSum::SIZE_IN_BYTES; - s += GetTlvStringSize(item->mPgpIdSign); + s += GetTlvStringSize(mPgpIdSign); - RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->mRecognTags); + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, mRecognTags); s += set.TlvSize(); - - s += item->mImage.TlvSize() ; + s += mImage.TlvSize() ; return s; } -bool RsGxsIdSerialiser::serialiseGxsIdGroupItem(RsGxsIdGroupItem *item, void *data, uint32_t *size) + +bool RsGxsIdLocalInfoItem::serialise(void *data, uint32_t& size) { - - - uint32_t tlvsize = sizeGxsIdGroupItem(item); - uint32_t offset = 0; - - if(*size < tlvsize) - { -#ifdef GXSID_DEBUG - std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() Size too small" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* GxsIdGroupItem */ - ok &= item->mPgpIdHash.serialise(data, tlvsize, offset); - ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_SIGN, item->mPgpIdSign); + uint32_t tlvsize,offset=0; + bool ok = true; - RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->mRecognTags); - ok &= set.SetTlv(data, tlvsize, &offset); + if(!serialise_header(data,size,tlvsize,offset)) + return false ; - ok &= item->mImage.SetTlv(data,tlvsize,&offset) ; + ok &= setRawUInt32(data, tlvsize, &offset, mTimeStamps.size()) ; - if(offset != tlvsize) - { + for(std::map::const_iterator it = mTimeStamps.begin();it!=mTimeStamps.end();++it) + { + ok &= it->first.serialise(data,tlvsize,offset) ; + ok &= setRawTimeT(data,tlvsize,&offset,it->second) ; + } + if(offset != tlvsize) + { #ifdef GXSID_DEBUG - std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() FAIL Size Error! " << std::endl; + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() FAIL Size Error! " << std::endl; #endif - ok = false; - } - + ok = false; + } + #ifdef GXSID_DEBUG - if (!ok) - { - std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; - } + if (!ok) + { + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } #endif - - return ok; - } + + return ok; +} + +bool RsGxsIdGroupItem::serialise(void *data, uint32_t& size) +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; + + /* GxsIdGroupItem */ + ok &= mPgpIdHash.serialise(data, tlvsize, offset); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_SIGN, mPgpIdSign); + + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, mRecognTags); + ok &= set.SetTlv(data, tlvsize, &offset); + + ok &= mImage.SetTlv(data,tlvsize,&offset) ; + + if(offset != tlvsize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdGroupItem() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef GXSID_DEBUG + if (!ok) + { + std::cerr << "RsGxsIdSerialiser::serialiseGxsIdgroupItem() NOK" << std::endl; + } +#endif + + return ok; +} bool RsGxsIdGroupItem::fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage) @@ -273,8 +269,74 @@ bool RsGxsIdGroupItem::toGxsIdGroup(RsGxsIdGroup &group, bool moveImage) } return true ; } +RsGxsIdGroupItem* RsGxsIdSerialiser::deserialise_GxsIdGroupItem(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); -RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint32_t *size) + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_GXS_TYPE_GXSID != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_GXSID_GROUP_ITEM != getRsItemSubType(rstype))) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + /* skip the header */ + offset += 8; + + ok &= item->mPgpIdHash.deserialise(data, rssize, offset); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_SIGN, item->mPgpIdSign); + + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->mRecognTags); + ok &= set.GetTlv(data, rssize, &offset); + + // image is optional,so that we can continue reading old items. + if(offset < rssize) + ok &= item->mImage.GetTlv(data,rssize,&offset) ; + + if (offset != rssize) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef GXSID_DEBUG + std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} +RsGxsIdLocalInfoItem *RsGxsIdSerialiser::deserialise_GxsIdLocalInfoItem(void *data, uint32_t *size) { /* get the type and size */ uint32_t rstype = getRsItemId(data); @@ -285,7 +347,7 @@ RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint3 if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_GXS_TYPE_GXSID != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_GXSID_GROUP_ITEM != getRsItemSubType(rstype))) + (RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM != getRsItemSubType(rstype))) { #ifdef GXSID_DEBUG std::cerr << "RsGxsIdSerialiser::deserialiseGxsIdGroupItem() FAIL wrong type" << std::endl; @@ -306,19 +368,23 @@ RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint3 bool ok = true; - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + RsGxsIdLocalInfoItem* item = new RsGxsIdLocalInfoItem(); /* skip the header */ offset += 8; - - ok &= item->mPgpIdHash.deserialise(data, rssize, offset); - ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_SIGN, item->mPgpIdSign); - RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->mRecognTags); - ok &= set.GetTlv(data, rssize, &offset); + uint32_t n=0 ; + ok &= getRawUInt32(data, rssize, &offset, &n) ; - // image is optional,so that we can continue reading old items. - if(offset < rssize) - ok &= item->mImage.GetTlv(data,rssize,&offset) ; + for(int i=0;ok && imTimeStamps[gxsid] = TS ; + } if (offset != rssize) { @@ -374,7 +440,7 @@ std::ostream& RsGxsIdOpinionItem::print(std::ostream& out, uint16_t indent) } -uint32_t RsGxsIdSerialiser::sizeGxsIdOpinionItem(RsGxsIdOpinionItem *item) +uint32_t RsGxsIdOpinionItem::serial_size() { const RsGxsIdOpinion& opinion = item->opinion; @@ -387,29 +453,13 @@ uint32_t RsGxsIdSerialiser::sizeGxsIdOpinionItem(RsGxsIdOpinionItem *item) return s; } -bool RsGxsIdSerialiser::serialiseGxsIdOpinionItem(RsGxsIdOpinionItem *item, void *data, uint32_t *size) +bool RsGxsIdOpinionItem::serialise(void *data, uint32_t *size) { - - - uint32_t tlvsize = sizeGxsIdOpinionItem(item); - uint32_t offset = 0; - - if(*size < tlvsize) - { -#ifdef GXSID_DEBUG - std::cerr << "RsGxsIdSerialiser::serialiseGxsIdOpinionItem()" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; /* GxsIdOpinionItem */ ok &= setRawUInt32(data, tlvsize, &offset, item->opinion.mOpinion); @@ -434,7 +484,7 @@ bool RsGxsIdSerialiser::serialiseGxsIdOpinionItem(RsGxsIdOpinionItem *item, void return ok; } -RsGxsIdOpinionItem* RsGxsIdSerialiser::deserialiseGxsIdOpinionItem(void *data, uint32_t *size) +RsGxsIdOpinionItem* RsGxsIdSerialiser::deserialise_GxsIdOpinionItem(void *data, uint32_t *size) { /* get the type and size */ @@ -521,7 +571,7 @@ std::ostream& RsGxsIdCommentItem::print(std::ostream& out, uint16_t indent) } -uint32_t RsGxsIdSerialiser::sizeGxsIdCommentItem(RsGxsIdCommentItem *item) +uint32_t RsGxsIdCommentItem::serial_size() { const RsGxsIdComment& comment = item->comment; @@ -532,28 +582,13 @@ uint32_t RsGxsIdSerialiser::sizeGxsIdCommentItem(RsGxsIdCommentItem *item) return s; } -bool RsGxsIdSerialiser::serialiseGxsIdCommentItem(RsGxsIdCommentItem *item, void *data, uint32_t *size) +bool RsGxsIdCommentItem::serialise(void *data, uint32_t *size) { - - uint32_t tlvsize = sizeGxsIdCommentItem(item); - uint32_t offset = 0; - - if(*size < tlvsize) - { -#ifdef GXSID_DEBUG - std::cerr << "RsGxsIdSerialiser::serialiseGxsIdCommentItem() Not enough space" << std::endl; -#endif - return false; - } - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,size,tlvsize,offset)) + return false ; /* GxsIdCommentItem */ ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->comment.mComment); @@ -576,7 +611,7 @@ bool RsGxsIdSerialiser::serialiseGxsIdCommentItem(RsGxsIdCommentItem *item, void return ok; } -RsGxsIdCommentItem* RsGxsIdSerialiser::deserialiseGxsIdCommentItem(void *data, uint32_t *size) +RsGxsIdCommentItem* RsGxsIdSerialiser::deserialise_GxsIdCommentItem(void *data, uint32_t *size) { /* get the type and size */ diff --git a/libretroshare/src/serialiser/rsgxsiditems.h b/libretroshare/src/serialiser/rsgxsiditems.h index 8cd4e814c..df8c936a5 100644 --- a/libretroshare/src/serialiser/rsgxsiditems.h +++ b/libretroshare/src/serialiser/rsgxsiditems.h @@ -36,21 +36,37 @@ //const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM_deprecated = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSID_OPINION_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM = 0x04; +const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_GXSID_OPINION_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM = 0x04; +const uint8_t RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM = 0x05; -class RsGxsIdGroupItem : public RsGxsGrpItem +class RsGxsIdItem: public RsGxsGrpItem { + public: + RsGxsIdItem(uint8_t item_subtype) : RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSID,item_subtype) {} + virtual bool serialise(void *data,uint32_t& size) = 0 ; + virtual uint32_t serial_size() = 0 ; + + virtual void clear() = 0 ; + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0; + + bool serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) ; +}; + +class RsGxsIdGroupItem : public RsGxsIdItem +{ public: - RsGxsIdGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSID, - RS_PKT_SUBTYPE_GXSID_GROUP_ITEM) { return;} - virtual ~RsGxsIdGroupItem() { return;} + RsGxsIdGroupItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_GROUP_ITEM) {} + virtual ~RsGxsIdGroupItem() {} - void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; bool fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage); bool toGxsIdGroup(RsGxsIdGroup &group, bool moveImage); @@ -66,6 +82,22 @@ public: // Avatar RsTlvImage mImage ; }; +class RsGxsIdLocalInfoItem : public RsGxsIdItem +{ + +public: + + RsGxsIdLocalInfoItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM) {} + virtual ~RsGxsIdLocalInfoItem() {} + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; + + std::map mTimeStamps ; +}; #if 0 class RsGxsIdOpinionItem : public RsGxsMsgItem @@ -76,7 +108,10 @@ public: RS_PKT_SUBTYPE_GXSID_OPINION_ITEM) {return; } virtual ~RsGxsIdOpinionItem() { return;} void clear(); - std::ostream &print(std::ostream &out, uint16_t indent = 0); + virtual bool serialise(void *data,uint32_t& size) = 0 ; + virtual uint32_t serial_size() = 0 ; + + std::ostream &print(std::ostream &out, uint16_t indent = 0); RsGxsIdOpinion opinion; }; @@ -88,6 +123,9 @@ public: RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM) { return; } virtual ~RsGxsIdCommentItem() { return; } void clear(); + virtual bool serialise(void *data,uint32_t& size) = 0 ; + virtual uint32_t serial_size() = 0 ; + std::ostream &print(std::ostream &out, uint16_t indent = 0); RsGxsIdComment comment; @@ -97,33 +135,26 @@ public: class RsGxsIdSerialiser : public RsSerialType { public: + RsGxsIdSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_GXSID) {} + virtual ~RsGxsIdSerialiser() {} - RsGxsIdSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_GXS_TYPE_GXSID) - { return; } - virtual ~RsGxsIdSerialiser() { return; } - - uint32_t size(RsItem *item); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - private: - - uint32_t sizeGxsIdGroupItem(RsGxsIdGroupItem *item); - bool serialiseGxsIdGroupItem (RsGxsIdGroupItem *item, void *data, uint32_t *size); - RsGxsIdGroupItem * deserialiseGxsIdGroupItem(void *data, uint32_t *size); + virtual uint32_t size (RsItem *item) + { + return dynamic_cast(item)->serial_size() ; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + return dynamic_cast(item)->serialise(data,*size) ; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; +private: #if 0 - uint32_t sizeGxsIdOpinionItem(RsGxsIdOpinionItem *item); - bool serialiseGxsIdOpinionItem (RsGxsIdOpinionItem *item, void *data, uint32_t *size); - RsGxsIdOpinionItem * deserialiseGxsIdOpinionItem(void *data, uint32_t *size); - - uint32_t sizeGxsIdCommentItem(RsGxsIdCommentItem *item); - bool serialiseGxsIdCommentItem (RsGxsIdCommentItem *item, void *data, uint32_t *size); - RsGxsIdCommentItem * deserialiseGxsIdCommentItem(void *data, uint32_t *size); + static RsGxsIdOpinionItem *deserialise_GxsIdOpinionItem(void *data, uint32_t *size); + static RsGxsIdCommentItem *deserialise_GxsIdCommentItem(void *data, uint32_t *size); #endif - - + static RsGxsIdGroupItem *deserialise_GxsIdGroupItem(void *data, uint32_t *size); + static RsGxsIdLocalInfoItem *deserialise_GxsIdLocalInfoItem(void *data, uint32_t *size); }; #endif /* RS_GXS_IDENTITY_ITEMS_H */ diff --git a/libretroshare/src/serialiser/rsserial.cc b/libretroshare/src/serialiser/rsserial.cc index 372fcff4d..a1407eb05 100644 --- a/libretroshare/src/serialiser/rsserial.cc +++ b/libretroshare/src/serialiser/rsserial.cc @@ -52,7 +52,8 @@ RsItem::RsItem(uint32_t t) { _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities } - + + #ifdef DO_STATISTICS class Counter { diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h index 146bcba9f..dadf9a3d6 100644 --- a/libretroshare/src/serialiser/rsserial.h +++ b/libretroshare/src/serialiser/rsserial.h @@ -104,7 +104,8 @@ class RsItem: public RsMemoryManagement::SmallObject void setPacketService(uint16_t service); inline uint8_t priority_level() const { return _priority_level ;} - inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} + inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} + private: uint32_t type; RsPeerId peerId; diff --git a/libretroshare/src/serialiser/rstlvstring.cc b/libretroshare/src/serialiser/rstlvstring.cc index 3f05d99d4..43344c118 100644 --- a/libretroshare/src/serialiser/rstlvstring.cc +++ b/libretroshare/src/serialiser/rstlvstring.cc @@ -218,14 +218,14 @@ std::ostream &RsTlvStringSet::printHex(std::ostream &out, uint16_t indent) const /************************************* String Set Ref ************************************/ /* This is exactly the same as StringSet, but it uses an alternative list. */ -RsTlvStringSetRef::RsTlvStringSetRef(uint16_t type, std::list &refids) +RsTlvStringSetRef::RsTlvStringSetRef(uint16_t type, std::list &refids) :mType(type), ids(refids) { } void RsTlvStringSetRef::TlvClear() { - ids.clear(); + ids.clear(); } diff --git a/libretroshare/src/serialiser/rstlvstring.h b/libretroshare/src/serialiser/rstlvstring.h index 1cdcdda56..9408668c5 100644 --- a/libretroshare/src/serialiser/rstlvstring.h +++ b/libretroshare/src/serialiser/rstlvstring.h @@ -53,7 +53,7 @@ virtual std::ostream &printHex(std::ostream &out, uint16_t indent) const; class RsTlvStringSetRef: public RsTlvItem { public: - RsTlvStringSetRef(uint16_t type, std::list &refids); + RsTlvStringSetRef(uint16_t type, std::list &refids); virtual ~RsTlvStringSetRef() { return; } virtual uint32_t TlvSize() const; virtual void TlvClear(); @@ -62,7 +62,7 @@ virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); virtual std::ostream &print(std::ostream &out, uint16_t indent) const; uint16_t mType; - std::list &ids; /* Mandatory */ + std::list &ids; /* Mandatory */ }; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index f00dd9910..304b6215c 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -26,6 +26,7 @@ #include "services/p3idservice.h" #include "pgp/pgpauxutils.h" #include "serialiser/rsgxsiditems.h" +#include "serialiser/rsconfigitems.h" #include "retroshare/rsgxsflags.h" #include "util/rsrandom.h" #include "util/rsstring.h" @@ -52,10 +53,11 @@ #define ID_REQUEST_REPUTATION 0x0003 #define ID_REQUEST_OPINION 0x0004 +static const uint32_t MAX_KEEP_UNUSED_KEYS = 30*86400 ; // remove unused keys after 30 days +static const uint32_t MAX_DELAY_BEFORE_CLEANING = 3601 ; // clean old keys every hour RsIdentity *rsIdentity = NULL; - /****** * Some notes: * Identity tasks: @@ -144,7 +146,8 @@ p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *ne mPgpUtils(pgpUtils) { mBgSchedule_Mode = 0; - mBgSchedule_Active = false; + mBgSchedule_Active = false; + mLastKeyCleaningTime = time(NULL) ; // Kick off Cache Testing, + Others. RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); @@ -201,12 +204,86 @@ uint32_t p3IdService::idAuthenPolicy() return policy; } +time_t p3IdService::locked_getLastUsageTS(const RsGxsId& gxs_id) +{ + std::map::const_iterator it = mKeysTS.find(gxs_id) ; + if(it == mKeysTS.end()) + { + IndicateConfigChanged() ; + return mKeysTS[gxs_id] = time(NULL) ; + } + else + return it->second ; +} +void p3IdService::timeStampKey(const RsGxsId& gxs_id) +{ + RS_STACK_MUTEX(mIdMtx) ; + + mKeysTS[gxs_id] = time(NULL) ; + + IndicateConfigChanged() ; +} + +bool p3IdService::loadList(std::list& items) +{ + RS_STACK_MUTEX(mIdMtx) ; + RsGxsIdLocalInfoItem *lii; + + for(std::list::const_iterator it = items.begin();it!=items.end();++it) + if( (lii = dynamic_cast(*it)) != NULL) + for(std::map::const_iterator it2 = lii->mTimeStamps.begin();it2!=lii->mTimeStamps.end();++it2) + mKeysTS.insert(*it2) ; + return true ; +} + +bool p3IdService::saveList(bool& cleanup,std::list& items) +{ + std::cerr << "p3IdService::saveList()" << std::endl; + + RS_STACK_MUTEX(mIdMtx) ; + cleanup = true ; + RsGxsIdLocalInfoItem *item = new RsGxsIdLocalInfoItem ; + item->mTimeStamps = mKeysTS ; + + items.push_back(item) ; + return true ; +} +void p3IdService::cleanUnusedKeys() +{ + RS_STACK_MUTEX(mIdMtx) ; + + time_t now = time(NULL) ; + + for(std::map::iterator it(mKeysTS.begin());it!=mKeysTS.end();) + if(it->second + MAX_KEEP_UNUSED_KEYS < now && !isOwnId(it->first)) + { + std::cerr << "Deleting identity " << it->first << " which is too old." << std::endl; + uint32_t token ; + RsGxsIdGroup group; + group.mMeta.mGroupId=RsGxsGroupId(it->first); + rsIdentity->deleteIdentity(token, group); + + std::map::iterator tmp = it ; + ++tmp ; + mKeysTS.erase(it) ; + } + else + ++it ; +} void p3IdService::service_tick() { RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. + GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. + + time_t now = time(NULL) ; + + if(mLastKeyCleaningTime + MAX_DELAY_BEFORE_CLEANING < now) + { + cleanUnusedKeys() ; + mLastKeyCleaningTime = now ; + } return; } @@ -288,22 +365,25 @@ bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details) std::cerr << std::endl; #endif - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - if (mPublicKeyCache.fetch(id, data)) - { - details = data.details; - return true; - } - - /* try private cache too */ - if (mPrivateKeyCache.fetch(id, data)) - { - details = data.details; - return true; - } - } + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + RsGxsIdCache data; + if (mPublicKeyCache.fetch(id, data)) + { + details = data.details; + + details.mLastUsageTS = locked_getLastUsageTS(id) ; + return true; + } + + /* try private cache too */ + if (mPrivateKeyCache.fetch(id, data)) + { + details = data.details; + details.mLastUsageTS = locked_getLastUsageTS(id) ; + return true; + } + } /* it isn't there - add to public requests */ cache_request_load(id); @@ -312,6 +392,12 @@ bool p3IdService:: getIdDetails(const RsGxsId &id, RsIdentityDetails &details) } +bool p3IdService::isOwnId(const RsGxsId& id) +{ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + return std::find(mOwnIds.begin(),mOwnIds.end(),id) != mOwnIds.end() ; +} void p3IdService::getOwnIds(std::list &ownIds) { RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ @@ -524,6 +610,144 @@ bool p3IdService::getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) } +bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId& own_gxs_id,RsTlvKeySignature& signature,uint32_t& error_status) +{ + //RsIdentityDetails details ; + RsTlvSecurityKey signature_key ; + + //getIdDetails(own_gxs_id,details); + + int i ; + for(i=0;i<6;++i) + if(!getPrivateKey(own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL) + { +#ifdef DEBUG_IDS + std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; +#endif + usleep(500 * 1000) ; // sleep for 500 msec. + } + else + break ; + + if(i == 6) + { + std::cerr << " (EE) Could not retrieve own private key for ID = " << own_gxs_id << ". Giging up sending DH session params. This should not happen." << std::endl; + error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; + return false ; + } + +#ifdef DEBUG_IDS + std::cerr << " Signing..." << std::endl; +#endif + + if(!GxsSecurity::getSignature((char *)data,data_size,signature_key,signature)) + { + std::cerr << " (EE) Cannot sign for id " << own_gxs_id << ". Signature call failed." << std::endl; + error_status = RS_GIXS_ERROR_UNKNOWN ; + return false ; + } + error_status = RS_GIXS_ERROR_NO_ERROR ; + timeStampKey(own_gxs_id) ; + return true ; +} +bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error) +{ + // RsIdentityDetails details ; + // getIdDetails(signature.keyId,details); + RsTlvSecurityKey signature_key ; + + for(int i=0;i< (force_load?6:1);++i) + if(!getKey(signature.keyId,signature_key) || signature_key.keyData.bin_data == NULL) + { +#ifdef DEBUG_IDS + std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; +#endif + usleep(500 * 1000) ; // sleep for 500 msec. + } + else + break ; + + if(signature_key.keyData.bin_data == NULL) + { + std::cerr << "(EE) Cannot validate signature for unknown key " << signature.keyId << std::endl; + signing_error = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; + return false; + } + + if(!GxsSecurity::validateSignature((char*)data,data_size,signature_key,signature)) + { + std::cerr << "(EE) Signature was verified and it doesn't check! This is a security issue!" << std::endl; + signing_error = RS_GIXS_ERROR_SIGNATURE_MISMATCH ; + return false; + } + signing_error = RS_GIXS_ERROR_NO_ERROR ; + + timeStampKey(signature.keyId) ; + return true ; +} +bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& error_status) +{ + RsTlvSecurityKey encryption_key ; + + // get the key, and let the cache find it. + for(int i=0;i<(force_load?6:1);++i) + if(getKey(encryption_key_id,encryption_key)) + break ; + else + usleep(500*1000) ; // sleep half a sec. + + if(encryption_key.keyId.isNull()) + { + std::cerr << " (EE) Cannot get encryption key for id " << encryption_key_id << std::endl; + error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; + return false ; + } + + if(!GxsSecurity::encrypt(encrypted_data,encrypted_data_size,decrypted_data,decrypted_data_size,encryption_key)) + { + std::cerr << " (EE) Encryption failed." << std::endl; + error_status = RS_GIXS_ERROR_UNKNOWN ; + return false ; + } + error_status = RS_GIXS_ERROR_NO_ERROR ; + timeStampKey(encryption_key_id) ; + + return true ; +} + +bool p3IdService::decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& decrypted_data,uint32_t& decrypted_size,const RsGxsId& key_id,uint32_t& error_status) +{ + RsTlvSecurityKey encryption_key ; + + // Get the key, and let the cache find it. It's our own key, so we should be able to find it, even if it takes + // some seconds. + + for(int i=0;i<4;++i) + if(getPrivateKey(key_id,encryption_key)) + break ; + else + usleep(500*1000) ; // sleep half a sec. + + if(encryption_key.keyId.isNull()) + { + std::cerr << " (EE) Cannot get own encryption key for id " << key_id << " to decrypt data. This should not happen." << std::endl; + error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; + return false ; + } + + if(!GxsSecurity::decrypt(decrypted_data,decrypted_size,encrypted_data,encrypted_data_size,encryption_key)) + { + std::cerr << " (EE) Decryption failed." << std::endl; + error_status = RS_GIXS_ERROR_UNKNOWN ; + return false ; + } + error_status = RS_GIXS_ERROR_NO_ERROR ; + timeStampKey(key_id) ; + + return true ; +} + + /********************************************************************************/ /******************* RsGixsReputation ***************************************/ /********************************************************************************/ @@ -722,6 +946,16 @@ bool p3IdService::opinion_handlerequest(uint32_t token) /******************* Get/Set Data ******************************************/ /********************************************************************************/ +RsSerialiser *p3IdService::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + + rss->addSerialType(new RsGxsIdSerialiser()) ; + rss->addSerialType(new RsGeneralConfigSerialiser()); + + return rss ; +} + bool p3IdService::getGroupData(const uint32_t &token, std::vector &groups) { std::vector grpData; @@ -745,6 +979,11 @@ bool p3IdService::getGroupData(const uint32_t &token, std::vector RsGxsIdGroup group ; item->toGxsIdGroup(group,false) ; + { + RS_STACK_MUTEX(mIdMtx) ; + group.mLastUsageTS = locked_getLastUsageTS(RsGxsId(group.mMeta.mGroupId)) ; + } + // Decode information from serviceString. SSGxsIdGroup ssdata; if (ssdata.load(group.mMeta.mServiceString)) @@ -1282,32 +1521,31 @@ RsGxsIdCache::RsGxsIdCache() RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey, const std::list &tagList) { - // Save Keys. - pubkey = in_pkey; + // Save Keys. + pubkey = in_pkey; - // Save Time for ServiceString comparisions. - mPublishTs = item->meta.mPublishTs; - - // Save RecognTags. + // Save Time for ServiceString comparisions. + mPublishTs = item->meta.mPublishTs; + + // Save RecognTags. mRecognTags = tagList; - details.mAvatar.copy((uint8_t *) item->mImage.binData.bin_data, item->mImage.binData.bin_len); + details.mAvatar.copy((uint8_t *) item->mImage.binData.bin_data, item->mImage.binData.bin_len); - // Fill in Details. - details.mNickname = item->meta.mGroupName; - details.mId = RsGxsId(item->meta.mGroupId); + // Fill in Details. + details.mNickname = item->meta.mGroupName; + details.mId = RsGxsId(item->meta.mGroupId); #ifdef DEBUG_IDS - std::cerr << "RsGxsIdCache::RsGxsIdCache() for: " << details.mId; - std::cerr << std::endl; + std::cerr << "RsGxsIdCache::RsGxsIdCache() for: " << details.mId; + std::cerr << std::endl; #endif // DEBUG_IDS - details.mIsOwnId = (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); + details.mIsOwnId = (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); + details.mPgpLinked = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); - details.mPgpLinked = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); - - /* rest must be retrived from ServiceString */ - updateServiceString(item->meta.mServiceString); + /* rest must be retrived from ServiceString */ + updateServiceString(item->meta.mServiceString); } void RsGxsIdCache::updateServiceString(std::string serviceString) @@ -1729,7 +1967,7 @@ bool p3IdService::cache_load_for_token(uint32_t token) { - // remove identities that are present + // remove identities that are present RsStackMutex stack(mIdMtx); mPendingCache.erase(RsGxsId(item->meta.mGroupId.toStdString())); } @@ -2005,7 +2243,7 @@ bool p3IdService::cachetest_handlerequest(uint32_t token) else { RsTlvSecurityKey seckey; - if (getKey(*vit, seckey)) + if (getKey(*vit, seckey)) { #ifdef DEBUG_IDS std::cerr << "p3IdService::cachetest_request() Got Key OK Id: " << *vit; @@ -2195,8 +2433,8 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte std::cerr << "p3IdService::service_CreateGroup() ERROR no admin key"; std::cerr << std::endl; return SERVICE_CREATE_FAIL; - } - + } + mKeysTS[RsGxsId(item->meta.mGroupId)] = time(NULL) ; /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 5cd5be26f..5d22850c0 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -213,8 +213,7 @@ void updateServiceString(std::string serviceString); // Not sure exactly what should be inherited here? // Chris - please correct as necessary. -class p3IdService: public RsGxsIdExchange, public RsIdentity, - public GxsTokenQueue, public RsTickEvent +class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQueue, public RsTickEvent, public p3Config { public: p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, PgpAuxUtils *pgpUtils); @@ -254,12 +253,8 @@ virtual bool deleteGroup(uint32_t& token, RsGxsIdGroup &group); * Also need to handle Cache updates / invalidation from internal changes. * */ - //virtual bool getNickname(const RsGxsId &id, std::string &nickname); virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details); -virtual void getOwnIds(std::list &ownIds); - - // virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, @@ -274,25 +269,32 @@ virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname, virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag); + /**************** RsGixs Implementation ***************/ - /**************** RsGixs Implementation - * Notes: - * Interface is only suggestion at the moment, will be changed as necessary. - * Results should be cached / preloaded for maximum speed. - * - */ -virtual bool haveKey(const RsGxsId &id); -virtual bool requestKey(const RsGxsId &id, const std::list &peers); -virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key); + virtual void getOwnIds(std::list &ownIds); -virtual bool havePrivateKey(const RsGxsId &id); -virtual bool requestPrivateKey(const RsGxsId &id); -virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key); + //virtual bool getPublicKey(const RsGxsId &id, RsTlvSecurityKey &key) ; + //virtual void networkRequestPublicKey(const RsGxsId& key_id,const std::list& peer_ids) ; - /**************** RsGixsReputation Implementation - * Notes: - * Again should be cached if possible. - */ + virtual bool isOwnId(const RsGxsId& key_id) ; + + virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) ; + virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,uint32_t& signing_error) ; + + virtual bool encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) ; + virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& decrypted_data,uint32_t& decrypted_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) ; + + virtual bool haveKey(const RsGxsId &id); + virtual bool havePrivateKey(const RsGxsId &id); + + virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key); + virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key); + + virtual bool requestKey(const RsGxsId &id, const std::list &peers); + virtual bool requestPrivateKey(const RsGxsId &id); + + + /**************** RsGixsReputation Implementation ****************/ // get Reputation. virtual bool haveReputation(const RsGxsId &id); @@ -300,9 +302,8 @@ virtual bool loadReputation(const RsGxsId &id, const std::list& peers) virtual bool getReputation(const RsGxsId &id, GixsReputation &rep); - protected: - - /** Notifications **/ + protected: + /** Notifications **/ virtual void notifyChanges(std::vector& changes); /** Overloaded to add PgpIdHash to Group Definition **/ @@ -314,6 +315,18 @@ virtual void handleResponse(uint32_t token, uint32_t req_type); // Overloaded from RsTickEvent. virtual void handle_event(uint32_t event_type, const std::string &elabel); + //===================================================// + // p3Config methods // + //===================================================// + + // Load/save the routing info, the pending items in transit, and the config variables. + // + virtual bool loadList(std::list& items) ; + virtual bool saveList(bool& cleanup,std::list& items) ; + + virtual RsSerialiser *setupSerialiser() ; + + private: /************************************************************************ @@ -441,6 +454,10 @@ virtual void generateDummyData(); void generateDummy_UnknownPGP(); void generateDummy_UnknownPseudo(); + void cleanUnusedKeys() ; + virtual void timeStampKey(const RsGxsId& id) ; + time_t locked_getLastUsageTS(const RsGxsId& gxs_id); + std::string genRandomId(int len = 20); #if 0 @@ -480,7 +497,8 @@ std::string genRandomId(int len = 20); std::map > mIdsPendingCache; std::map > mGroupNotPresent; - std::map > mIdsNotPresent; + std::map > mIdsNotPresent; + std::map mKeysTS ; RsNetworkExchangeService* mNes; /************************** @@ -488,7 +506,9 @@ std::string genRandomId(int len = 20); * without depending directly on all these classes. */ - PgpAuxUtils *mPgpUtils; + PgpAuxUtils *mPgpUtils; + + time_t mLastKeyCleaningTime ; }; #endif // P3_IDENTITY_SERVICE_HEADER diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 725c0e8f7..1a06ced7f 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -92,7 +92,8 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type); - mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->toolButton_Reputation); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->toolButton_Reputation); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingOverall); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingImplicit); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->line_RatingOwn); @@ -112,7 +113,8 @@ IdDialog::IdDialog(QWidget *parent) : mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Type); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); + mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOverall); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingImplicit); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingOwn); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->line_RatingPeers); @@ -122,8 +124,9 @@ IdDialog::IdDialog(QWidget *parent) : // mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgHash); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgId); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Type); - mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); - mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingOverall); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_GpgName); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_LastUsed); + mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingOverall); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingImplicit); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingOwn); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->line_RatingPeers); @@ -542,6 +545,18 @@ void IdDialog::requestIdDetails() mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, IDDIALOG_IDDETAILS); } +static QString getHumanReadableDuration(uint32_t seconds) +{ + if(seconds < 60) + return QString::number(seconds) + QObject::tr(" seconds ago") ; + else if(seconds < 3600) + return QString::number(seconds/60) + QObject::tr(" minute(s) ago") ; + else if(seconds < 24*3600) + return QString::number(seconds/3600) + QObject::tr(" hour(s) ago") ; + else + return QString::number(seconds/86400) + QObject::tr(" day(s) ago") ; +} + void IdDialog::insertIdDetails(uint32_t token) { mStateHelper->setLoading(IDDIALOG_IDDETAILS, false); @@ -583,9 +598,11 @@ void IdDialog::insertIdDetails(uint32_t token) ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str())); ui->lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId.toStdString())); //ui->lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash.toStdString())); - ui->lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId.toStdString())); - - ui->headerTextLabel->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str())); + ui->lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId.toStdString())); + + time_t now = time(NULL) ; + ui->lineEdit_LastUsed->setText(getHumanReadableDuration(now - data.mLastUsageTS)) ; + ui->headerTextLabel->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str())); QPixmap pixmap ; @@ -1117,4 +1134,4 @@ int IdDialog::getNumColVisible() } } return iNumColVis; -} \ No newline at end of file +} diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index fa4647ac2..9cd05bf53 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -307,6 +307,26 @@ 6 + + + + Identity name : + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -321,19 +341,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -344,15 +351,18 @@ - - - - Identity name : + + + + true + + + true - - + + true @@ -378,16 +388,6 @@ - - - - true - - - true - - - @@ -398,6 +398,16 @@ + + + + Last used: + + + + + + @@ -692,6 +702,11 @@ + + StyledLabel + QLabel +
gui/common/StyledLabel.h
+
RSTreeWidget QTreeWidget @@ -702,11 +717,6 @@ QLineEdit
gui/common/LineEditClear.h
- - StyledLabel - QLabel -
gui/common/StyledLabel.h
-
todoPushButton diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index afade184c..59d9f3d4d 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -557,7 +557,6 @@ void ChatWidget::completeNickname(bool reverse) word.chop(2); } -#warning still need to use real nicknames for nickname completion. if (word.length() > 0) { // Sort participants list std::list participants;