Hallo,
* Adam D. Barratt [Tue, Jan 28 2020, 10:28:08PM]:

> > I can, of course, convert all that into debian/patches/XXX but
> > honestly, that would really feel like greenwashing.
> >
> > The changes reported here can be reviewed at
> > https://salsa.debian.org/blade/apt-cacher-ng/commits/temp/debian-merge ,
> > starting with the commit from 2019-12-20.
>
> Those look OK as individual commits, thanks. For completeness, could we
> please have a finalised source debdiff of the built source package,
> compared to current stable?

Of course, attached.

Although, there are a couple of changes which I added on top:
a) removing -Wl,threads from considered linker options. That's a non-functional 
change, supposed to counteract FTBFS on mipsel/mips64el which I had experienced 
recently (there is a similar workaround in Testing, which detects mipsel 
explicitly, but this change simply removed -Wl,threads completely for all 
architectures which is the safer option, IMHO)
b) upstreaming the fix of #928957 (this was approved last year for Stable 
already, the code just wanders from debian-patch into upstream change)

BTW, there is one remaining change in the Debian diff on the systemd file which 
I will keep as is. It existed already in Stable. Not critical and not that 
important, and might be upstreamed in Sid, sooner or later.

Best regards,
Eduard.
diff -Nru apt-cacher-ng-3.2/CMakeLists.txt apt-cacher-ng-3.2.1/CMakeLists.txt
--- apt-cacher-ng-3.2/CMakeLists.txt	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/CMakeLists.txt	2020-02-03 19:54:57.000000000 +0100
@@ -58,6 +58,8 @@
 if(NOT DEFINED(RUNDIR))
 	set(RUNDIR "/run")
 endif()
+set(SOCKET_PATH "${RUNDIR}/${PACKAGE}/socket")
+

 # carefully splicing of command line arguments, even from lists
 macro(_append varname)
@@ -106,7 +108,7 @@
         _append(ACNG_CXXFLAGS -fvisibility-inlines-hidden)
 endif()

-foreach(linkarg -Wl,--as-needed -Wl,-O1 -Wl,--discard-all -Wl,--no-undefined -Wl,--build-id=sha1 -Wl,-fuse-ld=gold -Wl,--threads)
+foreach(linkarg -Wl,--as-needed -Wl,-O1 -Wl,--discard-all -Wl,--no-undefined -Wl,--build-id=sha1 -Wl,-fuse-ld=gold)
 	STRING(REGEX REPLACE "=|-|," "" optname "${linkarg}")
 	set(CMAKE_REQUIRED_FLAGS "${linkarg}")
 	CHECK_CXX_COMPILER_FLAG("" "LD_${optname}")
