]> git.saurik.com Git - apt.git/commitdiff
add sources.list Check-Valid-Until and Valid-Until-{Max,Min} options
authorDavid Kalnischkies <david@kalnischkies.de>
Tue, 23 Jun 2015 15:26:57 +0000 (17:26 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Mon, 10 Aug 2015 15:25:26 +0000 (17:25 +0200)
These options could be set via configuration before, but the connection
to the actual sources is so strong that they should really be set in the
sources.list instead – especially as this can be done a lot more
specific rather than e.g. disabling Valid-Until for all sources at once.

Valid-Until-* names are chosen instead of the Min/Max-ValidTime as this
seems like a better name and their use in the wild is probably low
enough that this isn't going to confuse anyone if we have to names for
the same thing in different areas.

In the longrun, the config options should be removed, but for now
documentation hinting at the new options is good enough as these are the
kind of options you set once across many systems with different apt
versions, so the new way should work everywhere first before we
deprecate the old way.

apt-pkg/acquire-item.cc
apt-pkg/deb/debmetaindex.cc
apt-pkg/deb/debmetaindex.h
apt-pkg/sourcelist.cc
doc/apt-get.8.xml
doc/apt.conf.5.xml
doc/sources.list.5.xml
test/integration/test-releasefile-valid-until

index 100199bc10689afd2417ddcec7b5e2b90fc3b077..a30a5d1548d5e2829219fb89f20efbbd1802fb23 100644 (file)
@@ -1041,8 +1041,8 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message)          /*{{{*/
       Transformed = "";
    }
 
-   if (_config->FindB("Acquire::Check-Valid-Until", true) == true &&
-       TransactionManager->MetaIndexParser->GetValidUntil() > 0) {
+   if (TransactionManager->MetaIndexParser->GetValidUntil() > 0)
+   {
       time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil();
       if (invalid_since > 0)
       {
index f0b859eb4c74eb7fe502293daafdd9ae041d242b..5d7e539c7cbd5f7d9310246ce54d2b353d6dc2d6 100644 (file)
@@ -44,7 +44,11 @@ class APT_HIDDEN debReleaseIndexPrivate                                      /*{{{*/
    std::vector<debSectionEntry> DebEntries;
    std::vector<debSectionEntry> DebSrcEntries;
 
-   debReleaseIndexPrivate() {}
+   metaIndex::TriState CheckValidUntil;
+   time_t ValidUntilMin;
+   time_t ValidUntilMax;
+
+   debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {}
 };
                                                                        /*}}}*/
 // ReleaseIndex::MetaIndex* - display helpers                          /*{{{*/
@@ -283,43 +287,56 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro
       return false;
    }
 
-   std::string const Label = Section.FindS("Label");
-   std::string const StrValidUntil = Section.FindS("Valid-Until");
+   bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true);
+   if (d->CheckValidUntil == metaIndex::TRI_NO)
+      CheckValidUntil = false;
+   else if (d->CheckValidUntil == metaIndex::TRI_YES)
+      CheckValidUntil = true;
 
-   // if we have a Valid-Until header in the Release file, use it as default
-   if (StrValidUntil.empty() == false)
+   if (CheckValidUntil == true)
    {
-      if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
+      std::string const Label = Section.FindS("Label");
+      std::string const 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 (ErrorText != NULL)
-           strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
-        return false;
+        if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
+        {
+           if (ErrorText != NULL)
+              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
+      time_t MaxAge = d->ValidUntilMax;
+      if (MaxAge == 0)
+      {
+        MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
+        if (Label.empty() == false)
+           MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
+      }
+      time_t MinAge = d->ValidUntilMin;
+      if (MinAge == 0)
+      {
+        MinAge = _config->FindI("Acquire::Min-ValidTime", 0);
+        if (Label.empty() == false)
+           MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge);
       }
-   }
-   // get the user settings for this archive and use what expires earlier
-   int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
-   if (Label.empty() == false)
-      MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
-   int MinAge = _config->FindI("Acquire::Min-ValidTime", 0);
-   if (Label.empty() == false)
-      MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge);
-
-   LoadedSuccessfully = TRI_YES;
-   if(MaxAge == 0 &&
-      (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file
-      return true;
 
-   if (MinAge != 0 && ValidUntil != 0) {
-      time_t const min_date = Date + MinAge;
-      if (ValidUntil < min_date)
-        ValidUntil = min_date;
-   }
-   if (MaxAge != 0) {
-      time_t const max_date = Date + MaxAge;
-      if (ValidUntil == 0 || ValidUntil > max_date)
-        ValidUntil = max_date;
+      if (MinAge != 0 && ValidUntil != 0) {
+        time_t const min_date = Date + MinAge;
+        if (ValidUntil < min_date)
+           ValidUntil = min_date;
+      }
+      if (MaxAge != 0) {
+        time_t const max_date = Date + MaxAge;
+        if (ValidUntil == 0 || ValidUntil > max_date)
+           ValidUntil = max_date;
+      }
    }
 
+   LoadedSuccessfully = TRI_YES;
    return true;
 }
                                                                        /*}}}*/
@@ -411,7 +428,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/
    return true;
 }
                                                                        /*}}}*/
