]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-packet.c
Merge pull request #30661 from rpigott/resolved-https-record
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
index 29d9dab060974cc78272e88dc78b8cf069ff789b..a7d04449b2f78bb33bd4bb36d8268fdbac79a4b9 100644 (file)
@@ -310,9 +310,23 @@ int dns_packet_validate_query(DnsPacket *p) {
 
         switch (p->protocol) {
 
-        case DNS_PROTOCOL_LLMNR:
         case DNS_PROTOCOL_DNS:
-                if (DNS_PACKET_TC(p)) /* mDNS query may have truncation flag. */
+                if (DNS_PACKET_TC(p))
+                        return -EBADMSG;
+
+                if (DNS_PACKET_QDCOUNT(p) != 1)
+                        return -EBADMSG;
+
+                if (DNS_PACKET_ANCOUNT(p) > 0)
+                        return -EBADMSG;
+
+                /* Note, in most cases, DNS query packet does not have authority section. But some query
+                 * types, e.g. IXFR, have Authority sections. Hence, unlike the check for LLMNR, we do not
+                 * check DNS_PACKET_NSCOUNT(p) here. */
+                break;
+
+        case DNS_PROTOCOL_LLMNR:
+                if (DNS_PACKET_TC(p))
                         return -EBADMSG;
 
                 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
@@ -330,6 +344,9 @@ int dns_packet_validate_query(DnsPacket *p) {
                 break;
 
         case DNS_PROTOCOL_MDNS:
+                /* Note, mDNS query may have truncation flag. So, unlike the check for DNS and LLMNR,
+                 * we do not check DNS_PACKET_TC(p) here. */
+
                 /* RFC 6762, Section 18 specifies that messages with non-zero RCODE
                  * must be silently ignored, and that we must ignore the values of
                  * AA, RD, RA, AD, and CD bits. */
@@ -2677,17 +2694,15 @@ bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b) {
         return dns_packet_compare_func(a, b) == 0;
 }
 
-int dns_packet_ede_rcode(DnsPacket *p, char **ret_ede_msg) {
-        assert(p);
-
-        _cleanup_free_ char *msg = NULL, *msg_escaped = NULL;
-        int ede_rcode = _DNS_EDNS_OPT_MAX_DEFINED;
-        int r;
+int dns_packet_ede_rcode(DnsPacket *p, int *ret_ede_rcode, char **ret_ede_msg) {
         const uint8_t *d;
         size_t l;
+        int r;
+
+        assert(p);
 
         if (!p->opt)
-                return _DNS_EDE_RCODE_INVALID;
+                return -ENOENT;
 
         d = p->opt->opt.data;
         l = p->opt->opt.data_size;
@@ -2707,31 +2722,40 @@ int dns_packet_ede_rcode(DnsPacket *p, char **ret_ede_msg) {
                                                "Truncated option in EDNS0 variable part.");
 
                 if (code == DNS_EDNS_OPT_EXT_ERROR) {
+                        _cleanup_free_ char *msg = NULL;
+
                         if (length < 2U)
                                 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
-                                                "EDNS0 truncated EDE info code.");
-                        ede_rcode = unaligned_read_be16(d + 4);
-                        r = make_cstring((char *)d + 6, length - 2U, MAKE_CSTRING_ALLOW_TRAILING_NUL, &msg);
+                                                       "EDNS0 truncated EDE info code.");
+
+                        r = make_cstring((char *) d + 6, length - 2U, MAKE_CSTRING_ALLOW_TRAILING_NUL, &msg);
                         if (r < 0)
-                                return log_debug_errno(r, "Invalid EDE text in opt");
-                        else if (!utf8_is_valid(msg))
-                                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Invalid EDE text in opt");
-                        else if (ede_rcode < _DNS_EDNS_OPT_MAX_DEFINED) {
-                                msg_escaped = cescape(msg);
-                                if (!msg_escaped)
-                                        return -ENOMEM;
+                                return log_debug_errno(r, "Invalid EDE text in opt.");
+
+                        if (ret_ede_msg) {
+                                if (!utf8_is_valid(msg)) {
+                                        _cleanup_free_ char *msg_escaped = NULL;
+
+                                        msg_escaped = cescape(msg);
+                                        if (!msg_escaped)
+                                                return log_oom_debug();
+
+                                        *ret_ede_msg = TAKE_PTR(msg_escaped);
+                                } else
+                                        *ret_ede_msg = TAKE_PTR(msg);
                         }
-                        break;
+
+                        if (ret_ede_rcode)
+                                *ret_ede_rcode = unaligned_read_be16(d + 4);
+
+                        return 0;
                 }
 
                 d += 4U + length;
                 l -= 4U + length;
         }
 
-        if (ret_ede_msg)
-                *ret_ede_msg = TAKE_PTR(msg_escaped);
-
-        return ede_rcode;
+        return -ENOENT;
 }
 
 bool dns_ede_rcode_is_dnssec(int ede_rcode) {
@@ -2821,6 +2845,7 @@ static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
         [DNS_RCODE_NXRRSET]   = "NXRRSET",
         [DNS_RCODE_NOTAUTH]   = "NOTAUTH",
         [DNS_RCODE_NOTZONE]   = "NOTZONE",
+        [DNS_RCODE_DSOTYPENI] = "DSOTYPENI",
         [DNS_RCODE_BADVERS]   = "BADVERS",
         [DNS_RCODE_BADKEY]    = "BADKEY",
         [DNS_RCODE_BADTIME]   = "BADTIME",