From c99fe2e169243fc6e1a3278ce3768f0f521e260b Mon Sep 17 00:00:00 2001
From: Michael Vogt <mvo@ubuntu.com>
Date: Wed, 1 Oct 2014 12:21:55 +0200
Subject: [PATCH] Use
 Acquire::Allow{InsecureRepositories,DowngradeToInsecureRepositories}

The configuration key Acquire::AllowInsecureRepositories controls if
apt allows loading of unsigned repositories at all.

The configuration Acquire::AllowDowngradeToInsecureRepositories
controls if a signed repository can ever become unsigned. This
should really never be needed but we provide it to avoid having
to mess around in /var/lib/apt/lists if there is a use-case for
this (which I can't think of right now).
---
 apt-pkg/acquire-item.cc                       | 35 +++++++++++++------
 apt-pkg/init.cc                               |  4 +++
 apt-private/private-cmndline.cc               |  1 +
 doc/examples/configure-index                  |  2 +-
 .../test-apt-get-source-authenticated         |  2 +-
 .../test-apt-get-update-unauth-warning        |  4 +--
 test/integration/test-apt-update-nofallback   | 23 ++++++++++++
 test/integration/test-apt-update-rollback     |  2 +-
 test/integration/test-apt-update-unauth       |  2 +-
 .../test-bug-596498-trusted-unsigned-repo     |  2 +-
 ...-allow-unauthenticated-makes-all-untrusted |  4 +--
 .../test-bug-717891-abolute-uris-for-proxies  |  2 +-
 .../test-bug-738785-switch-protocol           |  2 +-
 test/integration/test-hashsum-verification    |  2 +-
 test/integration/test-policy-pinning          |  2 +-
 15 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 4a684f40c..93ba098ee 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -1629,14 +1629,27 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
                                          "InRelease");
    string FinalInRelease = _config->FindDir("Dir::State::lists") + URItoFileName(InReleaseURI);
 
-   if(RealFileExists(Final) || RealFileExists(FinalInRelease))
+   if (RealFileExists(Final) || RealFileExists(FinalInRelease))
    {
-      _error->Error("The repository '%s' is no longer signed.",
-                    URIDesc.c_str());
-      Rename(MetaIndexFile, MetaIndexFile+".FAILED");
-      Status = pkgAcquire::Item::StatError;
-      TransactionManager->AbortTransaction();
-      return;
+      std::string downgrade_msg;
+      strprintf(downgrade_msg, _("The repository '%s' is no longer signed."),
+                URIDesc.c_str());
+      if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories"))
+      {
+         // meh, the users wants to take risks (we still mark the packages
+         // from this repository as unauthenticated)
+         _error->Warning("%s", downgrade_msg.c_str());
+         _error->Warning(_("This is normally not allowed, but the option "
+                           "Acquire::AllowDowngradeToInsecureRepositories was "
+                           "given to override it."));
+         
+      } else {
+         _error->Error("%s", downgrade_msg.c_str());
+         Rename(MetaIndexFile, MetaIndexFile+".FAILED");
+         Status = pkgAcquire::Item::StatError;
+         TransactionManager->AbortTransaction();
+         return;
+      }
    }
 
    // this ensures that any file in the lists/ dir is removed by the
@@ -1654,7 +1667,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
    }
 
    // only allow going further if the users explicitely wants it
-   if(_config->FindB("APT::Get::AllowUnauthenticated", false) == true)
+   if(_config->FindB("Acquire::AllowInsecureRepositories") == true)
    {
       // we parse the indexes here because at this point the user wanted
       // a repository that may potentially harm him
@@ -1663,7 +1676,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
    } 
    else 
    {
-      _error->Warning("Use --allow-unauthenticated to force the update");
+      _error->Warning("Use --allow-insecure-repositories to force the update");
    }
 
    // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor
@@ -2123,12 +2136,12 @@ void pkgAcqMetaIndex::Failed(string Message,
    // No Release file was present, or verification failed, so fall
    // back to queueing Packages files without verification
    // only allow going further if the users explicitely wants it
-   if(_config->FindB("APT::Get::AllowUnauthenticated", false) == true)
+   if(_config->FindB("Acquire::AllowInsecureRepositories") == true)
    {
       QueueIndexes(false);
    } else {
       // warn if the repository is unsinged
-      _error->Warning("Use --allow-unauthenticated to force the update");
+      _error->Warning("Use --allow-insecure-repositories to force the update");
    } 
 }
 									/*}}}*/
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index 241628632..82dff4ee8 100644
--- a/apt-pkg/init.cc
+++ b/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/");
 
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index a4490f5b4..079f81ee3 100644
--- a/apt-private/private-cmndline.cc
+++ b/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);
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index 2d9f829ba..2925733d7 100644
--- a/doc/examples/configure-index
+++ b/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";
diff --git a/test/integration/test-apt-get-source-authenticated b/test/integration/test-apt-get-source-authenticated
index d73097b54..d833ddd85 100755
--- a/test/integration/test-apt-get-source-authenticated
+++ b/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 --allow-unauthenticated
+testsuccess aptget update --allow-insecure-repositories
 
 # this all should fail
 testfailure aptget install -y foo
diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning
index b1c676738..510249747 100755
--- a/test/integration/test-apt-get-update-unauth-warning
+++ b/test/integration/test-apt-get-update-unauth-warning
@@ -23,7 +23,7 @@ testequal "Ign file: unstable InRelease
 Ign file: unstable Release
 Reading package lists...
 W: The data from 'file: unstable Release' is not signed. Packages from that repository can not be authenticated.
-W: Use --allow-unauthenticated to force the update" aptget update
+W: Use --allow-insecure-repositories to force the update" aptget update
 
 # no package foo
 testequal "Listing..." apt list foo
@@ -32,7 +32,7 @@ testequal "Listing..." apt list foo
 testequal "Ign file: unstable InRelease
 Ign file: unstable Release
 Reading package lists...
-W: The data from 'file: unstable Release' is not signed. Packages from that repository can not be authenticated." aptget update --allow-unauthenticated
+W: The data from 'file: unstable Release' is not signed. Packages from that repository can not be authenticated." aptget update --allow-insecure-repositories
 
 # ensure we can not install the package
 testequal "WARNING: The following packages cannot be authenticated!
diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback
index 4e8ea9916..a53226e18 100755
--- a/test/integration/test-apt-update-nofallback
+++ b/test/integration/test-apt-update-nofallback
@@ -78,6 +78,25 @@ test_from_release_gpg_to_unsigned()
     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
@@ -205,3 +224,7 @@ 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
diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback
index e37be9554..ee8bc6926 100755
--- a/test/integration/test-apt-update-rollback
+++ b/test/integration/test-apt-update-rollback
@@ -114,7 +114,7 @@ test_unauthenticated_to_invalid_inrelease() {
     rm $APTARCHIVE/dists/unstable/Release.gpg
     avoid_ims_hit
     
-    testsuccess aptget update -qq --allow-unauthenticated
+    testsuccess aptget update -qq --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
diff --git a/test/integration/test-apt-update-unauth b/test/integration/test-apt-update-unauth
index 5db8a3c16..ade523ea7 100755
--- a/test/integration/test-apt-update-unauth
+++ b/test/integration/test-apt-update-unauth
@@ -28,7 +28,7 @@ runtest() {
     rm -f aptarchive/dists/unstable/*Release*
     # remove uncompressed version
     find aptarchive/ -name Packages | xargs rm -f
-    aptget update -qq --allow-unauthenticated
+    aptget update -qq --allow-insecure-repositories
 
     # become authenticated
     generatereleasefiles
diff --git a/test/integration/test-bug-596498-trusted-unsigned-repo b/test/integration/test-bug-596498-trusted-unsigned-repo
index 973520a97..3104a70c2 100755
--- a/test/integration/test-bug-596498-trusted-unsigned-repo
+++ b/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 --allow-unauthenticated
+	aptget update -qq --allow-insecure-repositories
 }
 
 PKGTEXT="$(aptget install cool --assume-no -d | head -n 7)"
diff --git a/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted b/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted
index 276e10564..0736bb6dc 100755
--- a/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted
+++ b/test/integration/test-bug-617690-allow-unauthenticated-makes-all-untrusted
@@ -26,7 +26,7 @@ testrun() {
 	rm -rf rootdir/var/lib/apt
 
 	if [ "$1" = 'trusted' ]; then
-	    testsuccess aptget update
+	        testsuccess aptget update
 
 		testsuccess aptget download cool
 		testfileexists 'cool_1.0_i386.deb'
@@ -34,7 +34,7 @@ testrun() {
 		testsuccess aptget download cool --allow-unauthenticated
 		testfileexists 'cool_1.0_i386.deb'
 	else
-	    testsuccess aptget update --allow-unauthenticated
+                testsuccess aptget update --allow-insecure-repositories
 
 		testfailure aptget download cool
 		testfilemissing 'cool_1.0_i386.deb'
diff --git a/test/integration/test-bug-717891-abolute-uris-for-proxies b/test/integration/test-bug-717891-abolute-uris-for-proxies
index a8947b5e2..54a616686 100755
--- a/test/integration/test-bug-717891-abolute-uris-for-proxies
+++ b/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 --allow-unauthenticated
+testfailure --nomsg aptget update --allow-insecure-repositories
 
 echo 'Acquire::http::Proxy "http://localhost:8080";' > rootdir/etc/apt/apt.conf.d/99proxy
 
diff --git a/test/integration/test-bug-738785-switch-protocol b/test/integration/test-bug-738785-switch-protocol
index 4ff044515..f81bba4b9 100755
--- a/test/integration/test-bug-738785-switch-protocol
+++ b/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 --allow-unauthenticated
+testfailure aptget update --allow-insecure-repositories
diff --git a/test/integration/test-hashsum-verification b/test/integration/test-hashsum-verification
index 2db2bab0f..5f88110b3 100755
--- a/test/integration/test-hashsum-verification
+++ b/test/integration/test-hashsum-verification
@@ -70,7 +70,7 @@ 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 --allow-unauthenticated >output.log 2>&1 || true
+	aptget update --allow-insecure-repositories >output.log 2>&1 || true
         if grep -q "Hash Sum mismatch" output.log; then
             msgpass
         else
diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning
index 2281d7a1d..c08a2f103 100755
--- a/test/integration/test-policy-pinning
+++ b/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  --allow-unauthenticated -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
 }
-- 
2.47.2