summaryrefslogtreecommitdiff
path: root/apt-pkg/deb/debmetaindex.cc
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-04-29 16:48:16 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-05-01 10:50:24 +0200
commit89901946f936446f439b95f1a9a85ac942ac2c92 (patch)
treef74a7cf049fbfbda478c1fdeec05c1a45d552302 /apt-pkg/deb/debmetaindex.cc
parent46e00c9062d09a642973e83a334483db1f310397 (diff)
support Signed-By in Release files as a sort of HPKP
Users have the option since apt >= 1.1 to enforce that a Release file is signed with specific key(s) either via keyring filename or fingerprints. This commit adds an entry with the same name and value (except that it doesn't accept filenames for obvious reasons) to the Release file so that the repository owner can set a default value for this setting effecting the *next* Release file, not the current one, which provides a functionality similar "HTTP Public Key Pinning". The pinning is in effect as long as the (then old) Release file is considered valid, but it is also ignored if the Release file has no Valid-Until at all.
Diffstat (limited to 'apt-pkg/deb/debmetaindex.cc')
-rw-r--r--apt-pkg/deb/debmetaindex.cc56
1 files changed, 53 insertions, 3 deletions
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 5b84ea5e8..d152eaf68 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -442,7 +442,7 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
std::string const StrDate = Section.FindS("Date");
if (RFC1123StrToTime(StrDate.c_str(), Date) == false)
{
- _error->Warning( _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
+ _error->Warning( _("Invalid '%s' entry in Release file %s"), "Date", Filename.c_str());
Date = 0;
}
@@ -463,7 +463,7 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
{
if (ErrorText != NULL)
- strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
+ strprintf(*ErrorText, _("Invalid '%s' entry in Release file %s"), "Valid-Until", Filename.c_str());
return false;
}
}
@@ -498,6 +498,33 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
}
}
+ /* as the Release file is parsed only after it was verified, the Signed-By field
+ does not effect the current, but the "next" Release file */
+ 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();
+ }
+ }
+
LoadedSuccessfully = TRI_YES;
return true;
}
@@ -956,7 +983,30 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/
std::map<std::string, std::string>::const_iterator const signedby = Options.find("signed-by");
if (signedby == Options.end())
{
- if (Deb->SetSignedBy("") == false)
+ bool alreadySet = false;
+ std::string filename;
+ if (ReleaseFileName(Deb, filename))
+ {
+ auto OldDeb = Deb->UnloadedClone();
+ _error->PushToStack();
+ OldDeb->Load(filename, nullptr);
+ bool const goodLoad = _error->PendingError() == false;
+ _error->RevertToStack();
+ if (goodLoad)
+ {
+ if (OldDeb->GetValidUntil() > 0)
+ {
+ time_t const invalid_since = time(NULL) - OldDeb->GetValidUntil();
+ if (invalid_since <= 0)
+ {
+ Deb->SetSignedBy(OldDeb->GetSignedBy());
+ alreadySet = true;
+ }
+ }
+ }
+ delete OldDeb;
+ }
+ if (alreadySet == false && Deb->SetSignedBy("") == false)
return false;
}
else