Add some extra checks

packet-size
Frank Denis 4 years ago
parent 1c63906795
commit da00ac2194

@ -153,8 +153,9 @@ pub fn is_truncated(packet: &[u8]) -> bool {
pub fn qname(packet: &[u8]) -> Result<Vec<u8>, Error> { pub fn qname(packet: &[u8]) -> Result<Vec<u8>, Error> {
debug_assert!(std::usize::MAX > 0xffff); debug_assert!(std::usize::MAX > 0xffff);
debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff); debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff);
ensure!(qdcount(packet) == 1, "Unexpected query count");
let packet_len = packet.len(); let packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(qdcount(packet) == 1, "Unexpected query count");
let mut offset = DNS_HEADER_SIZE; let mut offset = DNS_HEADER_SIZE;
let mut qname = Vec::with_capacity(DNS_MAX_HOSTNAME_SIZE); let mut qname = Vec::with_capacity(DNS_MAX_HOSTNAME_SIZE);
loop { loop {
@ -190,8 +191,9 @@ pub fn qname(packet: &[u8]) -> Result<Vec<u8>, Error> {
pub fn normalize_qname(packet: &mut [u8]) -> Result<(), Error> { pub fn normalize_qname(packet: &mut [u8]) -> Result<(), Error> {
debug_assert!(std::usize::MAX > 0xffff); debug_assert!(std::usize::MAX > 0xffff);
debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff); debug_assert!(DNS_MAX_HOSTNAME_SIZE > 0xff);
ensure!(qdcount(packet) == 1, "Unexpected query count");
let packet_len = packet.len(); let packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(qdcount(packet) == 1, "Unexpected query count");
let mut offset = DNS_HEADER_SIZE; let mut offset = DNS_HEADER_SIZE;
loop { loop {
ensure!(offset < packet_len, "Short packet"); ensure!(offset < packet_len, "Short packet");
@ -225,8 +227,9 @@ pub fn qname_tld(qname: &[u8]) -> &[u8] {
pub fn recase_qname(packet: &mut [u8], qname: &[u8]) -> Result<(), Error> { pub fn recase_qname(packet: &mut [u8], qname: &[u8]) -> Result<(), Error> {
debug_assert!(std::usize::MAX > 0xffff); debug_assert!(std::usize::MAX > 0xffff);
ensure!(qdcount(packet) == 1, "Unexpected query count");
let packet_len = packet.len(); let packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(qdcount(packet) == 1, "Unexpected query count");
let qname_len = qname.len(); let qname_len = qname.len();
let mut offset = DNS_HEADER_SIZE; let mut offset = DNS_HEADER_SIZE;
let mut qname_offset = 0; let mut qname_offset = 0;
@ -302,7 +305,7 @@ fn skip_name(packet: &[u8], offset: usize) -> Result<usize, Error> {
fn traverse_rrs<F: FnMut(usize) -> Result<(), Error>>( fn traverse_rrs<F: FnMut(usize) -> Result<(), Error>>(
packet: &[u8], packet: &[u8],
mut offset: usize, mut offset: usize,
rrcount: u16, rrcount: usize,
mut cb: F, mut cb: F,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
let packet_len = packet.len(); let packet_len = packet.len();
@ -324,7 +327,7 @@ fn traverse_rrs<F: FnMut(usize) -> Result<(), Error>>(
fn traverse_rrs_mut<F: FnMut(&mut [u8], usize) -> Result<(), Error>>( fn traverse_rrs_mut<F: FnMut(&mut [u8], usize) -> Result<(), Error>>(
packet: &mut [u8], packet: &mut [u8],
mut offset: usize, mut offset: usize,
rrcount: u16, rrcount: usize,
mut cb: F, mut cb: F,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
let packet_len = packet.len(); let packet_len = packet.len();
@ -344,16 +347,16 @@ fn traverse_rrs_mut<F: FnMut(&mut [u8], usize) -> Result<(), Error>>(
} }
pub fn min_ttl(packet: &[u8], min_ttl: u32, max_ttl: u32, failure_ttl: u32) -> Result<u32, Error> { pub fn min_ttl(packet: &[u8], min_ttl: u32, max_ttl: u32, failure_ttl: u32) -> Result<u32, Error> {
ensure!(qdcount(packet) == 1, "Unsupported number of questions");
let packet_len = packet.len(); let packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet"); ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet"); ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
ensure!(qdcount(packet) == 1, "No question");
let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?; let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
assert!(offset > DNS_OFFSET_QUESTION); assert!(offset > DNS_OFFSET_QUESTION);
ensure!(packet_len - offset > 4, "Short packet"); ensure!(packet_len - offset > 4, "Short packet");
offset += 4; offset += 4;
let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet)); let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
let rrcount = ancount + nscount + arcount; let rrcount = ancount as usize + nscount as usize + arcount as usize;
let mut found_min_ttl = if rrcount > 0 { max_ttl } else { failure_ttl }; let mut found_min_ttl = if rrcount > 0 { max_ttl } else { failure_ttl };
offset = traverse_rrs(packet, offset, rrcount, |offset| { offset = traverse_rrs(packet, offset, rrcount, |offset| {
@ -395,19 +398,23 @@ fn add_edns_section(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), E
} }
pub fn set_edns_max_payload_size(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error> { pub fn set_edns_max_payload_size(packet: &mut Vec<u8>, max_payload_size: u16) -> Result<(), Error> {
ensure!(qdcount(packet) == 1, "Unsupported number of questions");
let packet_len = packet.len(); let packet_len = packet.len();
ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet"); ensure!(packet_len > DNS_OFFSET_QUESTION, "Short packet");
ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet"); ensure!(packet_len <= DNS_MAX_PACKET_SIZE, "Large packet");
ensure!(qdcount(packet) == 1, "No question");
let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?; let mut offset = skip_name(packet, DNS_OFFSET_QUESTION)?;
assert!(offset > DNS_OFFSET_QUESTION); assert!(offset > DNS_OFFSET_QUESTION);
ensure!(packet_len - offset >= 4, "Short packet"); ensure!(packet_len - offset >= 4, "Short packet");
offset += 4; offset += 4;
let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet)); let (ancount, nscount, arcount) = (ancount(packet), nscount(packet), arcount(packet));
offset = traverse_rrs(packet, offset, ancount + nscount, |_offset| Ok(()))?; offset = traverse_rrs(
packet,
offset,
ancount as usize + nscount as usize,
|_offset| Ok(()),
)?;
let mut edns_payload_set = false; let mut edns_payload_set = false;
traverse_rrs_mut(packet, offset, arcount, |packet, offset| { traverse_rrs_mut(packet, offset, arcount as _, |packet, offset| {
let qtype = BigEndian::read_u16(&packet[offset..]); let qtype = BigEndian::read_u16(&packet[offset..]);
if qtype == DNS_TYPE_OPT { if qtype == DNS_TYPE_OPT {
ensure!(!edns_payload_set, "Duplicate OPT RR found"); ensure!(!edns_payload_set, "Duplicate OPT RR found");
@ -429,7 +436,7 @@ pub fn serve_certificates<'t>(
dnscrypt_encryption_params_set: impl IntoIterator<Item = &'t Arc<DNSCryptEncryptionParams>>, dnscrypt_encryption_params_set: impl IntoIterator<Item = &'t Arc<DNSCryptEncryptionParams>>,
) -> Result<Option<Vec<u8>>, Error> { ) -> Result<Option<Vec<u8>>, Error> {
ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet"); ensure!(client_packet.len() >= DNS_HEADER_SIZE, "Short packet");
ensure!(qdcount(&client_packet) == 1, "No question"); ensure!(qdcount(client_packet) == 1, "No question");
ensure!( ensure!(
!is_response(&client_packet), !is_response(&client_packet),
"Question expected, but got a response instead" "Question expected, but got a response instead"

Loading…
Cancel
Save