Skip to content

Commit

Permalink
resolved: authenticate bypass queries
Browse files Browse the repository at this point in the history
Following 13e15da, resolved does not forward the AD bit for bypass
queries, but resolved also didn't do it's own validation, making these
replies appear to never be authentic. We should enable validation for
bypass queries.

Let's disable our own validation when processing a +cd query, and also
ensure that it skips the cache so that we don't accidentally fail to
return inauthentic replies from upstream.

Previously, when we had a bypass transaction without cd, a cached,
authenticated, reply with cd could be served, leaving the cd bit
erroneously set in the reply. Only reply with a CD bit if the client
requested it.

Fixes: 13e15da (resolved: clear the AD bit for bypass packets)
(cherry picked from commit 008f23b)
  • Loading branch information
rpigott authored and bluca committed Nov 13, 2024
1 parent c414ca8 commit 8fac6f2
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/resolve/resolved-dns-packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ static inline uint8_t* DNS_PACKET_DATA(const DnsPacket *p) {
#define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1)
#define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1)

#define DNS_PACKET_FLAG_CD (UINT16_C(1) << 4)
#define DNS_PACKET_FLAG_AD (UINT16_C(1) << 5)
#define DNS_PACKET_FLAG_TC (UINT16_C(1) << 9)

Expand Down
13 changes: 10 additions & 3 deletions src/resolve/resolved-dns-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ static int dns_stub_patch_bypass_reply_packet(
DnsPacket **ret, /* Where to place the patched packet */
DnsPacket *original, /* The packet to patch */
DnsPacket *request, /* The packet the patched packet shall look like a reply to */
bool validated,
bool authenticated) {
_cleanup_(dns_packet_unrefp) DnsPacket *c = NULL;
int r;
Expand Down Expand Up @@ -726,9 +727,14 @@ static int dns_stub_patch_bypass_reply_packet(
DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) | DNS_PACKET_FLAG_TC);
}

/* Patch the cd bit to reflect the state of validation: set when both we and the upstream
* resolver have checking disabled. */
DNS_PACKET_HEADER(c)->flags = htobe16(UPDATE_FLAG(be16toh(DNS_PACKET_HEADER(c)->flags),
DNS_PACKET_FLAG_CD, DNS_PACKET_CD(original) && !validated));

/* Ensure we don't pass along an untrusted ad flag for bypass packets */
if (!authenticated)
DNS_PACKET_HEADER(c)->flags = htobe16(be16toh(DNS_PACKET_HEADER(c)->flags) & ~DNS_PACKET_FLAG_AD);
DNS_PACKET_HEADER(c)->flags = htobe16(UPDATE_FLAG(be16toh(DNS_PACKET_HEADER(c)->flags),
DNS_PACKET_FLAG_AD, authenticated));

*ret = TAKE_PTR(c);
return 0;
Expand All @@ -751,6 +757,7 @@ static void dns_stub_query_complete(DnsQuery *query) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;

r = dns_stub_patch_bypass_reply_packet(&reply, q->answer_full_packet, q->request_packet,
/* validated = */ !FLAGS_SET(q->flags, SD_RESOLVED_NO_VALIDATE),
FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED));
if (r < 0)
log_debug_errno(r, "Failed to patch bypass reply packet: %m");
Expand Down Expand Up @@ -982,7 +989,7 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
protocol_flags|
SD_RESOLVED_NO_CNAME|
SD_RESOLVED_NO_SEARCH|
SD_RESOLVED_NO_VALIDATE|
(DNS_PACKET_CD(p) ? SD_RESOLVED_NO_VALIDATE | SD_RESOLVED_NO_CACHE : 0)|
SD_RESOLVED_REQUIRE_PRIMARY|
SD_RESOLVED_CLAMP_TTL|
SD_RESOLVED_RELAX_SINGLE_LABEL);
Expand Down

0 comments on commit 8fac6f2

Please sign in to comment.