Put in place auth policy, storage time and testing

Better memory handling for message dispatching
Better typing for some methods
This commit is contained in:
Gioacchino Mazzurco 2017-02-09 16:11:53 +01:00
parent 4daca00359
commit 9cde0fd996
5 changed files with 121 additions and 78 deletions

View File

@ -1499,6 +1499,8 @@ int RsServer::StartupRetroShare()
mGxsMails->setNetworkExchangeService(gxsmails_ns); mGxsMails->setNetworkExchangeService(gxsmails_ns);
pqih->addService(gxsmails_ns, true); pqih->addService(gxsmails_ns, true);
mConfigMgr->addConfiguration("gxs_mail.cfg", gxsmails_ns); mConfigMgr->addConfiguration("gxs_mail.cfg", gxsmails_ns);
new TestGxsMailClientService(*mGxsMails);
# endif // RS_GXS_MAIL # endif // RS_GXS_MAIL
// remove pword from memory // remove pword from memory

View File

@ -71,7 +71,8 @@ bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in)
} }
/* UInt16 get/set */ /* UInt16 get/set */
bool getRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t *out) bool getRawUInt16( const void *data, uint32_t size, uint32_t *offset,
uint16_t *out )
{ {
/* first check there is space */ /* first check there is space */
if (size < *offset + 2) if (size < *offset + 2)

View File

@ -51,7 +51,8 @@
bool getRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t *out); bool getRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t *out);
bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in); bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in);
bool getRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t *out); bool getRawUInt16( const void* data, uint32_t size, uint32_t *offset,
uint16_t *out );
bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in); bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in);
bool getRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t *out); bool getRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t *out);

View File

@ -229,14 +229,14 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type)
vT& mv(gIt->second); vT& mv(gIt->second);
for( vT::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt ) for( vT::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt )
{ {
RsGxsMsgItem* it = *mIt; RsGxsMsgItem* gItem = *mIt;
std::cout << "p3GxsMails::handleResponse(...) MAILS_UPDATE " std::cout << "p3GxsMails::handleResponse(...) MAILS_UPDATE "
<< (uint32_t)it->PacketSubType() << std::endl; << (uint32_t)gItem->PacketSubType() << std::endl;
switch(it->PacketSubType()) switch(gItem->PacketSubType())
{ {
case GXS_MAIL_SUBTYPE_MAIL: case GXS_MAIL_SUBTYPE_MAIL:
{ {
RsGxsMailItem* msg = dynamic_cast<RsGxsMailItem*>(it); RsGxsMailItem* msg = dynamic_cast<RsGxsMailItem*>(gItem);
if(!msg) if(!msg)
{ {
std::cerr << "p3GxsMails::handleResponse(...) " std::cerr << "p3GxsMails::handleResponse(...) "
@ -252,9 +252,10 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type)
default: default:
std::cerr << "p3GxsMails::handleResponse(...) MAILS_UPDATE " std::cerr << "p3GxsMails::handleResponse(...) MAILS_UPDATE "
<< "Unknown mail subtype : " << "Unknown mail subtype : "
<< it->PacketSubType() << std::endl; << gItem->PacketSubType() << std::endl;
break; break;
} }
delete gItem;
} }
} }
break; break;
@ -280,14 +281,14 @@ void p3GxsMails::service_tick()
if(idService.isOwnId(gxsidA)) if(idService.isOwnId(gxsidA))
{ {
std::string ciao("CiAone!"); std::string ciao("CiAone!");
sendMail( GxsMailsClient::MSG_SERVICE, gxsidA, gxsidB, sendMail( GxsMailsClient::TEST_SERVICE, gxsidA, gxsidB,
reinterpret_cast<const uint8_t*>(ciao.data()), reinterpret_cast<const uint8_t*>(ciao.data()),
ciao.size(), RsGxsMailBaseItem::RSA ); ciao.size(), RsGxsMailBaseItem::RSA );
} }
else if(idService.isOwnId(gxsidB)) else if(idService.isOwnId(gxsidB))
{ {
std::string ciao("CiBuono!"); std::string ciao("CiBuono!");
sendMail( GxsMailsClient::MSG_SERVICE, gxsidB, gxsidA, sendMail( GxsMailsClient::TEST_SERVICE, gxsidB, gxsidA,
reinterpret_cast<const uint8_t*>(ciao.data()), reinterpret_cast<const uint8_t*>(ciao.data()),
ciao.size(), RsGxsMailBaseItem::RSA ); ciao.size(), RsGxsMailBaseItem::RSA );
} }
@ -343,6 +344,35 @@ void p3GxsMails::notifyChanges(std::vector<RsGxsNotify*>& changes)
} }
} }
uint32_t p3GxsMails::AuthenPolicy()
{
uint32_t policy = 0;
uint32_t flag = 0;
// This ensure propagated message have valid author signature
flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN |
GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag( flag, policy,
RsGenExchange::PUBLIC_GRP_BITS );
/* This ensure that in for restricted and private groups only authorized
* authors get the messages. Really not used ATM but don't hurts. */
flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN |
GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN;
RsGenExchange::setAuthenPolicyFlag( flag, policy,
RsGenExchange::RESTRICTED_GRP_BITS );
RsGenExchange::setAuthenPolicyFlag( flag, policy,
RsGenExchange::PRIVATE_GRP_BITS );
/* This seems never used RetroShare wide but we should investigate it
* more before considering this conclusive */
flag = 0;
RsGenExchange::setAuthenPolicyFlag( flag, policy,
RsGenExchange::GRP_OPTION_BITS );
return policy;
}
bool p3GxsMails::requestGroupsData(const std::list<RsGxsGroupId>* groupIds) bool p3GxsMails::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
{ {
// std::cout << "p3GxsMails::requestGroupsList()" << std::endl; // std::cout << "p3GxsMails::requestGroupsList()" << std::endl;
@ -354,7 +384,7 @@ bool p3GxsMails::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
return true; return true;
} }
bool p3GxsMails::handleEcryptedMail(RsGxsMailItem* mail) bool p3GxsMails::handleEcryptedMail(const RsGxsMailItem* mail)
{ {
std::set<RsGxsId> decryptIds; std::set<RsGxsId> decryptIds;
std::list<RsGxsId> ownIds; std::list<RsGxsId> ownIds;
@ -363,66 +393,50 @@ bool p3GxsMails::handleEcryptedMail(RsGxsMailItem* mail)
if(mail->maybeRecipient(*it)) decryptIds.insert(*it); if(mail->maybeRecipient(*it)) decryptIds.insert(*it);
// Hint match none of our own ids // Hint match none of our own ids
if(decryptIds.empty()) goto hFail; if(decryptIds.empty()) return true;
for(auto it=decryptIds.begin(); it != decryptIds.end(); ++it)
std::cout << *it;
std::cout << std::endl;
switch (mail->cryptoType) switch (mail->cryptoType)
{ {
case RsGxsMailBaseItem::CLEAR_TEXT: case RsGxsMailBaseItem::CLEAR_TEXT:
{ {
uint16_t csri; uint16_t csri = 0;
uint32_t off = 0; uint32_t off = 0;
getRawUInt16(&mail->payload[0], 2, &off, &csri); getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri);
std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" std::cerr << "service: " << csri << " got CLEAR_TEXT mail!"
<< std::endl; << std::endl;
if( !dispatchDecryptedMail( mail, &mail->payload[2], return dispatchDecryptedMail( mail, &mail->payload[0],
mail->payload.size()-2 ) ) mail->payload.size() );
goto hFail;
break;
} }
case RsGxsMailBaseItem::RSA: case RsGxsMailBaseItem::RSA:
{ {
uint8_t* decrypted_data = NULL; uint8_t* decrypted_data = NULL;
uint32_t decrypted_data_size = 0; uint32_t decrypted_data_size = 0;
uint32_t decryption_error; uint32_t decryption_error;
bool ok = idService.decryptData( &mail->payload[0], bool ok = true;
mail->payload.size(), decrypted_data, if( idService.decryptData( &mail->payload[0],
decrypted_data_size, decryptIds, mail->payload.size(), decrypted_data,
decryption_error ); decrypted_data_size, decryptIds,
ok = ok && dispatchDecryptedMail( mail, decrypted_data, decryption_error ) )
decrypted_data_size ); ok = dispatchDecryptedMail( mail, decrypted_data,
if(!ok) decrypted_data_size );
{ free(decrypted_data);
std::cout << "p3GxsMails::handleEcryptedMail(...) " return ok;
<< "RSA decryption failed" << std::endl;
free(decrypted_data);
goto hFail;
}
break;
} }
default: default:
std::cout << "Unknown encryption type:" std::cout << "Unknown encryption type:"
<< mail->cryptoType << std::endl; << mail->cryptoType << std::endl;
goto hFail; return false;
} }
return true;
hFail:
delete mail;
return false;
} }
bool p3GxsMails::dispatchDecryptedMail( RsGxsMailItem* received_msg, bool p3GxsMails::dispatchDecryptedMail( const RsGxsMailItem* received_msg,
uint8_t* decrypted_data, const uint8_t* decrypted_data,
uint32_t decrypted_data_size ) uint32_t decrypted_data_size )
{ {
uint16_t csri; std::cout << "p3GxsMails::dispatchDecryptedMail(, , " << decrypted_data_size << ")" << std::endl;
uint32_t off; uint16_t csri = 0;
getRawUInt16(decrypted_data, decrypted_data_size, &off, &csri); uint32_t off = 0;
getRawUInt16( decrypted_data, decrypted_data_size, &off, &csri);
GxsMailsClient::GxsMailSubServices rsrvc; GxsMailsClient::GxsMailSubServices rsrvc;
rsrvc = static_cast<GxsMailsClient::GxsMailSubServices>(csri); rsrvc = static_cast<GxsMailsClient::GxsMailSubServices>(csri);
@ -431,6 +445,7 @@ bool p3GxsMails::dispatchDecryptedMail( RsGxsMailItem* received_msg,
RS_STACK_MUTEX(servClientsMutex); RS_STACK_MUTEX(servClientsMutex);
reecipientService = servClients[rsrvc]; reecipientService = servClients[rsrvc];
} }
if(reecipientService) if(reecipientService)
return reecipientService->receiveGxsMail( received_msg, return reecipientService->receiveGxsMail( received_msg,
&decrypted_data[2], &decrypted_data[2],

View File

@ -29,39 +29,27 @@ struct p3GxsMails;
struct GxsMailsClient struct GxsMailsClient
{ {
/// Subservices identifiers (like port for TCP) /// Subservices identifiers (like port for TCP)
enum GxsMailSubServices { MSG_SERVICE }; enum GxsMailSubServices { TEST_SERVICE = 1 };
/**
* This is usually used to save a pointer to the p3GxsMails service (e.g. by
* coping it in a member variable), so as to be able to send mails, and to
* register as a mail receiver via
* p3GxsMails::registerGxsMailsClient(GxsMailSubServices, GxsMailsClient)
*/
//virtual void connectToGxsMails(p3GxsMails *pt) = 0 ;
/** /**
* This will be called by p3GxsMails to dispatch mails to the subservice * This will be called by p3GxsMails to dispatch mails to the subservice
* @param originalMessage message as received from GXS backend (encrypted) * @param originalMessage message as received from GXS backend (encrypted)
* GxsMailsClient take ownership of it ( aka should take free/delete it
* when not needed anymore )
* @param data buffer containing the decrypted data * @param data buffer containing the decrypted data
* GxsMailsClient take ownership of it ( aka should take free/delete it
* when not needed anymore )
* @param dataSize size of the buffer * @param dataSize size of the buffer
* @return true if dispatching goes fine, false otherwise * @return true if dispatching goes fine, false otherwise
*/ */
virtual bool receiveGxsMail( RsGxsMailItem* originalMessage, virtual bool receiveGxsMail( const RsGxsMailItem* originalMessage,
uint8_t* data, uint32_t dataSize ) = 0; const uint8_t* data, uint32_t dataSize ) = 0;
}; };
struct p3GxsMails : RsGenExchange, GxsTokenQueue struct p3GxsMails : RsGenExchange, GxsTokenQueue
{ {
p3GxsMails( RsGeneralDataService* gds, RsNetworkExchangeService* nes, p3GxsMails( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
p3IdService& identities ) : p3IdService& identities ) :
RsGenExchange( gds, nes, new RsGxsMailSerializer(), RsGenExchange( gds, nes, new RsGxsMailSerializer(),
RS_SERVICE_TYPE_GXS_MAIL, &identities, RS_SERVICE_TYPE_GXS_MAIL, &identities,
AuthenPolicy(), AuthenPolicy(), GXS_STORAGE_PERIOD ),
RS_GXS_DEFAULT_MSG_STORE_PERIOD ), // TODO: Discuss with Cyril about this
GxsTokenQueue(this), idService(identities), GxsTokenQueue(this), idService(identities),
servClientsMutex("p3GxsMails client services map mutex") {} servClientsMutex("p3GxsMails client services map mutex") {}
@ -101,9 +89,8 @@ struct p3GxsMails : RsGenExchange, GxsTokenQueue
void registerGxsMailsClient( GxsMailsClient::GxsMailSubServices serviceType, void registerGxsMailsClient( GxsMailsClient::GxsMailSubServices serviceType,
GxsMailsClient* service ); GxsMailsClient* service );
/**
* @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type) /// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type)
*/
virtual void handleResponse(uint32_t token, uint32_t req_type); virtual void handleResponse(uint32_t token, uint32_t req_type);
/// @see RsGenExchange::service_tick() /// @see RsGenExchange::service_tick()
@ -120,11 +107,27 @@ protected:
void notifyChanges(std::vector<RsGxsNotify *> &changes); void notifyChanges(std::vector<RsGxsNotify *> &changes);
private: private:
/// Time interval of inactivity before a distribution group is unsubscribed /** Time interval of inactivity before a distribution group is unsubscribed.
const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 0x76A700; // 3 months approx * Approximatively 3 months seems ok ATM. */
const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 0x76A700;
/// @brief AuthenPolicy check nothing ATM TODO talk with Cyril how this should be /**
static uint32_t AuthenPolicy() { return 0; } * This should be as little as possible as the size of the database can grow
* very fast taking in account we are handling mails for the whole network.
* We do prefer to resend a not acknowledged yet mail after
* GXS_STORAGE_PERIOD has passed and keep it little.
* Tought it can't be too little as this may cause signed acknowledged to
* get lost thus causing resend and fastly grow perceived async latency, in
* case two sporadically connected users sends mails each other.
* TODO: While it is ok for signed acknowledged to stays in the DB for a
* full GXS_STORAGE_PERIOD, mails should be removed as soon as a valid
* signed acknowledged is received for each of them.
* Two weeks seems fair ATM.
*/
const static uint32_t GXS_STORAGE_PERIOD = 0x127500;
/// Define how the backend should handle authentication based on signatures
static uint32_t AuthenPolicy();
/// Types to mark queries in tokens queue /// Types to mark queries in tokens queue
enum GxsReqResTypes enum GxsReqResTypes
@ -158,7 +161,6 @@ private:
*/ */
bool inline supersedePreferredGroup(const RsGxsGroupId& potentialGrId) bool inline supersedePreferredGroup(const RsGxsGroupId& potentialGrId)
{ {
//std::cout << "supersedePreferredGroup(const RsGxsGroupId& potentialGrId) " << preferredGroupId << " <? " << potentialGrId << std::endl;
if(preferredGroupId < potentialGrId) if(preferredGroupId < potentialGrId)
{ {
std::cerr << "supersedePreferredGroup(...) " << potentialGrId std::cerr << "supersedePreferredGroup(...) " << potentialGrId
@ -169,17 +171,39 @@ private:
return false; return false;
} }
/// @return true if has passed more then interval seconds time since timeStamp /** @return true if has passed more then interval seconds between timeStamp
bool static inline olderThen(time_t timeStamp, int32_t interval) * and ref. @param ref by default now is taked as reference. */
{ return (timeStamp + interval) < time(NULL); } bool static inline olderThen(time_t timeStamp, int32_t interval,
time_t ref = time(NULL))
{ return (timeStamp + interval) < ref; }
/// Decrypt email content and pass it to dispatchDecryptedMail(...) /// Decrypt email content and pass it to dispatchDecryptedMail(...)
bool handleEcryptedMail(RsGxsMailItem* mail); bool handleEcryptedMail(const RsGxsMailItem* mail);
/// Dispatch the message to the recipient service /// Dispatch the message to the recipient service
bool dispatchDecryptedMail( RsGxsMailItem* received_msg, bool dispatchDecryptedMail( const RsGxsMailItem* received_msg,
uint8_t* decrypted_data, const uint8_t* decrypted_data,
uint32_t decrypted_data_size ); uint32_t decrypted_data_size );
}; };
struct TestGxsMailClientService : GxsMailsClient
{
TestGxsMailClientService(p3GxsMails& gmxMailService)
{
gmxMailService.registerGxsMailsClient( GxsMailSubServices::TEST_SERVICE,
this );
}
/// @see GxsMailsClient::receiveGxsMail(...)
virtual bool receiveGxsMail( const RsGxsMailItem* originalMessage,
const uint8_t* data, uint32_t dataSize )
{
std::cout << "TestGxsMailClientService::receiveGxsMail(...) got message"
<< " from: " << originalMessage->meta.mAuthorId << std::endl
<< "\t" << std::string((char*)data, dataSize) << std::endl;
return true;
}
};