From 1096f875476472e054a91cbcd6b8e6b9dab4d648 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Tue, 6 Aug 2024 16:30:30 -0400 Subject: [PATCH] add tsig to message --- src/message.rs | 48 +++++++++++++++++++++++++++++++++ src/message/resource_record.rs | 34 +++++++++++------------ src/tsig.rs | 7 +++-- tests/tsig_integration_tests.rs | 3 ++- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/message.rs b/src/message.rs index f820f175..85e91690 100644 --- a/src/message.rs +++ b/src/message.rs @@ -15,12 +15,15 @@ use crate::message::question::Question; use crate::message::resource_record::ResourceRecord; use crate::message::rdata::Rdata; use crate::message::rdata::opt_rdata::OptRdata; +use crate::tsig; +use crate::tsig::tsig_algorithm::TsigAlgorithm; use crate::message::rdata::opt_rdata::option_code::OptionCode; use rand::thread_rng; use rand::Rng; use resource_record::ToBytes; use core::fmt; use std::vec::Vec; +use std::time::SystemTime; #[derive(Clone)] /// Structs that represents a DNS message. @@ -286,6 +289,51 @@ impl DnsMessage { self.update_header_counters(); } + /// Adds Tsig to the message. + /// + /// # Example + /// ``` + /// let dns_query_message = new_query_message(DomainName::new_from_str("example.com".to_string()), Rrtype::A, Rclass:IN, 0, false); + /// let key = vec![1, 2, 3, 4, 5, 6, 7, 8]; + /// let alg_name = TsigAlgorithm::HmacSha1; + /// let fudge = 300; + /// let key_name = "key".to_string(); + /// let mac_request = vec![]; + /// dns_query_message.add_tsig(key, alg_name, fudge, key_name, mac_request); + /// ``` + pub fn add_tsig(&mut self, key: Vec, alg_name: TsigAlgorithm, + fudge: u16, key_name: String, mac_request: Vec) { + let message = self; + let time_signed = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + tsig::sign_tsig(message, &key, alg_name, + fudge, time_signed, key_name, mac_request); + } + + /// Gets the MAC from the TSIG RR. + /// + /// # Example + /// ``` + /// let dns_query_message = new_query_message(DomainName::new_from_str("example.com".to_string()), Rrtype::A, Rclass:IN, 0, false); + /// let key = vec![1, 2, 3, 4, 5, 6, 7, 8]; + /// let alg_name = TsigAlgorithm::HmacSha1; + /// let fudge = 300; + /// let key_name = "key".to_string(); + /// let mac_request = vec![]; + /// dns_query_message.add_tsig(key, alg_name, fudge, key_name, mac_request); + /// let mac = dns_query_message.get_mac(); + /// ``` + pub fn get_mac(&self) -> Vec { + let mut mac = Vec::new(); + let additional = self.get_additional(); + + for rr in additional { + if let Rdata::TSIG(tsig_rdata) = rr.get_rdata() { + mac = tsig_rdata.get_mac(); + } + } + + mac + } /// Creates a new axfr query message. /// diff --git a/src/message/resource_record.rs b/src/message/resource_record.rs index 64ab9a0b..eda68225 100644 --- a/src/message/resource_record.rs +++ b/src/message/resource_record.rs @@ -86,7 +86,7 @@ impl ResourceRecord { rtype: Rrtype::A, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::A(val), }, Rdata::NS(val) => ResourceRecord { @@ -94,7 +94,7 @@ impl ResourceRecord { rtype: Rrtype::NS, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::NS(val), }, Rdata::CNAME(val) => ResourceRecord { @@ -102,7 +102,7 @@ impl ResourceRecord { rtype: Rrtype::CNAME, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::CNAME(val), }, Rdata::SOA(val) => ResourceRecord { @@ -110,7 +110,7 @@ impl ResourceRecord { rtype: Rrtype::SOA, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::SOA(val), }, Rdata::PTR(val) => ResourceRecord { @@ -118,7 +118,7 @@ impl ResourceRecord { rtype: Rrtype::PTR, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::PTR(val), }, Rdata::HINFO(val) => ResourceRecord { @@ -126,7 +126,7 @@ impl ResourceRecord { rtype: Rrtype::HINFO, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::HINFO(val), }, Rdata::MX(val) => ResourceRecord { @@ -134,7 +134,7 @@ impl ResourceRecord { rtype: Rrtype::MX, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::MX(val), }, Rdata::TXT(val) => ResourceRecord { @@ -142,7 +142,7 @@ impl ResourceRecord { rtype: Rrtype::TXT, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::TXT(val), }, Rdata::AAAA(val) => ResourceRecord { @@ -150,7 +150,7 @@ impl ResourceRecord { rtype: Rrtype::AAAA, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::AAAA(val), }, Rdata::OPT(val) => ResourceRecord { @@ -158,7 +158,7 @@ impl ResourceRecord { rtype: Rrtype::OPT, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::OPT(val), }, Rdata::DS(val) => ResourceRecord { @@ -166,7 +166,7 @@ impl ResourceRecord { rtype: Rrtype::DS, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::DS(val), }, Rdata::RRSIG(val) => ResourceRecord { @@ -174,7 +174,7 @@ impl ResourceRecord { rtype: Rrtype::RRSIG, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::RRSIG(val), }, Rdata::NSEC(val) => ResourceRecord { @@ -182,7 +182,7 @@ impl ResourceRecord { rtype: Rrtype::NSEC, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::NSEC(val), }, Rdata::DNSKEY(val) => ResourceRecord { @@ -190,7 +190,7 @@ impl ResourceRecord { rtype: Rrtype::DNSKEY, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::DNSKEY(val), }, Rdata::NSEC3(val) => ResourceRecord { @@ -198,7 +198,7 @@ impl ResourceRecord { rtype: Rrtype::NSEC3, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::NSEC3(val), }, Rdata::NSEC3PARAM(val) => ResourceRecord { @@ -206,7 +206,7 @@ impl ResourceRecord { rtype: Rrtype::NSEC3PARAM, rclass: Rclass::IN, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::NSEC3PARAM(val), }, Rdata::TSIG(val) => ResourceRecord { @@ -214,7 +214,7 @@ impl ResourceRecord { rtype: Rrtype::TSIG, rclass: Rclass::ANY, ttl: 0 as u32, - rdlength: 0 as u16, + rdlength: val.to_bytes().len() as u16, rdata: Rdata::TSIG(val), }, _ => ResourceRecord { diff --git a/src/tsig.rs b/src/tsig.rs index 7e9ea491..93b9007a 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -140,7 +140,7 @@ fn digest(bytes: Vec, tsig_algorithm: TsigAlgorithm, key: Vec) -> Vec) -> Vec { + fudge: u16, time_signed: u64, key_name: String, mac_request: Vec) { let tsig_rd: TSigRdata; let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); @@ -184,14 +184,12 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm } } let rr_len = tsig_rd.to_bytes().len() as u16; - let signature = tsig_rd.get_mac(); let mut new_rr: ResourceRecord = ResourceRecord::new(Rdata::TSIG(tsig_rd)); new_rr.set_name(DomainName::new_from_string(key_name)); new_rr.set_rdlength(rr_len); let mut vec: Vec = vec![]; vec.push(new_rr); query_msg.add_additionals(vec); - return signature; } //Revisa si el nombre de la llave es correcto @@ -596,7 +594,8 @@ mod tsig_test { let tsig_rr = set_tsig_vars(String::from(alg_name.clone()).as_str(), &name, time_signed, fudge); let q_for_mac = q.clone(); //creation of the signature to compare - let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed, name, vec![]); + sign_tsig(&mut q, key, alg_name, fudge, time_signed, name, vec![]); + let firma_a_comparar = q.get_mac(); // creation of the signature digest let dig_for_mac = get_digest_request(vec![],q_for_mac.to_bytes(), tsig_rr); let mut hasher = crypto_hmac::new(Sha1::new(), key); diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index 9343f980..6d656f58 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -147,7 +147,8 @@ async fn tsig_signature() { // se instancia un socket cliente que enviará y mensajes let client_sock = UdpSocket::bind("127.0.0.1:8001").expect("Nothing"); // El cliente firma el mensaje para enviar al servidor. Se guarda el mac de la firma - let mac = sign_tsig(&mut dns_query_message, key, alg_name, fudge, time_signed, name.to_string(), vec![]); + sign_tsig(&mut dns_query_message, key, alg_name, fudge, time_signed, name.to_string(), vec![]); + let mac = dns_query_message.get_mac(); let buf = dns_query_message.to_bytes(); client_sock.send_to(&buf,"127.0.0.1:8002").unwrap(); println!("Mensaje enviado");