diff -Nru apt-cacher-ng-3.2/ChangeLog apt-cacher-ng-3.2.1/ChangeLog
--- apt-cacher-ng-3.2/ChangeLog	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/ChangeLog	2020-02-03 19:54:57.000000000 +0100
@@ -1,3 +1,38 @@
+apt-cacher-ng (3.2.1) SHAUN-OF-THE-LIVING; urgency=medium
+
+  * POTENTIAL SECURITY ISSUE (CVE-2020-5202):
+    - in certain situations, the maint job run by acngtool could leak the
+      administrator credentials from apt-cacher-ng configuration. This is only
+      likely if the attacker is able to impersonate the daemon with an own
+      server listening on the same port.
+    - The mitigation path for this is:
+      - SocketPath option is configured by default
+      - By default, acngtool only attempts to run the maint job through the
+        Unix Domain Socket. If SocketPath is not set but admin credentials are
+        configured, the operation is denied.
+      - For non-standard cases where acngtool is used to run special arbitrary
+        commands (ACNG_REQ variable) and the operation through SocketPath is not
+        possible (i.e. missing permissions or the tool is run on a different
+        host), the operation through TCP can be enforced with ACNG_INSECURE
+        environment variable
+
+  [ REALITY SYNC ]
+  * increased size of the decompression line buffer for config file reading
+    (Debian bug #942634)
+  * Support .zst compressed packages (reference:
+    https://www.archlinux.org/news/now-using-zstandard-instead-of-xz-for-package-compression/ )
+
+  [ Debian Stable Bugfix ]
+  * Fix of Debian bug #928957: overoptimistic guessing of the SHA256SUMS file location
+    Incorrect assumption of an existing SHA256SUMS file for Debian
+    repositories makes the expiration task fail without a proper way for the
+    end user to recover from it. Now ignore a download error in this case
+    (similar handling as for other guesses), assuming that permanent 404ing
+    for other reasons than removal of remote content can be considered
+    unlikely.
+
+ -- Eduard Bloch <bl...@debian.org>  Wed, 22 Jan 2020 20:53:50 +0100
+
 apt-cacher-ng (3.2) MY-NAME-IS-ANYBODY; urgency=medium

   * Maintenance release
diff -Nru apt-cacher-ng-3.2/VERSION apt-cacher-ng-3.2.1/VERSION
--- apt-cacher-ng-3.2/VERSION	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/VERSION	2020-02-03 19:54:57.000000000 +0100
@@ -1 +1 @@
-3.2
+3.2.1
diff -Nru apt-cacher-ng-3.2/conf/acng.conf.in apt-cacher-ng-3.2.1/conf/acng.conf.in
--- apt-cacher-ng-3.2/conf/acng.conf.in	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/conf/acng.conf.in	2020-02-03 19:54:57.000000000 +0100
@@ -81,11 +81,12 @@
 ReportPage: acng-report.html

 # Socket file for accessing through local UNIX socket instead of TCP/IP. Can be
-# used with inetd (via bridge tool in.acng from apt-cacher-ng package).
+# used with inetd (via bridge tool in.acng from apt-cacher-ng package), is also
+# used internally for administrative purposes.
 #
-# Default: not set, UNIX socket bridge is disabled.
+# Default: @SOCKET_PATH@
 #
-# SocketPath:/var/run/apt-cacher-ng/socket
+# SocketPath = /var/run/apt-cacher-ng/socket

 # If set to 1, makes log files be written to disk on every new line. Default
 # is 0, buffers are flushed after the client disconnects. Technically,
diff -Nru apt-cacher-ng-3.2/debian/changelog apt-cacher-ng-3.2.1/debian/changelog
--- apt-cacher-ng-3.2/debian/changelog	2019-05-17 22:59:21.000000000 +0200
+++ apt-cacher-ng-3.2.1/debian/changelog	2020-02-03 20:54:45.000000000 +0100
@@ -1,3 +1,14 @@
+apt-cacher-ng (3.2.1-1) buster; urgency=medium
+
+  * Minor bugfix upstream release
+    + (CVE-2020-5202) Enforce secured call to the server in maint job triggering
+    + Allow .zst compression for tarballs (closes: Bug#948259, thanks
+      to Arnaud Rebillout)
+    + Upstreaming fix from #928957 and adding workaround of build failure on
+      mips(64)el (no multithreading with gold linker)
+
+ -- Eduard Bloch <bl...@debian.org>  Mon, 03 Feb 2020 20:54:45 +0100
+
 apt-cacher-ng (3.2-2) unstable; urgency=medium

   *  Fix for incorrect assumption of some existing SHA256SUMS files in Debian
diff -Nru apt-cacher-ng-3.2/debian/patches/debian-changes apt-cacher-ng-3.2.1/debian/patches/debian-changes
--- apt-cacher-ng-3.2/debian/patches/debian-changes	2019-05-17 22:59:21.000000000 +0200
+++ apt-cacher-ng-3.2.1/debian/patches/debian-changes	2020-02-03 20:54:45.000000000 +0100
@@ -5,16 +5,16 @@
  information below has been extracted from the changelog. Adjust it or drop
  it.
  .
- apt-cacher-ng (3.2-2) unstable; urgency=medium
+ apt-cacher-ng (3.2.1-1) buster; urgency=medium
  .
-   *  Fix for incorrect assumption of some existing SHA256SUMS files in Debian
-      repositories which makes the expiration task fail without a proper way
-      for the end user to recover from it. Now ignore a download error in this
-      case (similar handling as for other guesses), assuming that permanent
-      404ing for other reasons than removal of remote content can be considered
-      unlikely (closes: #928957)
+   * Minor bugfix upstream release
+     + (CVE-2020-5202) Enforce secured call to the server in maint job triggering
+     + Allow .zst compression for tarballs (closes: Bug#948259, thanks
+       to Arnaud Rebillout)
+     + Upstreaming fix from #928957 and adding workaround of build failure on
+       mips(64)el (no multithreading with gold linker)
 Author: Eduard Bloch <bl...@debian.org>
-Bug-Debian: https://bugs.debian.org/928957
+Bug-Debian: https://bugs.debian.org/948259

 ---
 The information above should follow the Patch Tagging Guidelines, please
@@ -27,26 +27,10 @@
 Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
 Forwarded: <no|not-needed|url proving that it has been forwarded>
 Reviewed-By: <name and email of someone who approved the patch>
-Last-Update: 2019-05-21
+Last-Update: 2020-02-03

---- apt-cacher-ng-3.2.orig/source/expiration.cc
-+++ apt-cacher-ng-3.2/source/expiration.cc
-@@ -806,6 +806,13 @@ bool expiration::ProcessRegular(const st
- 			flags.eIdxType = EIDX_SHA256DILIST;
- 			flags.vfile_ondisk = true;
- 			flags.uptodate = false;
-+
-+			// the original source context will probably provide a viable source for
-+			// this URL - it might go 404 if the whole folder is missing but then the
-+			// referenced content would also be outdated/gone and not worth keeping
-+			// in the cache anyway
-+
-+			flags.forgiveDlErrors = true;
- 		}
- 		// and last but not least - care only about the modern version of that index
- 		m_metaFilesRel.erase(idir + "MD5SUMS");
---- apt-cacher-ng-3.2.orig/systemd/apt-cacher-ng.service.in
-+++ apt-cacher-ng-3.2/systemd/apt-cacher-ng.service.in
+--- apt-cacher-ng-3.2.1.orig/systemd/apt-cacher-ng.service.in
++++ apt-cacher-ng-3.2.1/systemd/apt-cacher-ng.service.in
 @@ -1,6 +1,7 @@
  [Unit]
  Description=Apt-Cacher NG software download proxy
diff -Nru apt-cacher-ng-3.2/include/acsyscap.h.in apt-cacher-ng-3.2.1/include/acsyscap.h.in
--- apt-cacher-ng-3.2/include/acsyscap.h.in	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/include/acsyscap.h.in	2020-02-03 19:54:57.000000000 +0100
@@ -31,3 +31,4 @@
 #cmakedefine BINDIR "@BINDIR@"
 #cmakedefine SBINDIR "@SBINDIR@"
 #cmakedefine HAVE_CHECKSUM
+#define UDSPATH "@SOCKET_PATH@"
diff -Nru apt-cacher-ng-3.2/source/acfg_defaults.cc apt-cacher-ng-3.2.1/source/acfg_defaults.cc
--- apt-cacher-ng-3.2/source/acfg_defaults.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/acfg_defaults.cc	2020-02-03 19:54:57.000000000 +0100
@@ -16,12 +16,12 @@
 namespace cfg
 {

-string cachedir("/var/tmp"), logdir("/var/tmp"), fifopath, pidfile, reportpage,
+string cachedir("/var/tmp"), logdir("/var/tmp"), fifopath(UDSPATH), pidfile, reportpage,
 confdir, adminauth, adminauthB64, bindaddr, mirrorsrcs, suppdir(LIBDIR),
 capath("/etc/ssl/certs"), cafile, badredmime("text/html");

 #define INFOLDER "(^|.*/)"
-#define COMPRLIST "(\\.gz|\\.bz2|\\.lzma|\\.xz)"
+#define COMPRLIST "(\\.gz|\\.bz2|\\.lzma|\\.xz|\\.zst)"
 #define ALXPATTERN ".*\\.(db|files|abs)(\\.tar" COMPRLIST ")?"
 #define COMPOPT COMPRLIST"?"
 //#define COMPONENT_OPTIONAL "(-[a-z0-9-])"
diff -Nru apt-cacher-ng-3.2/source/acngtool.cc apt-cacher-ng-3.2.1/source/acngtool.cc
--- apt-cacher-ng-3.2/source/acngtool.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/acngtool.cc	2020-02-03 19:54:57.000000000 +0100
@@ -27,7 +27,7 @@
 #include <cstdio>
 #include <cstring>
 #include <functional>
-
+#include <thread>
 #include <iostream>
 #include <fstream>
 #include <string>
@@ -38,7 +38,7 @@
 #include "dlcon.h"
 #include "fileio.h"
 #include "fileitem.h"
-
+#include "sockio.h"
 #ifdef HAVE_SSL
 #include "openssl/bio.h"
 #include "openssl/ssl.h"
@@ -57,6 +57,13 @@

 bool g_bVerbose = false;

+// from sockio.cc in more recent versions
+bool isUdsAccessible(cmstring& path)
+{
+	Cstat s(path);
+	return s && S_ISSOCK(s.st_mode) && 0 == access(path.c_str(), W_OK);
+}
+
 // dummies to satisfy references
 namespace acng
 {
@@ -117,6 +124,54 @@
 	}
 };

+// That is relevant to push the download agent logics correctly and are shown in logs;
+// not relevant for the actual connection since it's rerouted through TUdsFactory
+#define FAKE_UDS_HOSTNAME "UNIX-DOMAIN-SOCKET"
+
+SHARED_PTR<fileitem> CreateStdoutItem()
+{
+	class tPrintItem: public fileitem
+	{
+	public:
+		tPrintItem()
+		{
+			m_bAllowStoreData = false;
+			m_nSizeChecked = m_nSizeSeen = 0;
+		}
+		virtual FiStatus Setup(bool) override
+		{
+			m_nSizeChecked = m_nSizeSeen = 0;
+			return m_status = FIST_INITED;
+		}
+		virtual int GetFileFd() override
+		{
+			return 1;
+		}
+		; // something, don't care for now
+		virtual bool DownloadStartedStoreHeader(const header &h, size_t, const char*, bool, bool&)
+				override
+		{
+			m_head = h;
+			auto opt_dbg = getenv("ACNGTOOL_DEBUG_DOWNLOAD");
+			if (opt_dbg && *opt_dbg)
+				std::cerr << (std::string) h.ToString() << std::endl;
+			return true;
+		}
+		virtual bool StoreFileData(const char *data, unsigned int size) override
+		{
+			if (!size)
+				m_status = FIST_COMPLETE;
+
+			return (size == fwrite(data, sizeof(char), size, stdout));
+		}
+		ssize_t SendData(int, int, off_t&, size_t) override
+		{
+			return 0;
+		}
+	};
+	return make_shared<tPrintItem>();
+}
+
 struct verbprint
 {
 	int cnt = 0;
@@ -145,98 +200,115 @@
 	}
 } vprint;

-struct CReportItemFactory : public IFitemFactory
-{
-	virtual SHARED_PTR<fileitem> Create()
-	{
-		class tRepItem : public fileitem
-		{
-			acbuf lineBuf;
-			string m_key = maark;
-			tStrVec m_errMsg;
-
-		public:
+/**
+ * Create a special processor which looks for error markers in the download stream and
+ * reports the result only then.
+ */
+SHARED_PTR<fileitem> CreateReportItem()
+{
+	class tRepItem: public fileitem
+	{
+		acbuf lineBuf;
+		string m_key = maark;
+		tStrVec m_errMsg;

-			tRepItem()
-			{
-				m_bAllowStoreData=false;
-				m_nSizeChecked = m_nSizeSeen = 0;
-				lineBuf.setsize(1<<16);
-				memset(lineBuf.wptr(), 0, 1<<16);
-			};
-			virtual FiStatus Setup(bool) override
-			{
-				m_nSizeChecked = m_nSizeSeen = 0;
-				return m_status = FIST_INITED;
-			}
-			virtual int GetFileFd() override
-			{	return 1;}; // something, don't care for now
-			virtual bool DownloadStartedStoreHeader(const header &h, size_t, const char *,
-					bool, bool&) override
+	public:
+		tRepItem()
+		{
+			m_bAllowStoreData = false;
+			m_nSizeChecked = m_nSizeSeen = 0;
+			lineBuf.setsize(1 << 16);
+			memset(lineBuf.wptr(), 0, 1 << 16);
+		}
+		;
+		virtual FiStatus Setup(bool) override
+		{
+			m_nSizeChecked = m_nSizeSeen = 0;
+			return m_status = FIST_INITED;
+		}
+		virtual int GetFileFd() override
+		{
+			return 1;
+		}
+		; // something, don't care for now
+		virtual bool DownloadStartedStoreHeader(const header &h, size_t, const char*, bool, bool&)
+				override
+		{
+			m_head = h;
+			return true;
+		}
+		virtual bool StoreFileData(const char *data, unsigned int size) override
+		{
+			if (!size)
 			{
-				m_head = h;
-				return true;
+				m_status = FIST_COMPLETE;
+				vprint.fin();
 			}
-			virtual bool StoreFileData(const char *data, unsigned int size) override
-			{
-				if(!size)
-				{
-					m_status = FIST_COMPLETE;
-					vprint.fin();
-				}
-				auto consumed = std::min(size, lineBuf.freecapa());
-				memcpy(lineBuf.wptr(), data, consumed);
-				lineBuf.got(consumed);
-				for(;;)
+			auto consumed = std::min(size, lineBuf.freecapa());
+			memcpy(lineBuf.wptr(), data, consumed);
+			lineBuf.got(consumed);
+			for (;;)
+			{
+				LPCSTR p = lineBuf.rptr();
+				auto end = mempbrk(p, "\r\n", lineBuf.size());
+				if (!end)
+					break;
+				string s(p, end - p);
+				lineBuf.drop(s.length() + 1);
+				vprint.dot();
+				if (startsWith(s, m_key))
 				{
-					LPCSTR p = lineBuf.rptr();
-					auto end = mempbrk(p, "\r\n", lineBuf.size());
-					if(!end)
+					// that's for us... "<key><type> content\n"
+					char *endchar = nullptr;
+					p = s.c_str();
+					auto val = strtoul(p + m_key.length(), &endchar, 10);
+					if (!endchar || !*endchar)
+						continue; // heh? shall not finish here
+					switch (ControLineType(val))
+					{
+					case ControLineType::BeforeError:
+						m_errMsg.emplace_back(endchar, s.size() - (endchar - p));
+						vprint.msg(m_errMsg.back());
 						break;
-					string s(p, end-p);
-					lineBuf.drop(s.length()+1);
-					vprint.dot();
-					if(startsWith(s, m_key))
+					case ControLineType::Error:
 					{
-						// that's for us... "<key><type> content\n"
-						char *endchar = nullptr;
-						p = s.c_str();
-						auto val = strtoul(p + m_key.length(), &endchar, 10);
-						if(!endchar || !*endchar)
-							continue; // heh? shall not finish here
-						switch(ControLineType(val))
-						{
-						case ControLineType::BeforeError:
-							m_errMsg.emplace_back(endchar, s.size() - (endchar - p));
-							vprint.msg(m_errMsg.back());
-							break;
-						case ControLineType::Error:
-						{
-							if(!g_bVerbose) // printed before
-								for(auto l : m_errMsg)
-									cerr << l << endl;
-							m_errMsg.clear();
-							string msg(endchar, s.size() - (endchar - p));
-							vprint.fin();
-							cerr << msg << endl;
-							break;
-						}
-						default:
-							continue;
-						}
+						if (!g_bVerbose) // printed before
+							for (auto l : m_errMsg)
+								cerr << l << endl;
+						m_errMsg.clear();
+						string msg(endchar, s.size() - (endchar - p));
+						vprint.fin();
+						cerr << msg << endl;
+						break;
+					}
+					default:
+						continue;
 					}
 				}
-				return true;
-			}
-			ssize_t SendData(int , int, off_t &, size_t ) override
-			{
-				return 0;
 			}
-		};
-		return make_shared<tRepItem>();
-	}
-};
+			return true;
+		}
+		ssize_t SendData(int, int, off_t&, size_t) override
+		{
+			return 0;
+		}
+	};
+	return make_shared<tRepItem>();
+}

+void DownloadItem(const tHttpUrl &url, IDlConFactory &pDlconFac, const SHARED_PTR<fileitem> &fi)
+{
+	dlcon dl("", nullptr, &pDlconFac);
+	std::thread dlThread([&]() {dl.WorkLoop();});
+	dl.AddJob(fi, &url, nullptr, nullptr, 0, cfg::REDIRMAX_DEFAULT);
+	int st;
+	auto fistatus = fi->WaitForFinish(&st);
+	// just be sure to set a proper error code
+	if(fistatus != fileitem::FIST_COMPLETE && fi->GetHeader().getStatus() < 400)
+		fi->GetHeader().frontLine = "909 Incomplete download";
+	dl.SignalStop();
+	dlThread.join();
+}
 int wcat(LPCSTR url, LPCSTR proxy, IFitemFactory*, IDlConFactory *pdlconfa = &g_tcp_con_factory);

 static void usage(int retCode = 0, LPCSTR cmd = nullptr)
@@ -488,127 +560,147 @@
 	return true;
 }

-int maint_job()
+/**
+ * Helper which implements a custom connection class that runs through a specified Unix Domain
+ * Socket (see base class for the name).
+ */
+struct TUdsFactory : public ::acng::IDlConFactory
 {
-	cfg::SetOption("proxy=", nullptr);
-
-	tStrVec hostips;
-#if 0 // FIXME, processing on UDS gets stuck somewhere
-	// prefer UDS if configured in a sane way
-	if (startsWithSz(cfg::fifopath, "/"))
-		hostips.emplace_back(cfg::fifopath);
-#endif
-	auto nips = Tokenize(cfg::bindaddr, SPACECHARS, hostips, true);
-	if (!nips)
-		hostips.emplace_back("localhost");
-
-	for (const auto& hostaddr : hostips)
-	{
-		// use an own connection factory which does "the right thing" and leaks the
-		// internal connection result
-		struct maintfac: public IDlConFactory
-		{
-			bool m_bOK = false;
-			mstring m_hname;
-			maintfac(cmstring& s) :
-					m_hname(s)
-			{
-			}
-
-			void RecycleIdleConnection(tDlStreamHandle & handle) override
-			{
-				// keep going, no recycling/restoring
-			}
-			virtual tDlStreamHandle CreateConnected(cmstring &, cmstring &, mstring &, bool *,
-					cfg::tRepoData::IHookHandler *, bool, int, bool) override
+	void RecycleIdleConnection(tDlStreamHandle &handle) override
+	{
+		// keep going, no recycling/restoring
+	}
+	tDlStreamHandle CreateConnected(cmstring&, cmstring&, mstring& sErrorOut, bool*,
+			cfg::tRepoData::IHookHandler*, bool, int, bool) override
+	{
+		struct udsconnection: public tcpconnect
+		{
+			bool failed = false;
+			udsconnection() : tcpconnect(nullptr)
 			{
-				string serr;
+				// some static and dummy parameters, and invalidate SSL for sure
+				m_ssl = nullptr;
+				m_bio = nullptr;
+				m_sHostName = FAKE_UDS_HOSTNAME;
+				m_sPort = cfg::port;

-				if (m_hname[0] != '/') // not UDS
+				m_conFd = socket(PF_UNIX, SOCK_STREAM, 0);
+				if (m_conFd < 0)
 				{
-					auto mhandle = g_tcp_con_factory.CreateConnected(m_hname, cfg::port, serr, 0, 0,
-							false, 30, true);
-					m_bOK = mhandle.get();
-					return mhandle;
+					failed = true;
+					return;
 				}
-				// otherwise build a fake connection on unix domain socket
-				struct udsconnection: public tcpconnect
+				struct sockaddr_un addr;
+				addr.sun_family = PF_UNIX;
+				strcpy(addr.sun_path, cfg::fifopath.c_str());
+				socklen_t adlen = cfg::fifopath.length() + 1 + offsetof(struct sockaddr_un, sun_path);
+				if (connect(m_conFd, (struct sockaddr*) &addr, adlen))
 				{
-					udsconnection(cmstring& udspath, bool *ok) :
-							tcpconnect(nullptr)
-					{
-#ifdef DEBUG
-						cerr << "Socket path: " << udspath << endl;
-#endif
-						auto m_conFd = socket(PF_UNIX, SOCK_STREAM, 0);
-						if (m_conFd < 0)
-							return;
-
-						struct sockaddr_un addr;
-						addr.sun_family = PF_UNIX;
-						strcpy(addr.sun_path, cfg::fifopath.c_str());
-						socklen_t adlen =
-								cfg::fifopath.length() + 1 + offsetof(struct sockaddr_un, sun_path);
-						if (connect(m_conFd, (struct sockaddr*) &addr, adlen))
-						{
-#ifdef DEBUG
-							perror("connect");
-#endif
-							return;
-						}
-						// basic identification needed
-						tSS ids;
-						ids << "GET / HTTP/1.0\r\nX-Original-Source: localhost\r\n\r\n";
-						if (!ids.send(m_conFd))
-							return;
-
-						m_ssl = nullptr;
-						m_bio = nullptr;
-						// better match the TCP socket parameters
-						m_sHostName = "localhost";
-						m_sPort = sDefPortHTTP;
-						*ok = true;
-					}
-				};
-				return make_shared<udsconnection>(m_hname, &m_bOK);
+					DBGQLOG(tErrnoFmter("connect result: "));
+					checkforceclose(m_conFd);
+					failed = true;
+					return;
+				}
+				// basic identification needed
+				tSS ids;
+				ids << "GET / HTTP/1.0\r\nX-Original-Source: localhost\r\n\r\n";
+				if (!ids.send(m_conFd))
+				{
+					failed = true;
+					return;
+				}
 			}
 		};
-		maintfac factoryWrapper(hostaddr);
-		tSS urlPath;
-		urlPath << "http://";;
-		if (!cfg::adminauth.empty())
-			urlPath << UserinfoEscape(cfg::adminauth) << "@";
-		if (hostaddr[0] == '/')
-			urlPath << "localhost";
-		else
-			urlPath << hostaddr << ":" << cfg::port;
+		auto ret = make_shared<udsconnection>();
+		// mimic regular processing of a bad result here!
+		if(ret && ret->failed) ret.reset();
+		if(!ret) sErrorOut = "912 Cannot establish control connection";
+		return ret;
+	}
+};
+
+int maint_job()
+{
+	if (cfg::reportpage.empty())
+	{
+		cerr << "ReportPage is not configured in the server config, aborting..." <<endl;
+		return -1;
+	}

-		if (cfg::reportpage.empty())
-			return -1;
-		if(cfg::reportpage[0] != '/')
-			urlPath << "/";
-		urlPath << cfg::reportpage;
-		LPCSTR req = getenv("ACNGREQ");
-		urlPath << (req ? req : "?doExpire=Start+Expiration&abortOnErrors=aOe");
+	// base target URL, can be adapted for TCP requests
+	tHttpUrl url("localhost", cfg::port, false);
+	url.sUserPass = cfg::adminauth;
+	LPCSTR req = getenv("ACNGREQ");
+	url.sPath = "/" + cfg::reportpage + (req ? req : "?doExpire=Start+Expiration&abortOnErrors=aOe");

-#ifdef DEBUG
-		cerr << "Constructed URL: " << (string) urlPath << endl;
-#endif
+	auto isInsecForced = []() { auto se = getenv("ACNG_INSECURE"); return se && *se; };
+
+	// by default, use the socket connection; if credentials require it -> enforce it
+	bool have_cred = !url.sUserPass.empty(),
+			have_uds = !cfg::fifopath.empty(),
+			try_tcp = !have_cred;
+	bool uds_ok = have_uds && isUdsAccessible(cfg::fifopath);
+
+	if(have_cred)
+	{
+		if(isInsecForced()) // so try TCP anyway
+		{
+			try_tcp = true;
+		}
+		else if(have_uds && !uds_ok)
+		{
+			cerr << "This operation transmits credentials but the socket (" << cfg::fifopath
+					<< ") is currently not accessible!" << endl;
+			return EXIT_FAILURE;
+		}
+		else if(!have_uds)
+		{
+			cerr << "This operation transmits credentials but SocketPath is not configured to a safe location in the server configuration. "
+					"Please set SocketPath to a safe location, or set ACNG_INSECURE environment variable to override this check."
+					<<endl;
+			return EXIT_FAILURE;
+		}
+		// ok, otherwise use Unix Domain Socket
+	}

-		CReportItemFactory printItemFactory;
-		auto retcode = wcat(urlPath.c_str(), nullptr, &printItemFactory, &factoryWrapper);
-		if (retcode)
-		{
-			if (!factoryWrapper.m_bOK) // connection failed, try another IP
-				continue;
-			// otherwise the stuff has been printed
-			return 2;
+	bool response_ok = false;
+	if(have_uds && uds_ok)
+	{
+		DBGQLOG("Trying UDS path")
+		auto fi =CreateReportItem();
+		url.sHost = FAKE_UDS_HOSTNAME;
+		TUdsFactory udsConFac;
+		DownloadItem(url, udsConFac, fi);
+		response_ok = fi->GetHeader().getStatus() == 200;
+		DBGQLOG("UDS result: " << response_ok)
+	}
+	if(!response_ok && try_tcp)
+	{
+		DBGQLOG("Trying TCP path")
+		// never use a proxy here (insecure?), those are most likely local IPs
+		cfg::SetOption("Proxy=", nullptr);
+		cfg::nettimeout = 30;
+		vector<string> hostips;
+		Tokenize(cfg::bindaddr, SPACECHARS, hostips, false);
+		if(hostips.empty())
+			hostips.emplace_back("127.0.0.1");
+		for (const auto &tgt : hostips)
+		{
+			url.sHost = tgt;
+			auto fi = CreateReportItem();
+			DownloadItem(url, g_tcp_con_factory, fi);
+			response_ok = fi->GetHeader().getStatus() == 200;
+			if (response_ok)
+				break;
 		}
-		else
-			return 0;
 	}
-	// all attempts failed
-	return 3;
+	if(!response_ok)
+	{
+		cerr << "Could not make a valid request to the server. Please visit "
+				<< url.ToURI(false) << " and check special conditions." <<endl;
+		return EXIT_FAILURE;
+	}
+	return EXIT_SUCCESS;
 }

 int patch_file(string sBase, string sPatch, string sResult)
diff -Nru apt-cacher-ng-3.2/source/dlcon.cc apt-cacher-ng-3.2.1/source/dlcon.cc
--- apt-cacher-ng-3.2/source/dlcon.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/dlcon.cc	2020-02-03 19:54:57.000000000 +0100
@@ -1315,8 +1315,8 @@
 				}
         	}
         }
-
 		ldbg("Request(s) cooked, buffer contents: " << m_sendBuf);
+		ASSERT(!m_sendBuf.empty());

         go_select:

diff -Nru apt-cacher-ng-3.2/source/expiration.cc apt-cacher-ng-3.2.1/source/expiration.cc
--- apt-cacher-ng-3.2/source/expiration.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/expiration.cc	2020-02-03 19:54:57.000000000 +0100
@@ -806,6 +806,13 @@
 			flags.eIdxType = EIDX_SHA256DILIST;
 			flags.vfile_ondisk = true;
 			flags.uptodate = false;
+
+			// the original source context will probably provide a viable source for
+			// this URL - it might go 404 if the whole folder is missing but then the
+			// referenced content would also be outdated/gone and not worth keeping
+			// in the cache anyway
+
+			flags.forgiveDlErrors = true;
 		}
 		// and last but not least - care only about the modern version of that index
 		m_metaFilesRel.erase(idir + "MD5SUMS");
