summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/contrib/gpgv.cc59
1 files changed, 54 insertions, 5 deletions
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index dd1a279fc..fdc292f4f 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -168,17 +168,66 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
Args.push_back(aptkey);
Args.push_back("--quiet");
Args.push_back("--readonly");
+ auto dearmorKeyOrCheckFormat = [&](std::string const &k) -> std::string
+ {
+ FileFd keyFd(k, FileFd::ReadOnly);
+ if (not keyFd.IsOpen())
+ {
+ apt_warning(std::cerr, statusfd, fd, "The key(s) in the keyring %s are ignored as the file is not readable by user executing apt-key.\n", k.c_str());
+ return "";
+ }
+ if (APT::String::Endswith(k, ".gpg") || APT::String::Endswith(k, ".pub"))
+ {
+ unsigned char c;
+ if (not keyFd.Read(&c, sizeof(c)))
+ goto err;
+ // Identify the leading byte of an OpenPGP public key packet
+ // 0x98 -- old-format OpenPGP public key packet, up to 255 octets
+ // 0x99 -- old-format OpenPGP public key packet, 256-65535 octets
+ // 0xc6 -- new-format OpenPGP public key packet, any length
+ if (c == 0x98 || c == 0x99 || c == 0xc6)
+ return k;
+ }
+ else if (APT::String::Endswith(k, ".asc"))
+ {
+ std::string b64msg;
+ int state = 0;
+ for (std::string line; keyFd.ReadLine(line);)
+ {
+ line = APT::String::Strip(line);
+ if (APT::String::Startswith(line, "-----BEGIN PGP PUBLIC KEY BLOCK-----"))
+ state = 1;
+ else if (state == 1 && line == "")
+ state = 2;
+ else if (state == 2 && line != "" && line[0] != '=' && line[0] != '-')
+ b64msg += line;
+ else if (APT::String::Startswith(line, "-----END"))
+ state = 3;
+ }
+ if (state != 3)
+ goto err;
+
+ FileFd dearmoredFd;
+ if (GetTempFile("apt.XXXXXX.gpg", false, &dearmoredFd) == nullptr)
+ local_exit(EINTERNAL);
+ if (auto decoded = Base64Decode(b64msg); not decoded.empty())
+ dearmoredFd.Write(decoded.data(), decoded.size());
+ local_exit.files.push_back(dearmoredFd.Name());
+ return dearmoredFd.Name();
+ }
+ err:
+ apt_warning(std::cerr, statusfd, fd, "The key(s) in the keyring %s are ignored as the file has an unsupported filetype.", k.c_str());
+ return "";
+ };
auto maybeAddKeyring = [&](std::string const &k)
{
if (struct stat st; stat(k.c_str(), &st) != 0 || st.st_size == 0)
return;
- if (access(k.c_str(), R_OK) != 0)
+ if (auto cleanKey = dearmorKeyOrCheckFormat(k); not cleanKey.empty())
{
- apt_warning(std::cerr, statusfd, fd, "The key(s) in the keyring %s are ignored as the file is not readable by user executing apt-key.\n", k.c_str());
- return;
+ Args.push_back("--keyring");
+ Args.push_back(cleanKey);
}
- Args.push_back("--keyring");
- Args.push_back(k);
return;
};