caa.rs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. use log::*;
  2. use crate::wire::*;
  3. /// A **CAA** record. These allow domain names to specify which Certificate
  4. /// Authorities are allowed to issue certificates for the domain.
  5. ///
  6. /// # References
  7. ///
  8. /// - [RFC 6844](https://tools.ietf.org/html/rfc6844) — DNS Certification Authority Authorization Resource Record (January 2013s
  9. #[derive(PartialEq, Debug, Clone)]
  10. pub struct CAA {
  11. /// Whether this record is marked as “critical” or not.
  12. pub critical: bool,
  13. /// The “tag” part of the CAA record.
  14. pub tag: String,
  15. /// The “value” part of the CAA record.
  16. pub value: String,
  17. }
  18. impl Wire for CAA {
  19. const NAME: &'static str = "CAA";
  20. const RR_TYPE: u16 = 257;
  21. #[cfg_attr(all(test, feature = "with_mutagen"), ::mutagen::mutate)]
  22. fn read(len: u16, c: &mut Cursor<&[u8]>) -> Result<Self, WireError> {
  23. let flags = c.read_u8()?;
  24. trace!("Parsed flags -> {:#08b}", flags);
  25. let critical = flags & 0b_1000_0000 == 0b_1000_0000;
  26. trace!("Parsed critical flag -> {:?}", critical);
  27. let tag_length = c.read_u8()?;
  28. trace!("Parsed tag length -> {:?}", tag_length);
  29. let mut tag_buf = Vec::new();
  30. for _ in 0 .. tag_length {
  31. tag_buf.push(c.read_u8()?);
  32. }
  33. let tag = String::from_utf8_lossy(&tag_buf).to_string();
  34. trace!("Parsed tag -> {:?}", tag);
  35. let remaining_length = len.saturating_sub(u16::from(tag_length)).saturating_sub(2);
  36. trace!("Remaining length -> {:?}", remaining_length);
  37. let mut value_buf = Vec::new();
  38. for _ in 0 .. remaining_length {
  39. value_buf.push(c.read_u8()?);
  40. }
  41. let value = String::from_utf8_lossy(&value_buf).to_string();
  42. trace!("Parsed value -> {:?}", value);
  43. let got_len = 1 + 1 + u16::from(tag_length) + remaining_length;
  44. if len == got_len {
  45. // This one’s a little weird, because remaining_len is based on len
  46. trace!("Length is correct");
  47. Ok(Self { critical, tag, value })
  48. }
  49. else {
  50. warn!("Length is incorrect (record length {:?}, flags plus tag plus data length {:?}", len, got_len);
  51. Err(WireError::WrongLabelLength { expected: len, got: got_len })
  52. }
  53. }
  54. }
  55. #[cfg(test)]
  56. mod test {
  57. use super::*;
  58. #[test]
  59. fn parses() {
  60. let buf = &[
  61. 0x00, // flags
  62. 0x09, // tag length
  63. 0x69, 0x73, 0x73, 0x75, 0x65, 0x77, 0x69, 0x6c, 0x64, // tag
  64. 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, // value
  65. ];
  66. assert_eq!(CAA::read(buf.len() as _, &mut Cursor::new(buf)).unwrap(),
  67. CAA {
  68. critical: false,
  69. tag: String::from("issuewild"),
  70. value: String::from("entrust.net"),
  71. });
  72. }
  73. #[test]
  74. fn empty() {
  75. assert_eq!(CAA::read(0, &mut Cursor::new(&[])),
  76. Err(WireError::IO));
  77. }
  78. }