From cfacba5230f2e6bb88a1949505843ac22ed342d5 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 25 Nov 2013 08:36:57 +0100 Subject: add basic "edit-sources" command --- cmdline/apt-get.cc | 19 +------------------ cmdline/apt.cc | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 15373b050..912b2d609 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -59,6 +59,7 @@ #include #include #include +#include #include @@ -1378,24 +1379,6 @@ bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, return _error->Error("changelog download failed"); } /*}}}*/ -// DisplayFileInPager - Display File with pager /*{{{*/ -void DisplayFileInPager(string filename) -{ - pid_t Process = ExecFork(); - if (Process == 0) - { - const char *Args[3]; - Args[0] = "/usr/bin/sensible-pager"; - Args[1] = filename.c_str(); - Args[2] = 0; - execvp(Args[0],(char **)Args); - exit(100); - } - - // Wait for the subprocess - ExecWait(Process, "sensible-pager", false); -} - /*}}}*/ // DoChangelog - Get changelog from the command line /*{{{*/ // --------------------------------------------------------------------- bool DoChangelog(CommandLine &CmdL) diff --git a/cmdline/apt.cc b/cmdline/apt.cc index e30967ec2..ef31d0029 100644 --- a/cmdline/apt.cc +++ b/cmdline/apt.cc @@ -54,8 +54,28 @@ #include #include #include +#include /*}}}*/ +// EditSource - EditSourcesList /*{{{*/ +// --------------------------------------------------------------------- +bool EditSources(CommandLine &CmdL) +{ + // FIXME: suport CmdL.FileList to specify sources.list.d files + + std::string sourceslist = _config->FindFile("Dir::Etc::sourcelist"); + + // FIXME: take hash before, + // when changed display message to apt update + // do syntax check after save (like visudo) + + EditFileInSensibleEditor(sourceslist); + + return true; +} + /*}}}*/ + + bool ShowHelp(CommandLine &CmdL) { ioprintf(c1out,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, @@ -74,6 +94,8 @@ bool ShowHelp(CommandLine &CmdL) " update - update list of available packages\n" " install - install packages\n" " upgrade - upgrade the systems packages\n" + "\n" + " edit-sources - edit the source information file\n" ); return true; @@ -89,6 +111,8 @@ int main(int argc, const char *argv[]) /*{{{*/ {"remove", &DoInstall}, {"update",&DoUpdate}, {"upgrade",&DoUpgradeWithAllowNewPackages}, + // misc + {"edit-sources",&EditSources}, // helper {"moo",&DoMoo}, {"help",&ShowHelp}, -- cgit v1.2.3-70-g09d2 From d2524a53bbd219ee6d069006fd243a5bcda0245b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 26 Nov 2013 09:22:40 +0100 Subject: add syntax check for sources.list --- cmdline/apt.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt.cc b/cmdline/apt.cc index ef31d0029..38610e731 100644 --- a/cmdline/apt.cc +++ b/cmdline/apt.cc @@ -67,9 +67,22 @@ bool EditSources(CommandLine &CmdL) // FIXME: take hash before, // when changed display message to apt update - // do syntax check after save (like visudo) - - EditFileInSensibleEditor(sourceslist); + bool res; + pkgSourceList sl; + + do { + EditFileInSensibleEditor(sourceslist); + _error->PushToStack(); + res = sl.Read(sourceslist); + if (!res) { + std::string outs; + strprintf(outs, _("Failed to parse %s. Edit again? "), + sourceslist.c_str()); + std::cout << outs; + res = !YnPrompt(true); + } + _error->RevertToStack(); + } while (res == false); return true; } -- cgit v1.2.3-70-g09d2 From e6645b9fb9ba3a7ff7b6663af3f5e1bcb6f23d78 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 26 Nov 2013 10:32:21 +0100 Subject: add check when sources.list changed --- apt-pkg/contrib/hashes.cc | 25 +++++++++++++++++++++---- apt-pkg/contrib/hashes.h | 9 ++++++++- cmdline/apt.cc | 20 ++++++++++++++------ 3 files changed, 43 insertions(+), 11 deletions(-) (limited to 'cmdline') diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index e1a431823..b4c768db9 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -54,6 +54,26 @@ HashString::HashString(std::string StringedHash) /*{{{*/ } /*}}}*/ bool HashString::VerifyFile(std::string filename) const /*{{{*/ +{ + std::string fileHash = GetHashForFile(filename); + + if(_config->FindB("Debug::Hashes",false) == true) + std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl; + + return (fileHash == Hash); +} + /*}}}*/ +bool HashString::FromFile(std::string filename) /*{{{*/ +{ + // pick the strongest hash + if (Type == "") + Type = _SupportedHashes[0]; + + Hash = GetHashForFile(filename); + return true; +} + /*}}}*/ +std::string HashString::GetHashForFile(std::string filename) const /*{{{*/ { std::string fileHash; @@ -84,10 +104,7 @@ bool HashString::VerifyFile(std::string filename) const /*{{{*/ } Fd.Close(); - if(_config->FindB("Debug::Hashes",false) == true) - std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl; - - return (fileHash == Hash); + return fileHash; } /*}}}*/ const char** HashString::SupportedHashes() diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 0c0b6c6a7..0a8bcd259 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -36,7 +36,10 @@ class HashString protected: std::string Type; std::string Hash; - static const char * _SupportedHashes[10]; + static const char* _SupportedHashes[10]; + + // internal helper + std::string GetHashForFile(std::string filename) const; public: HashString(std::string Type, std::string Hash); @@ -49,6 +52,10 @@ class HashString // verify the given filename against the currently loaded hash bool VerifyFile(std::string filename) const; + // generate a hash string from the given filename + bool FromFile(std::string filename); + + // helper std::string toStr() const; // convert to str as "type:hash" bool empty() const; diff --git a/cmdline/apt.cc b/cmdline/apt.cc index 38610e731..47187fac2 100644 --- a/cmdline/apt.cc +++ b/cmdline/apt.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -61,21 +62,21 @@ // --------------------------------------------------------------------- bool EditSources(CommandLine &CmdL) { - // FIXME: suport CmdL.FileList to specify sources.list.d files + bool res; + pkgSourceList sl; + std::string outs; + // FIXME: suport CmdL.FileList to specify sources.list.d files std::string sourceslist = _config->FindFile("Dir::Etc::sourcelist"); - // FIXME: take hash before, - // when changed display message to apt update - bool res; - pkgSourceList sl; + HashString before; + before.FromFile(sourceslist); do { EditFileInSensibleEditor(sourceslist); _error->PushToStack(); res = sl.Read(sourceslist); if (!res) { - std::string outs; strprintf(outs, _("Failed to parse %s. Edit again? "), sourceslist.c_str()); std::cout << outs; @@ -84,6 +85,13 @@ bool EditSources(CommandLine &CmdL) _error->RevertToStack(); } while (res == false); + if (!before.VerifyFile(sourceslist)) { + strprintf( + outs, _("Your '%s' file changed, please run 'apt-get update'."), + sourceslist.c_str()); + std::cout << outs << std::endl; + } + return true; } /*}}}*/ -- cgit v1.2.3-70-g09d2 From 9e6b13f3751f8a1287ff79861980afb7792a5f9e Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 28 Nov 2013 12:15:47 +0100 Subject: move EditSources into its own file --- apt-private/makefile | 2 +- apt-private/private-sources.cc | 45 ++++++++++++++++++++++++++++++++++++++++++ apt-private/private-sources.h | 3 +++ cmdline/apt.cc | 38 +---------------------------------- 4 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 apt-private/private-sources.cc create mode 100644 apt-private/private-sources.h (limited to 'cmdline') diff --git a/apt-private/makefile b/apt-private/makefile index b3d764097..728890b9b 100644 --- a/apt-private/makefile +++ b/apt-private/makefile @@ -17,7 +17,7 @@ MAJOR=0.0 MINOR=0 SLIBS=$(PTHREADLIB) -lapt-pkg -PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main utils +PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main utils sources SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc) HEADERS += $(foreach private, $(PRIVATES), private-$(private).h) diff --git a/apt-private/private-sources.cc b/apt-private/private-sources.cc new file mode 100644 index 000000000..eb9c5b971 --- /dev/null +++ b/apt-private/private-sources.cc @@ -0,0 +1,45 @@ + +#include +#include + +#include "private-output.h" +#include "private-sources.h" +#include "private-utils.h" + +// EditSource - EditSourcesList /*{{{*/ +// --------------------------------------------------------------------- +bool EditSources(CommandLine &CmdL) +{ + bool res; + pkgSourceList sl; + std::string outs; + + // FIXME: suport CmdL.FileList to specify sources.list.d files + std::string sourceslist = _config->FindFile("Dir::Etc::sourcelist"); + + HashString before; + before.FromFile(sourceslist); + + do { + EditFileInSensibleEditor(sourceslist); + _error->PushToStack(); + res = sl.Read(sourceslist); + if (!res) { + strprintf(outs, _("Failed to parse %s. Edit again? "), + sourceslist.c_str()); + std::cout << outs; + res = !YnPrompt(true); + } + _error->RevertToStack(); + } while (res == false); + + if (!before.VerifyFile(sourceslist)) { + strprintf( + outs, _("Your '%s' file changed, please run 'apt-get update'."), + sourceslist.c_str()); + std::cout << outs << std::endl; + } + + return true; +} + /*}}}*/ diff --git a/apt-private/private-sources.h b/apt-private/private-sources.h new file mode 100644 index 000000000..b394622be --- /dev/null +++ b/apt-private/private-sources.h @@ -0,0 +1,3 @@ +#include + +bool EditSources(CommandLine &CmdL); diff --git a/cmdline/apt.cc b/cmdline/apt.cc index 47187fac2..4bcae0aba 100644 --- a/cmdline/apt.cc +++ b/cmdline/apt.cc @@ -56,45 +56,9 @@ #include #include #include +#include /*}}}*/ -// EditSource - EditSourcesList /*{{{*/ -// --------------------------------------------------------------------- -bool EditSources(CommandLine &CmdL) -{ - bool res; - pkgSourceList sl; - std::string outs; - - // FIXME: suport CmdL.FileList to specify sources.list.d files - std::string sourceslist = _config->FindFile("Dir::Etc::sourcelist"); - - HashString before; - before.FromFile(sourceslist); - - do { - EditFileInSensibleEditor(sourceslist); - _error->PushToStack(); - res = sl.Read(sourceslist); - if (!res) { - strprintf(outs, _("Failed to parse %s. Edit again? "), - sourceslist.c_str()); - std::cout << outs; - res = !YnPrompt(true); - } - _error->RevertToStack(); - } while (res == false); - - if (!before.VerifyFile(sourceslist)) { - strprintf( - outs, _("Your '%s' file changed, please run 'apt-get update'."), - sourceslist.c_str()); - std::cout << outs << std::endl; - } - - return true; -} - /*}}}*/ bool ShowHelp(CommandLine &CmdL) -- cgit v1.2.3-70-g09d2 From f87338d2da95ba7d55a1a67b4506717e94d49bca Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 30 Nov 2013 23:07:20 +0100 Subject: cherry-pick ubuntus (disabled) net-update fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the net-update command a special keyring can be downloaded and imported into apt, which must be signed by a master key. Its is currently disabled because of security problems with it – and the only known user before that was Ubuntu. --- cmdline/apt-key | 44 +++++++--- .../integration/exploid-keyring-with-dupe-keys.pub | Bin 0 -> 3986 bytes .../exploid-keyring-with-dupe-subkeys.pub | Bin 0 -> 2016 bytes test/integration/test-apt-key-net-update | 95 +++++++++++++++++++++ 4 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 test/integration/exploid-keyring-with-dupe-keys.pub create mode 100644 test/integration/exploid-keyring-with-dupe-subkeys.pub create mode 100755 test/integration/test-apt-key-net-update (limited to 'cmdline') diff --git a/cmdline/apt-key b/cmdline/apt-key index 713a41c07..64cf5a6f4 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -25,17 +25,15 @@ GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" -MASTER_KEYRING="" -#MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg +MASTER_KEYRING='' eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) -ARCHIVE_KEYRING_URI="" -#ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg -eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) - -ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg +ARCHIVE_KEYRING='/usr/share/keyrings/debian-archive-keyring.gpg' eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) -REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg +REMOVED_KEYS='/usr/share/keyrings/debian-archive-removed-keys.gpg' eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) +ARCHIVE_KEYRING_URI='' +eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) +TMP_KEYRING=/var/lib/apt/keyrings/maybe-import-keyring.gpg requires_root() { if [ "$(id -u)" -ne 0 ]; then @@ -57,7 +55,7 @@ init_keyring() { add_keys_with_verify_against_master_keyring() { ADD_KEYRING=$1 MASTER=$2 - + if [ ! -f "$ADD_KEYRING" ]; then echo "ERROR: '$ADD_KEYRING' not found" return @@ -72,12 +70,28 @@ add_keys_with_verify_against_master_keyring() { # all keys that are exported must have a valid signature # from a key in the $distro-master-keyring add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^pub | cut -d: -f5` + all_add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5` master_keys=`$GPG_CMD --keyring $MASTER --with-colons --list-keys | grep ^pub | cut -d: -f5` + + # ensure there are no colisions LP: #857472 + for all_add_key in $all_add_keys; do + for master_key in $master_keys; do + if [ "$all_add_key" = "$master_key" ]; then + echo >&2 "Keyid collision for '$all_add_key' detected, operation aborted" + return 1 + fi + done + done + for add_key in $add_keys; do - ADDED=0 + # export the add keyring one-by-one + rm -f $TMP_KEYRING + $GPG_CMD --keyring $ADD_KEYRING --output $TMP_KEYRING --export $add_key + # check if signed with the master key and only add in this case + ADDED=0 for master_key in $master_keys; do - if $GPG_CMD --keyring $ADD_KEYRING --list-sigs --with-colons $add_key | grep ^sig | cut -d: -f5 | grep -q $master_key; then - $GPG_CMD --quiet --batch --keyring $ADD_KEYRING --export $add_key | $GPG --import + if $GPG_CMD --keyring $MASTER --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then + $GPG --import $TMP_KEYRING ADDED=1 fi done @@ -85,12 +99,16 @@ add_keys_with_verify_against_master_keyring() { echo >&2 "Key '$add_key' not added. It is not signed with a master key" fi done + rm -f $TMP_KEYRING } # update the current archive signing keyring from a network URI # the archive-keyring keys needs to be signed with the master key # (otherwise it does not make sense from a security POV) net_update() { + # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) + exit 1 + if [ -z "$ARCHIVE_KEYRING_URI" ]; then echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" exit 1 @@ -110,7 +128,7 @@ net_update() { if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) fi - (cd /var/lib/apt/keyrings; wget -q -N $ARCHIVE_KEYRING_URI) + (cd /var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) if [ ! -e $keyring ]; then return fi diff --git a/test/integration/exploid-keyring-with-dupe-keys.pub b/test/integration/exploid-keyring-with-dupe-keys.pub new file mode 100644 index 000000000..642952a40 Binary files /dev/null and b/test/integration/exploid-keyring-with-dupe-keys.pub differ diff --git a/test/integration/exploid-keyring-with-dupe-subkeys.pub b/test/integration/exploid-keyring-with-dupe-subkeys.pub new file mode 100644 index 000000000..02d4e6ee8 Binary files /dev/null and b/test/integration/exploid-keyring-with-dupe-subkeys.pub differ diff --git a/test/integration/test-apt-key-net-update b/test/integration/test-apt-key-net-update new file mode 100755 index 000000000..d5205836f --- /dev/null +++ b/test/integration/test-apt-key-net-update @@ -0,0 +1,95 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture "i386" + +# mock +requires_root() { + return 0 +} + +# extract net_update() and import it +func=$( sed -n -e '/^add_keys_with_verify_against_master_keyring/,/^}/p' ${BUILDDIRECTORY}/apt-key ) +eval "$func" + +mkdir -p ./etc/apt +TRUSTEDFILE=./etc/apt/trusted.gpg +mkdir -p ./var/lib/apt/keyrings +TMP_KEYRING=./var/lib/apt/keyrings/maybe-import-keyring.gpg +GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" +GPG="$GPG_CMD --keyring $TRUSTEDFILE" +MASTER_KEYRING=/usr/share/keyrings/ubuntu-master-keyring.gpg + + +msgtest "add_keys_with_verify_against_master_keyring" +if [ ! -e $MASTER_KEYRING ]; then + echo -n "No $MASTER_KEYRING found" + msgskip + exit 0 +fi + +# test bad keyring and ensure its not added (LP: #857472) +ADD_KEYRING=./keys/exploid-keyring-with-dupe-keys.pub +if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then + msgfail +else + msgpass +fi + +# ensure the keyring is still empty +gpg_out=$($GPG --list-keys) +msgtest "Test if keyring is empty" +if [ -n "" ]; then + msgfail +else + msgpass +fi + + +# test another possible attack vector using subkeys (LP: #1013128) +msgtest "add_keys_with_verify_against_master_keyring with subkey attack" +ADD_KEYRING=./keys/exploid-keyring-with-dupe-subkeys.pub +if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then + msgfail +else + msgpass +fi + +# ensure the keyring is still empty +gpg_out=$($GPG --list-keys) +msgtest "Test if keyring is empty" +if [ -n "" ]; then + msgfail +else + msgpass +fi + + +# test good keyring and ensure we get no errors +ADD_KEYRING=/usr/share/keyrings/ubuntu-archive-keyring.gpg +if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then + msgpass +else + msgfail +fi + +testequal './etc/apt/trusted.gpg +--------------------- +pub 1024D/437D05B5 2004-09-12 +uid Ubuntu Archive Automatic Signing Key +sub 2048g/79164387 2004-09-12 + +pub 1024D/FBB75451 2004-12-30 +uid Ubuntu CD Image Automatic Signing Key + +pub 4096R/C0B21F32 2012-05-11 +uid Ubuntu Archive Automatic Signing Key (2012) + +pub 4096R/EFE21092 2012-05-11 +uid Ubuntu CD Image Automatic Signing Key (2012) +' $GPG --list-keys + -- cgit v1.2.3-70-g09d2 From 5b2c6ddcc0e45c92c544032ad2bb91bdf7222d7c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 30 Nov 2013 23:11:43 +0100 Subject: generate apt-key script with vendor info about keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The apt-key script uses quiet a few keyring files for operation which are specific to the distribution it is build on and is hence one of the most patched parts – even if it is not that often used anymore now that a fragment directory for trusted.gpg exists. --- .gitignore | 1 + cmdline/apt-key | 354 ------------------------------------------- cmdline/apt-key.in | 354 +++++++++++++++++++++++++++++++++++++++++++ cmdline/makefile | 8 + vendor/debian/apt-vendor.ent | 2 + vendor/getinfo | 2 +- vendor/ubuntu/apt-vendor.ent | 2 + 7 files changed, 368 insertions(+), 355 deletions(-) delete mode 100755 cmdline/apt-key create mode 100644 cmdline/apt-key.in (limited to 'cmdline') diff --git a/.gitignore b/.gitignore index 76b24f9c5..321b15471 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ /debian/apt-transport-https/ # generated from *.in files +/cmdline/apt-key /doc/apt-vendor.ent /doc/examples/sources.list /debian/libapt-pkg*.install diff --git a/cmdline/apt-key b/cmdline/apt-key deleted file mode 100755 index 64cf5a6f4..000000000 --- a/cmdline/apt-key +++ /dev/null @@ -1,354 +0,0 @@ -#!/bin/sh - -set -e -unset GREP_OPTIONS - -GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" - -# gpg needs a trustdb to function, but it can't be invalid (not even empty) -# so we create a temporary directory to store our fresh readable trustdb in -TRUSTDBDIR="$(mktemp -d)" -CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" -trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -chmod 700 "$TRUSTDBDIR" -# We also don't use a secret keyring, of course, but gpg panics and -# implodes if there isn't one available - and writeable for imports -SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" -touch $SECRETKEYRING -GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" -GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" - -# now create the trustdb with an (empty) dummy keyring -$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING -# and make sure that gpg isn't trying to update the file -GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" - -GPG="$GPG_CMD" - -MASTER_KEYRING='' -eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) -ARCHIVE_KEYRING='/usr/share/keyrings/debian-archive-keyring.gpg' -eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) -REMOVED_KEYS='/usr/share/keyrings/debian-archive-removed-keys.gpg' -eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) -ARCHIVE_KEYRING_URI='' -eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) -TMP_KEYRING=/var/lib/apt/keyrings/maybe-import-keyring.gpg - -requires_root() { - if [ "$(id -u)" -ne 0 ]; then - echo >&1 "ERROR: This command can only be used by root." - exit 1 - fi -} - -# gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead. -init_keyring() { - for path; do - if ! [ -e "$path" ]; then - touch -- "$path" - chmod 0644 -- "$path" - fi - done -} - -add_keys_with_verify_against_master_keyring() { - ADD_KEYRING=$1 - MASTER=$2 - - if [ ! -f "$ADD_KEYRING" ]; then - echo "ERROR: '$ADD_KEYRING' not found" - return - fi - if [ ! -f "$MASTER" ]; then - echo "ERROR: '$MASTER' not found" - return - fi - - # when adding new keys, make sure that the archive-master-keyring - # is honored. so: - # all keys that are exported must have a valid signature - # from a key in the $distro-master-keyring - add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^pub | cut -d: -f5` - all_add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5` - master_keys=`$GPG_CMD --keyring $MASTER --with-colons --list-keys | grep ^pub | cut -d: -f5` - - # ensure there are no colisions LP: #857472 - for all_add_key in $all_add_keys; do - for master_key in $master_keys; do - if [ "$all_add_key" = "$master_key" ]; then - echo >&2 "Keyid collision for '$all_add_key' detected, operation aborted" - return 1 - fi - done - done - - for add_key in $add_keys; do - # export the add keyring one-by-one - rm -f $TMP_KEYRING - $GPG_CMD --keyring $ADD_KEYRING --output $TMP_KEYRING --export $add_key - # check if signed with the master key and only add in this case - ADDED=0 - for master_key in $master_keys; do - if $GPG_CMD --keyring $MASTER --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then - $GPG --import $TMP_KEYRING - ADDED=1 - fi - done - if [ $ADDED = 0 ]; then - echo >&2 "Key '$add_key' not added. It is not signed with a master key" - fi - done - rm -f $TMP_KEYRING -} - -# update the current archive signing keyring from a network URI -# the archive-keyring keys needs to be signed with the master key -# (otherwise it does not make sense from a security POV) -net_update() { - # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) - exit 1 - - if [ -z "$ARCHIVE_KEYRING_URI" ]; then - echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" - exit 1 - fi - requires_root - # in theory we would need to depend on wget for this, but this feature - # isn't useable in debian anyway as we have no keyring uri nor a master key - if ! which wget >/dev/null 2>&1; then - echo >&2 "ERROR: an installed wget is required for a network-based update" - exit 1 - fi - if [ ! -d /var/lib/apt/keyrings ]; then - mkdir -p /var/lib/apt/keyrings - fi - keyring=/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) - old_mtime=0 - if [ -e $keyring ]; then - old_mtime=$(stat -c %Y $keyring) - fi - (cd /var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) - if [ ! -e $keyring ]; then - return - fi - new_mtime=$(stat -c %Y $keyring) - if [ $new_mtime -ne $old_mtime ]; then - echo "Checking for new archive signing keys now" - add_keys_with_verify_against_master_keyring $keyring $MASTER_KEYRING - fi -} - -update() { - if [ ! -f $ARCHIVE_KEYRING ]; then - echo >&2 "ERROR: Can't find the archive-keyring" - echo >&2 "Is the debian-archive-keyring package installed?" - exit 1 - fi - requires_root - - # add new keys from the package; - - # we do not use add_keys_with_verify_against_master_keyring here, - # because "update" is run on regular package updates. A - # attacker might as well replace the master-archive-keyring file - # in the package and add his own keys. so this check wouldn't - # add any security. we *need* this check on net-update though - $GPG_CMD --quiet --batch --keyring $ARCHIVE_KEYRING --export | $GPG --import - - if [ -r "$REMOVED_KEYS" ]; then - # remove no-longer supported/used keys - keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5` - for key in $keys; do - if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then - $GPG --quiet --batch --delete-key --yes ${key} - fi - done - else - echo "Warning: removed keys keyring $REMOVED_KEYS missing or not readable" >&2 - fi -} - -remove_key_from_keyring() { - local GPG="$GPG_CMD --keyring $1" - # check if the key is in this keyring: the key id is in the 5 column at the end - if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then - return - fi - if [ ! -w "$1" ]; then - echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only." - return - fi - # check if it is the only key in the keyring and if so remove the keyring alltogether - if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then - mv -f "$1" "${1}~" # behave like gpg - return - fi - # we can't just modify pointed to files as these might be in /usr or something - local REALTARGET - if [ -L "$1" ]; then - REALTARGET="$(readlink -f "$1")" - mv -f "$1" "${1}.dpkg-tmp" - cp -a "$REALTARGET" "$1" - ls "$(dirname $1)" - fi - # delete the key from the keyring - $GPG --batch --delete-key --yes "$2" - if [ -n "$REALTARGET" ]; then - # the real backup is the old link, not the copy we made - mv -f "${1}.dpkg-tmp" "${1}~" - fi -} - -remove_key() { - requires_root - - # if a --keyring was given, just remove from there - if [ -n "$FORCED_KEYRING" ]; then - remove_key_from_keyring "$FORCED_KEYRING" "$1" - else - # otherwise all known keyrings are up for inspection - local TRUSTEDFILE="/etc/apt/trusted.gpg" - eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) - eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) - remove_key_from_keyring "$TRUSTEDFILE" "$1" - TRUSTEDPARTS="/etc/apt/trusted.gpg.d" - eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) - if [ -d "$TRUSTEDPARTS" ]; then - for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do - remove_key_from_keyring "$trusted" "$1" - done - fi - fi - echo "OK" -} - - -usage() { - echo "Usage: apt-key [--keyring file] [command] [arguments]" - echo - echo "Manage apt's list of trusted keys" - echo - echo " apt-key add - add the key contained in ('-' for stdin)" - echo " apt-key del - remove the key " - echo " apt-key export - output the key " - echo " apt-key exportall - output all trusted keys" - echo " apt-key update - update keys using the keyring package" - echo " apt-key net-update - update keys using the network" - echo " apt-key list - list keys" - echo " apt-key finger - list fingerprints" - echo " apt-key adv - pass advanced options to gpg (download key)" - echo - echo "If no specific keyring file is given the command applies to all keyring files." -} - -while [ -n "$1" ]; do - case "$1" in - --keyring) - shift - TRUSTEDFILE="$1" - FORCED_KEYRING="$1" - if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then - GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" - else - echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" - exit 1 - fi - shift - ;; - --fakeroot) - requires_root() { true; } - shift - ;; - --*) - echo >&2 "Unknown option: $1" - usage - exit 1;; - *) - break;; - esac -done - -if [ -z "$TRUSTEDFILE" ]; then - TRUSTEDFILE="/etc/apt/trusted.gpg" - eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) - eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) - if [ -r "$TRUSTEDFILE" ]; then - GPG="$GPG --keyring $TRUSTEDFILE" - fi - GPG="$GPG --primary-keyring $TRUSTEDFILE" - TRUSTEDPARTS="/etc/apt/trusted.gpg.d" - eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) - if [ -d "$TRUSTEDPARTS" ]; then - # strip / suffix as gpg will double-slash in that case (#665411) - STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}" - if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then - TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS" - fi - for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do - GPG="$GPG --keyring $trusted" - done - fi -fi - -command="$1" -if [ -z "$command" ]; then - usage - exit 1 -fi -shift - -if [ "$command" != "help" ] && ! which gpg >/dev/null 2>&1; then - echo >&2 "Warning: gnupg does not seem to be installed." - echo >&2 "Warning: apt-key requires gnupg for most operations." - echo >&2 -fi - -case "$command" in - add) - requires_root - init_keyring "$TRUSTEDFILE" - $GPG --quiet --batch --import "$1" - echo "OK" - ;; - del|rm|remove) - init_keyring "$TRUSTEDFILE" - remove_key "$1" - ;; - update) - init_keyring "$TRUSTEDFILE" - update - ;; - net-update) - init_keyring "$TRUSTEDFILE" - net_update - ;; - list) - init_keyring "$TRUSTEDFILE" - $GPG --batch --list-keys - ;; - finger*) - init_keyring "$TRUSTEDFILE" - $GPG --batch --fingerprint - ;; - export) - init_keyring "$TRUSTEDFILE" - $GPG --armor --export "$1" - ;; - exportall) - init_keyring "$TRUSTEDFILE" - $GPG --armor --export - ;; - adv*) - init_keyring "$TRUSTEDFILE" - echo "Executing: $GPG $*" - $GPG $* - ;; - help) - usage - ;; - *) - usage - exit 1 - ;; -esac diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in new file mode 100644 index 000000000..779872b4c --- /dev/null +++ b/cmdline/apt-key.in @@ -0,0 +1,354 @@ +#!/bin/sh + +set -e +unset GREP_OPTIONS + +GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" + +# gpg needs a trustdb to function, but it can't be invalid (not even empty) +# so we create a temporary directory to store our fresh readable trustdb in +TRUSTDBDIR="$(mktemp -d)" +CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" +trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +chmod 700 "$TRUSTDBDIR" +# We also don't use a secret keyring, of course, but gpg panics and +# implodes if there isn't one available - and writeable for imports +SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" +touch $SECRETKEYRING +GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" +GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" + +# now create the trustdb with an (empty) dummy keyring +$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING +# and make sure that gpg isn't trying to update the file +GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" + +GPG="$GPG_CMD" + +MASTER_KEYRING='&keyring-master-filename;' +eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) +ARCHIVE_KEYRING='&keyring-filename;' +eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) +REMOVED_KEYS='&keyring-removed-filename;' +eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) +ARCHIVE_KEYRING_URI='&keyring-uri;' +eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) +TMP_KEYRING=/var/lib/apt/keyrings/maybe-import-keyring.gpg + +requires_root() { + if [ "$(id -u)" -ne 0 ]; then + echo >&1 "ERROR: This command can only be used by root." + exit 1 + fi +} + +# gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead. +init_keyring() { + for path; do + if ! [ -e "$path" ]; then + touch -- "$path" + chmod 0644 -- "$path" + fi + done +} + +add_keys_with_verify_against_master_keyring() { + ADD_KEYRING=$1 + MASTER=$2 + + if [ ! -f "$ADD_KEYRING" ]; then + echo "ERROR: '$ADD_KEYRING' not found" + return + fi + if [ ! -f "$MASTER" ]; then + echo "ERROR: '$MASTER' not found" + return + fi + + # when adding new keys, make sure that the archive-master-keyring + # is honored. so: + # all keys that are exported must have a valid signature + # from a key in the $distro-master-keyring + add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^pub | cut -d: -f5` + all_add_keys=`$GPG_CMD --keyring $ADD_KEYRING --with-colons --list-keys | grep ^[ps]ub | cut -d: -f5` + master_keys=`$GPG_CMD --keyring $MASTER --with-colons --list-keys | grep ^pub | cut -d: -f5` + + # ensure there are no colisions LP: #857472 + for all_add_key in $all_add_keys; do + for master_key in $master_keys; do + if [ "$all_add_key" = "$master_key" ]; then + echo >&2 "Keyid collision for '$all_add_key' detected, operation aborted" + return 1 + fi + done + done + + for add_key in $add_keys; do + # export the add keyring one-by-one + rm -f $TMP_KEYRING + $GPG_CMD --keyring $ADD_KEYRING --output $TMP_KEYRING --export $add_key + # check if signed with the master key and only add in this case + ADDED=0 + for master_key in $master_keys; do + if $GPG_CMD --keyring $MASTER --keyring $TMP_KEYRING --check-sigs --with-colons $add_key | grep '^sig:!:' | cut -d: -f5 | grep -q $master_key; then + $GPG --import $TMP_KEYRING + ADDED=1 + fi + done + if [ $ADDED = 0 ]; then + echo >&2 "Key '$add_key' not added. It is not signed with a master key" + fi + done + rm -f $TMP_KEYRING +} + +# update the current archive signing keyring from a network URI +# the archive-keyring keys needs to be signed with the master key +# (otherwise it does not make sense from a security POV) +net_update() { + # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) + exit 1 + + if [ -z "$ARCHIVE_KEYRING_URI" ]; then + echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" + exit 1 + fi + requires_root + # in theory we would need to depend on wget for this, but this feature + # isn't useable in debian anyway as we have no keyring uri nor a master key + if ! which wget >/dev/null 2>&1; then + echo >&2 "ERROR: an installed wget is required for a network-based update" + exit 1 + fi + if [ ! -d /var/lib/apt/keyrings ]; then + mkdir -p /var/lib/apt/keyrings + fi + keyring=/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + old_mtime=0 + if [ -e $keyring ]; then + old_mtime=$(stat -c %Y $keyring) + fi + (cd /var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) + if [ ! -e $keyring ]; then + return + fi + new_mtime=$(stat -c %Y $keyring) + if [ $new_mtime -ne $old_mtime ]; then + echo "Checking for new archive signing keys now" + add_keys_with_verify_against_master_keyring $keyring $MASTER_KEYRING + fi +} + +update() { + if [ ! -f $ARCHIVE_KEYRING ]; then + echo >&2 "ERROR: Can't find the archive-keyring" + echo >&2 "Is the &keyring-package; package installed?" + exit 1 + fi + requires_root + + # add new keys from the package; + + # we do not use add_keys_with_verify_against_master_keyring here, + # because "update" is run on regular package updates. A + # attacker might as well replace the master-archive-keyring file + # in the package and add his own keys. so this check wouldn't + # add any security. we *need* this check on net-update though + $GPG_CMD --quiet --batch --keyring $ARCHIVE_KEYRING --export | $GPG --import + + if [ -r "$REMOVED_KEYS" ]; then + # remove no-longer supported/used keys + keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5` + for key in $keys; do + if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then + $GPG --quiet --batch --delete-key --yes ${key} + fi + done + else + echo "Warning: removed keys keyring $REMOVED_KEYS missing or not readable" >&2 + fi +} + +remove_key_from_keyring() { + local GPG="$GPG_CMD --keyring $1" + # check if the key is in this keyring: the key id is in the 5 column at the end + if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then + return + fi + if [ ! -w "$1" ]; then + echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only." + return + fi + # check if it is the only key in the keyring and if so remove the keyring alltogether + if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then + mv -f "$1" "${1}~" # behave like gpg + return + fi + # we can't just modify pointed to files as these might be in /usr or something + local REALTARGET + if [ -L "$1" ]; then + REALTARGET="$(readlink -f "$1")" + mv -f "$1" "${1}.dpkg-tmp" + cp -a "$REALTARGET" "$1" + ls "$(dirname $1)" + fi + # delete the key from the keyring + $GPG --batch --delete-key --yes "$2" + if [ -n "$REALTARGET" ]; then + # the real backup is the old link, not the copy we made + mv -f "${1}.dpkg-tmp" "${1}~" + fi +} + +remove_key() { + requires_root + + # if a --keyring was given, just remove from there + if [ -n "$FORCED_KEYRING" ]; then + remove_key_from_keyring "$FORCED_KEYRING" "$1" + else + # otherwise all known keyrings are up for inspection + local TRUSTEDFILE="/etc/apt/trusted.gpg" + eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) + eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) + remove_key_from_keyring "$TRUSTEDFILE" "$1" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do + remove_key_from_keyring "$trusted" "$1" + done + fi + fi + echo "OK" +} + + +usage() { + echo "Usage: apt-key [--keyring file] [command] [arguments]" + echo + echo "Manage apt's list of trusted keys" + echo + echo " apt-key add - add the key contained in ('-' for stdin)" + echo " apt-key del - remove the key " + echo " apt-key export - output the key " + echo " apt-key exportall - output all trusted keys" + echo " apt-key update - update keys using the keyring package" + echo " apt-key net-update - update keys using the network" + echo " apt-key list - list keys" + echo " apt-key finger - list fingerprints" + echo " apt-key adv - pass advanced options to gpg (download key)" + echo + echo "If no specific keyring file is given the command applies to all keyring files." +} + +while [ -n "$1" ]; do + case "$1" in + --keyring) + shift + TRUSTEDFILE="$1" + FORCED_KEYRING="$1" + if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then + GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" + else + echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" + exit 1 + fi + shift + ;; + --fakeroot) + requires_root() { true; } + shift + ;; + --*) + echo >&2 "Unknown option: $1" + usage + exit 1;; + *) + break;; + esac +done + +if [ -z "$TRUSTEDFILE" ]; then + TRUSTEDFILE="/etc/apt/trusted.gpg" + eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) + eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) + if [ -r "$TRUSTEDFILE" ]; then + GPG="$GPG --keyring $TRUSTEDFILE" + fi + GPG="$GPG --primary-keyring $TRUSTEDFILE" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + # strip / suffix as gpg will double-slash in that case (#665411) + STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}" + if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then + TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS" + fi + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do + GPG="$GPG --keyring $trusted" + done + fi +fi + +command="$1" +if [ -z "$command" ]; then + usage + exit 1 +fi +shift + +if [ "$command" != "help" ] && ! which gpg >/dev/null 2>&1; then + echo >&2 "Warning: gnupg does not seem to be installed." + echo >&2 "Warning: apt-key requires gnupg for most operations." + echo >&2 +fi + +case "$command" in + add) + requires_root + init_keyring "$TRUSTEDFILE" + $GPG --quiet --batch --import "$1" + echo "OK" + ;; + del|rm|remove) + init_keyring "$TRUSTEDFILE" + remove_key "$1" + ;; + update) + init_keyring "$TRUSTEDFILE" + update + ;; + net-update) + init_keyring "$TRUSTEDFILE" + net_update + ;; + list) + init_keyring "$TRUSTEDFILE" + $GPG --batch --list-keys + ;; + finger*) + init_keyring "$TRUSTEDFILE" + $GPG --batch --fingerprint + ;; + export) + init_keyring "$TRUSTEDFILE" + $GPG --armor --export "$1" + ;; + exportall) + init_keyring "$TRUSTEDFILE" + $GPG --armor --export + ;; + adv*) + init_keyring "$TRUSTEDFILE" + echo "Executing: $GPG $*" + $GPG $* + ;; + help) + usage + ;; + *) + usage + exit 1 + ;; +esac diff --git a/cmdline/makefile b/cmdline/makefile index e77ad5669..06f170b6a 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -41,6 +41,14 @@ SOURCE = apt-cdrom.cc include $(PROGRAM_H) # The apt-key program +apt-key: apt-key.in + sed -e "s#&keyring-filename;#$(shell ../vendor/getinfo keyring-filename)#" \ + -e "s#&keyring-removed-filename;#$(shell ../vendor/getinfo keyring-removed-filename)#" \ + -e "s#&keyring-master-filename;#$(shell ../vendor/getinfo keyring-master-filename)#" \ + -e "s#&keyring-uri;#$(shell ../vendor/getinfo keyring-uri)#" \ + -e "s#&keyring-package;#$(shell ../vendor/getinfo keyring-package)#" $< > $@ + chmod 755 $@ + SOURCE=apt-key TO=$(BIN) TARGET=program diff --git a/vendor/debian/apt-vendor.ent b/vendor/debian/apt-vendor.ent index 56775bbaa..6cda5995c 100644 --- a/vendor/debian/apt-vendor.ent +++ b/vendor/debian/apt-vendor.ent @@ -3,3 +3,5 @@ debian-archive-keyring"> /usr/share/keyrings/debian-archive-keyring.gpg"> /usr/share/keyrings/debian-archive-removed-keys.gpg"> + + diff --git a/vendor/getinfo b/vendor/getinfo index df5a44e5c..ac816e10e 100755 --- a/vendor/getinfo +++ b/vendor/getinfo @@ -26,7 +26,7 @@ debian-stable-codename) ubuntu-codename) getrawfield 'stable-codename' "${BASEDIR}/../doc/apt-verbatim.ent" ;; -keyring-package) +keyring-package|keyring-filename|keyring-master-filename|keyring-removed-filename|keyring-uri) getfield "$1" ;; *) diff --git a/vendor/ubuntu/apt-vendor.ent b/vendor/ubuntu/apt-vendor.ent index fd5e5a7cf..caa532699 100644 --- a/vendor/ubuntu/apt-vendor.ent +++ b/vendor/ubuntu/apt-vendor.ent @@ -3,3 +3,5 @@ ubuntu-keyring"> /usr/share/keyrings/ubuntu-archive-keyring.gpg"> /usr/share/keyrings/ubuntu-archive-removed-keys.gpg"> + + -- cgit v1.2.3-70-g09d2 From 7014e1482942d00b66eb30061b0cf5d2a7b3ebf3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 5 Dec 2013 08:11:11 +0100 Subject: * enable release based selection for deb-src (closes: 731102) --- apt-pkg/deb/debmetaindex.cc | 17 +++++- apt-pkg/deb/debmetaindex.h | 7 +++ apt-pkg/indexfile.h | 4 +- apt-pkg/indexrecords.cc | 5 ++ apt-pkg/indexrecords.h | 1 + apt-pkg/metaindex.h | 24 ++++++--- cmdline/apt-get.cc | 122 +++++++++++++++++++++++++++++++++++--------- 7 files changed, 145 insertions(+), 35 deletions(-) (limited to 'cmdline') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index b597b6f3c..504877558 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1,4 +1,3 @@ -// ijones, walters #include #include @@ -72,6 +71,22 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) +std::string debReleaseIndex::LocalFileName() const +{ + // see if we have a InRelease file + std::string PathInRelease = MetaIndexFile("InRelease"); + if (FileExists(PathInRelease)) + return PathInRelease; + + // and if not return the normal one + if (FileExists(PathInRelease)) + return MetaIndexFile("Release"); + + return ""; +} +#endif + string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const { string Res =""; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index b9ecab97c..cef8d68f7 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -3,6 +3,7 @@ #define PKGLIB_DEBMETAINDEX_H #include +#include #include #include @@ -39,9 +40,15 @@ class debReleaseIndex : public metaIndex { virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; std::vector * ComputeIndexTargets() const; std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const; + std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; std::string MetaIndexURI(const char *Type) const; + +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + virtual std::string LocalFileName() const; +#endif + std::string IndexURI(const char *Type, std::string const &Section, std::string const &Arch="native") const; std::string IndexURISuffix(const char *Type, std::string const &Section, std::string const &Arch="native") const; std::string SourceIndexURI(const char *Type, const std::string &Section) const; diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 1d34dc773..2d433b60a 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -78,10 +78,10 @@ class pkgIndexFile virtual bool Exists() const = 0; virtual bool HasPackages() const = 0; virtual unsigned long Size() const = 0; - virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const { return false; }; + virtual bool Merge(pkgCacheGenerator &Gen, OpProgress* Prog) const { return false; }; __deprecated virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const { return Merge(Gen, &Prog); }; - virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;}; + virtual bool MergeFileProvides(pkgCacheGenerator &Gen,OpProgress* Prog) const {return true;}; __deprecated virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const {return MergeFileProvides(Gen, &Prog);}; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 8a72ca151..f8097c3c6 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -27,6 +27,11 @@ string indexRecords::GetDist() const return this->Dist; } +string indexRecords::GetSuite() const +{ + return this->Suite; +} + bool indexRecords::CheckDist(const string MaybeDist) const { return (this->Dist == MaybeDist diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index a98b939bc..d003ec0fa 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -46,6 +46,7 @@ class indexRecords virtual bool Load(std::string Filename); std::string GetDist() const; + std::string GetSuite() const; time_t GetValidUntil() const; virtual bool CheckDist(const std::string MaybeDist) const; std::string GetExpectedDist() const; diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 5783735ff..18a90a29d 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -5,6 +5,7 @@ #include #include #include +#include #ifndef APT_8_CLEANER_HEADERS #include @@ -28,27 +29,36 @@ class metaIndex public: - // Various accessors virtual std::string GetURI() const {return URI;} virtual std::string GetDist() const {return Dist;} virtual const char* GetType() const {return Type;} + // interface to to query it +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + // returns the path of the local file (or "" if its not available) + virtual std::string LocalFileName() const {return "";}; +#endif + // Interface for acquire - virtual std::string ArchiveURI(std::string const& /*File*/) const = 0; + virtual std::string ArchiveURI(std::string const& File) const = 0; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; - virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; - metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) : - Indexes(NULL), Type(Type), URI(URI), Dist(Dist) { + metaIndex(std::string const &URI, std::string const &Dist, + char const * const Type) + : Indexes(NULL), Type(Type), URI(URI), Dist(Dist) + { + /* nothing */ } - virtual ~metaIndex() { + virtual ~metaIndex() + { if (Indexes == 0) return; - for (std::vector::iterator I = (*Indexes).begin(); I != (*Indexes).end(); ++I) + for (std::vector::iterator I = (*Indexes).begin(); + I != (*Indexes).end(); ++I) delete *I; delete Indexes; } diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 912b2d609..7e59f3d67 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -61,6 +63,8 @@ #include #include +#include + #include #include @@ -130,22 +134,80 @@ bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, return true; } /*}}}*/ + + +// helper that can go wit hthe next ABI break +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) +std::string MetaIndexFileNameOnDisk(metaIndex *metaindex) +{ + // FIXME: this cast is the horror, the horror + debReleaseIndex *r = (debReleaseIndex*)metaindex; + + // see if we have a InRelease file + std::string PathInRelease = r->MetaIndexFile("InRelease"); + if (FileExists(PathInRelease)) + return PathInRelease; + + // and if not return the normal one + if (FileExists(PathInRelease)) + return r->MetaIndexFile("Release"); + + return ""; +} +#endif + +// GetReleaseForSourceRecord - Return Suite for the given srcrecord /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, + pkgSrcRecords::Parser *Parse) +{ + // try to find release + const pkgIndexFile& CurrentIndexFile = Parse->Index(); + + for (pkgSourceList::const_iterator S = SrcList->begin(); + S != SrcList->end(); ++S) + { + vector *Indexes = (*S)->GetIndexFiles(); + for (vector::const_iterator IF = Indexes->begin(); + IF != Indexes->end(); ++IF) + { + if (&CurrentIndexFile == (*IF)) + { +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) + std::string path = MetaIndexFileNameOnDisk(*S); +#else + std::string path = (*S)->LocalFileName(); +#endif + if (path != "") + { + indexRecords records; + records.Load(path); + return records.GetSuite(); + } + } + } + } + return ""; +} + /*}}}*/ // FindSrc - Find a source record /*{{{*/ // --------------------------------------------------------------------- /* */ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords &SrcRecs,string &Src, - pkgDepCache &Cache) + CacheFile &CacheFile) { string VerTag; - string DefRel = _config->Find("APT::Default-Release"); + string RelTag = _config->Find("APT::Default-Release"); string TmpSrc = Name; + pkgDepCache *Cache = CacheFile.GetDepCache(); // extract the version/release from the pkgname const size_t found = TmpSrc.find_last_of("/="); if (found != string::npos) { if (TmpSrc[found] == '/') - DefRel = TmpSrc.substr(found+1); + RelTag = TmpSrc.substr(found+1); else VerTag = TmpSrc.substr(found+1); TmpSrc = TmpSrc.substr(0,found); @@ -155,10 +217,10 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, install a version and determine the source package name, then look in the archive for a source package of the same name. */ bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source"); - const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc); + const pkgCache::PkgIterator Pkg = Cache->FindPkg(TmpSrc); if (MatchSrcOnly == false && Pkg.end() == false) { - if(VerTag.empty() == false || DefRel.empty() == false) + if(VerTag.empty() == false || RelTag.empty() == false) { bool fuzzy = false; // we have a default release, try to locate the pkg. we do it like @@ -180,7 +242,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, } // We match against a concrete version (or a part of this version) if (VerTag.empty() == false && - (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match + (fuzzy == true || Cache->VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match continue; @@ -198,8 +260,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, // or we match against a release if(VerTag.empty() == false || - (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) || - (VF.File().Codename() != 0 && VF.File().Codename() == DefRel)) + (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) || + (VF.File().Codename() != 0 && VF.File().Codename() == RelTag)) { pkgRecords::Parser &Parse = Recs.Lookup(VF); Src = Parse.SourcePkg(); @@ -217,22 +279,14 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Src.empty() == false) break; } - if (Src.empty() == true) - { - // Sources files have no codename information - if (VerTag.empty() == true && DefRel.empty() == false) - { - _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str()); - return 0; - } - } } if (Src.empty() == true) { // if we don't have found a fitting package yet so we will // choose a good candidate and proceed with that. // Maybe we will find a source later on with the right VerTag - pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg); + // or RelTag + pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg); if (Ver.end() == false) { pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList()); @@ -244,7 +298,9 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, } if (Src.empty() == true) + { Src = TmpSrc; + } else { /* if we have a source pkg name, make sure to only search @@ -262,6 +318,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords::Parser *Last = 0; unsigned long Offset = 0; string Version; + pkgSourceList *SrcList = CacheFile.GetSourceList(); /* Iterate over all of the hits, which includes the resulting binary packages in the search */ @@ -273,25 +330,40 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, { const string Ver = Parse->Version(); + // See if we need to look for a specific release tag + if (RelTag != "") + { + const string Rel = GetReleaseForSourceRecord(SrcList, Parse); + + if (Rel == RelTag) + { + ioprintf(c1out, "Selectied version '%s' (%s) for %s\n", + Ver.c_str(), RelTag.c_str(), Src.c_str()); + Last = Parse; + Offset = Parse->Offset(); + break; + } + } + // Ignore all versions which doesn't fit if (VerTag.empty() == false && - Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match + Cache->VS().CmpVersion(VerTag, Ver) != 0) // exact match continue; // Newer version or an exact match? Save the hit - if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) { + if (Last == 0 || Cache->VS().CmpVersion(Version,Ver) < 0) { Last = Parse; Offset = Parse->Offset(); Version = Ver; } - // was the version check above an exact match? If so, we don't need to look further - if (VerTag.empty() == false && VerTag.size() == Ver.size()) + // was the version check above an exact match? + // If so, we don't need to look further + if (VerTag.empty() == false && (VerTag == Ver)) break; } if (Last != 0 || VerTag.empty() == true) break; - //if (VerTag.empty() == false && Last == 0) _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); return 0; } @@ -628,7 +700,7 @@ bool DoSource(CommandLine &CmdL) for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; - pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache); + pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); if (Last == 0) { delete[] Dsc; @@ -925,7 +997,7 @@ bool DoBuildDep(CommandLine &CmdL) for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; - pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache); + pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); if (Last == 0) return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); -- cgit v1.2.3-70-g09d2 From 651ae5ce5f376ae5274933c621a3b897ac5152a6 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 10 Dec 2013 16:35:44 +0100 Subject: if there is only deb-src pick higest version in deb-src release matching --- cmdline/apt-get.cc | 8 +++++--- test/integration/test-apt-get-source | 9 +++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 7e59f3d67..3853f94c2 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -337,11 +337,9 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Rel == RelTag) { - ioprintf(c1out, "Selectied version '%s' (%s) for %s\n", - Ver.c_str(), RelTag.c_str(), Src.c_str()); Last = Parse; Offset = Parse->Offset(); - break; + Version = Ver; } } @@ -362,6 +360,10 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (VerTag.empty() == false && (VerTag == Ver)) break; } + if (Version != "" && RelTag != "") + ioprintf(c1out, "Selectied version '%s' (%s) for %s\n", + Version.c_str(), RelTag.c_str(), Src.c_str()); + if (Last != 0 || VerTag.empty() == true) break; _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source index 5bef781f1..6bca22145 100755 --- a/test/integration/test-apt-get-source +++ b/test/integration/test-apt-get-source @@ -15,10 +15,14 @@ insertpackage 'wheezy' 'unreleated-package' 'all' '1.0' insertpackage 'unstable' 'foo' 'all' '2.0' insertsource 'unstable' 'foo' 'all' '2.0' +# its possible to have multiple src versions in the sources file, do not break +# in this case (bts #731853) +insertsource 'stable' 'foo' 'all' '1.5' insertpackage 'stable' 'foo' 'all' '1.0' insertsource 'stable' 'foo' 'all' '1.0' -# this package exists only as source +# this packages exists only as source +insertsource 'wheezy' 'foo' 'all' '0.0.1' insertsource 'wheezy' 'foo' 'all' '0.1' setupaptarchive @@ -46,7 +50,8 @@ Need to get 0 B of source archives. 'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo=1.0 -# select by release with no binary package (Bug#731102) +# select by release with no binary package (Bug#731102) but ensure to get +# higest version testequal "$HEADER Selectied version '0.1' (wheezy) for foo Need to get 0 B of source archives. -- cgit v1.2.3-70-g09d2 From bfa7bfc8e426f662ee5a5d0fcba3daeea23fe2ae Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 10 Dec 2013 17:02:30 +0100 Subject: fix typo --- cmdline/apt-get.cc | 2 +- test/integration/test-apt-get-source | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 3853f94c2..da04561c0 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -361,7 +361,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, break; } if (Version != "" && RelTag != "") - ioprintf(c1out, "Selectied version '%s' (%s) for %s\n", + ioprintf(c1out, "Selected version '%s' (%s) for %s\n", Version.c_str(), RelTag.c_str(), Src.c_str()); if (Last != 0 || VerTag.empty() == true) diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source index e2536ae7a..b98ebbada 100755 --- a/test/integration/test-apt-get-source +++ b/test/integration/test-apt-get-source @@ -41,7 +41,7 @@ Need to get 0 B of source archives. # select by release testequal "$HEADER -Selectied version '1.0' (stable) for foo +Selected version '1.0' (stable) for foo Need to get 0 B of source archives. 'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/stable @@ -55,7 +55,7 @@ Need to get 0 B of source archives. # select by release with no binary package (Bug#731102) but ensure to get # higest version testequal "$HEADER -Selectied version '0.1' (wheezy) for foo +Selected version '0.1' (wheezy) for foo Need to get 0 B of source archives. 'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/wheezy -- cgit v1.2.3-70-g09d2 From 65dcff55dc5c9b47230d340a70c5067921eec4bf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 10 Dec 2013 17:09:56 +0100 Subject: user-requested version tag gets precedence in apt-get source -t dist pkg=version requests --- cmdline/apt-get.cc | 8 ++++---- test/integration/test-apt-get-source | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index da04561c0..581466326 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -198,7 +198,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords &SrcRecs,string &Src, CacheFile &CacheFile) { - string VerTag; + string VerTag, UserRequestedVerTag; string RelTag = _config->Find("APT::Default-Release"); string TmpSrc = Name; pkgDepCache *Cache = CacheFile.GetDepCache(); @@ -209,7 +209,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (TmpSrc[found] == '/') RelTag = TmpSrc.substr(found+1); else - VerTag = TmpSrc.substr(found+1); + VerTag = UserRequestedVerTag = TmpSrc.substr(found+1); TmpSrc = TmpSrc.substr(0,found); } @@ -331,7 +331,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, const string Ver = Parse->Version(); // See if we need to look for a specific release tag - if (RelTag != "") + if (RelTag != "" && UserRequestedVerTag == "") { const string Rel = GetReleaseForSourceRecord(SrcList, Parse); @@ -360,7 +360,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (VerTag.empty() == false && (VerTag == Ver)) break; } - if (Version != "" && RelTag != "") + if (UserRequestedVerTag == "" && Version != "" && RelTag != "") ioprintf(c1out, "Selected version '%s' (%s) for %s\n", Version.c_str(), RelTag.c_str(), Src.c_str()); diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source index b98ebbada..c8db4edbe 100755 --- a/test/integration/test-apt-get-source +++ b/test/integration/test-apt-get-source @@ -65,3 +65,8 @@ testequal "$HEADER E: Ignore unavailable version '9.9-not-there' of package 'foo' E: Unable to find a source package for foo" aptget source -q --print-uris foo=9.9-not-there +# version and release +testequal "$HEADER +Need to get 0 B of source archives. +'file://${APTARCHIVE}/foo_0.0.1.dsc' foo_0.0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/foo_0.0.1.tar.gz' foo_0.0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris -t unstable foo=0.0.1 -- cgit v1.2.3-70-g09d2 From adf379e7ad1900db6d3942ac7dca5cec4737d9a1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 11 Dec 2013 08:21:04 +0100 Subject: add support for "apt-get source pkg:arch" --- cmdline/apt-get.cc | 60 +++++++++++++++++++++++++------ test/integration/test-apt-get-source-arch | 60 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 10 deletions(-) create mode 100755 test/integration/test-apt-get-source-arch (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 581466326..9cc5b4031 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -198,18 +198,31 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgSrcRecords &SrcRecs,string &Src, CacheFile &CacheFile) { - string VerTag, UserRequestedVerTag; + string VerTag, UserRequestedVerTag; + string ArchTag = ""; string RelTag = _config->Find("APT::Default-Release"); string TmpSrc = Name; pkgDepCache *Cache = CacheFile.GetDepCache(); - // extract the version/release from the pkgname - const size_t found = TmpSrc.find_last_of("/="); - if (found != string::npos) { - if (TmpSrc[found] == '/') - RelTag = TmpSrc.substr(found+1); - else - VerTag = UserRequestedVerTag = TmpSrc.substr(found+1); + // extract release + size_t found = TmpSrc.find_last_of("/"); + if (found != string::npos) + { + RelTag = TmpSrc.substr(found+1); + TmpSrc = TmpSrc.substr(0,found); + } + // extract the version + found = TmpSrc.find_last_of("="); + if (found != string::npos) + { + VerTag = UserRequestedVerTag = TmpSrc.substr(found+1); + TmpSrc = TmpSrc.substr(0,found); + } + // extract arch + found = TmpSrc.find_last_of(":"); + if (found != string::npos) + { + ArchTag = TmpSrc.substr(found+1); TmpSrc = TmpSrc.substr(0,found); } @@ -217,10 +230,25 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, install a version and determine the source package name, then look in the archive for a source package of the same name. */ bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source"); - const pkgCache::PkgIterator Pkg = Cache->FindPkg(TmpSrc); + pkgCache::PkgIterator Pkg; + if (ArchTag != "") + Pkg = Cache->FindPkg(TmpSrc, ArchTag); + else + Pkg = Cache->FindPkg(TmpSrc); + + // if we can't find a package but the user qualified with a arch, + // error out here + if (Pkg.end() && ArchTag != "") + { + Src = Name; + _error->Error(_("Can not find a package for architecture '%s'"), + ArchTag.c_str()); + return 0; + } + if (MatchSrcOnly == false && Pkg.end() == false) { - if(VerTag.empty() == false || RelTag.empty() == false) + if(VerTag != "" || RelTag != "" || ArchTag != "") { bool fuzzy = false; // we have a default release, try to locate the pkg. we do it like @@ -240,6 +268,17 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Ver.end() == true) break; } + + // pick highest version for the arch unless the user wants + // something else + if (ArchTag != "" && VerTag == "" && RelTag == "") + { + if(Ver.Arch() != ArchTag) + continue; + if(Cache->VS().CmpVersion(VerTag, Ver.VerStr()) < 0) + VerTag = Ver.VerStr(); + } + // We match against a concrete version (or a part of this version) if (VerTag.empty() == false && (fuzzy == true || Cache->VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match @@ -280,6 +319,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, break; } } + if (Src.empty() == true) { // if we don't have found a fitting package yet so we will diff --git a/test/integration/test-apt-get-source-arch b/test/integration/test-apt-get-source-arch new file mode 100755 index 000000000..3ac6907a9 --- /dev/null +++ b/test/integration/test-apt-get-source-arch @@ -0,0 +1,60 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture "i386" "amd64" + + +# different version for the individual arches +insertpackage 'stable' 'foo' 'amd64' '1.0' +insertsource 'stable' 'foo' 'amd64' '1.0' + +insertpackage 'stable' 'foo' 'i386' '1.0' +insertsource 'stable' 'foo' 'i386' '1.0' +insertpackage 'stable' 'foo' 'i386' '2.0' +insertsource 'stable' 'foo' 'i386' '2.0' + +insertpackage 'oldstable' 'foo' 'i386' '0.1' +insertsource 'oldstable' 'foo' 'i386' '0.1' +# just needed so that there is a release file entry for the test +insertpackage 'oldstable' 'unreleated' 'amd64' '0.1' + +setupaptarchive + +APTARCHIVE=$(readlink -f ./aptarchive) + +HEADER="Reading package lists... +Building dependency tree..." + +# pick :amd64 +testequal "$HEADER +Need to get 0 B of source archives. +'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:amd64 + +# pick :i386 +testequal "$HEADER +Need to get 0 B of source archives. +'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386 + +# pick :i386 by release +testequal "$HEADER +Selected version '0.1' (oldstable) for foo +Need to get 0 B of source archives. +'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386/oldstable + +# pick :i386 by version +testequal "$HEADER +Need to get 0 B of source archives. +'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e +'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386=1.0 + +# error on unknown arch +testequal "$HEADER +E: Can not find a package for architecture 'not-a-available-arch' +E: Unable to find a source package for foo:not-a-available-arch" aptget source -q --print-uris foo:not-a-available-arch -- cgit v1.2.3-70-g09d2 From 37f45a579d4344c3ef6a044b12b992353e238301 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 11 Dec 2013 09:21:26 +0100 Subject: improve error message for apt-get source pkg:arch{=ver,/release} --- cmdline/apt-get.cc | 18 ++++++++++++++---- test/integration/test-apt-get-source-arch | 10 ++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 9cc5b4031..c2b59a83c 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -269,15 +269,15 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, break; } + // ignore arches that are not for us + if (ArchTag != "" && Ver.Arch() != ArchTag) + continue; + // pick highest version for the arch unless the user wants // something else if (ArchTag != "" && VerTag == "" && RelTag == "") - { - if(Ver.Arch() != ArchTag) - continue; if(Cache->VS().CmpVersion(VerTag, Ver.VerStr()) < 0) VerTag = Ver.VerStr(); - } // We match against a concrete version (or a part of this version) if (VerTag.empty() == false && @@ -320,6 +320,16 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, } } + if (Src == "" && ArchTag != "") + { + _error->Error(_("Can not find a package '%s' with version '%s' and " + "release '%s'"), Pkg.FullName().c_str(), + VerTag.c_str(), RelTag.c_str()); + Src = Name; + return 0; + } + + if (Src.empty() == true) { // if we don't have found a fitting package yet so we will diff --git a/test/integration/test-apt-get-source-arch b/test/integration/test-apt-get-source-arch index 3ac6907a9..97d0e096a 100755 --- a/test/integration/test-apt-get-source-arch +++ b/test/integration/test-apt-get-source-arch @@ -58,3 +58,13 @@ Need to get 0 B of source archives. testequal "$HEADER E: Can not find a package for architecture 'not-a-available-arch' E: Unable to find a source package for foo:not-a-available-arch" aptget source -q --print-uris foo:not-a-available-arch + +# error on unavailable version for arch +testequal "$HEADER +E: Can not find a package 'foo:amd64' with version '2.0' and release '' +E: Unable to find a source package for foo:amd64=2.0" aptget source -q --print-uris foo:amd64=2.0 + +# error on unavailable release for arch +testequal "$HEADER +E: Can not find a package 'foo:amd64' with version '' and release 'oldstable' +E: Unable to find a source package for foo:amd64/oldstable" aptget source -q --print-uris foo:amd64/oldstable -- cgit v1.2.3-70-g09d2 From c9829e0744ca678e105aa0af26b87588023d7536 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 11 Dec 2013 14:03:53 +0100 Subject: improve error message --- cmdline/apt-get.cc | 9 ++++++--- test/integration/test-apt-get-source-arch | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index c2b59a83c..0b980cdf4 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -322,9 +322,12 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Src == "" && ArchTag != "") { - _error->Error(_("Can not find a package '%s' with version '%s' and " - "release '%s'"), Pkg.FullName().c_str(), - VerTag.c_str(), RelTag.c_str()); + if (VerTag != "") + _error->Error(_("Can not find a package '%s' with version '%s'"), + Pkg.FullName().c_str(), VerTag.c_str()); + if (RelTag != "") + _error->Error(_("Can not find a package '%s' with release '%s'"), + Pkg.FullName().c_str(), RelTag.c_str()); Src = Name; return 0; } diff --git a/test/integration/test-apt-get-source-arch b/test/integration/test-apt-get-source-arch index 97d0e096a..d7ed56dc9 100755 --- a/test/integration/test-apt-get-source-arch +++ b/test/integration/test-apt-get-source-arch @@ -61,10 +61,10 @@ E: Unable to find a source package for foo:not-a-available-arch" aptget source - # error on unavailable version for arch testequal "$HEADER -E: Can not find a package 'foo:amd64' with version '2.0' and release '' +E: Can not find a package 'foo:amd64' with version '2.0' E: Unable to find a source package for foo:amd64=2.0" aptget source -q --print-uris foo:amd64=2.0 # error on unavailable release for arch testequal "$HEADER -E: Can not find a package 'foo:amd64' with version '' and release 'oldstable' +E: Can not find a package 'foo:amd64' with release 'oldstable' E: Unable to find a source package for foo:amd64/oldstable" aptget source -q --print-uris foo:amd64/oldstable -- cgit v1.2.3-70-g09d2 From 017d3f3b4b0da976b1d2ecfcd26251369c5aec88 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 12 Dec 2013 07:41:17 +0100 Subject: clarify error message when apt-get source=ver fails, print a real error message instead of "ignoring" --- cmdline/apt-get.cc | 2 +- test/integration/test-apt-get-source | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index c2b59a83c..6973901dc 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -416,7 +416,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Last != 0 || VerTag.empty() == true) break; - _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); + _error->Error(_("Can not find version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); return 0; } diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source index c8db4edbe..3ee7a9e23 100755 --- a/test/integration/test-apt-get-source +++ b/test/integration/test-apt-get-source @@ -62,7 +62,7 @@ Need to get 0 B of source archives. # unavailable one testequal "$HEADER -E: Ignore unavailable version '9.9-not-there' of package 'foo' +E: Can not find version '9.9-not-there' of package 'foo' E: Unable to find a source package for foo" aptget source -q --print-uris foo=9.9-not-there # version and release -- cgit v1.2.3-70-g09d2 From 5acf154d810a0225cc7d14637d101205e43ceba8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 13 Dec 2013 14:37:14 +0100 Subject: make apt-key net-update actually testable --- cmdline/apt-key.in | 19 +++++++++++++------ test/integration/test-apt-key-net-update | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index 779872b4c..c7d3ce8b5 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -25,6 +25,9 @@ GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" +APT_DIR="/" +eval $(apt-config shell APT_DIR Dir) + MASTER_KEYRING='&keyring-master-filename;' eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) ARCHIVE_KEYRING='&keyring-filename;' @@ -33,7 +36,7 @@ REMOVED_KEYS='&keyring-removed-filename;' eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) ARCHIVE_KEYRING_URI='&keyring-uri;' eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) -TMP_KEYRING=/var/lib/apt/keyrings/maybe-import-keyring.gpg +TMP_KEYRING=${APT_DIR}/var/lib/apt/keyrings/maybe-import-keyring.gpg requires_root() { if [ "$(id -u)" -ne 0 ]; then @@ -107,7 +110,11 @@ add_keys_with_verify_against_master_keyring() { # (otherwise it does not make sense from a security POV) net_update() { # Disabled for now as code is insecure (LP: #1013639 (and 857472, 1013128)) - exit 1 + APT_KEY_NET_UPDATE_ENABLED="" + eval $(apt-config shell APT_KEY_NET_UPDATE_ENABLED APT::Key::Net-Update-Enabled) + if [ -z "$APT_KEY_NET_UPDATE_ENABLED" ]; then + exit 1 + fi if [ -z "$ARCHIVE_KEYRING_URI" ]; then echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" @@ -120,15 +127,15 @@ net_update() { echo >&2 "ERROR: an installed wget is required for a network-based update" exit 1 fi - if [ ! -d /var/lib/apt/keyrings ]; then - mkdir -p /var/lib/apt/keyrings + if [ ! -d ${APT_DIR}/var/lib/apt/keyrings ]; then + mkdir -p ${APT_DIR}/var/lib/apt/keyrings fi - keyring=/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) old_mtime=0 if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) fi - (cd /var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) + (cd ${APT_DIR}/var/lib/apt/keyrings; wget --timeout=90 -q -N $ARCHIVE_KEYRING_URI) if [ ! -e $keyring ]; then return fi diff --git a/test/integration/test-apt-key-net-update b/test/integration/test-apt-key-net-update index 73545aff7..e0869402e 100755 --- a/test/integration/test-apt-key-net-update +++ b/test/integration/test-apt-key-net-update @@ -6,6 +6,20 @@ TESTDIR=$(readlink -f $(dirname $0)) setupenvironment configarchitecture "i386" +changetowebserver + +# setup env +mkdir -p aptarchive/ubuntu/project var/lib/apt/keyrings +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/ubuntu-archive-keyring.gpg";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf + +# signed thing +echo "meep" > aptarchive/ubuntu/project/ubuntu-archive-keyring.gpg + +# test against the "real" webserver +aptkey --fakeroot net-update + +exit 1 # mock requires_root() { -- cgit v1.2.3-70-g09d2 From e5543ea5a236426dd33e74e427e8485a030a2540 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 19 Dec 2013 16:43:50 +0100 Subject: fix apt-key net-update test to use the buildin webserver --- cmdline/apt-key.in | 2 +- .../integration/exploid-keyring-with-dupe-keys.pub | Bin 3986 -> 0 bytes .../exploid-keyring-with-dupe-subkeys.pub | Bin 2016 -> 0 bytes test/integration/keyrings/test-archive-keyring.pub | Bin 0 -> 979 bytes test/integration/keyrings/test-archive-keyring.sec | Bin 0 -> 1355 bytes test/integration/keyrings/test-master-keyring.pub | Bin 0 -> 1199 bytes test/integration/keyrings/test-master-keyring.sec | Bin 0 -> 2501 bytes test/integration/test-apt-key-net-update | 133 ++++----------------- 8 files changed, 25 insertions(+), 110 deletions(-) delete mode 100644 test/integration/exploid-keyring-with-dupe-keys.pub delete mode 100644 test/integration/exploid-keyring-with-dupe-subkeys.pub create mode 100644 test/integration/keyrings/test-archive-keyring.pub create mode 100644 test/integration/keyrings/test-archive-keyring.sec create mode 100644 test/integration/keyrings/test-master-keyring.pub create mode 100644 test/integration/keyrings/test-master-keyring.sec (limited to 'cmdline') diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index c7d3ce8b5..463e4b4b4 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -130,7 +130,7 @@ net_update() { if [ ! -d ${APT_DIR}/var/lib/apt/keyrings ]; then mkdir -p ${APT_DIR}/var/lib/apt/keyrings fi - keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING) + keyring=${APT_DIR}/var/lib/apt/keyrings/$(basename $ARCHIVE_KEYRING_URI) old_mtime=0 if [ -e $keyring ]; then old_mtime=$(stat -c %Y $keyring) diff --git a/test/integration/exploid-keyring-with-dupe-keys.pub b/test/integration/exploid-keyring-with-dupe-keys.pub deleted file mode 100644 index 642952a40..000000000 Binary files a/test/integration/exploid-keyring-with-dupe-keys.pub and /dev/null differ diff --git a/test/integration/exploid-keyring-with-dupe-subkeys.pub b/test/integration/exploid-keyring-with-dupe-subkeys.pub deleted file mode 100644 index 02d4e6ee8..000000000 Binary files a/test/integration/exploid-keyring-with-dupe-subkeys.pub and /dev/null differ diff --git a/test/integration/keyrings/test-archive-keyring.pub b/test/integration/keyrings/test-archive-keyring.pub new file mode 100644 index 000000000..d8d9d472b Binary files /dev/null and b/test/integration/keyrings/test-archive-keyring.pub differ diff --git a/test/integration/keyrings/test-archive-keyring.sec b/test/integration/keyrings/test-archive-keyring.sec new file mode 100644 index 000000000..aece750e8 Binary files /dev/null and b/test/integration/keyrings/test-archive-keyring.sec differ diff --git a/test/integration/keyrings/test-master-keyring.pub b/test/integration/keyrings/test-master-keyring.pub new file mode 100644 index 000000000..33aa16796 Binary files /dev/null and b/test/integration/keyrings/test-master-keyring.pub differ diff --git a/test/integration/keyrings/test-master-keyring.sec b/test/integration/keyrings/test-master-keyring.sec new file mode 100644 index 000000000..9cb33176c Binary files /dev/null and b/test/integration/keyrings/test-master-keyring.sec differ diff --git a/test/integration/test-apt-key-net-update b/test/integration/test-apt-key-net-update index e0869402e..4b38cd9b5 100755 --- a/test/integration/test-apt-key-net-update +++ b/test/integration/test-apt-key-net-update @@ -9,120 +9,35 @@ configarchitecture "i386" changetowebserver # setup env -mkdir -p aptarchive/ubuntu/project var/lib/apt/keyrings -echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/ubuntu-archive-keyring.gpg";' >> ./aptconfig.conf -echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf - -# signed thing -echo "meep" > aptarchive/ubuntu/project/ubuntu-archive-keyring.gpg - -# test against the "real" webserver -aptkey --fakeroot net-update - -exit 1 - -# mock -requires_root() { - return 0 -} - -# extract net_update() and import it -func=$( sed -n -e '/^add_keys_with_verify_against_master_keyring/,/^}/p' ${BUILDDIRECTORY}/apt-key ) -eval "$func" - -mkdir -p ./etc/apt -TRUSTEDFILE=./etc/apt/trusted.gpg -mkdir -p ./var/lib/apt/keyrings -TMP_KEYRING=./var/lib/apt/keyrings/maybe-import-keyring.gpg -GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" - -# FIXME: instead of copying this use apt-key and the buildin apt webserver -# to do a real test - -# COPYIED from apt-key.in -------------- - -# gpg needs a trustdb to function, but it can't be invalid (not even empty) -# so we create a temporary directory to store our fresh readable trustdb in -TRUSTDBDIR="$(mktemp -d)" -CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" -trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -chmod 700 "$TRUSTDBDIR" -# We also don't use a secret keyring, of course, but gpg panics and -# implodes if there isn't one available - and writeable for imports -SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" -touch $SECRETKEYRING -GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" -GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" -#----------------------------------------- END COPY +mkdir -p var/lib/apt/keyrings +mkdir -p usr/share/keyrings -GPG="$GPG_CMD --keyring $TRUSTEDFILE" -MASTER_KEYRING=/usr/share/keyrings/ubuntu-master-keyring.gpg - -msgtest "add_keys_with_verify_against_master_keyring" -if [ ! -e $MASTER_KEYRING ]; then - echo -n "No $MASTER_KEYRING found" - msgskip - exit 0 -fi - -# test bad keyring and ensure its not added (LP: #857472) -ADD_KEYRING=./keys/exploid-keyring-with-dupe-keys.pub -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgfail -else - msgpass -fi - -# ensure the keyring is still empty -gpg_out=$($GPG --list-keys) -msgtest "Test if keyring is empty" -if [ -n "" ]; then - msgfail -else - msgpass -fi - - -# test another possible attack vector using subkeys (LP: #1013128) -msgtest "add_keys_with_verify_against_master_keyring with subkey attack" -ADD_KEYRING=./keys/exploid-keyring-with-dupe-subkeys.pub -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgfail -else - msgpass -fi - -# ensure the keyring is still empty -gpg_out=$($GPG --list-keys) -msgtest "Test if keyring is empty" -if [ -n "" ]; then - msgfail -else - msgpass -fi +# install the fake master keyring +install -m0644 keys/test-master-keyring.pub usr/share/keyrings +echo "APT::Key::MasterKeyring \"${TMPWORKINGDIRECTORY}/usr/share/keyrings/test-master-keyring.pub\";" >> ./aptconfig.conf +# setup archive-keyring +mkdir -p aptarchive/ubuntu/project +install -m0644 keys/test-archive-keyring.pub aptarchive/ubuntu/project/ +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/test-archive-keyring.pub";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf -# test good keyring and ensure we get no errors -ADD_KEYRING=/usr/share/keyrings/ubuntu-archive-keyring.gpg -if add_keys_with_verify_against_master_keyring $ADD_KEYRING $MASTER_KEYRING; then - msgpass -else - msgfail -fi +# test against the "real" webserver +testequal 'Checking for new archive signing keys now +gpg: key F68C85A3: public key "Test Automatic Archive Signing Key " imported +gpg: Total number processed: 1 +gpg: imported: 1 (RSA: 1)' aptkey --fakeroot net-update -testequal './etc/apt/trusted.gpg ---------------------- -pub 1024D/437D05B5 2004-09-12 -uid Ubuntu Archive Automatic Signing Key -sub 2048g/79164387 2004-09-12 -pub 1024D/FBB75451 2004-12-30 -uid Ubuntu CD Image Automatic Signing Key +# now try a different one +# setup archive-keyring +mkdir -p aptarchive/ubuntu/project +install -m0644 keys/marvinparanoid.pub aptarchive/ubuntu/project/ +echo 'APT::Key::ArchiveKeyringURI "http://localhost:8080/ubuntu/project/marvinparanoid.pub";' >> ./aptconfig.conf +echo 'APT::Key::Net-Update-Enabled "1";' >> ./aptconfig.conf -pub 4096R/C0B21F32 2012-05-11 -uid Ubuntu Archive Automatic Signing Key (2012) +# test against the "real" webserver +testequal "Checking for new archive signing keys now +Key 'E8525D47528144E2' not added. It is not signed with a master key" aptkey --fakeroot net-update -pub 4096R/EFE21092 2012-05-11 -uid Ubuntu CD Image Automatic Signing Key (2012) -' $GPG --list-keys -- cgit v1.2.3-70-g09d2 From 68e0172140872d8044b3c768a6bea3ac58d426c4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 22 Dec 2013 22:15:52 +0100 Subject: factor GetTempDir out --- apt-pkg/contrib/fileutl.cc | 17 +++++++++++++++++ apt-pkg/contrib/fileutl.h | 2 ++ apt-pkg/contrib/gpgv.cc | 15 ++------------- cmdline/apt-extracttemplates.cc | 11 +++-------- cmdline/apt-get.cc | 10 ++++------ 5 files changed, 28 insertions(+), 27 deletions(-) (limited to 'cmdline') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 7fbe4d604..847d8b47f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1827,3 +1827,20 @@ std::vector Glob(std::string const &pattern, int flags) return result; } /*}}}*/ + +std::string GetTempDir() +{ + const char *tmpdir = getenv("TMPDIR"); + +#ifdef P_tmpdir + if (!tmpdir) + tmpdir = P_tmpdir; +#endif + + // check that tmpdir is set and exists + struct stat st; + if (!tmpdir || stat(tmpdir, &st) != 0) + tmpdir = "/tmp"; + + return string(tmpdir); +} diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index e9a9aab28..e752e9621 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -165,6 +165,8 @@ bool DirectoryExists(std::string const &Path) __attrib_const; bool CreateDirectory(std::string const &Parent, std::string const &Path); time_t GetModificationTime(std::string const &Path); +std::string GetTempDir(); + /** \brief Ensure the existence of the given Path * * \param Parent directory of the Path directory - a trailing diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 8f619fee2..f57a72d86 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -22,20 +22,9 @@ /*}}}*/ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/ { - const char *tmpdir = getenv("TMPDIR"); - -#ifdef P_tmpdir - if (!tmpdir) - tmpdir = P_tmpdir; -#endif - - // check that tmpdir is set and exists - struct stat st; - if (!tmpdir || stat(tmpdir, &st) != 0) - tmpdir = "/tmp"; - std::string out; - strprintf(out, "%s/%s.XXXXXX", tmpdir, basename); + std::string tmpdir = GetTempDir(); + strprintf(out, "%s/%s.XXXXXX", tmpdir.c_str(), basename); return strdup(out.c_str()); } /*}}}*/ diff --git a/cmdline/apt-extracttemplates.cc b/cmdline/apt-extracttemplates.cc index 8fe15fdf9..8e1937113 100644 --- a/cmdline/apt-extracttemplates.cc +++ b/cmdline/apt-extracttemplates.cc @@ -47,8 +47,6 @@ using namespace std; -#define TMPDIR "/tmp" - pkgCache *DebFile::Cache = 0; // DebFile::DebFile - Construct the DebFile object /*{{{*/ @@ -253,14 +251,11 @@ string WriteFile(const char *package, const char *prefix, const char *data) { char fn[512]; static int i; - const char *tempdir = NULL; - - tempdir = getenv("TMPDIR"); - if (tempdir == NULL) - tempdir = TMPDIR; + std::string tempdir = GetTempDir(); snprintf(fn, sizeof(fn), "%s/%s.%s.%u%d", - _config->Find("APT::ExtractTemplates::TempDir", tempdir).c_str(), + _config->Find("APT::ExtractTemplates::TempDir", + tempdir.c_str()).c_str(), package, prefix, getpid(), i++); FileFd f; if (data == NULL) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 730d3ea18..8a0772ce2 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1536,14 +1536,12 @@ bool DoChangelog(CommandLine &CmdL) bool const downOnly = _config->FindB("APT::Get::Download-Only", false); char tmpname[100]; - char* tmpdir = NULL; + const char* tmpdir = NULL; if (downOnly == false) { - const char* const tmpDir = getenv("TMPDIR"); - if (tmpDir != NULL && *tmpDir != '\0') - snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir); - else - strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname)); + std::string systemTemp = GetTempDir(); + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", + systemTemp.c_str()); tmpdir = mkdtemp(tmpname); if (tmpdir == NULL) return _error->Errno("mkdtemp", "mkdtemp failed"); -- cgit v1.2.3-70-g09d2