From: Michael Vogt Date: Mon, 6 Oct 2014 15:42:39 +0000 (+0200) Subject: make http size check work X-Git-Tag: 1.1.exp4~5^2~9 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/a2d40703e4a5590a689ace4466f92e590434944d?hp=-c make http size check work --- a2d40703e4a5590a689ace4466f92e590434944d diff --combined apt-pkg/acquire-method.cc index 9fc176747,82f2fb3ce..330854e75 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@@ -118,6 -118,18 +118,18 @@@ void pkgAcqMethod::Fail(string Err,boo std::cout << "\n" << std::flush; } + /*}}}*/ + // AcqMethod::DropPrivsOrDie - Drop privileges or die /*{{{*/ + // --------------------------------------------------------------------- + /* */ + void pkgAcqMethod::DropPrivsOrDie() + { + if (!DropPrivs()) { + Fail(false); + exit(112); /* call the european emergency number */ + } + } + /*}}}*/ // AcqMethod::URIStart - Indicate a download is starting /*{{{*/ // --------------------------------------------------------------------- @@@ -360,8 -372,6 +372,8 @@@ int pkgAcqMethod::Run(bool Single if (hash.empty() == false) Tmp->ExpectedHashes.push_back(HashString(*t, hash)); } + char *End; + Tmp->ExpectedSize = strtoll(LookupTag(Message, "Expected-Size", "0").c_str(), &End, 10); Tmp->Next = 0; // Append it to the list diff --combined apt-pkg/acquire-method.h index 8a680335e,cdeecc9a7..2e4e8281a --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@@ -48,7 -48,6 +48,7 @@@ class pkgAcqMetho bool IndexFile; bool FailIgnore; HashStringList ExpectedHashes; + unsigned long long ExpectedSize; }; struct FetchResult @@@ -106,7 -105,7 +106,7 @@@ pkgAcqMethod(const char *Ver,unsigned long Flags = 0); virtual ~pkgAcqMethod() {}; - + void DropPrivsOrDie(); private: APT_HIDDEN void Dequeue(); }; diff --combined methods/http.cc index 916fa464f,f2a4a4db6..b076e59cc --- a/methods/http.cc +++ b/methods/http.cc @@@ -34,6 -34,7 +34,7 @@@ #include #include #include + #include #include #include @@@ -63,8 -64,7 +64,8 @@@ const unsigned int CircleBuf::BW_HZ=10 // CircleBuf::CircleBuf - Circular input buffer /*{{{*/ // --------------------------------------------------------------------- /* */ -CircleBuf::CircleBuf(unsigned long long Size) : Size(Size), Hash(0) +CircleBuf::CircleBuf(unsigned long long Size) + : Size(Size), Hash(0), TotalWriten(0) { Buf = new unsigned char[Size]; Reset(); @@@ -80,7 -80,6 +81,7 @@@ void CircleBuf::Reset( InP = 0; OutP = 0; StrPos = 0; + TotalWriten = 0; MaxGet = (unsigned long long)-1; OutQueue = string(); if (Hash != 0) @@@ -218,8 -217,6 +219,8 @@@ bool CircleBuf::Write(int Fd return false; } + + TotalWriten += Res; if (Hash != 0) Hash->Add(Buf + (OutP%Size),Res); @@@ -308,6 -305,7 +309,7 @@@ bool HttpServerState::Open( Persistent = true; // Determine the proxy setting + AutoDetectProxy(ServerName); string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); if (!SpecificProxy.empty()) { @@@ -653,10 -651,6 +655,12 @@@ bool HttpServerState::Go(bool ToFile, F return _error->Errno("write",_("Error writing to output file")); } - if (ExpectedSize > 0 && In.TotalWriten > ExpectedSize) ++ if (ExpectedSize > 0 && File && File->Tell() > ExpectedSize) ++ { + return _error->Error("Writing more data than expected (%llu > %llu)", - In.TotalWriten, ExpectedSize); ++ File->Tell(), ExpectedSize); ++ } + // Handle commands from APT if (FD_ISSET(STDIN_FILENO,&rfds)) { @@@ -752,7 -746,7 +756,7 @@@ void HttpMethod::SendReq(FetchItem *Itm Req << "\r\n"; if (Debug == true) - cerr << Req << endl; + cerr << Req.str() << endl; Server->WriteResponse(Req.str()); } @@@ -770,66 -764,6 +774,6 @@@ bool HttpMethod::Configuration(string M PipelineDepth); Debug = _config->FindB("Debug::Acquire::http",false); - // Get the proxy to use - AutoDetectProxy(); - - return true; - } - /*}}}*/ - // HttpMethod::AutoDetectProxy - auto detect proxy /*{{{*/ - // --------------------------------------------------------------------- - /* */ - bool HttpMethod::AutoDetectProxy() - { - // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old - // name without the dash ("-") - AutoDetectProxyCmd = _config->Find("Acquire::http::Proxy-Auto-Detect", - _config->Find("Acquire::http::ProxyAutoDetect")); - - if (AutoDetectProxyCmd.empty()) - return true; - - if (Debug) - clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << endl; - - int Pipes[2] = {-1,-1}; - if (pipe(Pipes) != 0) - return _error->Errno("pipe", "Failed to create Pipe"); - - pid_t Process = ExecFork(); - if (Process == 0) - { - close(Pipes[0]); - dup2(Pipes[1],STDOUT_FILENO); - SetCloseExec(STDOUT_FILENO,false); - - const char *Args[2]; - Args[0] = AutoDetectProxyCmd.c_str(); - Args[1] = 0; - execv(Args[0],(char **)Args); - cerr << "Failed to exec method " << Args[0] << endl; - _exit(100); - } - char buf[512]; - int InFd = Pipes[0]; - close(Pipes[1]); - int res = read(InFd, buf, sizeof(buf)-1); - ExecWait(Process, "ProxyAutoDetect", true); - - if (res < 0) - return _error->Errno("read", "Failed to read"); - if (res == 0) - return _error->Warning("ProxyAutoDetect returned no data"); - - // add trailing \0 - buf[res] = 0; - - if (Debug) - clog << "auto detect command returned: '" << buf << "'" << endl; - - if (strstr(buf, "http://") == buf) - _config->Set("Acquire::http::proxy", _strstrip(buf)); - return true; } /*}}}*/ diff --combined methods/http.h index c98fe8e5f,1df9fa07d..40a88a7be --- a/methods/http.h +++ b/methods/http.h @@@ -63,8 -63,6 +63,8 @@@ class CircleBu public: Hashes *Hash; + // total amount of data that got written so far + unsigned long long TotalWriten; // Read data in bool Read(int Fd); @@@ -83,8 -81,8 +83,8 @@@ bool ReadSpace() const {return Size - (InP - OutP) > 0;}; bool WriteSpace() const {return InP - OutP > 0;}; - // Dump everything void Reset(); + // Dump everything void Stats(); CircleBuf(unsigned long long Size); @@@ -126,9 -124,6 +126,6 @@@ class HttpMethod : public ServerMetho public: virtual void SendReq(FetchItem *Itm); - /** \brief Try to AutoDetect the proxy */ - bool AutoDetectProxy(); - virtual bool Configuration(std::string Message); virtual ServerState * CreateServerState(URI uri); diff --combined methods/https.cc index cacd8a6bc,a74d2a38b..eec858417 --- a/methods/https.cc +++ b/methods/https.cc @@@ -20,6 -20,7 +20,7 @@@ #include #include #include + #include #include #include @@@ -81,12 -82,6 +82,12 @@@ HttpsMethod::write_data(void *buffer, s if(me->File->Write(buffer, size*nmemb) != true) return false; + me->TotalWritten += size*nmemb; + if(me->TotalWritten > me->Queue->ExpectedSize) + return _error->Error("Writing more data than expected (%llu > %llu)", + me->TotalWritten, me->Queue->ExpectedSize); + + return size*nmemb; } @@@ -113,6 -108,9 +114,9 @@@ void HttpsMethod::SetupProxy() /* { URI ServerName = Queue->Uri; + // Determine the proxy setting + AutoDetectProxy(ServerName); + // Curl should never read proxy settings from the environment, as // we determine which proxy to use. Do this for consistency among // methods and prevent an environment variable overriding a @@@ -448,6 -446,8 +452,8 @@@ int main( HttpsMethod Mth; curl_global_init(CURL_GLOBAL_SSL) ; + Mth.DropPrivsOrDie(); + return Mth.Run(); } diff --combined methods/https.h index 2335559fb,45d1f7f63..0387cb9b5 --- a/methods/https.h +++ b/methods/https.h @@@ -66,14 -66,12 +66,13 @@@ class HttpsMethod : public pkgAcqMetho CURL *curl; FetchResult Res; HttpsServerState *Server; + unsigned long long TotalWritten; public: FileFd *File; - - HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), File(NULL) + - HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), TotalWritten(0), File(NULL) ++ HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), TotalWritten(0), File(NULL) { - File = 0; curl = curl_easy_init(); }; diff --combined methods/server.cc index 1b6511c59,4a961f454..223737901 --- a/methods/server.cc +++ b/methods/server.cc @@@ -44,7 -44,8 +44,8 @@@ time_t ServerMethod::FailTime = 0 // --------------------------------------------------------------------- /* Returns 0 if things are OK, 1 if an IO error occurred and 2 if a header parse error occurred */ - ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File) + ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File, + const std::string &Uri) { State = Header; @@@ -66,7 -67,7 +67,7 @@@ continue; if (Owner->Debug == true) - clog << Data; + clog << "Answer for: " << Uri << endl << Data; for (string::const_iterator I = Data.begin(); I < Data.end(); ++I) { @@@ -323,10 -324,10 +324,10 @@@ ServerMethod::DealWithHeaders(FetchResu failure */ if (Server->Result < 200 || Server->Result >= 300) { - char err[255]; - snprintf(err,sizeof(err)-1,"HttpError%i",Server->Result); + std::string err; + strprintf(err, "HttpError%u", Server->Result); SetFailReason(err); - _error->Error("%u %s",Server->Result,Server->Code); + _error->Error("%u %s", Server->Result, Server->Code); if (Server->HaveContent == true) return ERROR_WITH_CONTENT_PAGE; return ERROR_UNRECOVERABLE; @@@ -485,7 -486,7 +486,7 @@@ int ServerMethod::Loop( Fetch(0); // Fetch the next URL header data from the server. - switch (Server->RunHeaders(File)) + switch (Server->RunHeaders(File, Queue->Uri)) { case ServerState::RUN_HEADERS_OK: break; @@@ -531,11 -532,6 +532,11 @@@ // Run the data bool Result = true; + + // ensure we don't fetch too much + if (Queue->ExpectedSize > 0) + Server->ExpectedSize = Queue->ExpectedSize; + if (Server->HaveContent) Result = Server->RunData(File); @@@ -609,7 -605,7 +610,10 @@@ QueueBack = Queue; } else ++ { ++ Server->Close(); Fail(true); ++ } } break; } diff --combined methods/server.h index 0d7333140,aa692ea93..0134a9538 --- a/methods/server.h +++ b/methods/server.h @@@ -49,8 -49,6 +49,8 @@@ struct ServerStat URI Proxy; unsigned long TimeOut; + unsigned long long ExpectedSize; + protected: ServerMethod *Owner; @@@ -70,12 -68,12 +70,12 @@@ RUN_HEADERS_PARSE_ERROR }; /** \brief Get the headers before the data */ - RunHeadersResult RunHeaders(FileFd * const File); + RunHeadersResult RunHeaders(FileFd * const File, const std::string &Uri); bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;}; virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0; StartPos = 0; Encoding = Closes; time(&Date); HaveContent = false; - State = Header; Persistent = false; Pipeline = true;}; + State = Header; Persistent = false; Pipeline = true; ExpectedSize = 0;}; virtual bool WriteResponse(std::string const &Data) = 0; /** \brief Transfer the data from the socket */ diff --combined test/integration/test-apt-update-expected-size index 000000000,000000000..72812336d new file mode 100755 --- /dev/null +++ b/test/integration/test-apt-update-expected-size @@@ -1,0 -1,0 +1,27 @@@ ++#!/bin/sh ++set -e ++ ++TESTDIR=$(readlink -f $(dirname $0)) ++. $TESTDIR/framework ++ ++setupenvironment ++configarchitecture "i386" ++ ++insertpackage 'unstable' 'apt' 'all' '1.0' ++ ++setupaptarchive --no-update ++changetowebserver ++ ++# normal update works fine ++testsuccess aptget update ++ ++# append junk at the end of the Packages.gz/Packages ++SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" ++echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages.gz ++echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages ++NEW_SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" ++rm -f rootdir/var/lib/apt/lists/localhost* ++testequal "W: Failed to fetch http://localhost:8080/dists/unstable/main/binary-i386/Packages Writing more data than expected ($NEW_SIZE > $SIZE) [IP: ::1 8080] ++ ++E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq ++