mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-29 09:26:18 -05:00
GxsMail implemented RSA encrypted mails sending
Add notice about param not being checked in GxsSecurity Use proper types for RsGenExchange::getMsg* params Implement bitwise or and not operators for t_RsGenericIdType GxsMail unsubscribe old unused groups GxsMail initial work on supporting client services Implemented p3IdService::encryptData(...) for multiple recipients
This commit is contained in:
parent
0af9291e54
commit
54a0f87369
@ -35,9 +35,10 @@
|
||||
|
||||
|
||||
/*!
|
||||
* This contains functionality for performing security
|
||||
* operations needed to validate data received in RsGenExchange
|
||||
* This contains functionality for performing basic security operations needed
|
||||
* in RsGenExchange operations.
|
||||
* Also has routine for creating security objects around msgs and groups
|
||||
* TODO: Those functions doesn't do param checking!
|
||||
*/
|
||||
class GxsSecurity
|
||||
{
|
||||
|
@ -1332,7 +1332,7 @@ bool RsGenExchange::getGroupData(const uint32_t &token, std::vector<RsGxsGrpItem
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RsGenExchange::getMsgData(const uint32_t &token, GxsMsgDataMap &msgItems)
|
||||
bool RsGenExchange::getMsgData(uint32_t token, GxsMsgDataMap &msgItems)
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
NxsMsgDataResult msgResult;
|
||||
@ -1382,7 +1382,8 @@ bool RsGenExchange::getMsgData(const uint32_t &token, GxsMsgDataMap &msgItems)
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RsGenExchange::getMsgRelatedData(const uint32_t &token, GxsMsgRelatedDataMap &msgItems)
|
||||
bool RsGenExchange::getMsgRelatedData( uint32_t token,
|
||||
GxsMsgRelatedDataMap &msgItems )
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
NxsMsgRelatedDataResult msgResult;
|
||||
|
@ -324,11 +324,11 @@ public:
|
||||
* @param token token to be redeemed for message item retrieval
|
||||
* @param msgItems
|
||||
*/
|
||||
bool getMsgData(const uint32_t &token, GxsMsgDataMap& msgItems);
|
||||
bool getMsgData(uint32_t token, GxsMsgDataMap& msgItems);
|
||||
|
||||
template <class MsgType>
|
||||
bool getMsgDataT(const uint32_t &token, std::map<RsGxsGroupId,
|
||||
std::vector<MsgType*> >& msgItems)
|
||||
bool getMsgDataT( uint32_t token, std::map<RsGxsGroupId,
|
||||
std::vector<MsgType*> >& msgItems)
|
||||
{
|
||||
GxsMsgDataMap msgData;
|
||||
bool ok = getMsgData(token, msgData);
|
||||
@ -365,7 +365,7 @@ public:
|
||||
* @param token token to be redeemed for message item retrieval
|
||||
* @param msgItems
|
||||
*/
|
||||
bool getMsgRelatedData(const uint32_t &token, GxsMsgRelatedDataMap& msgItems);
|
||||
bool getMsgRelatedData(uint32_t token, GxsMsgRelatedDataMap& msgItems);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -855,7 +855,7 @@ gxsphotoshare {
|
||||
rs_gxs_mail
|
||||
{
|
||||
HEADERS += serialiser/rsgxsmailitems.h services/p3gxsmails.h
|
||||
SOURCES += services/p3gxsmails.cpp
|
||||
SOURCES += serialiser/rsgxsmailitems.cc services/p3gxsmails.cpp
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,6 +94,22 @@ template<uint32_t ID_SIZE_IN_BYTES,bool UPPER_CASE,uint32_t UNIQUE_IDENTIFIER> c
|
||||
inline bool operator==(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& fp) const { return !memcmp(bytes,fp.bytes,ID_SIZE_IN_BYTES) ; }
|
||||
inline bool operator!=(const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& fp) const { return !!memcmp(bytes,fp.bytes,ID_SIZE_IN_BYTES); }
|
||||
inline bool operator< (const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& fp) const { return (memcmp(bytes,fp.bytes,ID_SIZE_IN_BYTES) < 0) ; }
|
||||
inline t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>
|
||||
operator~ () const
|
||||
{
|
||||
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> ret;
|
||||
for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i)
|
||||
ret.bytes[i] = ~bytes[i];
|
||||
return ret;
|
||||
}
|
||||
inline t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>
|
||||
operator| (const t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER>& fp) const
|
||||
{
|
||||
t_RsGenericIdType<ID_SIZE_IN_BYTES,UPPER_CASE,UNIQUE_IDENTIFIER> ret;
|
||||
for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i)
|
||||
ret.bytes[i] = bytes[i] | fp.bytes[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool isNull() const
|
||||
{
|
||||
|
@ -137,7 +137,7 @@ public:
|
||||
|
||||
/*!
|
||||
* Use this to request group related information
|
||||
* @param token The token returned for the request, store this value to pool for request completion
|
||||
* @param token The token returned for the request, store this value to poll for request completion
|
||||
* @param ansType The type of result (e.g. group data, meta, ids)
|
||||
* @param opts Additional option that affect outcome of request. Please see specific services, for valid values
|
||||
* @param groupIds group id to request info for
|
||||
@ -147,7 +147,7 @@ public:
|
||||
|
||||
/*!
|
||||
* Use this to request all group related info
|
||||
* @param token The token returned for the request, store this value to pool for request completion
|
||||
* @param token The token returned for the request, store this value to poll for request completion
|
||||
* @param ansType The type of result (e.g. group data, meta, ids)
|
||||
* @param opts Additional option that affect outcome of request. Please see specific services, for valid values
|
||||
* @return
|
||||
@ -155,7 +155,7 @@ public:
|
||||
virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) = 0;
|
||||
|
||||
/*!
|
||||
* Use this to get msg related information, store this value to pole for request completion
|
||||
* Use this to get msg related information, store this value to poll for request completion
|
||||
* @param token The token returned for the request
|
||||
* @param ansType The type of result wanted
|
||||
* @param opts Additional option that affect outcome of request. Please see specific services, for valid values
|
||||
@ -165,7 +165,7 @@ public:
|
||||
virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) = 0;
|
||||
|
||||
/*!
|
||||
* Use this to get msg related information, store this value to pole for request completion
|
||||
* Use this to get msg related information, store this value to poll for request completion
|
||||
* @param token The token returned for the request
|
||||
* @param ansType The type of result wanted
|
||||
* @param opts Additional option that affect outcome of request. Please see specific services, for valid values
|
||||
|
@ -1491,7 +1491,7 @@ int RsServer::StartupRetroShare()
|
||||
RsGeneralDataService* gxsmail_ds = new RsDataService(
|
||||
currGxsDir + "/", "gxsmails_db", RS_SERVICE_TYPE_GXS_MAIL,
|
||||
NULL, rsInitConfig->gxs_passwd );
|
||||
p3GxsMails* mGxsMails = new p3GxsMails(gxsmail_ds, NULL, mGxsIdService);
|
||||
p3GxsMails* mGxsMails = new p3GxsMails(gxsmail_ds, NULL, *mGxsIdService);
|
||||
RsGxsNetService* gxsmails_ns = new RsGxsNetService(
|
||||
RS_SERVICE_TYPE_GXS_MAIL, gxsmail_ds, nxsMgr, mGxsMails,
|
||||
mGxsMails->getServiceInfo(), mReputations, mGxsCircles,
|
||||
|
96
libretroshare/src/serialiser/rsgxsmailitems.cc
Normal file
96
libretroshare/src/serialiser/rsgxsmailitems.cc
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* GXS Mailing Service
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "serialiser/rsgxsmailitems.h"
|
||||
|
||||
const RsGxsId RsGxsMailBaseItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
||||
|
||||
|
||||
bool RsGxsMailBaseItem::serialize(uint8_t* data, uint32_t size,
|
||||
uint32_t& offset) const
|
||||
{
|
||||
bool ok = setRsItemHeader(data, size, PacketId(), size);
|
||||
ok = ok && (offset += 8); // Take in account the header
|
||||
ok = ok && setRawUInt8(data, size, &offset, cryptoType);
|
||||
ok = ok && recipientsHint.serialise(data, size, offset);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RsGxsMailBaseItem::deserialize(const uint8_t* data, uint32_t& size,
|
||||
uint32_t& offset)
|
||||
{
|
||||
void* dataPtr = reinterpret_cast<void*>(const_cast<uint8_t*>(data));
|
||||
uint32_t rssize = getRsItemSize(dataPtr);
|
||||
uint32_t roffset = offset + 8;
|
||||
bool ok = rssize <= size;
|
||||
uint8_t crType;
|
||||
ok = ok && getRawUInt8(dataPtr, rssize, &offset, &crType);
|
||||
cryptoType = static_cast<EncryptionMode>(crType);
|
||||
ok = ok && recipientsHint.deserialise(dataPtr, rssize, roffset);
|
||||
if(ok) { size = rssize; offset = roffset; }
|
||||
else size = 0;
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::ostream&RsGxsMailBaseItem::print(std::ostream& out, uint16_t)
|
||||
{ return out; }
|
||||
|
||||
bool RsGxsMailSerializer::serialise(RsItem* item, void* data, uint32_t* size)
|
||||
{
|
||||
uint32_t itemSize = RsGxsMailSerializer::size(item);
|
||||
if(*size < itemSize)
|
||||
{
|
||||
std::cout << "RsGxsMailSerializer::serialise(...) failed due to wrong size: "
|
||||
<< size << " < " << itemSize << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* dataPtr = reinterpret_cast<uint8_t*>(data);
|
||||
bool ok = true;
|
||||
switch(item->PacketSubType())
|
||||
{
|
||||
case GXS_MAIL_SUBTYPE_MAIL:
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
RsGxsMailItem* i = dynamic_cast<RsGxsMailItem*>(item);
|
||||
ok = ok && i->serialize(dataPtr, itemSize, offset);
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_ACK:
|
||||
{
|
||||
RsGxsMailAckItem* i = dynamic_cast<RsGxsMailAckItem*>(item);
|
||||
ok = ok && setRsItemHeader(data, itemSize, item->PacketId(), itemSize);
|
||||
uint32_t offset = 8;
|
||||
ok = ok && i->recipient.serialise(data, itemSize, offset);
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_GROUP:
|
||||
ok = ok && setRsItemHeader(data, itemSize, item->PacketId(), itemSize);
|
||||
break;
|
||||
default: ok = false; break;
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
*size = itemSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << "RsGxsMailSerializer::serialise(...) failed!" << std::endl;
|
||||
return false;
|
||||
}
|
@ -24,28 +24,36 @@
|
||||
#include "serialiser/rstlvidset.h"
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC
|
||||
#include "services/p3idservice.h"
|
||||
|
||||
|
||||
enum GxsMailSubtypes
|
||||
/// Values must fit into uint8_t
|
||||
enum GxsMailItemsSubtypes
|
||||
{
|
||||
GXS_MAIL_SUBTYPE_MAIL = 1,
|
||||
GXS_MAIL_SUBTYPE_ACK,
|
||||
GXS_MAIL_SUBTYPE_GROUP
|
||||
GXS_MAIL_SUBTYPE_MAIL = 1,
|
||||
GXS_MAIL_SUBTYPE_ACK = 2,
|
||||
GXS_MAIL_SUBTYPE_GROUP = 3
|
||||
};
|
||||
|
||||
struct RsGxsMailBaseItem : RsGxsMsgItem
|
||||
{
|
||||
RsGxsMailBaseItem(GxsMailSubtypes subtype) :
|
||||
RsGxsMsgItem(RS_SERVICE_TYPE_GXS_MAIL, (uint8_t)subtype), flags(0) {}
|
||||
RsGxsMailBaseItem(GxsMailItemsSubtypes subtype) :
|
||||
RsGxsMsgItem( RS_SERVICE_TYPE_GXS_MAIL,
|
||||
static_cast<uint8_t>(subtype) ) {}
|
||||
|
||||
enum RsGxsMailFlags { READ = 0x1 };
|
||||
uint8_t flags;
|
||||
/// Values must fit into uint8_t
|
||||
enum EncryptionMode
|
||||
{
|
||||
CLEAR_TEXT = 1,
|
||||
RSA = 2,
|
||||
UNDEFINED_ENCRYPTION = 250
|
||||
};
|
||||
EncryptionMode cryptoType;
|
||||
|
||||
/**
|
||||
* @brief recipient_hint used instead of plain recipient id, so sender can
|
||||
* @brief recipientsHint used instead of plain recipient id, so sender can
|
||||
* decide the equilibrium between exposing the recipient and the cost of
|
||||
* completely anonymize it. So a bunch of luky non recipient can conclude
|
||||
* rapidly that they are not recipiend without trying to decrypt the
|
||||
* rapidly that they are not the recipient without trying to decrypt the
|
||||
* message.
|
||||
*
|
||||
* To be able to decide how much metadata we disclose sending a message we
|
||||
@ -54,10 +62,10 @@ struct RsGxsMailBaseItem : RsGxsMsgItem
|
||||
* obscure like 0xFF...FF so potentially everyone could be the recipient, or
|
||||
* may expose the complete recipient id or be a middle ground.
|
||||
* To calculate arbitrary precise hint one do a bitwise OR of the recipients
|
||||
* keys and an arbytrary salting mask, the more recipients has the mail and
|
||||
* the more 1 bits has the mask the less accurate is the hint.
|
||||
* keys and an arbitrary salt, the more recipients has the mail and the more
|
||||
* 1 bits has the salt the less accurate is the hint.
|
||||
* This way the sender is able to adjust the metadata privacy needed for the
|
||||
* message, in the more private case (recipient_hint == 0xFF...FF) no one
|
||||
* message, in the more private case (recipientsHint == 0xFFF...FFF) no one
|
||||
* has a clue about who is the actual recipient, while this imply the cost
|
||||
* that every potencial recipient has to try to decrypt it to know if it is
|
||||
* for herself. This way a bunch of non recipients can rapidly discover that
|
||||
@ -76,42 +84,75 @@ struct RsGxsMailBaseItem : RsGxsMsgItem
|
||||
* mail is directed to the actual recipient as the "apparently"
|
||||
* corresponding hint may be fruit of a "luky" salting of another id.
|
||||
*/
|
||||
uint32_t recipient_hint;
|
||||
RsGxsId recipientsHint;
|
||||
|
||||
void inline saltRecipientHint(const RsGxsId& salt)
|
||||
{ saltRecipientHint(recipientsHint, salt); }
|
||||
|
||||
void static inline saltRecipientHint(RsGxsId& hint, const RsGxsId& salt)
|
||||
{ hint = hint | salt; }
|
||||
|
||||
/**
|
||||
* @brief maybe_recipient given an id and an hint check if they match
|
||||
* @see recipient_hint
|
||||
* @brief maybeRecipient given an id and an hint check if they match
|
||||
* @see recipientHint
|
||||
* @note this is not the final implementation as id and hint are not 32bit
|
||||
* integers it is just to not forget how to verify the hint/id matching
|
||||
* fastly with boolean ops
|
||||
* @return true if the id may be recipient of the hint, false otherwise
|
||||
*/
|
||||
static bool maybe_recipient(uint32_t id, uint32_t hint)
|
||||
{ return (~id|hint) == 0xFFFFFFFF; }
|
||||
bool static inline maybeRecipient(const RsGxsId& hint, const RsGxsId& id)
|
||||
{ return (~id|hint) == allRecipientsHint; }
|
||||
|
||||
const static RsGxsId allRecipientsHint;
|
||||
|
||||
void inline clear()
|
||||
{
|
||||
cryptoType = UNDEFINED_ENCRYPTION;
|
||||
recipientsHint.clear();
|
||||
meta = RsMsgMetaData();
|
||||
}
|
||||
|
||||
static uint32_t inline size()
|
||||
{
|
||||
return 8 + // Header
|
||||
1 + // cryptoType
|
||||
RsGxsId::serial_size(); // recipientsHint
|
||||
}
|
||||
bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const;
|
||||
bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset);
|
||||
std::ostream &print(std::ostream &out, uint16_t /*indent = 0*/);
|
||||
};
|
||||
|
||||
struct RsGxsMailItem : RsGxsMailBaseItem
|
||||
{
|
||||
RsGxsMailItem() : RsGxsMailBaseItem(GXS_MAIL_SUBTYPE_MAIL) {}
|
||||
RsGxsMailItem(GxsMailItemsSubtypes subtype) :
|
||||
RsGxsMailBaseItem(subtype) {}
|
||||
RsGxsMailItem() :
|
||||
RsGxsMailBaseItem(GXS_MAIL_SUBTYPE_MAIL) {}
|
||||
|
||||
RsTlvGxsIdSet recipients;
|
||||
/** This should travel encrypted, unless EncryptionMode::CLEAR_TEXT
|
||||
* is specified */
|
||||
std::vector<uint8_t> payload;
|
||||
|
||||
/**
|
||||
* @brief body of the email
|
||||
* Should we ue MIME for compatibility with fido RS-email gateway?
|
||||
* https://github.com/zeroreserve/fido
|
||||
* https://github.com/RetroShare/fido
|
||||
* https://en.wikipedia.org/wiki/MIME
|
||||
*/
|
||||
std::string body;
|
||||
|
||||
void clear()
|
||||
uint32_t size() const { return RsGxsMailBaseItem::size() + payload.size(); }
|
||||
bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const
|
||||
{
|
||||
recipients.TlvClear();
|
||||
body.clear();
|
||||
return size < MAX_SIZE
|
||||
&& RsGxsMailBaseItem::serialize(data, size, offset)
|
||||
&& memcpy(data+offset, &payload[0], payload.size());
|
||||
}
|
||||
std::ostream &print(std::ostream &out, uint16_t indent = 0)
|
||||
{ return recipients.print(out, indent) << body; }
|
||||
bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset)
|
||||
{
|
||||
uint32_t bsz = RsGxsMailBaseItem::size();
|
||||
uint32_t psz = size - bsz;
|
||||
return size < MAX_SIZE && size >= bsz
|
||||
&& RsGxsMailBaseItem::deserialize(data, size, offset)
|
||||
&& (payload.resize(psz), memcpy(&payload[0], data+offset, psz));
|
||||
}
|
||||
void clear() { RsGxsMailBaseItem::clear(); payload.clear(); }
|
||||
|
||||
/// Maximum mail size in bytes 10 MiB is more than anything sane can need
|
||||
const static uint32_t MAX_SIZE = 10*8*1024*1024;
|
||||
};
|
||||
|
||||
struct RsGxsMailAckItem : RsGxsMailBaseItem
|
||||
@ -147,19 +188,13 @@ struct RsGxsMailSerializer : RsSerialType
|
||||
|
||||
uint32_t size(RsItem* item)
|
||||
{
|
||||
uint32_t s = 8; // Header
|
||||
|
||||
uint32_t sz = 0;
|
||||
switch(item->PacketSubType())
|
||||
{
|
||||
case GXS_MAIL_SUBTYPE_MAIL:
|
||||
{
|
||||
RsGxsMailItem* i = dynamic_cast<RsGxsMailItem*>(item);
|
||||
if(i)
|
||||
{
|
||||
s += 4; // RsGxsMailBaseItem::recipient_hint
|
||||
s += i->recipients.TlvSize();
|
||||
s += getRawStringSize(i->body);
|
||||
}
|
||||
if(i) sz = i->size();
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_ACK:
|
||||
@ -167,74 +202,36 @@ struct RsGxsMailSerializer : RsSerialType
|
||||
RsGxsMailAckItem* i = dynamic_cast<RsGxsMailAckItem*>(item);
|
||||
if(i)
|
||||
{
|
||||
s += 4; // RsGxsMailBaseItem::recipient_hint
|
||||
s += 1; // RsGxsMailAckItem::read
|
||||
s += i->recipient.serial_size();
|
||||
sz = 8; // Header
|
||||
sz += 4; // RsGxsMailBaseItem::recipient_hint
|
||||
sz += 1; // RsGxsMailAckItem::read
|
||||
sz += i->recipient.serial_size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_GROUP: break;
|
||||
default: return 0;
|
||||
case GXS_MAIL_SUBTYPE_GROUP: sz = 8; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return s;
|
||||
return sz;
|
||||
}
|
||||
|
||||
bool serialise(RsItem* item, void* data, uint32_t* size)
|
||||
{
|
||||
uint32_t tlvsize = RsGxsMailSerializer::size(item);
|
||||
uint32_t offset = 0;
|
||||
|
||||
if(*size < tlvsize) return false;
|
||||
|
||||
*size = tlvsize;
|
||||
|
||||
bool ok = true;
|
||||
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
|
||||
|
||||
/* skip the header */
|
||||
offset += 8;
|
||||
|
||||
switch(item->PacketSubType())
|
||||
{
|
||||
case GXS_MAIL_SUBTYPE_MAIL:
|
||||
{
|
||||
RsGxsMailItem* i = dynamic_cast<RsGxsMailItem*>(item);
|
||||
if(i)
|
||||
{
|
||||
ok &= i->recipients.SetTlv(data, tlvsize, &offset);
|
||||
ok &= setRawString(data, tlvsize, &offset, i->body);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_ACK:
|
||||
{
|
||||
RsGxsMailAckItem* i = dynamic_cast<RsGxsMailAckItem*>(item);
|
||||
if(i)
|
||||
{
|
||||
ok &= i->recipient.serialise(data, tlvsize, offset);
|
||||
ok &= setRawUInt8(data, tlvsize, &offset, i->flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_GROUP: break;
|
||||
default: ok = false; break;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
bool serialise(RsItem* item, void* data, uint32_t* size);
|
||||
|
||||
RsItem* deserialise(void* data, uint32_t* size)
|
||||
{
|
||||
uint32_t rstype = getRsItemId(data);
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
uint32_t offset = 8;
|
||||
uint8_t pktv = getRsItemVersion(rstype);
|
||||
uint16_t srvc = getRsItemService(rstype);
|
||||
|
||||
|
||||
if ( (RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) ||
|
||||
(RS_SERVICE_TYPE_GXS_MAIL != getRsItemService(rstype)) ||
|
||||
if ( (RS_PKT_VERSION_SERVICE != pktv) || // 0x02
|
||||
(RS_SERVICE_TYPE_GXS_MAIL != srvc) || // 0x0230 = 560
|
||||
(*size < rssize) )
|
||||
{
|
||||
print_stacktrace();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*size = rssize;
|
||||
bool ok = true;
|
||||
@ -245,15 +242,16 @@ struct RsGxsMailSerializer : RsSerialType
|
||||
case GXS_MAIL_SUBTYPE_MAIL:
|
||||
{
|
||||
RsGxsMailItem* i = new RsGxsMailItem();
|
||||
ok &= i->recipients.GetTlv(data, *size, &offset);
|
||||
ok &= getRawString(data, *size, &offset, i->body);
|
||||
uint32_t offset = 0;
|
||||
const uint8_t* dataPtr = reinterpret_cast<uint8_t*>(data);
|
||||
ok = ok && i->deserialize(dataPtr, *size, offset);
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
case GXS_MAIL_SUBTYPE_ACK:
|
||||
{
|
||||
RsGxsMailAckItem* i = new RsGxsMailAckItem();
|
||||
ok &= getRawUInt8(data, *size, &offset, &i->flags);
|
||||
uint32_t offset = 0;
|
||||
ok &= i->recipient.deserialise(data, *size, offset);
|
||||
ret = i;
|
||||
break;
|
||||
|
@ -17,30 +17,137 @@
|
||||
*/
|
||||
|
||||
#include "p3gxsmails.h"
|
||||
#include "util/stacktrace.h"
|
||||
|
||||
|
||||
bool p3GxsMails::sendEmail(const RsGxsId& own_gxsid, const RsGxsId& recipient, const std::string& body)
|
||||
bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service,
|
||||
const RsGxsId& own_gxsid, const RsGxsId& recipient,
|
||||
const uint8_t* data, uint32_t size,
|
||||
RsGxsMailBaseItem::EncryptionMode cm)
|
||||
{
|
||||
std::vector<const RsGxsId*> recipients;
|
||||
recipients.push_back(&recipient);
|
||||
return sendMail(service, own_gxsid, recipients, data, size, cm);
|
||||
}
|
||||
|
||||
bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service,
|
||||
const RsGxsId& own_gxsid,
|
||||
const std::vector<const RsGxsId*>& recipients,
|
||||
const uint8_t* data, uint32_t size,
|
||||
RsGxsMailBaseItem::EncryptionMode cm )
|
||||
{
|
||||
std::cout << "p3GxsMails::sendEmail(...)" << std::endl;
|
||||
|
||||
if(preferredGroupId.isNull())
|
||||
{
|
||||
requestGroupsList();
|
||||
requestGroupsData();
|
||||
std::cerr << "p3GxsMails::sendEmail(...) preferredGroupId.isNull()!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
RsGxsMailItem* m = new RsGxsMailItem;
|
||||
m->meta.mAuthorId = own_gxsid;
|
||||
m->meta.mGroupId = preferredGroupId;
|
||||
m->recipients.ids.insert(recipient);
|
||||
m->body = body;
|
||||
if(!idService.isOwnId(own_gxsid))
|
||||
{
|
||||
std::cerr << "p3GxsMails::sendEmail(...) isOwnId(own_gxsid) false!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<RsGxsId> rcps;
|
||||
typedef std::vector<const RsGxsId*>::const_iterator itT;
|
||||
for(itT it = recipients.begin(); it != recipients.end(); it++)
|
||||
{
|
||||
const RsGxsId* gId = *it;
|
||||
|
||||
if(!gId || gId->isNull())
|
||||
{
|
||||
std::cerr << "p3GxsMails::sendEmail(...) got invalid recipient"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
rcps.insert(*gId);
|
||||
}
|
||||
if(rcps.empty())
|
||||
{
|
||||
std::cerr << "p3GxsMails::sendEmail(...) got no recipients"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
RsGxsMailItem* item = new RsGxsMailItem();
|
||||
|
||||
// Public metadata
|
||||
item->meta.mAuthorId = own_gxsid;
|
||||
item->meta.mGroupId = preferredGroupId;
|
||||
|
||||
typedef std::set<RsGxsId>::const_iterator siT;
|
||||
for(siT it = rcps.begin(); it != rcps.end(); ++it)
|
||||
item->saltRecipientHint(*it);
|
||||
|
||||
// If there is jut one recipient salt with a random id to avoid leaking it
|
||||
if(rcps.size() == 1) item->saltRecipientHint(RsGxsId::random());
|
||||
|
||||
|
||||
/* At this point we do a lot of memory copying, it doesn't look pretty but
|
||||
* ATM haven't thinked of an elegant way to have the GxsMailSubServices
|
||||
* travelling encrypted withuot copying memory around or responsabilize the
|
||||
* client service to embed it in data array that is awful */
|
||||
|
||||
uint16_t serv = static_cast<uint16_t>(service);
|
||||
uint32_t clearTextPldSize = size+2;
|
||||
item->payload.resize(clearTextPldSize);
|
||||
uint32_t _discard = 0;
|
||||
setRawUInt16(&item->payload[0], clearTextPldSize, &_discard, serv);
|
||||
memcpy(&item->payload[2], data, size);
|
||||
|
||||
switch (cm)
|
||||
{
|
||||
case RsGxsMailBaseItem::CLEAR_TEXT:
|
||||
{
|
||||
std::cerr << "p3GxsMails::sendMail(...) you are sending a mail without"
|
||||
<< " encryption, everyone can read it!" << std::endl;
|
||||
print_stacktrace();
|
||||
break;
|
||||
}
|
||||
case RsGxsMailBaseItem::RSA:
|
||||
{
|
||||
uint8_t* encryptedData = NULL;
|
||||
uint32_t encryptedSize = 0;
|
||||
uint32_t encryptError = 0;
|
||||
if( idService.encryptData( &item->payload[0], clearTextPldSize,
|
||||
encryptedData, encryptedSize,
|
||||
rcps, true, encryptError ) )
|
||||
{
|
||||
item->payload.resize(encryptedSize);
|
||||
memcpy(&item->payload[0], encryptedData, encryptedSize);
|
||||
free(encryptedData);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "p3GxsMails::sendMail(...) RSA encryption failed! "
|
||||
<< "error_status: " << encryptError << std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case RsGxsMailBaseItem::UNDEFINED_ENCRYPTION:
|
||||
default:
|
||||
std::cerr << "p3GxsMails::sendMail(...) attempt to send mail with wrong"
|
||||
<< " EncryptionMode " << cm << " dropping mail!" << std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t token;
|
||||
publishMsg(token, m);
|
||||
|
||||
publishMsg(token, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type)
|
||||
{
|
||||
//std::cout << "p3GxsMails::handleResponse(" << token << ", " << req_type << ")" << std::endl;
|
||||
@ -54,21 +161,37 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type)
|
||||
for( std::vector<RsGxsGrpItem *>::iterator it = groups.begin();
|
||||
it != groups.end(); ++it )
|
||||
{
|
||||
RsGxsGrpItem* grp = *it;
|
||||
if(!IS_GROUP_SUBSCRIBED(grp->meta.mSubscribeFlags))
|
||||
{
|
||||
std::cout << "p3GxsMails::handleResponse(...) subscribing to group: " << grp->meta.mGroupId << std::endl;
|
||||
uint32_t token;
|
||||
subscribeToGroup(token, grp->meta.mGroupId, true);
|
||||
}
|
||||
/* For each group check if it is better candidate then
|
||||
* preferredGroupId, if it is supplant it and subscribe if it is not
|
||||
* subscribed yet.
|
||||
* Otherwise if it has recent messages subscribe.
|
||||
* If the group was already subscribed has no recent messages
|
||||
* unsubscribe.
|
||||
*/
|
||||
|
||||
supersedePreferredGroup(grp->meta.mGroupId);
|
||||
const RsGroupMetaData& meta = (*it)->meta;
|
||||
bool subscribed = IS_GROUP_SUBSCRIBED(meta.mSubscribeFlags);
|
||||
bool old = olderThen( meta.mLastPost,
|
||||
UNUSED_GROUP_UNSUBSCRIBE_INTERVAL );
|
||||
bool supersede = supersedePreferredGroup(meta.mGroupId);
|
||||
uint32_t token;
|
||||
|
||||
if( !subscribed && ( !old || supersede ))
|
||||
subscribeToGroup(token, meta.mGroupId, true);
|
||||
else if( subscribed && old )
|
||||
subscribeToGroup(token, meta.mGroupId, false);
|
||||
}
|
||||
|
||||
if(preferredGroupId.isNull())
|
||||
{
|
||||
std::cout << "p3GxsMails::handleResponse(...) preferredGroupId.isNull()" << std::endl;
|
||||
// TODO: Should check if we have friends before of doing this?
|
||||
/* This is true only at first run when we haven't received mail
|
||||
* distribuition groups from friends
|
||||
* TODO: We should check if we have some connected firend too, to
|
||||
* avoid to create yet another never used mail distribution group.
|
||||
*/
|
||||
|
||||
std::cerr << "p3GxsMails::handleResponse(...) preferredGroupId.isNu"
|
||||
<< "ll() let's create a new group." << std::endl;
|
||||
uint32_t token;
|
||||
publishGroup(token, new RsGxsMailGroupItem());
|
||||
queueRequest(token, GROUP_CREATE);
|
||||
@ -78,45 +201,86 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type)
|
||||
}
|
||||
case GROUP_CREATE:
|
||||
{
|
||||
std::cout << "p3GxsMails::handleResponse(...) GROUP_CREATE" << std::endl;
|
||||
std::cerr << "p3GxsMails::handleResponse(...) GROUP_CREATE" << std::endl;
|
||||
RsGxsGroupId grpId;
|
||||
acknowledgeTokenGrp(token, grpId);
|
||||
supersedePreferredGroup(grpId);
|
||||
break;
|
||||
}
|
||||
case MAILS_UPDATE:
|
||||
{
|
||||
std::cout << "p3GxsMails::handleResponse(...) MAILS_UPDATE" << std::endl;
|
||||
typedef std::map<RsGxsGroupId, std::vector<RsGxsMsgItem*> > GxsMsgDataMap;
|
||||
GxsMsgDataMap gpMsgMap;
|
||||
getMsgData(token, gpMsgMap);
|
||||
for ( GxsMsgDataMap::iterator gIt = gpMsgMap.begin();
|
||||
gIt != gpMsgMap.end(); ++gIt )
|
||||
{
|
||||
typedef std::vector<RsGxsMsgItem*> vT;
|
||||
vT& mv(gIt->second);
|
||||
for( vT::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt )
|
||||
{
|
||||
RsGxsMsgItem* it = *mIt;
|
||||
std::cout << "p3GxsMails::handleResponse(...) MAILS_UPDATE "
|
||||
<< (uint32_t)it->PacketSubType() << std::endl;
|
||||
switch(it->PacketSubType())
|
||||
{
|
||||
case GXS_MAIL_SUBTYPE_MAIL:
|
||||
{
|
||||
RsGxsMailItem* msg = dynamic_cast<RsGxsMailItem*>(it);
|
||||
if(msg)
|
||||
{
|
||||
std::cout << "p3GxsMails::handleResponse(...) "
|
||||
<< "GXS_MAIL_SUBTYPE_MAIL got recipientsHint: "
|
||||
<< msg->recipientsHint << " cryptoType: "
|
||||
<< (uint32_t)msg->cryptoType
|
||||
<< " payload size: " << msg->payload.size()
|
||||
<< std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cerr << "p3GxsMails::handleResponse(...) MAILS_UPDATE "
|
||||
<< "Unknown mail subtype : "
|
||||
<< it->PacketSubType() << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
std::cout << "p3GxsMails::handleResponse(...) Unknown req_type: " << req_type << std::endl;
|
||||
std::cerr << "p3GxsMails::handleResponse(...) Unknown req_type: "
|
||||
<< req_type << std::endl;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
GxsMsgDataMap msgItems;
|
||||
if(!RsGenExchange::getMsgData(token, msgItems))
|
||||
{
|
||||
std::cerr << "p3GxsMails::handleResponse(...) Cannot get msg data. "
|
||||
<< "Something's weird." << std::endl;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void p3GxsMails::service_tick()
|
||||
{
|
||||
static int tc = 0;
|
||||
++tc;
|
||||
if((tc % 100) == 0)
|
||||
{
|
||||
// std::cout << "p3GxsMails::service_tick() " << tc << " "
|
||||
// << preferredGroupId << std::endl;
|
||||
requestGroupsList();
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(((tc % 1000) == 0) || (tc == 50)) requestGroupsData();
|
||||
|
||||
if(tc == 500)
|
||||
{
|
||||
RsGxsId own_gxsid("d0df7474bdde0464679e6ef787890287");
|
||||
RsGxsId recipient("d060bea09dfa14883b5e6e517eb580cd");
|
||||
sendEmail(own_gxsid, recipient, "Ciao!");
|
||||
RsGxsId gxsidA("d0df7474bdde0464679e6ef787890287");
|
||||
RsGxsId gxsidB("d060bea09dfa14883b5e6e517eb580cd");
|
||||
if(idService.isOwnId(gxsidA))
|
||||
{
|
||||
std::string ciao("CiAone!");
|
||||
sendMail( GxsMailsClient::MSG_SERVICE, gxsidA, gxsidB,
|
||||
reinterpret_cast<const uint8_t*>(ciao.data()),
|
||||
ciao.size());
|
||||
}
|
||||
else if(idService.isOwnId(gxsidB))
|
||||
{
|
||||
std::string ciao("CiBone!");
|
||||
sendMail( GxsMailsClient::MSG_SERVICE, gxsidB, gxsidA,
|
||||
reinterpret_cast<const uint8_t*>(ciao.data()),
|
||||
ciao.size());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GxsTokenQueue::checkRequests();
|
||||
}
|
||||
@ -138,20 +302,19 @@ void p3GxsMails::notifyChanges(std::vector<RsGxsNotify*>& changes)
|
||||
|
||||
if (grpChange)
|
||||
{
|
||||
typedef std::list<RsGxsGroupId>::const_iterator itT;
|
||||
for( itT it = grpChange->mGrpIdList.begin();
|
||||
it != grpChange->mGrpIdList.end(); ++it )
|
||||
{
|
||||
const RsGxsGroupId& grpId = *it;
|
||||
std::cout << "p3GxsMails::notifyChanges(...) got group "
|
||||
<< grpId << std::endl;
|
||||
supersedePreferredGroup(grpId);
|
||||
}
|
||||
std::cout << "p3GxsMails::notifyChanges(...) grpChange" << std::endl;
|
||||
requestGroupsData(&(grpChange->mGrpIdList));
|
||||
}
|
||||
else if(msgChange)
|
||||
{
|
||||
typedef std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > mT;
|
||||
for( mT::const_iterator it = msgChange->msgChangeMap.begin();
|
||||
std::cout << "p3GxsMails::notifyChanges(...) msgChange" << std::endl;
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
getTokenService()->requestMsgInfo( token, 0xcaca,
|
||||
opts, msgChange->msgChangeMap );
|
||||
GxsTokenQueue::queueRequest(token, MAILS_UPDATE);
|
||||
|
||||
for( GxsMsgReq::const_iterator it = msgChange->msgChangeMap.begin();
|
||||
it != msgChange->msgChangeMap.end(); ++it )
|
||||
{
|
||||
const RsGxsGroupId& grpId = it->first;
|
||||
@ -161,20 +324,22 @@ void p3GxsMails::notifyChanges(std::vector<RsGxsNotify*>& changes)
|
||||
{
|
||||
const RsGxsMessageId& msgId = *vit;
|
||||
std::cout << "p3GxsMails::notifyChanges(...) got "
|
||||
<< "new message " << msgId << " in group "
|
||||
<< grpId << std::endl;
|
||||
<< "notification for message " << msgId
|
||||
<< " in group " << grpId << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool p3GxsMails::requestGroupsList()
|
||||
bool p3GxsMails::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
|
||||
{
|
||||
// std::cout << "p3GxsMails::requestGroupsList() GXS_REQUEST_TYPE_GROUP_META" << std::endl;
|
||||
// std::cout << "p3GxsMails::requestGroupsList()" << std::endl;
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts);
|
||||
if(!groupIds) getTokenService()->requestGroupInfo(token, 0xcaca, opts);
|
||||
else getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds);
|
||||
GxsTokenQueue::queueRequest(token, GROUPS_LIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -24,21 +24,81 @@
|
||||
#include "serialiser/rsgxsmailitems.h" // For RS_SERVICE_TYPE_GXS_MAIL
|
||||
#include "services/p3idservice.h" // For p3IdService
|
||||
|
||||
struct p3GxsMails;
|
||||
|
||||
class p3GxsMails : public RsGenExchange, public GxsTokenQueue
|
||||
struct GxsMailsClient
|
||||
{
|
||||
/// Subservices identifiers (like port for TCP)
|
||||
enum GxsMailSubServices { MSG_SERVICE };
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param destinationId
|
||||
* @param signingKey
|
||||
* @param data
|
||||
* @param dataSize
|
||||
* @return true if dispatching goes fine, false otherwise
|
||||
*/
|
||||
virtual bool receiveGxsMail( const RsGxsId& destinationId,
|
||||
const RsGxsId& signingKey,
|
||||
uint8_t* data, uint32_t dataSize ) = 0;
|
||||
};
|
||||
|
||||
struct p3GxsMails : RsGenExchange, GxsTokenQueue
|
||||
{
|
||||
public:
|
||||
p3GxsMails( RsGeneralDataService* gds, RsNetworkExchangeService* nes,
|
||||
p3IdService *identities ) :
|
||||
p3IdService& identities ) :
|
||||
RsGenExchange( gds, nes, new RsGxsMailSerializer(),
|
||||
RS_SERVICE_TYPE_GXS_MAIL, identities,
|
||||
RS_SERVICE_TYPE_GXS_MAIL, &identities,
|
||||
AuthenPolicy(),
|
||||
RS_GXS_DEFAULT_MSG_STORE_PERIOD ), // TODO: Discuss with Cyril about this
|
||||
GxsTokenQueue(this) {}
|
||||
GxsTokenQueue(this), idService(identities) {}
|
||||
|
||||
/// Public interface
|
||||
bool sendEmail( const RsGxsId& own_gxsid, const RsGxsId& recipient,
|
||||
const std::string& body );
|
||||
/**
|
||||
* Send an email to recipient, in the process author of the email is
|
||||
* disclosed to the network (because the sent GXS item is signed), while
|
||||
* recipient is not @see RsGxsMailBaseItem::recipientsHint for details on
|
||||
* recipient protection.
|
||||
* This method is part of the public interface of this service.
|
||||
* @return true if the mail will be sent, false if not
|
||||
*/
|
||||
bool sendMail( GxsMailsClient::GxsMailSubServices service,
|
||||
const RsGxsId& own_gxsid, const RsGxsId& recipient,
|
||||
const uint8_t* data, uint32_t size,
|
||||
RsGxsMailBaseItem::EncryptionMode cm = RsGxsMailBaseItem::RSA
|
||||
);
|
||||
|
||||
/**
|
||||
* Send an email to recipients, in the process author of the email is
|
||||
* disclosed to the network (because the sent GXS item is signed), while
|
||||
* recipients are not @see RsGxsMailBaseItem::recipientsHint for details on
|
||||
* recipient protection.
|
||||
* This method is part of the public interface of this service.
|
||||
* @return true if the mail will be sent, false if not
|
||||
*/
|
||||
bool sendMail( GxsMailsClient::GxsMailSubServices service,
|
||||
const RsGxsId& own_gxsid,
|
||||
const std::vector<const RsGxsId*>& recipients,
|
||||
const uint8_t* data, uint32_t size,
|
||||
RsGxsMailBaseItem::EncryptionMode cm = RsGxsMailBaseItem::RSA
|
||||
);
|
||||
|
||||
/**
|
||||
* Register a client service to p3GxsMails to receive mails via
|
||||
* GxsMailsClient::receiveGxsMail(...) callback
|
||||
* This is NOT thread safe!
|
||||
*/
|
||||
void registerGxsMailsClient( GxsMailsClient::GxsMailSubServices serviceType,
|
||||
GxsMailsClient* service )
|
||||
{ servClients[serviceType] = service; }
|
||||
|
||||
/**
|
||||
* @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type)
|
||||
@ -59,17 +119,26 @@ protected:
|
||||
void notifyChanges(std::vector<RsGxsNotify *> &changes);
|
||||
|
||||
private:
|
||||
/// Time interval of inactivity before a distribution group is unsubscribed
|
||||
const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 0x76A700; // 3 months approx
|
||||
|
||||
/// @brief AuthenPolicy check nothing ATM TODO talk with Cyril how this should be
|
||||
static uint32_t AuthenPolicy() { return 0; }
|
||||
|
||||
/// Types to mark GXS queries and answhers
|
||||
enum GxsReqResTypes { GROUPS_LIST, GROUP_CREATE };
|
||||
enum GxsReqResTypes { GROUPS_LIST, GROUP_CREATE, MAILS_UPDATE };
|
||||
|
||||
/// Store the id of the preferred GXS group to send emails
|
||||
RsGxsGroupId preferredGroupId;
|
||||
|
||||
/// Used for items {de,en}cryption
|
||||
p3IdService& idService;
|
||||
|
||||
/// Stores pointers to client services to notify them about new mails
|
||||
std::map<GxsMailsClient::GxsMailSubServices, GxsMailsClient*> servClients;
|
||||
|
||||
/// Request groups list to GXS backend. Async method.
|
||||
bool requestGroupsList();
|
||||
bool requestGroupsData(const std::list<RsGxsGroupId>* groupIds = NULL);
|
||||
|
||||
/**
|
||||
* Check if current preferredGroupId is the best against potentialGrId, if
|
||||
@ -84,21 +153,16 @@ private:
|
||||
//std::cout << "supersedePreferredGroup(const RsGxsGroupId& potentialGrId) " << preferredGroupId << " <? " << potentialGrId << std::endl;
|
||||
if(preferredGroupId < potentialGrId)
|
||||
{
|
||||
std::cerr << "supersedePreferredGroup(...) " << potentialGrId
|
||||
<< " supersed " << preferredGroupId << std::endl;
|
||||
preferredGroupId = potentialGrId;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @return true if has passed more then interval seconds time since timeStamp
|
||||
bool static inline olderThen(time_t timeStamp, int32_t interval)
|
||||
{ return (timeStamp + interval) < time(NULL); }
|
||||
};
|
||||
|
||||
/*
|
||||
19:27:29 G10h4ck: About the scalability stuff i have thinked we can implement TTL mechanism like IP does
|
||||
19:27:48 G10h4ck: better HTL Hop To Live
|
||||
19:28:09 G10h4ck: one send an email with an associated HTL for example 2
|
||||
19:28:32 G10h4ck: when a node receive that it decrement the HTL and store and forward it
|
||||
19:29:03 G10h4ck: if a received mail has an HTL greater then the last we received we store that one
|
||||
19:29:18 G10h4ck: this way we can control how much the mail should spread in the net
|
||||
19:29:47 G10h4ck: HTL should be upper limited to a maximum
|
||||
19:30:03 G10h4ck: so an abuser cant spread mails with 10000000 as HTL
|
||||
19:30:30 G10h4ck: if a mail is received witha suspicios HTL it may be dropped or the HTL reduced to MAX_HTL
|
||||
*/
|
||||
|
@ -1035,13 +1035,14 @@ bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTl
|
||||
timeStampKey(signature.keyId,info);
|
||||
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)
|
||||
{
|
||||
RsTlvPublicRSAKey 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))
|
||||
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.
|
||||
@ -1065,6 +1066,94 @@ bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_d
|
||||
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 std::set<RsGxsId>& encrypt_ids,
|
||||
bool force_load, uint32_t& error_status )
|
||||
{
|
||||
std::set<const RsGxsId*> keyNotYetFoundIds;
|
||||
|
||||
for( std::set<RsGxsId>::const_iterator it = encrypt_ids.begin();
|
||||
it != encrypt_ids.end(); ++it )
|
||||
{
|
||||
const RsGxsId& gId(*it);
|
||||
if(gId.isNull())
|
||||
{
|
||||
std::cerr << "p3IdService::encryptData(...) (EE) got null GXS id"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
else keyNotYetFoundIds.insert(&gId);
|
||||
}
|
||||
|
||||
if(keyNotYetFoundIds.empty())
|
||||
{
|
||||
std::cerr << "p3IdService::encryptData(...) (EE) got empty GXS ids set"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<RsTlvPublicRSAKey> encryption_keys;
|
||||
int maxRounds = force_load ? 6 : 1;
|
||||
for( int i=0; i < maxRounds; ++i )
|
||||
{
|
||||
for( std::set<const RsGxsId*>::iterator it = keyNotYetFoundIds.begin();
|
||||
it !=keyNotYetFoundIds.end(); ++it )
|
||||
{
|
||||
RsTlvPublicRSAKey encryption_key;
|
||||
if(getKey(**it, encryption_key) && !encryption_key.keyId.isNull())
|
||||
{
|
||||
encryption_keys.push_back(encryption_key);
|
||||
keyNotYetFoundIds.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if(keyNotYetFoundIds.empty()) break;
|
||||
else usleep(500*1000);
|
||||
}
|
||||
|
||||
if(!keyNotYetFoundIds.empty())
|
||||
{
|
||||
std::cerr << "p3IdService::encryptData(...) (EE) Cannot get "
|
||||
<< "encryption key for: ";
|
||||
for( std::set<const RsGxsId*>::iterator it = keyNotYetFoundIds.begin();
|
||||
it !=keyNotYetFoundIds.end(); ++it )
|
||||
std::cerr << **it << " ";
|
||||
std::cerr << std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!GxsSecurity::encrypt( encrypted_data, encrypted_data_size,
|
||||
decrypted_data, decrypted_data_size,
|
||||
encryption_keys ))
|
||||
{
|
||||
std::cerr << "p3IdService::encryptData(...) (EE) Encryption failed."
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
|
||||
error_status = RS_GIXS_ERROR_UNKNOWN;
|
||||
return false ;
|
||||
}
|
||||
|
||||
for( std::set<RsGxsId>::const_iterator it = encrypt_ids.begin();
|
||||
it != encrypt_ids.end(); ++it )
|
||||
{
|
||||
timeStampKey( *it,
|
||||
RsIdentityUsage(
|
||||
serviceType(),
|
||||
RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION ) );
|
||||
}
|
||||
|
||||
error_status = RS_GIXS_ERROR_NO_ERROR;
|
||||
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)
|
||||
{
|
||||
RsTlvPrivateRSAKey encryption_key ;
|
||||
|
@ -287,11 +287,37 @@ public:
|
||||
|
||||
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, const RsIdentityUsage &info, uint32_t& signing_error) ;
|
||||
virtual bool signData( const uint8_t* data,
|
||||
uint32_t data_size,
|
||||
const RsGxsId& signer_id,
|
||||
RsTlvKeySignature& signature,
|
||||
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 validateData( const uint8_t *data, uint32_t data_size,
|
||||
const RsTlvKeySignature& signature,
|
||||
bool force_load, const RsIdentityUsage &info,
|
||||
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);
|
||||
|
||||
bool encryptData( const uint8_t* decrypted_data,
|
||||
uint32_t decrypted_data_size,
|
||||
uint8_t*& encrypted_data,
|
||||
uint32_t& encrypted_data_size,
|
||||
const std::set<RsGxsId>& encrypt_ids,
|
||||
bool force_load, uint32_t& error_status );
|
||||
|
||||
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);
|
||||
@ -299,7 +325,9 @@ public:
|
||||
virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey &key);
|
||||
virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key);
|
||||
|
||||
virtual bool requestKey(const RsGxsId &id, const std::list<RsPeerId> &peers, const RsIdentityUsage &use_info);
|
||||
virtual bool requestKey( const RsGxsId &id,
|
||||
const std::list<RsPeerId> &peers,
|
||||
const RsIdentityUsage &use_info );
|
||||
virtual bool requestPrivateKey(const RsGxsId &id);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user