When the mirror method handles a URI Acquire from apt for a mirror list
it already has, it calls the `RedirectItem` function directly. This
function assumes that the item being redirected is at the head of the
queue, and as such calls `Dequeue` to remove it from the queue. This
resulted in incorrect items being removed from the queue when this
branch is taken and the queue was already non-empty, as the item to be
handled in this case is actually the last item in the queue.
This changes `RedirectItem` to properly remove the item passed to it
instead of calling Dequeue.
Change the logic to use "Valid" instead of "Good" to determine
whether we need to fallback and if fallback was successful. That
means that if you have an expired key in trusted.gpg.d, and a
non-expired in trusted.gpg, verification will now fail directly
with the expired key in trusted.gpg.d and not try to fallback.
Likewise, if the key in trusted.gpg is expired, this will now
also be reported correctly again, instead of producing an error
message that the key could not be found.
If a repository is signed with multiple keys, apt 2.4.0 would
ignore the fallback result if some keys were still missing,
causing signature verification to fail.
Rework the logic such that when checking if fallback was "succesful",
missing keys are ignored - it only matters if we managed to verify
one key now, whether good or bad.
Likewise, simplify the logic when to do the fallback:
If there was a bad signature in trusted.gpg.d, do NOT fallback at all
- this is a minor security issue, as a key in trusted.gpg.d could
fail silently with a bad signature, and then a key in trusted.gpg
might allow the signature to succeed (as trusted.gpg.d key is then
missing).
Only fallback if we are missing a good signature, and there are
keys we have not yet checked.
Extend the Signed-By field to handle embedded public key blocks,
this allows shipping self-contained .sources files, making it
substantially easier to provide third party repositories.
Debian buster (oldstable) ships 6.1 while bullseye (stable) ships 6.5
and so the later is 'fixed'. Upstream declares 6.0 still as supported.
It might be still a while we encounter "bad" versions in the wild, so
if we can detect and work around the issue at runtime automatically we
can save some users from running into "persistent" partial files.
References: https://varnish-cache.org/docs/6.4/whats-new/changes-6.4.html#changes-in-behavior
apt makes heavy usage of HTTP1.1 features including Range and If-Range.
Sadly it is not obvious if the involved server(s) (and proxies) actually
support them all. The Acquire::http::AllowRange option defaults to true
as before, but now a user can disable Range usage if it is known that
the involved server is not dealing with such requests correctly.
The settings used for unwrapping TLS connections depend on the access
and hostname we connect to more than what we eventually unwrap. The
bugreport mentions CaInfo, but all other https-settings should also
apply (regardless of generic or hostname specific) to an https proxy,
even if the connection we proxy through it is http-only.
Closes: #990555
Set haveContent to HaveContent::FALSE when Content-Length is 0,
and change remaining code to only set it to TRUE if it has not
been set so far.
Closes: #990281
The maximum request size is accidentally set to any sized file,
so if an unsized file is present, and it turns out to be larger
than the maximum size we set, we'd error out when checking if
its size is smaller than the maximum request size.
LP: #1921626
There isn't a lot of sense in working on empty patches as they change
nothing (quite literally), but they can be the result of merging
multiple patches and so to not require our users to specifically detect
and remove them, we can be nice and just ignore them instead of erroring
out.
We use the code in error messages, so at least for that edgecase we
should ensure that it has sensible content. Note that the acquire
system aborts on non-sensible message content in SendMessage, so you
can't really exploit this.
varg API is a nightmare as the symbols seems different on ever other
arch, but more importantly SendMessage does a few checks on the content
of the message and it is all outputted via C++ iostreams and not mixed
in FILE* which is handy for overriding the streams.
The rest of our code uses return-code errors and it isn't that nice to
crash the rred method on bad patches anyway, so we move to properly
reporting errors in our usual way which incidently also helps writing
a fuzzer for it.
This is not really security relevant though as the patches passed hash
verification while they were downloaded, so an attacker has to overtake a
trusted repository first which gives plenty better options of attack.
The "last connection" cache is currently being stored and looked up on
the combination of (LastHost, LastPort). However, these are not what the
arguments to getaddrinfo() were on the first try: the call is to
getaddrinfo(Host, ServiceNameOrPort, ...), i.e. with the port *or if 0,
the service name* (e.g. http).
Effectively this means that the connection cache lookup for:
https://example.org/... i.e. Host = example.org, Port = 0, Service = http
would end up matching the "last" connection of (if existed):
https://example.org/... i.e. Host = example.org, Port = 0, Service = https
...and thus performing a TLS request over an (unrelated) port 80
connection. Therefore, an HTTP request, followed up by an (unrelated)
HTTPS request to the same server, would always fail.
Address this by using as the cache key the ServiceNameOrPort, rather
than Port.
Convert the fixed-size (300) char array "ServStr" to a std::string, and
simplify the code by removing snprintfs in the process.
While at it, rename to the more aptly named "ServiceNameOrPort" and
update the comment to reflect what this variable is meant to be.
ServerState->Comp() is used by the HTTP methods main loop to check
whether a connection can be reused, or whether a new one is needed.
Unfortunately, the currently implementation only compares the Host and
Port between the ServerState's internal URI, with a new URI. However
these are URIs, and therefore Port is 0 when a URI port is not
specificied, i.e. in the most common configurations.
As a result, a ServerState for http://example.org/... will be reused for
URIs of the form https://example.org/..., as both Host (example.org) and
Port (0) match. In turn this means that GET requests will happen over
port 80, in cleartext, even for those https URLs(!).
URI Acquires for an http URI and subsequently for an https one, in the
same aptmethod session, do not typically happen with apt as the
frontend, as apt opens a new pipe with the "https" aptmethod binary
(nowadays a symlink to http), which is why this hasn't been a problem in
practice and has eluded detection so far. It does happen in the wild
with other frontends (e.g. reprepro), plus is legitimately an odd and
surprising behavior on apt's end.
Therefore add a comparison for the URI's "Access" (= the scheme) in
addition to Host and Port, to ensure that we're not reusing the same
state for multiple different schemes.
Every method opts in to getting the encoded URI passed along while
keeping compat in case we are operated by an older acquire system.
Effectively this is just a change for the http-based methods as the
others just decode the URI as they work with files directly.