From 24a3fb58d4b0ccd9f8c0b878186fac36584456d8 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 9 Sep 2012 13:59:21 +0000 Subject: [PATCH] Improved plugin system: - the user is asked at start wether to load or deny unregistered plugins, but can make it mind later in config->plugins - added API and SVN numbers into required external plugin symbols - user-defined plugin rules are dropped when a plugin changes (hash changes) or when the main executable changes. - added new status flags (Plugin denied, missing API/SVN numbers) - modified saveList()/loadList() to allow saving a list of rejected plugins as well. - added methods in notifyBase and inherited classes to ask for plugin confirmation. - adapted VOIP plugin to follow these new rules (API+SVN numbers). Other plugins should be adapted as well by addign the missing symbols (RETROSHARE_PLUGIN_api and RETROSHARE_PLUGIN_revision). git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5529 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/plugins/pluginmanager.cc | 221 ++++++++++++------ libretroshare/src/plugins/pluginmanager.h | 41 +++- libretroshare/src/retroshare/rsiface.h | 1 + libretroshare/src/retroshare/rsplugin.h | 10 +- libretroshare/src/rsserver/rsinit.cc | 121 +++++----- libretroshare/src/serialiser/rstlvtypes.cc | 2 +- libretroshare/src/serialiser/rstlvtypes.h | 1 + plugins/VOIP/VOIPPlugin.cpp | 6 + retroshare-gui/src/gui/notifyqt.cpp | 27 +++ retroshare-gui/src/gui/notifyqt.h | 1 + .../src/gui/settings/PluginsPage.cpp | 30 ++- retroshare-nogui/src/notifytxt.cc | 19 +- retroshare-nogui/src/notifytxt.h | 1 + 13 files changed, 334 insertions(+), 147 deletions(-) diff --git a/libretroshare/src/plugins/pluginmanager.cc b/libretroshare/src/plugins/pluginmanager.cc index 9af0f6cb0..7a62b99b1 100644 --- a/libretroshare/src/plugins/pluginmanager.cc +++ b/libretroshare/src/plugins/pluginmanager.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -23,8 +24,10 @@ #include #endif -std::string RsPluginManager::_plugin_entry_symbol ; -std::string RsPluginManager::_plugin_revision_symbol ; +std::string RsPluginManager::_plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; +std::string RsPluginManager::_plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ; +std::string RsPluginManager::_plugin_API_symbol = "RETROSHARE_PLUGIN_api" ; + std::string RsPluginManager::_local_cache_dir ; std::string RsPluginManager::_remote_cache_dir ; std::vector RsPluginManager::_plugin_directories ; @@ -35,7 +38,8 @@ p3LinkMgr *RsPluginManager::_linkmgr = NULL ; typedef RsPlugin *(*RetroSharePluginEntry)(void) ; RsPluginHandler *rsPlugins ; -RsPluginManager::RsPluginManager() : p3Config(CONFIG_TYPE_PLUGINS) +RsPluginManager::RsPluginManager(const std::string& hash) + : p3Config(CONFIG_TYPE_PLUGINS),_current_executable_hash(hash) { _allow_all_plugins = false ; } @@ -133,7 +137,14 @@ void RsPluginManager::loadPlugins(const std::vector& plugin_directo dirIt.closedir(); } - std::cerr << "Loaded a total of " << _plugins.size() << " plugins." << std::endl; + std::cerr << "Examined a total of " << _plugins.size() << " plugins." << std::endl; + + // Save list of accepted hashes and reference value + + // Calling IndicateConfigChanged() at this point is not sufficient because the config flags are cleared + // at start of the p3config thread, and this thread has not yet started. + // + saveConfiguration(); } void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,std::string& hash,uint32_t& svn_revision,std::string& error_string) const @@ -204,79 +215,110 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name) std::cerr << " -> hashing." << std::endl; uint64_t size ; + // Stage 1 - get information related to file (hash, name, ...) + // if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size)) { std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl; return false; } - // This file can be loaded. Insert an entry into the list of detected plugins. - // _plugins.push_back(pf) ; PluginInfo& pinfo(_plugins.back()) ; std::cerr << " -> hash = " << pinfo.file_hash << std::endl; + if(!_allow_all_plugins) + { + if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) + if(!rsicontrol->getNotify().askForPluginConfirmation(pinfo.file_name,pinfo.file_hash)) + _rejected_hashes.insert(pinfo.file_hash) ; // accepted hashes are treated at the end, for security. - // The following choice is conservative by forcing RS to resolve all dependencies at - // the time of loading the plugin. - - int link_mode = RTLD_NOW | RTLD_GLOBAL ; - - void *handle = dlopen(plugin_name.c_str(),link_mode) ; - - if(handle == NULL) + if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() ) { - const char *val = dlerror() ; - std::cerr << " Cannot open plugin: " << val << std::endl ; - pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ; - pinfo.info_string = val ; + pinfo.status = PLUGIN_STATUS_REJECTED_HASH ; + std::cerr << " -> hash rejected. Giving up plugin. " << std::endl; return false ; } + } + else + std::cerr << " -> ALLOW_ALL_PLUGINS Enabled => plugin loaded by default." << std::endl; - void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; - pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ; + std::cerr << " -> hash authorized. Loading plugin. " << std::endl; - std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl; - std::cerr << " -> retroshare svn number: " << SVN_REVISION_NUMBER << std::endl; + // Stage 2 - open with dlopen, and get some basic info. + // - if( (pinfo.svn_revision == 0 || pinfo.svn_revision != SVN_REVISION_NUMBER) && (!_allow_all_plugins) && _accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end()) - { - std::cerr << " -> revision numbers do not match, and hash is not in white list. Plugin is rejected. Go to config->plugins to authorise this plugin." << std::endl; - pinfo.status = PLUGIN_STATUS_UNKNOWN_HASH ; - pinfo.info_string = "" ; - return false ; - } + // The following choice is conservative by forcing RS to resolve all dependencies at + // the time of loading the plugin. - // Now look for the plugin class symbol. - // - void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ; + int link_mode = RTLD_NOW | RTLD_GLOBAL ; - if(pfe == NULL) - { - std::cerr << dlerror() << std::endl ; - pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ; - pinfo.info_string = "Symbol " + _plugin_entry_symbol + " is missing." ; - return false ; - } - std::cerr << " Added function entry for symbol " << _plugin_entry_symbol << std::endl ; + void *handle = dlopen(plugin_name.c_str(),link_mode) ; - RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ; + if(handle == NULL) + { + const char *val = dlerror() ; + std::cerr << " Cannot open plugin: " << val << std::endl ; + pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ; + pinfo.info_string = val ; + return false ; + } - if(p == NULL) - { - std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl; - pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ; - pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ; - return false ; - } + void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ; + void *papi = dlsym(handle,_plugin_API_symbol.c_str()) ; pinfo.API_version = (papi == NULL) ? 0 : (*(uint32_t *)papi) ; - pinfo.status = PLUGIN_STATUS_LOADED ; - pinfo.plugin = p ; - p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries + std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl; + std::cerr << " plugin API number : " << (void*)pinfo.API_version << std::endl; + std::cerr << " retroshare svn number: " << SVN_REVISION_NUMBER << std::endl; + + // Check that the plugin provides a svn revision number and a API number + // + if(pinfo.API_version == 0) + { + std::cerr << " -> No API version number." << std::endl; + pinfo.status = PLUGIN_STATUS_MISSING_API ; pinfo.info_string = "" ; + return false ; + } + if(pinfo.svn_revision == 0) + { + std::cerr << " -> No svn revision number." << std::endl; + pinfo.status = PLUGIN_STATUS_MISSING_SVN ; + pinfo.info_string = "" ; + return false ; + } - return true; + // Now look for the plugin class symbol. + // + void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ; + + if(pfe == NULL) + { + std::cerr << dlerror() << std::endl ; + pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ; + pinfo.info_string = _plugin_entry_symbol ; + return false ; + } + std::cerr << " -> Added function entry for symbol " << _plugin_entry_symbol << std::endl ; + + RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ; + + if(p == NULL) + { + std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl; + pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ; + pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ; + return false ; + } + + pinfo.status = PLUGIN_STATUS_LOADED ; + pinfo.plugin = p ; + p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries + pinfo.info_string = "" ; + + _accepted_hashes.insert(pinfo.file_hash) ; // do it now, to avoid putting in list a plugin that might have crashed during the load. + return true; } p3LinkMgr *RsPluginManager::getLinkMgr() const @@ -355,56 +397,91 @@ void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr) bool RsPluginManager::loadList(std::list& list) { - _accepted_hashes.clear() ; + std::set accepted_hash_candidates ; + std::set rejected_hash_candidates ; std::cerr << "RsPluginManager::loadList(): " << std::endl; + std::string reference_executable_hash = "" ; std::list::iterator it; for(it = list.begin(); it != list.end(); it++) { - RsPluginHashSetItem *vitem = dynamic_cast(*it); - - if(vitem) - for(std::list::const_iterator it(vitem->hashes.ids.begin());it!=vitem->hashes.ids.end();++it) - { - _accepted_hashes.insert(*it) ; - std::cerr << " loaded hash " << *it << std::endl; - } - RsConfigKeyValueSet *witem = dynamic_cast(*it) ; if(witem) - { for(std::list::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit) + { if((*kit).key == "ALLOW_ALL_PLUGINS") { - std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ; _allow_all_plugins = (kit->value == "YES"); + + if(_allow_all_plugins) + std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ; } - } + else if((*kit).key == "REFERENCE_EXECUTABLE_HASH") + { + reference_executable_hash = kit->value ; + std::cerr << " Reference executable hash: " << kit->value << std::endl; + } + else if((*kit).key == "ACCEPTED") + { + accepted_hash_candidates.insert((*kit).value) ; + std::cerr << " Accepted hash: " << (*kit).value << std::endl; + } + else if((*kit).key == "REJECTED") + { + rejected_hash_candidates.insert((*kit).value) ; + std::cerr << " Rejected hash: " << (*kit).value << std::endl; + } + } delete (*it); } + + if(reference_executable_hash == _current_executable_hash) + { + std::cerr << "(II) Executable hash matches. Updating the list of accepted/rejected plugins." << std::endl; + + _accepted_hashes = accepted_hash_candidates ; + _rejected_hashes = rejected_hash_candidates ; + } + else + std::cerr << "(WW) Executable hashes do not match. Executable hash has changed. Discarding the list of accepted/rejected plugins." << std::endl; + return true; } bool RsPluginManager::saveList(bool& cleanup, std::list& list) { + std::cerr << "PluginManager: saving list." << std::endl; cleanup = true ; - RsPluginHashSetItem *vitem = new RsPluginHashSetItem() ; - - for(std::set::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it) - vitem->hashes.ids.push_back(*it) ; - - list.push_back(vitem) ; - RsConfigKeyValueSet *witem = new RsConfigKeyValueSet ; RsTlvKeyValue kv; kv.key = "ALLOW_ALL_PLUGINS" ; kv.value = _allow_all_plugins?"YES":"NO" ; witem->tlvkvs.pairs.push_back(kv) ; + kv.key = "REFERENCE_EXECUTABLE_HASH" ; + kv.value = _current_executable_hash ; + witem->tlvkvs.pairs.push_back(kv) ; + + std::cerr << " Saving current executable hash: " << kv.value << std::endl; + + // now push accepted and rejected hashes. + + for(std::set::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it) + { + witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "ACCEPTED", *it ) ) ; + std::cerr << " " << *it << " : " << "ACCEPTED" << std::endl; + } + + for(std::set::const_iterator it(_rejected_hashes.begin());it!=_rejected_hashes.end();++it) + { + witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "REJECTED", *it ) ) ; + std::cerr << " " << *it << " : " << "REJECTED" << std::endl; + } + list.push_back(witem) ; return true; diff --git a/libretroshare/src/plugins/pluginmanager.h b/libretroshare/src/plugins/pluginmanager.h index d1bf131de..aeea3c814 100644 --- a/libretroshare/src/plugins/pluginmanager.h +++ b/libretroshare/src/plugins/pluginmanager.h @@ -13,18 +13,32 @@ class p3LinkMgr ; class PluginInfo { public: + // Main object provided by the plugin. NULL is the plugin could not be loaded. + // RsPlugin *plugin ; - std::string info_string ; + + // Information related to the file. Do not require the plugin to be loaded nor the DSO to be openned. + // std::string file_hash ; std::string file_name ; - uint32_t svn_revision ; - uint32_t status ; + + // Information coming from directly loaded symbols. The plugin is responsible for providing them. + // + std::string creator ; // creator of the plugin + std::string name ; // name of the plugin + uint32_t API_version ; // API version. + uint32_t svn_revision ; // Coming from scripts. Same svn version but changing hash could be a security issue. + + // This info is filled when accessing the .so, and loading the plugin. + // + uint32_t status ; // See the flags in retroshare/rsplugin.h + std::string info_string ; }; class RsPluginManager: public RsPluginHandler, public p3Config { public: - RsPluginManager() ; + RsPluginManager(const std::string& current_executable_sha1_hash) ; virtual ~RsPluginManager() {} // ------------ Derived from RsPluginHandler ----------------// @@ -60,8 +74,8 @@ class RsPluginManager: public RsPluginHandler, public p3Config * sets interfaces for all loaded plugins * @param interfaces */ - void setInterfaces(RsPlugInInterfaces& interfaces); - static void setPluginEntrySymbol(const std::string& s) { _plugin_entry_symbol = s ; } + void setInterfaces(RsPlugInInterfaces& interfaces); + static bool acceptablePluginName(const std::string& s) ; static void setCacheDirectories(const std::string& local,const std::string& remote) ; static void setFileServer(ftServer *ft) { _ftserver = ft ; } @@ -88,11 +102,24 @@ class RsPluginManager: public RsPluginHandler, public p3Config std::string hashPlugin(const std::string& shared_library_name) ; std::vector _plugins ; - std::set _accepted_hashes ; + + // Should allow + // - searching + // - saving all hash + // + // At start + // * load reference executable hash. Compare with current executable. + // - if different => flush all plugin hashes from cache + // - if equal, + // + std::set _accepted_hashes ; // accepted hash values for reference executable hash. + std::set _rejected_hashes ; // rejected hash values for reference executable hash. + std::string _current_executable_hash ; // At all times, the list of accepted plugins should be related to the current hash of the executable. bool _allow_all_plugins ; static std::string _plugin_entry_symbol ; static std::string _plugin_revision_symbol ; + static std::string _plugin_API_symbol ; static std::string _remote_cache_dir ; static std::string _local_cache_dir ; static ftServer *_ftserver ; diff --git a/libretroshare/src/retroshare/rsiface.h b/libretroshare/src/retroshare/rsiface.h index df62c16cf..64ceebf17 100644 --- a/libretroshare/src/retroshare/rsiface.h +++ b/libretroshare/src/retroshare/rsiface.h @@ -206,6 +206,7 @@ class NotifyBase virtual void notifyHistoryChanged(uint32_t /* msgId */, int /* type */) {} virtual bool askForPassword(const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */ ) { return false ;} + virtual bool askForPluginConfirmation(const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */) { return false ;} }; const int NOTIFY_LIST_NEIGHBOURS = 1; diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h index 0b2eedc50..a64d2dddf 100644 --- a/libretroshare/src/retroshare/rsplugin.h +++ b/libretroshare/src/retroshare/rsplugin.h @@ -52,14 +52,22 @@ class RsPQIService ; class RsAutoUpdatePage ; class PopupChatDialog ; +// Plugin API version. Not used yet, but will be in the future the +// main value that decides for compatibility. +// +#define RS_PLUGIN_API_VERSION 0x000101 + // Used for the status of plugins. // #define PLUGIN_STATUS_NO_STATUS 0x0000 -#define PLUGIN_STATUS_UNKNOWN_HASH 0x0001 +#define PLUGIN_STATUS_REJECTED_HASH 0x0001 #define PLUGIN_STATUS_DLOPEN_ERROR 0x0002 #define PLUGIN_STATUS_MISSING_SYMBOL 0x0003 #define PLUGIN_STATUS_NULL_PLUGIN 0x0004 #define PLUGIN_STATUS_LOADED 0x0005 +#define PLUGIN_STATUS_WRONG_API 0x0006 +#define PLUGIN_STATUS_MISSING_API 0x0007 +#define PLUGIN_STATUS_MISSING_SVN 0x0008 class RsPluginHandler; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 6b3227fa4..359c833f2 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -86,6 +86,7 @@ class RsInitConfig /* Directories (SetupBaseDir) */ static std::string basedir; static std::string homePath; + static std::string main_executable_hash; #ifdef WINDOWS_SYS static bool portable; static bool isWindowsXP; @@ -151,6 +152,7 @@ static const int SSLPWD_LEN = 64; std::list RsInitConfig::accountIds; std::string RsInitConfig::preferedId; +std::string RsInitConfig::main_executable_hash; rs_lock_handle_t RsInitConfig::lockHandle; @@ -599,6 +601,15 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck #endif /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + // Hash the main executable. + + uint64_t tmp_size ; + std::string tmp_name ; + + if(!RsDirUtil::getFileHash(argv[0],RsInitConfig::main_executable_hash,tmp_size,NULL)) + std::cerr << "Cannot hash executable! Plugins will not be loaded correctly." << std::endl; + else + std::cerr << "Hashed main executable: " << RsInitConfig::main_executable_hash << std::endl; /* At this point we want to. * 1) Load up Dase Directory. @@ -1888,7 +1899,7 @@ int RsServer::StartupRetroShare() /* (1) Load up own certificate (DONE ALREADY) - just CHECK */ /**************************************************************************/ - if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL)) + if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL)) { std::cerr << "main() - Fatal Error....." << std::endl; std::cerr << "Invalid Certificate configuration!" << std::endl; @@ -1896,15 +1907,15 @@ int RsServer::StartupRetroShare() return false ; } - std::string ownId = AuthSSL::getAuthSSL()->OwnId(); + std::string ownId = AuthSSL::getAuthSSL()->OwnId(); /**************************************************************************/ /* Any Initial Configuration (Commandline Options) */ /**************************************************************************/ /* set the debugging to crashMode */ - std::cerr << "set the debugging to crashMode." << std::endl; - if ((!RsInitConfig::haveLogFile) && (!RsInitConfig::outStderr)) + std::cerr << "set the debugging to crashMode." << std::endl; + if ((!RsInitConfig::haveLogFile) && (!RsInitConfig::outStderr)) { std::string crashfile = RsInitConfig::basedir + "/"; crashfile += ownId + "/" + configLogFileName; @@ -1919,7 +1930,7 @@ int RsServer::StartupRetroShare() /**************************************************************************/ // Load up Certificates, and Old Configuration (if present) - std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; + std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; std::string emergencySaveDir = RsInitConfig::configDir.c_str(); std::string emergencyPartialsDir = RsInitConfig::configDir.c_str(); @@ -1934,7 +1945,7 @@ int RsServer::StartupRetroShare() /**************************************************************************/ /* setup classes / structures */ /**************************************************************************/ - std::cerr << "setup classes / structures" << std::endl; + std::cerr << "setup classes / structures" << std::endl; @@ -1944,21 +1955,21 @@ int RsServer::StartupRetroShare() mNetMgr = new p3NetMgrIMPL(); mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr); - /* Setup Notify Early - So we can use it. */ - rsNotify = new p3Notify(); - rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr); + /* Setup Notify Early - So we can use it. */ + rsNotify = new p3Notify(); + rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr); mPeerMgr->setManagers(mLinkMgr, mNetMgr); mNetMgr->setManagers(mPeerMgr, mLinkMgr); - - //load all the SSL certs as friends -// std::list sslIds; -// AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); -// for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) { -// mConnMgr->addFriend(*sslIdsIt); -// } - //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir); -/**************************** BITDHT ***********************************/ + + //load all the SSL certs as friends + // std::list sslIds; + // AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); + // for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) { + // mConnMgr->addFriend(*sslIdsIt); + // } + //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir); + /**************************** BITDHT ***********************************/ // Make up an address. XXX @@ -2058,13 +2069,13 @@ int RsServer::StartupRetroShare() p3BitDht *mBitDht = new p3BitDht(ownId, mLinkMgr, mNetMgr, mDhtStack, bootstrapfile); /* install external Pointer for Interface */ rsDht = mBitDht; - + // NEXT THE RELAY (NEED to keep a reference for installing RELAYS) UdpRelayReceiver *mRelay = new UdpRelayReceiver(mDhtStack); udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX] = mRelay; /* RELAY Connections (DHT Port) */ udpTypes[RSUDP_TOU_RECVER_RELAY_IDX] = TOU_RECEIVER_TYPE_UDPRELAY; mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX]); - + // LAST ON THIS STACK IS STANDARD DIRECT TOU udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX] = new UdpPeerReceiver(mDhtStack); /* standard DIRECT Connections (DHT Port) */ udpTypes[RSUDP_TOU_RECVER_DIRECT_IDX] = TOU_RECEIVER_TYPE_UDPPEER; @@ -2073,19 +2084,19 @@ int RsServer::StartupRetroShare() // NOW WE BUILD THE SECOND STACK. // Create the Second UdpStack... Port should be random (but openable!). -//#define MIN_RANDOM_PORT 30000 -//#define MAX_RANDOM_PORT 50000 - + //#define MIN_RANDOM_PORT 30000 + //#define MAX_RANDOM_PORT 50000 + struct sockaddr_in sndladdr; sockaddr_clear(&sndladdr); -// #ifdef LOCALNET_TESTING -// // HACK Proxy Port near Dht Port - For Relay Testing. -// uint16_t rndport = RsInitConfig::port + 3; -// sndladdr.sin_port = htons(rndport); -// #else -// uint16_t rndport = MIN_RANDOM_PORT + RSRandom::random_u32() % (MAX_RANDOM_PORT - MIN_RANDOM_PORT); -// #endif + // #ifdef LOCALNET_TESTING + // // HACK Proxy Port near Dht Port - For Relay Testing. + // uint16_t rndport = RsInitConfig::port + 3; + // sndladdr.sin_port = htons(rndport); + // #else + // uint16_t rndport = MIN_RANDOM_PORT + RSRandom::random_u32() % (MAX_RANDOM_PORT - MIN_RANDOM_PORT); + // #endif #ifdef LOCALNET_TESTING @@ -2104,23 +2115,23 @@ int RsServer::StartupRetroShare() // FIRSTLY THE PROXY STUNNER. UdpStunner *mProxyStunner = new UdpStunner(mProxyStack); mProxyStunner->setTargetStunPeriod(300); /* slow (5mins) */ - mProxyStack->addReceiver(mProxyStunner); + mProxyStack->addReceiver(mProxyStunner); #ifdef LOCALNET_TESTING mProxyStunner->SetAcceptLocalNet(); #endif - + // FINALLY THE PROXY UDP CONNECTIONS udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX] = new UdpPeerReceiver(mProxyStack); /* PROXY Connections (Alt UDP Port) */ udpTypes[RSUDP_TOU_RECVER_PROXY_IDX] = TOU_RECEIVER_TYPE_UDPPEER; mProxyStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX]); - + // REAL INITIALISATION - WITH THREE MODES tou_init((void **) udpReceivers, udpTypes, RSUDP_NUM_TOU_RECVERS); mBitDht->setupConnectBits(mDhtStunner, mProxyStunner, mRelay); - + mNetMgr->setAddrAssist(new stunAddrAssist(mDhtStunner), new stunAddrAssist(mProxyStunner)); #else /* install NULL Pointer for rsDht Interface */ @@ -2128,7 +2139,7 @@ int RsServer::StartupRetroShare() #endif -/**************************** BITDHT ***********************************/ + /**************************** BITDHT ***********************************/ SecurityPolicy *none = secpolicy_create(); @@ -2150,7 +2161,7 @@ int RsServer::StartupRetroShare() /* This should be set by config ... there is no default */ //ftserver->setSharedDirectories(fileList); - + rsFiles = ftserver; @@ -2173,10 +2184,10 @@ int RsServer::StartupRetroShare() plugins_directories.push_back(RsInitConfig::basedir + "/extensions/") ; #ifdef DEBUG_PLUGIN_SYSTEM plugins_directories.push_back(".") ; // this list should be saved/set to some correct value. - // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. + // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. #endif - RsPluginManager *mPluginsManager = new RsPluginManager ; + RsPluginManager *mPluginsManager = new RsPluginManager(RsInitConfig::main_executable_hash) ; rsPlugins = mPluginsManager ; mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager); @@ -2197,7 +2208,7 @@ int RsServer::StartupRetroShare() // - developping plugins // std::vector programatically_inserted_plugins ; - + // Push your own plugins into this list, before the call: // // programatically_inserted_plugins.push_back(myCoolPlugin) ; @@ -2217,7 +2228,7 @@ int RsServer::StartupRetroShare() mStatusSrv = new p3StatusService(mLinkMgr); #ifndef PQI_DISABLE_TUNNEL - p3tunnel *tn = new p3tunnel(mConnMgr, pqih); + p3tunnel *tn = new p3tunnel(mConnMgr, pqih); pqih -> addService(tn); mConnMgr->setP3tunnel(tn); #endif @@ -2259,23 +2270,23 @@ int RsServer::StartupRetroShare() // Testing New Cache Services. p3PhotoService *mPhotos = new p3PhotoService(RS_SERVICE_TYPE_PHOTO); pqih -> addService(mPhotos); - + // Testing New Cache Services. p3WikiService *mWikis = new p3WikiService(RS_SERVICE_TYPE_WIKI); pqih -> addService(mWikis); - + // Testing New Cache Services. p3Wire *mWire = new p3Wire(RS_SERVICE_TYPE_WIRE); pqih -> addService(mWire); - + // Testing New Cache Services. p3IdService *mIdentity = new p3IdService(RS_SERVICE_TYPE_IDENTITY); pqih -> addService(mIdentity); - + // Testing New Cache Services. p3ForumsV2 *mForumsV2 = new p3ForumsV2(RS_SERVICE_TYPE_FORUMSV2); pqih -> addService(mForumsV2); - + // Testing New Cache Services. p3PostedService *mPosted = new p3PostedService(RS_SERVICE_TYPE_POSTED); pqih -> addService(mPosted); @@ -2319,8 +2330,8 @@ int RsServer::StartupRetroShare() #ifdef RS_ENABLE_ZEROCONF p3ZeroConf *mZeroConf = new p3ZeroConf( - AuthGPG::getAuthGPG()->getGPGOwnId(), ownId, - mLinkMgr, mNetMgr, mPeerMgr); + AuthGPG::getAuthGPG()->getGPGOwnId(), ownId, + mLinkMgr, mNetMgr, mPeerMgr); mNetMgr->addNetAssistConnect(2, mZeroConf); mNetMgr->addNetListener(mZeroConf); #endif @@ -2384,7 +2395,7 @@ int RsServer::StartupRetroShare() /**************************************************************************/ /* (2) Load configuration files */ /**************************************************************************/ - std::cerr << "(2) Load configuration files" << std::endl; + std::cerr << "(2) Load configuration files" << std::endl; mConfigMgr->loadConfiguration(); @@ -2398,12 +2409,12 @@ int RsServer::StartupRetroShare() /**************************************************************************/ pqih->setConfig(mGeneralConfig); - pqih->load_config(); + pqih->load_config(); /**************************************************************************/ /* Force Any Configuration before Startup (After Load) */ /**************************************************************************/ - std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl; + std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl; if (RsInitConfig::forceLocalAddr) { @@ -2411,7 +2422,7 @@ int RsServer::StartupRetroShare() /* clean sockaddr before setting values (MaxOSX) */ sockaddr_clear(&laddr); - + laddr.sin_family = AF_INET; laddr.sin_port = htons(RsInitConfig::port); @@ -2436,7 +2447,7 @@ int RsServer::StartupRetroShare() if (load_trustedpeer) { /* sslroot does further checks */ - sslr -> loadInitialTrustedPeer(load_trustedpeer_file); + sslr -> loadInitialTrustedPeer(load_trustedpeer_file); } } #endif @@ -2480,7 +2491,7 @@ int RsServer::StartupRetroShare() /* flag that the basic Caches are now in the pending Queues */ mForums->HistoricalCachesDone(); mChannels->HistoricalCachesDone(); - + #ifdef RS_USE_BLOGS mBlogs->HistoricalCachesDone(); #endif @@ -2502,9 +2513,9 @@ int RsServer::StartupRetroShare() ftserver->StartupThreads(); ftserver->ResumeTransfers(); - //mDhtMgr->start(); + //mDhtMgr->start(); #ifdef RS_USE_BITDHT - mBitDht->start(); + mBitDht->start(); #endif // startup the p3distrib threads (for cache loading). diff --git a/libretroshare/src/serialiser/rstlvtypes.cc b/libretroshare/src/serialiser/rstlvtypes.cc index 0196b8acb..6a2fc0579 100644 --- a/libretroshare/src/serialiser/rstlvtypes.cc +++ b/libretroshare/src/serialiser/rstlvtypes.cc @@ -77,7 +77,7 @@ RsTlvBinaryData::RsTlvBinaryData(uint16_t t) } RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b) - : tlvtype(b.tlvtype), bin_data(NULL), bin_len(0) { + : tlvtype(b.tlvtype), bin_len(0) , bin_data(NULL) { setBinData(b.bin_data, b.bin_len); } diff --git a/libretroshare/src/serialiser/rstlvtypes.h b/libretroshare/src/serialiser/rstlvtypes.h index c2e7f60bb..4148faa62 100644 --- a/libretroshare/src/serialiser/rstlvtypes.h +++ b/libretroshare/src/serialiser/rstlvtypes.h @@ -213,6 +213,7 @@ class RsTlvKeyValue: public RsTlvItem { public: RsTlvKeyValue() { return; } + RsTlvKeyValue(const std::string& k,const std::string& v): key(k),value(v) {} virtual ~RsTlvKeyValue() { return; } virtual uint32_t TlvSize(); virtual void TlvClear(); diff --git a/plugins/VOIP/VOIPPlugin.cpp b/plugins/VOIP/VOIPPlugin.cpp index 89ec84931..521b11438 100644 --- a/plugins/VOIP/VOIPPlugin.cpp +++ b/plugins/VOIP/VOIPPlugin.cpp @@ -38,6 +38,12 @@ extern "C" { // with same revision numbers, assuming that the revision numbers are up-to-date. // uint32_t RETROSHARE_PLUGIN_revision = SVN_REVISION_NUMBER ; + + // This symbol contains the svn revision number grabbed from the executable. + // It will be tested by RS to load the plugin automatically, since it is safe to load plugins + // with same revision numbers, assuming that the revision numbers are up-to-date. + // + uint32_t RETROSHARE_PLUGIN_api = RS_PLUGIN_API_VERSION ; } void VOIPPlugin::getPluginVersion(int& major,int& minor,int& svn_rev) const diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp index 43bb2eeb2..8e2896b79 100644 --- a/retroshare-gui/src/gui/notifyqt.cpp +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -167,6 +167,33 @@ bool NotifyQt::askForPassword(const std::string& key_details, bool prev_is_bad, return false; } +bool NotifyQt::askForPluginConfirmation(const std::string& plugin_file_name, const std::string& plugin_file_hash) +{ + RsAutoUpdatePage::lockAllEvents() ; + + QMessageBox dialog; + dialog.setWindowTitle(tr("Unregistered plugin/executable")); + + QString text ; + text += tr( "RetroShare has detected an unregistered plugin. This happens in two cases:
  • Your RetroShare executable has changed.
  • The plugin has changed
Click on Yes to authorize this plugin, or No to deny it. You can change your mind later in Options -> Plugins, then restart." ) ; + text += "
    " ; + text += "
  • Hash:\t" + QString::fromStdString(plugin_file_hash) + "
  • " ; + text += "
  • File:\t" + QString::fromStdString(plugin_file_name) + "
  • "; + text += "
" ; + + dialog.setText(text) ; + dialog.setWindowIcon(QIcon(":/images/rstray3.png")); + dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No) ; + + int ret = dialog.exec(); + + RsAutoUpdatePage::unlockAllEvents() ; + + if (ret == QMessageBox::Yes) + return true ; + else + return false; +} void NotifyQt::notifyDiscInfoChanged() { diff --git a/retroshare-gui/src/gui/notifyqt.h b/retroshare-gui/src/gui/notifyqt.h index 8d1c8b4b6..fb90cee4f 100644 --- a/retroshare-gui/src/gui/notifyqt.h +++ b/retroshare-gui/src/gui/notifyqt.h @@ -59,6 +59,7 @@ class NotifyQt: public QObject, public NotifyBase virtual void notifyDownloadComplete(const std::string& fileHash); virtual void notifyDownloadCompleteCount(uint32_t count); virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password); + virtual bool askForPluginConfirmation(const std::string& plugin_filename, const std::string& plugin_file_hash); /* Notify from GUI */ void notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType); diff --git a/retroshare-gui/src/gui/settings/PluginsPage.cpp b/retroshare-gui/src/gui/settings/PluginsPage.cpp index 22c27306b..6f13b168a 100644 --- a/retroshare-gui/src/gui/settings/PluginsPage.cpp +++ b/retroshare-gui/src/gui/settings/PluginsPage.cpp @@ -57,16 +57,26 @@ PluginsPage::PluginsPage(QWidget * parent, Qt::WFlags flags) switch(status) { - case PLUGIN_STATUS_UNKNOWN_HASH: status_string = tr("SVN revision number ")+QString::number(svn_revision)+tr(" does not match current. Please manually enable the plugin at your own risk.") ; - break ; - case PLUGIN_STATUS_DLOPEN_ERROR: status_string = tr("Loading error.") ; - break ; - case PLUGIN_STATUS_MISSING_SYMBOL: status_string = tr("Missing symbol. Wrong version?") ; - break ; - case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ; - break ; - case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ; - break ; + case PLUGIN_STATUS_REJECTED_HASH: status_string = tr("Hash rejected. Enable it manually and restart, if you need.") ; + break ; + + case PLUGIN_STATUS_MISSING_API: status_string = tr("No API number supplied. Please read plugin development manual.") ; + break ; + + case PLUGIN_STATUS_MISSING_SVN: status_string = tr("No SVN number supplied. Please read plugin development manual.") ; + break ; + + case PLUGIN_STATUS_DLOPEN_ERROR: status_string = tr("Loading error.") ; + break ; + + case PLUGIN_STATUS_MISSING_SYMBOL:status_string = tr("Missing symbol. Wrong version?") ; + break ; + + case PLUGIN_STATUS_NULL_PLUGIN: status_string = tr("No plugin object") ; + break ; + + case PLUGIN_STATUS_LOADED: status_string = tr("Plugins is loaded.") ; + break ; default: status_string = tr("Unknown status.") ; } diff --git a/retroshare-nogui/src/notifytxt.cc b/retroshare-nogui/src/notifytxt.cc index 7bf15b115..01c98b753 100644 --- a/retroshare-nogui/src/notifytxt.cc +++ b/retroshare-nogui/src/notifytxt.cc @@ -23,7 +23,7 @@ * */ - +#include #include "notifytxt.h" #include #include @@ -84,6 +84,23 @@ void NotifyTxt::notifyChat() return; } +bool NotifyTxt::askForPluginConfirmation(const std::string& plugin_file_name, const std::string& plugin_file_hash) +{ + std::cerr << "The following plugin is not registered as accepted or denied. You probably upgraded the main executable or the plugin itself." << std::endl; + std::cerr << " Hash: " << plugin_file_hash << std::endl; + std::cerr << " File: " << plugin_file_name << std::endl; + + char a = 0 ; + while(a != 'y' && a != 'n') + { + std::cerr << "Enable this plugin ? (y/n) :" ; + std::cerr.flush() ; + + a = fgetc(stdin) ; + } + return a == 'y' ; +} + bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password) { char *passwd = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ; diff --git a/retroshare-nogui/src/notifytxt.h b/retroshare-nogui/src/notifytxt.h index a5b1bb851..82a019dc8 100644 --- a/retroshare-nogui/src/notifytxt.h +++ b/retroshare-nogui/src/notifytxt.h @@ -41,6 +41,7 @@ class NotifyTxt: public NotifyBase virtual void notifyErrorMsg(int list, int sev, std::string msg); virtual void notifyChat(); virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password); + virtual bool askForPluginConfirmation(const std::string& plugin_file, const std::string& plugin_hash); private: