]> git.saurik.com Git - apt.git/commitdiff
Merge branch 'feature/acq-trans' into feature/expected-size
authorMichael Vogt <mvo@ubuntu.com>
Tue, 7 Oct 2014 18:06:44 +0000 (20:06 +0200)
committerMichael Vogt <mvo@ubuntu.com>
Tue, 7 Oct 2014 18:06:44 +0000 (20:06 +0200)
13 files changed:
apt-pkg/acquire-method.cc
apt-pkg/acquire-method.h
apt-pkg/acquire-worker.cc
methods/ftp.cc
methods/ftp.h
methods/http.cc
methods/http.h
methods/https.cc
methods/https.h
methods/server.cc
methods/server.h
test/integration/test-apt-update-expected-size [new file with mode: 0755]
test/integration/test-cve-2013-1051-InRelease-parsing

index 82f2fb3ce091e51c9e11afe88f21bedc60bef096..9c0558223dfaa659a567d4bdba3082dc40a713b2 100644 (file)
@@ -372,6 +372,8 @@ int pkgAcqMethod::Run(bool Single)
               if (hash.empty() == false)
                  Tmp->ExpectedHashes.push_back(HashString(*t, hash));
            }
+            char *End;
+            Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10);
            Tmp->Next = 0;
            
            // Append it to the list
index cdeecc9a73983d602db3e304da750e6bcf9c7d3c..675c4f8448231d22f321e18b753a15e91332ddbe 100644 (file)
@@ -48,6 +48,10 @@ class pkgAcqMethod
       bool IndexFile;
       bool FailIgnore;
       HashStringList ExpectedHashes;
+      // a maximum size we will download, this can be the exact filesize
+      // for when we know it or a arbitrary limit when we don't know the
+      // filesize (like a InRelease file)
+      unsigned long long MaximumSize;
    };
    
    struct FetchResult
index 4a357bdab884df1e2e1e4f1e8ff0ab3bf5427fc7..64df3c80fe13456734c86ea1e5d94f1fd6f141a8 100644 (file)
@@ -534,6 +534,12 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
    HashStringList const hsl = Item->Owner->HashSums();
    for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
       Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
+   if(Item->Owner->FileSize > 0)
+   {
+      string MaximumSize;
+      strprintf(MaximumSize, "%llu", Item->Owner->FileSize);
+      Message += "\nMaximum-Size: " + MaximumSize;
+   }
    Message += Item->Owner->Custom600Headers();
    Message += "\n\n";
    
index ac76295f02ef1342e00dc7a0e9aac52fa38a77a5..bc84dda7dbf919f0b0464ebfad22d6f24e94c477 100644 (file)
@@ -849,7 +849,7 @@ bool FTPConn::Finalize()
 /* This opens a data connection, sends REST and RETR and then
    transfers the file over. */
 bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume,
-                 Hashes &Hash,bool &Missing)
+                 Hashes &Hash,bool &Missing, unsigned long long MaximumSize)
 {
    Missing = false;
    if (CreateDataFd() == false)
@@ -922,7 +922,11 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume,
       {
         Close();
         return false;
-      }      
+      }
+
+      if (MaximumSize > 0 && To.Tell() > MaximumSize)
+         return _error->Error("Writing more data than expected (%llu > %llu)",
+                              To.Tell(), MaximumSize);
    }
 
    // All done
@@ -1063,7 +1067,7 @@ bool FtpMethod::Fetch(FetchItem *Itm)
       FailFd = Fd.Fd();
       
       bool Missing;
-      if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing) == false)
+      if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing,Itm->MaximumSize) == false)
       {
         Fd.Close();
 
index dd92f0086e936043af045211f923ae0eccad9ceb..a31ebc999c8c2de5f9dc553f5de3b8fe7d1cac45 100644 (file)
@@ -62,7 +62,7 @@ class FTPConn
    bool Size(const char *Path,unsigned long long &Size);
    bool ModTime(const char *Path, time_t &Time);
    bool Get(const char *Path,FileFd &To,unsigned long long Resume,
-           Hashes &MD5,bool &Missing);
+           Hashes &MD5,bool &Missing, unsigned long long MaximumSize);
    
    FTPConn(URI Srv);
    ~FTPConn();
index f2a4a4db631add976bcbf36d329a57d45d3304a5..f8faa0cf8cbfff41be3a4867c3cc26936aa97a0b 100644 (file)
@@ -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,6 +81,7 @@ void CircleBuf::Reset()
    InP = 0;
    OutP = 0;
    StrPos = 0;
+   TotalWriten = 0;
    MaxGet = (unsigned long long)-1;
    OutQueue = string();
    if (Hash != 0)
@@ -217,6 +219,8 @@ bool CircleBuf::Write(int Fd)
         
         return false;
       }
+
+      TotalWriten += Res;
       
       if (Hash != 0)
         Hash->Add(Buf + (OutP%Size),Res);
@@ -651,6 +655,12 @@ bool HttpServerState::Go(bool ToFile, FileFd * const File)
         return _error->Errno("write",_("Error writing to output file"));
    }
 
+   if (MaximumSize > 0 && File && File->Tell() > MaximumSize)
+   {
+      return _error->Error("Writing more data than expected (%llu > %llu)",
+                           File->Tell(), MaximumSize);
+   }
+
    // Handle commands from APT
    if (FD_ISSET(STDIN_FILENO,&rfds))
    {
index 1df9fa07d68c60849d375cb3a7cc952b6c144625..40a88a7be03b3a8e254b981ca6711f833c8173e7 100644 (file)
@@ -63,6 +63,8 @@ class CircleBuf
 
    public:
    Hashes *Hash;
+   // total amount of data that got written so far
+   unsigned long long TotalWriten;
 
    // Read data in
    bool Read(int Fd);
@@ -81,8 +83,8 @@ class CircleBuf
    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);
index a74d2a38be4ba416ee7f1bfffbc1fdc3e43a9e0a..787e4a5075a99aaf180935f6380fab83fe5a63de 100644 (file)
@@ -82,6 +82,10 @@ HttpsMethod::write_data(void *buffer, size_t size, size_t nmemb, void *userp)
    if(me->File->Write(buffer, size*nmemb) != true)
       return false;
 
+   if(me->Queue->MaximumSize > 0 && me->File->Tell() > me->Queue->MaximumSize)
+      return _error->Error("Writing more data than expected (%llu > %llu)",
+                           me->TotalWritten, me->Queue->MaximumSize);
+
    return size*nmemb;
 }
 
index 45d1f7f63a94858731e3659fa0742e8fc0ec3622..0387cb9b579764c4615808531630ce4007698145 100644 (file)
@@ -66,11 +66,12 @@ class HttpsMethod : public pkgAcqMethod
    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), Server(NULL), TotalWritten(0), File(NULL)
    {
       curl = curl_easy_init();
    };
index 4a961f454df65bd152e29c75ed04afec920db620..82f9b4750b835fc72fb5bbe421e7b82fec5a0ef2 100644 (file)
@@ -532,6 +532,11 @@ int ServerMethod::Loop()
 
            // Run the data
            bool Result = true;
+
+            // ensure we don't fetch too much
+            if (Queue->MaximumSize > 0)
+               Server->MaximumSize = Queue->MaximumSize;
+
             if (Server->HaveContent)
               Result = Server->RunData(File);
 
@@ -605,7 +610,10 @@ int ServerMethod::Loop()
                  QueueBack = Queue;
               }
               else
+               {
+                  Server->Close();
                  Fail(true);
+               }
            }
            break;
         }
index aa692ea931ba5773a2dd8d4453916bfcb4793972..3093e00c99ba44f0218f12d3a0b0826b830f911f 100644 (file)
@@ -49,6 +49,8 @@ struct ServerState
    URI Proxy;
    unsigned long TimeOut;
 
+   unsigned long long MaximumSize;
+
    protected:
    ServerMethod *Owner;
 
@@ -73,7 +75,7 @@ struct ServerState
    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; MaximumSize = 0;};
    virtual bool WriteResponse(std::string const &Data) = 0;
 
    /** \brief Transfer the data from the socket */
diff --git a/test/integration/test-apt-update-expected-size b/test/integration/test-apt-update-expected-size
new file mode 100755 (executable)
index 0000000..c1eecc0
--- /dev/null
@@ -0,0 +1,34 @@
+#!/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
+
+# make InRelease really big
+mv aptarchive/dists/unstable/InRelease aptarchive/dists/unstable/InRelease.good
+dd if=/dev/zero of=aptarchive/dists/unstable/InRelease bs=1M count=2
+touch -d '+1hour' aptarchive/dists/unstable/InRelease
+aptget update -o acquire::MaxReleaseFileSize=$((1*1000*1000))
+
+
+# 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
+
index 41b27f6917c78b797ee2d40576608852dcfc47f1..8f980399157951776cb653fa9b63214d6d27acd8 100755 (executable)
@@ -42,7 +42,7 @@ touch -d '+1hour' aptarchive/dists/stable/InRelease
 # ensure the update fails
 # useful for debugging to add "-o Debug::pkgAcquire::auth=true"
 msgtest 'apt-get update for should fail with the modified' 'InRelease'
-aptget update 2>&1 | grep -q 'Hash Sum mismatch' > /dev/null && msgpass || msgfail
+aptget update 2>&1 | grep -E -q '(Writing more data than expected|Hash Sum mismatch)' > /dev/null && msgpass || msgfail
 
 # ensure there is no package
 testequal 'Reading package lists...