summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorMichael Vogt <mvo@ubuntu.com>2014-09-16 20:23:43 +0200
committerMichael Vogt <mvo@ubuntu.com>2014-09-16 20:39:13 +0200
commitca7fd76c2f30c100dcf1c12e717ce397cccd690b (patch)
tree70a49859068972ec03c8c70d581135ee4e1a9c7f /apt-pkg
parent13fe505ceed4cee05667c05cf07896386310ebbc (diff)
SECURITY UPDATE for CVE-2014-{0488,0487,0489}
incorrect invalidating of unauthenticated data (CVE-2014-0488) incorect verification of 304 reply (CVE-2014-0487) incorrect verification of Acquire::Gzip indexes (CVE-2014-0489)
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc97
-rw-r--r--apt-pkg/acquire-item.h8
-rw-r--r--apt-pkg/contrib/fileutl.h2
3 files changed, 85 insertions, 22 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 6cb9b012a..058b8bf74 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -1021,6 +1021,31 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
Item::Failed(Message,Cnf);
}
/*}}}*/
+// pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/
+std::string pkgAcqIndex::GetFinalFilename(std::string const &URI,
+ std::string const &compExt)
+{
+ std::string FinalFile = _config->FindDir("Dir::State::lists");
+ FinalFile += URItoFileName(URI);
+ if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+ FinalFile += ".gz";
+ return FinalFile;
+}
+ /*}}}*/
+// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/
+void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName)
+{
+ std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
+ if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+ DestFile += ".gz";
+
+ string FinalFile = GetFinalFilename(RealURI, compExt);
+ Rename(FinalFile, FileName);
+ Decompression = true;
+ Desc.URI = "copy:" + FileName;
+ QueueURI(Desc);
+}
+ /*}}}*/
// AcqIndex::Done - Finished a fetch /*{{{*/
// ---------------------------------------------------------------------
/* This goes through a number of states.. On the initial fetch the
@@ -1032,6 +1057,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
pkgAcquire::MethodConfig *Cfg)
{
Item::Done(Message,Size,Hash,Cfg);
+ std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
if (Decompression == true)
{
@@ -1043,6 +1069,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
{
+ Desc.URI = RealURI;
RenameOnError(HashSumMismatch);
return;
}
@@ -1053,9 +1080,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
/* Always verify the index file for correctness (all indexes must
* have a Package field) (LP: #346386) (Closes: #627642)
*/
- FileFd fd(DestFile, FileFd::ReadOnly);
+ FileFd fd(DestFile, FileFd::ReadOnlyGzip);
// Only test for correctness if the file is not empty (empty is ok)
- if (fd.FileSize() > 0)
+ if (fd.Size() > 0)
{
pkgTagSection sec;
pkgTagFile tag(&fd);
@@ -1069,8 +1096,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
}
// Done, move it into position
- string FinalFile = _config->FindDir("Dir::State::lists");
- FinalFile += URItoFileName(RealURI);
+ string FinalFile = GetFinalFilename(RealURI, compExt);
Rename(DestFile,FinalFile);
chmod(FinalFile.c_str(),0644);
@@ -1078,7 +1104,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
will work OK */
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
DestFile += URItoFileName(RealURI);
-
+ if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+ DestFile += ".gz";
+
// Remove the compressed version.
if (Erase == true)
unlink(DestFile.c_str());
@@ -1094,7 +1122,10 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
{
// The files timestamp matches
if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
- return;
+ {
+ ReverifyAfterIMS(FileName);
+ return;
+ }
Decompression = true;
Local = true;
DestFile += ".decomp";
@@ -1111,15 +1142,12 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
ErrorText = "Method gave a blank filename";
}
- std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
-
// The files timestamp matches
- if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) {
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
- // Update DestFile for .gz suffix so that the clean operation keeps it
- DestFile += ".gz";
+ if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+ {
+ ReverifyAfterIMS(FileName);
return;
- }
+ }
if (FileName == DestFile)
Erase = true;
@@ -1128,16 +1156,16 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
string decompProg;
- // If we enable compressed indexes and already have gzip, keep it
- if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) {
- string FinalFile = _config->FindDir("Dir::State::lists");
- FinalFile += URItoFileName(RealURI) + ".gz";
- Rename(DestFile,FinalFile);
- chmod(FinalFile.c_str(),0644);
-
- // Update DestFile for .gz suffix so that the clean operation keeps it
- DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ // If we enable compressed indexes, queue for hash verification
+ if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local)
+ {
+ DestFile = _config->FindDir("Dir::State::lists");
DestFile += URItoFileName(RealURI) + ".gz";
+
+ Decompression = true;
+ Desc.URI = "copy:" + FileName;
+ QueueURI(Desc);
+
return;
}
@@ -1181,6 +1209,9 @@ string pkgAcqIndexTrans::Custom600Headers()
string Final = _config->FindDir("Dir::State::lists");
Final += URItoFileName(RealURI);
+ if (_config->FindB("Acquire::GzipIndexes",false))
+ Final += ".gz";
+
struct stat Buf;
if (stat(Final.c_str(),&Buf) != 0)
return "\nFail-Ignore: true\nIndex-File: true";
@@ -1510,6 +1541,28 @@ void pkgAcqMetaIndex::AuthDone(string Message) /*{{{*/
std::cerr << "Signature verification succeeded: "
<< DestFile << std::endl;
+ // do not trust any previously unverified content that we may have
+ string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI));
+ if (DestFile != SigFile)
+ LastGoodSigFile.append(".gpg");
+ LastGoodSigFile.append(".reverify");
+ if(IMSHit == false && RealFileExists(LastGoodSigFile) == false)
+ {
+ for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+ Target != IndexTargets->end();
+ ++Target)
+ {
+ // remove old indexes
+ std::string index = _config->FindDir("Dir::State::lists") +
+ URItoFileName((*Target)->URI);
+ unlink(index.c_str());
+ // and also old gzipindexes
+ index += ".gz";
+ unlink(index.c_str());
+ }
+ }
+
+
// Download further indexes with verification
QueueIndexes(true);
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index 06537bf2c..384c5ee2b 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -706,6 +706,14 @@ class pkgAcqIndex : public pkgAcquire::Item
*/
std::string CompressionExtension;
+ /** \brief Get the full pathname of the final file for the given URI
+ */
+ std::string GetFinalFilename(std::string const &URI,
+ std::string const &compExt);
+
+ /** \brief Schedule file for verification after a IMS hit */
+ void ReverifyAfterIMS(std::string const &FileName);
+
public:
// Specialized action members
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index cc1a98eae..667057067 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -85,7 +85,9 @@ class FileFd
bool Skip(unsigned long long To);
bool Truncate(unsigned long long To);
unsigned long long Tell();
+ // the size of the file content (compressed files will be uncompressed first)
unsigned long long Size();
+ // the size of the file itself
unsigned long long FileSize();
time_t ModificationTime();