diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-02-27 08:22:58 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-02-27 08:22:58 +0000 |
| commit | dc2a51b54a5ef934109edd8416f82a0e050657b2 (patch) | |
| tree | ce8eb40d47c96432f47cd72cdc98198aaae43e80 /src | |
| parent | 513a6bd12dcbbb14e67a6a7b44fe77bfdef30318 (diff) | |
2010-02-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Discard torrent file if path data in it contains directory
traversal directives. Discard metalink:file element in Metalink3
format if its name attribute contains directory traversal
directives. Ignore name attribute of metalink:signature element
in Metalink3 format if it contains directory traversal directives.
* src/MetalinkParserStateV3Impl.cc
* src/bittorrent_helper.cc
* src/message.h
* test/BittorrentHelperTest.cc
* test/Makefile.am
* test/MetalinkProcessorTest.cc
* test/metalink3-dirtraversal.xml
* test/test.xml
Diffstat (limited to 'src')
| -rw-r--r-- | src/MetalinkParserStateV3Impl.cc | 11 | ||||
| -rw-r--r-- | src/bittorrent_helper.cc | 35 | ||||
| -rw-r--r-- | src/message.h | 1 |
3 files changed, 26 insertions, 21 deletions
diff --git a/src/MetalinkParserStateV3Impl.cc b/src/MetalinkParserStateV3Impl.cc index dd850442..33fb1309 100644 --- a/src/MetalinkParserStateV3Impl.cc +++ b/src/MetalinkParserStateV3Impl.cc @@ -113,8 +113,12 @@ void FilesMetalinkParserState::beginElement stm->setFileState(); std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, NAME); if(itr != attrs.end()) { + std::string name = util::trim((*itr).value); + if(util::detectDirTraversal(name)) { + return; + } stm->newEntryTransaction(); - stm->setFileNameOfEntry(util::trim((*itr).value)); + stm->setFileNameOfEntry(name); } } else { stm->setSkipTagState(); @@ -275,7 +279,10 @@ void VerificationMetalinkParserState::beginElement stm->setTypeOfSignature(util::trim((*itr).value)); std::vector<XmlAttr>::const_iterator itr = findAttr(attrs, FILE); if(itr != attrs.end()) { - stm->setFileOfSignature(util::trim((*itr).value)); + std::string file = util::trim((*itr).value); + if(!util::detectDirTraversal(file)) { + stm->setFileOfSignature(file); + } } } } else { diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index fc8a3b49..73bb434b 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -200,19 +200,18 @@ static void extractFileEntries } const BDE& nameData = infoDict[nameKey]; if(nameData.isString()) { - // Split path by '/' just in case nasty ".." is included in name - std::vector<std::string> pathelems; - util::split(nameData.s(), std::back_inserter(pathelems), "/"); - name = util::joinPath(pathelems.begin(), pathelems.end()); - torrent[NAME] = nameData.s(); + if(util::detectDirTraversal(nameData.s())) { + throw DL_ABORT_EX + (StringFormat(MSG_DIR_TRAVERSAL_DETECTED,nameData.s().c_str()).str()); + } + name = nameData.s(); } else { name = strconcat(File(defaultName).getBasename(), ".file"); - torrent[NAME] = name; } } else { name = overrideName; - torrent[NAME] = name; } + torrent[NAME] = name; const BDE& filesList = infoDict[C_FILES]; std::vector<SharedHandle<FileEntry> > fileEntries; @@ -246,17 +245,15 @@ static void extractFileEntries throw DL_ABORT_EX("Path is empty."); } - std::vector<std::string> pathelem(pathList.size()); - std::transform(pathList.listBegin(), pathList.listEnd(), pathelem.begin(), - std::mem_fun_ref(&BDE::s)); - std::string path = name; - strappend(path, "/", util::joinPath(pathelem.begin(), pathelem.end())); - // Split path with '/' again because each pathList element can - // contain "/" inside. - std::vector<std::string> elements; - util::split(path, std::back_inserter(elements), "/"); - path = util::joinPath(elements.begin(), elements.end()); - + std::vector<std::string> pathelem(pathList.size()+1); + pathelem[0] = name; + std::transform(pathList.listBegin(), pathList.listEnd(), + pathelem.begin()+1, std::mem_fun_ref(&BDE::s)); + std::string path = strjoin(pathelem.begin(), pathelem.end(), '/'); + if(util::detectDirTraversal(path)) { + throw DL_ABORT_EX + (StringFormat(MSG_DIR_TRAVERSAL_DETECTED, path.c_str()).str()); + } std::deque<std::string> uris; createUri(urlList.begin(), urlList.end(), std::back_inserter(uris), path); SharedHandle<FileEntry> fileEntry @@ -282,7 +279,7 @@ static void extractFileEntries std::deque<std::string> uris; for(std::vector<std::string>::const_iterator i = urlList.begin(); i != urlList.end(); ++i) { - if(util::endsWith(*i, "/")) { + if(util::endsWith(*i, A2STR::SLASH_C)) { uris.push_back((*i)+name); } else { uris.push_back(*i); diff --git a/src/message.h b/src/message.h index 930e4139..c563c2b3 100644 --- a/src/message.h +++ b/src/message.h @@ -180,6 +180,7 @@ #define MSG_METADATA_SAVED _("Saved metadata as %s.") #define MSG_METADATA_NOT_SAVED _("Saving metadata as %s failed. Maybe file" \ " already exists.") +#define MSG_DIR_TRAVERSAL_DETECTED _("Detected directory traversal directive in %s") #define EX_TIME_OUT _("Timeout.") #define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.") |
