From 5629f35ecb7956b180364ebaf57e79f35885344e Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 3 Dec 2018 17:39:03 +0100 Subject: Add support for /etc/apt/auth.conf.d/*.conf (netrcparts) This allows us to install matching auth files for sources.list.d files, for example; very useful. This converts aptmethod's authfd from one FileFd to a vector of pointers to FileFd, as FileFd cannot be copied, and move operators are hard. (cherry picked from commit bbfcc05c1978decd28df9681fd73e2a7d9a8c2a5) LP: #1811120 --- apt-pkg/init.cc | 1 + doc/apt_auth.conf.5.xml | 7 ++++- doc/examples/configure-index | 1 + methods/aptmethod.h | 47 +++++++++++++++++++++++------- test/integration/test-authentication-basic | 13 ++++++++- 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index ab0474fac..43092381d 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -150,6 +150,7 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("Dir::Etc::sourceparts","sources.list.d"); Cnf.CndSet("Dir::Etc::main","apt.conf"); Cnf.CndSet("Dir::Etc::netrc", "auth.conf"); + Cnf.CndSet("Dir::Etc::netrcparts", "auth.conf.d"); Cnf.CndSet("Dir::Etc::parts","apt.conf.d"); Cnf.CndSet("Dir::Etc::preferences","preferences"); Cnf.CndSet("Dir::Etc::preferencesparts","preferences.d"); diff --git a/doc/apt_auth.conf.5.xml b/doc/apt_auth.conf.5.xml index 37e4fbc98..26d14b8e8 100644 --- a/doc/apt_auth.conf.5.xml +++ b/doc/apt_auth.conf.5.xml @@ -36,7 +36,8 @@ needed to connect to a proxy or to download data from a repository on the other hand shouldn't always be accessible by everyone and can hence not be placed in a file with world-readable file permissions. -The APT auth.conf file /etc/apt/auth.conf can be used to store +The APT auth.conf file /etc/apt/auth.conf, and .conf files inside +/etc/apt/auth.conf.d can be used to store login information in a netrc-like format with restrictive file permissions. @@ -119,6 +120,10 @@ you need multiple they should all have a path specified in the Login information for APT sources and proxies in a netrc-like format. Configuration Item: Dir::Etc::netrc. + /etc/apt/auth.conf.d/*.conf + Login information for APT sources and proxies in a netrc-like format. + Configuration Item: Dir::Etc::netrcparts. + diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 71ec57be0..df91d7738 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -398,6 +398,7 @@ Dir "" Etc "" { Main ""; Netrc ""; + NetrcParts ""; Parts ""; Preferences ""; PreferencesParts ""; diff --git a/methods/aptmethod.h b/methods/aptmethod.h index cb5a30e21..f6613ac3b 100644 --- a/methods/aptmethod.h +++ b/methods/aptmethod.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -471,8 +472,9 @@ protected: }; class aptAuthConfMethod : public aptMethod { - FileFd authconf; -public: + std::vector> authconfs; + + public: virtual bool Configuration(std::string Message) APT_OVERRIDE { if (pkgAcqMethod::Configuration(Message) == false) @@ -481,14 +483,25 @@ public: std::string const conf = std::string("Binary::") + Binary; _config->MoveSubTree(conf.c_str(), NULL); + // ignore errors with opening the auth file as it doesn't need to exist + _error->PushToStack(); auto const netrc = _config->FindFile("Dir::Etc::netrc"); if (netrc.empty() == false) { - // ignore errors with opening the auth file as it doesn't need to exist - _error->PushToStack(); - authconf.Open(netrc, FileFd::ReadOnly); - _error->RevertToStack(); + authconfs.emplace_back(new FileFd()); + authconfs.back()->Open(netrc, FileFd::ReadOnly); + } + + auto const netrcparts = _config->FindDir("Dir::Etc::netrcparts"); + if (netrcparts.empty() == false) + { + for (auto const &netrc : GetListOfFilesInDir(netrcparts, "conf", true, true)) + { + authconfs.emplace_back(new FileFd()); + authconfs.back()->Open(netrc, FileFd::ReadOnly); + } } + _error->RevertToStack(); DropPrivsOrDie(); @@ -500,13 +513,25 @@ public: bool MaybeAddAuthTo(URI &uri) { + bool result = true; + if (uri.User.empty() == false || uri.Password.empty() == false) return true; - if (authconf.IsOpen() == false) - return true; - if (authconf.Seek(0) == false) - return false; - return MaybeAddAuth(authconf, uri); + + for (auto &authconf : authconfs) + { + if (authconf->IsOpen() == false) + continue; + if (authconf->Seek(0) == false) + { + result = false; + continue; + } + + result &= MaybeAddAuth(*authconf, uri); + } + + return result; } aptAuthConfMethod(std::string &&Binary, char const *const Ver, unsigned long const Flags) APT_NONNULL(3) diff --git a/test/integration/test-authentication-basic b/test/integration/test-authentication-basic index 011f205af..211c73e35 100755 --- a/test/integration/test-authentication-basic +++ b/test/integration/test-authentication-basic @@ -53,7 +53,8 @@ Conf foo (1 unstable [all])' aptget install foo -s } authfile() { - local AUTHCONF='rootdir/etc/apt/auth.conf' + local AUTHCONF="${2:-rootdir/etc/apt/auth.conf}" + mkdir -p "$(dirname "$AUTHCONF")" rm -f "$AUTHCONF" printf '%s' "$1" > "$AUTHCONF" chmod 600 "$AUTHCONF" @@ -85,6 +86,16 @@ machine localhost login star@irc password hunter2' testauthsuccess "$1" + + # delete file, make sure it fails; add auth.conf.d snippet, works again. + rm rootdir/etc/apt/auth.conf + testauthfailure "$1" + + authfile 'machine localhost +login star@irc +password hunter2' rootdir/etc/apt/auth.conf.d/myauth.conf + testauthsuccess "$1" + rm rootdir/etc/apt/auth.conf.d/myauth.conf } msgmsg 'server basic auth' -- cgit v1.2.3