diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc index 62078f7ae..ea820e1b4 100644 --- a/libretroshare/src/gxs/gxssecurity.cc +++ b/libretroshare/src/gxs/gxssecurity.cc @@ -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) diff --git a/libretroshare/src/gxs/gxssecurity.h b/libretroshare/src/gxs/gxssecurity.h index 889006017..2bccf542f 100644 --- a/libretroshare/src/gxs/gxssecurity.h +++ b/libretroshare/src/gxs/gxssecurity.h @@ -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 diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 2c47327b7..cbd3fa818 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -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 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 &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 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::iterator vit = mReceivedGrps.begin(); + NxsGrpPendValidVect::iterator vit = mReceivedGrps.begin(); std::map grps; std::list grpIds; - for(; vit != mReceivedGrps.end(); vit++) + while( vit != mReceivedGrps.end()) { - RsNxsGrp* grp = *vit; + GxsPendingSignItem& 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(); - } - diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index b4cffc100..be7c0820a 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -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 mReceivedMsgs; - std::vector mReceivedGrps; + + typedef std::vector > NxsGrpPendValidVect; + NxsGrpPendValidVect mReceivedGrps; std::map mGrpsToPublish; std::map mMsgsToPublish; @@ -662,10 +672,6 @@ private: std::vector > mMsgPendingValidate; typedef std::vector > NxsMsgPendingVect; - - std::vector > - mGrpPendingValidation; - std::vector > mGrpPendingSign; typedef std::vector > NxsGrpSignPendVect; diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index 3c66ed085..ccc364ea2 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -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 &changes) { RsGxsIfaceHelper::receiveChanges(changes); diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc index 7772ba736..7df0b7cd0 100644 --- a/libretroshare/src/services/p3wiki.cc +++ b/libretroshare/src/services/p3wiki.cc @@ -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);