Added group validation code.

Tested and seems to work fine
Reverted back setAuthenPolicy static function to overwrite semantics and modified wiki and channels policy to equivalents statements

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6201 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
chrisparker126 2013-03-10 15:08:04 +00:00
parent 3fe1bf78be
commit bc8c569db3
6 changed files with 303 additions and 100 deletions

View File

@ -362,9 +362,105 @@ std::string GxsSecurity::getRsaKeySign(RSA *pubkey)
}
bool GxsSecurity::validateNxsGrp(RsNxsGrp *newGrp, RsTlvKeySignature& sign, RsTlvSecurityKey& key)
bool GxsSecurity::validateNxsGrp(RsNxsGrp& grp, RsTlvKeySignature& sign, RsTlvSecurityKey& key)
{
return false;
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << std::endl;
std::cerr << "RsNxsGrp :";
std::cerr << std::endl;
grp.print(std::cerr, 10);
std::cerr << std::endl;
#endif
RsGxsGrpMetaData& grpMeta = *(grp.metaData);
/********************* check signature *******************/
/* check signature timeperiod */
if ((grpMeta.mPublishTs < key.startTS) ||
(grpMeta.mPublishTs > key.endTS))
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << " GxsSecurity::validateNxsMsg() TS out of range";
std::cerr << std::endl;
#endif
return false;
}
/* decode key */
const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data;
long keylen = key.keyData.bin_len;
unsigned int siglen = sign.signData.bin_len;
unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data;
#ifdef DISTRIB_DEBUG
std::cerr << "GxsSecurity::validateNxsMsg() Decode Key";
std::cerr << " keylen: " << keylen << " siglen: " << siglen;
std::cerr << std::endl;
#endif
/* extract admin key */
RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen);
if (!rsakey)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << " Invalid RSA Key";
std::cerr << std::endl;
key.print(std::cerr, 10);
#endif
}
RsTlvKeySignatureSet signSet = grpMeta.signSet;
grpMeta.signSet.TlvClear();
uint32_t metaDataLen = grpMeta.serial_size();
uint32_t allGrpDataLen = metaDataLen + grp.grp.bin_len;
char* metaData = new char[metaDataLen];
char* allGrpData = new char[allGrpDataLen]; // msgData + metaData
grpMeta.serialise(metaData, metaDataLen);
// copy msg data and meta in allmsgData buffer
memcpy(allGrpData, grp.grp.bin_data, grp.grp.bin_len);
memcpy(allGrpData+(grp.grp.bin_len), metaData, metaDataLen);
EVP_PKEY *signKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(signKey, rsakey);
/* calc and check signature */
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
EVP_VerifyInit(mdctx, EVP_sha1());
EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen);
int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey);
/* clean up */
EVP_PKEY_free(signKey);
EVP_MD_CTX_destroy(mdctx);
grpMeta.signSet = signSet;
if (signOk == 1)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp() Signature OK";
std::cerr << std::endl;
#endif
return true;
}
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp() Signature invalid";
std::cerr << std::endl;
#endif
return false;
}
void GxsSecurity::setRSAPublicKey(RsTlvSecurityKey & key, RSA *rsa_pub)

View File

