]> git.saurik.com Git - apt.git/commitdiff
- try downloading clearsigned InRelease before trying Release.gpg
authorDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 20 Jan 2011 13:53:52 +0000 (14:53 +0100)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Thu, 20 Jan 2011 13:53:52 +0000 (14:53 +0100)
* apt-pkg/deb/deblistparser.cc:
  - rewrite LoadReleaseInfo to cope with clearsigned Releasefiles

18 files changed:
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/deb/debindexfile.cc
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/debmetaindex.cc
apt-pkg/indexcopy.cc
apt-pkg/indexrecords.cc
apt-pkg/tagfile.cc
apt-pkg/tagfile.h
debian/changelog
doc/apt-secure.8.xml
test/integration/Packages-releasefile-verification [new file with mode: 0644]
test/integration/Packages-releasefile-verification-new [new file with mode: 0644]
test/integration/framework
test/integration/marvinparanoid.pub [new file with mode: 0644]
test/integration/marvinparanoid.sec [new file with mode: 0644]
test/integration/test-bug-595691-empty-and-broken-archive-files
test/integration/test-releasefile-verification [new file with mode: 0755]

index d4e90b552b352bac397151326f69cdc5bd092392..2cd6ab359005d96b1141c6a5ea41e172a9eb03f7 100644 (file)
@@ -1077,6 +1077,8 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash, /*{{{*
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+        SigFile = FinalFile;
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
       DestFile = FinalFile;
@@ -1110,6 +1112,8 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)                       /*{{{*/
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+        SigFile = FinalFile;
       DestFile = FinalFile;
    }
    Complete = true;
@@ -1141,6 +1145,10 @@ void pkgAcqMetaIndex::AuthDone(string Message)                           /*{{{*/
    // Download further indexes with verification
    QueueIndexes(true);
 
+   // is it a clearsigned MetaIndex file?
+   if (DestFile == SigFile)
+      return;
+
    // Done, move signature file into position
    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
       URItoFileName(RealURI) + ".gpg";
@@ -1300,13 +1308,20 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    if (AuthPass == true)
    {
       // 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))
       {
-        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;
         _error->Warning(_("A error occurred during the signature "
                           "verification. The repository is not updated "
@@ -1330,6 +1345,35 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    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                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* This just sets up the initial fetch environment and queues the first
index d97a96a0f3fea0c1d6bbbe0a3b6bff6604ab17fd..581761e320bffdcd83fdf1a8c3f7d6fcd6f739c5 100644 (file)
@@ -772,6 +772,39 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
                   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.    {{{
  *
  *  If the package file already exists in the cache, nothing will be
index af1209ccb9124bd0acda0b798553b6d093a3ac27..9961b5ae44178e135c8a2e78b3968db1b43c0281 100644 (file)
@@ -324,8 +324,14 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
 
    // 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)
+      releaseExists = true;
+   else
+      ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
+
+   if (releaseExists == true || FileExists(ReleaseFile) == true)
    {
       FileFd Rel(ReleaseFile,FileFd::ReadOnly);
       if (_error->PendingError() == true)
index 1b3bfd6ae492c77deff4ea208403d3081f9e4f90..9201e6a5441d1117ba23523b3a7a2dc1898dda63 100644 (file)
@@ -783,45 +783,89 @@ bool debListParser::Step()
 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
                                    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
    // file. to provide Component pinning we use the section name now
    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();
 }
index 717d0bcdef3cdd5392af7b4e5009afb4524bf2a0..e2c680b14614dae24cd0404e825af13351ebab7b 100644 (file)
@@ -182,21 +182,15 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
         new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
                         (*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
        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
 {
-   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-      URItoFileName(MetaIndexURI("Release")) + ".gpg";
-   
    if(_config->FindB("APT::Authentication::TrustCDROM", false))
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
         return true;
-   
+
+   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("Release")) + ".gpg";
+
    if (FileExists(VerifiedSigFile))
       return true;
-   return false;
+
+   VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("InRelease"));
+
+   return FileExists(VerifiedSigFile);
 }
 
 vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {
index f88d51fc54d31efcdb380763fc9386bfe9e1b83a..c2ee1c34726f70de4d73ea055ed69726fbb340cb 100644 (file)
@@ -722,7 +722,8 @@ bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG,
    }
 
    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);
 
    if (Debug == true)
index eb9a368662e9f8b192a8513ce9db6fdc6ef1c2fd..10e154ad2305b33c1887bace3777d846d61604b5 100644 (file)
@@ -55,14 +55,17 @@ bool indexRecords::Load(const string Filename)                              /*{{{*/
    }
 
    pkgTagSection Section;
-   if (TagFile.Step(Section) == false)
-   {
-      strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
-      return false;
-   }
-
    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");
    Dist = Section.FindS("Codename");
index 96a681bec9f8ce9224192db4a50304b9492aa001..4a2f3f7e6ed76e3063f64142bb88ff0d1d6320bf 100644 (file)
@@ -399,9 +399,13 @@ bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
    const char *Stop;
    if (Find(Tag,Start,Stop) == false)
       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:
       Flags &= ~Flag;
       return true;
index 6891c1d81c448378d08d948bbc4af10beb75d602..61491aa047adeb5572835cc9f7a9ef0b2931c52b 100644 (file)
@@ -60,6 +60,8 @@ class pkgTagSection
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char *Tag,unsigned long &Flags,
                 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);
    inline unsigned long size() const {return Stop - Section;};
    void Trim();
index b74508804d2346d81ff7930c4775d8232828bf27..59f51675131ce18b790997d519539fb32ffba399 100644 (file)
@@ -53,11 +53,14 @@ apt (0.8.11+wheezy) unstable; urgency=low
     - operate optional on gzip compressed pdiffs
   * apt-pkg/acquire-item.cc:
     - don't uncompress downloaded pdiff files before feeding it to rred
+    - try downloading clearsigned InRelease before trying Release.gpg
   * cmdline/apt-key:
     - don't set trustdb-name as non-root so 'list' and 'finger'
       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
 
index f345c3f89ac6286050462aa8a108a424b3e80bfa..f8ff678b957b91879ac5790c1deb8bb75930da35 100644 (file)
    (you should make sure you are using a trusted communication channel
    when retrieving it), add it with <command>apt-key</command> and
    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>
 </refsect1>
 
        (provided in apt-utils).</para></listitem>
    
       <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>
 
       <listitem><para><emphasis>Publish the key fingerprint</emphasis>,
diff --git a/test/integration/Packages-releasefile-verification b/test/integration/Packages-releasefile-verification
new file mode 100644 (file)
index 0000000..29a385f
--- /dev/null
@@ -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.
diff --git a/test/integration/Packages-releasefile-verification-new b/test/integration/Packages-releasefile-verification-new
new file mode 100644 (file)
index 0000000..e3b2edf
--- /dev/null
@@ -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.
index 5d54e49b67986a7f2328e4a29632f82ce628dac0..cb3fca35dad6c489ee658245b0869b5580f3f020 100644 (file)
@@ -383,6 +383,7 @@ buildaptarchivefromfiles() {
 
 generatereleasefiles() {
        msgninfo "\tGenerate Release files… "
+       local DATE="${1:-now}"
        if [ -e aptarchive/dists ]; then
                for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
                        local CODENAME="$(echo "$dir" | cut -d'/' -f 4)"
@@ -395,6 +396,11 @@ NotAutomatic: yes' $dir/Release
        else
                aptftparchive -qq release ./aptarchive | sed -e '/0 Release$/ d' > aptarchive/Release # remove the self reference
        fi
+       if [ "$DATE" != "now" ]; then
+               for release in $(find ./aptarchive -name 'Release'); do
+                       touch -d "$1" $release
+               done
+       fi
        msgdone "info"
 }
 
@@ -455,6 +461,7 @@ signreleasefiles() {
        done
        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" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE
        done
        msgdone "info"
 }
diff --git a/test/integration/marvinparanoid.pub b/test/integration/marvinparanoid.pub
new file mode 100644 (file)
index 0000000..9a59c2e
Binary files /dev/null and b/test/integration/marvinparanoid.pub differ
diff --git a/test/integration/marvinparanoid.sec b/test/integration/marvinparanoid.sec
new file mode 100644 (file)
index 0000000..ff54e86
Binary files /dev/null and b/test/integration/marvinparanoid.sec differ
index 66792899a834e4c1b3ee5aa5ade5efbfd985dd4f..c5379dca030cb216c728c6f189508b596f768876 100755 (executable)
@@ -74,28 +74,24 @@ testoverfile() {
        setupcompressor "$1"
 
        createemptyfile 'en'
-       testaptgetupdate "Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+       testaptgetupdate "Get:1 file:  InRelease []
 Ign file:$(readlink -f aptarchive)/  Translation-en
 Reading package lists..." "empty file en.$COMPRESS over file"
 
        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"
 
        createemptyarchive 'Packages'
        # FIXME: Why omits the file transport the Packages Get line?
        #Get:3 file:  Packages []
        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"
 
        createemptyfile 'Packages'
        testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
-Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+Get:1 file:  InRelease []
 Err file:  Packages
   Undetermined Error
 W: Failed to fetch file:$(readlink -f aptarchive/Packages.$COMPRESS)  Undetermined Error
@@ -107,33 +103,29 @@ testoverhttp() {
        setupcompressor "$1"
 
        createemptyfile 'en'
-       testaptgetupdate "Get:1 http://localhost  Release.gpg []
+       testaptgetupdate "Get:1 http://localhost  InRelease []
 Get:2 http://localhost/  Translation-en
-Get:3 http://localhost  Release []
+Get:3 http://localhost  Packages []
 Ign http://localhost/  Translation-en
-Get:4 http://localhost  Packages []
 Reading package lists..." "empty file en.$COMPRESS over http"
 
        createemptyarchive 'en'
-       testaptgetupdate "Get:1 http://localhost  Release.gpg []
+       testaptgetupdate "Get:1 http://localhost  InRelease []
 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"
 
        createemptyarchive 'Packages'
-       testaptgetupdate "Get:1 http://localhost  Release.gpg []
+       testaptgetupdate "Get:1 http://localhost  InRelease []
 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"
 
        createemptyfile 'Packages'
        #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
-Get:2 http://localhost  Release []
-Get:3 http://localhost  Packages
+Get:2 http://localhost  Packages
 Err http://localhost  Packages
   Undetermined Error
 W: Failed to fetch http://localhost:8080/Packages.$COMPRESS  Undetermined Error
diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification
new file mode 100755 (executable)
index 0000000..961c498
--- /dev/null
@@ -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