X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-packet.c;h=ba056f1f444441000c65a77d3c9bc217bfbcdb52;hp=32c4876a54a2e8e80494c1b0cb0cf13e343d93df;hb=bdf10b5b4d9e7abdc08bdca4b073d021b0043d1f;hpb=cbd67a86fbb0452bb4a341783b15eb504a432fc0 diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 32c4876a5..ba056f1f4 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -390,6 +390,7 @@ int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) { _cleanup_free_ char *s = NULL; char label[DNS_LABEL_MAX]; size_t n; + int k; n = PTR_TO_SIZE(hashmap_get(p->names, name)); if (n > 0) { @@ -414,6 +415,17 @@ int dns_packet_append_name(DnsPacket *p, const char *name, size_t *start) { if (r < 0) goto fail; + if (p->protocol == DNS_PROTOCOL_DNS) + k = dns_label_apply_idna(label, r, label, sizeof(label)); + else + k = dns_label_undo_idna(label, r, label, sizeof(label)); + if (k < 0) { + r = k; + goto fail; + } + if (k > 0) + r = k; + r = dns_packet_append_label(p, label, r, &n); if (r < 0) goto fail; @@ -499,9 +511,26 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + case DNS_TYPE_SRV: + r = dns_packet_append_uint16(p, rr->srv.priority, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->srv.weight, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->srv.port, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_name(p, rr->srv.name, NULL); + break; + case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: r = dns_packet_append_name(p, rr->ptr.name, NULL); break; @@ -523,6 +552,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star goto fail; } + r = 0; break; } @@ -587,20 +617,28 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star if (r < 0) goto fail; - r = dns_packet_append_uint16(p, rr->loc.latitude, NULL); + r = dns_packet_append_uint32(p, rr->loc.latitude, NULL); if (r < 0) goto fail; - r = dns_packet_append_uint16(p, rr->loc.longitude, NULL); + r = dns_packet_append_uint32(p, rr->loc.longitude, NULL); if (r < 0) goto fail; - r = dns_packet_append_uint16(p, rr->loc.altitude, NULL); + r = dns_packet_append_uint32(p, rr->loc.altitude, NULL); break; - case DNS_TYPE_SRV: - case DNS_TYPE_DNAME: case DNS_TYPE_SSHFP: + r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL); + if (r < 0) + goto fail; + r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL); + break; + case _DNS_TYPE_INVALID: /* unparseable */ default: @@ -814,7 +852,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret, size_t *start) { else first = false; - memcpy(ret + n, t, c); + memcpy(ret + n, t, r); n += r; continue; } else if ((c & 0xc0) == 0xc0) { @@ -904,6 +942,12 @@ fail: return r; } +static bool loc_size_ok(uint8_t size) { + uint8_t m = size >> 4, e = size & 0xF; + + return m <= 9 && e <= 9 && (m > 0 || e == 0); +} + int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; @@ -950,9 +994,23 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { switch (rr->key->type) { + case DNS_TYPE_SRV: + r = dns_packet_read_uint16(p, &rr->srv.priority, NULL); + if (r < 0) + goto fail; + r = dns_packet_read_uint16(p, &rr->srv.weight, NULL); + if (r < 0) + goto fail; + r = dns_packet_read_uint16(p, &rr->srv.port, NULL); + if (r < 0) + goto fail; + r = dns_packet_read_name(p, &rr->srv.name, NULL); + break; + case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: r = dns_packet_read_name(p, &rr->ptr.name, NULL); break; @@ -976,7 +1034,9 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { r = strv_consume(&rr->txt.strings, s); if (r < 0) goto fail; - }; + } + + r = 0; break; } @@ -1039,14 +1099,29 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; + if (!loc_size_ok(rr->loc.size)) { + r = -EBADMSG; + goto fail; + } + r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL); if (r < 0) goto fail; + if (!loc_size_ok(rr->loc.horiz_pre)) { + r = -EBADMSG; + goto fail; + } + r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL); if (r < 0) goto fail; + if (!loc_size_ok(rr->loc.vert_pre)) { + r = -EBADMSG; + goto fail; + } + r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL); if (r < 0) goto fail; @@ -1063,14 +1138,35 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { } else { dns_packet_rewind(p, pos); rr->unparseable = true; - /* fall through */ + goto unparseable; } } - case DNS_TYPE_SRV: - case DNS_TYPE_DNAME: case DNS_TYPE_SSHFP: + + r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL); + if (r < 0) + goto fail; + + r = dns_packet_read(p, rdlength - 2, &d, NULL); + if (r < 0) + goto fail; + + rr->sshfp.key = memdup(d, rdlength - 2); + if (!rr->sshfp.key) { + r = -ENOMEM; + goto fail; + } + + rr->sshfp.key_size = rdlength - 2; + break; + default: + unparseable: r = dns_packet_read(p, rdlength, &d, NULL); if (r < 0) goto fail;