diff options
author | David Kalnischkies <david@kalnischkies.de> | 2016-04-29 16:48:16 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2016-05-01 10:50:24 +0200 |
commit | 89901946f936446f439b95f1a9a85ac942ac2c92 (patch) | |
tree | f74a7cf049fbfbda478c1fdeec05c1a45d552302 /apt-pkg/deb | |
parent | 46e00c9062d09a642973e83a334483db1f310397 (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')
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 56 |
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 |