-// ReleaseIndex::IsTrusted                                             /*{{{*/
+// ReleaseIndex::Set* TriState options                                 /*{{{*/
 bool debReleaseIndex::SetTrusted(TriState const pTrusted)
 {
    if (Trusted == TRI_UNSET)
@@ -421,6 +438,32 @@ bool debReleaseIndex::SetTrusted(TriState const pTrusted)
       return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str());
    return true;
 }
+bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil)
+{
+   if (d->CheckValidUntil == TRI_UNSET)
+      d->CheckValidUntil = pCheckValidUntil;
+   else if (d->CheckValidUntil != pCheckValidUntil)
+      return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str());
+   return true;
+}
+bool debReleaseIndex::SetValidUntilMin(time_t const Valid)
+{
+   if (d->ValidUntilMin == 0)
+      d->ValidUntilMin = Valid;
+   else if (d->ValidUntilMin != Valid)
+      return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str());
+   return true;
+}
+bool debReleaseIndex::SetValidUntilMax(time_t const Valid)
+{
+   if (d->ValidUntilMax == 0)
+      d->ValidUntilMax = Valid;
+   else if (d->ValidUntilMax != Valid)
+      return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str());
+   return true;
+}
+                                                                       /*}}}*/
+// ReleaseIndex::IsTrusted                                             /*{{{*/
 bool debReleaseIndex::IsTrusted() const
 {
    if (Trusted == TRI_YES)
@@ -601,6 +644,22 @@ static std::vector<std::string> parsePlusMinusOptions(std::string const &Name, /
                                                                        /*}}}*/
 class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type          /*{{{*/
 {
+   metaIndex::TriState GetTriStateOption(std::map<std::string, std::string>const &Options, char const * const name) const
+   {
+      std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
+      if (opt != Options.end())
+        return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO;
+      return metaIndex::TRI_DONTCARE;
+   }
+
+   time_t GetTimeOption(std::map<std::string, std::string>const &Options, char const * const name) const
+   {
+      std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
+      if (opt == Options.end())
+        return 0;
+      return strtoull(opt->second.c_str(), NULL, 10);
+   }
+
    protected:
 
    bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI,
@@ -641,13 +700,10 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type             /*{{{*/
            parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true))
            );
 
-      std::map<std::string, std::string>::const_iterator const trusted = Options.find("trusted");
-      if (trusted != Options.end())
-      {
-        if (Deb->SetTrusted(StringToBool(trusted->second, false) ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) == false)
-           return false;
-      }
-      else if (Deb->SetTrusted(debReleaseIndex::TRI_DONTCARE) == false)
+      if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false ||
+        Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false ||
+        Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false ||
+        Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false)
         return false;
 
       return true;
index 19fe6806ca7209b51659fc218b1dbd2f8312ba87..879eb3bfca827ab348bf85d14b8d4e8136a25d45 100644 (file)
@@ -53,6 +53,9 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
    virtual std::vector <pkgIndexFile *> *GetIndexFiles();
 
    bool SetTrusted(TriState const Trusted);
+   bool SetCheckValidUntil(TriState const Trusted);
+   bool SetValidUntilMin(time_t const Valid);
+   bool SetValidUntilMax(time_t const Valid);
 
    virtual bool IsTrusted() const;
 
