diff options
-rw-r--r-- | apt-pkg/acquire-item.cc | 4 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 23 | ||||
-rw-r--r-- | doc/sources.list.5.xml | 17 | ||||
-rw-r--r-- | methods/gpgv.cc | 34 | ||||
-rwxr-xr-x | test/integration/test-signed-by-option | 35 |
5 files changed, 104 insertions, 9 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index eb8053feb..a4a6bc4a3 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1912,7 +1912,7 @@ string pkgAcqMetaClearSig::Custom600Headers() const Header += "\nFail-Ignore: true"; std::string const key = TransactionManager->MetaIndexParser->GetSignedBy(); if (key.empty() == false) - Header += "\nSigned-By: " + key; + Header += "\nSigned-By: " + QuoteString(key, ""); return Header; } @@ -2168,7 +2168,7 @@ std::string pkgAcqMetaSig::Custom600Headers() const std::string Header = pkgAcqTransactionItem::Custom600Headers(); std::string const key = TransactionManager->MetaIndexParser->GetSignedBy(); if (key.empty() == false) - Header += "\nSigned-By: " + key; + Header += "\nSigned-By: " + QuoteString(key, ""); return Header; } /*}}}*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index d78cea758..88a55a477 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -54,8 +54,27 @@ static std::string transformFingergrpintsWithFilenames(std::string const &finger return transformFingergrpints(finger); } /*}}}*/ -static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFilenames) /*{{{*/ +// Introducer is set if additional keys may be introduced, for example /*{{{*/ +// by setting it to a filename or a complete key +static std::string NormalizeSignedBy(std::string SignedBy, bool const Introducer) { + // This is an embedded public pgp key, normalize spaces inside it and empty "." lines + if (Introducer && SignedBy.find("-----BEGIN PGP PUBLIC KEY BLOCK-----") != std::string::npos) { + std::istringstream is(SignedBy); + std::ostringstream os; + std::string line; + + while (std::getline(is, line)) { + line = APT::String::Strip(line); + // The special encoding for empty lines in deb822 + if (line == ".") + line=""; + os << line << std::endl; + } + std::clog << "OUTPUT " << os.str() << std::endl; + return os.str(); + } + // we could go all fancy and allow short/long/string matches as gpgv/apt-key does, // but fingerprints are harder to fake than the others and this option is set once, // not interactively all the time so easy to type is not really a concern. @@ -67,7 +86,7 @@ static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFil fingers.erase(std::remove_if(fingers.begin(), fingers.end(), isAnEmptyString), fingers.end()); if (unlikely(fingers.empty())) return ""; - if (SupportFilenames) + if (Introducer) std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpintsWithFilenames); else std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpints); diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index 6929201a0..ed99f08f8 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -312,6 +312,23 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. of this repository (only fingerprints can be specified there through). Otherwise all keys in the trusted keyrings are considered valid signers for this repository. + + The option may also be set directly to an embedded GPG public key block. Special + care is needed to encode the empty line with leading spaces and ".": + <literallayout>Types: deb +URIs: https://deb.debian.org +Suites: stable +Components: main contrib non-free +Signed-By: + -----BEGIN PGP PUBLIC KEY BLOCK----- + . + mDMEYCQjIxYJKwYBBAHaRw8BAQdAD/P5Nvvnvk66SxBBHDbhRml9ORg1WV5CvzKY + CuMfoIS0BmFiY2RlZoiQBBMWCgA4FiEErCIG1VhKWMWo2yfAREZd5NfO31cFAmAk + IyMCGyMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQREZd5NfO31fbOwD6ArzS + dM0Dkd5h2Ujy1b6KcAaVW9FOa5UNfJ9FFBtjLQEBAJ7UyWD3dZzhvlaAwunsk7DG + 3bHcln8DMpIJVXht78sL + =IE0r + -----END PGP PUBLIC KEY BLOCK-----</literallayout> </para></listitem> <listitem><para><option>Check-Valid-Until</option> (<option>check-valid-until</option>) diff --git a/methods/gpgv.cc b/methods/gpgv.cc index a9da456ec..594e8781a 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -416,6 +416,14 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, return _("Unknown error executing apt-key"); } +static std::string GenerateKeyFile(std::string const key) +{ + FileFd fd; + GetTempFile("apt-key.XXXXXX.asc", false, &fd); + fd.Write(key.data(), key.size()); + return fd.Name(); +} + bool GPGVMethod::URIAcquire(std::string const &Message, FetchItem *Itm) { URI const Get(Itm->Uri); @@ -423,11 +431,27 @@ bool GPGVMethod::URIAcquire(std::string const &Message, FetchItem *Itm) SignersStorage Signers; std::vector<std::string> keyFpts, keyFiles; - for (auto &&key : VectorizeString(LookupTag(Message, "Signed-By"), ',')) - if (key.empty() == false && key[0] == '/') - keyFiles.emplace_back(std::move(key)); - else - keyFpts.emplace_back(std::move(key)); + struct TemporaryFile + { + std::string name = ""; + ~TemporaryFile() { if (0) RemoveFile("~TemporaryFile", name); } + } tmpKey; + + std::string SignedBy = DeQuoteString(LookupTag(Message, "Signed-By")); + + if (SignedBy.find("-----BEGIN PGP PUBLIC KEY BLOCK-----") != std::string::npos) + { + tmpKey.name = GenerateKeyFile(SignedBy); + keyFiles.emplace_back(tmpKey.name); + } + else + { + for (auto &&key : VectorizeString(SignedBy, ',')) + if (key.empty() == false && key[0] == '/') + keyFiles.emplace_back(std::move(key)); + else + keyFpts.emplace_back(std::move(key)); + } // Run apt-key on file, extract contents and get the key ID of the signer string const msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), keyFpts, keyFiles, Signers); diff --git a/test/integration/test-signed-by-option b/test/integration/test-signed-by-option index faa7dec44..986088bce 100755 --- a/test/integration/test-signed-by-option +++ b/test/integration/test-signed-by-option @@ -31,3 +31,38 @@ Signed-By: CDE5618B8805FD6E202CE9C2D73C39E56580B386! AAAAAAAAAAAAAAAAAAAAA , , BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB EOF testsuccess --nomsg aptcache policy + +buildsimplenativepackage "coolstuff" "all" "1.0" "stable" +setupaptarchive --no-update +rm -f rootdir/etc/apt/sources.list.d/* rootdir/etc/apt/sources.list +rm -f rootdir/etc/apt/trusted.gpg.d/* rootdir/etc/apt/trusted.gpg + +cat > rootdir/etc/apt/sources.list.d/deb822.sources << EOF +Types: deb +URIs: file://$PWD/aptarchive +Suites: stable +Components: main +xSigned-By: + -----BEGIN PGP PUBLIC KEY BLOCK----- + . + mQENBExsGNYBCADNVx+TQ6h1tEyUP11f7ihfta3ZePkW1rIdkdHgA3Fw/TeLnTEq + mWuhMw2pL4zy1vQhU8efNrRaNUrUS7kV3LIdSjd5K4Aizqtsdy/gLKFoTcO8LFIm + KAXPg5hZBZ1B1HWvw7Npe4nkIj0Ar+bUyMfyCBUeqoaNeIy31a4IiNo8LdD73DOh + 4APKcp+pXh2s2DOmWOnTI8Z+WZ9W2ZurtdZl8g04hszGatwVKrNc6p5wK0wAvJ+X + M0HaIVt/+90GVLCMb/Gjf66At73BS19BdRDPi54PPK5N+Q9HZAYq0zPPNySB3l4A + vGjZtCqljkSqiaL1C0ZKf8c5ey/FoAviyS7TABEBAAG0M0pvZSBTaXhwYWNrIChB + UFQgVGVzdGNhc2VzIER1bW15KSA8am9lQGV4YW1wbGUub3JnPokBNwQTAQoAIQIb + AwIeAQIXgAUCV7L5PQULCQgHAwUVCgkICwUWAgMBAAAKCRBakNFB26yNri5RB/sF + xRzAFAwwp6TQNeZk3L2zsHD2ZPKaoWzi1l+nD4grfP1enuAnwcLR3HG4zouN3nCg + M0PgZEUo2yOAnKK4D5XWkcZjhcoCj133bTW807e+aM6d08ns+piIGJ8VdUVYlNZ2 + Tnr8eunkUQVkWQGjtHicIJFtjbokIKXzlJtVSklF/kDQ+v93kyj1SNM7Tm57Q01i + ZtB2jCXNYvqdlHaZw1oXdVd1R6u0+SSb4wtjHuTeYG76JaCnWKBnvexWhIEN1MxK + xNHhRHzEPTYZ4PCCyaRX4YRAwsEMFsscsghpQgqRDhGSWq+jUVI+Aay7FTnd+1UA + 1snsGpB0o9qxx8JpGMXI + =c/k4 + -----END PGP PUBLIC KEY BLOCK----- +EOF +testfailure apt update -o Debug::Acquire::gpgv=1 +testsuccess grep "NO_PUBKEY 5A90D141DBAC8DAE" rootdir/tmp/testfailure.output +sed -i s/^xSigned-By/Signed-By/ rootdir/etc/apt/sources.list.d/deb822.sources +testsuccess apt update -o Debug::Acquire::gpgv=1 |