diff -Nru apt-cacher-ng-3.2/source/filereader.cc apt-cacher-ng-3.2.1/source/filereader.cc
--- apt-cacher-ng-3.2/source/filereader.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/filereader.cc	2020-02-03 19:54:57.000000000 +0100
@@ -31,7 +31,7 @@

 // must be something sensible, ratio impacts stack size by inverse power of 2
 #define BUFSIZEMIN 4095 // makes one page on i386 and should be enough for typical index files
-#define BUFSIZEMAX 16*4096
+#define BUFSIZEMAX 256*1024


 #ifdef MINIBUILD
diff -Nru apt-cacher-ng-3.2/source/tcpconnect.cc apt-cacher-ng-3.2.1/source/tcpconnect.cc
--- apt-cacher-ng-3.2/source/tcpconnect.cc	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/source/tcpconnect.cc	2020-02-03 19:54:57.000000000 +0100
@@ -257,7 +257,7 @@

 void tcpconnect::Disconnect()
 {
-	LOGSTART("tcpconnect::_Disconnect");
+	LOGSTART2("tcpconnect::_Disconnect", m_sHostName);

 #ifdef DEBUG
 	nDisconCount.fetch_add(m_conFd >=0);
diff -Nru apt-cacher-ng-3.2/systemd/apt-cacher-ng.service.in apt-cacher-ng-3.2.1/systemd/apt-cacher-ng.service.in
--- apt-cacher-ng-3.2/systemd/apt-cacher-ng.service.in	2018-09-07 15:02:18.000000000 +0200
+++ apt-cacher-ng-3.2.1/systemd/apt-cacher-ng.service.in	2020-02-03 19:54:57.000000000 +0100
@@ -4,7 +4,7 @@

 [Service]
 # the SocketPath option can be removed if the inetd bridge functionality is not needed
-ExecStart=@SBINDIR@/apt-cacher-ng SocketPath=@RUNDIR@/apt-cacher-ng/socket -c @CFGDIR@ ForeGround=1
+ExecStart=@SBINDIR@/apt-cacher-ng -c @CFGDIR@ ForeGround=1
 User=apt-cacher-ng
 Group=apt-cacher-ng
 # this can be changed to notify if the support was enabled at build time
[The following lists of changes regard files as different if they have
different names, permissions or owners.]

Files in second .changes but not in first
-----------------------------------------
-rw-r--r--  root/root   /usr/lib/debug/.build-id/23/8f383d2cb9caac6ecd05decfa364be2ca2ee8a.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/7f/6e31b099b6e22585b5630db507283d37ca0127.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/d3/b64ad65fc84b1f68eabd45285dadffeb276ba6.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/f7/5dcd898980cc17280919d7c7a524b60242e854.debug

Files in first .changes but not in second
-----------------------------------------
-rw-r--r--  root/root   /usr/lib/debug/.build-id/40/f6065f2a4a8e153cc69323dfa5c811e96cb883.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/71/41dd60e3dcbd3d9144bd63804b8e5fa4aabff5.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/81/a9f7f4ce42b21217018ccd4405776eef38620c.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/86/418c61da38c572d498e2573f3cf2225ee115d8.debug

Control files of package apt-cacher-ng: lines which differ (wdiff format)
-------------------------------------------------------------------------
Depends: libbz2-1.0, libc6 (>= 2.28), libgcc1 (>= 1:3.3.1), liblzma5 (>= 5.1.1alpha+20120614), libssl1.1 (>= 1.1.0), libstdc++6 (>= [-5.2),-] {+6),+} libsystemd0 (>= 210), libwrap0 (>= 7.6-4~), zlib1g (>= 1:1.2.0), debconf (>= 0.5) | debconf-2.0, adduser, lsb-base (>= 3.0-6)
Installed-Size: [-1425-] {+1430+}
Version: [-3.2-2-] {+3.2.1-1+}

Control files of package apt-cacher-ng-dbgsym: lines which differ (wdiff format)
--------------------------------------------------------------------------------
Build-Ids: [-40f6065f2a4a8e153cc69323dfa5c811e96cb883 7141dd60e3dcbd3d9144bd63804b8e5fa4aabff5 81a9f7f4ce42b21217018ccd4405776eef38620c 86418c61da38c572d498e2573f3cf2225ee115d8-] {+238f383d2cb9caac6ecd05decfa364be2ca2ee8a 7f6e31b099b6e22585b5630db507283d37ca0127 d3b64ad65fc84b1f68eabd45285dadffeb276ba6 f75dcd898980cc17280919d7c7a524b60242e854+}
Depends: apt-cacher-ng (= [-3.2-2)-] {+3.2.1-1)+}
Installed-Size: [-5986-] {+6018+}
Version: [-3.2-2-] {+3.2.1-1+}

Reply via email to