index 0502f0e1dca48ac4254ccdb2e2d4b6365901c517..0d65558edcbf45a7840a752e28cdd1247c8125bd 100644 (file)
@@ -103,6 +103,9 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,    /*{{{*/
    APT_PLUSMINUS("Targets", "target");
 #undef APT_PLUSMINUS
    mapping.insert(std::make_pair("Trusted", "trusted"));
+   mapping.insert(std::make_pair("Check-Valid-Until", "check-valid-until"));
+   mapping.insert(std::make_pair("Valid-Until-Min", "valid-until-min"));
+   mapping.insert(std::make_pair("Valid-Until-Max", "valid-until-max"));
 
    for (std::map<char const * const, char const * const>::const_iterator m = mapping.begin(); m != mapping.end(); ++m)
       if (Tags.Exists(m->first))
index 5b6788ed49a41e5622c9153a85a946eaecb80bbc..b0fe390df848907238c0e13b3194addb9b8e79d5 100644 (file)
      </varlistentry>
 
      <varlistentry><term><option>--allow-unauthenticated</option></term>
-     <listitem><para>Ignore if packages can't be authenticated and don't prompt about it.
-     This is useful for tools like pbuilder.
-     Configuration Item: <literal>APT::Get::AllowUnauthenticated</literal>.</para></listitem>
+     <listitem><para>Ignore if packages can't be authenticated and don't prompt
+          about it.  This can be useful while working with local repositories,
+          but is a huge security risk if data authenticity isn't ensured in
+          another way by the user itself.  The usage of the
+          <option>Trusted</option> option for &sources-list; entries should
+          usually be preferred over this global override.  Configuration Item:
+          <literal>APT::Get::AllowUnauthenticated</literal>.</para></listitem>
      </varlistentry>
 
      <varlistentry><term><option>--no-allow-insecure-repositories</option></term>
index 7d5f7e9b38ae55a6f64efe2b36e4ce40f132f2d9..103d0622c0a569f92567412e25a712219c78298b 100644 (file)
@@ -301,6 +301,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      <literal>Valid-Until</literal> header, but if they don't or a
      stricter value is desired the <literal>Max-ValidTime</literal>
      option below can be used.
+     The <option>Check-Valid-Until</option> option of &sources-list; entries should be
+     preferred to disable the check selectively instead of using this global override.
      </para></listitem>
      </varlistentry>
 
@@ -312,7 +314,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
         the earlier date of the two is used as the expiration date.
         The default value is <literal>0</literal> which stands for "valid forever".
         Archive specific settings can be made by appending the label of the archive
-        to the option name.
+        to the option name. Preferably, the same can be achieved for specific
+        &sources-list; entries by using the <option>Valid-Until-Max</option> option there.
         </para></listitem>
      </varlistentry>
 
@@ -324,7 +327,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
         frequently updated archive with a <literal>Valid-Until</literal> header
         instead of completely disabling the expiration date checking.
         Archive specific settings can and should be used by appending the label of
-        the archive to the option name.
+        the archive to the option name. Preferably, the same can be achieved for specific
+        &sources-list; entries by using the <option>Valid-Until-Min</option> option there.
         </para></listitem>
      </varlistentry>
 
