Explorar el Código

verify hash of input file in rred

We read the entire input file we want to patch anyhow, so we can also
calculate the hash for that file and compare it with what he had
expected it to be.

Note that this isn't really a security improvement as a) the file we
patch is trusted & b) if the input is incorrect, the result will hardly be
matching, so this is just for failing slightly earlier with a more
relevant error message (althrough, in terms of rred its ignored and
complete download attempt instead).
David Kalnischkies hace 10 años
padre
commit
6e71ec6fcd
Se han modificado 2 ficheros con 47 adiciones y 19 borrados
  1. 6 3
      apt-pkg/acquire-item.cc
  2. 41 16
      methods/rred.cc

+ 6 - 3
apt-pkg/acquire-item.cc

@@ -2616,9 +2616,10 @@ std::string pkgAcqIndexDiffs::Custom600Headers() const			/*{{{*/
    if(State != StateApplyDiff)
    if(State != StateApplyDiff)
       return pkgAcqBaseIndex::Custom600Headers();
       return pkgAcqBaseIndex::Custom600Headers();
    std::ostringstream patchhashes;
    std::ostringstream patchhashes;
-   HashStringList const ExpectedHashes = available_patches[0].patch_hashes;
-   for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs)
-      patchhashes <<  "\nPatch-0-" << hs->HashType() << "-Hash: " << hs->HashValue();
+   for (auto && hs : available_patches[0].result_hashes)
+      patchhashes <<  "\nStart-" << hs.HashType() << "-Hash: " << hs.HashValue();
+   for (auto && hs : available_patches[0].patch_hashes)
+      patchhashes <<  "\nPatch-0-" << hs.HashType() << "-Hash: " << hs.HashValue();
    patchhashes << pkgAcqBaseIndex::Custom600Headers();
    patchhashes << pkgAcqBaseIndex::Custom600Headers();
    return patchhashes.str();
    return patchhashes.str();
 }
 }
@@ -2765,6 +2766,8 @@ std::string pkgAcqIndexMergeDiffs::Custom600Headers() const		/*{{{*/
       return pkgAcqBaseIndex::Custom600Headers();
       return pkgAcqBaseIndex::Custom600Headers();
    std::ostringstream patchhashes;
    std::ostringstream patchhashes;
    unsigned int seen_patches = 0;
    unsigned int seen_patches = 0;
+   for (auto && hs : (*allPatches)[0]->patch.result_hashes)
+      patchhashes <<  "\nStart-" << hs.HashType() << "-Hash: " << hs.HashValue();
    for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
    for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
 	 I != allPatches->end(); ++I)
 	 I != allPatches->end(); ++I)
    {
    {

+ 41 - 16
methods/rred.cc

@@ -335,26 +335,30 @@ class Patch {
    FileChanges filechanges;
    FileChanges filechanges;
    MemBlock add_text;
    MemBlock add_text;
 
 
-   static bool retry_fwrite(char *b, size_t l, FileFd &f, Hashes *hash)
+   static bool retry_fwrite(char *b, size_t l, FileFd &f, Hashes * const start_hash, Hashes * const end_hash = nullptr)
    {
    {
       if (f.Write(b, l) == false)
       if (f.Write(b, l) == false)
 	 return false;
 	 return false;
-      if (hash)
-	 hash->Add((unsigned char*)b, l);
+      if (start_hash)
+	 start_hash->Add((unsigned char*)b, l);
+      if (end_hash)
+	 end_hash->Add((unsigned char*)b, l);
       return true;
       return true;
    }
    }
 
 
-   static void dump_rest(FileFd &o, FileFd &i, Hashes *hash)
+   static void dump_rest(FileFd &o, FileFd &i,
+	 Hashes * const start_hash, Hashes * const end_hash)
    {
    {
       char buffer[BLOCK_SIZE];
       char buffer[BLOCK_SIZE];
       unsigned long long l = 0;
       unsigned long long l = 0;
       while (i.Read(buffer, sizeof(buffer), &l)) {
       while (i.Read(buffer, sizeof(buffer), &l)) {
-	 if (l ==0  || !retry_fwrite(buffer, l, o, hash))
+	 if (l ==0  || !retry_fwrite(buffer, l, o, start_hash, end_hash))
 	    break;
 	    break;
       }
       }
    }
    }
 
 
-   static void dump_lines(FileFd &o, FileFd &i, size_t n, Hashes *hash)
+   static void dump_lines(FileFd &o, FileFd &i, size_t n,
+	 Hashes * const start_hash, Hashes * const end_hash)
    {
    {
       char buffer[BLOCK_SIZE];
       char buffer[BLOCK_SIZE];
       while (n > 0) {
       while (n > 0) {
@@ -363,11 +367,11 @@ class Patch {
 	 size_t const l = strlen(buffer);
 	 size_t const l = strlen(buffer);
 	 if (l == 0 || buffer[l-1] == '\n')
 	 if (l == 0 || buffer[l-1] == '\n')
 	    n--;
 	    n--;
-	 retry_fwrite(buffer, l, o, hash);
+	 retry_fwrite(buffer, l, o, start_hash, end_hash);
       }
       }
    }
    }
 
 
-   static void skip_lines(FileFd &i, int n)
+   static void skip_lines(FileFd &i, int n, Hashes * const start_hash)
    {
    {
       char buffer[BLOCK_SIZE];
       char buffer[BLOCK_SIZE];
       while (n > 0) {
       while (n > 0) {
@@ -376,6 +380,8 @@ class Patch {
 	 size_t const l = strlen(buffer);
 	 size_t const l = strlen(buffer);
 	 if (l == 0 || buffer[l-1] == '\n')
 	 if (l == 0 || buffer[l-1] == '\n')
 	    n--;
 	    n--;
+	 if (start_hash)
+	    start_hash->Add((unsigned char*)buffer, l);
       }
       }
    }
    }
 
 
@@ -525,15 +531,16 @@ class Patch {
       }
       }
    }
    }
 
 
-   void apply_against_file(FileFd &out, FileFd &in, Hashes *hash = NULL)
+   void apply_against_file(FileFd &out, FileFd &in,
+	 Hashes * const start_hash = nullptr, Hashes * const end_hash = nullptr)
    {
    {
       std::list<struct Change>::iterator ch;
       std::list<struct Change>::iterator ch;
       for (ch = filechanges.begin(); ch != filechanges.end(); ++ch) {
       for (ch = filechanges.begin(); ch != filechanges.end(); ++ch) {
-	 dump_lines(out, in, ch->offset, hash);
-	 skip_lines(in, ch->del_cnt);
-	 dump_mem(out, ch->add, ch->add_len, hash);
+	 dump_lines(out, in, ch->offset, start_hash, end_hash);
+	 skip_lines(in, ch->del_cnt, start_hash);
+	 dump_mem(out, ch->add, ch->add_len, end_hash);
       }
       }
-      dump_rest(out, in, hash);
+      dump_rest(out, in, start_hash, end_hash);
       out.Flush();
       out.Flush();
    }
    }
 };
 };
@@ -581,6 +588,16 @@ class RredMethod : public aptMethod {
 	 std::vector<PDiffFile> patchfiles;
 	 std::vector<PDiffFile> patchfiles;
 	 Patch patch;
 	 Patch patch;
 
 
+	 HashStringList StartHashes;
+	 for (char const * const * type = HashString::SupportedHashes(); *type != nullptr; ++type)
+	 {
+	    std::string tagname;
+	    strprintf(tagname, "Start-%s-Hash", *type);
+	    std::string const hashsum = LookupTag(Message, tagname.c_str());
+	    if (hashsum.empty() == false)
+	       StartHashes.push_back(HashString(*type, hashsum));
+	 }
+
 	 if (FileExists(Path + ".ed") == true)
 	 if (FileExists(Path + ".ed") == true)
 	 {
 	 {
 	    HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(0, Message);
 	    HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(0, Message);
@@ -653,8 +670,16 @@ class RredMethod : public aptMethod {
 	    return _error->Error("Failed to open out %s", Itm->DestFile.c_str());
 	    return _error->Error("Failed to open out %s", Itm->DestFile.c_str());
 	 }
 	 }
 
 
-	 Hashes hash(Itm->ExpectedHashes);
-	 patch.apply_against_file(out, inp, &hash);
+	 Hashes end_hash(Itm->ExpectedHashes);
+	 if (StartHashes.usable())
+	 {
+	    Hashes start_hash(StartHashes);
+	    patch.apply_against_file(out, inp, &start_hash, &end_hash);
+	    if (start_hash.GetHashStringList() != StartHashes)
+	       _error->Error("The input file hadn't the expected hash!");
+	 }
+	 else
+	    patch.apply_against_file(out, inp, nullptr, &end_hash);
 
 
 	 out.Close();
 	 out.Close();
 	 inp.Close();
 	 inp.Close();
@@ -685,7 +710,7 @@ class RredMethod : public aptMethod {
 
 
 	 Res.LastModified = bufbase.st_mtime;
 	 Res.LastModified = bufbase.st_mtime;
 	 Res.Size = bufbase.st_size;
 	 Res.Size = bufbase.st_size;
-	 Res.TakeHashes(hash);
+	 Res.TakeHashes(end_hash);
 	 URIDone(Res);
 	 URIDone(Res);
 
 
 	 return true;
 	 return true;