Commit d03b947b authored by David Kalnischkies's avatar David Kalnischkies

add insecure (and weak) allow-options for sources.list

Weak had no dedicated option before and Insecure and Downgrade were both
global options, which given the effect they all have on security is
rather bad. Setting them for individual repositories only isn't great
but at least slightly better and also more consistent with other
settings for repositories.
parent 5da51e0e
......@@ -175,7 +175,7 @@ static void ReportMirrorFailureToCentral(pkgAcquire::Item const &I, std::string
}
/*}}}*/
static bool MessageInsecureRepository(bool const isError, char const * const msg, std::string const &repo)/*{{{*/
static APT_NONNULL(2) bool MessageInsecureRepository(bool const isError, char const * const msg, std::string const &repo)/*{{{*/
{
std::string m;
strprintf(m, msg, repo.c_str());
......@@ -195,7 +195,28 @@ static bool MessageInsecureRepository(bool const isError, char const * const msg
/*}}}*/
// AllowInsecureRepositories /*{{{*/
enum class InsecureType { UNSIGNED, WEAK, NORELEASE };
static bool APT_NONNULL(3, 4, 5) AllowInsecureRepositories(InsecureType msg, std::string const &repo,
static bool TargetIsAllowedToBe(IndexTarget const &Target, InsecureType const type)
{
if (_config->FindB("Acquire::AllowInsecureRepositories"))
return true;
if (Target.OptionBool(IndexTarget::ALLOW_INSECURE))
return true;
switch (type)
{
case InsecureType::UNSIGNED: break;
case InsecureType::NORELEASE: break;
case InsecureType::WEAK:
if (_config->FindB("Acquire::AllowWeakRepositories"))
return true;
if (Target.OptionBool(IndexTarget::ALLOW_WEAK))
return true;
break;
}
return false;
}
static bool APT_NONNULL(3, 4, 5) AllowInsecureRepositories(InsecureType const msg, std::string const &repo,
metaIndex const * const MetaIndexParser, pkgAcqMetaClearSig * const TransactionManager, pkgAcquire::Item * const I)
{
// we skip weak downgrades as its unlikely that a repository gets really weaker –
......@@ -213,7 +234,8 @@ static bool APT_NONNULL(3, 4, 5) AllowInsecureRepositories(InsecureType msg, std
case InsecureType::NORELEASE: msgstr = _("The repository '%s' does no longer have a Release file."); break;
case InsecureType::WEAK: /* unreachable */ break;
}
if (_config->FindB("Acquire::AllowDowngradeToInsecureRepositories"))
if (_config->FindB("Acquire::AllowDowngradeToInsecureRepositories") ||
TransactionManager->Target.OptionBool(IndexTarget::ALLOW_DOWNGRADE_TO_INSECURE))
{
// meh, the users wants to take risks (we still mark the packages
// from this repository as unauthenticated)
......@@ -241,7 +263,7 @@ static bool APT_NONNULL(3, 4, 5) AllowInsecureRepositories(InsecureType msg, std
case InsecureType::WEAK: msgstr = _("The repository '%s' provides only weak security information."); break;
}
if (_config->FindB("Acquire::AllowInsecureRepositories") == true)
if (TargetIsAllowedToBe(TransactionManager->Target, msg) == true)
{
MessageInsecureRepository(false, msgstr, repo);
return true;
......@@ -277,7 +299,20 @@ APT_CONST bool pkgAcqTransactionItem::HashesRequired() const
we can at least trust them for integrity of the download itself.
Only repositories without a Release file can (obviously) not have
hashes – and they are very uncommon and strongly discouraged */
return TransactionManager->MetaIndexParser->GetLoadedSuccessfully() == metaIndex::TRI_YES;
if (TransactionManager->MetaIndexParser->GetLoadedSuccessfully() != metaIndex::TRI_YES)
return false;
if (TargetIsAllowedToBe(Target, InsecureType::WEAK))
{
/* If we allow weak hashes, we check that we have some (weak) and then
declare hashes not needed. That will tip us in the right direction
as if hashes exist, they will be used, even if not required */
auto const hsl = GetExpectedHashes();
if (hsl.usable())
return true;
if (hsl.empty() == false)
return false;
}
return true;
}
HashStringList pkgAcqTransactionItem::GetExpectedHashes() const
{
......@@ -1333,7 +1368,7 @@ void pkgAcqMetaClearSig::QueueIndexes(bool const verify) /*{{{*/
auto const hashes = GetExpectedHashesFor(Target.MetaKey);
if (hashes.empty() == false)
{
if (hashes.usable() == false)
if (hashes.usable() == false && TargetIsAllowedToBe(TransactionManager->Target, InsecureType::WEAK) == false)
{
new CleanupItem(Owner, TransactionManager, Target);
_error->Warning(_("Skipping acquire of configured file '%s' as repository '%s' provides only weak security information for it"),
......@@ -1525,8 +1560,7 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/
IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget,
metaIndex * const MetaIndexParser) :
pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget),
d(NULL), ClearsignedTarget(ClearsignedTarget),
DetachedDataTarget(DetachedDataTarget),
d(NULL), DetachedDataTarget(DetachedDataTarget),
MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL)
{
// index targets + (worst case:) Release/Release.gpg
......@@ -1640,7 +1674,7 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c
if(CheckStopAuthentication(this, Message))
return;
if(AllowInsecureRepositories(InsecureType::UNSIGNED, ClearsignedTarget.Description, TransactionManager->MetaIndexParser, TransactionManager, this) == true)
if(AllowInsecureRepositories(InsecureType::UNSIGNED, Target.Description, TransactionManager->MetaIndexParser, TransactionManager, this) == true)
{
Status = StatDone;
......
......@@ -368,12 +368,13 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/
{
void * const d;
protected:
IndexTarget const Target;
HashStringList GetExpectedHashesFor(std::string const &MetaKey) const;
bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE;
public:
IndexTarget const Target;
/** \brief storge name until a transaction is finished */
std::string PartialFile;
......@@ -559,8 +560,6 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem
class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex
{
void * const d;
IndexTarget const ClearsignedTarget;
IndexTarget const DetachedDataTarget;
public:
......
......@@ -378,6 +378,7 @@ bool pkgAcquire::Worker::RunMessages()
bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) ||
StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false);
auto const forcedHash = _config->Find("Acquire::ForceHash");
for (auto const Owner: ItmOwners)
{
HashStringList const ExpectedHashes = Owner->GetExpectedHashes();
......@@ -395,9 +396,10 @@ bool pkgAcquire::Worker::RunMessages()
// decide if what we got is what we expected
bool consideredOkay = false;
if (ExpectedHashes.usable())
if ((forcedHash.empty() && ExpectedHashes.empty() == false) ||
(forcedHash.empty() == false && ExpectedHashes.usable()))
{
if (ReceivedHashes.usable() == false)
if (ReceivedHashes.empty())
{
/* IMS-Hits can't be checked here as we will have uncompressed file,
but the hashes for the compressed file. What we have was good through
......@@ -410,16 +412,8 @@ bool pkgAcquire::Worker::RunMessages()
consideredOkay = false;
}
else if (Owner->HashesRequired() == true)
consideredOkay = false;
else
{
consideredOkay = true;
// even if the hashes aren't usable to declare something secure
// we can at least use them to declare it an integrity failure
if (ExpectedHashes.empty() == false && ReceivedHashes != ExpectedHashes && _config->Find("Acquire::ForceHash").empty())
consideredOkay = false;
}
consideredOkay = !Owner->HashesRequired();
if (consideredOkay == true)
consideredOkay = Owner->VerifyDone(Message, Config);
......
This diff is collapsed.
......@@ -34,8 +34,8 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
APT_HIDDEN std::string MetaIndexFile(const char *Types) const;
APT_HIDDEN std::string MetaIndexURI(const char *Type) const;
debReleaseIndex(std::string const &URI, std::string const &Dist);
debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted);
debReleaseIndex(std::string const &URI, std::string const &Dist, std::map<std::string,std::string> const &Options);
debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted, std::map<std::string,std::string> const &Options);
virtual ~debReleaseIndex();
virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE {return URI + File;};
......@@ -56,6 +56,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex
bool SetValidUntilMin(time_t const Valid);
bool SetValidUntilMax(time_t const Valid);
bool SetSignedBy(std::string const &SignedBy);
std::map<std::string, std::string> GetReleaseOptions();
virtual bool IsTrusted() const APT_OVERRIDE;
bool IsArchitectureSupported(std::string const &arch) const;
......
......@@ -550,7 +550,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
if(Debug)
cout << "Signature verify for: " << *I << endl;
metaIndex *MetaIndex = new debReleaseIndex("","");
metaIndex *MetaIndex = new debReleaseIndex("","", {});
string prefix = *I;
string const releasegpg = *I+"Release.gpg";
......
......@@ -147,6 +147,9 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
APT_CASE(SOURCESENTRY);
APT_CASE(BY_HASH);
APT_CASE(KEEPCOMPRESSEDAS);
APT_CASE(ALLOW_INSECURE);
APT_CASE(ALLOW_WEAK);
APT_CASE(ALLOW_DOWNGRADE_TO_INSECURE);
#undef APT_CASE
case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
case EXISTING_FILENAME:
......@@ -170,7 +173,7 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
/*}}}*/
bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
{
return StringToBool(Option(EnumKey));
return StringToBool(Option(EnumKey), false);
}
/*}}}*/
std::string IndexTarget::Format(std::string format) const /*{{{*/
......
......@@ -93,6 +93,9 @@ class IndexTarget /*{{{*/
KEEPCOMPRESSEDAS,
FALLBACK_OF,
IDENTIFIER,
ALLOW_INSECURE,
ALLOW_WEAK,
ALLOW_DOWNGRADE_TO_INSECURE,
};
std::string Option(OptionKeys const Key) const;
bool OptionBool(OptionKeys const Key) const;
......
......@@ -87,6 +87,7 @@ bool pkgInitConfig(Configuration &Cnf)
// Repository security
Cnf.CndSet("Acquire::AllowInsecureRepositories", false);
Cnf.CndSet("Acquire::AllowWeakRepositories", false);
Cnf.CndSet("Acquire::AllowDowngradeToInsecureRepositories", false);
// Default cdrom mount point
......
......@@ -265,6 +265,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
addArg(0,"arch-only","APT::Get::Arch-Only",0);
addArg(0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0);
addArg(0,"allow-insecure-repositories","Acquire::AllowInsecureRepositories",0);
addArg(0,"allow-weak-repositories","Acquire::AllowWeakRepositories",0);
addArg(0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean);
addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);
......
......@@ -75,7 +75,10 @@
<para>
You can force all APT clients to raise only warnings by setting the
configuration option <option>Acquire::AllowInsecureRepositories</option> to
<literal>true</literal>. Note that this option will eventually be removed.
<literal>true</literal>. Individual repositories can also be allowed to be insecure
via the &sources-list; option <literal>allow-insecure=yes</literal>.
Note that insecure repositories are strongly discouraged and all options
to force apt to continue supporting them will eventually be removed.
Users also have the <option>Trusted</option> option available to disable
even the warnings, but be sure to understand the implications as detailed in
&sources-list;.
......@@ -87,7 +90,8 @@
irrespective of the option to allow or forbid usage of insecure repositories.
The error can be overcome by additionally setting
<option>Acquire::AllowDowngradeToInsecureRepositories</option>
to <literal>true</literal>.
to <literal>true</literal> or for Individual repositories with the &sources-list;
option <literal>allow-downgrade-to-insecure=yes</literal>.
</para>
<para>
......
......@@ -653,7 +653,17 @@ APT::Compressor::rev {
Allow update operations to load data files from
repositories without sufficient security information.
The default value is "<literal>false</literal>".
Concept and implications of this are detailed in &apt-secure;.
Concept, implications as well as alternatives are detailed in &apt-secure;.
</para></listitem>
</varlistentry>
<varlistentry><term><option>AllowWeakRepositories</option></term>
<listitem><para>
Allow update operations to load data files from
repositories which provide security information, but these
are deemed no longer cryptographically strong enough.
The default value is "<literal>false</literal>".
Concept, implications as well as alternatives are detailed in &apt-secure;.
</para></listitem>
</varlistentry>
......@@ -664,9 +674,7 @@ APT::Compressor::rev {
for a previously trusted repository apt will refuse the update. This
option can be used to override this protection. You almost certainly
never want to enable this. The default is <literal>false</literal>.
Note that apt will still consider packages from this source
untrusted and warns about them if you try to install them.
Concept, implications as well as alternatives are detailed in &apt-secure;.
</para></listitem>
</varlistentry>
......
......@@ -269,6 +269,14 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [.
anomalies.
<itemizedlist>
<listitem><para><option>Allow-Insecure</option> (<option>allow-insecure</option>),
<option>Allow-Weak</option> (<option>allow-weak</option>) and
<option>Allow-Downgrade-To-Insecure</option> (<option>allow-downgrade-to-insecure</option>)
are boolean values which all default to <literal>no</literal>.
If set to <literal>yes</literal> they circumvent parts of &apt-secure;
and should therefore not be used lightly!
</para></listitem>
<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.
......
......@@ -93,10 +93,16 @@ test_from_inrelease_to_unsigned_with_override()
find "$APTARCHIVE" -name '*Packages*' -exec touch -d '+2 hours' {} \;
# and ensure we can update to it (with enough force)
testfailure apt update
testfailure aptget update
testfailure aptget update --allow-insecure-repositories
testwarning aptget update --allow-insecure-repositories \
-o Acquire::AllowDowngradeToInsecureRepositories=1 -o Debug::pkgAcquire::Worker=1 -o Debug::pkgAcquire::Auth=1
testfailure aptget update --no-allow-insecure-repositories
sed -i 's#^deb\(-src\)\? #deb\1 [allow-downgrade-to-insecure=yes] #' rootdir/etc/apt/sources.list.d/*
testfailure aptget update --no-allow-insecure-repositories
testfailure apt update
testwarning apt update --allow-insecure-repositories \
-o Debug::pkgAcquire::Worker=1 -o Debug::pkgAcquire::Auth=1
sed -i 's#^deb\(-src\)\? \[allow-downgrade-to-insecure=yes\] #deb\1 #' rootdir/etc/apt/sources.list.d/*
# but that the individual packages are still considered untrusted
testfailureequal "WARNING: The following packages cannot be authenticated!
evil
......
......@@ -58,6 +58,16 @@ N: See apt-secure(8) manpage for repository creation and user configuration deta
testbadpkg 'foo'
fi
msgmsg "$TYPE contains only weak hashes, but source allows weak"
sed -i 's#^deb\(-src\)\? #deb\1 [allow-weak=yes] #' rootdir/etc/apt/sources.list.d/*
genericprepare
testwarningmsg "W: No Hash entry in Release file ${MANGLED} which is considered strong enough for security purposes
W: The repository 'file:${APTARCHIVE} unstable $(basename "$FILENAME")' provides only weak security information.
N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use.
N: See apt-secure(8) manpage for repository creation and user configuration details." apt update "$@"
testbadpkg 'foo'
sed -i 's#^deb\(-src\)\? \[allow-weak=yes\] #deb\1 #' rootdir/etc/apt/sources.list.d/*
msgmsg "$TYPE contains no hashes"
generatereleasefiles
sed -i -e '/^ / d' -e '/^MD5Sum:/ d' "$APTARCHIVE/dists/unstable/Release"
......@@ -85,10 +95,15 @@ N: See apt-secure(8) manpage for repository creation and user configuration deta
sed -i '/^ [0-9a-fA-Z]\{64\} .*Sources$/d' "$APTARCHIVE/dists/unstable/Release"
signreleasefiles
preparetest
# trust is a repository property, so individual files can't be insecure
testwarningmsg "W: Skipping acquire of configured file 'main/source/Sources' as repository 'file:${APTARCHIVE} unstable InRelease' provides only weak security information for it" apt update "$@"
if [ -z "$1" ]; then
testwarningmsg "W: Skipping acquire of configured file 'main/source/Sources' as repository 'file:${APTARCHIVE} unstable InRelease' provides only weak security information for it" apt update
testnosrcpackage foo
else
rm -f rootdir/var/lib/apt/lists/partial/*
testsuccess apt update "$@"
testnotempty apt showsrc foo
fi
testsuccess apt show foo
testnosrcpackage foo
}
genericprepare() {
......@@ -107,14 +122,14 @@ preparetest() {
genericprepare
}
testrun 'InRelease' "${APTARCHIVE}/dists/unstable/InRelease"
testrun 'InRelease' "${APTARCHIVE}/dists/unstable/InRelease" --allow-insecure-repositories -o APT::Get::List-Cleanup=0
testrun 'InRelease' "${APTARCHIVE}/dists/unstable/InRelease" --allow-weak-repositories -o APT::Get::List-Cleanup=0
preparetest() {
rm -f "${APTARCHIVE}/dists/unstable/InRelease"
genericprepare
}
testrun 'Release+Release.gpg' "${APTARCHIVE}/dists/unstable/Release"
testrun 'Release+Release.gpg' "${APTARCHIVE}/dists/unstable/Release" --allow-insecure-repositories -o APT::Get::List-Cleanup=0
testrun 'Release+Release.gpg' "${APTARCHIVE}/dists/unstable/Release" --allow-weak-repositories -o APT::Get::List-Cleanup=0
preparetest() {
rm -f "${APTARCHIVE}/dists/unstable/InRelease" "${APTARCHIVE}/dists/unstable/Release.gpg"
......@@ -128,7 +143,7 @@ generatereleasefiles 'now - 7 days'
signreleasefiles
testfailure apt update
testnopkg 'foo'
testwarning apt update --allow-insecure-repositories
testwarning apt update --allow-weak-repositories
testbadpkg 'foo'
confighashes 'MD5' 'SHA256'
......@@ -153,7 +168,7 @@ testnopkg foo3
testnotempty find rootdir/var/lib/apt/lists -maxdepth 1 -name '*InRelease' -o -name '*Release.gpg'
testnotempty apt show foo2
testnotempty apt showsrc foo2
testwarning apt update --allow-insecure-repositories
testwarning apt update --allow-weak-repositories
testnopkg foo2
testbadpkg foo3
......
......@@ -414,6 +414,11 @@ runfailure() {
testnopackage 'apt'
testwarning aptget update --allow-insecure-repositories -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::gpgv=1
failaptold
rm -rf rootdir/var/lib/apt/lists
sed -i 's#^deb\(-src\)\? #deb\1 [allow-insecure=yes] #' rootdir/etc/apt/sources.list.d/*
testwarning aptget update --no-allow-insecure-repositories -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::gpgv=1
failaptold
sed -i 's#^deb\(-src\)\? \[allow-insecure=yes\] #deb\1 #' rootdir/etc/apt/sources.list.d/*
msgmsg 'Cold archive signed by' 'Marvin Paranoid'
prepare "${PKGFILE}"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment