strings.rs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. //! Reading strings from the DNS wire protocol.
  2. use std::convert::TryFrom;
  3. use std::fmt;
  4. use std::io::{self, Write};
  5. use byteorder::{ReadBytesExt, WriteBytesExt};
  6. use log::*;
  7. use crate::wire::*;
  8. /// Domain names in the DNS protocol are encoded as **Labels**, which are
  9. /// segments of ASCII characters prefixed by their length. When written out,
  10. /// each segment is followed by a dot.
  11. ///
  12. /// The maximum length of a segment is 255 characters.
  13. #[derive(PartialEq, Debug, Clone)]
  14. pub struct Labels {
  15. segments: Vec<(u8, String)>,
  16. }
  17. impl Labels {
  18. /// Creates a new empty set of labels, which represent the root of the DNS
  19. /// as a domain with no name.
  20. pub fn root() -> Self {
  21. Self { segments: Vec::new() }
  22. }
  23. /// Encodes the given input string as labels. If any segment is too long,
  24. /// returns that segment as an error.
  25. pub fn encode(input: &str) -> Result<Self, &str> {
  26. let mut segments = Vec::new();
  27. for label in input.split('.') {
  28. if label.is_empty() {
  29. continue;
  30. }
  31. match u8::try_from(label.len()) {
  32. Ok(length) => {
  33. segments.push((length, label.to_owned()));
  34. }
  35. Err(e) => {
  36. warn!("Could not encode label {:?}: {}", label, e);
  37. return Err(label);
  38. }
  39. }
  40. }
  41. Ok(Self { segments })
  42. }
  43. }
  44. impl fmt::Display for Labels {
  45. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  46. for (_, segment) in &self.segments {
  47. write!(f, "{}.", segment)?;
  48. }
  49. Ok(())
  50. }
  51. }
  52. /// An extension for `Cursor` that enables reading compressed domain names
  53. /// from DNS packets.
  54. pub(crate) trait ReadLabels {
  55. /// Read and expand a compressed domain name.
  56. fn read_labels(&mut self) -> Result<(Labels, u16), WireError>;
  57. }
  58. impl ReadLabels for Cursor<&[u8]> {
  59. fn read_labels(&mut self) -> Result<(Labels, u16), WireError> {
  60. let mut labels = Labels { segments: Vec::new() };
  61. let bytes_read = read_string_recursive(&mut labels, self, &mut Vec::new())?;
  62. Ok((labels, bytes_read))
  63. }
  64. }
  65. /// An extension for `Write` that enables writing domain names.
  66. pub(crate) trait WriteLabels {
  67. /// Write a domain name.
  68. ///
  69. /// The names being queried are written with one byte slice per
  70. /// domain segment, preceded by each segment’s length, with the
  71. /// whole thing ending with a segment of zero length.
  72. ///
  73. /// So “dns.lookup.dog” would be encoded as:
  74. /// “3, dns, 6, lookup, 3, dog, 0”.
  75. fn write_labels(&mut self, input: &Labels) -> io::Result<()>;
  76. }
  77. impl<W: Write> WriteLabels for W {
  78. fn write_labels(&mut self, input: &Labels) -> io::Result<()> {
  79. for (length, label) in &input.segments {
  80. self.write_u8(*length)?;
  81. for b in label.as_bytes() {
  82. self.write_u8(*b)?;
  83. }
  84. }
  85. self.write_u8(0)?; // terminate the string
  86. Ok(())
  87. }
  88. }
  89. const RECURSION_LIMIT: usize = 8;
  90. /// Reads bytes from the given cursor into the given buffer, using the list of
  91. /// recursions to track backtracking positions. Returns the count of bytes
  92. /// that had to be read to produce the string, including the bytes to signify
  93. /// backtracking, but not including the bytes read _during_ backtracking.
  94. #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
  95. fn read_string_recursive(labels: &mut Labels, c: &mut Cursor<&[u8]>, recursions: &mut Vec<u16>) -> Result<u16, WireError> {
  96. let mut bytes_read = 0;
  97. loop {
  98. let byte = c.read_u8()?;
  99. bytes_read += 1;
  100. if byte == 0 {
  101. break;
  102. }
  103. else if byte >= 0b_1100_0000 {
  104. let name_one = byte - 0b1100_0000;
  105. let name_two = c.read_u8()?;
  106. bytes_read += 1;
  107. let offset = u16::from_be_bytes([name_one, name_two]);
  108. if recursions.contains(&offset) {
  109. warn!("Hit previous offset ({}) decoding string", offset);
  110. return Err(WireError::TooMuchRecursion(recursions.clone()));
  111. }
  112. recursions.push(offset);
  113. if recursions.len() >= RECURSION_LIMIT {
  114. warn!("Hit recursion limit ({}) decoding string", RECURSION_LIMIT);
  115. return Err(WireError::TooMuchRecursion(recursions.clone()));
  116. }
  117. trace!("Backtracking to offset {}", offset);
  118. let new_pos = c.position();
  119. c.set_position(u64::from(offset));
  120. read_string_recursive(labels, c, recursions)?;
  121. trace!("Coming back to {}", new_pos);
  122. c.set_position(new_pos);
  123. break;
  124. }
  125. // Otherwise, treat the byte as the length of a label, and read that
  126. // many characters.
  127. else {
  128. let mut name_buf = Vec::new();
  129. for _ in 0 .. byte {
  130. let c = c.read_u8()?;
  131. bytes_read += 1;
  132. name_buf.push(c);
  133. }
  134. let string = String::from_utf8_lossy(&*name_buf).to_string();
  135. labels.segments.push((byte, string));
  136. }
  137. }
  138. Ok(bytes_read)
  139. }
  140. #[cfg(test)]
  141. mod test {
  142. use super::*;
  143. use pretty_assertions::assert_eq;
  144. // The buffers used in these tests contain nothing but the labels we’re
  145. // decoding. In DNS packets found in the wild, the cursor will be able to
  146. // reach all the bytes of the packet, so the Answer section can reference
  147. // strings in the Query section.
  148. #[test]
  149. fn nothing() {
  150. let buf: &[u8] = &[
  151. 0x00, // end reading
  152. ];
  153. assert_eq!(Cursor::new(buf).read_labels(),
  154. Ok((Labels::root(), 1)));
  155. }
  156. #[test]
  157. fn one_label() {
  158. let buf: &[u8] = &[
  159. 0x03, // label of length 3
  160. b'o', b'n', b'e', // label
  161. 0x00, // end reading
  162. ];
  163. assert_eq!(Cursor::new(buf).read_labels(),
  164. Ok((Labels::encode("one.").unwrap(), 5)));
  165. }
  166. #[test]
  167. fn two_labels() {
  168. let buf: &[u8] = &[
  169. 0x03, // label of length 3
  170. b'o', b'n', b'e', // label
  171. 0x03, // label of length 3
  172. b't', b'w', b'o', // label
  173. 0x00, // end reading
  174. ];
  175. assert_eq!(Cursor::new(buf).read_labels(),
  176. Ok((Labels::encode("one.two.").unwrap(), 9)));
  177. }
  178. #[test]
  179. fn label_followed_by_backtrack() {
  180. let buf: &[u8] = &[
  181. 0x03, // label of length 3
  182. b'o', b'n', b'e', // label
  183. 0xc0, 0x06, // skip to position 6 (the next byte)
  184. 0x03, // label of length 3
  185. b't', b'w', b'o', // label
  186. 0x00, // end reading
  187. ];
  188. assert_eq!(Cursor::new(buf).read_labels(),
  189. Ok((Labels::encode("one.two.").unwrap(), 6)));
  190. }
  191. #[test]
  192. fn extremely_long_label() {
  193. let mut buf: Vec<u8> = vec![
  194. 0xbf, // label of length 191
  195. ];
  196. buf.extend(vec![0x65; 191]); // the rest of the label
  197. buf.push(0x00); // end reading
  198. assert_eq!(Cursor::new(&*buf).read_labels().unwrap().1, 193);
  199. }
  200. #[test]
  201. fn immediate_recursion() {
  202. let buf: &[u8] = &[
  203. 0xc0, 0x00, // skip to position 0
  204. ];
  205. assert_eq!(Cursor::new(buf).read_labels(),
  206. Err(WireError::TooMuchRecursion(vec![ 0 ])));
  207. }
  208. #[test]
  209. fn mutual_recursion() {
  210. let buf: &[u8] = &[
  211. 0xc0, 0x02, // skip to position 2
  212. 0xc0, 0x00, // skip to position 0
  213. ];
  214. let mut cursor = Cursor::new(buf);
  215. assert_eq!(cursor.read_labels(),
  216. Err(WireError::TooMuchRecursion(vec![ 2, 0 ])));
  217. }
  218. #[test]
  219. fn too_much_recursion() {
  220. let buf: &[u8] = &[
  221. 0xc0, 0x02, // skip to position 2
  222. 0xc0, 0x04, // skip to position 4
  223. 0xc0, 0x06, // skip to position 6
  224. 0xc0, 0x08, // skip to position 8
  225. 0xc0, 0x0A, // skip to position 10
  226. 0xc0, 0x0C, // skip to position 12
  227. 0xc0, 0x0E, // skip to position 14
  228. 0xc0, 0x10, // skip to position 16
  229. 0x00, // no label
  230. ];
  231. let mut cursor = Cursor::new(buf);
  232. assert_eq!(cursor.read_labels(),
  233. Err(WireError::TooMuchRecursion(vec![ 2, 4, 6, 8, 10, 12, 14, 16 ])));
  234. }
  235. }