mirror of
https://github.com/systemd/systemd.git
synced 2025-02-10 17:57:40 +03:00
Merge pull request #18617 from poettering/resolved-confidential
resolved: tell clients which source a response is from, and whether it was never sent via unencrypted transports
This commit is contained in:
commit
ff05157f82
@ -155,9 +155,22 @@ static void print_source(uint64_t flags, usec_t rtt) {
|
||||
assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
|
||||
|
||||
printf(" in %s.%s\n"
|
||||
"%s-- Data is authenticated: %s%s\n",
|
||||
"%s-- Data is authenticated: %s; Data was acquired via local or encrypted transport: %s%s\n",
|
||||
rtt_str, ansi_normal(),
|
||||
ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal());
|
||||
ansi_grey(),
|
||||
yes_no(flags & SD_RESOLVED_AUTHENTICATED),
|
||||
yes_no(flags & SD_RESOLVED_CONFIDENTIAL),
|
||||
ansi_normal());
|
||||
|
||||
if ((flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC)) != 0)
|
||||
printf("%s-- Data from:%s%s%s%s%s%s\n",
|
||||
ansi_grey(),
|
||||
FLAGS_SET(flags, SD_RESOLVED_SYNTHETIC) ? " synthetic" : "",
|
||||
FLAGS_SET(flags, SD_RESOLVED_FROM_CACHE) ? " cache" : "",
|
||||
FLAGS_SET(flags, SD_RESOLVED_FROM_ZONE) ? " zone" : "",
|
||||
FLAGS_SET(flags, SD_RESOLVED_FROM_TRUST_ANCHOR) ? " trust-anchor" : "",
|
||||
FLAGS_SET(flags, SD_RESOLVED_FROM_NETWORK) ? " network" : "",
|
||||
ansi_normal());
|
||||
}
|
||||
|
||||
static void print_ifindex_comment(int printed_so_far, int ifindex) {
|
||||
|
@ -252,7 +252,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
|
||||
r = sd_bus_message_append(
|
||||
reply, "st",
|
||||
normalized,
|
||||
SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
|
||||
dns_query_reply_flags_make(q));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -367,7 +367,8 @@ static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "st", canonical,
|
||||
SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
|
||||
SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true) |
|
||||
SD_RESOLVED_SYNTHETIC);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -510,7 +511,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
|
||||
r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -672,7 +673,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
|
||||
r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -1048,7 +1049,7 @@ static void resolve_service_all_complete(DnsQuery *q) {
|
||||
reply,
|
||||
"ssst",
|
||||
name, type, domain,
|
||||
SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
|
||||
dns_query_reply_flags_make(q));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
|
@ -52,8 +52,28 @@
|
||||
/* Input: If reply is answered from cache, the TTLs will be adjusted by age of cache entry */
|
||||
#define SD_RESOLVED_CLAMP_TTL (UINT64_C(1) << 17)
|
||||
|
||||
/* Output: Result was only sent via encrypted channels, or never left this system */
|
||||
#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
|
||||
|
||||
/* Output: Result was (at least partially) synthesized locally */
|
||||
#define SD_RESOLVED_SYNTHETIC (UINT64_C(1) << 19)
|
||||
|
||||
/* Output: Result was (at least partially) answered from cache */
|
||||
#define SD_RESOLVED_FROM_CACHE (UINT64_C(1) << 20)
|
||||
|
||||
/* Output: Result was (at least partially) answered from local zone */
|
||||
#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) << 21)
|
||||
|
||||
/* Output: Result was (at least partially) answered from trust anchor */
|
||||
#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) << 22)
|
||||
|
||||
/* Output: Result was (at least partially) answered from network */
|
||||
#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
|
||||
|
||||
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
|
||||
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
|
||||
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
|
||||
|
||||
#define SD_RESOLVED_FROM_MASK (SD_RESOLVED_FROM_CACHE|SD_RESOLVED_FROM_ZONE|SD_RESOLVED_FROM_TRUST_ANCHOR|SD_RESOLVED_FROM_NETWORK)
|
||||
|
||||
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
|
||||
|
@ -22,6 +22,8 @@
|
||||
* now) */
|
||||
#define CACHE_TTL_STRANGE_RCODE_USEC (10 * USEC_PER_SEC)
|
||||
|
||||
#define CACHEABLE_QUERY_FLAGS (SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL)
|
||||
|
||||
typedef enum DnsCacheItemType DnsCacheItemType;
|
||||
typedef struct DnsCacheItem DnsCacheItem;
|
||||
|
||||
@ -41,8 +43,8 @@ struct DnsCacheItem {
|
||||
int rcode;
|
||||
|
||||
usec_t until;
|
||||
bool authenticated:1;
|
||||
bool shared_owner:1;
|
||||
uint64_t query_flags; /* SD_RESOLVED_AUTHENTICATED and/or SD_RESOLVED_CONFIDENTIAL */
|
||||
DnssecResult dnssec_result;
|
||||
|
||||
int ifindex;
|
||||
@ -353,7 +355,7 @@ static void dns_cache_item_update_positive(
|
||||
DnsResourceRecord *rr,
|
||||
DnsAnswer *answer,
|
||||
DnsPacket *full_packet,
|
||||
bool authenticated,
|
||||
uint64_t query_flags,
|
||||
bool shared_owner,
|
||||
DnssecResult dnssec_result,
|
||||
usec_t timestamp,
|
||||
@ -390,7 +392,7 @@ static void dns_cache_item_update_positive(
|
||||
i->full_packet = full_packet;
|
||||
|
||||
i->until = calculate_until(rr, UINT32_MAX, timestamp, false);
|
||||
i->authenticated = authenticated;
|
||||
i->query_flags = query_flags & CACHEABLE_QUERY_FLAGS;
|
||||
i->shared_owner = shared_owner;
|
||||
i->dnssec_result = dnssec_result;
|
||||
|
||||
@ -407,7 +409,7 @@ static int dns_cache_put_positive(
|
||||
DnsResourceRecord *rr,
|
||||
DnsAnswer *answer,
|
||||
DnsPacket *full_packet,
|
||||
bool authenticated,
|
||||
uint64_t query_flags,
|
||||
bool shared_owner,
|
||||
DnssecResult dnssec_result,
|
||||
usec_t timestamp,
|
||||
@ -448,7 +450,7 @@ static int dns_cache_put_positive(
|
||||
rr,
|
||||
answer,
|
||||
full_packet,
|
||||
authenticated,
|
||||
query_flags,
|
||||
shared_owner,
|
||||
dnssec_result,
|
||||
timestamp,
|
||||
@ -476,7 +478,7 @@ static int dns_cache_put_positive(
|
||||
.answer = dns_answer_ref(answer),
|
||||
.full_packet = dns_packet_ref(full_packet),
|
||||
.until = calculate_until(rr, (uint32_t) -1, timestamp, false),
|
||||
.authenticated = authenticated,
|
||||
.query_flags = query_flags & CACHEABLE_QUERY_FLAGS,
|
||||
.shared_owner = shared_owner,
|
||||
.dnssec_result = dnssec_result,
|
||||
.ifindex = ifindex,
|
||||
@ -495,8 +497,9 @@ static int dns_cache_put_positive(
|
||||
|
||||
(void) in_addr_to_string(i->owner_family, &i->owner_address, &t);
|
||||
|
||||
log_debug("Added positive %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
|
||||
i->authenticated ? "authenticated" : "unauthenticated",
|
||||
log_debug("Added positive %s %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
|
||||
FLAGS_SET(i->query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unauthenticated",
|
||||
FLAGS_SET(i->query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential",
|
||||
i->shared_owner ? " shared" : "",
|
||||
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
|
||||
(i->until - timestamp) / USEC_PER_SEC,
|
||||
@ -515,7 +518,7 @@ static int dns_cache_put_negative(
|
||||
int rcode,
|
||||
DnsAnswer *answer,
|
||||
DnsPacket *full_packet,
|
||||
bool authenticated,
|
||||
uint64_t query_flags,
|
||||
DnssecResult dnssec_result,
|
||||
uint32_t nsec_ttl,
|
||||
usec_t timestamp,
|
||||
@ -566,7 +569,7 @@ static int dns_cache_put_negative(
|
||||
.type =
|
||||
rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA :
|
||||
rcode == DNS_RCODE_NXDOMAIN ? DNS_CACHE_NXDOMAIN : DNS_CACHE_RCODE,
|
||||
.authenticated = authenticated,
|
||||
.query_flags = query_flags & CACHEABLE_QUERY_FLAGS,
|
||||
.dnssec_result = dnssec_result,
|
||||
.owner_family = owner_family,
|
||||
.owner_address = *owner_address,
|
||||
@ -669,7 +672,7 @@ int dns_cache_put(
|
||||
int rcode,
|
||||
DnsAnswer *answer,
|
||||
DnsPacket *full_packet,
|
||||
bool authenticated,
|
||||
uint64_t query_flags,
|
||||
DnssecResult dnssec_result,
|
||||
uint32_t nsec_ttl,
|
||||
int owner_family,
|
||||
@ -761,7 +764,8 @@ int dns_cache_put(
|
||||
item->rr,
|
||||
primary ? answer : NULL,
|
||||
primary ? full_packet : NULL,
|
||||
item->flags & DNS_ANSWER_AUTHENTICATED,
|
||||
((item->flags & DNS_ANSWER_AUTHENTICATED) ? SD_RESOLVED_AUTHENTICATED : 0) |
|
||||
(query_flags & SD_RESOLVED_CONFIDENTIAL),
|
||||
item->flags & DNS_ANSWER_SHARED_OWNER,
|
||||
dnssec_result,
|
||||
timestamp,
|
||||
@ -802,7 +806,8 @@ int dns_cache_put(
|
||||
if (r > 0) {
|
||||
/* Refuse using the SOA data if it is unsigned, but the key is
|
||||
* signed */
|
||||
if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0)
|
||||
if (FLAGS_SET(query_flags, SD_RESOLVED_AUTHENTICATED) &&
|
||||
(flags & DNS_ANSWER_AUTHENTICATED) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -819,7 +824,7 @@ int dns_cache_put(
|
||||
rcode,
|
||||
answer,
|
||||
full_packet,
|
||||
authenticated,
|
||||
query_flags,
|
||||
dnssec_result,
|
||||
nsec_ttl,
|
||||
timestamp,
|
||||
@ -951,7 +956,7 @@ int dns_cache_lookup(
|
||||
int *ret_rcode,
|
||||
DnsAnswer **ret_answer,
|
||||
DnsPacket **ret_full_packet,
|
||||
bool *ret_authenticated,
|
||||
uint64_t *ret_query_flags,
|
||||
DnssecResult *ret_dnssec_result) {
|
||||
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *full_packet = NULL;
|
||||
@ -961,7 +966,7 @@ int dns_cache_lookup(
|
||||
int r;
|
||||
bool nxdomain = false;
|
||||
DnsCacheItem *j, *first, *nsec = NULL;
|
||||
bool have_authenticated = false, have_non_authenticated = false;
|
||||
bool have_authenticated = false, have_non_authenticated = false, have_confidential = false, have_non_confidential = false;
|
||||
usec_t current;
|
||||
int found_rcode = -1;
|
||||
DnssecResult dnssec_result = -1;
|
||||
@ -1013,11 +1018,16 @@ int dns_cache_lookup(
|
||||
n++;
|
||||
}
|
||||
|
||||
if (j->authenticated)
|
||||
if (FLAGS_SET(j->query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
have_authenticated = true;
|
||||
else
|
||||
have_non_authenticated = true;
|
||||
|
||||
if (FLAGS_SET(j->query_flags, SD_RESOLVED_CONFIDENTIAL))
|
||||
have_confidential = true;
|
||||
else
|
||||
have_non_confidential = true;
|
||||
|
||||
if (j->dnssec_result < 0) {
|
||||
have_dnssec_result = false; /* an entry without dnssec result? then invalidate things for good */
|
||||
dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
@ -1049,7 +1059,14 @@ int dns_cache_lookup(
|
||||
}
|
||||
|
||||
} else if (j->rr) {
|
||||
r = answer_add_clamp_ttl(&answer, j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0, NULL, query_flags, j->until, current);
|
||||
r = answer_add_clamp_ttl(&answer,
|
||||
j->rr,
|
||||
j->ifindex,
|
||||
FLAGS_SET(j->query_flags, SD_RESOLVED_AUTHENTICATED) ? DNS_ANSWER_AUTHENTICATED : 0,
|
||||
NULL,
|
||||
query_flags,
|
||||
j->until,
|
||||
current);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1072,8 +1089,8 @@ int dns_cache_lookup(
|
||||
*ret_answer = TAKE_PTR(answer);
|
||||
if (ret_full_packet)
|
||||
*ret_full_packet = TAKE_PTR(full_packet);
|
||||
if (ret_authenticated)
|
||||
*ret_authenticated = false;
|
||||
if (ret_query_flags)
|
||||
*ret_query_flags = 0;
|
||||
if (ret_dnssec_result)
|
||||
*ret_dnssec_result = dnssec_result;
|
||||
|
||||
@ -1097,8 +1114,8 @@ int dns_cache_lookup(
|
||||
*ret_answer = TAKE_PTR(answer);
|
||||
if (ret_full_packet)
|
||||
*ret_full_packet = TAKE_PTR(full_packet);
|
||||
if (ret_authenticated)
|
||||
*ret_authenticated = nsec->authenticated;
|
||||
if (ret_query_flags)
|
||||
*ret_query_flags = nsec->query_flags;
|
||||
if (ret_dnssec_result)
|
||||
*ret_dnssec_result = nsec->dnssec_result;
|
||||
|
||||
@ -1127,8 +1144,10 @@ int dns_cache_lookup(
|
||||
*ret_answer = TAKE_PTR(answer);
|
||||
if (ret_full_packet)
|
||||
*ret_full_packet = TAKE_PTR(full_packet);
|
||||
if (ret_authenticated)
|
||||
*ret_authenticated = have_authenticated && !have_non_authenticated;
|
||||
if (ret_query_flags)
|
||||
*ret_query_flags =
|
||||
((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
|
||||
((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
|
||||
if (ret_dnssec_result)
|
||||
*ret_dnssec_result = dnssec_result;
|
||||
|
||||
@ -1143,8 +1162,10 @@ int dns_cache_lookup(
|
||||
*ret_answer = TAKE_PTR(answer);
|
||||
if (ret_full_packet)
|
||||
*ret_full_packet = TAKE_PTR(full_packet);
|
||||
if (ret_authenticated)
|
||||
*ret_authenticated = have_authenticated && !have_non_authenticated;
|
||||
if (ret_query_flags)
|
||||
*ret_query_flags =
|
||||
((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
|
||||
((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
|
||||
if (ret_dnssec_result)
|
||||
*ret_dnssec_result = dnssec_result;
|
||||
|
||||
@ -1157,8 +1178,8 @@ miss:
|
||||
*ret_answer = NULL;
|
||||
if (ret_full_packet)
|
||||
*ret_full_packet = NULL;
|
||||
if (ret_authenticated)
|
||||
*ret_authenticated = false;
|
||||
if (ret_query_flags)
|
||||
*ret_query_flags = 0;
|
||||
if (ret_dnssec_result)
|
||||
*ret_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
|
||||
|
@ -30,7 +30,7 @@ int dns_cache_put(
|
||||
int rcode,
|
||||
DnsAnswer *answer,
|
||||
DnsPacket *full_packet,
|
||||
bool authenticated,
|
||||
uint64_t query_flags,
|
||||
DnssecResult dnssec_result,
|
||||
uint32_t nsec_ttl,
|
||||
int owner_family,
|
||||
@ -43,7 +43,7 @@ int dns_cache_lookup(
|
||||
int *ret_rcode,
|
||||
DnsAnswer **ret_answer,
|
||||
DnsPacket **ret_full_packet,
|
||||
bool *ret_authenticated,
|
||||
uint64_t *ret_query_flags,
|
||||
DnssecResult *ret_dnssec_result);
|
||||
|
||||
int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);
|
||||
|
@ -269,12 +269,17 @@ DnsProtocol dns_protocol_from_string(const char *s) _pure_;
|
||||
|
||||
extern const struct hash_ops dns_packet_hash_ops;
|
||||
|
||||
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
|
||||
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(
|
||||
DnsProtocol protocol,
|
||||
int family,
|
||||
bool authenticated,
|
||||
bool confidential) {
|
||||
uint64_t f;
|
||||
|
||||
/* Converts a protocol + family into a flags field as used in queries and responses */
|
||||
|
||||
f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
|
||||
f = (authenticated ? SD_RESOLVED_AUTHENTICATED : 0) |
|
||||
(confidential ? SD_RESOLVED_CONFIDENTIAL : 0);
|
||||
|
||||
switch (protocol) {
|
||||
case DNS_PROTOCOL_DNS:
|
||||
|
@ -346,7 +346,7 @@ static void dns_query_reset_answer(DnsQuery *q) {
|
||||
q->answer_rcode = 0;
|
||||
q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
q->answer_errno = 0;
|
||||
q->answer_authenticated = false;
|
||||
q->answer_query_flags = 0;
|
||||
q->answer_protocol = _DNS_PROTOCOL_INVALID;
|
||||
q->answer_family = AF_UNSPEC;
|
||||
q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain);
|
||||
@ -630,7 +630,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
|
||||
q->answer_rcode = DNS_RCODE_NXDOMAIN;
|
||||
q->answer_protocol = dns_synthesize_protocol(q->flags);
|
||||
q->answer_family = dns_synthesize_family(q->flags);
|
||||
q->answer_authenticated = true;
|
||||
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
|
||||
*state = DNS_TRANSACTION_RCODE_FAILURE;
|
||||
|
||||
return 0;
|
||||
@ -644,7 +644,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
|
||||
q->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
q->answer_protocol = dns_synthesize_protocol(q->flags);
|
||||
q->answer_family = dns_synthesize_family(q->flags);
|
||||
q->answer_authenticated = true;
|
||||
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
|
||||
|
||||
*state = DNS_TRANSACTION_SUCCESS;
|
||||
|
||||
@ -676,7 +676,7 @@ static int dns_query_try_etc_hosts(DnsQuery *q) {
|
||||
q->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
q->answer_protocol = dns_synthesize_protocol(q->flags);
|
||||
q->answer_family = dns_synthesize_family(q->flags);
|
||||
q->answer_authenticated = true;
|
||||
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL|SD_RESOLVED_SYNTHETIC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -795,7 +795,7 @@ fail:
|
||||
|
||||
static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
|
||||
bool has_authenticated = false, has_non_authenticated = false;
|
||||
bool has_authenticated = false, has_non_authenticated = false, has_confidential = false, has_non_confidential = false;
|
||||
DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
|
||||
DnsTransaction *t;
|
||||
int r;
|
||||
@ -817,7 +817,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
q->answer = dns_answer_unref(q->answer);
|
||||
q->answer_rcode = 0;
|
||||
q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
q->answer_authenticated = false;
|
||||
q->answer_query_flags = 0;
|
||||
q->answer_errno = c->error_code;
|
||||
q->answer_full_packet = dns_packet_unref(q->answer_full_packet);
|
||||
}
|
||||
@ -833,10 +833,14 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
r = dns_answer_extend(&q->answer, t->answer);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
q->answer_query_flags |= dns_transaction_source_to_query_flags(t->answer_source);
|
||||
} else {
|
||||
/* Override non-successful previous answers */
|
||||
dns_answer_unref(q->answer);
|
||||
q->answer = dns_answer_ref(t->answer);
|
||||
|
||||
q->answer_query_flags = dns_transaction_source_to_query_flags(t->answer_source);
|
||||
}
|
||||
|
||||
q->answer_rcode = t->answer_rcode;
|
||||
@ -845,7 +849,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
dns_packet_unref(q->answer_full_packet);
|
||||
q->answer_full_packet = dns_packet_ref(t->received);
|
||||
|
||||
if (t->answer_authenticated) {
|
||||
if (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED)) {
|
||||
has_authenticated = true;
|
||||
dnssec_result_authenticated = t->answer_dnssec_result;
|
||||
} else {
|
||||
@ -853,6 +857,11 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
dnssec_result_non_authenticated = t->answer_dnssec_result;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
|
||||
has_confidential = true;
|
||||
else
|
||||
has_non_confidential = true;
|
||||
|
||||
state = DNS_TRANSACTION_SUCCESS;
|
||||
break;
|
||||
}
|
||||
@ -870,14 +879,15 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
continue;
|
||||
|
||||
/* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
|
||||
if (q->answer_authenticated && !t->answer_authenticated)
|
||||
if (FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) &&
|
||||
!FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
continue;
|
||||
|
||||
dns_answer_unref(q->answer);
|
||||
q->answer = dns_answer_ref(t->answer);
|
||||
q->answer_rcode = t->answer_rcode;
|
||||
q->answer_dnssec_result = t->answer_dnssec_result;
|
||||
q->answer_authenticated = t->answer_authenticated;
|
||||
q->answer_query_flags = t->answer_query_flags | dns_transaction_source_to_query_flags(t->answer_source);
|
||||
q->answer_errno = t->answer_errno;
|
||||
dns_packet_unref(q->answer_full_packet);
|
||||
q->answer_full_packet = dns_packet_ref(t->received);
|
||||
@ -888,8 +898,9 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
||||
}
|
||||
|
||||
if (state == DNS_TRANSACTION_SUCCESS) {
|
||||
q->answer_authenticated = has_authenticated && !has_non_authenticated;
|
||||
q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated;
|
||||
SET_FLAG(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED, has_authenticated && !has_non_authenticated);
|
||||
SET_FLAG(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, has_confidential && !has_non_confidential);
|
||||
q->answer_dnssec_result = FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? dnssec_result_authenticated : dnssec_result_non_authenticated;
|
||||
}
|
||||
|
||||
q->answer_protocol = c->scope->protocol;
|
||||
@ -1049,8 +1060,10 @@ int dns_query_process_cname(DnsQuery *q) {
|
||||
if (q->flags & SD_RESOLVED_NO_CNAME)
|
||||
return -ELOOP;
|
||||
|
||||
if (!q->answer_authenticated)
|
||||
if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
q->previous_redirect_unauthenticated = true;
|
||||
if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
|
||||
q->previous_redirect_non_confidential = true;
|
||||
|
||||
/* OK, let's actually follow the CNAME */
|
||||
r = dns_query_cname_redirect(q, cname);
|
||||
@ -1119,5 +1132,11 @@ const char *dns_query_string(DnsQuery *q) {
|
||||
bool dns_query_fully_authenticated(DnsQuery *q) {
|
||||
assert(q);
|
||||
|
||||
return q->answer_authenticated && !q->previous_redirect_unauthenticated;
|
||||
return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) && !q->previous_redirect_unauthenticated;
|
||||
}
|
||||
|
||||
bool dns_query_fully_confidential(DnsQuery *q) {
|
||||
assert(q);
|
||||
|
||||
return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) && !q->previous_redirect_non_confidential;
|
||||
}
|
||||
|
@ -66,12 +66,13 @@ struct DnsQuery {
|
||||
DnsAnswer *answer;
|
||||
int answer_rcode;
|
||||
DnssecResult answer_dnssec_result;
|
||||
bool answer_authenticated;
|
||||
uint64_t answer_query_flags;
|
||||
DnsProtocol answer_protocol;
|
||||
int answer_family;
|
||||
DnsSearchDomain *answer_search_domain;
|
||||
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
|
||||
bool previous_redirect_unauthenticated;
|
||||
bool previous_redirect_non_confidential;
|
||||
DnsPacket *answer_full_packet;
|
||||
|
||||
/* Bus + Varlink client information */
|
||||
@ -132,3 +133,14 @@ const char *dns_query_string(DnsQuery *q);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
|
||||
|
||||
bool dns_query_fully_authenticated(DnsQuery *q);
|
||||
bool dns_query_fully_confidential(DnsQuery *q);
|
||||
|
||||
static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
|
||||
assert(q);
|
||||
|
||||
return SD_RESOLVED_FLAGS_MAKE(q->answer_protocol,
|
||||
q->answer_family,
|
||||
dns_query_fully_authenticated(q),
|
||||
dns_query_fully_confidential(q)) |
|
||||
(q->answer_query_flags & (SD_RESOLVED_FROM_MASK|SD_RESOLVED_SYNTHETIC));
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ DnsScopeMatch dns_scope_good_domain(
|
||||
if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
|
||||
if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, false, false) & flags) == 0)
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
/* Never resolve any loopback hostname or IP address via DNS, LLMNR or mDNS. Instead, always rely on
|
||||
|
@ -29,7 +29,7 @@ static void dns_transaction_reset_answer(DnsTransaction *t) {
|
||||
t->answer_rcode = 0;
|
||||
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID;
|
||||
t->answer_authenticated = false;
|
||||
t->answer_query_flags = 0;
|
||||
t->answer_nsec_ttl = (uint32_t) -1;
|
||||
t->answer_errno = 0;
|
||||
}
|
||||
@ -410,7 +410,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
|
||||
else
|
||||
st = dns_transaction_state_to_string(state);
|
||||
|
||||
log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
|
||||
log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s; %s).",
|
||||
t->bypass ? "Bypass" : "Regular",
|
||||
t->id,
|
||||
dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
|
||||
@ -420,7 +420,8 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
|
||||
st,
|
||||
t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
|
||||
FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) ? "not validated" :
|
||||
(t->answer_authenticated ? "authenticated" : "unsigned"));
|
||||
(FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unsigned"),
|
||||
FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential");
|
||||
|
||||
t->state = state;
|
||||
|
||||
@ -561,10 +562,15 @@ static void on_transaction_stream_error(DnsTransaction *t, int error) {
|
||||
dns_transaction_complete_errno(t, error);
|
||||
}
|
||||
|
||||
static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
|
||||
static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsStream *s, DnsPacket *p) {
|
||||
bool encrypted;
|
||||
|
||||
assert(t);
|
||||
assert(s);
|
||||
assert(p);
|
||||
|
||||
encrypted = s->encrypted;
|
||||
|
||||
dns_transaction_close_connection(t, true);
|
||||
|
||||
if (dns_packet_validate_reply(p) <= 0) {
|
||||
@ -576,7 +582,7 @@ static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
|
||||
dns_scope_check_conflicts(t->scope, p);
|
||||
|
||||
t->block_gc++;
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, encrypted);
|
||||
t->block_gc--;
|
||||
|
||||
/* If the response wasn't useful, then complete the transition
|
||||
@ -621,12 +627,11 @@ static int on_stream_packet(DnsStream *s) {
|
||||
assert(s);
|
||||
|
||||
/* Take ownership of packet to be able to receive new packets */
|
||||
p = dns_stream_take_read_packet(s);
|
||||
assert(p);
|
||||
assert_se(p = dns_stream_take_read_packet(s));
|
||||
|
||||
t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
|
||||
if (t)
|
||||
return dns_transaction_on_stream_packet(t, p);
|
||||
return dns_transaction_on_stream_packet(t, s, p);
|
||||
|
||||
/* Ignore incorrect transaction id as an old transaction can have been canceled. */
|
||||
log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p));
|
||||
@ -793,7 +798,7 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
|
||||
* since our usecase for caching them
|
||||
* is "bypass" mode which is only
|
||||
* enabled for CD packets. */
|
||||
t->answer_authenticated,
|
||||
t->answer_query_flags,
|
||||
t->answer_dnssec_result,
|
||||
t->answer_nsec_ttl,
|
||||
t->received->family,
|
||||
@ -990,7 +995,7 @@ static int dns_transaction_fix_rcode(DnsTransaction *t) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
|
||||
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
@ -1231,7 +1236,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
|
||||
t->answer = dns_answer_ref(p->answer);
|
||||
t->answer_rcode = DNS_PACKET_RCODE(p);
|
||||
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
t->answer_authenticated = false;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, encrypted);
|
||||
|
||||
r = dns_transaction_fix_rcode(t);
|
||||
if (r < 0)
|
||||
@ -1315,7 +1321,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
|
||||
return 0;
|
||||
}
|
||||
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1519,7 +1525,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
|
||||
if (r > 0) {
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
|
||||
t->answer_authenticated = true;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
@ -1538,7 +1544,8 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
|
||||
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
|
||||
t->answer_authenticated = false;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, true);
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
|
||||
} else
|
||||
/* If we are not in downgrade mode, then fail the lookup, because we cannot
|
||||
@ -1559,7 +1566,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
|
||||
if (r > 0) {
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
t->answer_source = DNS_TRANSACTION_ZONE;
|
||||
t->answer_authenticated = true;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
@ -1582,7 +1589,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
|
||||
&t->answer_rcode,
|
||||
&t->answer,
|
||||
&t->received,
|
||||
&t->answer_authenticated,
|
||||
&t->answer_query_flags,
|
||||
&t->answer_dnssec_result);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2566,7 +2573,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
|
||||
* RRs we are looking at. If it discovered signed DS
|
||||
* RRs, then we need to be signed, too. */
|
||||
|
||||
if (!dt->answer_authenticated)
|
||||
if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
return false;
|
||||
|
||||
return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
|
||||
@ -2618,7 +2625,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
return t->answer_authenticated;
|
||||
return FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2642,12 +2649,10 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
/* We found the transaction that was supposed to find
|
||||
* the SOA RR for us. It was successful, but found no
|
||||
* RR for us. This means we are not at a zone cut. In
|
||||
* this case, we require authentication if the SOA
|
||||
* lookup was authenticated too. */
|
||||
return t->answer_authenticated;
|
||||
/* We found the transaction that was supposed to find the SOA RR for us. It was
|
||||
* successful, but found no RR for us. This means we are not at a zone cut. In this
|
||||
* case, we require authentication if the SOA lookup was authenticated too. */
|
||||
return FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2788,7 +2793,7 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
return dt->answer_authenticated;
|
||||
return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
|
||||
}
|
||||
|
||||
/* If in doubt, require NSEC/NSEC3 */
|
||||
@ -2832,11 +2837,10 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
/* OK, we found an auxiliary DNSKEY
|
||||
* lookup. If that lookup is
|
||||
* authenticated, report this. */
|
||||
/* OK, we found an auxiliary DNSKEY lookup. If that lookup is authenticated,
|
||||
* report this. */
|
||||
|
||||
if (dt->answer_authenticated)
|
||||
if (FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
return true;
|
||||
|
||||
found = true;
|
||||
@ -2849,12 +2853,10 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
/* OK, we found an auxiliary DS
|
||||
* lookup. If that lookup is
|
||||
* authenticated and non-zero, we
|
||||
* won! */
|
||||
/* OK, we found an auxiliary DS lookup. If that lookup is authenticated and
|
||||
* non-zero, we won! */
|
||||
|
||||
if (!dt->answer_authenticated)
|
||||
if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
return false;
|
||||
|
||||
return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
|
||||
@ -2942,7 +2944,7 @@ static int dns_transaction_copy_validated(DnsTransaction *t) {
|
||||
if (DNS_TRANSACTION_IS_LIVE(dt->state))
|
||||
continue;
|
||||
|
||||
if (!dt->answer_authenticated)
|
||||
if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||
continue;
|
||||
|
||||
r = dns_answer_extend(&t->validated_keys, dt->answer);
|
||||
@ -3244,7 +3246,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
/* Our own stuff needs no validation */
|
||||
if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) {
|
||||
t->answer_dnssec_result = DNSSEC_VALIDATED;
|
||||
t->answer_authenticated = true;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3332,11 +3334,11 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
/* The answer is fully authenticated, yay. */
|
||||
t->answer_dnssec_result = DNSSEC_VALIDATED;
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
t->answer_authenticated = true;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
|
||||
} else {
|
||||
/* The answer is not fully authenticated. */
|
||||
t->answer_dnssec_result = DNSSEC_UNSIGNED;
|
||||
t->answer_authenticated = false;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
|
||||
}
|
||||
|
||||
} else if (r == 0) {
|
||||
@ -3355,7 +3357,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
|
||||
t->answer_dnssec_result = DNSSEC_VALIDATED;
|
||||
t->answer_rcode = DNS_RCODE_NXDOMAIN;
|
||||
t->answer_authenticated = authenticated;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
|
||||
|
||||
manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
|
||||
break;
|
||||
@ -3365,7 +3367,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
|
||||
t->answer_dnssec_result = DNSSEC_VALIDATED;
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
t->answer_authenticated = authenticated;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, authenticated);
|
||||
|
||||
manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, dns_transaction_key(t));
|
||||
break;
|
||||
@ -3374,7 +3376,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
/* NSEC3 says the data might not be signed */
|
||||
log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str);
|
||||
t->answer_dnssec_result = DNSSEC_UNSIGNED;
|
||||
t->answer_authenticated = false;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
|
||||
|
||||
manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
|
||||
break;
|
||||
@ -3390,7 +3392,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
|
||||
manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, dns_transaction_key(t));
|
||||
} else {
|
||||
t->answer_dnssec_result = DNSSEC_UNSIGNED;
|
||||
t->answer_authenticated = false;
|
||||
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
|
||||
manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, dns_transaction_key(t));
|
||||
}
|
||||
|
||||
|
@ -77,15 +77,12 @@ struct DnsTransaction {
|
||||
uint32_t answer_nsec_ttl;
|
||||
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
|
||||
|
||||
/* Indicates whether the primary answer is authenticated,
|
||||
* i.e. whether the RRs from answer which directly match the
|
||||
* question are authenticated, or, if there are none, whether
|
||||
* the NODATA or NXDOMAIN case is. It says nothing about
|
||||
* additional RRs listed in the answer, however they have
|
||||
* their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit
|
||||
* is defined different than the AD bit in DNS packets, as
|
||||
* that covers more than just the actual primary answer. */
|
||||
bool answer_authenticated;
|
||||
/* SD_RESOLVED_AUTHENTICATED here indicates whether the primary answer is authenticated, i.e. whether
|
||||
* the RRs from answer which directly match the question are authenticated, or, if there are none,
|
||||
* whether the NODATA or NXDOMAIN case is. It says nothing about additional RRs listed in the answer,
|
||||
* however they have their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit is defined different
|
||||
* than the AD bit in DNS packets, as that covers more than just the actual primary answer. */
|
||||
uint64_t answer_query_flags;
|
||||
|
||||
/* Contains DNSKEY, DS, SOA RRs we already verified and need
|
||||
* to authenticate this reply */
|
||||
@ -148,7 +145,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
|
||||
|
||||
int dns_transaction_go(DnsTransaction *t);
|
||||
|
||||
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
|
||||
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted);
|
||||
void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state);
|
||||
|
||||
void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
|
||||
@ -172,6 +169,27 @@ static inline DnsResourceKey *dns_transaction_key(DnsTransaction *t) {
|
||||
return t->bypass->question->keys[0];
|
||||
}
|
||||
|
||||
static inline uint64_t dns_transaction_source_to_query_flags(DnsTransactionSource s) {
|
||||
|
||||
switch (s) {
|
||||
|
||||
case DNS_TRANSACTION_NETWORK:
|
||||
return SD_RESOLVED_FROM_NETWORK;
|
||||
|
||||
case DNS_TRANSACTION_CACHE:
|
||||
return SD_RESOLVED_FROM_CACHE;
|
||||
|
||||
case DNS_TRANSACTION_ZONE:
|
||||
return SD_RESOLVED_FROM_ZONE;
|
||||
|
||||
case DNS_TRANSACTION_TRUST_ANCHOR:
|
||||
return SD_RESOLVED_FROM_TRUST_ANCHOR;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
|
||||
DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;
|
||||
|
||||
|
@ -99,7 +99,7 @@ static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *u
|
||||
|
||||
t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
|
||||
if (t)
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
|
||||
} else if (dns_packet_validate_query(p) > 0) {
|
||||
log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
|
||||
|
@ -303,20 +303,20 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
||||
|
||||
t = dns_scope_find_transaction(scope, rr->key, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
|
||||
if (t)
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
|
||||
/* Also look for the various types of ANY transactions */
|
||||
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
|
||||
if (t)
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
|
||||
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
|
||||
if (t)
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
|
||||
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
|
||||
if (t)
|
||||
dns_transaction_process_reply(t, p);
|
||||
dns_transaction_process_reply(t, p, false);
|
||||
}
|
||||
|
||||
dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, (uint32_t) -1, p->family, &p->sender);
|
||||
|
@ -222,7 +222,7 @@ static void vl_method_resolve_hostname_complete(DnsQuery *q) {
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("addresses", JSON_BUILD_VARIANT(array)),
|
||||
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized)),
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
|
||||
finish:
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to send hostname reply: %m");
|
||||
@ -267,7 +267,8 @@ static int parse_as_address(Varlink *link, LookupParameters *p) {
|
||||
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(ff)),
|
||||
JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(&parsed, FAMILY_ADDRESS_SIZE(ff)))))),
|
||||
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(canonical)),
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true)))));
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true, true)|
|
||||
SD_RESOLVED_SYNTHETIC))));
|
||||
}
|
||||
|
||||
static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
|
||||
@ -440,7 +441,7 @@ static void vl_method_resolve_address_complete(DnsQuery *q) {
|
||||
r = varlink_replyb(q->varlink_request,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("names", JSON_BUILD_VARIANT(array)),
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
|
||||
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
|
||||
finish:
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to send address reply: %m");
|
||||
|
Loading…
x
Reference in New Issue
Block a user