diff --git a/core/net/dns.odin b/core/net/dns.odin index 9febc8b3493..7eb543db341 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -7,10 +7,11 @@ package net */ /* - Copyright 2022 Tetralux - Copyright 2022 Colin Davidson - Copyright 2022 Jeroen van Rijn . - Copyright 2024 Feoramund . + Copyright 2022 Tetralux + Copyright 2022 Colin Davidson + Copyright 2022 Jeroen van Rijn . + Copyright 2024 Feoramund . + Copyright 2025 Christiano Haesbaert . Made available under Odin's BSD-3 license. List of contributors: @@ -18,12 +19,14 @@ package net Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver Jeroen van Rijn: Cross platform unification, code style, documentation Feoramund: FreeBSD platform code + Haesbaert: Security fixes */ import "core:mem" import "core:strings" import "core:time" import "core:os" +import "core:math/rand" /* Default configuration for DNS resolution. */ @@ -227,7 +230,7 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type } hdr := DNS_Header{ - id = 0, + id = u16be(rand.uint32()), is_response = false, opcode = 0, is_authoritative = false, @@ -272,17 +275,23 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return nil, .Connection_Error } - recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue + recv_sz, src := recv_udp(conn, dns_response_buf[:]) or_continue if recv_sz == 0 { continue } + if src != name_server { + continue + } dns_response = dns_response_buf[:recv_sz] - rsp, _ok := parse_response(dns_response, type) + rsp, xid, _ok := parse_response(dns_response, type) if !_ok { return nil, .Server_Error } + if id != xid { + continue + } if len(rsp) == 0 { continue @@ -803,7 +812,7 @@ parse_record :: proc(packet: []u8, cur_off: ^int, filter: DNS_Record_Type = nil) - Data[] */ -parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator := context.allocator) -> (records: []DNS_Record, ok: bool) { +parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator := context.allocator) -> (records: []DNS_Record, xid: u16be, ok: bool) { context.allocator = allocator HEADER_SIZE_BYTES :: 12 @@ -816,11 +825,13 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator dns_hdr_chunks := mem.slice_data_cast([]u16be, response[:HEADER_SIZE_BYTES]) hdr := unpack_dns_header(dns_hdr_chunks[0], dns_hdr_chunks[1]) if !hdr.is_response { + delete(_records) return } question_count := int(dns_hdr_chunks[2]) if question_count != 1 { + delete(_records) return } answer_count := int(dns_hdr_chunks[3]) @@ -872,6 +883,7 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator append(&_records, rec) } } + xid = hdr.id - return _records[:], true + return _records[:], xid, true }