Просмотр исходного кода

- try downloading clearsigned InRelease before trying Release.gpg
* apt-pkg/deb/deblistparser.cc:
- rewrite LoadReleaseInfo to cope with clearsigned Releasefiles

David Kalnischkies лет назад: 15
Родитель
Сommit
fe0f7911b6

+ 49 - 5
apt-pkg/acquire-item.cc

@@ -1077,6 +1077,8 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,	/*{{{*
    {
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+	 SigFile = FinalFile;
       Rename(DestFile,FinalFile);
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
       chmod(FinalFile.c_str(),0644);
       DestFile = FinalFile;
       DestFile = FinalFile;
@@ -1110,6 +1112,8 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)			/*{{{*/
    {
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+	 SigFile = FinalFile;
       DestFile = FinalFile;
       DestFile = FinalFile;
    }
    }
    Complete = true;
    Complete = true;
@@ -1141,6 +1145,10 @@ void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
    // Download further indexes with verification
    // Download further indexes with verification
    QueueIndexes(true);
    QueueIndexes(true);
 
 
+   // is it a clearsigned MetaIndex file?
+   if (DestFile == SigFile)
+      return;
+
    // Done, move signature file into position
    // Done, move signature file into position
    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
       URItoFileName(RealURI) + ".gpg";
       URItoFileName(RealURI) + ".gpg";
