summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-01-31 16:21:00 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-02-12 20:00:42 -0500
commit95052df3760523e1f3bb9705c918d85aae7fb431 (patch)
treea5d8b8516314a5e751787db02d405783cf6fd5f6
parentfa45182ed6b833017dde5a7cee27cdf25985790a (diff)
resolve: parse CAA records
-rw-r--r--src/basic/escape.c28
-rw-r--r--src/basic/escape.h1
-rw-r--r--src/resolve/resolved-dns-packet.c27
-rw-r--r--src/resolve/resolved-dns-rr.c36
-rw-r--r--src/resolve/resolved-dns-rr.h8
5 files changed, 100 insertions, 0 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c
index f276c36c56..d59aa9f42f 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -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);
diff --git a/src/basic/escape.h b/src/basic/escape.h
index ac8f5f3910..bc25646a3d 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -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);
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 6a9a1f732d..4c4d16d109 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -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:
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 422bbe4bc4..35c0de1a6d 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -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);
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 01c7091645..b75676912b 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -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;
};
};