]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
merged from lp:~donkult/apt/sid
[apt.git] / apt-pkg / acquire-item.cc
index d4df31e85bc067f8267c340a48e929bac176ff46..39ce90ddae56d7f344ceabfb3955a01f4a316105 100644 (file)
@@ -17,7 +17,6 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/sourcelist.h>
-#include <apt-pkg/vendorlist.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
@@ -220,8 +219,8 @@ string pkgAcqSubIndex::Custom600Headers()
 
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+      return "\nIndex-File: true\nFail-Ignore: true\n";
+   return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
 void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)      /*{{{*/
@@ -272,6 +271,14 @@ void pkgAcqSubIndex::Done(string Message,unsigned long Size,string Md5Hash,        /*{{
 
    string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
 
+   /* Downloaded invalid transindex => Error (LP: #346386) (Closes: #627642) */
+   indexRecords SubIndexParser;
+   if (FileExists(DestFile) == true && !SubIndexParser.Load(DestFile)) {
+      Status = StatError;
+      ErrorText = SubIndexParser.ErrorText;
+      return;
+   }
+
    // sucess in downloading the index
    // rename the index
    if(Debug)
@@ -674,17 +681,17 @@ bool pkgAcqIndexDiffs::QueueNextDiff()                                    /*{{{*/
    // remove all patches until the next matching patch is found
    // this requires the Index file to be ordered
    for(vector<DiffInfo>::iterator I=available_patches.begin();
-       available_patches.size() > 0 && 
+       available_patches.empty() == false &&
          I != available_patches.end() &&
-         (*I).sha1 != local_sha1; 
-       I++) 
+         I->sha1 != local_sha1;
+       ++I)
    {
       available_patches.erase(I);
    }
 
    // error checking and falling back if no patch was found
-   if(available_patches.size() == 0) 
-   { 
+   if(available_patches.empty() == true)
+   {
       Failed("", NULL);
       return false;
    }
@@ -749,7 +756,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,       /*
       chmod(FinalFile.c_str(),0644);
 
       // see if there is more to download
-      if(available_patches.size() > 0) {
+      if(available_patches.empty() == false) {
         new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
                              ExpectedHash, ServerSha1, available_patches);
         return Finish();
@@ -835,10 +842,16 @@ string pkgAcqIndex::Custom600Headers()
    if (_config->FindB("Acquire::GzipIndexes",false))
       Final += ".gz";
    
+   string msg = "\nIndex-File: true";
+   // FIXME: this really should use "IndexTarget::IsOptional()" but that
+   //        seems to be difficult without breaking ABI
+   if (ShortDesc().find("Translation") != 0)
+      msg += "\nFail-Ignore: true";
    struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+   if (stat(Final.c_str(),&Buf) == 0)
+      msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+
+   return msg;
 }
                                                                        /*}}}*/
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
@@ -889,6 +902,30 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
         ReportMirrorFailure("HashChecksumFailure");
          return;
       }
+
+      /* Verify the index file for correctness (all indexes must
+       * have a Package field) (LP: #346386) (Closes: #627642) */
+      {
+        FileFd fd(DestFile, FileFd::ReadOnly);
+        pkgTagSection sec;
+        pkgTagFile tag(&fd);
+
+         // Only test for correctness if the file is not empty (empty is ok)
+         if (fd.Size() > 0) {
+            if (_error->PendingError() || !tag.Step(sec)) {
+               Status = StatError;
+               _error->DumpErrors();
+               Rename(DestFile,DestFile + ".FAILED");
+               return;
+            } else if (!sec.Exists("Package")) {
+               Status = StatError;
+               ErrorText = ("Encountered a section with no Package: header");
+               Rename(DestFile,DestFile + ".FAILED");
+               return;
+            }
+         }
+      }
+       
       // Done, move it into position
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
@@ -1002,8 +1039,8 @@ string pkgAcqIndexTrans::Custom600Headers()
 
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
-      return "\nFail-Ignore: true";
-   return "\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+      return "\nFail-Ignore: true\nIndex-File: true";
+   return "\nFail-Ignore: true\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
 // AcqIndexTrans::Failed - Silence failure messages for missing files  /*{{{*/
@@ -1221,7 +1258,8 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash, /*{{{*
       if (SigFile == "")
       {
          // There was no signature file, so we are finished.  Download
-         // the indexes without verification.
+         // the indexes and do only hashsum verification if possible
+         MetaIndexParser->Load(DestFile);
          QueueIndexes(false);
       }
       else
@@ -1325,37 +1363,45 @@ void pkgAcqMetaIndex::AuthDone(string Message)                          /*{{{*/
                                                                        /*}}}*/
 void pkgAcqMetaIndex::QueueIndexes(bool verify)                                /*{{{*/
 {
+#if 0
+   /* Reject invalid, existing Release files (LP: #346386) (Closes: #627642)
+    * FIXME: Disabled; it breaks unsigned repositories without hashes */
+   if (!verify && FileExists(DestFile) && !MetaIndexParser->Load(DestFile))
+   {
+      Status = StatError;
+      ErrorText = MetaIndexParser->ErrorText;
+      return;
+   }
+#endif
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
         Target != IndexTargets->end();
-        Target++)
+        ++Target)
    {
       HashString ExpectedIndexHash;
-      if (verify)
+      const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+      if (Record == NULL)
       {
-        const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
-        if (Record == NULL)
+        if (verify == true && (*Target)->IsOptional() == false)
         {
-           if ((*Target)->IsOptional() == false)
-           {
-              Status = StatAuthError;
-              strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
-              return;
-           }
+           Status = StatAuthError;
+           strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
+           return;
         }
-        else
+      }
+      else
+      {
+        ExpectedIndexHash = Record->Hash;
+        if (_config->FindB("Debug::pkgAcquire::Auth", false))
         {
-           ExpectedIndexHash = Record->Hash;
-           if (_config->FindB("Debug::pkgAcquire::Auth", false))
-           {
-              std::cerr << "Queueing: " << (*Target)->URI << std::endl;
-              std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
-           }
-           if (ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
-           {
-              Status = StatAuthError;
-              strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
-              return;
-           }
+           std::cerr << "Queueing: " << (*Target)->URI << std::endl;
+           std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
+           std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
+        }
+        if (verify == true && ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
+        {
+           Status = StatAuthError;
+           strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
+           return;
         }
       }
 
@@ -1384,29 +1430,6 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)                          /*{{{*/
                                                                        /*}}}*/
 bool pkgAcqMetaIndex::VerifyVendor(string Message)                     /*{{{*/
 {
-//    // Maybe this should be made available from above so we don't have
-//    // to read and parse it every time?
-//    pkgVendorList List;
-//    List.ReadMainList();
-
-//    const Vendor* Vndr = NULL;
-//    for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
-//    {
-//       string::size_type pos = (*I).find("VALIDSIG ");
-//       if (_config->FindB("Debug::Vendor", false))
-//          std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos 
-//                    << std::endl;
-//       if (pos != std::string::npos)
-//       {
-//          string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
-//          if (_config->FindB("Debug::Vendor", false))
-//             std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
-//                std::endl;
-//          Vndr = List.FindVendor(Fingerprint) != "";
-//          if (Vndr != NULL);
-//          break;
-//       }
-//    }
    string::size_type pos;
 
    // check for missing sigs (that where not fatal because otherwise we had
@@ -1449,8 +1472,10 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)                       /*{{{*/
         // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
         // the time since then the file is invalid - formated in the same way as in
         // the download progress display (e.g. 7d 3h 42min 1s)
-        return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
-                             RealURI.c_str(), TimeToStr(invalid_since).c_str());
+        return _error->Error(
+            _("Release file for %s is expired (invalid since %s). "
+              "Updates for this repository will not be applied."),
+            RealURI.c_str(), TimeToStr(invalid_since).c_str());
    }
 
    if (_config->FindB("Debug::pkgAcquire::Auth", false)) 
@@ -1511,6 +1536,12 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
                         LookupTag(Message,"Message").c_str());
         RunScripts("APT::Update::Auth-Failure");
         return;
+      } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
+        /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
+        _error->Error(_("GPG error: %s: %s"),
+                        Desc.Description.c_str(),
+                        LookupTag(Message,"Message").c_str());
+        return;
       } else {
         _error->Warning(_("GPG error: %s: %s"),
                         Desc.Description.c_str(),
@@ -1520,6 +1551,26 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       ReportMirrorFailure("GPGFailure");
    }
 
+   /* Always move the meta index, even if gpgv failed. This ensures
+    * that PackageFile objects are correctly filled in */
+   if (FileExists(DestFile)) {
+      string FinalFile = _config->FindDir("Dir::State::lists");
+      FinalFile += URItoFileName(RealURI);
+      /* InRelease files become Release files, otherwise
+       * they would be considered as trusted later on */
+      if (SigFile == DestFile) {
+        RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9,
+                                      "Release");
+        FinalFile = FinalFile.replace(FinalFile.rfind("InRelease"), 9,
+                                      "Release");
+        SigFile = FinalFile;
+      }
+      Rename(DestFile,FinalFile);
+      chmod(FinalFile.c_str(),0644);
+
+      DestFile = FinalFile;
+   }
+
    // No Release file was present, or verification failed, so fall
    // back to queueing Packages files without verification
    QueueIndexes(false);
@@ -1538,6 +1589,21 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,                /*{{{*/
    SigFile = DestFile;
 }
                                                                        /*}}}*/
+// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers        /*{{{*/
+// ---------------------------------------------------------------------
+// FIXME: this can go away once the InRelease file is used widely
+string pkgAcqMetaClearSig::Custom600Headers()
+{
+   string Final = _config->FindDir("Dir::State::lists");
+   Final += URItoFileName(RealURI);
+
+   struct stat Buf;
+   if (stat(Final.c_str(),&Buf) != 0)
+      return "\nIndex-File: true\nFail-Ignore: true\n";
+
+   return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+                                                                       /*}}}*/
 void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
 {
    if (AuthPass == false)
@@ -1604,7 +1670,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
 
    // check if we have one trusted source for the package. if so, switch
    // to "TrustedOnly" mode
-   for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; i++)
+   for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; ++i)
    {
       pkgIndexFile *Index;
       if (Sources->FindIndex(i.File(),Index) == false)
@@ -1628,7 +1694,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
 
    // Select a source
    if (QueueNext() == false && _error->PendingError() == false)
-      _error->Error(_("I wasn't able to locate file for the %s package. "
+      _error->Error(_("I wasn't able to locate file for the %s package. "
                    "This might mean you need to manually fix this package."),
                    Version.ParentPkg().Name());
 }
@@ -1641,7 +1707,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
 bool pkgAcqArchive::QueueNext()
 {
    string const ForceHash = _config->Find("Acquire::ForceHash");
-   for (; Vf.end() == false; Vf++)
+   for (; Vf.end() == false; ++Vf)
    {
       // Ignore not source sources
       if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
@@ -1752,7 +1818,7 @@ bool pkgAcqArchive::QueueNext()
       Desc.ShortDesc = Version.ParentPkg().Name();
       QueueURI(Desc);
 
-      Vf++;
+      ++Vf;
       return true;
    }
    return false;
@@ -1826,7 +1892,7 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
        StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
    {
       // Vf = Version.FileList();
-      while (Vf.end() == false) Vf++;
+      while (Vf.end() == false) ++Vf;
       StoreFilename = string();
       Item::Failed(Message,Cnf);
       return;