1 use std::fmt; 2 use std::fmt::Write; 3 use std::str::from_utf8; 4 5 // Deprecated since rustc 1.23 6 #[allow(unused_imports, deprecated)] 7 use std::ascii::AsciiExt; 8 9 use byteorder::{BigEndian, ByteOrder}; 10 11 use {Error}; 12 13 /// The DNS name as stored in the original packet 14 /// 15 /// This contains just a reference to a slice that contains the data. 16 /// You may turn this into a string using `.to_string()` 17 #[derive(Clone, Copy)] 18 pub struct Name<'a>{ 19 labels: &'a [u8], 20 /// This is the original buffer size. The compressed names in original 21 /// are calculated in this buffer 22 original: &'a [u8], 23 } 24 25 impl<'a> Name<'a> { 26 /// Scan the data to get Name object 27 /// 28 /// The `data` should be a part of `original` where name should start. 29 /// The `original` is the data starting a the start of a packet, so 30 /// that offsets in compressed name starts from the `original`. scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error>31 pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> { 32 let mut parse_data = data; 33 let mut return_pos = None; 34 let mut pos = 0; 35 if parse_data.len() <= pos { 36 return Err(Error::UnexpectedEOF); 37 } 38 // By setting the largest_pos to be the original len, a side effect 39 // is that the pos variable can move forwards in the buffer once. 40 let mut largest_pos = original.len(); 41 let mut byte = parse_data[pos]; 42 while byte != 0 { 43 if parse_data.len() <= pos { 44 return Err(Error::UnexpectedEOF); 45 } 46 if byte & 0b1100_0000 == 0b1100_0000 { 47 if parse_data.len() < pos+2 { 48 return Err(Error::UnexpectedEOF); 49 } 50 let off = (BigEndian::read_u16(&parse_data[pos..pos+2]) 51 & !0b1100_0000_0000_0000) as usize; 52 if off >= original.len() { 53 return Err(Error::UnexpectedEOF); 54 } 55 // Set value for return_pos which is the pos in the original 56 // data buffer that should be used to return after validating 57 // the offsetted labels. 58 if let None = return_pos { 59 return_pos = Some(pos); 60 } 61 62 // Check then set largest_pos to ensure we never go backwards 63 // in the buffer. 64 if off >= largest_pos { 65 return Err(Error::BadPointer); 66 } 67 largest_pos = off; 68 pos = 0; 69 parse_data = &original[off..]; 70 } else if byte & 0b1100_0000 == 0 { 71 let end = pos + byte as usize + 1; 72 if parse_data.len() < end { 73 return Err(Error::UnexpectedEOF); 74 } 75 if !parse_data[pos+1..end].is_ascii() { 76 return Err(Error::LabelIsNotAscii); 77 } 78 pos = end; 79 if parse_data.len() <= pos { 80 return Err(Error::UnexpectedEOF); 81 } 82 } else { 83 return Err(Error::UnknownLabelFormat); 84 } 85 byte = parse_data[pos]; 86 } 87 if let Some(return_pos) = return_pos { 88 return Ok(Name {labels: &data[..return_pos+2], original: original}); 89 } else { 90 return Ok(Name {labels: &data[..pos+1], original: original }); 91 } 92 } 93 /// Number of bytes serialized name occupies byte_len(&self) -> usize94 pub fn byte_len(&self) -> usize { 95 self.labels.len() 96 } 97 } 98 99 impl<'a> fmt::Display for Name<'a> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result100 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 101 let data = self.labels; 102 let original = self.original; 103 let mut pos = 0; 104 loop { 105 let byte = data[pos]; 106 if byte == 0 { 107 return Ok(()); 108 } else if byte & 0b1100_0000 == 0b1100_0000 { 109 let off = (BigEndian::read_u16(&data[pos..pos+2]) 110 & !0b1100_0000_0000_0000) as usize; 111 if pos != 0 { 112 try!(fmt.write_char('.')); 113 } 114 return fmt::Display::fmt( 115 &Name::scan(&original[off..], original).unwrap(), fmt) 116 } else if byte & 0b1100_0000 == 0 { 117 if pos != 0 { 118 try!(fmt.write_char('.')); 119 } 120 let end = pos + byte as usize + 1; 121 try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap())); 122 pos = end; 123 continue; 124 } else { 125 unreachable!(); 126 } 127 } 128 } 129 } 130 impl<'a> fmt::Debug for Name<'a> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result131 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 132 fmt.debug_tuple("Name") 133 .field(&format!("{}", self)) 134 .finish() 135 } 136 } 137 138 #[cfg(test)] 139 mod test { 140 use Error; 141 use Name; 142 143 #[test] parse_badpointer_same_offset()144 fn parse_badpointer_same_offset() { 145 // A buffer where an offset points to itself, 146 // which is a bad compression pointer. 147 let same_offset = vec![192, 2, 192, 2]; 148 let is_match = matches!(Name::scan(&same_offset, &same_offset), 149 Err(Error::BadPointer)); 150 151 assert!(is_match); 152 } 153 154 #[test] parse_badpointer_forward_offset()155 fn parse_badpointer_forward_offset() { 156 // A buffer where the offsets points back to each other which causes 157 // infinite recursion if never checked, a bad compression pointer. 158 let forwards_offset = vec![192, 2, 192, 4, 192, 2]; 159 let is_match = matches!(Name::scan(&forwards_offset, &forwards_offset), 160 Err(Error::BadPointer)); 161 162 assert!(is_match); 163 } 164 165 #[test] nested_names()166 fn nested_names() { 167 // A buffer where an offset points to itself, a bad compression pointer. 168 let buf = b"\x02xx\x00\x02yy\xc0\x00\x02zz\xc0\x04"; 169 170 assert_eq!(Name::scan(&buf[..], buf).unwrap().to_string(), 171 "xx"); 172 assert_eq!(Name::scan(&buf[..], buf).unwrap().labels, 173 b"\x02xx\x00"); 174 assert_eq!(Name::scan(&buf[4..], buf).unwrap().to_string(), 175 "yy.xx"); 176 assert_eq!(Name::scan(&buf[4..], buf).unwrap().labels, 177 b"\x02yy\xc0\x00"); 178 assert_eq!(Name::scan(&buf[9..], buf).unwrap().to_string(), 179 "zz.yy.xx"); 180 assert_eq!(Name::scan(&buf[9..], buf).unwrap().labels, 181 b"\x02zz\xc0\x04"); 182 } 183 } 184