diff --git a/libretroshare/src/rsiface/rschannels.h b/libretroshare/src/rsiface/rschannels.h index 9253f0066..971b80d09 100644 --- a/libretroshare/src/rsiface/rschannels.h +++ b/libretroshare/src/rsiface/rschannels.h @@ -186,6 +186,13 @@ virtual bool channelExtraFileRemove(std::string hash, std::string chId) = 0; */ virtual bool channelRestoreKeys(std::string chId) = 0; +/*! + * shares keys with peers + *@param chId the channel for which private publish keys will be shared + *@param peers peers in this list will be sent keys + * + */ +virtual bool channelShareKeys(std::string chId, std::list& peers) = 0; /****************************************/ }; diff --git a/libretroshare/src/serialiser/rsserviceids.h b/libretroshare/src/serialiser/rsserviceids.h index d9fe7bec3..60e933f11 100644 --- a/libretroshare/src/serialiser/rsserviceids.h +++ b/libretroshare/src/serialiser/rsserviceids.h @@ -87,6 +87,7 @@ const uint16_t RS_SERVICE_TYPE_PHOTO = 0xf040; const uint16_t RS_SERVICE_TYPE_DISTRIB = 0xf110; const uint16_t RS_SERVICE_TYPE_FORUM = 0xf120; const uint16_t RS_SERVICE_TYPE_CHANNEL = 0xf130; +const uint16_t RS_SERVICE_TYPE_CHANNEL_SOCKET = 0xf140; /* Games/External Apps - Service Only */ const uint16_t RS_SERVICE_TYPE_GAME_LAUNCHER = 0xf200; diff --git a/libretroshare/src/services/p3channels.cc b/libretroshare/src/services/p3channels.cc index af7a5c558..df6531729 100644 --- a/libretroshare/src/services/p3channels.cc +++ b/libretroshare/src/services/p3channels.cc @@ -437,6 +437,16 @@ bool p3Channels::channelSubscribe(std::string cId, bool subscribe) return subscribeToGroup(cId, subscribe); } +bool p3Channels::channelShareKeys(std::string chId, std::list& peers){ + +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::channelShareKeys() " << chId << std::endl; +#endif + + return sharePubKey(chId, peers); + +} + /***************************************************************************************/ /****************** Event Feedback (Overloaded form p3distrib) *************************/ diff --git a/libretroshare/src/services/p3channels.h b/libretroshare/src/services/p3channels.h index 5af285a01..351f2efd3 100644 --- a/libretroshare/src/services/p3channels.h +++ b/libretroshare/src/services/p3channels.h @@ -72,7 +72,7 @@ virtual bool channelSubscribe(std::string cId, bool subscribe); virtual bool channelExtraFileHash(std::string path, std::string chId, FileInfo& fInfo); virtual bool channelExtraFileRemove(std::string hash, std::string chId); virtual bool channelRestoreKeys(std::string chId); - +virtual bool channelShareKeys(std::string chId, std::list& peers); /***************************************************************************************/ /****************** Event Feedback (Overloaded form p3distrib) *************************/ /***************************************************************************************/ diff --git a/libretroshare/src/services/p3distrib.cc b/libretroshare/src/services/p3distrib.cc index d3bad4178..933ce4740 100644 --- a/libretroshare/src/services/p3distrib.cc +++ b/libretroshare/src/services/p3distrib.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "rsiface/rsdistrib.h" #include "services/p3distrib.h" @@ -56,12 +57,12 @@ p3GroupDistrib::p3GroupDistrib(uint16_t subtype, :CacheSource(subtype, true, cs, sourcedir), CacheStore(subtype, true, cs, cft, storedir), - p3Config(configId), nullService(subtype), + p3Config(configId), p3Service(RS_SERVICE_TYPE_DISTRIB), mStorePeriod(storePeriod), mPubPeriod(pubPeriod), mLastPublishTime(0), mMaxCacheSubId(1), - mKeyBackUpDir(keyBackUpDir), BACKUP_KEY_FILE("key.log") + mKeyBackUpDir(keyBackUpDir), BACKUP_KEY_FILE("key.log"), mLastKeyPublishTime(0) { /* not much yet */ time_t now = time(NULL); @@ -70,6 +71,8 @@ p3GroupDistrib::p3GroupDistrib(uint16_t subtype, mGroupsRepublish = true; mOwnId = AuthSSL::getAuthSSL()->OwnId(); + + addSerialType(new RsDistribSerialiser()); return; } @@ -88,6 +91,7 @@ int p3GroupDistrib::tick() { RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/ toPublish = (mPendingPublish.size() > 0) && (now > mPubPeriod + mLastPublishTime); + } if (toPublish) @@ -113,6 +117,32 @@ int p3GroupDistrib::tick() mGroupsRepublish = false; } + { + RsStackMutex stack(distribMtx); + toPublish = (mPendingPubKeyRecipients.size() > 0) && (now > 5 + mLastKeyPublishTime); + } + + if(toPublish){ + RsStackMutex stack(distribMtx); + locked_sharePubKey(); + } + + bool toReceive = receivedItems(); + + if(toReceive){ + RsStackMutex stack(distribMtx); + locked_receivePubKeys(); + } + + + { + RsStackMutex stack(distribMtx); + + if(mPubKeysRecvd){ + locked_loadRecvdPubKeys(); + } + } + return 0; } @@ -1767,13 +1797,17 @@ bool p3GroupDistrib::restoreGrpKeys(std::string grpId){ } } - gi->flags |= RS_DISTRIB_SUBSCRIBED; - locked_notifyGroupChanged(*gi, GRP_SUBSCRIBED); - IndicateConfigChanged(); - mGroupsRepublish = true; + ok &= itemAttempted; + if(ok){ + gi->flags |= RS_DISTRIB_SUBSCRIBED; + locked_notifyGroupChanged(*gi, GRP_SUBSCRIBED); + IndicateConfigChanged(); + mGroupsRepublish = true; + } + #ifdef DISTRIB_DEBUG if(!ok){ std::cerr << "p3Distrib::restoreGrpKeys() Failed to restore private keys for grp " @@ -1785,6 +1819,201 @@ bool p3GroupDistrib::restoreGrpKeys(std::string grpId){ return ok; } + + +bool p3GroupDistrib::sharePubKey(std::string grpId, std::list& peers){ + + RsStackMutex stack(distribMtx); + + // first check that group actually exists + if(mGroups.find(grpId) == mGroups.end()){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::sharePubKey(): Group does not exist" << std::endl; +#endif + return false; + } + + // add to pending list to be sent + mPendingPubKeyRecipients[grpId] = peers; + + return true; +} + +void p3GroupDistrib::locked_sharePubKey(){ + + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_sharePubKey() " << std::endl; +#endif + + std::map >::iterator mit; + std::list::iterator lit; + + // get list of peers that are online + std::list peersOnline; + rsPeers->getOnlineList(peersOnline); + std::list toDelete; + + /* send public key to peers online */ + + for(mit = mPendingPubKeyRecipients.begin(); mit != mPendingPubKeyRecipients.end(); mit++){ + + GroupInfo *gi = locked_getGroupInfo(mit->first); + + if(gi == NULL){ + toDelete.push_back(mit->first); // grp does not exist, stop attempting to share key for dead group + continue; + } + + // find full public key, and send to given peers + std::map::iterator kit; + for(kit = gi->publishKeys.begin(); + kit != gi->publishKeys.end(); kit++) + { + if (kit->second.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_sharePubKey() Sharing Key: " << kit->first; + std::cerr << std::endl; +#endif + + // send keys to peers who are online + for(lit = mit->second.begin() ; lit != mit->second.end(); lit++){ + + if(std::find(peersOnline.begin(), peersOnline.end(), *lit) != peersOnline.end()){ + + /* create Key for sharing */ + RsDistribGrpKey* pubKey = new RsDistribGrpKey(); + + + pubKey->clear(); + pubKey->grpId = mit->first; + + RSA *rsa_priv = EVP_PKEY_get1_RSA(kit->second.key); + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = kit->second.type; + pubKey->key.startTS = kit->second.startTS; + pubKey->key.endTS = kit->second.endTS; + pubKey->PeerId(*lit); + std::cout << *lit << std::endl; + sendItem(pubKey); + + // remove peer from list + lit = mit->second.erase(lit); // no need to send to peer anymore + lit--; + } + } + } + } + + // if given peers have all received key(s) then stop sending for group + if(mit->second.empty()) + toDelete.push_back(mit->first); + } + + // delete pending peer list which are done with + for(lit = toDelete.begin(); lit != toDelete.end(); lit++) + mPendingPubKeyRecipients.erase(*lit); + + mLastKeyPublishTime = time(NULL); + + return; +} + + +void p3GroupDistrib::locked_receivePubKeys(){ + + + RsItem* item; + + while(NULL != (item = recvItem())){ + + RsDistribGrpKey* key_item = dynamic_cast(item); + + if(key_item != NULL){ + + +#ifdef STATUS_DEBUG + std::cerr << "p3GroupDistrib::locked_receiveKeys()" << std::endl; + std::cerr << "PeerId : " << key_item->PeerId() << std::endl; + std::cerr << "GrpId: " << key_item->grpId << std::endl; + std::cerr << "Got key Item" << std::endl; +#endif + if(key_item->key.keyFlags == RSTLV_KEY_TYPE_FULL){ + mRecvdPubKeys[key_item->grpId] = key_item; + } + else{ + std::cerr << "p3GroupDistrib::locked_receiveKeys():" << "Not full public key" + << "Deleting item"<< std::endl; + delete key_item; + } + }else{ + delete item; + } + } + + if(mRecvdPubKeys.size() != 0){ + mPubKeysRecvd = true; + } + + return; +} + +void p3GroupDistrib::locked_loadRecvdPubKeys(){ + + std::map::iterator mit; + GroupInfo *gi; + std::list toDelete; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_loadRecvdPubKeys() " << std::endl; +#endif + + bool ok = false; + + // load received keys + for(mit = mRecvdPubKeys.begin(); mit != mRecvdPubKeys.end(); mit++ ){ + + gi = locked_getGroupInfo(mit->second->grpId); + + if(gi != NULL){ + + + + if(locked_updateGroupPublishKey(*gi, mit->second)){ + toDelete.push_back(mit->first); + gi->flags |= RS_DISTRIB_SUBSCRIBED; + locked_notifyGroupChanged(*gi, GRP_SUBSCRIBED); + ok |= true; + } + else + std::cerr << "p3GroupDistrib::locked_loadRecvdPubKeys(): Failed to load" << std::endl; + + }else{ + + std::cerr << "p3GroupDistrib::locked_loadRecvdPubKeys(): group does not exist" << std::endl; + } + + } + + if(mRecvdPubKeys.size() == 0) + mPubKeysRecvd = false; + + + if(ok) + IndicateConfigChanged(); + + std::list::iterator lit; + + // delete keys that have been loaded to groups + for(lit = toDelete.begin(); lit != toDelete.end(); lit++) + mRecvdPubKeys.erase(*lit); + + return; +} + std::string p3GroupDistrib::publishMsg(RsDistribMsg *msg, bool personalSign) { diff --git a/libretroshare/src/services/p3distrib.h b/libretroshare/src/services/p3distrib.h index b6defdbb8..d0c4c6ac5 100644 --- a/libretroshare/src/services/p3distrib.h +++ b/libretroshare/src/services/p3distrib.h @@ -236,7 +236,7 @@ const uint32_t GRP_UNSUBSCRIBED = 0x0006; * * Create a Signing structure for Messages in general. */ -class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, public nullService +class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, public p3Service { public: @@ -256,12 +256,6 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu virtual bool loadLocalCache(const CacheData &data); /// overloaded from Cache Source virtual int loadCache(const CacheData &data); /// overloaded from Cache Store -/** - * @param grpId the grpId id for which backup keys should be restored - * @return false if failed and vice versa - */ -virtual bool restoreGrpKeys(std::string grpId); /// restores a group keys from backup - private: /* top level load */ int loadAnyCache(const CacheData &data, bool local); @@ -270,6 +264,7 @@ int loadAnyCache(const CacheData &data, bool local); void loadFileGroups(std::string filename, std::string src, bool local); void loadFileMsgs(std::string filename, uint16_t cacheSubId, std::string src, uint32_t ts, bool local); bool backUpKeys(const std::list &keysToBackUp, std::string grpId); +void locked_sharePubKey(); protected: /* load cache msgs */ @@ -368,6 +363,28 @@ void clear_local_caches(time_t now); void locked_publishPendingMsgs(); uint16_t locked_determineCacheSubId(); +/** + * @param grpId the grpId id for which backup keys should be restored + * @return false if failed and vice versa + */ +virtual bool restoreGrpKeys(std::string grpId); /// restores a group keys from backup + +/** + * @param grpId the group for which to share public keys + * @param peers The peers to which public keys should be sent + */ +virtual bool sharePubKey(std::string grpId, std::list& peers); + +/** + * attempts to receive publication keys + */ +virtual void locked_receivePubKeys(); + +/** + * this load received pub keys, useful in the case that publish keys have been received + * but group info hasn't + */ +virtual void locked_loadRecvdPubKeys(); /***************************************************************************************/ @@ -449,11 +466,17 @@ bool groupsChanged(std::list &groupIds); bool mGroupsChanged; bool mGroupsRepublish; + bool mPubKeysRecvd; std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ std::string mKeyBackUpDir; const std::string BACKUP_KEY_FILE; + std::map mRecvdPubKeys; /// full publishing keys received from users + std::map > mPendingPubKeyRecipients; /// peers to receive publics key for a given grp + time_t mLastKeyPublishTime; + + };