index f87dcda23489f98098167dddeda197d66ef230f4..aded8ecefcf7adefbf1743a1abd5c452dc4e78c3 100644 (file)
@@ -202,26 +202,26 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [.
        APT versions.
 
        <itemizedlist>
-         <listitem><para><literal>Architectures</literal>
-               (<literal>arch</literal>) is a multivalue option defining for
+         <listitem><para><option>Architectures</option>
+               (<option>arch</option>) is a multivalue option defining for
                which architectures information should be downloaded. If this
                option isn't set the default is all architectures as defined by
-               the <literal>APT::Architectures</literal> config option.
+               the <option>APT::Architectures</option> config option.
          </para></listitem>
 
-         <listitem><para><literal>Languages</literal>
-               (<literal>lang</literal>) is a multivalue option defining for
+         <listitem><para><option>Languages</option>
+               (<option>lang</option>) is a multivalue option defining for
                which languages information like translated package
                descriptions should be downloaded.  If this option isn't set
                the default is all languages as defined by the
-               <literal>Acquire::Languages</literal> config option.
+               <option>Acquire::Languages</option> config option.
          </para></listitem>
 
-         <listitem><para><literal>Targets</literal>
-               (<literal>target</literal>) is a multivalue option defining
+         <listitem><para><option>Targets</option>
+               (<option>target</option>) is a multivalue option defining
                which download targets apt will try to acquire from this
                source. If not specified, the default set is defined by the
-               <literal>APT::Acquire::Targets</literal> configuration scope.
+               <option>APT::Acquire::Targets</option> configuration scope.
          </para></listitem>
        </itemizedlist>
 
@@ -232,7 +232,7 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [.
        anomalies.
 
        <itemizedlist>
-         <listitem><para><literal>Trusted</literal> (<literal>trusted</literal>)
+         <listitem><para><option>Trusted</option> (<option>trusted</option>)
                is a tri-state value which defaults to APT deciding if a source
                is considered trusted or if warnings should be raised before e.g.
                packages are installed from this source. This option can be used
@@ -245,6 +245,41 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [.
                as untrusted even if the authentication checks passed successfully.
                The default value can't be set explicitly.
          </para></listitem>
+
+         <listitem><para><option>Check-Valid-Until</option> (<option>check-valid-until</option>)
+               is a yes/no value which controls if APT should try to detect
+               replay attacks. A repository creator can declare until then the
+               data provided in the repository should be considered valid and
+               if this time is reached, but no new data is provided the data
+               is considered expired and an error is raised.  Beside
+               increasing security as a malicious attacker can't sent old data
+               forever denying a user to be able to upgrade to a new version,
+               this also helps users identify mirrors which are no longer
+               updated. Some repositories like historic archives aren't
+               updated anymore by design through, so this check can be
+               disabled by setting this option to <literal>no</literal>.
+               Defaults to the value of configuration option
+               <option>Acquire::Check-Valid-Until</option> which itself
+               defaults to <literal>yes</literal>.
+         </para></listitem>
+
+         <listitem><para><option>Valid-Until-Min</option>
+               (<option>check-valid-min</option>) and
+               <option>Valid-Until-Max</option>
+               (<option>valid-until-max</option>) can be used to raise or
+               lower the time period in seconds in which the data from this
+               repository is considered valid. -Max can be especially useful
+               if the repository provides no Valid-Until field on its Release
+               file to set your own value, while -Min can be used to increase
+               the valid time on seldomly updated (local) mirrors of a more
+               frequently updated but less accessible archive (which is in the
+               sources.list as well) instead of disabling the check entirely.
+               Default to the value of the configuration options
+               <option>Acquire::Min-ValidTime</option> and
+               <option>Acquire::Max-ValidTime</option> which are both unset by
+               default.
+         </para></listitem>
+
        </itemizedlist>
 
     </para>
index e000abf5d3ebfc44b453dc14580000f652cb9fcf..43574ec3e7d919d65e20ee25fca7dd11f4767272 100755 (executable)
@@ -46,3 +46,12 @@ runtest 'accepted' 'good Min-Valid (bad Until, good Max-Valid) <' 'now - 7 days'
 runtest 'rejected' 'bad Max-Valid (bad Until, good Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=2419200
 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) <' 'now - 7 days' 'now - 2 days' -o Acquire::Min-ValidTime=12096 -o Acquire::Max-ValidTime=241920
 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=241920
+
+sed -i -e 's#\(deb\(-src\)\?\) #\1 [check-valid-until=no] #' rootdir/etc/apt/sources.list.d/*
+runtest 'accepted' 'bad Until but overriden by sources option' 'now - 7 days' 'now - 4 days'
+
+sed -i -e 's#\(deb\(-src\)\?\) \[check-valid-until=no\] #\1 [valid-until-max=86400] #' rootdir/etc/apt/sources.list.d/*
+runtest 'rejected' 'bad Max-Valid (good Until) via sources option' 'now - 7 days' 'now + 4 days'
+
+sed -i -e 's#\(deb\(-src\)\?\) \[valid-until-max=86400\] #\1 [valid-until-min=1209600] #' rootdir/etc/apt/sources.list.d/*
+runtest 'accepted' 'good Min-Valid (bad Until) via sources option' 'now - 7 days' 'now - 4 days'