summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/deb/debmetaindex.cc113
1 files changed, 62 insertions, 51 deletions
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 9c7c70784..1afcdf2c0 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -28,6 +28,57 @@
#include <apti18n.h>
+static std::string transformFingergrpints(std::string finger) /*{{{*/
+{
+ std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
+ if (finger.length() == 40)
+ {
+ if (finger.find_first_not_of("0123456789ABCDEF") == std::string::npos)
+ return finger;
+ }
+ else if (finger.length() == 41)
+ {
+ auto bang = finger.find_first_not_of("0123456789ABCDEF");
+ if (bang == 40 && finger[bang] == '!')
+ return finger;
+ }
+ return "";
+}
+ /*}}}*/
+static std::string transformFingergrpintsWithFilenames(std::string const &finger) /*{{{*/
+{
+ // no check for existence as we could be chrooting later or such things
+ if (finger.empty() == false && finger[0] == '/')
+ return finger;
+ return transformFingergrpints(finger);
+}
+ /*}}}*/
+static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFilenames) /*{{{*/
+{
+ // 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.
+ std::transform(SignedBy.begin(), SignedBy.end(), SignedBy.begin(), [](char const c) {
+ return (isspace(c) == 0) ? c : ',';
+ });
+ auto fingers = VectorizeString(SignedBy, ',');
+ auto const isAnEmptyString = [](std::string const &s) { return s.empty(); };
+ fingers.erase(std::remove_if(fingers.begin(), fingers.end(), isAnEmptyString), fingers.end());
+ if (unlikely(fingers.empty()))
+ return "";
+ if (SupportFilenames)
+ std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpintsWithFilenames);
+ else
+ std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpints);
+ if (std::any_of(fingers.begin(), fingers.end(), isAnEmptyString))
+ return "";
+ std::stringstream os;
+ std::copy(fingers.begin(), fingers.end() - 1, std::ostream_iterator<std::string>(os, ","));
+ os << *fingers.rbegin();
+ return os.str();
+}
+ /*}}}*/
+
class APT_HIDDEN debReleaseIndexPrivate /*{{{*/
{
public:
@@ -566,26 +617,9 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
auto Sign = Section.FindS("Signed-By");
if (Sign.empty() == false)
{
- std::transform(Sign.begin(), Sign.end(), Sign.begin(), [&](char const c) {
- return (isspace(c) == 0) ? c : ',';
- });
- auto fingers = VectorizeString(Sign, ',');
- std::transform(fingers.begin(), fingers.end(), fingers.begin(), [&](std::string finger) {
- std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
- if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos)
- {
- if (ErrorText != NULL)
- strprintf(*ErrorText, _("Invalid '%s' entry in Release file %s"), "Signed-By", Filename.c_str());
- return std::string();
- }
- return finger;
- });
- if (fingers.empty() == false && std::find(fingers.begin(), fingers.end(), "") == fingers.end())
- {
- std::stringstream os;
- std::copy(fingers.begin(), fingers.end(), std::ostream_iterator<std::string>(os, ","));
- SignedBy = os.str();
- }
+ SignedBy = NormalizeSignedBy(Sign, false);
+ if (SignedBy.empty() && ErrorText != NULL)
+ strprintf(*ErrorText, _("Invalid '%s' entry in Release file %s"), "Signed-By", Filename.c_str());
}
if (AuthPossible)
@@ -737,38 +771,15 @@ bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy)
{
if (SignedBy.empty() == true && pSignedBy.empty() == false)
{
- if (pSignedBy[0] == '/') // no check for existence as we could be chrooting later or such things
- SignedBy = pSignedBy; // absolute path to a keyring file
- else
- {
- // 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.
- auto fingers = VectorizeString(pSignedBy, ',');
- std::transform(fingers.begin(), fingers.end(), fingers.begin(), [&](std::string finger) {
- std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
- if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos)
- {
- _error->Error(_("Invalid value set for option %s regarding source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint");
- return std::string();
- }
- return finger;
- });
- std::stringstream os;
- std::copy(fingers.begin(), fingers.end(), std::ostream_iterator<std::string>(os, ","));
- SignedBy = os.str();
- }
- // Normalize the string: Remove trailing commas
- while (SignedBy[SignedBy.size() - 1] == ',')
- SignedBy.resize(SignedBy.size() - 1);
+ SignedBy = NormalizeSignedBy(pSignedBy, true);
+ if (SignedBy.empty())
+ _error->Error(_("Invalid value set for option %s regarding source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint");
}
- else {
- // Only compare normalized strings
- auto pSignedByView = APT::StringView(pSignedBy);
- while (pSignedByView[pSignedByView.size() - 1] == ',')
- pSignedByView = pSignedByView.substr(0, pSignedByView.size() - 1);
- if (pSignedByView != SignedBy)
- return _error->Error(_("Conflicting values set for option %s regarding source %s %s: %s != %s"), "Signed-By", URI.c_str(), Dist.c_str(), SignedBy.c_str(), pSignedByView.to_string().c_str());
+ else
+ {
+ auto const normalSignedBy = NormalizeSignedBy(pSignedBy, true);
+ if (normalSignedBy != SignedBy)
+ return _error->Error(_("Conflicting values set for option %s regarding source %s %s: %s != %s"), "Signed-By", URI.c_str(), Dist.c_str(), SignedBy.c_str(), normalSignedBy.c_str());
}
return true;
}