Przeglądaj źródła

Pass ExpectedSize to tthe backend method

This ensures that we can stop downloading if the server send
too much data by accident (or by a malicious attempt)
Michael Vogt 12 lat temu
rodzic
commit
dcd5856b11

+ 2 - 0
apt-pkg/acquire-method.cc

@@ -360,6 +360,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

+ 1 - 0
apt-pkg/acquire-method.h

@@ -48,6 +48,7 @@ class pkgAcqMethod
       bool IndexFile;
       bool FailIgnore;
       HashStringList ExpectedHashes;
+      unsigned long long ExpectedSize;
    };
    
    struct FetchResult

+ 4 - 0
apt-pkg/acquire-worker.cc

@@ -526,6 +526,9 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
    if (OutFd == -1)
       return false;
    
+   string ExpectedSize;
+   strprintf(ExpectedSize, "%llu", Item->Owner->FileSize);
+
    string Message = "600 URI Acquire\n";
    Message.reserve(300);
    Message += "URI: " + Item->URI;
@@ -533,6 +536,7 @@ 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();
+   Message += "\nExpected-Size: " + ExpectedSize;
    Message += Item->Owner->Custom600Headers();
    Message += "\n\n";
    

+ 9 - 1
methods/http.cc

@@ -63,7 +63,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();
@@ -79,6 +80,7 @@ void CircleBuf::Reset()
    InP = 0;
    OutP = 0;
    StrPos = 0;
+   TotalWriten = 0;
    MaxGet = (unsigned long long)-1;
    OutQueue = string();
    if (Hash != 0)
@@ -216,6 +218,8 @@ bool CircleBuf::Write(int Fd)
 	 
 	 return false;
       }
+
+      TotalWriten += Res;
       
       if (Hash != 0)
 	 Hash->Add(Buf + (OutP%Size),Res);
@@ -649,6 +653,10 @@ bool HttpServerState::Go(bool ToFile, FileFd * const File)
 	 return _error->Errno("write",_("Error writing to output file"));
    }
 
+   if (ExpectedSize > 0 && In.TotalWriten > ExpectedSize)
+      return _error->Error("Writing more data than expected (%llu > %llu)",
+                           In.TotalWriten, ExpectedSize);
+
    // Handle commands from APT
    if (FD_ISSET(STDIN_FILENO,&rfds))
    {

+ 3 - 1
methods/http.h

@@ -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);

+ 5 - 0
methods/server.cc

@@ -531,6 +531,11 @@ int ServerMethod::Loop()
 
 	    // 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);
 

+ 3 - 1
methods/server.h

@@ -49,6 +49,8 @@ struct ServerState
    URI Proxy;
    unsigned long TimeOut;
 
+   unsigned long long ExpectedSize;
+
    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; ExpectedSize = 0;};
    virtual bool WriteResponse(std::string const &Data) = 0;
 
    /** \brief Transfer the data from the socket */