Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1
aria2
aria2-0.16.0-CVE-2010-1512.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File aria2-0.16.0-CVE-2010-1512.patch of Package aria2
diff -ru aria2c-0.16.0-orig/src/array_fun.h aria2c-0.16.0/src/array_fun.h --- aria2c-0.16.0-orig/src/array_fun.h 2008-10-06 10:38:51.000000000 +0200 +++ aria2c-0.16.0/src/array_fun.h 2010-05-26 23:20:56.000000000 +0200 @@ -142,6 +142,29 @@ typedef R result_type; }; +template<typename T, size_t N> +class array_wrapper { +private: + T _array[N]; +public: + array_wrapper() {} + + operator T*() + { + return _array; + } + + operator const T*() const + { + return _array; + } + + size_t size() const + { + return N; + } +}; + template<typename R, typename A> array_fun<R> array_negate(A a) diff -ru aria2c-0.16.0-orig/src/DHTRoutingTableDeserializer.cc aria2c-0.16.0/src/DHTRoutingTableDeserializer.cc --- aria2c-0.16.0-orig/src/DHTRoutingTableDeserializer.cc 2008-10-06 10:38:50.000000000 +0200 +++ aria2c-0.16.0/src/DHTRoutingTableDeserializer.cc 2010-05-26 23:55:08.000000000 +0200 @@ -41,10 +41,12 @@ #include "a2netcompat.h" #include "StringFormat.h" #include "Util.h" +#include "array_fun.h" #include <cerrno> #include <cstring> #include <istream> #include <utility> +#include <cassert> namespace aria2 { @@ -57,11 +59,30 @@ return _localNode; } +static void readBytes(unsigned char* buf, size_t buflen, + std::istream& in, size_t readlen) +{ + assert(readlen <= buflen); + in.read(reinterpret_cast<char*>(buf), readlen); +} + const std::deque<SharedHandle<DHTNode> >& DHTRoutingTableDeserializer::getNodes() const { return _nodes; } +#define CHECK_STREAM(in, length) \ + if(in.gcount() != length) { \ + throw DlAbortEx \ + (StringFormat("Failed to load DHT routing table. cause:%s", \ + "Unexpected EOF").str()); \ + } \ + if(!in) { \ + throw DlAbortEx \ + (StringFormat("Failed to load DHT routing table. cause:%s", \ + strerror(errno)).str()); \ + } + void DHTRoutingTableDeserializer::deserialize(std::istream& in) { try { @@ -91,9 +112,12 @@ memset(zero, 0, sizeof(zero)); int version; - char buf[26]; + // If you change the code to read more than the size of buf, then + // expand the buf size here. + array_wrapper<unsigned char, 255> buf; + // header - in.read(buf, 8); + readBytes(buf, buf.size(), in, 8); if(memcmp(header, buf, 8) == 0) { version = 3; } else if(memcmp(headerCompat, buf, 8) == 0) { @@ -105,31 +129,46 @@ } // time if(version == 2) { - in.read(buf, 4); - _serializedTime.setTimeInSec(ntohl(*reinterpret_cast<uint32_t*>(buf))); + uint32_t temp32; + // time + in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32)); + CHECK_STREAM(in, sizeof(temp32)); + _serializedTime.setTimeInSec(ntohl(temp32)); // 4bytes reserved - in.read(buf, 4); + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); + } else { - in.read(buf, 8); - _serializedTime.setTimeInSec(ntoh64(*reinterpret_cast<uint64_t*>(buf))); + uint64_t temp64; + // time + in.read(reinterpret_cast<char*>(&temp64), sizeof(temp64)); + CHECK_STREAM(in, sizeof(temp64)); + _serializedTime.setTimeInSec(ntoh64(temp64)); } // localnode // 8bytes reserved - in.read(buf, 8); + readBytes(buf, buf.size(), in, 8); + CHECK_STREAM(in, 8); // localnode ID - in.read(buf, DHT_ID_LENGTH); - SharedHandle<DHTNode> localNode(new DHTNode(reinterpret_cast<const unsigned char*>(buf))); + readBytes(buf, buf.size(), in, DHT_ID_LENGTH); + CHECK_STREAM(in, DHT_ID_LENGTH); + SharedHandle<DHTNode> localNode(new DHTNode(buf)); // 4bytes reserved - in.read(buf, 4); + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); // number of nodes - in.read(buf, 4); - uint32_t numNodes = ntohl(*reinterpret_cast<uint32_t*>(buf)); + uint32_t temp32; + in.read(reinterpret_cast<char*>(&temp32), sizeof(temp32)); + CHECK_STREAM(in, sizeof(temp32)); + uint32_t numNodes = ntohl(temp32); // 4bytes reserved - in.read(buf, 4); + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); // nodes + std::deque<SharedHandle<DHTNode> > nodes; for(size_t i = 0; i < numNodes; ++i) { // Currently, only IPv4 addresses are supported. // 1byte compact peer info length @@ -137,46 +176,59 @@ in >> peerInfoLen; if(peerInfoLen != 6) { // skip this entry - in.read(buf, 42+7+6); + readBytes(buf, buf.size(), in, 42+7+6); + CHECK_STREAM(in, 42+7+6); continue; } // 7bytes reserved - in.read(buf, 7); + readBytes(buf, buf.size(), in, 7); + CHECK_STREAM(in, 7); // 6bytes compact peer info - in.read(buf, 6); + readBytes(buf, buf.size(), in, 6); + CHECK_STREAM(in, 6); if(memcmp(zero, buf, 6) == 0) { // skip this entry - in.read(buf, 42); + readBytes(buf, buf.size(), in, 42); + CHECK_STREAM(in, 42); continue; } std::pair<std::string, uint16_t> peer = - PeerMessageUtil::unpackcompact(reinterpret_cast<const unsigned char*>(buf)); + PeerMessageUtil::unpackcompact(buf); if(peer.first.empty()) { // skip this entry - in.read(buf, 42); + readBytes(buf, buf.size(), in, 42); + CHECK_STREAM(in, 42); continue; } // 2bytes reserved - in.read(buf, 2); + readBytes(buf, buf.size(), in, 2); + CHECK_STREAM(in, 2); // 16byte reserved - in.read(buf, 16); + readBytes(buf, buf.size(), in, 16); + CHECK_STREAM(in, 16); // localnode ID - in.read(buf, DHT_ID_LENGTH); + readBytes(buf, buf.size(), in, DHT_ID_LENGTH); + CHECK_STREAM(in, DHT_ID_LENGTH); - SharedHandle<DHTNode> node(new DHTNode(reinterpret_cast<const unsigned char*>(buf))); + SharedHandle<DHTNode> node(new DHTNode(buf)); node->setIPAddress(peer.first); node->setPort(peer.second); // 4bytes reserved - in.read(buf, 4); + readBytes(buf, buf.size(), in, 4); + CHECK_STREAM(in, 4); - _nodes.push_back(node); + nodes.push_back(node); } _localNode = localNode; + _nodes = nodes; } catch(std::ios::failure const& exception) { _nodes.clear(); throw DlAbortEx (StringFormat("Failed to load DHT routing table. cause:%s", strerror(errno)).str()); + } catch(RecoverableException& e) { + _nodes.clear(); + throw; } } diff -ru aria2c-0.16.0-orig/src/FilesMetalinkParserState.cc aria2c-0.16.0/src/FilesMetalinkParserState.cc --- aria2c-0.16.0-orig/src/FilesMetalinkParserState.cc 2008-10-06 10:38:51.000000000 +0200 +++ aria2c-0.16.0/src/FilesMetalinkParserState.cc 2010-05-26 23:20:56.000000000 +0200 @@ -34,6 +34,7 @@ /* copyright --> */ #include "FilesMetalinkParserState.h" #include "MetalinkParserStateMachine.h" +#include "Util.h" namespace aria2 { @@ -50,6 +51,9 @@ std::map<std::string, std::string>::const_iterator itr = attrs.find(FilesMetalinkParserState::NAME); if(itr != attrs.end()) { + if((*itr).second.empty() || Util::detectDirTraversal((*itr).second)) { + return; + } stm->newEntryTransaction(); stm->setFileNameOfEntry((*itr).second); } diff -ru aria2c-0.16.0-orig/src/MetalinkParserController.cc aria2c-0.16.0/src/MetalinkParserController.cc --- aria2c-0.16.0-orig/src/MetalinkParserController.cc 2008-10-06 10:38:51.000000000 +0200 +++ aria2c-0.16.0/src/MetalinkParserController.cc 2010-05-26 23:20:56.000000000 +0200 @@ -46,6 +46,7 @@ #endif // ENABLE_MESSAGE_DIGEST #include "Signature.h" #include <algorithm> +#include "Util.h" namespace aria2 { @@ -78,9 +79,9 @@ return; } if(_tEntry->file.isNull()) { - _tEntry->file.reset(new FileEntry(filename, 0, 0)); + _tEntry->file.reset(new FileEntry(Util::escapePath(filename), 0, 0)); } else { - _tEntry->file->setPath(filename); + _tEntry->file->setPath(Util::escapePath(filename)); } } diff -ru aria2c-0.16.0-orig/src/Util.cc aria2c-0.16.0/src/Util.cc --- aria2c-0.16.0-orig/src/Util.cc 2008-10-06 10:38:51.000000000 +0200 +++ aria2c-0.16.0/src/Util.cc 2010-05-26 23:20:56.000000000 +0200 @@ -901,4 +901,55 @@ return std::pair<std::string, uint16_t>(host, atoi(service)); // TODO } +bool Util::detectDirTraversal(const std::string& s) +{ + for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) { + if(0x00 <= (*i) && (*i) <= 0x1f) { + return true; + } + } + return s == A2STR::DOT_C || + s == ".." || + Util::startsWith(s, A2STR::SLASH_C) || + Util::startsWith(s, "./") || + Util::startsWith(s, "../") || + s.find("/../") != std::string::npos || + s.find("/./") != std::string::npos || + Util::endsWith(s, "/") || + Util::endsWith(s, "/.") || + Util::endsWith(s, "/.."); +} + +namespace { +class EscapePath { +private: + char _repChar; +public: + EscapePath(const char& repChar):_repChar(repChar) {} + + char operator()(const char& c) { + if(0x00 <= c && c <=0x1f) { + return _repChar; + } +#ifdef __MINGW32__ + // We don't escape '/' because we use it as a path separator. + static const char WIN_INVALID_PATH_CHARS[] = + { '"', '*', ':', '<', '>', '?', '\\', '|' }; + if(std::find(vbegin(WIN_INVALID_PATH_CHARS), vend(WIN_INVALID_PATH_CHARS), + c) != vend(WIN_INVALID_PATH_CHARS)) { + return _repChar; + } +#endif // __MINGW32__ + return c; + } +}; +} + +std::string Util::escapePath(const std::string& s) +{ + std::string d = s; + std::transform(d.begin(), d.end(), d.begin(), EscapePath('_')); + return d; +} + } // namespace aria2 diff -ru aria2c-0.16.0-orig/src/Util.h aria2c-0.16.0/src/Util.h --- aria2c-0.16.0-orig/src/Util.h 2008-10-06 10:38:50.000000000 +0200 +++ aria2c-0.16.0/src/Util.h 2010-05-26 23:20:56.000000000 +0200 @@ -267,6 +267,16 @@ static std::pair<std::string, uint16_t> getNumericNameInfo(const struct sockaddr* sockaddr, socklen_t len); + + // Returns true if s contains directory traversal path component such + // as '..' or it contains null or control character which may fool + // user. + static bool detectDirTraversal(const std::string& s); + + // Replaces null(0x00) and control character(0x01-0x1f) with '_'. If + // __MINGW32__ is defined, following characters are also replaced with + // '_': '"', '*', ':', '<', '>', '?', '\', '|'. + static std::string escapePath(const std::string& s); }; } // namespace aria2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor