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

Merge remote-tracking branch 'mvo/feature/acq-trans' into debian/experimental

Michael Vogt лет назад: 11
Родитель
Сommit
a943fbf21c
45 измененных файлов с 2069 добавлено и 1157 удалено
  1. 862 745
      apt-pkg/acquire-item.cc
  2. 348 283
      apt-pkg/acquire-item.h
  3. 4 1
      apt-pkg/acquire-method.cc
  4. 2 1
      apt-pkg/acquire-worker.cc
  5. 56 23
      apt-pkg/acquire.cc
  6. 13 6
      apt-pkg/acquire.h
  7. 1 1
      apt-pkg/contrib/fileutl.cc
  8. 13 13
      apt-pkg/deb/debmetaindex.cc
  9. 4 0
      apt-pkg/init.cc
  10. 2 2
      apt-pkg/update.cc
  11. 3 0
      apt-private/acqprogress.cc
  12. 1 0
      apt-private/private-cmndline.cc
  13. 3 3
      apt-private/private-install.cc
  14. 1 3
      apt-private/private-update.cc
  15. 4 14
      cmdline/apt-get.cc
  16. 2 4
      cmdline/apt-helper.cc
  17. 9 6
      debian/apt.postinst
  18. 1 1
      doc/examples/configure-index
  19. 8 0
      methods/copy.cc
  20. 1 1
      methods/gpgv.cc
  21. 37 10
      test/integration/framework
  22. 1 1
      test/integration/test-apt-by-hash-update
  23. 1 0
      test/integration/test-apt-get-clean
  24. 16 0
      test/integration/test-apt-get-download
  25. 1 1
      test/integration/test-apt-get-source-authenticated
  26. 46 0
      test/integration/test-apt-get-update-unauth-warning
  27. 85 0
      test/integration/test-apt-update-ims
  28. 234 0
      test/integration/test-apt-update-nofallback
  29. 195 0
      test/integration/test-apt-update-rollback
  30. 24 0
      test/integration/test-apt-update-transactions
  31. 39 8
      test/integration/test-apt-update-unauth
  32. 1 1
      test/integration/test-bug-595691-empty-and-broken-archive-files
  33. 1 1
      test/integration/test-bug-596498-trusted-unsigned-repo
  34. 4 1
      test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted
  35. 1 1
      test/integration/test-bug-717891-abolute-uris-for-proxies
  36. 1 1
      test/integration/test-bug-728500-tempdir
  37. 1 1
      test/integration/test-bug-738785-switch-protocol
  38. 2 2
      test/integration/test-compressed-indexes
  39. 7 3
      test/integration/test-hashsum-verification
  40. 12 8
      test/integration/test-http-pipeline-messup
  41. 2 1
      test/integration/test-pdiff-usage
  42. 2 1
      test/integration/test-policy-pinning
  43. 12 1
      test/integration/test-releasefile-verification
  44. 5 5
      test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
  45. 1 3
      test/integration/test-ubuntu-bug-784473-InRelease-one-message-only

Разница между файлами не показана из-за своего большого размера
+ 862 - 745
apt-pkg/acquire-item.cc


+ 348 - 283
apt-pkg/acquire-item.h

@@ -47,6 +47,7 @@ class indexRecords;
 class pkgRecords;
 class pkgSourceList;
 class IndexTarget;
+class pkgAcqMetaBase;
 
 /** \brief Represents the process by which a pkgAcquire object should	{{{
  *  retrieve a file or a collection of files.
@@ -62,6 +63,8 @@ class IndexTarget;
  */
 class pkgAcquire::Item : public WeakPointable
 {  
+   void *d;
+
    protected:
    
    /** \brief The acquire object with which this item is associated. */
@@ -72,12 +75,11 @@ class pkgAcquire::Item : public WeakPointable
     *  \param Item Metadata about this item (its URI and
     *  description).
     */
-   inline void QueueURI(ItemDesc &Item)
-                 {Owner->Enqueue(Item);};
+   void QueueURI(ItemDesc &Item);
 
    /** \brief Remove this item from its owner's queue. */
-   inline void Dequeue() {Owner->Dequeue(this);};
-   
+   void Dequeue();
+
    /** \brief Rename a file without modifying its timestamp.
     *
     *  Many item methods call this as their final action.
@@ -87,7 +89,7 @@ class pkgAcquire::Item : public WeakPointable
     *  \param To The new name of \a From.  If \a To exists it will be
     *  overwritten.
     */
-   void Rename(std::string From,std::string To);
+   bool Rename(std::string From,std::string To);
 
    public:
 
@@ -116,7 +118,7 @@ class pkgAcquire::Item : public WeakPointable
        /** \brief The item was could not be downloaded because of 
 	*  a transient network error (e.g. network down)
 	*/
-       StatTransientNetworkError
+       StatTransientNetworkError,
      } Status;
 
    /** \brief Contains a textual description of the error encountered
@@ -173,6 +175,9 @@ class pkgAcquire::Item : public WeakPointable
     */
    unsigned int QueueCounter;
 
+   /** \brief TransactionManager */
+   pkgAcqMetaBase *TransactionManager;
+
    /** \brief The number of additional fetch items that are expected
     *  once this item is done.
     *
@@ -188,6 +193,9 @@ class pkgAcquire::Item : public WeakPointable
     */
    std::string DestFile;
 
+   /** \brief storge name until a transaction is finished */
+   std::string PartialFile;
+
    /** \brief Invoked by the acquire worker when the object couldn't
     *  be fetched.
     *
@@ -274,7 +282,6 @@ class pkgAcquire::Item : public WeakPointable
    /** \return \b true if this object is being fetched from a trusted source. */
    virtual bool IsTrusted() const {return false;};
    
-   // report mirror problems
    /** \brief Report mirror problem
     * 
     *  This allows reporting mirror failures back to a centralized
@@ -284,6 +291,11 @@ class pkgAcquire::Item : public WeakPointable
     */
    void ReportMirrorFailure(std::string FailCode);
 
+   /** \brief Set the name of the current active subprocess
+    *
+    *  See also #ActiveSubprocess
+    */
+   void SetActiveSubprocess(const std::string &subprocess);
 
    /** \brief Initialize an item.
     *
@@ -295,7 +307,8 @@ class pkgAcquire::Item : public WeakPointable
     *  \param ExpectedHashes of the file represented by this item
     */
    Item(pkgAcquire *Owner,
-        HashStringList const &ExpectedHashes=HashStringList());
+        HashStringList const &ExpectedHashes=HashStringList(),
+        pkgAcqMetaBase *TransactionManager=NULL);
 
    /** \brief Remove this item from its owner's queue by invoking
     *  pkgAcquire::Remove.
@@ -307,7 +320,9 @@ class pkgAcquire::Item : public WeakPointable
    enum RenameOnErrorState {
       HashSumMismatch,
       SizeMismatch,
-      InvalidFormat
+      InvalidFormat,
+      SignatureError,
+      NotClearsigned,
    };
 
    /** \brief Rename failed file and set error
@@ -341,62 +356,286 @@ struct DiffInfo {
    unsigned long long patch_size;
 };
 									/*}}}*/
