added proper decryption calls for partial decryption and possible re-try after loading keys.

This commit is contained in:
csoler 2016-02-19 20:47:50 -05:00
parent 0293e246a2
commit 405ecefbf8
2 changed files with 90 additions and 57 deletions

View File

@ -306,7 +306,10 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds,
RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs, RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs,
PgpAuxUtils *pgpUtils, bool grpAutoSync,bool msgAutoSync) PgpAuxUtils *pgpUtils, bool grpAutoSync,bool msgAutoSync)
: p3ThreadedService(), p3Config(), mTransactionN(0), : p3ThreadedService(), p3Config(), mTransactionN(0),
mObserver(nxsObs),mGixs(gixs), mDataStore(gds), mServType(servType), mObserver(nxsObs),
mDataStore(gds),
mServType(servType),
mGixs(gixs),
mTransactionTimeOut(TRANSAC_TIMEOUT), mNetMgr(netMgr), mNxsMutex("RsGxsNetService"), mTransactionTimeOut(TRANSAC_TIMEOUT), mNetMgr(netMgr), mNxsMutex("RsGxsNetService"),
mSyncTs(0), mLastKeyPublishTs(0),mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), mCircles(circles), mReputations(reputations), mSyncTs(0), mLastKeyPublishTs(0),mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), mCircles(circles), mReputations(reputations),
mPgpUtils(pgpUtils), mPgpUtils(pgpUtils),
@ -2144,25 +2147,28 @@ void RsGxsNetService::processTransactions()
// Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted. // Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted.
if(decryptTransaction(tr)) if(decryptTransaction(tr))
{ {
#ifdef NXS_NET_DEBUG_7 #ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted transaction " << transN << std::endl; GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted/processed transaction " << transN << ". Adding to completed list." << std::endl;
#endif #endif
mComplTransactions.push_back(tr); mComplTransactions.push_back(tr);
}
#ifdef NXS_NET_DEBUG_7
else
GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " no decryption occurred in transaction " << transN << std::endl;
#endif
// transaction processing done
// for this id, add to removal list
toRemove.push_back(mmit->first);
#ifdef NXS_NET_DEBUG_1 #ifdef NXS_NET_DEBUG_1
int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ;
GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl;
#endif #endif
}
else
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " no decryption occurred because of unloaded keys. Will retry later. TransN=" << transN << std::endl;
#endif
}
// transaction processing done
// for this id, add to removal list
toRemove.push_back(mmit->first);
} }
else if(flag & NxsTransaction::FLAG_STATE_STARTING) else if(flag & NxsTransaction::FLAG_STATE_STARTING)
{ {
@ -3598,6 +3604,10 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
return true ; return true ;
} }
// Tries to decrypt the transaction. First load the keys and process all items.
// If keys are loaded, encrypted items that cannot be decrypted are discarded.
// Otherwise the transaction is untouched for retry later.
bool RsGxsNetService::decryptTransaction(NxsTransaction *tr) bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
{ {
#ifdef NXS_NET_DEBUG_7 #ifdef NXS_NET_DEBUG_7
@ -3709,70 +3719,93 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
// get all private keys. Normally we should look into the circle name and only supply the keys that we have // get all private keys. Normally we should look into the circle name and only supply the keys that we have
std::list<RsGxsId> own_keys ; for(std::list<RsNxsItem*>::iterator it(tr->mItems.begin());it!=tr->mItems.end();)
mGixs->getOwnIds(own_keys) ;
for(std::list<RsGxsId>::const_iterator it(own_keys.begin());it!=own_keys.end();++it)
{
RsTlvSecurityKey private_key ;
if(mGixs->getPrivateKey(*it,private_key))
{
std::cerr << "(EE) Cannot retrieve private key for ID " << *it << std::endl;
return false ;
}
private_keys.push_back(private_key) ;
std::cerr << " retrived private key " << *it << std::endl;
}
for(std::list<RsNxsItem*>::iterator it(tr->mItems.begin());it!=tr->mItems.end();++it)
{ {
RsNxsEncryptedDataItem *encrypted_item = dynamic_cast<RsNxsEncryptedDataItem*>(*it) ; RsNxsEncryptedDataItem *encrypted_item = dynamic_cast<RsNxsEncryptedDataItem*>(*it) ;
if(encrypted_item == NULL) if(encrypted_item == NULL)
{ {
std::cerr << " skipping unencrypted item..." << std::endl; std::cerr << " skipping unencrypted item..." << std::endl;
++it ;
continue ; continue ;
} }
// we need the private keys to decrypt the item. First load them in!
bool key_loading_failed = false ;
if(private_keys.empty())
{
std::cerr << " need to retrieve private keys..." << std::endl;
std::list<RsGxsId> own_keys ;
mGixs->getOwnIds(own_keys) ;
for(std::list<RsGxsId>::const_iterator it(own_keys.begin());it!=own_keys.end();++it)
{
RsTlvSecurityKey private_key ;
if(mGixs->getPrivateKey(*it,private_key))
{
private_keys.push_back(private_key) ;
std::cerr << " retrieved private key " << *it << std::endl;
}
else
{
std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl;
key_loading_failed = true ;
break ;
}
}
}
if(key_loading_failed)
{
std::cerr << " Some keys not loaded.Returning false to retry later." << std::endl;
return false ;
}
// we do this only when something actually needs to be decrypted. // we do this only when something actually needs to be decrypted.
unsigned char *decrypted_mem = NULL; unsigned char *decrypted_mem = NULL;
uint32_t decrypted_len =0; uint32_t decrypted_len =0;
std::cerr << " Trying to decrypt item..." ; std::cerr << " Trying to decrypt item..." ;
if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->aes_encrypted_data.bin_data,encrypted_item->aes_encrypted_data.bin_len,private_keys)) if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->aes_encrypted_data.bin_data,encrypted_item->aes_encrypted_data.bin_len,private_keys))
{ {
std::cerr << "Failed! Cannot decrypt transaction. Giving up." << std::endl; std::cerr << "Failed! Cannot decrypt this item." << std::endl;
return false ; decrypted_mem = NULL ; // for safety
} }
std::cerr << "Succeeded! deserialising..." << std::endl; std::cerr << " Succeeded! deserialising..." << std::endl;
// deserialise the item // deserialise the item
RsItem *ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ;
if(ditem == NULL) RsItem *ditem = NULL ;
{ RsNxsItem *nxsitem = NULL ;
std::cerr << " Cannot deserialise. Item encoding error!" << std::endl;
return false ;
}
RsNxsItem *nxsitem = dynamic_cast<RsNxsItem*>(ditem) ;
if(nxsitem == NULL) if(decrypted_mem!=NULL)
{ {
std::cerr << " Deserialised item is not an NxsItem. Weird. Dropping transaction." << std::endl; ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ;
return false ;
}
// replace the encrypted item with the clear one if(ditem == NULL)
std::cerr << " Replacing the encrypted item with the clear one." << std::endl; std::cerr << " Cannot deserialise. Item encoding error!" << std::endl;
nxsitem = dynamic_cast<RsNxsItem*>(ditem) ;
if(nxsitem == NULL)
std::cerr << " (EE) Deserialised item is not an NxsItem. Weird. Dropping transaction." << std::endl;
}
// remove the encrypted item. After that it points to the next item to handle
it = tr->mItems.erase(it) ; it = tr->mItems.erase(it) ;
tr->mItems.insert(it,nxsitem) ;
--it ; // this is to make sure the ++it in the for loop is not goign to skip the item just after the one being inserted if(nxsitem != NULL)
{
std::cerr << " Replacing the encrypted item with the clear one." << std::endl;
tr->mItems.insert(it,nxsitem) ; // inserts before it, so no need to ++it
}
delete encrypted_item ;
} }
#endif #endif

View File

@ -455,7 +455,7 @@ private:
* encrypts/decrypts the transaction for the destination circle id. * encrypts/decrypts the transaction for the destination circle id.
*/ */
bool encryptTransaction(NxsTransaction *tr); bool encryptTransaction(NxsTransaction *tr);
bool decryptTransaction(NxsTransaction *tr); bool decryptTransaction(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
void cleanRejectedMessages(); void cleanRejectedMessages();
void processObserverNotifications(); void processObserverNotifications();