summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2010-06-09 10:52:45 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2010-06-09 10:52:45 +0200
commit308b793694774eece8765d172b8e989d8ed29925 (patch)
treebad798009c7f2b857c060e299294f63eabc3b20f /apt-pkg
parent1aa9b2974d33015102224ffb738b2e8e0a4bcb42 (diff)
parentb02fffa64833e1f8e2617669d89de0a6d0882747 (diff)
- backport forgotten Valid-Until patch from the obsolete experimental
branch to prevent replay attacks better, thanks to Thomas Viehmann for the initial patch! (Closes: #499897) * doc/apt.conf.5.xml: - document the new Valid-Until related options * apt-pkg/contrib/strutl.cc: - split StrToTime() into HTTP1.1 and FTP date parser methods and use strptime() instead of some self-made scanf mangling - use the portable timegm shown in his manpage instead of a strange looking code copycat from wget * ftparchive/writer.cc: - add ValidTime option to generate a Valid-Until header in Release file
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc14
-rw-r--r--apt-pkg/acquire-method.cc2
-rw-r--r--apt-pkg/contrib/strutl.cc72
-rw-r--r--apt-pkg/contrib/strutl.h4
-rw-r--r--apt-pkg/indexrecords.cc45
-rw-r--r--apt-pkg/indexrecords.h4
6 files changed, 115 insertions, 26 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 9e29f8189..629d572a4 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -33,6 +33,7 @@
#include <string>
#include <sstream>
#include <stdio.h>
+#include <ctime>
/*}}}*/
using namespace std;
@@ -1180,6 +1181,17 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message) /*{{{*/
Transformed = "";
}
+ if (_config->FindB("Acquire::Check-Valid-Until", true) == true &&
+ MetaIndexParser->GetValidUntil() > 0) {
+ time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil();
+ if (invalid_since > 0)
+ // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
+ // the time since then the file is invalid - formated in the same way as in
+ // the download progress display (e.g. 7d 3h 42min 1s)
+ return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
+ RealURI.c_str(), TimeToStr(invalid_since).c_str());
+ }
+
if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl;
@@ -1197,7 +1209,7 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message) /*{{{*/
// return false;
if (!Transformed.empty())
{
- _error->Warning("Conflicting distribution: %s (expected %s but got %s)",
+ _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
Desc.Description.c_str(),
Transformed.c_str(),
MetaIndexParser->GetDist().c_str());
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index fe066741c..b82dceecb 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -373,7 +373,7 @@ int pkgAcqMethod::Run(bool Single)
Tmp->Uri = LookupTag(Message,"URI");
Tmp->DestFile = LookupTag(Message,"FileName");
- if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
+ if (RFC1123StrToTime(LookupTag(Message,"Last-Modified").c_str(),Tmp->LastModified) == false)
Tmp->LastModified = 0;
Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
Tmp->Next = 0;
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index c7d63ce8a..160450366 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -827,34 +827,66 @@ static int MonthConv(char *Month)
}
}
/*}}}*/
-// timegm - Internal timegm function if gnu is not available /*{{{*/
+// timegm - Internal timegm if the gnu version is not available /*{{{*/
// ---------------------------------------------------------------------
-/* Ripped this evil little function from wget - I prefer the use of
- GNU timegm if possible as this technique will have interesting problems
- with leap seconds, timezones and other.
-
- Converts struct tm to time_t, assuming the data in tm is UTC rather
+/* Converts struct tm to time_t, assuming the data in tm is UTC rather
than local timezone (mktime assumes the latter).
-
- Contributed by Roger Beeman <beeman@cisco.com>, with the help of
- Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO. */
-
-/* Turned it into an autoconf check, because GNU is not the only thing which
- can provide timegm. -- 2002-09-22, Joel Baker */
-#ifndef HAVE_TIMEGM // Now with autoconf!
+ This function is a nonstandard GNU extension that is also present on
+ the BSDs and maybe other systems. For others we follow the advice of
+ the manpage of timegm and use his portable replacement. */
+#ifndef HAVE_TIMEGM
static time_t timegm(struct tm *t)
{
- time_t tl, tb;
-
- tl = mktime (t);
- if (tl == -1)
- return -1;
- tb = mktime (gmtime (&tl));
- return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl)));
+ char *tz = getenv("TZ");
+ setenv("TZ", "", 1);
+ tzset();
+ time_t ret = mktime(t);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+ return ret;
}
#endif
/*}}}*/
+// FullDateToTime - Converts a HTTP1.1 full date strings into a time_t /*{{{*/
+// ---------------------------------------------------------------------
+/* tries to parses a full date as specified in RFC2616 Section 3.3.1
+ with one exception: All timezones (%Z) are accepted but the protocol
+ says that it MUST be GMT, but this one is equal to UTC which we will
+ encounter from time to time (e.g. in Release files) so we accept all
+ here and just assume it is GMT (or UTC) later on */
+bool RFC1123StrToTime(const char* const str,time_t &time)
+{
+ struct tm Tm;
+ // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ if (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL &&
+ // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &Tm) == NULL &&
+ // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL)
+ return false;
+
+ time = timegm(&Tm);
+ return true;
+}
+ /*}}}*/
+// FTPMDTMStrToTime - Converts a ftp modification date into a time_t /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FTPMDTMStrToTime(const char* const str,time_t &time)
+{
+ struct tm Tm;
+ // MDTM includes no whitespaces but recommend and ignored by strptime
+ if (strptime(str, "%Y %m %d %H %M %S", &Tm) == NULL)
+ return false;
+
+ time = timegm(&Tm);
+ return true;
+}
+ /*}}}*/
// StrToTime - Converts a string into a time_t /*{{{*/
// ---------------------------------------------------------------------
/* This handles all 3 populare time formats including RFC 1123, RFC 1036
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index e509145f9..a457ff047 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -45,7 +45,9 @@ string Base64Encode(const string &Str);
string OutputInDepth(const unsigned long Depth, const char* Separator=" ");
string URItoFileName(const string &URI);
string TimeRFC1123(time_t Date);
-bool StrToTime(const string &Val,time_t &Result);
+bool RFC1123StrToTime(const char* const str,time_t &time) __must_check;
+bool FTPMDTMStrToTime(const char* const str,time_t &time) __must_check;
+__deprecated bool StrToTime(const string &Val,time_t &Result);
string LookupTag(const string &Message,const char *Tag,const char *Default = 0);
int StringToBool(const string &Text,int Default = -1);
bool ReadMessages(int Fd, vector<string> &List);
diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc
index 9a9600531..eb9a36866 100644
--- a/apt-pkg/indexrecords.cc
+++ b/apt-pkg/indexrecords.cc
@@ -7,8 +7,11 @@
#include <apt-pkg/tagfile.h>
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
+#include <apt-pkg/configuration.h>
#include <apti18n.h>
#include <sys/stat.h>
+#include <clocale>
+
/*}}}*/
string indexRecords::GetDist() const
{
@@ -26,6 +29,11 @@ string indexRecords::GetExpectedDist() const
return this->ExpectedDist;
}
+time_t indexRecords::GetValidUntil() const
+{
+ return this->ValidUntil;
+}
+
const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
{
return Entries[MetaKey];
@@ -85,9 +93,40 @@ bool indexRecords::Load(const string Filename) /*{{{*/
{
strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
return false;
- }
+ }
+
+ string Label = Section.FindS("Label");
+ string StrDate = Section.FindS("Date");
+ string StrValidUntil = Section.FindS("Valid-Until");
+
+ // if we have a Valid-Until header in the Release file, use it as default
+ if (StrValidUntil.empty() == false)
+ {
+ if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
+ {
+ strprintf(ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
+ return false;
+ }
+ }
+ // get the user settings for this archive and use what expires earlier
+ int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
+ if (Label.empty() == true)
+ MaxAge = _config->FindI(string("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
+
+ if(MaxAge == 0) // No user settings, use the one from the Release file
+ return true;
+
+ time_t date;
+ if (RFC1123StrToTime(StrDate.c_str(), date) == false)
+ {
+ strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
+ return false;
+ }
+ date += 24*60*60*MaxAge;
+
+ if (ValidUntil == 0 || ValidUntil > date)
+ ValidUntil = date;
- string Strdate = Section.FindS("Date"); // FIXME: verify this somehow?
return true;
}
/*}}}*/
@@ -165,6 +204,6 @@ indexRecords::indexRecords()
}
indexRecords::indexRecords(const string ExpectedDist) :
- ExpectedDist(ExpectedDist)
+ ExpectedDist(ExpectedDist), ValidUntil(0)
{
}
diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h
index 2e3103b70..5b532c1a5 100644
--- a/apt-pkg/indexrecords.h
+++ b/apt-pkg/indexrecords.h
@@ -12,6 +12,7 @@
#include <map>
#include <vector>
+#include <ctime>
class indexRecords
{
@@ -25,6 +26,8 @@ class indexRecords
string Dist;
string Suite;
string ExpectedDist;
+ time_t ValidUntil;
+
std::map<string,checkSum *> Entries;
public:
@@ -40,6 +43,7 @@ class indexRecords
virtual bool Load(string Filename);
string GetDist() const;
+ time_t GetValidUntil() const;
virtual bool CheckDist(const string MaybeDist) const;
string GetExpectedDist() const;
virtual ~indexRecords(){};