-/** \brief An item that is responsible for fetching a SubIndex		{{{
- *
- *  The MetaIndex file includes only records for important indexes
- *  and records for these SubIndex files so these can carry records
- *  for addition files like PDiffs and Translations
- */
-class pkgAcqSubIndex : public pkgAcquire::Item
+									/*}}}*/
+
+class pkgAcqMetaBase  : public pkgAcquire::Item
 {
+   void *d;
+
  protected:
-   /** \brief If \b true, debugging information will be written to std::clog. */
-   bool Debug;
+   std::vector<Item*> Transaction;
 
- public:
-   // Specialized action members
-   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
-		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() {return Desc.URI;};
-   virtual std::string Custom600Headers() const;
-   virtual bool ParseIndex(std::string const &IndexFile);
+   /** \brief A package-system-specific parser for the meta-index file. */
+   indexRecords *MetaIndexParser;
 
-   /** \brief Create a new pkgAcqSubIndex.
+   /** \brief The index files which should be looked up in the meta-index
+    *  and then downloaded.
+    */
+   const std::vector<IndexTarget*>* IndexTargets;
+
+   /** \brief If \b true, the index's signature is currently being verified.
+    */
+   bool AuthPass;
+
+   // required to deal gracefully with problems caused by incorrect ims hits
+   bool IMSHit; 
+
+   /** \brief Starts downloading the individual index files.
     *
-    *  \param Owner The Acquire object that owns this item.
+    *  \param verify If \b true, only indices whose expected hashsum
+    *  can be determined from the meta-index will be downloaded, and
+    *  the hashsums of indices will be checked (reporting
+    *  #StatAuthError if there is a mismatch).  If verify is \b false,
+    *  no hashsum checking will be performed.
+    */
+   void QueueIndexes(bool verify);
+
+
+   /** \brief Called when a file is finished being retrieved.
     *
-    *  \param URI The URI of the list file to download.
+    *  If the file was not downloaded to DestFile, a copy process is
+    *  set up to copy it to DestFile; otherwise, Complete is set to \b
+    *  true and the file is moved to its final location.
     *
-    *  \param URIDesc A long description of the list file to download.
+    *  \param Message The message block received from the fetch
+    *  subprocess.
+    */
+   bool CheckDownloadDone(const std::string &Message,
+                          const std::string &RealURI);
+
+   /** \brief Queue the downloaded Signature for verification */
+   void QueueForSignatureVerify(const std::string &MetaIndexFile,
+                                const std::string &MetaIndexFileSignature);
+
+   /** \brief Called when authentication succeeded.
     *
-    *  \param ShortDesc A short description of the list file to download.
+    *  Sanity-checks the authenticated file, queues up the individual
+    *  index files for download, and saves the signature in the lists
+    *  directory next to the authenticated list file.
     *
-    *  \param ExpectedHashes The list file's hashsums which are expected.
+    *  \param Message The message block received from the fetch
+    *  subprocess.
+    */
+   bool CheckAuthDone(std::string Message, const std::string &RealURI);
+
+   /** Check if the current item should fail at this point */
+   bool CheckStopAuthentication(const std::string &RealURI,
+                                const std::string &Message);
+
+   /** \brief Check that the release file is a release file for the
+    *  correct distribution.
+    *
+    *  \return \b true if no fatal errors were encountered.
     */
-   pkgAcqSubIndex(pkgAcquire *Owner, std::string const &URI,std::string const &URIDesc,
-		   std::string const &ShortDesc, HashStringList const &ExpectedHashes);
+   bool VerifyVendor(std::string Message, const std::string &RealURI);
+   
+ public:
+   // transaction code
+   void Add(Item *I);
+   void AbortTransaction();
+   bool TransactionHasError() APT_PURE;
+   void CommitTransaction();
+
+   /** \brief Stage (queue) a copy action when the transaction is commited
+    */
+   void TransactionStageCopy(Item *I,
+                             const std::string &From, 
+                             const std::string &To);
+   /** \brief Stage (queue) a removal action when the transaction is commited
+    */
+   void TransactionStageRemoval(Item *I, const std::string &FinalFile);
+
+   pkgAcqMetaBase(pkgAcquire *Owner,
+                  const std::vector<IndexTarget*>* IndexTargets,
+                  indexRecords* MetaIndexParser,
+                  HashStringList const &ExpectedHashes=HashStringList(),
+                  pkgAcqMetaBase *TransactionManager=NULL)
+      : Item(Owner, ExpectedHashes, TransactionManager),
+        MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets),
+        AuthPass(false), IMSHit(false) {};
+};
+
+/** \brief An acquire item that downloads the detached signature	{{{
+ *  of a meta-index (Release) file, then queues up the release
+ *  file itself.
+ *
+ *  \todo Why protected members?
+ *
+ *  \sa pkgAcqMetaIndex
+ */
+class pkgAcqMetaSig : public pkgAcqMetaBase
+{
+   void *d;
+
+   protected:
+
+   /** \brief The URI of the signature file.  Unlike Desc.URI, this is
+    *  never modified; it is used to determine the file that is being
+    *  downloaded.
+    */
+   std::string RealURI;
+
+   /** \brief The file we need to verify */
+   std::string MetaIndexFile;
+
+   /** \brief The file we use to verify the MetaIndexFile with */
+   std::string MetaIndexFileSignature;
+
+   /** \brief Long URI description used in the acquire system */
+   std::string URIDesc;
+
+   /** \brief Short URI description used in the acquire system */
+   std::string ShortDesc;
+
+   public:
+   
+   // Specialized action members
+   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(std::string Message,unsigned long long Size,
+                     HashStringList const &Hashes,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual std::string Custom600Headers() const;
+   virtual std::string DescURI() {return RealURI; };
+
+   /** \brief Create a new pkgAcqMetaSig. */
+   pkgAcqMetaSig(pkgAcquire *Owner,
+                 pkgAcqMetaBase *TransactionManager,
+                 std::string URI,std::string URIDesc, std::string ShortDesc,
+                 std::string MetaIndexFile,
+		 const std::vector<IndexTarget*>* IndexTargets,
+		 indexRecords* MetaIndexParser);
+   virtual ~pkgAcqMetaSig();
+};
+									/*}}}*/
+
+/** \brief An item that is responsible for downloading the meta-index	{{{
+ *  file (i.e., Release) itself and verifying its signature.
+ *
+ *  Once the download and verification are complete, the downloads of
+ *  the individual index files are queued up using pkgAcqDiffIndex.
+ *  If the meta-index file had a valid signature, the expected hashsums
+ *  of the index files will be the md5sums listed in the meta-index;
+ *  otherwise, the expected hashsums will be "" (causing the
+ *  authentication of the index files to be bypassed).
+ */
+class pkgAcqMetaIndex : public pkgAcqMetaBase
+{
+   void *d;
+
+   protected:
+   /** \brief The URI that is actually being downloaded; never
+    *  modified by pkgAcqMetaIndex.
+    */
+   std::string RealURI;
+
+   std::string URIDesc;
+   std::string ShortDesc;
+
+   /** \brief The URI of the meta-index file for the detached signature */
+   std::string MetaIndexSigURI;
+
+   /** \brief A "URI-style" description of the meta-index file */
+   std::string MetaIndexSigURIDesc;
+
+   /** \brief A brief description of the meta-index file */
+   std::string MetaIndexSigShortDesc;
+
+   /** \brief delayed constructor */
+   void Init(std::string URIDesc, std::string ShortDesc);
+   
+   public:
+
+   // Specialized action members
+   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual std::string Custom600Headers() const;
+   virtual std::string DescURI() {return RealURI; };
+   virtual void Finished();
+
+   /** \brief Create a new pkgAcqMetaIndex. */
+   pkgAcqMetaIndex(pkgAcquire *Owner,
+                   pkgAcqMetaBase *TransactionManager,
+		   std::string URI,std::string URIDesc, std::string ShortDesc,
+                   std::string MetaIndexSigURI, std::string MetaIndexSigURIDesc, std::string MetaIndexSigShortDesc,
+		   const std::vector<IndexTarget*>* IndexTargets,
+		   indexRecords* MetaIndexParser);
+};
+									/*}}}*/
+/** \brief An item repsonsible for downloading clearsigned metaindexes	{{{*/
+class pkgAcqMetaClearSig : public pkgAcqMetaIndex
+{
+   void *d;
+
+   /** \brief The URI of the meta-index file for the detached signature */
+   std::string MetaIndexURI;
+
+   /** \brief A "URI-style" description of the meta-index file */
+   std::string MetaIndexURIDesc;
+
+   /** \brief A brief description of the meta-index file */
+   std::string MetaIndexShortDesc;
+
+   /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */
+   std::string MetaSigURI;
+
+   /** \brief A "URI-style" description of the meta-signature file */
+   std::string MetaSigURIDesc;
+
+   /** \brief A brief description of the meta-signature file */
+   std::string MetaSigShortDesc;
+
+public:
+   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual std::string Custom600Headers() const;
+   virtual void Done(std::string Message,unsigned long long Size,
+                     HashStringList const &Hashes,
+		     pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Create a new pkgAcqMetaClearSig. */
+   pkgAcqMetaClearSig(pkgAcquire *Owner,
+		std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc,
+		std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc,
+		std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
+		const std::vector<IndexTarget*>* IndexTargets,
+		indexRecords* MetaIndexParser);
+   virtual ~pkgAcqMetaClearSig();
 };
 									/*}}}*/
 
+
 /** \brief Common base class for all classes that deal with fetching 	{{{
            indexes
  */
 class pkgAcqBaseIndex : public pkgAcquire::Item
 {
+   void *d;
+
  protected:
    /** \brief Pointer to the IndexTarget data
     */
    const struct IndexTarget * Target;
+
+   /** \brief Pointer to the indexRecords parser */
    indexRecords *MetaIndexParser;
 
+   /** \brief The MetaIndex Key */
+   std::string MetaKey;
+
+   /** \brief The URI of the index file to recreate at our end (either
+    *  by downloading it or by applying partial patches).
+    */
+   std::string RealURI;
+
+   bool VerifyHashByMetaKey(HashStringList const &Hashes);
+
    pkgAcqBaseIndex(pkgAcquire *Owner,
+                   pkgAcqMetaBase *TransactionManager,
                    struct IndexTarget const * const Target,
                    HashStringList const &ExpectedHashes,
                    indexRecords *MetaIndexParser)
-      : Item(Owner, ExpectedHashes), Target(Target), 
+      : Item(Owner, ExpectedHashes, TransactionManager), Target(Target), 
         MetaIndexParser(MetaIndexParser) {};
-
 };
 									/*}}}*/
 /** \brief An item that is responsible for fetching an index file of	{{{
@@ -410,15 +649,12 @@ class pkgAcqBaseIndex : public pkgAcquire::Item
  */
 class pkgAcqDiffIndex : public pkgAcqBaseIndex
 {
+   void *d;
+
  protected:
    /** \brief If \b true, debugging information will be written to std::clog. */
    bool Debug;
 
-   /** \brief The URI of the index file to recreate at our end (either
-    *  by downloading it or by applying partial patches).
-    */
-   std::string RealURI;
-
    /** \brief The index file which will be patched to generate the new
     *  file.
     */
@@ -429,6 +665,10 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
     */
    std::string Description;
 
+   /** \brief If the copy step of the packages file is done
+    */
+   bool PackagesFileReadyInPartial;
+
  public:
    // Specialized action members
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
@@ -463,6 +703,7 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
     *  \param ExpectedHashes The list file's hashsums which are expected.
     */
    pkgAcqDiffIndex(pkgAcquire *Owner,
+                   pkgAcqMetaBase *TransactionManager,
                    struct IndexTarget const * const Target,
                    HashStringList const &ExpectedHashes,
                    indexRecords *MetaIndexParser);
@@ -481,6 +722,8 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
  */
 class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
 {
+   void *d;
+
    protected:
 
    /** \brief If \b true, debugging output will be written to
@@ -488,11 +731,6 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     */
    bool Debug;
 
-   /** \brief URI of the package index file that is being
-    *  reconstructed.
-    */
-   std::string RealURI;
-
    /** \brief description of the file being downloaded. */
    std::string Description;
 
@@ -551,6 +789,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     *  check if it was the last one to complete the download step
     */
    pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
+                         pkgAcqMetaBase *TransactionManager,
                          struct IndexTarget const * const Target,
                          HashStringList const &ExpectedHash,
                          indexRecords *MetaIndexParser,
@@ -571,6 +810,8 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
  */
 class pkgAcqIndexDiffs : public pkgAcqBaseIndex
 {
+   void *d;
+
    private:
 
    /** \brief Queue up the next diff download.
@@ -604,11 +845,6 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     */
    bool Debug;
 
-   /** \brief The URI of the package index file that is being
-    *  reconstructed.
-    */
-   std::string RealURI;
-
    /** A description of the file being downloaded. */
    std::string Description;
 
@@ -649,7 +885,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
 
    virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string DescURI() {return RealURI + "Index";};
+   virtual std::string DescURI() {return RealURI + "IndexDiffs";};
 
    /** \brief Create an index diff item.
     *
@@ -674,6 +910,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     *  that depends on it.
     */
    pkgAcqIndexDiffs(pkgAcquire *Owner,
+                    pkgAcqMetaBase *TransactionManager,
                     struct IndexTarget const * const Target,
                     HashStringList const &ExpectedHash,
                     indexRecords *MetaIndexParser,
@@ -689,46 +926,68 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
  */
 class pkgAcqIndex : public pkgAcqBaseIndex
 {
-   protected:
+   void *d;
 
-   /** \brief If \b true, the index file has been decompressed. */
-   bool Decompression;
+   protected:
 
-   /** \brief If \b true, the partially downloaded file will be
-    *  removed when the download completes.
+   /** \brief The stages the method goes through
+    *
+    *  The method first downloads the indexfile, then its decompressed (or
+    *  copied) and verified
     */
-   bool Erase;
+   enum AllStages {
+      STAGE_DOWNLOAD,
+      STAGE_DECOMPRESS_AND_VERIFY,
+   };
+   AllStages Stage;
 
-   // Unused, used to be used to verify that "Packages: " header was there
-   bool __DELME_ON_NEXT_ABI_BREAK_Verify;
+   /** \brief Handle what needs to be done when the download is done */
+   void StageDownloadDone(std::string Message,
+                          HashStringList const &Hashes,
+                          pkgAcquire::MethodConfig *Cfg);
 
-   /** \brief The object that is actually being fetched (minus any
-    *  compression-related extensions).
+   /** \brief Handle what needs to be done when the decompression/copy is
+    *         done 
     */
-   std::string RealURI;
+   void StageDecompressDone(std::string Message,
+                            HashStringList const &Hashes,
+                            pkgAcquire::MethodConfig *Cfg);
+
+   /** \brief If \b set, this partially downloaded file will be
+    *  removed when the download completes.
+    */
+   std::string EraseFileName;
 
    /** \brief The compression-related file extensions that are being
     *  added to the downloaded file one by one if first fails (e.g., "gz bz2").
     */
-   std::string CompressionExtension;
+   std::string CompressionExtensions;
 
+   /** \brief The actual compression extension currently used */
+   std::string CurrentCompressionExtension;
 
    /** \brief Do the changes needed to fetch via AptByHash (if needed) */
    void InitByHashIfNeeded(const std::string MetaKey);
 
-   /** \brief Get the full pathname of the final file for the given URI
+   /** \brief Auto select the right compression to use */
+   void AutoSelectCompression();
+
+   /** \brief Get the full pathname of the final file for the current URI
     */
-   std::string GetFinalFilename(std::string const &URI,
-                                std::string const &compExt);
+   std::string GetFinalFilename() const;
 
    /** \brief Schedule file for verification after a IMS hit */
-   void ReverifyAfterIMS(std::string const &FileName);
+   void ReverifyAfterIMS();
+
+   /** \brief Validate the downloaded index file */
+   bool ValidateFile(const std::string &FileName);
 
    public:
    
    // Specialized action members
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
+   virtual void Done(std::string Message,unsigned long long Size, 
+                     HashStringList const &Hashes,
 		     pkgAcquire::MethodConfig *Cnf);
    virtual std::string Custom600Headers() const;
    virtual std::string DescURI() {return Desc.URI;};
@@ -753,12 +1012,12 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     *  fallback is ".gz" or none.
     */
    pkgAcqIndex(pkgAcquire *Owner,std::string URI,std::string URIDesc,
-	       std::string ShortDesc, HashStringList const &ExpectedHashes,
-	       std::string compressExt="");
-   pkgAcqIndex(pkgAcquire *Owner,
+	       std::string ShortDesc, HashStringList const &ExpectedHashes);
+   pkgAcqIndex(pkgAcquire *Owner, pkgAcqMetaBase *TransactionManager,
                IndexTarget const * const Target,
                HashStringList const &ExpectedHash,
                indexRecords *MetaIndexParser);
+               
    void Init(std::string const &URI, std::string const &URIDesc,
              std::string const &ShortDesc);
 };
@@ -772,6 +1031,8 @@ class pkgAcqIndex : public pkgAcqBaseIndex
  */
 class pkgAcqIndexTrans : public pkgAcqIndex
 {
+   void *d;
+
    public:
   
    virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
@@ -788,15 +1049,21 @@ class pkgAcqIndexTrans : public pkgAcqIndex
     *
     *  \param ShortDesc A brief description of this index file.
     */
-   pkgAcqIndexTrans(pkgAcquire *Owner,std::string URI,std::string URIDesc,
+   pkgAcqIndexTrans(pkgAcquire *Owner,
+                    std::string URI,std::string URIDesc,
 		    std::string ShortDesc);
-   pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const Target,
-		    HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser);
+   pkgAcqIndexTrans(pkgAcquire *Owner,
+                    pkgAcqMetaBase *TransactionManager,
+                    IndexTarget const * const Target,
+                    HashStringList const &ExpectedHashes,
+                    indexRecords *MetaIndexParser);
 };
 									/*}}}*/
 /** \brief Information about an index file. */				/*{{{*/
 class IndexTarget
 {
+   void *d;
+
  public:
    /** \brief A URI from which the index file can be downloaded. */
    std::string URI;
@@ -815,224 +1082,18 @@ class IndexTarget
    virtual bool IsOptional() const {
       return false;
    }
-   virtual bool IsSubIndex() const {
-      return false;
-   }
 };
 									/*}}}*/
 /** \brief Information about an optional index file. */			/*{{{*/
 class OptionalIndexTarget : public IndexTarget
 {
+   void *d;
+
    virtual bool IsOptional() const {
       return true;
    }
 };
 									/*}}}*/
-/** \brief Information about an subindex index file. */			/*{{{*/
-class SubIndexTarget : public IndexTarget
-{
-   virtual bool IsSubIndex() const {
-      return true;
-   }
-};
-									/*}}}*/
-/** \brief Information about an subindex index file. */			/*{{{*/
-class OptionalSubIndexTarget : public OptionalIndexTarget
-{
-   virtual bool IsSubIndex() const {
-      return true;
-   }
-};
-									/*}}}*/
-
-/** \brief An acquire item that downloads the detached signature	{{{
- *  of a meta-index (Release) file, then queues up the release
- *  file itself.
- *
- *  \todo Why protected members?
- *
- *  \sa pkgAcqMetaIndex
- */
-class pkgAcqMetaSig : public pkgAcquire::Item
-{
-   protected:
-   /** \brief The last good signature file */
-   std::string LastGoodSig;
-
-   /** \brief The URI of the signature file.  Unlike Desc.URI, this is
-    *  never modified; it is used to determine the file that is being
-    *  downloaded.
-    */
-   std::string RealURI;
-
-   /** \brief The URI of the meta-index file to be fetched after the signature. */
-   std::string MetaIndexURI;
-
-   /** \brief A "URI-style" description of the meta-index file to be
-    *  fetched after the signature.
-    */
-   std::string MetaIndexURIDesc;
-
-   /** \brief A brief description of the meta-index file to be fetched
-    *  after the signature.
-    */
-   std::string MetaIndexShortDesc;
-
-   /** \brief A package-system-specific parser for the meta-index file. */
-   indexRecords* MetaIndexParser;
-
-   /** \brief The index files which should be looked up in the meta-index
-    *  and then downloaded.
-    *
-    *  \todo Why a list of pointers instead of a list of structs?
-    */
-   const std::vector<IndexTarget*>* IndexTargets;
-
-   public:
-   
-   // Specialized action members
-   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
-		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string Custom600Headers() const;
-   virtual std::string DescURI() {return RealURI; };
-
-   /** \brief Create a new pkgAcqMetaSig. */
-   pkgAcqMetaSig(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc,
-		 std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc,
-		 const std::vector<IndexTarget*>* IndexTargets,
-		 indexRecords* MetaIndexParser);
-   virtual ~pkgAcqMetaSig();
-};
-									/*}}}*/
-/** \brief An item that is responsible for downloading the meta-index	{{{
- *  file (i.e., Release) itself and verifying its signature.
- *
- *  Once the download and verification are complete, the downloads of
- *  the individual index files are queued up using pkgAcqDiffIndex.
- *  If the meta-index file had a valid signature, the expected hashsums
- *  of the index files will be the md5sums listed in the meta-index;
- *  otherwise, the expected hashsums will be "" (causing the
- *  authentication of the index files to be bypassed).
- */
-class pkgAcqMetaIndex : public pkgAcquire::Item
-{
-   protected:
-   /** \brief The URI that is actually being downloaded; never
-    *  modified by pkgAcqMetaIndex.
-    */
-   std::string RealURI;
-
-   /** \brief The file in which the signature for this index was stored.
-    *
-    *  If empty, the signature and the md5sums of the individual
-    *  indices will not be checked.
-    */
-   std::string SigFile;
-
-   /** \brief The index files to download. */
-   const std::vector<IndexTarget*>* IndexTargets;
-
-   /** \brief The parser for the meta-index file. */
-   indexRecords* MetaIndexParser;
-
-   /** \brief If \b true, the index's signature is currently being verified.
-    */
-   bool AuthPass;
-   // required to deal gracefully with problems caused by incorrect ims hits
-   bool IMSHit; 
-
-   /** \brief Check that the release file is a release file for the
-    *  correct distribution.
-    *
-    *  \return \b true if no fatal errors were encountered.
-    */
-   bool VerifyVendor(std::string Message);
-
-   /** \brief Called when a file is finished being retrieved.
-    *
-    *  If the file was not downloaded to DestFile, a copy process is
-    *  set up to copy it to DestFile; otherwise, Complete is set to \b
-    *  true and the file is moved to its final location.
-    *
-    *  \param Message The message block received from the fetch
-    *  subprocess.
-    */
-   void RetrievalDone(std::string Message);
-
-   /** \brief Called when authentication succeeded.
-    *
-    *  Sanity-checks the authenticated file, queues up the individual
-    *  index files for download, and saves the signature in the lists
-    *  directory next to the authenticated list file.
-    *
-    *  \param Message The message block received from the fetch
-    *  subprocess.
-    */
-   void AuthDone(std::string Message);
-
-   /** \brief Starts downloading the individual index files.
-    *
-    *  \param verify If \b true, only indices whose expected hashsum
-    *  can be determined from the meta-index will be downloaded, and
-    *  the hashsums of indices will be checked (reporting
-    *  #StatAuthError if there is a mismatch).  If verify is \b false,
-    *  no hashsum checking will be performed.
-    */
-   void QueueIndexes(bool verify);
-   
-   public:
-   
-   // Specialized action members
-   virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes,
-		     pkgAcquire::MethodConfig *Cnf);
-   virtual std::string Custom600Headers() const;
-   virtual std::string DescURI() {return RealURI; };
-
-   /** \brief Create a new pkgAcqMetaIndex. */
-   pkgAcqMetaIndex(pkgAcquire *Owner,
-		   std::string URI,std::string URIDesc, std::string ShortDesc,
-		   std::string SigFile,
-		   const std::vector<IndexTarget*>* IndexTargets,
-		   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 */
-   std::string MetaIndexURI;
-
-   /** \brief A "URI-style" description of the meta-index file */
-   std::string MetaIndexURIDesc;
-
-   /** \brief A brief description of the meta-index file */
-   std::string MetaIndexShortDesc;
-
-   /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */
-   std::string MetaSigURI;
-
-   /** \brief A "URI-style" description of the meta-signature file */
-   std::string MetaSigURIDesc;
-
-   /** \brief A brief description of the meta-signature file */
-   std::string MetaSigShortDesc;
-
-public:
-   void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual std::string Custom600Headers() const;
-
-   /** \brief Create a new pkgAcqMetaClearSig. */
-   pkgAcqMetaClearSig(pkgAcquire *Owner,
-		std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc,
-		std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc,
-		std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
-		const std::vector<IndexTarget*>* IndexTargets,
-		indexRecords* MetaIndexParser);
-   virtual ~pkgAcqMetaClearSig();
-};
-									/*}}}*/
 /** \brief An item that is responsible for fetching a package file.	{{{
  *
  *  If the package file already exists in the cache, nothing will be
@@ -1040,6 +1101,8 @@ public:
  */
 class pkgAcqArchive : public pkgAcquire::Item
 {
+   void *d;
+
    protected:
    /** \brief The package version being fetched. */
    pkgCache::VerIterator Version;
@@ -1118,6 +1181,8 @@ class pkgAcqArchive : public pkgAcquire::Item
  */
 class pkgAcqFile : public pkgAcquire::Item
 {
+   void *d;
+
    /** \brief How many times to retry the download, set from
     *  Acquire::Retries.
     */

+ 4 - 1
apt-pkg/acquire-method.cc

@@ -102,7 +102,10 @@ void pkgAcqMethod::Fail(string Err,bool Transient)
    if (Queue != 0)
    {
       std::cout << "400 URI Failure\nURI: " << Queue->Uri << "\n"
-		<< "Message: " << Err << " " << IP << "\n";
+		<< "Message: " << Err;
+      if (IP.empty() == false && _config->FindB("Acquire::Failure::ShowIP", true) == true)
+	 std::cout << " " << IP;
+      std::cout << "\n";
       Dequeue();
    }
    else

+ 2 - 1
apt-pkg/acquire-worker.cc

@@ -371,7 +371,8 @@ bool pkgAcquire::Worker::RunMessages()
 	 {
 	    if (Itm == 0)
 	    {
-	       _error->Error("Method gave invalid 400 URI Failure message");
+	       std::string const msg = LookupTag(Message,"Message");
+	       _error->Error("Method gave invalid 400 URI Failure message: %s", msg.c_str());
 	       break;
 	    }
 

+ 56 - 23
apt-pkg/acquire.cc

@@ -27,16 +27,20 @@
 #include <vector>
 #include <iostream>
 #include <sstream>
+#include <iomanip>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <iomanip>
-
+#include <pwd.h>
+#include <grp.h>
 #include <dirent.h>
 #include <sys/time.h>
 #include <sys/select.h>
 #include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include <apti18n.h>
 									/*}}}*/
@@ -56,8 +60,8 @@ pkgAcquire::pkgAcquire() : LockFD(-1), Queues(0), Workers(0), Configs(0), Log(NU
    if (strcasecmp(Mode.c_str(),"access") == 0)
       QueueMode = QueueAccess;
 }
-pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) :  LockFD(-1), Queues(0), Workers(0),
-			   Configs(0), Log(Progress), ToFetch(0),
+pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : LockFD(-1), Queues(0), Workers(0),
+			   Configs(0), Log(NULL), ToFetch(0),
 			   Debug(_config->FindB("Debug::pkgAcquire",false)),
 			   Running(false)
 {
@@ -66,40 +70,69 @@ pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) :  LockFD(-1), Queues(0), Wor
       QueueMode = QueueHost;
    if (strcasecmp(Mode.c_str(),"access") == 0)
       QueueMode = QueueAccess;
-   Setup(Progress, "");
+   SetLog(Progress);
 }
 									/*}}}*/
-// Acquire::Setup - Delayed Constructor					/*{{{*/
-// ---------------------------------------------------------------------
-/* Do everything needed to be a complete Acquire object and report the
-   success (or failure) back so the user knows that something is wrong… */
-bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock,
-      bool const createDirectories)
+// Acquire::GetLock - lock directory and prepare for action		/*{{{*/
+static bool SetupAPTPartialDirectory(std::string const &grand, std::string const &parent)
 {
-   Log = Progress;
+   std::string const partial = parent + "partial";
+   if (CreateAPTDirectoryIfNeeded(grand, partial) == false &&
+	 CreateAPTDirectoryIfNeeded(parent, partial) == false)
+      return false;
 
-   // check for existence and possibly create auxiliary directories
-   if (createDirectories == true)
+   if (getuid() == 0) // if we aren't root, we can't chown, so don't try it
+   {
+      struct passwd *pw = getpwnam("_apt");
+      struct group *gr = getgrnam("root");
+      if (pw != NULL && gr != NULL && chown(partial.c_str(), pw->pw_uid, gr->gr_gid) != 0)
+	 _error->WarningE("SetupAPTPartialDirectory", "chown to _apt:root of directory %s failed", partial.c_str());
+   }
+   if (chmod(partial.c_str(), 0700) != 0)
+      _error->WarningE("SetupAPTPartialDirectory", "chmod 0700 of directory %s failed", partial.c_str());
+
+   return true;
+}
+bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock)
+{
+   Log = Progress;
+   if (Lock.empty())
    {
       string const listDir = _config->FindDir("Dir::State::lists");
-      string const partialListDir = listDir + "partial/";
+      if (SetupAPTPartialDirectory(_config->FindDir("Dir::State"), listDir) == false)
+	 return _error->Errno("Acquire", _("List directory %spartial is missing."), listDir.c_str());
       string const archivesDir = _config->FindDir("Dir::Cache::Archives");
-      string const partialArchivesDir = archivesDir + "partial/";
+      if (SetupAPTPartialDirectory(_config->FindDir("Dir::Cache"), archivesDir) == false)
+	 return _error->Errno("Acquire", _("Archives directory %spartial is missing."), archivesDir.c_str());
+      return true;
+   }
+   return GetLock(Lock);
+}
+bool pkgAcquire::GetLock(std::string const &Lock)
+{
+   if (Lock.empty() == true)
+      return false;
 
-      if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
-	    CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
-	 return _error->Errno("Acquire", _("List directory %spartial is missing."), listDir.c_str());
+   // check for existence and possibly create auxiliary directories
+   string const listDir = _config->FindDir("Dir::State::lists");
+   string const archivesDir = _config->FindDir("Dir::Cache::Archives");
 
-      if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::Cache"), partialArchivesDir) == false &&
-	    CreateAPTDirectoryIfNeeded(archivesDir, partialArchivesDir) == false)
+   if (Lock == listDir)
+   {
+      if (SetupAPTPartialDirectory(_config->FindDir("Dir::State"), listDir) == false)
+	 return _error->Errno("Acquire", _("List directory %spartial is missing."), listDir.c_str());
+   }
+   if (Lock == archivesDir)
+   {
+      if (SetupAPTPartialDirectory(_config->FindDir("Dir::Cache"), archivesDir) == false)
 	 return _error->Errno("Acquire", _("Archives directory %spartial is missing."), archivesDir.c_str());
    }
 
-   if (Lock.empty() == true || _config->FindB("Debug::NoLocking", false) == true)
+   if (_config->FindB("Debug::NoLocking", false) == true)
       return true;
 
    // Lock the directory this acquire object will work in
-   LockFD = GetLock(flCombine(Lock, "lock"));
+   LockFD = ::GetLock(flCombine(Lock, "lock"));
    if (LockFD == -1)
       return _error->Error(_("Unable to lock directory %s"), Lock.c_str());
 

+ 13 - 6
apt-pkg/acquire.h

@@ -351,17 +351,24 @@ class pkgAcquire
     *  long as the pkgAcquire object does.
     *  \param Lock defines a lock file that should be acquired to ensure
     *  only one Acquire class is in action at the time or an empty string
-    *  if no lock file should be used.
-    *  \param createDirectories can be used to disable the creation of directories,
-    *  e.g. if the fetcher is used with different directories later on
+    *  if no lock file should be used. If set also all needed directories
+    *  will be created.
     */
-   bool Setup(pkgAcquireStatus *Progress = NULL, std::string const &Lock = "",
-      bool const createDirectories = true);
+   APT_DEPRECATED bool Setup(pkgAcquireStatus *Progress = NULL, std::string const &Lock = "");
 
    void SetLog(pkgAcquireStatus *Progress) { Log = Progress; }
 
+   /** \brief acquire lock and perform directory setup
+    *
+    *  \param Lock defines a lock file that should be acquired to ensure
+    *  only one Acquire class is in action at the time or an empty string
+    *  if no lock file should be used. If set also all needed directories
+    *  will be created and setup.
+    */
+   bool GetLock(std::string const &Lock);
+
    /** \brief Construct a new pkgAcquire. */
-   pkgAcquire(pkgAcquireStatus *Log) APT_DEPRECATED;
+   pkgAcquire(pkgAcquireStatus *Log);
    pkgAcquire();
 
    /** \brief Destroy this pkgAcquire object.

+ 1 - 1
apt-pkg/contrib/fileutl.cc

@@ -1521,7 +1521,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
 	    int err;
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    if (err != BZ_IO_ERROR)
-	       return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
+	       return FileFdError("BZ2_bzread: %s %s (%d: %s)", FileName.c_str(), _("Read error"), err, errmsg);
 	 }
 #endif
 #ifdef HAVE_LZMA

+ 13 - 13
apt-pkg/deb/debmetaindex.cc

@@ -265,26 +265,26 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
       // this is normally created in pkgAcqMetaSig, but if we run
       // in --print-uris mode, we add it here
       if (tryInRelease == false)
-	 new pkgAcqMetaIndex(Owner, MetaIndexURI("Release"),
-	       MetaIndexInfo("Release"), "Release",
-	       MetaIndexURI("Release.gpg"),
-	       ComputeIndexTargets(),
-	       new indexRecords (Dist));
+	 new pkgAcqMetaIndex(Owner, NULL,
+                             MetaIndexURI("Release"),
+                             MetaIndexInfo("Release"), "Release",
+                             MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
+                             ComputeIndexTargets(),
+                             new indexRecords (Dist));
    }
-
    if (tryInRelease == true)
-      new pkgAcqMetaClearSig(Owner, MetaIndexURI("InRelease"),
-	    MetaIndexInfo("InRelease"), "InRelease",
+      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));
    else
-      new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"),
-	    MetaIndexInfo("Release.gpg"), "Release.gpg",
-	    MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
-	    ComputeIndexTargets(),
-	    new indexRecords (Dist));
+      new pkgAcqMetaIndex(Owner, NULL,
+          MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
+          MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
+          ComputeIndexTargets(),
+          new indexRecords (Dist));
 
    return true;
 }

+ 4 - 0
apt-pkg/init.cc

@@ -88,6 +88,10 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Ignore-Files-Silently::", "\\.orig$");
    Cnf.Set("Dir::Ignore-Files-Silently::", "\\.distUpgrade$");
 
+   // Repository security
+   Cnf.CndSet("Acquire::AllowInsecureRepositories", false);
+   Cnf.CndSet("Acquire::AllowDowngradeToInsecureRepositories", false);
+
    // Default cdrom mount point
    Cnf.CndSet("Acquire::cdrom::mount", "/media/cdrom/");
 

+ 2 - 2
apt-pkg/update.cc

@@ -27,8 +27,8 @@ bool ListUpdate(pkgAcquireStatus &Stat,
 		pkgSourceList &List, 
 		int PulseInterval)
 {
-   pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
+   pkgAcquire Fetcher(&Stat);
+   if (Fetcher.GetLock(_config->FindDir("Dir::State::Lists")) == false)
       return false;
 
    // Populate it with the source selection

+ 3 - 0
apt-private/acqprogress.cc

@@ -117,6 +117,9 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm)
    if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
    {
       cout << _("Ign ") << Itm.Description << endl;
+      if (Itm.Owner->ErrorText.empty() == false &&
+	    _config->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true)
+	 cout << "  " << Itm.Owner->ErrorText << endl;
    }
    else
    {

+ 1 - 0
apt-private/private-cmndline.cc

@@ -198,6 +198,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
    addArg(0,"only-source","APT::Get::Only-Source",0);
    addArg(0,"arch-only","APT::Get::Arch-Only",0);
    addArg(0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0);
+   addArg(0,"allow-insecure-repositories","Acquire::AllowInsecureRepositories",0);
    addArg(0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean);
    addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
    addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);

+ 3 - 3
apt-private/private-install.cc

@@ -119,14 +119,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
       return false;
 
    // Create the download object
-   pkgAcquire Fetcher;
-   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
+   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
+   pkgAcquire Fetcher(&Stat);
    if (_config->FindB("APT::Get::Print-URIs", false) == true)
    {
       // force a hashsum for compatibility reasons
       _config->CndSet("Acquire::ForceHash", "md5sum");
    }
-   else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
+   else if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false)
       return false;
 
    // Read the source list

+ 1 - 3
apt-private/private-update.cc

@@ -47,9 +47,7 @@ bool DoUpdate(CommandLine &CmdL)
       _config->CndSet("Acquire::ForceHash", "md5sum");
 
       // get a fetcher
-      pkgAcquire Fetcher;
-      if (Fetcher.Setup(&Stat) == false)
-	 return false;
+      pkgAcquire Fetcher(&Stat);
 
       // Populate it with the source selection and get all Indexes 
       // (GetAll=true)

+ 4 - 14
cmdline/apt-get.cc

@@ -646,9 +646,7 @@ static bool DoDownload(CommandLine &CmdL)
       return false;
 
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0));
-   pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat, "", false) == false)
-      return false;
+   pkgAcquire Fetcher(&Stat);
 
    pkgRecords Recs(Cache);
    pkgSourceList *SrcList = Cache.GetSourceList();
@@ -744,9 +742,8 @@ static bool DoSource(CommandLine &CmdL)
       return false;
 
    // Create the download object
-   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher;
-   Fetcher.SetLog(&Stat);
+   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
+   pkgAcquire Fetcher(&Stat);
 
    SPtrArray<DscFile> Dsc = new DscFile[CmdL.FileSize()];
    
@@ -1048,12 +1045,6 @@ static bool DoBuildDep(CommandLine &CmdL)
    if (_error->PendingError() == true)
       return false;
 
-   // Create the download object
-   AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat) == false)
-      return false;
-
    bool StripMultiArch;
    string hostArch = _config->Find("APT::Get::Host-Architecture");
    if (hostArch.empty() == false)
@@ -1565,8 +1556,7 @@ static bool DoChangelog(CommandLine &CmdL)
    }
 
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
-   if (Fetcher.Setup(&Stat, "",false) == false)
-      return false;
+   Fetcher.SetLog(&Stat);
 
    bool const downOnly = _config->FindB("APT::Get::Download-Only", false);
 

+ 2 - 4
cmdline/apt-helper.cc

@@ -48,11 +48,9 @@ static bool DoDownloadFile(CommandLine &CmdL)
    if (CmdL.FileSize() <= 2)
       return _error->Error(_("Must specify at least one pair url/filename"));
 
-
-   pkgAcquire Fetcher;
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
-   if (Fetcher.Setup(&Stat, "", false) == false)
-      return false;
+   pkgAcquire Fetcher(&Stat);
+
    std::string download_uri = CmdL.FileList[1];
    std::string targetfile = CmdL.FileList[2];
    std::string hash;

+ 9 - 6
debian/apt.postinst

@@ -39,12 +39,15 @@ case "$1" in
 	    fi
 	fi
 
-        # add unprivileged user for the apt methods
-        adduser --force-badname --system -home /var/empty \
-            --no-create-home --quiet _apt || true
-        chown -R _apt:root \
-            /var/lib/apt/lists \
-            /var/cache/apt/archives
+	# add unprivileged user for the apt methods
+	adduser --force-badname --system -home /var/empty \
+	    --no-create-home --quiet _apt || true
+
+	# deal with upgrades from experimental
+	if dpkg --compare-versions "$2" 'eq' '1.1~exp3'; then
+	    # libapt will setup partial/ at runtime
+	    chown -R root:root /var/lib/apt/lists /var/cache/apt/archives || true
+	fi
 
         # ensure tighter permissons on the logs, see LP: #975199
         if dpkg --compare-versions "$2" lt-nl 0.9.7.7; then

+ 1 - 1
doc/examples/configure-index

@@ -34,7 +34,7 @@ APT
   {
      Host-Architecture "armel";
      Arch-Only "false";
-     AllowUnauthenticated "false";
+     AllowUnauthenticated "false";        // packages from unauthenticated
      AutomaticRemove "false";       
      HideAutoRemove "false";
      Download-Only "false";

+ 8 - 0
methods/copy.cc

@@ -67,6 +67,14 @@ bool CopyMethod::Fetch(FetchItem *Itm)
    Res.LastModified = Buf.st_mtime;
    Res.IMSHit = false;      
    URIStart(Res);
+
+   // when the files are identical, just compute the hashes
+   if(File == Itm->DestFile)
+   {
+      CalculateHashes(Res);
+      URIDone(Res);
+      return true;
+   }
    
    // just calc the hashes if the source and destination are identical
    if (File == Itm->DestFile)

+ 1 - 1
methods/gpgv.cc

@@ -160,7 +160,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
    waitpid(pid, &status, 0);
    if (Debug == true)
    {
-      std::clog << "apt-key exited\n";
+      ioprintf(std::clog, "gpgv exited with status %i\n", WEXITSTATUS(status));
    }
    
    if (WEXITSTATUS(status) == 0)

+ 37 - 10
test/integration/framework

@@ -47,6 +47,9 @@ msgskip() { printf "${CWARNING}SKIP${CNORMAL}\n" >&2; }
 msgfail() {
 	if [ $# -gt 0 ]; then printf "${CFAIL}FAIL: $*${CNORMAL}\n" >&2;
 	else printf "${CFAIL}FAIL${CNORMAL}\n" >&2; fi
+        if [ -n "$APT_DEBUG_TESTS" ]; then
+            bash
+        fi
 	EXIT_CODE=$((EXIT_CODE+1));
 }
 
@@ -164,9 +167,10 @@ addtrap() {
 
 setupenvironment() {
 	TMPWORKINGDIRECTORY=$(mktemp -d)
-	TESTDIRECTORY=$(readlink -f $(dirname $0))
+	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY;"
 	msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
 
+	TESTDIRECTORY=$(readlink -f $(dirname $0))
         # allow overriding the default BUILDDIR location
 	BUILDDIRECTORY=${APT_INTEGRATION_TESTS_BUILD_DIR:-"${TESTDIRECTORY}/../../build/bin"}
 	LIBRARYPATH=${APT_INTEGRATION_TESTS_LIBRARY_PATH:-"${BUILDDIRECTORY}"}
@@ -177,7 +181,6 @@ setupenvironment() {
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
         # -----
 
-	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY;"
 	cd $TMPWORKINGDIRECTORY
 	mkdir rootdir aptarchive keys
 	cd rootdir
@@ -210,7 +213,9 @@ setupenvironment() {
 		cp "${TESTDIRECTORY}/${SOURCESSFILE}" aptarchive/Sources
 	fi
 	cp $(find $TESTDIRECTORY -name '*.pub' -o -name '*.sec') keys/
+	chmod 644 $(find keys -name '*.pub' -o -name '*.sec')
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
+
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
 	echo "Debug::NoLocking \"true\";" >> aptconfig.conf
@@ -228,8 +233,14 @@ setupenvironment() {
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
 	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	echo 'quiet::NoStatistic "true";' >> aptconfig.conf
+	# too distracting for users, but helpful to detect changes
+	echo 'Acquire::Progress::Ignore::ShowErrorText "true";' >> aptconfig.conf
+	# in testcases, it can appear as if localhost has a rotation setup,
+	# hide this as we can't really deal with it properly
+	echo 'Acquire::Failure::ShowIP "false";' >> aptconfig.conf
+
 	echo "Acquire::https::CaInfo \"${TESTDIR}/apt.pem\";" > rootdir/etc/apt/apt.conf.d/99https
-        echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary
+	echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary
 	configcompression '.' 'gz' #'bz2' 'lzma' 'xz'
 
 	# cleanup the environment a bit
@@ -714,7 +725,7 @@ buildaptarchivefromincoming() {
 	aptftparchive -qq generate ftparchive.conf
 	cd - > /dev/null
 	msgdone "info"
-	generatereleasefiles
+	generatereleasefiles "$@"
 }
 
 buildaptarchivefromfiles() {
@@ -829,17 +840,20 @@ setupflataptarchive() {
 }
 
 setupaptarchive() {
-	buildaptarchive
+	local NOUPDATE=0
+	if [ "$1" = '--no-update' ]; then
+		NOUPDATE=1
+		shift
+	fi
+	buildaptarchive "$@"
 	if [ -e aptarchive/dists ]; then
 		setupdistsaptarchive
 	else
 		setupflataptarchive
 	fi
-	signreleasefiles
-	if [ "$1" != '--no-update' ]; then
-		msgninfo "\tSync APT's cache with the archive… "
-		aptget update -qq
-		msgdone "info"
+	signreleasefiles 'Joe Sixpack' "$@"
+	if [ "1" != "$NOUPDATE" ]; then
+		testsuccess aptget update -o Debug::pkgAcquire::Worker=true -o Debug::Acquire::gpgv=true
 	fi
 }
 
@@ -1175,6 +1189,19 @@ testfailure() {
 	fi
 }
 
+testaccessrights() {
+	msgtest "Test that file $1 has access rights set to" "$2"
+	if [ "$2" = "$(stat --format '%a' "$1")" ]; then
+		msgpass
+	else
+		echo >&2
+		ls -l >&2 "$1"
+		echo -n >&2 "stat(1) reports access rights: "
+		stat --format '%a' "$1"
+		msgfail
+	fi
+}
+
 testwebserverlaststatuscode() {
 	local DOWNLOG='rootdir/tmp/webserverstatus-testfile.log'
 	local STATUS='rootdir/tmp/webserverstatus-statusfile.log'

+ 1 - 1
test/integration/test-apt-by-hash-update

@@ -34,7 +34,7 @@ Building dependency tree...
 E: Unable to locate package foo" aptget install -q -s foo
 
 # ensure we can apt-get update by hash
-testsuccess aptget update -o APT::Acquire::By-Hash=1
+testsuccess aptget update -o APT::Acquire::By-Hash=1 
 
 # ensure it works
 testequal "Inst foo (1.0 unstable [all])

+ 1 - 0
test/integration/test-apt-get-clean

@@ -18,6 +18,7 @@ testsuccess aptget clean
 
 # generate some dirt and clean it up
 touch rootdir/var/lib/apt/lists/partial/http.debian.net_debian_dists_sid_main_i18n_Translation-en
+mkdir -p rootdir/var/cache/apt/archives
 touch rootdir/var/cache/apt/archives/foo_1_all.deb
 touch rootdir/var/cache/apt/archives/foo_2_all.deb
 touch rootdir/var/cache/apt/archives/foo_3_all.deb

+ 16 - 0
test/integration/test-apt-get-download

@@ -11,8 +11,23 @@ buildsimplenativepackage 'apt' 'all' '1.0' 'stable'
 buildsimplenativepackage 'apt' 'all' '2.0' 'unstable'
 insertinstalledpackage 'vrms' 'all' '1.0'
 
+umask 0027
+
 setupaptarchive
 
+# apt-ftparchive knows how to chmod files
+find aptarchive/dists -name '*Packages*' -type f | while read file; do
+	testaccessrights "$file" '644'
+done
+# created by the framework without special care
+find aptarchive/dists -name '*Release*' -type f | while read file; do
+	testaccessrights "$file" '640'
+done
+# all copied files are properly chmodded
+find rootdir/var/lib/apt/lists -type f | while read file; do
+	testaccessrights "$file" '644'
+done
+
 testdownload() {
 	local APT="$2"
 	if [ -n "$3" ]; then
@@ -65,6 +80,7 @@ testsuccess aptget update
 # test with already stored deb
 testsuccess aptget install -d apt
 testsuccess test -s rootdir/var/cache/apt/archives/apt_2.0_all.deb
+testaccessrights 'aptarchive/pool/apt_2.0_all.deb' '644'
 mv aptarchive/pool/apt_2.0_all.deb aptarchive/pool/apt_2.0_all.deb.gone
 testdownload apt_2.0_all.deb apt
 mv aptarchive/pool/apt_2.0_all.deb.gone aptarchive/pool/apt_2.0_all.deb

+ 1 - 1
test/integration/test-apt-get-source-authenticated

@@ -21,7 +21,7 @@ APTARCHIVE=$(readlink -f ./aptarchive)
 rm -f $APTARCHIVE/dists/unstable/*Release*
 
 # update without authenticated InRelease file
-testsuccess aptget update
+testsuccess aptget update --allow-insecure-repositories
 
 # this all should fail
 testfailure aptget install -y foo

+ 46 - 0
test/integration/test-apt-get-update-unauth-warning

@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# ensure we print warnings for unauthenticated repositories
+# 
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+# a "normal" package with source and binary
+buildsimplenativepackage 'foo' 'all' '2.0'
+
+setupaptarchive --no-update
+
+APTARCHIVE=$(readlink -f ./aptarchive)
+rm -f $APTARCHIVE/dists/unstable/*Release*
+
+# update without authenticated files leads to warning
+testequal "Ign file: unstable InRelease
+  File not found
+Err file: unstable Release
+  File not found
+W: The repository 'file: unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository.
+W: Use --allow-insecure-repositories to force the update
+W: Failed to fetch file:$APTARCHIVE/dists/unstable/Release  File not found
+
+E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update
+
+# no package foo
+testequal "Listing..." apt list foo
+testequal "partial" ls rootdir/var/lib/apt/lists
+
+# allow override
+testequal "Ign file: unstable InRelease
+  File not found
+Ign file: unstable Release
+  File not found
+Reading package lists...
+W: The repository 'file: unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." aptget update --allow-insecure-repositories
+# ensure we can not install the package
+testequal "WARNING: The following packages cannot be authenticated!
+  foo
+E: There are problems and -y was used without --force-yes" aptget install -qq -y foo

+ 85 - 0
test/integration/test-apt-update-ims

@@ -0,0 +1,85 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable'
+
+setupaptarchive
+changetowebserver
+
+runtest() {
+    rm -f rootdir/var/lib/apt/lists/localhost*
+
+    testsuccess aptget update
+
+    # ensure no leftovers in partial
+    testfailure ls "rootdir/var/lib/apt/lists/partial/*"
+
+    # check that I-M-S header is kept in redirections
+    testequal "$EXPECT" aptget update  -o Debug::pkgAcquire::Worker=0 -o Debug::Acquire::http=0
+    
+    # ensure that we still do a hash check on ims hit
+    msgtest 'Test I-M-S reverify'
+    aptget update -o Debug::pkgAcquire::Auth=1 2>&1 | grep -A1 'RecivedHash:' | grep -q -- '- SHA' && msgpass || msgfail
+
+    # ensure no leftovers in partial
+    testfailure ls "rootdir/var/lib/apt/lists/partial/*"
+}
+
+msgmsg "InRelease"
+EXPECT="Hit http://localhost:8080 unstable InRelease
+Hit http://localhost:8080 unstable/main Sources
+Hit http://localhost:8080 unstable/main amd64 Packages
+Hit http://localhost:8080 unstable/main Translation-en
+Reading package lists..."
+# with InRelease
+runtest
+
+# with gzip
+echo "Acquire::GzipIndexes "1";" > rootdir/etc/apt/apt.conf.d/02compressindex
+runtest
+
+msgmsg "Release/Release.gpg"
+# with Release/Release.gpg
+EXPECT="Ign http://localhost:8080 unstable InRelease
+  404  Not Found
+Hit http://localhost:8080 unstable Release
+Hit http://localhost:8080 unstable Release.gpg
+Hit http://localhost:8080 unstable/main Sources
+Hit http://localhost:8080 unstable/main amd64 Packages
+Hit http://localhost:8080 unstable/main Translation-en
+Reading package lists..."
+
+find aptarchive -name "InRelease" | xargs rm -f
+
+echo "Acquire::GzipIndexes "0";" > rootdir/etc/apt/apt.conf.d/02compressindex
+runtest
+
+echo "Acquire::GzipIndexes "1";" > rootdir/etc/apt/apt.conf.d/02compressindex
+runtest
+
+
+# no Release.gpg or InRelease
+msgmsg "Release only"
+EXPECT="Ign http://localhost:8080 unstable InRelease
+  404  Not Found
+Hit http://localhost:8080 unstable Release
+Ign http://localhost:8080 unstable Release.gpg
+  404  Not Found
+Hit http://localhost:8080 unstable/main Sources
+Hit http://localhost:8080 unstable/main amd64 Packages
+Hit http://localhost:8080 unstable/main Translation-en
+Reading package lists..."
+
+find aptarchive -name "Release.gpg" | xargs rm -f
+
+echo 'Acquire::AllowInsecureRepositories "1";' > rootdir/etc/apt/apt.conf.d/insecure.conf
+echo "Acquire::GzipIndexes "0";" > rootdir/etc/apt/apt.conf.d/02compressindex
+runtest
+
+echo "Acquire::GzipIndexes "1";" > rootdir/etc/apt/apt.conf.d/02compressindex
+runtest

+ 234 - 0
test/integration/test-apt-update-nofallback

@@ -0,0 +1,234 @@
+#!/bin/sh
+#
+# ensure we never fallback from a signed to a unsigned repo
+# 
+# hash checks are done in 
+# 
+set -e
+
+simulate_mitm_and_inject_evil_package()
+{
+    rm -f $APTARCHIVE/dists/unstable/InRelease
+    rm -f $APTARCHIVE/dists/unstable/Release.gpg
+    inject_evil_package
+}
+
+inject_evil_package()
+{
+    cat > $APTARCHIVE/dists/unstable/main/binary-i386/Packages <<EOF
+Package: evil
+Installed-Size: 29
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Version: 1.0
+Filename: pool/evil_1.0_all.deb
+Size: 1270
+Description: an autogenerated evil package
+EOF
+    # avoid ims hit
+    touch -d '+1hour' aptarchive/dists/unstable/main/binary-i386/Packages
+}
+
+assert_update_is_refused_and_last_good_state_used()
+{
+    testequal "E: The repository 'file: unstable Release.gpg' is no longer signed." aptget update -qq
+
+    assert_repo_is_intact
+}
+
+assert_repo_is_intact()
+{
+    testequal "foo/unstable 2.0 all" apt list -q
+    testsuccess "" aptget install -y -s foo
+    testfailure "" aptget install -y evil
+
+    LISTDIR=rootdir/var/lib/apt/lists
+    if ! ( ls $LISTDIR/*InRelease >/dev/null 2>&1 || 
+            ls $LISTDIR/*Release.gpg >/dev/null 2>&1 ); then
+        echo "Can not find InRelease/Release.gpg in $(ls $LISTDIR)"
+        msgfail
+    fi
+}
+
+setupaptarchive_with_lists_clean()
+{
+    setupaptarchive --no-update
+    rm -f rootdir/var/lib/apt/lists/_*
+    #rm -rf rootdir/var/lib/apt/lists
+}
+
+test_from_inrelease_to_unsigned()
+{
+    # setup archive with InRelease file
+    setupaptarchive_with_lists_clean
+    testsuccess aptget update
+
+    simulate_mitm_and_inject_evil_package
+    assert_update_is_refused_and_last_good_state_used
+}
+
+test_from_release_gpg_to_unsigned()
+{
+    # setup archive with Release/Release.gpg (but no InRelease)
+    setupaptarchive_with_lists_clean
+    rm $APTARCHIVE/dists/unstable/InRelease
+    testsuccess aptget update
+
+    simulate_mitm_and_inject_evil_package
+    assert_update_is_refused_and_last_good_state_used
+}
+
+test_from_inrelease_to_unsigned_with_override()
+{
+    # setup archive with InRelease file
+    setupaptarchive_with_lists_clean
+    testsuccess aptget update
+
+    # simulate moving to a unsigned but otherwise valid repo
+    simulate_mitm_and_inject_evil_package
+    generatereleasefiles
+
+    # and ensure we can update to it (with enough force) 
+    testsuccess aptget update --allow-insecure-repositories \
+        -o Acquire::AllowDowngradeToInsecureRepositories=1
+    # but that the individual packages are still considered untrusted
+    testequal "WARNING: The following packages cannot be authenticated!
+  evil
+E: There are problems and -y was used without --force-yes" aptget install -qq -y evil
+}
+
+test_cve_2012_0214()
+{
+    # see https://bugs.launchpad.net/ubuntu/+source/apt/+bug/947108
+    #
+    # it was possible to MITM the download so that InRelease/Release.gpg
+    # are not delivered (404) and a altered Release file was send
+    #
+    # apt left the old InRelease file in /var/lib/apt/lists and downloaded
+    # the unauthenticated Release file too giving the false impression that
+    # Release was authenticated
+    #
+    # Note that this is pretty much impossible nowdays because:
+    # a) InRelease is left as is, not split to InRelease/Release as it was 
+    #    in the old days
+    # b) we refuse to go from signed->unsigned
+    #
+    # Still worth having a regression test the simulates the condition
+
+    # setup archive with InRelease
+    setupaptarchive_with_lists_clean
+    testsuccess aptget update
+
+    # do what CVE-2012-0214 did
+    rm $APTARCHIVE/dists/unstable/InRelease
+    rm $APTARCHIVE/dists/unstable/Release.gpg
+    inject_evil_package
+    # build valid Release file
+    aptftparchive -qq release ./aptarchive > aptarchive/dists/unstable/Release 
+
+    assert_update_is_refused_and_last_good_state_used
+
+    # ensure there is no _Release file downloaded
+    testfailure ls rootdir/var/lib/apt/lists/*_Release
+}
+
+test_subvert_inrelease()
+{
+    # setup archive with InRelease
+    setupaptarchive_with_lists_clean
+    testsuccess aptget update
+
+    # replace InRelease with something else
+    mv $APTARCHIVE/dists/unstable/Release $APTARCHIVE/dists/unstable/InRelease
+
+    testequal "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease  Does not start with a cleartext signature
+
+E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+    # ensure we keep the repo
+    assert_repo_is_intact
+}
+
+test_inrelease_to_invalid_inrelease()
+{
+    # setup archive with InRelease
+    setupaptarchive_with_lists_clean
+    testsuccess aptget update
+
+    # now remove InRelease and subvert Release do no longer verify
+    sed -i 's/Codename.*/Codename: evil!'/ $APTARCHIVE/dists/unstable/InRelease
+    inject_evil_package
+
+    testequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
+
+W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease  The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
+
+W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+    # ensure we keep the repo
+    assert_repo_is_intact
+    testfailure grep "evil" rootdir/var/lib/apt/lists/*InRelease
+}
+
+test_release_gpg_to_invalid_release_release_gpg()
+{
+    # setup archive with InRelease
+    setupaptarchive_with_lists_clean
+    rm $APTARCHIVE/dists/unstable/InRelease
+    testsuccess aptget update
+
+    # now subvert Release do no longer verify
+    echo "Some evil data" >>  $APTARCHIVE/dists/unstable/Release
+    inject_evil_package
+
+    testequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable Release.gpg: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
+
+W: Failed to fetch file:${APTARCHIVE}/dists/unstable/Release.gpg  
+
+W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+    assert_repo_is_intact
+    testfailure grep "evil" rootdir/var/lib/apt/lists/*Release
+}
+
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+# a "normal" package with source and binary
+buildsimplenativepackage 'foo' 'all' '2.0'
+
+# setup the archive and ensure we have a single package that installs fine
+setupaptarchive
+APTARCHIVE=$(readlink -f ./aptarchive)
+assert_repo_is_intact
+
+# test the various cases where a repo may go from signed->unsigned
+msgmsg "test_from_inrelease_to_unsigned"
+test_from_inrelease_to_unsigned
+
+msgmsg "test_from_release_gpg_to_unsigned"
+test_from_release_gpg_to_unsigned
+
+# ensure we do not regress on CVE-2012-0214
+msgmsg "test_cve_2012_0214"
+test_cve_2012_0214
+
+# ensure InRelase can not be subverted
+msgmsg "test_subvert_inrelease"
+test_subvert_inrelease
+
+# ensure we revert to last good state if InRelease does not verify
+msgmsg "test_inrelease_to_invalid_inrelease"
+test_inrelease_to_invalid_inrelease
+
+# ensure we revert to last good state if Release/Release.gpg does not verify
+msgmsg "test_release_gpg_to_invalid_release_release_gpg"
+test_release_gpg_to_invalid_release_release_gpg
+
+# ensure we can ovveride the downgrade error
+msgmsg "test_from_inrelease_to_unsigned"
+test_from_inrelease_to_unsigned_with_override

+ 195 - 0
test/integration/test-apt-update-rollback

@@ -0,0 +1,195 @@
+#!/bin/sh
+#
+# test that apt-get update is transactional
+# 
+set -e
+
+avoid_ims_hit() {
+    touch -d '+1hour' aptarchive/dists/unstable/main/binary-i386/Packages*
+    touch -d '+1hour' aptarchive/dists/unstable/main/source/Sources*
+    touch -d '+1hour' aptarchive/dists/unstable/*Release*
+
+    touch -d '-1hour' rootdir/var/lib/apt/lists/*
+}
+
+create_fresh_archive()
+{
+    rm -rf aptarchive/*
+    rm -f rootdir/var/lib/apt/lists/_* rootdir/var/lib/apt/lists/partial/*
+
+    insertpackage 'unstable' 'old' 'all' '1.0'
+
+    setupaptarchive --no-update
+}
+
+add_new_package() {
+    insertpackage "unstable" "new" "all" "1.0"
+    insertsource "unstable" "new" "all" "1.0"
+
+    setupaptarchive --no-update "$@"
+}
+
+break_repository_sources_index() {
+    printf 'xxx' > $APTARCHIVE/dists/unstable/main/source/Sources
+    compressfile "$APTARCHIVE/dists/unstable/main/source/Sources" "$@"
+}
+
+start_with_good_inrelease() {
+    create_fresh_archive
+    testsuccess aptget update
+    testequal "old/unstable 1.0 all" apt list -q
+}
+
+test_inrelease_to_new_inrelease() {
+    msgmsg 'Test InRelease to new InRelease works fine'
+    start_with_good_inrelease
+
+    add_new_package '+1hour'
+    testsuccess aptget update -o Debug::Acquire::Transaction=1
+    testequal "new/unstable 1.0 all
+old/unstable 1.0 all" apt list -q
+}
+
+test_inrelease_to_broken_hash_reverts_all() {
+    msgmsg 'Test InRelease to broken InRelease reverts everything'
+    start_with_good_inrelease
+
+    add_new_package '+1hour'
+    # break the Sources file
+    break_repository_sources_index '+1hour'
+
+    # test the error condition
+    testequal "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/main/source/Sources  Hash Sum mismatch
+
+E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+    # ensure that the Packages file is also rolled back
+    testequal "E: Unable to locate package new" aptget install new -s -qq
+}
+
+test_inrelease_to_valid_release() {
+    msgmsg 'Test InRelease to valid Release'
+    start_with_good_inrelease
+
+    add_new_package '+1hour'
+    # switch to a unsigned repo now
+    rm $APTARCHIVE/dists/unstable/InRelease
+    rm $APTARCHIVE/dists/unstable/Release.gpg
+
+    # update fails
+    testequal "E: The repository 'file: unstable Release.gpg' is no longer signed." aptget update -qq
+
+    # test that we can install the new packages but do no longer have a sig
+    testsuccess aptget install old -s
+    testfailure aptget install new -s
+    testsuccess ls $ROOTDIR/var/lib/apt/lists/*_InRelease
+    testfailure ls $ROOTDIR/var/lib/apt/lists/*_Release
+}
+
+test_inrelease_to_release_reverts_all() {
+    msgmsg 'Test InRelease to broken Release reverts everything'
+    start_with_good_inrelease
+
+    # switch to a unsigned repo now
+    add_new_package '+1hour'
+    rm $APTARCHIVE/dists/unstable/InRelease
+    rm $APTARCHIVE/dists/unstable/Release.gpg
+
+    # break it
+    break_repository_sources_index '+1hour'
+
+    # ensure error
+    testequal "E: The repository 'file: unstable Release.gpg' is no longer signed." aptget update -qq # -o Debug::acquire::transaction=1
+
+    # ensure that the Packages file is also rolled back
+    testsuccess aptget install old -s
+    testfailure aptget install new -s
+    testsuccess ls $ROOTDIR/var/lib/apt/lists/*_InRelease
+    testfailure ls $ROOTDIR/var/lib/apt/lists/*_Release
+}
+
+test_unauthenticated_to_invalid_inrelease() {
+    msgmsg 'Test UnAuthenticated to invalid InRelease reverts everything'
+    create_fresh_archive
+    rm $APTARCHIVE/dists/unstable/InRelease
+    rm $APTARCHIVE/dists/unstable/Release.gpg
+
+    testsuccess aptget update --allow-insecure-repositories
+    testequal "WARNING: The following packages cannot be authenticated!
+  old
+E: There are problems and -y was used without --force-yes" aptget install -qq -y old
+
+    # go to authenticated but not correct
+    add_new_package '+1hour'
+    break_repository_sources_index '+1hour'
+
+    testequal "W: Failed to fetch file:$APTARCHIVE/dists/unstable/main/source/Sources  Hash Sum mismatch
+
+E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+    testfailure ls rootdir/var/lib/apt/lists/*_InRelease
+    testequal "WARNING: The following packages cannot be authenticated!
+  old
+E: There are problems and -y was used without --force-yes" aptget install -qq -y old
+}
+
+test_inrelease_to_unauth_inrelease() {
+    msgmsg 'Test InRelease to InRelease without good sig'
+    start_with_good_inrelease
+
+    signreleasefiles 'Marvin Paranoid' '+1hour'
+
+    testequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2
+
+W: Failed to fetch file:$APTARCHIVE/dists/unstable/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2
+
+W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+    testsuccess ls rootdir/var/lib/apt/lists/*_InRelease
+}
+
+test_inrelease_to_broken_gzip() {
+    msgmsg "Test InRelease to broken gzip"
+    start_with_good_inrelease
+
+    # append junk at the end of the compressed file
+    echo "lala" >> $APTARCHIVE/dists/unstable/main/source/Sources.gz
+    touch -d '+2min' $APTARCHIVE/dists/unstable/main/source/Sources.gz
+    # remove uncompressed file to avoid fallback
+    rm $APTARCHIVE/dists/unstable/main/source/Sources
+
+    testfailure aptget update
+}
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+# setup the archive and ensure we have a single package that installs fine
+setupaptarchive
+APTARCHIVE=$(readlink -f ./aptarchive)
+ROOTDIR=${TMPWORKINGDIRECTORY}/rootdir
+APTARCHIVE_LISTS="$(echo $APTARCHIVE | tr "/" "_" )"
+
+# test the following cases:
+# - InRelease -> broken InRelease revert to previous state
+# - empty lists dir and broken remote leaves nothing on the system
+# - InRelease -> hashsum mismatch for one file reverts all files to previous state
+# - Release/Release.gpg -> hashsum mismatch
+# - InRelease -> Release with hashsum mismatch revert entire state and kills Release
+# - Release -> InRelease with broken Sig/Hash removes InRelease
+# going from Release/Release.gpg -> InRelease and vice versa
+# - unauthenticated -> invalid InRelease
+
+# stuff to do:
+# - ims-hit
+# - gzip-index tests
+
+test_inrelease_to_new_inrelease
+test_inrelease_to_broken_hash_reverts_all
+test_inrelease_to_valid_release
+test_inrelease_to_release_reverts_all
+test_unauthenticated_to_invalid_inrelease
+test_inrelease_to_unauth_inrelease
+test_inrelease_to_broken_gzip

+ 24 - 0
test/integration/test-apt-update-transactions

@@ -0,0 +1,24 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+
+setupaptarchive --no-update
+changetowebserver
+
+# break package file
+cat > aptarchive/dists/unstable/main/binary-i386/Packages <<EOF
+Package: bar
+EOF
+compressfile aptarchive/dists/unstable/main/binary-i386/Packages '+1hour'
+
+# ensure that a update will only succeed entirely or not at all
+testfailure aptget update
+testequal "partial" ls rootdir/var/lib/apt/lists
+

+ 39 - 8
test/integration/test-apt-update-unauth

@@ -8,6 +8,8 @@ set -e
 TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 
+umask 022
+
 setupenvironment
 configarchitecture "i386"
 
@@ -17,23 +19,53 @@ insertsource 'unstable' 'foo' 'all' '1.0'
 setupaptarchive
 changetowebserver
 
+# FIXME: 
+#  - also check the unauth -> auth success case, i.e. that all files are
+#    reverified
 runtest() {
     # start unauthenticated
     find rootdir/var/lib/apt/lists/ -type f | xargs rm -f
     rm -f aptarchive/dists/unstable/*Release*
-    aptget update -qq
+
+    testsuccess aptget update -qq --allow-insecure-repositories
+
+    # FIXME: this really shouldn't be needed
+    rm -f rootdir/var/lib/apt/lists/partial/*
 
     # become authenticated
     generatereleasefiles
     signreleasefiles
 
-    # and ensure we do download the data again
-    msgtest "Check that the data is check when going to authenticated"
-    if aptget update |grep -q Hit; then
-        msgfail
-    else
+    # move uncompressed away
+    mv aptarchive/dists/unstable/main/binary-i386/Packages \
+        aptarchive/dists/unstable/main/binary-i386/Packages.uncompressed
+
+    # and ensure we re-check the downloaded data
+
+    # change the local packages file
+    PKGS=$(ls rootdir/var/lib/apt/lists/*Packages*)
+    echo "meep" > $PKGS
+    ls rootdir/var/lib/apt/lists/ > lists.before
+
+    # update and ensure all is reverted on the hashsum failure
+    testfailure aptget update -o Debug::Acquire::Transaction=0 -o Debug::pkgAcquire::Auth=1 -o Debug::pkgAcquire::worker=0 -o Debug::acquire::http=0
+
+    # ensure we have before what we have after
+    msgtest 'Check rollback on going from' 'unauth -> auth'
+    ls rootdir/var/lib/apt/lists/ > lists.after
+    if cmp lists.before lists.after; then
         msgpass
+    else
+	echo >&2 '### Output of previous apt-get update ###'
+	cat >&2 rootdir/tmp/testfailure.output
+	echo >&2 '### Changes in the lists-directory: ###'
+	diff -u >&2 lists.before lists.after
+	msgfail
     fi
+
+    # move uncompressed back for release file
+    mv aptarchive/dists/unstable/main/binary-i386/Packages.uncompressed \
+        aptarchive/dists/unstable/main/binary-i386/Packages
 }
 
 for COMPRESSEDINDEXES in 'false' 'true'; do
@@ -43,6 +75,5 @@ for COMPRESSEDINDEXES in 'false' 'true'; do
 	else
 		msgmsg 'Run tests with GzipIndexes disabled'
 	fi
-
-        runtest
+	runtest
 done

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

@@ -13,7 +13,7 @@ setupflataptarchive
 testaptgetupdate() {
 	rm -rf rootdir/var/lib/apt
 	aptget update 2>> testaptgetupdate.diff >> testaptgetupdate.diff || true
-	sed -i -e '/Ign / d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
+	sed -i -e '/Ign /,+1d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
 	GIVEN="$1"
 	shift
 	msgtest "Test for correctness of" "apt-get update with $*"

+ 1 - 1
test/integration/test-bug-596498-trusted-unsigned-repo

@@ -12,7 +12,7 @@ setupaptarchive
 
 aptgetupdate() {
 	rm -rf rootdir/var/lib/apt/ rootdir/var/cache/apt/*.bin
-	aptget update -qq
+	aptget update -qq --allow-insecure-repositories
 }
 
 PKGTEXT="$(aptget install cool --assume-no -d | head -n 7)"

+ 4 - 1
test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted

@@ -24,15 +24,18 @@ testfilemissing() {
 
 testrun() {
 	rm -rf rootdir/var/lib/apt
-	testsuccess aptget update
 
 	if [ "$1" = 'trusted' ]; then
+	        testsuccess aptget update
+
 		testsuccess aptget download cool
 		testfileexists 'cool_1.0_i386.deb'
 
 		testsuccess aptget download cool --allow-unauthenticated
 		testfileexists 'cool_1.0_i386.deb'
 	else
+                testsuccess aptget update --allow-insecure-repositories
+
 		testfailure aptget download cool
 		testfilemissing 'cool_1.0_i386.deb'
 

+ 1 - 1
test/integration/test-bug-717891-abolute-uris-for-proxies

@@ -12,7 +12,7 @@ setupaptarchive
 changetowebserver --request-absolute='uri'
 
 msgtest 'Check that absolute paths are' 'not accepted'
-testfailure --nomsg aptget update
+testfailure --nomsg aptget update --allow-insecure-repositories
 
 echo 'Acquire::http::Proxy "http://localhost:8080";' > rootdir/etc/apt/apt.conf.d/99proxy
 

+ 1 - 1
test/integration/test-bug-728500-tempdir

@@ -17,7 +17,7 @@ msgtest 'Test apt-get update with incorrect' 'TMPDIR'
 OUTPUT=$(mktemp)
 addtrap "rm $OUTPUT;"
 export TMPDIR=/does-not-exists
-if aptget update >${OUTPUT} 2>&1; then
+if aptget update -o Debug::Acquire::gpg=1 >${OUTPUT} 2>&1; then
 	msgpass
 else
 	echo

+ 1 - 1
test/integration/test-bug-738785-switch-protocol

@@ -60,4 +60,4 @@ mv rootdir/${COPYMETHODS}.bak rootdir/${COPYMETHODS}
 # check that downgrades from https to http are not allowed
 webserverconfig 'aptwebserver::support::http' 'true'
 sed -i -e 's#:8080/redirectme#:4433/downgrademe#' -e 's# http:# https:#' rootdir/etc/apt/sources.list.d/*
-testfailure aptget update
+testfailure aptget update --allow-insecure-repositories

+ 2 - 2
test/integration/test-compressed-indexes

@@ -39,10 +39,10 @@ testrun() {
 		test -e rootdir/var/lib/apt/lists/*_Translation-en.${COMPRESS} || F=1
 		# there is no point in trying pdiff if we have compressed indexes
 		# as we can't patch compressed files (well, we can, but what is the point?)
-		! test -e rootdir/var/lib/apt/lists/*.IndexDiff || F=1
+		! test -e rootdir/var/lib/apt/lists/*diff_Index || F=1
 	else
 		# clear the faked pdiff indexes so the glob below works
-		rm -f rootdir/var/lib/apt/lists/*.IndexDiff
+		rm -f rootdir/var/lib/apt/lists/*diff_Index
 		test -e rootdir/var/lib/apt/lists/*_Packages || F=1
 		test -e rootdir/var/lib/apt/lists/*_Sources || F=1
 		test -e rootdir/var/lib/apt/lists/*_Translation-en || F=1

+ 7 - 3
test/integration/test-hashsum-verification

@@ -70,9 +70,13 @@ runtest() {
         rm -rf rootdir/var/lib/apt/lists
         rm aptarchive/InRelease aptarchive/Release.gpg
         msgtest 'unsigned apt-get update gets the expected hashsum mismatch'
-	aptget update 2>&1 | grep "Hash Sum mismatch" > /dev/null && msgpass || msgfail
-
-
+	aptget update --allow-insecure-repositories >output.log 2>&1 || true
+        if grep -q "Hash Sum mismatch" output.log; then
+            msgpass
+        else
+            cat output.log
+            msgfail
+        fi
 }
 
 for COMPRESSEDINDEXES in 'false' 'true'; do

+ 12 - 8
test/integration/test-http-pipeline-messup

@@ -7,10 +7,11 @@ TESTDIR=$(readlink -f $(dirname $0))
 setupenvironment
 configarchitecture "i386"
 
-buildsimplenativepackage 'pkga' 'all' '1.0' 'stable'
-buildsimplenativepackage 'pkgb' 'all' '1.0' 'stable'
-buildsimplenativepackage 'pkgc' 'all' '1.0' 'stable'
-buildsimplenativepackage 'pkgd' 'all' '1.0' 'stable'
+# try a little harder to create a size mismatch
+buildsimplenativepackage 'pkga' 'all' '1.0' 'stable' "Depends: foo" '' '' '' '' 'none'
+buildsimplenativepackage 'pkgb' 'all' '1.0' 'stable' "Depends: foo" '' '' '' '' 'none'
+buildsimplenativepackage 'pkgc' 'all' '1.0' 'stable' "Depends: f$(for i in $(seq 0 1000); do printf 'o'; done)" '' '' '' '' 'none'
+buildsimplenativepackage 'pkgd' 'all' '1.0' 'stable' "Depends: f$(for i in $(seq 0 1000); do printf 'o'; done)" '' '' '' '' 'none'
 
 setupaptarchive --no-update
 
@@ -21,17 +22,20 @@ changetowebserver \
 	-o 'aptwebserver::overwrite::.*pkgb.*::filename=/pool/pkgc_1.0_all.deb' \
 	-o 'aptwebserver::overwrite::.*pkgd.*::filename=/pool/pkga_1.0_all.deb'
 
-testsuccess aptget update -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+echo 'Debug::Acquire::http "true";
+Debug::pkgAcquire::Worker "true";' > rootdir/etc/apt/apt.conf.d/99debug
+
+testsuccess aptget update
 
 # messup is bigger than pipeline: checks if fixup isn't trying to hard
-testfailure aptget download pkga pkgb pkgc pkgd "$@" -o Acquire::http::Pipeline-Depth=2
+testfailure aptget download pkga pkgb pkgc pkgd -o Acquire::http::Pipeline-Depth=2
 testfailure test -f pkga_1.0_all.deb
 
 # ensure that pipeling is enabled for rest of this test
 echo 'Acquire::http::Pipeline-Depth 10;' > rootdir/etc/apt/apt.conf.d/99enable-pipeline
 
 # the output is a bit strange: it looks like it has downloaded pkga 4 times
-testsuccess aptget download pkga pkgb pkgc pkgd -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+testsuccess aptget download pkga pkgb pkgc pkgd
 for pkg in 'pkga' 'pkgb' 'pkgc' 'pkgd'; do
 	testsuccess test -f ${pkg}_1.0_all.deb
 	testsuccess cmp incoming/${pkg}_1.0_all.deb ${pkg}_1.0_all.deb
@@ -40,4 +44,4 @@ done
 
 # while hashes will pass (as none are available), sizes will not match, so failure
 # checks that no hashes means that pipeline depth is ignored as we can't fixup
-testfailure aptget download pkga pkgb pkgc pkgd "$@" --allow-unauthenticated -o Acquire::ForceHash=ROT26
+testfailure aptget download pkga pkgb pkgc pkgd --allow-unauthenticated -o Acquire::ForceHash=ROT26

+ 2 - 1
test/integration/test-pdiff-usage

@@ -94,7 +94,7 @@ SHA256-Patches:
 " aptcache show apt newstuff
 
 	msgmsg "Testcase: index is already up-to-date: $*"
-	find rootdir/var/lib/apt/lists -name '*.IndexDiff' -type f -delete
+	find rootdir/var/lib/apt/lists -name '*diff_Index' -type f -delete
 	testsuccess aptget update "$@"
 	testequal "$(cat ${PKGFILE}-new)
 " aptcache show apt newstuff
@@ -182,6 +182,7 @@ SHA256-Patches:
 " aptcache show apt newstuff
 }
 echo 'Debug::pkgAcquire::Diffs "true";
+Debug::Acquire::Transaction "true";
 Debug::pkgAcquire::rred "true";' > rootdir/etc/apt/apt.conf.d/rreddebug.conf
 
 testrun -o Acquire::PDiffs::Merge=0 -o APT::Get::List-Cleanup=1

+ 2 - 1
test/integration/test-policy-pinning

@@ -28,7 +28,7 @@ Pinned packages:" aptcache policy $*
 aptgetupdate() {
 	# just to be sure that no old files are used
 	rm -rf rootdir/var/lib/apt
-	if aptget update -qq 2>&1 | grep '^E: '; then
+	if aptget update  --allow-insecure-repositories -qq 2>&1 | grep '^E: '; then
 		msgwarn 'apt-get update failed with an error'
 	fi
 }
@@ -36,6 +36,7 @@ aptgetupdate() {
 ### not signed archive
 
 aptgetupdate
+
 testequalpolicy 100 500
 testequalpolicy 990 500 -t now
 

+ 12 - 1
test/integration/test-releasefile-verification

@@ -235,10 +235,21 @@ runtest2() {
 " aptcache show apt
 	failaptnew
 }
-runtest2
 
+# diable some protection by default and ensure we still do the verification
+# correctly
+cat > rootdir/etc/apt/apt.conf.d/weaken-security <<EOF
+Acquire::AllowInsecureRepositories "1";
+Acquire::AllowDowngradeToInsecureRepositories "1";
+EOF
+
+msgmsg "Runing base test"
+runtest2
 
 DELETEFILE="InRelease"
+msgmsg "Running test with deletion of $DELETEFILE"
 runtest
+
 DELETEFILE="Release.gpg"
+msgmsg "Running test with deletion of $DELETEFILE"
 runtest

+ 5 - 5
test/integration/test-ubuntu-bug-346386-apt-get-update-paywall

@@ -36,8 +36,8 @@ ensure_n_canary_strings_in_dir() {
 
 LISTS='rootdir/var/lib/apt/lists'
 rm -rf rootdir/var/lib/apt/lists
-msgtest 'Got expected NODATA failure in' 'apt-get update'
-aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+msgtest 'Got expected failure message' 'apt-get update'
+aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
 
 ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
 testequal 'partial' ls $LISTS
@@ -47,8 +47,8 @@ for f in Release Release.gpg main_binary-amd64_Packages main_source_Sources; do
     echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_${f}
 done
 
-msgtest 'Got expected NODATA failure in' 'apt-get update'
-aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+msgtest 'Got expected failure message in' 'apt-get update'
+aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
 
 ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 4
 ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
@@ -57,7 +57,7 @@ ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0
 echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_InRelease
 rm -f $LISTS/localhost:8080_dists_stable_Release $LISTS/localhost:8080_dists_stable_Release.gpg
 msgtest 'excpected failure of' 'apt-get update'
-aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail
+aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
 
 ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 3
 ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0

+ 1 - 3
test/integration/test-ubuntu-bug-784473-InRelease-one-message-only

@@ -28,12 +28,10 @@ MD5Sum:
 done
 
 msgtest 'The unsigned garbage before signed block is' 'ignored'
-testsuccess --nomsg aptget update
+aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail
 
 ROOTDIR="$(readlink -f .)"
 testequal "Package files:
  100 ${ROOTDIR}/rootdir/var/lib/dpkg/status
      release a=now
- 500 file:${ROOTDIR}/aptarchive/ unstable/main i386 Packages
-     release a=unstable,n=sid,c=main
 Pinned packages:" aptcache policy