resolve: parse CAA records
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 31 Jan 2016 21:21:00 +0000 (16:21 -0500)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 13 Feb 2016 01:00:42 +0000 (20:00 -0500)
src/basic/escape.c
src/basic/escape.h
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h

index f276c36..d59aa9f 100644 (file)
@@ -415,6 +415,34 @@ char *xescape(const char *s, const char *bad) {
         return r;
 }
 
+char *octescape(const char *s, size_t len) {
+        char *r, *t;
+        const char *f;
+
+        /* Escapes all chars in bad, in addition to \ and " chars,
+         * in \nnn style escaping. */
+
+        r = new(char, len * 4 + 1);
+        if (!r)
+                return NULL;
+
+        for (f = s, t = r; f < s + len; f++) {
+
+                if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+                        *(t++) = '\\';
+                        *(t++) = '0' + (*f >> 6);
+                        *(t++) = '0' + ((*f >> 3) & 8);
+                        *(t++) = '0' + (*f & 8);
+                } else
+                        *(t++) = *f;
+        }
+
+        *t = 0;
+
+        return r;
+
+}
+
 static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
         assert(bad);
 
index ac8f5f3..bc25646 100644 (file)
@@ -50,6 +50,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
 int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
 char *xescape(const char *s, const char *bad);
+char *octescape(const char *s, size_t len);
 
 char *shell_escape(const char *s, const char *bad);
 char *shell_maybe_quote(const char *s);
index 6a9a1f7..4c4d16d 100644 (file)
@@ -1086,6 +1086,18 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
                 r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
                 break;
 
+        case DNS_TYPE_CAA:
+                r = dns_packet_append_uint8(p, rr->caa.flags, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_string(p, rr->caa.tag, NULL);
+                if (r < 0)
+                        goto fail;
+
+                r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL);
+                break;
+
         case DNS_TYPE_OPT:
         case DNS_TYPE_OPENPGPKEY:
         case _DNS_TYPE_INVALID: /* unparseable */
@@ -1967,6 +1979,21 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_fl
 
                 break;
 
+        case DNS_TYPE_CAA:
+                r = dns_packet_read_uint8(p, &rr->caa.flags, NULL);
+                if (r < 0)
+                        return r;
+
+                r = dns_packet_read_string(p, &rr->caa.tag, NULL);
+                if (r < 0)
+                        return r;
+
+                r = dns_packet_read_memdup(p,
+                                           rdlength + offset - p->rindex,
+                                           &rr->caa.value, &rr->caa.value_size, NULL);
+
+                break;
+
         case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
         case DNS_TYPE_OPENPGPKEY:
         default:
index 422bbe4..35c0de1 100644 (file)
@@ -24,6 +24,7 @@
 #include "alloc-util.h"
 #include "dns-domain.h"
 #include "dns-type.h"
+#include "escape.h"
 #include "hexdecoct.h"
 #include "resolved-dns-dnssec.h"
 #include "resolved-dns-packet.h"
@@ -492,6 +493,11 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
                         free(rr->tlsa.data);
                         break;
 
+                case DNS_TYPE_CAA:
+                        free(rr->caa.tag);
+                        free(rr->caa.value);
+                        break;
+
                 case DNS_TYPE_OPENPGPKEY:
                 default:
                         free(rr->generic.data);
@@ -699,6 +705,12 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
                        a->tlsa.matching_type == b->tlsa.matching_type &&
                        FIELD_EQUAL(a->tlsa, b->tlsa, data);
 
+        case DNS_TYPE_CAA:
+                return a->caa.flags == b->caa.flags &&
+                       streq(a->caa.tag, b->caa.tag) &&
+                       FIELD_EQUAL(a->caa, b->caa, value);
+
+        case DNS_TYPE_OPENPGPKEY:
         default:
                 return FIELD_EQUAL(a->generic, b->generic, data);
         }
@@ -1142,6 +1154,24 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
                 break;
         }
 
+        case DNS_TYPE_CAA: {
+                _cleanup_free_ char *value;
+
+                value = octescape(rr->caa.value, rr->caa.value_size);
+                if (!value)
+                        return NULL;
+
+                r = asprintf(&s, "%s %u %s \"%s\"",
+                             k,
+                             rr->caa.flags,
+                             rr->caa.tag,
+                             value);
+                if (r < 0)
+                        return NULL;
+
+                break;
+        }
+
         case DNS_TYPE_OPENPGPKEY: {
                 int n;
 
@@ -1432,6 +1462,12 @@ void dns_resource_record_hash_func(const void *i, struct siphash *state) {
                 siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
                 break;
 
+        case DNS_TYPE_CAA:
+                siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
+                string_hash_func(rr->caa.tag, state);
+                siphash24_compress(rr->caa.value, rr->caa.value_size, state);
+                break;
+
         case DNS_TYPE_OPENPGPKEY:
         default:
                 siphash24_compress(rr->generic.data, rr->generic.data_size, state);
index 01c7091..b756769 100644 (file)
@@ -251,6 +251,14 @@ struct DnsResourceRecord {
                         void *data;
                         size_t data_size;
                 } tlsa;
+
+                /* https://tools.ietf.org/html/rfc6844 */
+                struct {
+                        uint8_t flags;
+                        char *tag;
+                        void *value;
+                        size_t value_size;
+                } caa;
         };
 };