From 39969cd34213f06f0bc88fa48ae7011ef5b47141 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 29 May 2010 13:10:32 +0000 Subject: [PATCH] Suppressed the possibility for browsable only files to be searched by hash from turtle router. This avoids that an attacker that captures a broadcast hash request can also ask for the file. This needed to add back explicit sources in SearchDialog and private chat transfer. I dynamically search for sources in file lists just before calling FileRequest. When RS links anchorClick() will work properly with Qt, we can remove the search flag "EXTRA" from the tunnel digging in p3turtle.cc, otherwise, people having this bug can't transfer files in private chat by copy+paste of a RS link. Also: - added missing mutexes in search requests into fimonitor.cc - suppressed some debug info in connect manager - added check for write fails when dumping config files git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5.0@3026 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/dbase/fimonitor.cc | 200 ++++++++++-------- libretroshare/src/dbase/fimonitor.h | 7 +- libretroshare/src/ft/ftcontroller.cc | 3 +- libretroshare/src/ft/ftdatamultiplex.cc | 12 +- libretroshare/src/ft/ftdbase.cc | 6 +- libretroshare/src/pqi/p3cfgmgr.cc | 5 + libretroshare/src/pqi/p3connmgr.cc | 2 + libretroshare/src/turtle/p3turtle.cc | 2 +- retroshare-gui/src/gui/SearchDialog.cpp | 19 ++ retroshare-gui/src/gui/SearchDialog.h | 2 + .../src/gui/chat/PopupChatDialog.cpp | 9 +- 11 files changed, 168 insertions(+), 99 deletions(-) diff --git a/libretroshare/src/dbase/fimonitor.cc b/libretroshare/src/dbase/fimonitor.cc index a3762635e..d4247a395 100644 --- a/libretroshare/src/dbase/fimonitor.cc +++ b/libretroshare/src/dbase/fimonitor.cc @@ -58,7 +58,6 @@ FileIndexMonitor::FileIndexMonitor(CacheStrapper *cs, NotifyBase *cb_in,std::str FileIndexMonitor::~FileIndexMonitor() { /* Data cleanup - TODO */ - return; } int FileIndexMonitor::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) @@ -66,7 +65,10 @@ int FileIndexMonitor::SearchKeywords(std::list keywords, std::list< results.clear(); std::list firesults; - fi.searchTerms(keywords, firesults); + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + fi.searchTerms(keywords, firesults); + } return filterResults(firesults,results,flags) ; } @@ -76,7 +78,10 @@ int FileIndexMonitor::SearchBoolExp(Expression *exp, std::list& resu results.clear(); std::list firesults; - fi.searchBoolExp(exp, firesults); + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + fi.searchBoolExp(exp, firesults); + } return filterResults(firesults,results,flags) ; } @@ -109,53 +114,64 @@ int FileIndexMonitor::filterResults(std::list& firesults,std::list results; bool ok = false; - fiMutex.lock(); { /* LOCKED DIRS */ + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ #ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::findLocalFile() Hash: " << hash << std::endl; + std::cerr << "FileIndexMonitor::findLocalFile() Hash: " << hash << std::endl; #endif - /* search through the fileIndex */ - fi.searchHash(hash, results); + /* search through the fileIndex */ + fi.searchHash(hash, results); - if (results.size() > 0) - { - /* find the full path for the first entry */ - FileEntry *fe = results.front(); - DirEntry *de = fe->parent; /* all files must have a valid parent! */ - -#ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::findLocalFile() Found Name: " << fe->name << std::endl; -#endif - std::string shpath = RsDirUtil::removeRootDir(de->path); - std::string basedir = RsDirUtil::getRootDir(de->path); - std::string realroot = locked_findRealRoot(basedir); - - /* construct full name */ - if (realroot.length() > 0) + if (results.size() > 0) { - fullpath = realroot + "/"; - if (shpath != "") - { - fullpath += shpath + "/"; - } - fullpath += fe->name; + /* find the full path for the first entry */ + FileEntry *fe = results.front(); + DirEntry *de = fe->parent; /* all files must have a valid parent! */ - size = fe->size; - ok = true; - } + uint32_t share_flags = locked_findShareFlags(fe) ; #ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::findLocalFile() Found Path: " << fullpath << std::endl; - std::cerr << "FileIndexMonitor::findLocalFile() Found Size: " << size << std::endl; + std::cerr << "FileIndexMonitor::findLocalFile: Filtering candidate " << fe->name << ", flags=" << share_flags << ", hint_flags=" << hint_flags << std::endl ; #endif - } + if((share_flags & hint_flags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE)) > 0) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile() Found Name: " << fe->name << std::endl; +#endif + std::string shpath = RsDirUtil::removeRootDir(de->path); + std::string basedir = RsDirUtil::getRootDir(de->path); + std::string realroot = locked_findRealRoot(basedir); - } fiMutex.unlock(); /* UNLOCKED DIRS */ + /* construct full name */ + if (realroot.length() > 0) + { + fullpath = realroot + "/"; + if (shpath != "") + { + fullpath += shpath + "/"; + } + fullpath += fe->name; + + size = fe->size; + ok = true; + } +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile() Found Path: " << fullpath << std::endl; + std::cerr << "FileIndexMonitor::findLocalFile() Found Size: " << size << std::endl; +#endif + } +#ifdef FIM_DEBUG + else + std::cerr << "FileIndexMonitor::findLocalFile() discarded" << std::endl ; +#endif + } + } /* UNLOCKED DIRS */ return ok; } @@ -164,28 +180,29 @@ bool FileIndexMonitor::convertSharedFilePath(std::string path, std::string &f { bool ok = false; - fiMutex.lock(); { /* LOCKED DIRS */ + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ #ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::convertSharedFilePath() path: " << path << std::endl; + std::cerr << "FileIndexMonitor::convertSharedFilePath() path: " << path << std::endl; #endif - std::string shpath = RsDirUtil::removeRootDir(path); - std::string basedir = RsDirUtil::getRootDir(path); - std::string realroot = locked_findRealRoot(basedir); + std::string shpath = RsDirUtil::removeRootDir(path); + std::string basedir = RsDirUtil::getRootDir(path); + std::string realroot = locked_findRealRoot(basedir); - /* construct full name */ - if (realroot.length() > 0) - { - fullpath = realroot + "/"; - fullpath += shpath; + /* construct full name */ + if (realroot.length() > 0) + { + fullpath = realroot + "/"; + fullpath += shpath; #ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::convertSharedFilePath() Found Path: " << fullpath << std::endl; + std::cerr << "FileIndexMonitor::convertSharedFilePath() Found Path: " << fullpath << std::endl; #endif - ok = true; - } + ok = true; + } - } fiMutex.unlock(); /* UNLOCKED DIRS */ + } /* UNLOCKED DIRS */ return ok; } @@ -244,8 +261,6 @@ void FileIndexMonitor::setPeriod(int period) void FileIndexMonitor::run() //void FileIndexMonitor::run(std::string& current_job) { - -// updateCycle(current_job); updateCycle(); while(1) @@ -258,8 +273,7 @@ void FileIndexMonitor::run() #ifndef WINDOWS_SYS sleep(1); #else - - Sleep(1000); + Sleep(1000); #endif /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ @@ -830,28 +844,26 @@ void FileIndexMonitor::getSharedDirectories(std::list &dirs) RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ /* must provide pendingDirs, as other parts depend on instanteous response */ - if (pendingDirs) - dirs = pendingDirList; - else - { + if (pendingDirs) + dirs = pendingDirList; + else + { /* get actual list (not pending stuff) */ std::map::const_iterator it; for(it = directoryMap.begin(); it != directoryMap.end(); it++) dirs.push_back(it->second) ; - } + } } /* interface */ void FileIndexMonitor::forceDirectoryCheck() { - fiMutex.lock(); { /* LOCKED DIRS */ + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ if (!mInCheck) mForceCheck = true; - - } fiMutex.unlock(); /* UNLOCKED DIRS */ } @@ -867,18 +879,16 @@ bool FileIndexMonitor::inDirectoryCheck() bool FileIndexMonitor::internal_setSharedDirectories() { int i; - fiMutex.lock(); /* LOCKED DIRS */ + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ if (!pendingDirs) { if (mForceCheck) { mForceCheck = false; - fiMutex.unlock(); /* UNLOCKED DIRS */ return true; } - fiMutex.unlock(); /* UNLOCKED DIRS */ return false; } @@ -933,7 +943,6 @@ bool FileIndexMonitor::internal_setSharedDirectories() fi.setRootDirectories(topdirs, 0); locked_saveFileIndexes() ; - fiMutex.unlock(); /* UNLOCKED DIRS */ return true; } @@ -1072,35 +1081,44 @@ int FileIndexMonitor::RequestDirDetails(void *ref, DirDetails &details, uint32_t if(ref != NULL) { FileEntry *file = (FileEntry *) ref; - DirEntry *dir = dynamic_cast(file) ; - if(dir == NULL) - dir = dynamic_cast(file->parent) ; - if(dir != NULL && dir->parent != NULL) - while(dir->parent->parent != NULL) - dir = dir->parent ; + uint32_t share_flags = locked_findShareFlags(file) ; - if(dir != NULL && dir->parent != NULL) - { -#ifdef FIM_DEBUG - std::cerr << "FileIndexMonitor::RequestDirDetails: top parent name=" << dir->name << std::endl ; -#endif - std::map::const_iterator it = directoryMap.find(dir->name) ; - - if(it == directoryMap.end()) - std::cerr << "*********** ERROR *********** In " << __PRETTY_FUNCTION__ << std::endl ; - else - { - details.flags |= (( (it->second.shareflags & RS_FILE_HINTS_BROWSABLE)>0)?DIR_FLAGS_BROWSABLE:0) ; - details.flags |= (( (it->second.shareflags & RS_FILE_HINTS_NETWORK_WIDE)>0)?DIR_FLAGS_NETWORK_WIDE:0) ; -#ifdef FIM_DEBUG - std::cerr << "flags = " << details.flags << std::endl ; -#endif - } - } + details.flags |= (( (share_flags & RS_FILE_HINTS_BROWSABLE )>0)?DIR_FLAGS_BROWSABLE :0) ; + details.flags |= (( (share_flags & RS_FILE_HINTS_NETWORK_WIDE)>0)?DIR_FLAGS_NETWORK_WIDE:0) ; } - return true ; } +uint32_t FileIndexMonitor::locked_findShareFlags(FileEntry *file) const +{ + uint32_t flags = 0 ; + + DirEntry *dir = dynamic_cast(file) ; + if(dir == NULL) + dir = dynamic_cast(file->parent) ; + + if(dir != NULL && dir->parent != NULL) + while(dir->parent->parent != NULL) + dir = dir->parent ; + + if(dir != NULL && dir->parent != NULL) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::RequestDirDetails: top parent name=" << dir->name << std::endl ; +#endif + std::map::const_iterator it = directoryMap.find(dir->name) ; + + if(it == directoryMap.end()) + std::cerr << "*********** ERROR *********** In " << __PRETTY_FUNCTION__ << std::endl ; + else + flags = it->second.shareflags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE) ; +#ifdef FIM_DEBUG + std::cerr << "flags = " << flags << std::endl ; +#endif + } + + return flags ; +} + diff --git a/libretroshare/src/dbase/fimonitor.h b/libretroshare/src/dbase/fimonitor.h index 611b1faf2..066e62e70 100644 --- a/libretroshare/src/dbase/fimonitor.h +++ b/libretroshare/src/dbase/fimonitor.h @@ -120,11 +120,16 @@ class FileIndexMonitor: public CacheSource, public RsThread /* util fns */ private: + /* the mutex should be locked before calling these 3. */ + // saves file indexs and update the cache. void locked_saveFileIndexes() ; - /* the mutex should be locked before calling... these. */ + // Finds the share flags associated with this file entry. + uint32_t locked_findShareFlags(FileEntry *fe) const ; + std::string locked_findRealRoot(std::string base) const; + void hashFiles(const std::vector& to_hash) ; bool hashFile(std::string path, FileEntry &fi); /* To Implement */ diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc index 60e31b908..e5c2ab2b3 100644 --- a/libretroshare/src/ft/ftcontroller.cc +++ b/libretroshare/src/ft/ftcontroller.cc @@ -63,6 +63,7 @@ * #define CONTROL_DEBUG 1 * #define DEBUG_DWLQUEUE 1 *****/ +#define CONTROL_DEBUG 1 static const uint32_t SAVE_TRANSFERS_DELAY = 61 ; // save transfer progress every 61 seconds. static const uint32_t INACTIVE_CHUNKS_CHECK_DELAY = 60 ; // time after which an inactive chunk is released @@ -942,7 +943,7 @@ bool ftController::alreadyHaveFile(const std::string& hash) return true ; // check for file lists - if (mSearch->search(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) + if (mSearch->search(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) return true ; return false ; diff --git a/libretroshare/src/ft/ftdatamultiplex.cc b/libretroshare/src/ft/ftdatamultiplex.cc index 3d45a8db0..7089d5901 100644 --- a/libretroshare/src/ft/ftdatamultiplex.cc +++ b/libretroshare/src/ft/ftdatamultiplex.cc @@ -695,10 +695,20 @@ bool ftDataMultiplex::handleSearchRequest(const std::string& peerId, const std:: * Do Actual search * Could be Cache File, Local or Extra * (anywhere but remote really) + * + * the network wide and browsable flags are needed, otherwise results get filtered. + * For tunnel creation, the check of browsable/network wide flag is already done, so + * if we get a file download packet here, the source is already allowed to download it. + * */ FileInfo info; - uint32_t hintflags = (RS_FILE_HINTS_CACHE | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY); + uint32_t hintflags = ( RS_FILE_HINTS_NETWORK_WIDE + | RS_FILE_HINTS_BROWSABLE + | RS_FILE_HINTS_CACHE + | RS_FILE_HINTS_EXTRA + | RS_FILE_HINTS_LOCAL + | RS_FILE_HINTS_SPEC_ONLY); if (mSearch->search(hash, hintflags, info)) { diff --git a/libretroshare/src/ft/ftdbase.cc b/libretroshare/src/ft/ftdbase.cc index 360845c3a..ffd591f97 100644 --- a/libretroshare/src/ft/ftdbase.cc +++ b/libretroshare/src/ft/ftdbase.cc @@ -136,8 +136,10 @@ bool ftFiMonitor::search(std::string hash, uint32_t hintflags, FileInfo &info) c std::cerr << std::endl; #endif - // setup search flags according to hintflags - uint32_t flags = 0; + // Setup search flags according to hintflags. Originally flags was 0. I (cyril) don't know + // why we don't just pass hintflags there, so I tried to keep the idea. + // + uint32_t flags = hintflags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE); if(findLocalFile(hash, flags, path, fsize)) { diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc index c366f1c5c..8f5a004ea 100644 --- a/libretroshare/src/pqi/p3cfgmgr.cc +++ b/libretroshare/src/pqi/p3cfgmgr.cc @@ -768,7 +768,12 @@ bool p3Config::backedUpFileSave(const std::string& cfg_fname, const std::string& } if(size_file != fwrite(buff, 1, size_file, cfg_file)) + { getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "Write error", "Error while writing backup configuration file " + cfg_fname_backup + "\nIs your disc full or out of quota ?"); + fclose(cfg_file); + return false ; + } + fclose(cfg_file); diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc index 893671901..3c71335b3 100644 --- a/libretroshare/src/pqi/p3connmgr.cc +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -3543,8 +3543,10 @@ void peerConnectState::updateIpAddressList(const IpAddressTimed& ipTimed) else ++it,++cnt ; +#ifdef CONN_DEBUG std::cerr << "Adress list updated:" << std::endl ; printIpAddressList(); +#endif } void peerConnectState::printIpAddressList() diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index 6889dcdc6..3d5c047ac 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -1740,7 +1740,7 @@ void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item) // bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,FileInfo& info) { - return rsFiles->FileDetails(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info); + return rsFiles->FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info); } static std::string printNumber(uint64_t num,bool hex=false) diff --git a/retroshare-gui/src/gui/SearchDialog.cpp b/retroshare-gui/src/gui/SearchDialog.cpp index 7f59ad1b7..1080a0c3a 100644 --- a/retroshare-gui/src/gui/SearchDialog.cpp +++ b/retroshare-gui/src/gui/SearchDialog.cpp @@ -263,6 +263,21 @@ void SearchDialog::searchtableWidgetCostumPopupMenu( QPoint point ) contextMnu->exec( mevent->globalPos() ); } +void SearchDialog::getSourceFriendsForHash(const std::string& hash,std::list& srcIds) +{ + std::cerr << "Searching sources for file " << hash << std::endl ; + srcIds.clear(); + + FileInfo finfo ; + rsFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE,finfo) ; + + for(std::list::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it) + { + std::cerr << " adding peerid " << (*it).peerId << std::endl ; + srcIds.push_back((*it).peerId) ; + } +} + void SearchDialog::download() { /* should also be able to handle multi-selection */ @@ -281,6 +296,8 @@ void SearchDialog::download() std::cerr << std::endl; std::list srcIds; + getSourceFriendsForHash((item->text(SR_HASH_COL)).toStdString(),srcIds) ; + if(!rsFiles -> FileRequest((item->text(SR_NAME_COL)).toStdString(), (item->text(SR_HASH_COL)).toStdString(), (item->text(SR_SIZE_COL)).toULongLong(), @@ -310,6 +327,8 @@ void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString + tr("/") + base + tr("/"); QString cleanPath = QDir::cleanPath(path); + getSourceFriendsForHash((item->text(SR_HASH_COL)).toStdString(),srcIds) ; + rsFiles->FileRequest(item->text(SR_NAME_COL).toStdString(), item->text(SR_HASH_COL).toStdString(), item->text(SR_SIZE_COL).toULongLong(), diff --git a/retroshare-gui/src/gui/SearchDialog.h b/retroshare-gui/src/gui/SearchDialog.h index 294e605c2..972a89e0b 100644 --- a/retroshare-gui/src/gui/SearchDialog.h +++ b/retroshare-gui/src/gui/SearchDialog.h @@ -104,6 +104,8 @@ private: void insertDirectory(const std::string &txt, qulonglong searchId, const DirDetails &dir); void setIconAndType(QTreeWidgetItem *item, QString &ext); void downloadDirectory(const QTreeWidgetItem *item, const QString &base); + void getSourceFriendsForHash(const std::string& hash,std::list& srcIds); + /** the advanced search dialog instance */ diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp index 4d0c1e342..871dee226 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -851,13 +851,18 @@ void PopupChatDialog::anchorClicked (const QUrl& link ) if(!rslink.valid()) { - QMessageBox mb(tr("Badly formed RS link"), tr("This RetroShare link is malformed. This is bug. Please contact the developers.\n\nNote: this possibly comes from a bug in Qt4.6. Try to right-click + copy link location."),QMessageBox::Information,QMessageBox::Ok,0,0); + QMessageBox mb(tr("Badly formed RS link"), tr("This RetroShare link is malformed. This is bug. Please contact the developers.\n\nNote: this possibly comes from a bug in Qt4.6. Try to right-click + copy link location, and paste in Transfer Tab."),QMessageBox::Information,QMessageBox::Ok,0,0); mb.setButtonText( QMessageBox::Ok, "OK" ); mb.exec(); return ; } + std::list srcIds ; + srcIds.push_back(dialogId); - if(rsFiles->FileRequest(rslink.name().toStdString(), rslink.hash().toStdString(), rslink.size(), "", RS_FILE_HINTS_NETWORK_WIDE, std::list())) + // I removed the NETWORK WIDE flag. Indeed, somebody can capture the turtle tunnel requests and ask for downloading the file while + // it's being downloaded (as partial files are always sources). + // + if(rsFiles->FileRequest(rslink.name().toStdString(), rslink.hash().toStdString(), rslink.size(), "", 0, srcIds)) { QMessageBox mb(tr("File Request Confirmation"), tr("The file has been added to your download list."),QMessageBox::Information,QMessageBox::Ok,0,0); mb.setButtonText( QMessageBox::Ok, "OK" );