@@ -1300,13 +1308,20 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    if (AuthPass == true)
    if (AuthPass == true)
    {
    {
       // gpgv method failed, if we have a good signature 
       // gpgv method failed, if we have a good signature 
-      string LastGoodSigFile = _config->FindDir("Dir::State::lists") +
-	 "partial/" + URItoFileName(RealURI) + ".gpg.reverify";
+      string LastGoodSigFile = _config->FindDir("Dir::State::lists");
+      if (DestFile == SigFile)
+	 LastGoodSigFile.append(URItoFileName(RealURI));
+      else
+	 LastGoodSigFile.append("partial/").append(URItoFileName(RealURI)).append(".gpg.reverify");
+
       if(FileExists(LastGoodSigFile))
       if(FileExists(LastGoodSigFile))
       {
       {
-	 string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-	    URItoFileName(RealURI) + ".gpg";
-	 Rename(LastGoodSigFile,VerifiedSigFile);
+	 if (DestFile != SigFile)
+	 {
+	    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+					URItoFileName(RealURI) + ".gpg";
+	    Rename(LastGoodSigFile,VerifiedSigFile);
+	 }
 	 Status = StatTransientNetworkError;
 	 Status = StatTransientNetworkError;
 	 _error->Warning(_("A error occurred during the signature "
 	 _error->Warning(_("A error occurred during the signature "
 			   "verification. The repository is not updated "
 			   "verification. The repository is not updated "
@@ -1330,6 +1345,35 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    QueueIndexes(false);
    QueueIndexes(false);
 }
 }
 									/*}}}*/
 									/*}}}*/
+pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,		/*{{{*/
+		string const &URI, string const &URIDesc, string const &ShortDesc,
+		string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
+		string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
+		const vector<struct IndexTarget*>* IndexTargets,
+		indexRecords* MetaIndexParser) :
+	pkgAcqMetaIndex(Owner, URI, URIDesc, ShortDesc, "", IndexTargets, MetaIndexParser),
+	MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
+	MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc)
+{
+   SigFile = DestFile;
+}
+									/*}}}*/
+void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
+{
+   if (AuthPass == false)
+   {
+      new pkgAcqMetaSig(Owner,
+			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
+			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
+			IndexTargets, MetaIndexParser);
+      if (Cnf->LocalOnly == true ||
+	  StringToBool(LookupTag(Message, "Transient-Failure"), false) == false)
+	 Dequeue();
+   }
+   else
+      pkgAcqMetaIndex::Failed(Message, Cnf);
+}
+									/*}}}*/
 // AcqArchive::AcqArchive - Constructor					/*{{{*/
 // AcqArchive::AcqArchive - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This just sets up the initial fetch environment and queues the first
 /* This just sets up the initial fetch environment and queues the first

+ 33 - 0
apt-pkg/acquire-item.h

@@ -772,6 +772,39 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
 		   indexRecords* MetaIndexParser);
 		   indexRecords* MetaIndexParser);
 };
 };
 									/*}}}*/
 									/*}}}*/
+/** \brief An item repsonsible for downloading clearsigned metaindexes	{{{*/
+class pkgAcqMetaClearSig : public pkgAcqMetaIndex
+{
+   /** \brief The URI of the meta-index file for the detached signature */
+   string MetaIndexURI;
+
+   /** \brief A "URI-style" description of the meta-index file */
+   string MetaIndexURIDesc;
+
+   /** \brief A brief description of the meta-index file */
+   string MetaIndexShortDesc;
+
+   /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */
+   string MetaSigURI;
+
+   /** \brief A "URI-style" description of the meta-signature file */
+   string MetaSigURIDesc;
+
+   /** \brief A brief description of the meta-signature file */
+   string MetaSigShortDesc;
+
+public:
+   void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Create a new pkgAcqMetaClearSig. */
+   pkgAcqMetaClearSig(pkgAcquire *Owner,
+		string const &URI, string const &URIDesc, string const &ShortDesc,
+		string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
+		string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
+		const vector<struct IndexTarget*>* IndexTargets,
+		indexRecords* MetaIndexParser);
+};
+									/*}}}*/
 /** \brief An item that is responsible for fetching a package file.	{{{
 /** \brief An item that is responsible for fetching a package file.	{{{
  *
  *
  *  If the package file already exists in the cache, nothing will be
  *  If the package file already exists in the cache, nothing will be

+ 7 - 1
apt-pkg/deb/debindexfile.cc

@@ -324,8 +324,14 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
 
 
    // Check the release file
    // Check the release file
-   string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
+   string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
+   bool releaseExists = false;
    if (FileExists(ReleaseFile) == true)
    if (FileExists(ReleaseFile) == true)
+      releaseExists = true;
+   else
+      ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
+
+   if (releaseExists == true || FileExists(ReleaseFile) == true)
    {
    {
       FileFd Rel(ReleaseFile,FileFd::ReadOnly);
       FileFd Rel(ReleaseFile,FileFd::ReadOnly);
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)

+ 79 - 35
apt-pkg/deb/deblistparser.cc

@@ -783,45 +783,89 @@ bool debListParser::Step()
 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 				    FileFd &File, string component)
 				    FileFd &File, string component)
 {
 {
-   pkgTagFile Tags(&File, File.Size() + 256); // XXX
-   pkgTagSection Section;
-   if (Tags.Step(Section) == false)
-      return false;
-
-   // FIXME: Do we need it now for multi-arch?
-   // mvo: I don't think we need to fill that in (it's unused since apt-0.6)
-//    FileI->Architecture = WriteUniqString(Arch);
-   
    // apt-secure does no longer download individual (per-section) Release
    // apt-secure does no longer download individual (per-section) Release
    // file. to provide Component pinning we use the section name now
    // file. to provide Component pinning we use the section name now
    FileI->Component = WriteUniqString(component);
    FileI->Component = WriteUniqString(component);
 
 
-   const char *Start;
-   const char *Stop;
-   if (Section.Find("Suite",Start,Stop) == true)
-      FileI->Archive = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Component",Start,Stop) == true)
-      FileI->Component = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Version",Start,Stop) == true)
-      FileI->Version = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Origin",Start,Stop) == true)
-      FileI->Origin = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Codename",Start,Stop) == true)
-      FileI->Codename = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Label",Start,Stop) == true)
-      FileI->Label = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Architecture",Start,Stop) == true)
-      FileI->Architecture = WriteUniqString(Start,Stop - Start);
-   
-   if (Section.FindFlag("NotAutomatic",FileI->Flags,
-			pkgCache::Flag::NotAutomatic) == false)
-      _error->Warning("Bad NotAutomatic flag");
-   if (Section.FindFlag("ButAutomaticUpgrades",FileI->Flags,
-			pkgCache::Flag::ButAutomaticUpgrades) == false)
-      _error->Warning("Bad ButAutomaticUpgrades flag");
-   // overrule the NotAutomatic setting if needed as they are both present for compatibility
-   else if ((FileI->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades)
-      FileI->Flags &= ~pkgCache::Flag::NotAutomatic;
+   FILE* release = fdopen(dup(File.Fd()), "r");
+   if (release == NULL)
+      return false;
+
+   char buffer[101];
+   bool gpgClose = false;
+   while (fgets(buffer, sizeof(buffer), release) != NULL)
+   {
+      size_t len = 0;
+
+      // Skip empty lines
+      for (; buffer[len] == '\r' && buffer[len] == '\n'; ++len);
+      if (buffer[len] == '\0')
+	 continue;
+
+      // only evalute the first GPG section
+      if (strncmp("-----", buffer, 5) == 0)
+      {
+	 if (gpgClose == true)
+	    break;
+	 gpgClose = true;
+	 continue;
+      }
+
+      // seperate the tag from the data
+      for (; buffer[len] != ':' && buffer[len] != '\0'; ++len);
+      if (buffer[len] == '\0')
+	 continue;
+      char* dataStart = buffer + len;
+      for (++dataStart; *dataStart == ' '; ++dataStart);
+      char* dataEnd = dataStart;
+      for (++dataEnd; *dataEnd != '\0'; ++dataEnd);
+
+      // which datastorage need to be updated
+      map_ptrloc* writeTo = NULL;
+      if (buffer[0] == ' ')
+	 ;
+      #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
+      APT_PARSER_WRITETO(FileI->Archive, "Suite")
+      APT_PARSER_WRITETO(FileI->Component, "Component")
+      APT_PARSER_WRITETO(FileI->Version, "Version")
+      APT_PARSER_WRITETO(FileI->Origin, "Origin")
+      APT_PARSER_WRITETO(FileI->Codename, "Codename")
+      APT_PARSER_WRITETO(FileI->Label, "Label")
+      #undef APT_PARSER_WRITETO
+      #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
+	 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
+      APT_PARSER_FLAGIT(NotAutomatic)
+      APT_PARSER_FLAGIT(ButAutomaticUpgrades)
+      #undef APT_PARSER_FLAGIT
+
+      // load all data from the line and save it
+      string data;
+      if (writeTo != NULL)
+	 data.append(dataStart, dataEnd);
+      if (sizeof(buffer) - 1 == (dataEnd - buffer))
+      {
+	 while (fgets(buffer, sizeof(buffer), release) != NULL)
+	 {
+	    if (writeTo != NULL)
+	       data.append(buffer);
+	    if (strlen(buffer) != sizeof(buffer) - 1)
+	       break;
+	 }
+      }
+      if (writeTo != NULL)
+      {
+	 // remove spaces and stuff from the end of the data line
+	 for (std::string::reverse_iterator s = data.rbegin();
+	      s != data.rend(); ++s)
+	 {
+	    if (*s != '\r' && *s != '\n' && *s != ' ')
+	       break;
+	    *s = '\0';
+	 }
+	 *writeTo = WriteUniqString(data);
+      }
+   }
+   fclose(release);
 
 
    return !_error->PendingError();
    return !_error->PendingError();
 }
 }

+ 16 - 18
apt-pkg/deb/debmetaindex.cc

@@ -182,21 +182,15 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 			 (*Target)->ShortDesc, HashString());
 			 (*Target)->ShortDesc, HashString());
       }
       }
-      // this is normally created in pkgAcqMetaSig, but if we run
-      // in --print-uris mode, we add it here
-      new pkgAcqMetaIndex(Owner, MetaIndexURI("Release"),
-		     MetaIndexInfo("Release"), "Release",
-		     MetaIndexURI("Release.gpg"), 
-		     ComputeIndexTargets(),
-		     new indexRecords (Dist));
-
    }
    }
 
 
-   new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"),
-		     MetaIndexInfo("Release.gpg"), "Release.gpg",
-		     MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
-		     ComputeIndexTargets(),
-		     new indexRecords (Dist));
+	new pkgAcqMetaClearSig(Owner, MetaIndexURI("InRelease"),
+		MetaIndexInfo("InRelease"), "InRelease",
+		MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
+		MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
+		ComputeIndexTargets(),
+		new indexRecords (Dist));
+
 
 
 	// Queue the translations
 	// Queue the translations
 	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
 	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
@@ -224,16 +218,20 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 
 
 bool debReleaseIndex::IsTrusted() const
 bool debReleaseIndex::IsTrusted() const
 {
 {
-   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-      URItoFileName(MetaIndexURI("Release")) + ".gpg";
-   
    if(_config->FindB("APT::Authentication::TrustCDROM", false))
    if(_config->FindB("APT::Authentication::TrustCDROM", false))
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
 	 return true;
 	 return true;
-   
+
+   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("Release")) + ".gpg";
+
    if (FileExists(VerifiedSigFile))
    if (FileExists(VerifiedSigFile))
       return true;
       return true;
-   return false;
+
+   VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("InRelease"));
+
+   return FileExists(VerifiedSigFile);
 }
 }
 
 
 vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {
 vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {

+ 2 - 1
apt-pkg/indexcopy.cc

@@ -722,7 +722,8 @@ bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG,
    }
    }
 
 
    Args.push_back(FileGPG.c_str());
    Args.push_back(FileGPG.c_str());
-   Args.push_back(File.c_str());
+   if (FileGPG != File)
+      Args.push_back(File.c_str());
    Args.push_back(NULL);
    Args.push_back(NULL);
 
 
    if (Debug == true)
    if (Debug == true)

+ 10 - 7
apt-pkg/indexrecords.cc

@@ -55,14 +55,17 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
    }
    }
 
 
    pkgTagSection Section;
    pkgTagSection Section;
-   if (TagFile.Step(Section) == false)
-   {
-      strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
-      return false;
-   }
-
    const char *Start, *End;
    const char *Start, *End;
-   Section.Get (Start, End, 0);
+   // Skip over sections beginning with ----- as this is an idicator for clearsigns
+   do {
+      if (TagFile.Step(Section) == false)
+      {
+	 strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
+	 return false;
+      }
+
+      Section.Get (Start, End, 0);
+   } while (End - Start > 5 && strncmp(Start, "-----", 5) == 0);
 
 
    Suite = Section.FindS("Suite");
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");
    Dist = Section.FindS("Codename");

+ 7 - 3
apt-pkg/tagfile.cc

@@ -399,9 +399,13 @@ bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
    const char *Stop;
    const char *Stop;
    if (Find(Tag,Start,Stop) == false)
    if (Find(Tag,Start,Stop) == false)
       return true;
       return true;
-   
-   switch (StringToBool(string(Start,Stop)))
-   {     
+   return FindFlag(Flags, Flag, Start, Stop);
+}
+bool const pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
+					char const* Start, char const* Stop)
+{
+   switch (StringToBool(string(Start, Stop)))
+   {
       case 0:
       case 0:
       Flags &= ~Flag;
       Flags &= ~Flag;
       return true;
       return true;

+ 2 - 0
apt-pkg/tagfile.h

@@ -60,6 +60,8 @@ class pkgTagSection
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char *Tag,unsigned long &Flags,
    bool FindFlag(const char *Tag,unsigned long &Flags,
 		 unsigned long Flag) const;
 		 unsigned long Flag) const;
+   bool static const FindFlag(unsigned long &Flags, unsigned long Flag,
+				const char* Start, const char* Stop);
    bool Scan(const char *Start,unsigned long MaxLength);
    bool Scan(const char *Start,unsigned long MaxLength);
    inline unsigned long size() const {return Stop - Section;};
    inline unsigned long size() const {return Stop - Section;};
    void Trim();
    void Trim();

+ 4 - 1
debian/changelog

@@ -53,11 +53,14 @@ apt (0.8.11+wheezy) unstable; urgency=low
     - operate optional on gzip compressed pdiffs
     - operate optional on gzip compressed pdiffs
   * apt-pkg/acquire-item.cc:
   * apt-pkg/acquire-item.cc:
     - don't uncompress downloaded pdiff files before feeding it to rred
     - don't uncompress downloaded pdiff files before feeding it to rred
+    - try downloading clearsigned InRelease before trying Release.gpg
   * cmdline/apt-key:
   * cmdline/apt-key:
     - don't set trustdb-name as non-root so 'list' and 'finger'
     - don't set trustdb-name as non-root so 'list' and 'finger'
       can be used without being root (Closes: #393005, #592107)
       can be used without being root (Closes: #393005, #592107)
+  * apt-pkg/deb/deblistparser.cc:
+    - rewrite LoadReleaseInfo to cope with clearsigned Releasefiles
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Sun, 16 Jan 2011 17:23:28 +0100
+ -- David Kalnischkies <kalnischkies@gmail.com>  Thu, 20 Jan 2011 14:52:32 +0100
 
 
 apt (0.8.10) unstable; urgency=low
 apt (0.8.10) unstable; urgency=low
 
 

+ 3 - 2
doc/apt-secure.8.xml

@@ -148,8 +148,8 @@
    (you should make sure you are using a trusted communication channel
    (you should make sure you are using a trusted communication channel
    when retrieving it), add it with <command>apt-key</command> and
    when retrieving it), add it with <command>apt-key</command> and
    then run <command>apt-get update</command> so that apt can download
    then run <command>apt-get update</command> so that apt can download
-   and verify the <filename>Release.gpg</filename> files from the archives you
-   have configured.
+   and verify the <filename>InRelease</filename> or <filename>Release.gpg</filename>
+   files from the archives you have configured.
    </para>
    </para>
 </refsect1>
 </refsect1>
 
 
@@ -166,6 +166,7 @@
        (provided in apt-utils).</para></listitem>
        (provided in apt-utils).</para></listitem>
    
    
       <listitem><para><emphasis>Sign it</emphasis>. You can do this by running
       <listitem><para><emphasis>Sign it</emphasis>. You can do this by running
+      <command>gpg --clearsign -o InRelease Release</command> and
       <command>gpg -abs -o Release.gpg Release</command>.</para></listitem>
       <command>gpg -abs -o Release.gpg Release</command>.</para></listitem>
 
 
       <listitem><para><emphasis>Publish the key fingerprint</emphasis>,
       <listitem><para><emphasis>Publish the key fingerprint</emphasis>,

+ 18 - 0
test/integration/Packages-releasefile-verification

@@ -0,0 +1,18 @@
+Package: apt
+Version: 0.7.25.3
+Architecture: i386
+Maintainer: APT Development Team <deity@lists.debian.org>
+Installed-Size: 5244
+Replaces: libapt-pkg-dev (<< 0.3.7), libapt-pkg-doc (<< 0.3.7)
+Provides: libapt-pkg-libc6.9-6-4.8
+Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, bzip2, lzma, python-apt
+Filename: apt.deb
+Size: 0
+MD5sum: d41d8cd98f00b204e9800998ecf8427e
+Description: Advanced front-end for dpkg
+ This is Debian's next generation front-end for the dpkg package manager.
+ It provides the apt-get utility and APT dselect method that provides a
+ simpler, safer way to install and upgrade packages.
+ .
+ APT features complete installation ordering, multiple source capability
+ and several other unique features, see the Users Guide in apt-doc.

+ 21 - 0
test/integration/Packages-releasefile-verification-new

@@ -0,0 +1,21 @@
+Package: apt
+Priority: important
+Section: admin
+Installed-Size: 5672
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.8.0~pre1
+Replaces: manpages-pl (<< 20060617-3~)
+Provides: libapt-pkg4.10
+Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, bzip2, lzma, python-apt
+Conflicts: python-apt (<< 0.7.93.2~)
+Filename: apt.deb
+Size: 0
+MD5sum: d41d8cd98f00b204e9800998ecf8427e
+Description: Advanced front-end for dpkg
+ This is Debian's next generation front-end for the dpkg package manager.
+ It provides the apt-get utility and APT dselect method that provides a
+ simpler, safer way to install and upgrade packages.
+ .
+ APT features complete installation ordering, multiple source capability
+ and several other unique features, see the Users Guide in apt-doc.

+ 7 - 0
test/integration/framework

@@ -383,6 +383,7 @@ buildaptarchivefromfiles() {
 
 
 generatereleasefiles() {
 generatereleasefiles() {
 	msgninfo "\tGenerate Release files… "
 	msgninfo "\tGenerate Release files… "
+	local DATE="${1:-now}"
 	if [ -e aptarchive/dists ]; then
 	if [ -e aptarchive/dists ]; then
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 			local CODENAME="$(echo "$dir" | cut -d'/' -f 4)"
 			local CODENAME="$(echo "$dir" | cut -d'/' -f 4)"
@@ -395,6 +396,11 @@ NotAutomatic: yes' $dir/Release
 	else
 	else
 		aptftparchive -qq release ./aptarchive | sed -e '/0 Release$/ d' > aptarchive/Release # remove the self reference
 		aptftparchive -qq release ./aptarchive | sed -e '/0 Release$/ d' > aptarchive/Release # remove the self reference
 	fi
 	fi
+	if [ "$DATE" != "now" ]; then
+		for release in $(find ./aptarchive -name 'Release'); do
+			touch -d "$1" $release
+		done
+	fi
 	msgdone "info"
 	msgdone "info"
 }
 }
 
 
@@ -455,6 +461,7 @@ signreleasefiles() {
 	done
 	done
 	for RELEASE in $(find aptarchive/ -name Release); do
 	for RELEASE in $(find aptarchive/ -name Release); do
 		gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE}
 		gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE}
+		gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE
 	done
 	done
 	msgdone "info"
 	msgdone "info"
 }
 }

BIN
test/integration/marvinparanoid.pub


BIN
test/integration/marvinparanoid.sec


+ 12 - 20
test/integration/test-bug-595691-empty-and-broken-archive-files

@@ -74,28 +74,24 @@ testoverfile() {
 	setupcompressor "$1"
 	setupcompressor "$1"
 
 
 	createemptyfile 'en'
 	createemptyfile 'en'
-	testaptgetupdate "Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+	testaptgetupdate "Get:1 file:  InRelease []
 Ign file:$(readlink -f aptarchive)/  Translation-en
 Ign file:$(readlink -f aptarchive)/  Translation-en
 Reading package lists..." "empty file en.$COMPRESS over file"
 Reading package lists..." "empty file en.$COMPRESS over file"
 
 
 	createemptyarchive 'en'
 	createemptyarchive 'en'
-	testaptgetupdate "Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+	testaptgetupdate "Get:1 file:  InRelease []
 Reading package lists..." "empty archive en.$COMPRESS over file"
 Reading package lists..." "empty archive en.$COMPRESS over file"
 
 
 	createemptyarchive 'Packages'
 	createemptyarchive 'Packages'
 	# FIXME: Why omits the file transport the Packages Get line?
 	# FIXME: Why omits the file transport the Packages Get line?
 	#Get:3 file:  Packages []
 	#Get:3 file:  Packages []
 	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
 	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
-Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+Get:1 file:  InRelease []
 Reading package lists..." "empty archive Packages.$COMPRESS over file"
 Reading package lists..." "empty archive Packages.$COMPRESS over file"
 
 
 	createemptyfile 'Packages'
 	createemptyfile 'Packages'
 	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
 	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
-Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+Get:1 file:  InRelease []
 Err file:  Packages
 Err file:  Packages
   Undetermined Error
   Undetermined Error
 W: Failed to fetch file:$(readlink -f aptarchive/Packages.$COMPRESS)  Undetermined Error
 W: Failed to fetch file:$(readlink -f aptarchive/Packages.$COMPRESS)  Undetermined Error
@@ -107,33 +103,29 @@ testoverhttp() {
 	setupcompressor "$1"
 	setupcompressor "$1"
 
 
 	createemptyfile 'en'
 	createemptyfile 'en'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
 Get:2 http://localhost/  Translation-en
 Get:2 http://localhost/  Translation-en
-Get:3 http://localhost  Release []
+Get:3 http://localhost  Packages []
 Ign http://localhost/  Translation-en
 Ign http://localhost/  Translation-en
-Get:4 http://localhost  Packages []
 Reading package lists..." "empty file en.$COMPRESS over http"
 Reading package lists..." "empty file en.$COMPRESS over http"
 
 
 	createemptyarchive 'en'
 	createemptyarchive 'en'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
 Get:2 http://localhost/  Translation-en []
 Get:2 http://localhost/  Translation-en []
-Get:3 http://localhost  Release []
-Get:4 http://localhost  Packages []
+Get:3 http://localhost  Packages []
 Reading package lists..." "empty archive en.$COMPRESS over http"
 Reading package lists..." "empty archive en.$COMPRESS over http"
 
 
 	createemptyarchive 'Packages'
 	createemptyarchive 'Packages'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
 Ign http://localhost/  Translation-en
 Ign http://localhost/  Translation-en
-Get:2 http://localhost  Release []
-Get:3 http://localhost  Packages []
+Get:2 http://localhost  Packages []
 Reading package lists..." "empty archive Packages.$COMPRESS over http"
 Reading package lists..." "empty archive Packages.$COMPRESS over http"
 
 
 	createemptyfile 'Packages'
 	createemptyfile 'Packages'
 	#FIXME: we should response with a good error message instead
 	#FIXME: we should response with a good error message instead
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
 Ign http://localhost/  Translation-en
 Ign http://localhost/  Translation-en
-Get:2 http://localhost  Release []
-Get:3 http://localhost  Packages
+Get:2 http://localhost  Packages
 Err http://localhost  Packages
 Err http://localhost  Packages
   Undetermined Error
   Undetermined Error
 W: Failed to fetch http://localhost:8080/Packages.$COMPRESS  Undetermined Error
 W: Failed to fetch http://localhost:8080/Packages.$COMPRESS  Undetermined Error

+ 160 - 0
test/integration/test-releasefile-verification

@@ -0,0 +1,160 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+buildaptarchive
+setupflataptarchive
+changetowebserver
+
+prepare() {
+	local DATE="${2:-now}"
+	if [ "$DATE" = 'now' -a "$1" = "${PKGFILE}-new" ]; then
+		DATE='now + 6 days'
+	fi
+	for release in $(find rootdir/var/lib/apt/lists 2> /dev/null); do
+		touch -d 'now - 6 hours' $release
+	done
+	rm -rf rootdir/var/cache/apt/archives
+	rm -f rootdir/var/cache/apt/*.bin
+	cp $1 aptarchive/Packages
+	find aptarchive -name 'Release' -delete
+	cat aptarchive/Packages | gzip > aptarchive/Packages.gz
+	cat aptarchive/Packages | bzip2 > aptarchive/Packages.bz2
+	cat aptarchive/Packages | lzma > aptarchive/Packages.lzma
+	generatereleasefiles "$DATE"
+}
+
+installaptold() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5370 kB of additional disk space will be used.
+Get:1 http://localhost/  apt 0.7.25.3
+Download complete and in download only mode' aptget install apt -dy
+}
+
+installaptnew() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5808 kB of additional disk space will be used.
+Get:1 http://localhost/  apt 0.8.0~pre1
+Download complete and in download only mode' aptget install apt -dy
+}
+
+failaptold() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5370 kB of additional disk space will be used.
+WARNING: The following packages cannot be authenticated!
+  apt
+E: There are problems and -y was used without --force-yes' aptget install apt -dy
+}
+
+failaptnew() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5808 kB of additional disk space will be used.
+WARNING: The following packages cannot be authenticated!
+  apt
+E: There are problems and -y was used without --force-yes' aptget install apt -dy
+}
+
+# fake our downloadable file
+touch aptarchive/apt.deb
+
+PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')"
+
+runtest() {
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+
+	prepare ${PKGFILE}-new
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Good warm archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	installaptnew
+
+
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Marvin Paranoid'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Marvin Paranoid'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	failaptold
+
+	prepare ${PKGFILE}-new
+	# weborf doesn't support If-Range
+	for release in $(find rootdir/var/lib/apt/lists/partial/ -name '*Release'); do
+		rm $release
+		touch $release
+	done
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Bad warm archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	installaptnew
+
+
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+
+	prepare ${PKGFILE}-new
+	signreleasefiles 'Marvin Paranoid'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Good warm archive signed by' 'Marvin Paranoid'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+}
+
+DELETEFILE="InRelease"
+runtest
+DELETEFILE="Release.gpg"
+runtest