@ -120,7 +120,7 @@ public:
* @param key the public key to use to check signature
* @return true if group valid false otherwise
*/
static bool validateNxsGrp(RsNxsGrp *newGrp, RsTlvKeySignature& sign, RsTlvSecurityKey& key);
static bool validateNxsGrp(RsNxsGrp& grp, RsTlvKeySignature& sign, RsTlvSecurityKey& key);
/*!
* Validate a msg's signature using the given public key

View File

@ -286,15 +286,6 @@ uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& privateKe
uint8_t ret = createGroupSignatures(meta->signSet, grpData, *(grp->metaData));
// set meta to be transported as meta without private
// key components
grp->meta.setBinData(metaData, metaDataLen);
// but meta that is stored locally
// has private keys
// nxs net transports only bin data
meta->keys = privateKeySet;
// clean up
delete[] allGrpData;
delete[] metaData;
@ -333,7 +324,7 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin
PrivacyBitPos pos = GRP_OPTION_BITS;
// Check required permissions, and allow them to sign it - if they want too - as well!
if (checkAuthenFlag(pos, author_flag))
if ((!grpMeta.mAuthorId.empty()) || checkAuthenFlag(pos, author_flag))
{
needIdentitySign = true;
std::cerr << "Needs Identity sign! (Service Flags)";
@ -577,41 +568,40 @@ int RsGenExchange::createMessage(RsNxsMsg* msg)
}
else
{
// get publish key
// get publish key
RsGxsGrpMetaData* grpMeta = metaMap[id];
uint32_t metaDataLen = meta.serial_size();
uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len;
char* metaData = new char[metaDataLen];
char* allMsgData = new char[allMsgDataLen]; // msgData + metaData
uint32_t metaDataLen = meta.serial_size();
uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len;
char* metaData = new char[metaDataLen];
char* allMsgData = new char[allMsgDataLen]; // msgData + metaData
meta.serialise(metaData, &metaDataLen);
meta.serialise(metaData, &metaDataLen);
// copy msg data and meta in allmsgData buffer
memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len);
memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen);
// copy msg data and meta in allmsgData buffer
memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len);
memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen);
RsTlvBinaryData msgData(0);
RsTlvBinaryData msgData(0);
msgData.setBinData(allMsgData, allMsgDataLen);
msgData.setBinData(allMsgData, allMsgDataLen);
// create signatures
ret_val = createMsgSignatures(meta.signSet, msgData, meta, *grpMeta);
// create signatures
ret_val = createMsgSignatures(meta.signSet, msgData, meta, *grpMeta);
// get hash of msg data to create msg id
pqihash hash;
hash.addData(allMsgData, allMsgDataLen);
hash.Complete(msg->msgId);
// get hash of msg data to create msg id
pqihash hash;
hash.addData(allMsgData, allMsgDataLen);
hash.Complete(msg->msgId);
// assign msg id to msg meta
msg->metaData->mMsgId = msg->msgId;
// assign msg id to msg meta
msg->metaData->mMsgId = msg->msgId;
delete[] metaData;
delete[] allMsgData;
delete[] metaData;
delete[] allMsgData;
delete grpMeta;
delete grpMeta;
}
if(ret_val == SIGN_FAIL)
@ -752,6 +742,79 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, RsTlvSecu
}
int RsGenExchange::validateGrp(RsNxsGrp* grp, RsTlvSecurityKeySet& grpKeySet)
{
bool needIdentitySign = false, idValidate = false;
RsGxsGrpMetaData& metaData = *(grp->metaData);
int id_ret;
uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN;
PrivacyBitPos pos = GRP_OPTION_BITS;
// Check required permissions, and allow them to sign it - if they want too - as well!
if (!(metaData.mAuthorId.empty()) || checkAuthenFlag(pos, author_flag))
{
needIdentitySign = true;
std::cerr << "Needs Identity sign! (Service Flags)";
std::cerr << std::endl;
}
if(needIdentitySign)
{
if(mGixs)
{
bool haveKey = mGixs->haveKey(metaData.mAuthorId);
if(haveKey)
{
RsTlvSecurityKey authorKey;
bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) == 1;
if (auth_key_fetched)
{
RsTlvKeySignature sign = metaData.signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_IDENTITY];
idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey);
}
else
{
std::cerr << "RsGenExchange::validateGrp()";
std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation";
std::cerr << std::endl;
idValidate = false;
}
}else
{
std::list<std::string> peers;
mGixs->requestKey(metaData.mAuthorId, peers);
return VALIDATE_FAIL_TRY_LATER;
}
}
else
{
#ifdef GEN_EXHANGE_DEBUG
std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl;
#endif
idValidate = false;
}
}
else
{
idValidate = true;
}
if(idValidate)
return VALIDATE_SUCCESS;
else
return VALIDATE_FAIL;
}
bool RsGenExchange::checkAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const
{
std::cerr << "RsGenExchange::checkMsgAuthenFlag(pos: " << pos << " flag: ";
@ -1130,19 +1193,19 @@ bool RsGenExchange::setAuthenPolicyFlag(const uint8_t &msgFlag, uint32_t& authen
switch(pos)
{
case PUBLIC_GRP_BITS:
//authenFlag &= ~PUB_GRP_MASK;
authenFlag &= ~PUB_GRP_MASK;
authenFlag |= temp;
break;
case RESTRICTED_GRP_BITS:
//authenFlag &= ~RESTR_GRP_MASK;
authenFlag &= ~RESTR_GRP_MASK;
authenFlag |= (temp << RESTR_GRP_OFFSET);
break;
case PRIVATE_GRP_BITS:
//authenFlag &= ~PRIV_GRP_MASK;
authenFlag &= ~PRIV_GRP_MASK;
authenFlag |= (temp << PRIV_GRP_OFFSET);
break;
case GRP_OPTION_BITS:
//authenFlag &= ~GRP_OPTIONS_MASK;
authenFlag &= ~GRP_OPTIONS_MASK;
authenFlag |= (temp << GRP_OPTIONS_OFFSET);
break;
default:
@ -1160,7 +1223,23 @@ void RsGenExchange::notifyNewGroups(std::vector<RsNxsGrp *> &groups)
// store these for tick() to pick them up
for(; vit != groups.end(); vit++)
mReceivedGrps.push_back(*vit);
{
RsNxsGrp* grp = *vit;
NxsGrpPendValidVect::iterator received = std::find(mReceivedGrps.begin(),
mReceivedGrps.end(), grp->grpId);
// drop group if you already have them
// TODO: move this to nxs layer to save bandwidth
if(received == mReceivedGrps.end())
{
GxsPendingSignItem<RsNxsGrp*, RsGxsGroupId> gpsi(grp, grp->grpId);
mReceivedGrps.push_back(gpsi);
}
else
{
delete grp;
}
}
}
@ -1674,11 +1753,13 @@ void RsGenExchange::publishGrps()
ServiceCreate_Return ret = service_CreateGroup(grpItem, privatekeySet);
uint32_t size = mSerialiser->size(grpItem);
char gData[size];
bool serialOk = mSerialiser->serialise(grpItem, gData, &size);
char *gData = new char[size];
bool serialOk = mSerialiser->serialise(grpItem, gData, &size);
grp->grp.setBinData(gData, size);
delete[] gData;
if(serialOk)
{
grp->metaData = new RsGxsGrpMetaData();
@ -1690,11 +1771,23 @@ void RsGenExchange::publishGrps()
if(create == CREATE_SUCCESS)
{
if(mDataStore->validSize(grp))
uint32_t mdSize = grp->metaData->serial_size();
char* metaData = new char[mdSize];
serialOk = grp->metaData->serialise(metaData, mdSize);
grp->meta.setBinData(metaData, mdSize);
delete[] metaData;
// place back private keys for publisher
grp->metaData->keys = privatekeySet;
if(mDataStore->validSize(grp) && serialOk)
{
RsGxsGroupId grpId = grp->grpId;
mDataAccess->addGroupData(grp);
std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" << std::endl;
// add to published to allow acknowledgement
@ -1982,7 +2075,7 @@ void RsGenExchange::processRecvdMessages()
getMsgIdPair(*msg));
if(failed_entry != mMsgPendingValidate.end()) mMsgPendingValidate.erase(failed_entry);
delete msg;
delete msg;
}
@ -2024,37 +2117,69 @@ void RsGenExchange::processRecvdMessages()
mReceivedMsgs.clear();
}
void RsGenExchange::processRecvdGroups()
{
RsStackMutex stack(mGenMtx);
std::vector<RsNxsGrp*>::iterator vit = mReceivedGrps.begin();
NxsGrpPendValidVect::iterator vit = mReceivedGrps.begin();
std::map<RsNxsGrp*, RsGxsGrpMetaData*> grps;
std::list<RsGxsGroupId> grpIds;
for(; vit != mReceivedGrps.end(); vit++)
while( vit != mReceivedGrps.end())
{
RsNxsGrp* grp = *vit;
GxsPendingSignItem<RsNxsGrp*, RsGxsGroupId>& gpsi = *vit;
RsNxsGrp* grp = gpsi.mItem;
RsGxsGrpMetaData* meta = new RsGxsGrpMetaData();
bool ok = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len);
bool deserialOk = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len);
bool erase = true;
if(ok)
if(deserialOk)
{
meta->mGroupStatus = GXS_SERV::GXS_GRP_STATUS_UNPROCESSED | GXS_SERV::GXS_GRP_STATUS_UNREAD;
grps.insert(std::make_pair(grp, meta));
grpIds.push_back(grp->grpId);
grp->metaData = meta;
uint8_t ret = validateGrp(grp, meta->keys);
if(ret == VALIDATE_SUCCESS)
{
meta->mGroupStatus = GXS_SERV::GXS_GRP_STATUS_UNPROCESSED | GXS_SERV::GXS_GRP_STATUS_UNREAD;
grps.insert(std::make_pair(grp, meta));
grpIds.push_back(grp->grpId);
erase = true;
}
else if(ret == VALIDATE_FAIL)
{
#ifdef GXS_GENX_DEBUG
std::cerr << "failed to deserialise incoming meta, grpId: "
<< grp->grpId << std::endl;
#endif
delete grp;
erase = true;
}
else if(ret == VALIDATE_FAIL_TRY_LATER)
{
if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS)
{
delete grp;
erase = true;
}
else
{
erase = false;
}
}
}
else
{
#ifdef GXS_GENX_DEBUG
std::cerr << "failed to deserialise incoming meta, grpId: "
<< grp->grpId << std::endl;
#endif
delete grp;
delete meta;
delete grp;
erase = true;
}
if(erase)
vit = mReceivedGrps.erase(vit);
else
vit++;
}
if(!grpIds.empty())
@ -2064,8 +2189,4 @@ void RsGenExchange::processRecvdGroups()
mNotifications.push_back(c);
mDataStore->storeGroup(grps);
}
mReceivedGrps.clear();
}

View File

@ -550,7 +550,6 @@ private:
/*!
* This completes the creation of an instance on RsNxsGrp
* by assigning it a groupId and signature via SHA1 and EVP_sign respectively \n
* Meta is serialised and stored in group at this point also
* @param grp Nxs group to create
* @return CREATE_SUCCESS for success, CREATE_FAIL for fail,
* CREATE_FAIL_TRY_LATER for Id sign key not avail (but requested)
@ -606,15 +605,24 @@ private:
void generateGroupKeys(RsTlvSecurityKeySet& privatekeySet, RsTlvSecurityKeySet& publickeySet, bool genPublishKeys);
/*!
* Attempts to validate msg
* Attempts to validate msg signatures
* @param msg message to be validated
* @param grpFlag the flag for the group the message belongs to
* @param grpKeySet
* @param grpKeySet the key set user has for the message's group
* @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail,
* VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested)
*/
int validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, RsTlvSecurityKeySet& grpKeySet);
/*!
* Attempts to validate group signatures
* @param grp group to be validated
* @param grpKeySet the keys set user has for the group
* @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail,
* VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested)
*/
int validateGrp(RsNxsGrp* grp, RsTlvSecurityKeySet& grpKeySet);
/*!
* Checks flag against a given privacy bit block
* @param pos Determines 8 bit wide privacy block to check
@ -637,7 +645,9 @@ private:
RsGixs* mGixs;
std::vector<RsNxsMsg*> mReceivedMsgs;
std::vector<RsNxsGrp*> mReceivedGrps;
typedef std::vector<GxsPendingSignItem<RsNxsGrp*, RsGxsGroupId> > NxsGrpPendValidVect;
NxsGrpPendValidVect mReceivedGrps;
std::map<uint32_t, RsGxsGrpItem*> mGrpsToPublish;
std::map<uint32_t, RsGxsMsgItem*> mMsgsToPublish;
@ -662,10 +672,6 @@ private:
std::vector<GxsPendingSignItem<RsNxsMsg*, RsGxsGrpMsgIdPair> > mMsgPendingValidate;
typedef std::vector<GxsPendingSignItem<RsNxsMsg*, RsGxsGrpMsgIdPair> > NxsMsgPendingVect;
std::vector<GxsPendingSignItem<RsGxsGrpItem*, RsGxsGroupId> >
mGrpPendingValidation;
std::vector<GxsPendingSignItem<RsGxsGrpItem*, uint32_t> > mGrpPendingSign;
typedef std::vector<GxsPendingSignItem<RsGxsGrpItem*, uint32_t> > NxsGrpSignPendVect;

View File

@ -58,38 +58,24 @@ p3GxsChannels::p3GxsChannels(RsGeneralDataService *gds, RsNetworkExchangeService
mGenActive = false;
mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXSV1_TYPE_CHANNELS);
//#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET
#ifndef GXS_DEV_TESTNET // NO RESET, OR DUMMYDATA for TESTNET
RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD);
//#endif
#endif
}
uint32_t p3GxsChannels::channelsAuthenPolicy()
{
uint32_t policy = 0;
uint32_t flag = 0;
flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN;
flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN;
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN;
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN;
//flag |= GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
@ -98,8 +84,6 @@ uint32_t p3GxsChannels::channelsAuthenPolicy()
void p3GxsChannels::notifyChanges(std::vector<RsGxsNotify *> &changes)
{
RsGxsIfaceHelper::receiveChanges(changes);

View File

@ -69,7 +69,9 @@ uint32_t p3Wiki::wikiAuthenPolicy()
uint32_t policy = 0;
uint8_t flag = 0;
flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN;
// Edits generally need an authors signature.
flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
@ -85,12 +87,6 @@ uint32_t p3Wiki::wikiAuthenPolicy()
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
// Edits generally need an authors signature.
flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN;
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS);
RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS);
//flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN;
//RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS);