From 4c77ba8dc635903adb90e5b4cec787839fe64007 Mon Sep 17 00:00:00 2001 From: Dobore Date: Wed, 24 Apr 2024 13:13:23 -0400 Subject: [PATCH 001/124] test branch dnssec --- src/test_2/foo2.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/test_2/foo2.rs diff --git a/src/test_2/foo2.rs b/src/test_2/foo2.rs new file mode 100644 index 00000000..e69de29b From d6fe972e45d34f7412e0c2d61d1fdd32114ab232 Mon Sep 17 00:00:00 2001 From: Dobore Date: Tue, 14 May 2024 12:27:11 -0400 Subject: [PATCH 002/124] Added dnssec file with an incomplete decrypt function --- src/dnssec.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 103 insertions(+) create mode 100644 src/dnssec.rs diff --git a/src/dnssec.rs b/src/dnssec.rs new file mode 100644 index 00000000..685e7020 --- /dev/null +++ b/src/dnssec.rs @@ -0,0 +1,102 @@ +use crate::domain_name::DomainName; +use crate::message::class_qclass::Qclass; +use crate::message::type_qtype::Qtype; +use crate::message::{rdata::rrsig_rdata::RRSIGRdata, DnsMessage}; +use crate::message::rdata::Rdata; +use crate::message::rdata::rrsig::RRSIG; +use crate::message::rdata::dnskey::DNSKEY; +use openssl::rsa::Rsa; + +// A.1. DNSSEC Algorithm Types +// The DNSKEY, RRSIG, and DS RRs use an 8-bit number to identify the +// security algorithm being used. These values are stored in the +// "Algorithm number" field in the resource record RDATA. +// Some algorithms are usable only for zone signing (DNSSEC), some only +// for transaction security mechanisms (SIG(0) and TSIG), and some for +// both. Those usable for zone signing may appear in DNSKEY, RRSIG, and +// DS RRs. Those usable for transaction security would be present in +// SIG(0) and KEY RRs, as described in [RFC2931]. +// Zone +// Value Algorithm [Mnemonic] Signing References Status +// ----- -------------------- --------- ---------- --------- +// 0 reserved +// 1 RSA/MD5 [RSAMD5] n [RFC2537] NOT RECOMMENDED +// 2 Diffie-Hellman [DH] n [RFC2539] - +// 3 DSA/SHA-1 [DSA] y [RFC2536] OPTIONAL +// 4 Elliptic Curve [ECC] TBA - +// 5 RSA/SHA-1 [RSASHA1] y [RFC3110] MANDATORY +// 252 Indirect [INDIRECT] n - +// 253 Private [PRIVATEDNS] y see below OPTIONAL +// 254 Private [PRIVATEOID] y see below OPTIONAL +// 255 reserved + +// The following algorithm types are defined in this document: +// 0 - RSA/MD5 [RFC2537] +// 1 - Diffie-Hellman [RFC2539] +// 2 - DSA/SHA-1 [RFC2536] +// 3 - Elliptic Curve [TBA] +// 4 - RSA/SHA-1 [RFC3110] +// 5 - Indirect [RFC4034] + +fn get_algorithm_name(algorithm: u8) -> &'static str { + match algorithm { + 1 => "RSA/MD5", + 2 => "Diffie-Hellman", + 3 => "DSA/SHA-1", + 4 => "Elliptic Curve", + 5 => "RSA/SHA-1", + _ => "Unknown", + } +} + +// Once the resolver has validated the RRSIG RR as described in Section +// 5.3.1 and reconstructed the original signed data as described in +// Section 5.3.2, the validator can attempt to use the cryptographic +// signature to authenticate the signed data, and thus (finally!) +// authenticate the RRset. + +// The Algorithm field in the RRSIG RR identifies the cryptographic +// algorithm used to generate the signature. The signature itself is +// contained in the Signature field of the RRSIG RDATA, and the public +// key used to verify the signature is contained in the Public Key field +// of the matching DNSKEY RR(s) (found in Section 5.3.1). [RFC4034] +// provides a list of algorithm types and provides pointers to the +// documents that define each algorithm’s use. + +//The Funcion Verifies the zone's DNSKEY RR set by successfully decrypting the RR set's RRSig using the zone's Public Key signing key + +fn decrypt_signature(rrset: &Vec, rrsig: &RRSIG, dnskey: &DNSKEY) -> bool { + //The Algorithm field in the RRSIG RR identifies the cryptographic algorithm used to generate the signature. + algoritm = rrsig.algorithm; + // The signature itself is contained in the Signature field of the RRSIG RDATA + signature = rrsig.signature; + // and the public key used to verify the signature is contained in the Public Key field of the matching DNSKEY RR(s) + public_key = dnskey.public_key; + + // If the Labels field of the RRSIG RR is not equal to the number of labels in the RRset’s fully qualified owner name, then the RRset is invalid + if rrsig.labels != rrset[0].owner.labels() { + return false; + } + +// If the resolver accepts the RRset as authentic, the validator MUST +// set the TTL of the RRSIG RR and each RR in the authenticated RRset to +// a value no greater than the minimum of: +// o the RRset’s TTL as received in the response; +// o the RRSIG RR’s TTL as received in the response; +// o the value in the RRSIG RR’s Original TTL field; and +// o the difference of the RRSIG RR’s Signature Expiration time and the +// current time. + + // If the Signer’s Name field in the RRSIG RR is not equal to the owner name of the RRset, then the RRset is invalid + if rrsig.signer_name != rrset[0].owner { + return false; + } + + // If the Key Tag in the RRSIG RR does not match the Key Tag in the DNSKEY RR, then the RRset is invalid + if rrsig.key_tag != dnskey.key_tag { + return false; + } + + + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9fbfcdcc..e94a1329 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ pub mod message; pub mod async_resolver; pub mod utils; pub mod truncated_dns_message; +pub mod dnssec; From 5b6c8119d0582ece5f153e81373e058ae5dd7b95 Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 16 May 2024 13:09:54 -0400 Subject: [PATCH 003/124] Feat: sign_msg adds the computed signature to the provided DnSmessage --- src/tsig.rs | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index a46338a9..cd6b0439 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,6 +1,7 @@ //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; +use crate::message::resource_record::{self, ToBytes}; use crate::message::type_qtype::Qtype; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage}; use std::os::unix::process; @@ -21,13 +22,14 @@ enum TsigAlgorithm { HmacSha256, } -#[doc = r"This functions signs a DnsMessage with a key in bytes, and the algName will be used to select the algorithm to encrypt the key."] -fn sign_msg(query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ - let mut new_query_message = query_msg.clone(); +#[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] +fn sign_msg(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ let mut dig_string:&str; + let mut new_query_message = query_msg.clone(); let mut mac_len:&str; let mut a_name: &str; let placeholder_hex: String; + let mut additional = query_msg.get_additional(); //TODO: cambiar el match pattern match alg_name { TsigAlgorithm::HmacSha1 => { @@ -55,9 +57,27 @@ fn sign_msg(query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ }, _ => {panic!("Error: Invalid algorithm")}, } - //TODO: agregar los demas valores al msg_bytes !! Yo creo que deben llegar como argumentos - let mut msg_bytes: String = format!("{}.\n51921\n1234\n{}\n{}\n1234\n0\n0",a_name, mac_len, dig_string); - return msg_bytes.as_bytes(); + + //TODO: agregar los demas valores al dig_string !! Yo creo que deben llegar como argumentos + let mut dig_string: String = format!("{}.\n51921\n1234\n{}\n{}\n1234\n0\n0",a_name, mac_len, dig_string); + + //se modifica el resource record para añadir el hmac + let mut rr = additional.pop().expect("Empty Resource Record!"); + let mut rdata:Rdata= rr.get_rdata(); + match rdata { + Rdata::TSIG(mut data) =>{ + let mut mac: Vec =data.to_bytes(); + data.set_mac(mac); + } + _ => { + println!("Error: no valid rdata found!"); + } + } + // RFC 8945 4.2: Se añade el digest resource record, en la zona "additionals". + let mut vec = vec![]; + vec.push(rr); + query_msg.add_additionals(vec); + return dig_string.as_bytes(); } @@ -161,8 +181,8 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //ToDo: Crear bien un test que funcione #[test] fn ptsig_test(){ - let my_key = b"1201102391287592dsjshno039U021J"; - let alg: TsigAlgorithm = HmacSha256; + let my_key = b"1201102391287592dsjshno039U021Jg"; + let alg: TsigAlgorithm = TsigAlgorithm::HmacSha256; let mut dns_example_msg = DnsMessage::new_query_message( DomainName::new_from_string("uchile.cl".to_string()), @@ -171,8 +191,9 @@ fn ptsig_test(){ 0, false, 1); - //prueba de la firma + //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia let signature = sign_msg(dns_example_msg, my_key, alg); - //prueba de process_tsig + + //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) let processed_msg = process_tsig(dns_example_msg, my_key); } From fe8167ac94dcf9d5092b3b3aedb200400fc17b8f Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 16 May 2024 18:06:58 -0400 Subject: [PATCH 004/124] Refactoring: sign_msg -> sign_tsig. Changed the way the resource record with the Rdata is modified. --- src/tsig.rs | 80 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index cd6b0439..4cf27632 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,17 +1,16 @@ //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; -use crate::message::resource_record::{self, ToBytes}; +use crate::message::resource_record::{self, ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage}; use std::os::unix::process; use std::time::{SystemTime, UNIX_EPOCH}; -use crate::message::rdata::Rdata; -use sha2::Sha256; +use crate::message::rdata::{rrsig_rdata, Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; -use crypto::sha1::Sha1; +use crypto::{sha1::Sha1,sha2::Sha256}; use bytes::Bytes; type HmacSha256 = Hmac; @@ -21,9 +20,9 @@ enum TsigAlgorithm { HmacSha1, HmacSha256, } - +/* #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -fn sign_msg(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ +fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ let mut dig_string:&str; let mut new_query_message = query_msg.clone(); let mut mac_len:&str; @@ -73,13 +72,61 @@ fn sign_msg(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ println!("Error: no valid rdata found!"); } } - // RFC 8945 4.2: Se añade el digest resource record, en la zona "additionals". let mut vec = vec![]; vec.push(rr); query_msg.add_additionals(vec); return dig_string.as_bytes(); -} +} */ +// experimental +#[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] +fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> &[u8] { + let mut tsig_rd: TSigRdata = TSigRdata::new(); + let mut new_query_message = query_msg.clone(); + let original_id = query_msg.get_query_id(); + match alg_name { + TsigAlgorithm::HmacSha1 => { + let mut hasher = crypto_hmac::new(Sha1::new(), key); + hasher.input(&new_query_message.to_bytes()[..]); + let result = hasher.result(); + let mac = result.code(); + //Convertir los bytes brutos a una cadena hexadecimal + let mac_size = 20; + let a_name = "Hmac-Sha1".to_uppercase(); + let a_name = DomainName::new_from_string(a_name); + tsig_rd.set_algorithm_name(a_name); + tsig_rd.set_mac_size(mac_size); + tsig_rd.set_mac(mac.to_vec()); + tsig_rd.set_fudge(fudge); + tsig_rd.set_original_id(original_id); + tsig_rd.set_time_signed(time_signed); + }, + TsigAlgorithm::HmacSha256 => { + let mut hasher = crypto_hmac::new(Sha256::new(), key); + hasher.input(&new_query_message.to_bytes()[..]); + let result = hasher.result(); + let mac = result.code(); + //Convertir los bytes brutos a una cadena hexadecimal + let mac_size = 32; + let a_name = "Hmac-Sha256".to_uppercase(); + let a_name = DomainName::new_from_string(a_name); + tsig_rd.set_algorithm_name(a_name); + tsig_rd.set_mac_size(mac_size); + tsig_rd.set_mac(mac.to_vec()); + tsig_rd.set_fudge(fudge); + tsig_rd.set_original_id(original_id); + tsig_rd.set_time_signed(time_signed); + + }, + _ => {panic!("Error: Invalid algorithm")}, + } + let mut new_rr = ResourceRecord::new(Rdata::TSIG(tsig_rd)); + new_rr.set_rdlength(tsig_rd.to_bytes().len() as u16); + let mut vec: Vec = vec![]; + vec.push(new_rr); + query_msg.add_additionals(vec); + return &tsig_rd.get_mac(); +} #[doc = r"This function process a tsig message, checking for errors in the DNS message"] fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { @@ -92,6 +139,13 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { let time =SystemTime::now().duration_since(UNIX_EPOCH).expect("no time").as_secs(); //vector con resource records que son TSIG let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); + //RF + //verificar que existen los resource records que corresponden a tsig + if filtered_tsig.len()>1 || x{ + let error_msg = DnsMessage::format_error_msg(); + return error_msg; + } + let x = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {true} else {false}; let rdata = rr.get_rdata(); let mut time_signed_v = 0; @@ -116,12 +170,7 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { } } - //verificar que existen los resource records que corresponden a tsig - if filtered_tsig.len()>1 || x{ - let error_msg = DnsMessage::format_error_msg(); - return error_msg; - } - + //Verificación de los tiempos de emisión y recepción + fudge del mensaje // Según lo especificado en el RFC 8945 5.2.3 time Check and Error Handling @@ -191,8 +240,9 @@ fn ptsig_test(){ 0, false, 1); + let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia - let signature = sign_msg(dns_example_msg, my_key, alg); + let signature = sign_tsig(dns_example_msg, my_key, alg,1000,time ); //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) let processed_msg = process_tsig(dns_example_msg, my_key); From 0f39787f66b65aab5fed127d665ab8585c0b3a48 Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 16 May 2024 18:14:12 -0400 Subject: [PATCH 005/124] Added some tsig verifications to process tsig --- src/tsig.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 4cf27632..808e5e21 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -131,22 +131,30 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud #[doc = r"This function process a tsig message, checking for errors in the DNS message"] fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { let mut retmsg = msg.clone(); - let mut addit = retmsg.get_additional(); + let mut addit = retmsg.getadditional(); println!("{:#?}",addit); //sacar el último elemento del vector resource record let rr = addit.pop().expect("No additional data"); let time =SystemTime::now().duration_since(UNIX_EPOCH).expect("no time").as_secs(); - //vector con resource records que son TSIG - let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - //RF + //RFC 8945 5.2 //verificar que existen los resource records que corresponden a tsig - if filtered_tsig.len()>1 || x{ + //vector con resource records que son TSIG + let filtered_tsig:Vec<> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); + //RFC 8945 5.4 + //Verifica si hay algún tsig rr + let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {true} else {false}; + if filtered_tsig.len()==0 { + //este debe ser un error de formato + let error_msg = DnsMessage::format_error_msg(); + return error_msg; + } + //Debe haber un único tsig + //Tsig RR debe ser el último en la sección adicional + if filtered_tsig.len()>1 || islast { let error_msg = DnsMessage::format_error_msg(); return error_msg; } - - let x = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {true} else {false}; let rdata = rr.get_rdata(); let mut time_signed_v = 0; let mut fudge = 0; From f640e8de8baa5aba2bba3e5f29a8e73271848a38 Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 16 May 2024 19:45:57 -0400 Subject: [PATCH 006/124] Fix: sign_tsig fixed ownership-related errors . Fixed overall ownershitp and moved value-related errors --- src/tsig.rs | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 808e5e21..c180cc7f 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -4,14 +4,13 @@ use crate::message::class_qclass::Qclass; use crate::message::resource_record::{self, ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage}; -use std::os::unix::process; use std::time::{SystemTime, UNIX_EPOCH}; use crate::message::rdata::{rrsig_rdata, Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; -use bytes::Bytes; + type HmacSha256 = Hmac; @@ -80,7 +79,7 @@ fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u // experimental #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> &[u8] { +fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); @@ -120,18 +119,20 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud }, _ => {panic!("Error: Invalid algorithm")}, } - let mut new_rr = ResourceRecord::new(Rdata::TSIG(tsig_rd)); - new_rr.set_rdlength(tsig_rd.to_bytes().len() as u16); + 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_rdlength(rr_len); let mut vec: Vec = vec![]; vec.push(new_rr); query_msg.add_additionals(vec); - return &tsig_rd.get_mac(); + return signature; } #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { +fn process_tsig(msg: DnsMessage, key: &[u8]) -> DnsMessage { let mut retmsg = msg.clone(); - let mut addit = retmsg.getadditional(); + let mut addit = retmsg.get_additional(); println!("{:#?}",addit); //sacar el último elemento del vector resource record @@ -140,7 +141,7 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { //RFC 8945 5.2 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG - let filtered_tsig:Vec<> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); + let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); //RFC 8945 5.4 //Verifica si hay algún tsig rr let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {true} else {false}; @@ -159,7 +160,7 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { let mut time_signed_v = 0; let mut fudge = 0; let mut rcode =0; - let mut key = String::from(""); + let mut n_key = String::from(""); //Verificar rdata match rdata { Rdata::TSIG(data) =>{ @@ -167,7 +168,7 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { fudge = data.get_fudge(); rcode = data.get_error(); for elem in data.get_mac(){ - key+=&elem.to_string(); + n_key+=&elem.to_string(); } } _ => { @@ -207,11 +208,14 @@ fn process_tsig(msg: DnsMessage, key: &[u8;32]) -> DnsMessage { old_head.set_arcount(0); retmsg.set_header(old_head); let algorithm = TsigAlgorithm::HmacSha256; + //TODO: extraer los siguientes valores del rdata del mensaje a verificar + let msg_time= SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); + let msg_fudge = 1000; //se verifica la autenticidad de la firma - let digest = sign_msg(retmsg, key, algorithm); - let digest_string = digest.to_string(); + let digest = sign_tsig(retmsg.clone(), key, algorithm,msg_time as u16,msg_fudge); + let digest_string = &digest; println!("El dig stirng es: {:#?}" , digest_string); - let binding = digest.as_bytes(); + let binding = &digest; let rdata = rr.get_rdata(); match rdata { Rdata::TSIG(tsigrdata) => { @@ -250,8 +254,9 @@ fn ptsig_test(){ 1); let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia - let signature = sign_tsig(dns_example_msg, my_key, alg,1000,time ); + let _signature = sign_tsig(dns_example_msg.clone(), my_key, alg,1000,time ); //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) - let processed_msg = process_tsig(dns_example_msg, my_key); + //let _processed_msg = process_tsig(dns_example_msg, my_key); + } From ab8a1a5fb63f6aef006f2a04b4685febaa43801d Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 16 May 2024 20:11:53 -0400 Subject: [PATCH 007/124] added some tests for sign_tsig --- src/tsig.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index c180cc7f..ee0dbec3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -10,7 +10,7 @@ use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; - +use std::str; type HmacSha256 = Hmac; @@ -243,6 +243,7 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ #[test] fn ptsig_test(){ let my_key = b"1201102391287592dsjshno039U021Jg"; + let my_short_key = b"1201102391287592dsjs"; let alg: TsigAlgorithm = TsigAlgorithm::HmacSha256; let mut dns_example_msg = DnsMessage::new_query_message( @@ -255,7 +256,19 @@ fn ptsig_test(){ let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia let _signature = sign_tsig(dns_example_msg.clone(), my_key, alg,1000,time ); + let _sha1signature = sign_tsig(dns_example_msg.clone(),my_short_key, TsigAlgorithm::HmacSha1,1000, time); + let signature = match str::from_utf8(&_signature){ + Ok(v) =>v, + Err(e) =>panic!("Invalid UTF-( sequence: {}",e) + }; + let sha1signature = match str::from_utf8(&_sha1signature){ + Ok(v) =>v, + Err(e) =>panic!("Invalid UTF-( sequence: {}",e) + }; + println!("SHA-256: {}",signature); + println!("SHA-1: {}",sha1signature); + //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) //let _processed_msg = process_tsig(dns_example_msg, my_key); From d521453176ac7a3ed8da1e06a0f05dce4aed85cc Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 13:27:26 -0400 Subject: [PATCH 008/124] =?UTF-8?q?Se=20avanz=C3=B3=20con=20process=5Ftsig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tsig.rs | 89 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index ee0dbec3..1f0a09c8 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -129,56 +129,87 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud return signature; } +//TODO: terminar función keycheck +fn check_key(alg_name: String,key_in_rr:String,key: &[u8])->Bool{ + let mut answer = true; + + return answer +} + + #[doc = r"This function process a tsig message, checking for errors in the DNS message"] fn process_tsig(msg: DnsMessage, key: &[u8]) -> DnsMessage { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); - println!("{:#?}",addit); - - //sacar el último elemento del vector resource record - let rr = addit.pop().expect("No additional data"); let time =SystemTime::now().duration_since(UNIX_EPOCH).expect("no time").as_secs(); - //RFC 8945 5.2 + //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig - //vector con resource records que son TSIG + //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - //RFC 8945 5.4 - //Verifica si hay algún tsig rr - let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {true} else {false}; + let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {false} else {true}; if filtered_tsig.len()==0 { - //este debe ser un error de formato let error_msg = DnsMessage::format_error_msg(); return error_msg; } //Debe haber un único tsig - //Tsig RR debe ser el último en la sección adicional + //Tsig RR debe ser el último en la sección adicional, y debe ser único if filtered_tsig.len()>1 || islast { let error_msg = DnsMessage::format_error_msg(); return error_msg; } - let rdata = rr.get_rdata(); - let mut time_signed_v = 0; - let mut fudge = 0; - let mut rcode =0; - let mut n_key = String::from(""); - //Verificar rdata - match rdata { + + //sacar el último elemento del vector resource record, y disminuir elvalor de ARCOUNT + let rr_copy = addit.pop().expect("No tsig rr"); + let mut tsig_rr_copy = TSigRdata::new(); + match rr_copy.get_rdata() { Rdata::TSIG(data) =>{ - time_signed_v = data.get_time_signed(); - fudge = data.get_fudge(); - rcode = data.get_error(); - for elem in data.get_mac(){ - n_key+=&elem.to_string(); - } + tsig_rr_copy = data; } _ => { - println!("Bad resource record"); - //TODO: ver/añadir el error del print anterior, especificado en el RFC 8945 - let error_msg = DnsMessage::format_error_msg(); - return error_msg; + println!("error") } - } + let nuevo_len_arcount = addit.len() as u16; + let new_header = msg.get_header(); + new_header.set_arcount(nuevo_len_arcount); + msg.set_header(new_header); + //RFC 8945 5.2.1 + let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); + let key_in_rr = rr_copy.get_name().get_name(); + let cond1 = check_key(name_alg,key_in_rr,key); + if cond1 { + println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + let error_msg = DnsMessage::format_error_msg(); + return error_msg; + } + //TODO: hacer los demas checkeos + //let cond2 = check_mac(); + //let cond3 = check_time_values(); + //let cond4 = check_truncation_policy(); + + //let rdata = rr.get_rdata(); + let mut time_signed_v = 0; + let mut fudge = 0; + //let mut rcode =0; + //let mut n_key = String::from(""); + ////Verificar rdata + //match rdata { + // Rdata::TSIG(data) =>{ + // time_signed_v = data.get_time_signed(); + // fudge = data.get_fudge(); + // rcode = data.get_error(); + // for elem in data.get_mac(){ + // n_key+=&elem.to_string(); + // } + // } + // _ => { + // println!("Bad resource record"); + // //TODO: ver/añadir el error del print anterior, especificado en el RFC 8945 + // let error_msg = DnsMessage::format_error_msg(); + // return error_msg; + // } + // + //} //Verificación de los tiempos de emisión y recepción + fudge del mensaje From 692889c1a2f6ad96987b12f459279dab1b44dea9 Mon Sep 17 00:00:00 2001 From: joalopez Date: Fri, 17 May 2024 15:23:06 -0400 Subject: [PATCH 009/124] CHORE: refactoring of check existing tsig rr in ar --- src/tsig.rs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 1f0a09c8..de118594 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -84,7 +84,9 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); match alg_name { + TsigAlgorithm::HmacSha1 => { + let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&new_query_message.to_bytes()[..]); let result = hasher.result(); @@ -130,27 +132,43 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud } //TODO: terminar función keycheck -fn check_key(alg_name: String,key_in_rr:String,key: &[u8])->Bool{ +fn check_key(alg_name: String,key_in_rr:String,key: &[u8])-> bool { let mut answer = true; - return answer + answer +} + +fn check_exists_tsig_rr(add_rec: &Vec) -> bool { + let filtered_tsig:Vec<_> = add_rec.iter() + .filter(|tsig| + if let Rdata::TSIG(data) = tsig.get_rdata() {true} + else {false}).collect(); + + let islast = if let Rdata::TSIG(data) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; + ! filtered_tsig.len()==0 } #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key: &[u8]) -> DnsMessage { +fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> DnsMessage { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); - let time =SystemTime::now().duration_since(UNIX_EPOCH).expect("no time").as_secs(); + + //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr - let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {false} else {true}; - if filtered_tsig.len()==0 { + // let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); + // let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {false} else {true}; + // if filtered_tsig.len()==0 { + // let error_msg = DnsMessage::format_error_msg(); + // return error_msg; + // } + if !check_exists_tsig_rr(&addit) { let error_msg = DnsMessage::format_error_msg(); return error_msg; } + //Debe haber un único tsig //Tsig RR debe ser el último en la sección adicional, y debe ser único if filtered_tsig.len()>1 || islast { From 2945e6fbd5035d1c2390b75ae596f20a3b990cc5 Mon Sep 17 00:00:00 2001 From: joalopez Date: Fri, 17 May 2024 15:55:15 -0400 Subject: [PATCH 010/124] CHORE: refactorting to check that tsig rr is the last one and unique --- src/tsig.rs | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index de118594..31912ec0 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -134,23 +134,38 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud //TODO: terminar función keycheck fn check_key(alg_name: String,key_in_rr:String,key: &[u8])-> bool { let mut answer = true; - answer } +//RFC 8945 5.2 y 5.4 +//verificar que existen los resource records que corresponden a tsig +//vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr fn check_exists_tsig_rr(add_rec: &Vec) -> bool { let filtered_tsig:Vec<_> = add_rec.iter() .filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); + !(filtered_tsig.len()==0) +} + + +//Debe haber un único tsig +//Tsig RR debe ser el último en la sección adicional, y debe ser único2 +fn check_last_one_is_tsig(add_rec: &Vec) -> bool { + let filtered_tsig:Vec<_> = add_rec.iter() + .filter(|tsig| + if let Rdata::TSIG(data) = tsig.get_rdata() {true} + else {false}).collect(); + let islast = if let Rdata::TSIG(data) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; - ! filtered_tsig.len()==0 + + !(filtered_tsig.len()>1 || islast) } #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> DnsMessage { +fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> bool { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); @@ -158,22 +173,16 @@ fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> DnsMessage { //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr - // let filtered_tsig:Vec<_> = addit.iter().filter(|tsig| if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - // let islast = if let Rdata::TSIG(data) = addit[addit.len()-1].get_rdata() {false} else {true}; - // if filtered_tsig.len()==0 { - // let error_msg = DnsMessage::format_error_msg(); - // return error_msg; - // } - if !check_exists_tsig_rr(&addit) { - let error_msg = DnsMessage::format_error_msg(); - return error_msg; + if check_exists_tsig_rr(&addit) { + println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + return false; } //Debe haber un único tsig //Tsig RR debe ser el último en la sección adicional, y debe ser único - if filtered_tsig.len()>1 || islast { - let error_msg = DnsMessage::format_error_msg(); - return error_msg; + if check_last_one_is_tsig(&addit) { + println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + return false; } //sacar el último elemento del vector resource record, y disminuir elvalor de ARCOUNT @@ -197,8 +206,7 @@ fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> DnsMessage { let cond1 = check_key(name_alg,key_in_rr,key); if cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); - let error_msg = DnsMessage::format_error_msg(); - return error_msg; + return false; } //TODO: hacer los demas checkeos //let cond2 = check_mac(); From 51318697913bbd4ae9edaf2854a9757c433e5d09 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 16:04:33 -0400 Subject: [PATCH 011/124] Added enum: TSIG Error codes 16 to 18 --- src/tsig.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index 31912ec0..6ba07795 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -19,6 +19,12 @@ enum TsigAlgorithm { HmacSha1, HmacSha256, } +enum TsigErrorCode{ + BADSIG = 16, + BADDKEY = 17, + BADTIME = 18, + +} /* #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ From 8d906d74bc48bf0e41c31fad007ffb7900da9ab4 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 16:49:31 -0400 Subject: [PATCH 012/124] =?UTF-8?q?Terminado=20check=5Falg=5Fname,=20y=20a?= =?UTF-8?q?gregamos=20un=20par=C3=A1metro=20a=20process=5Ftsig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tsig.rs | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 31912ec0..aa205a5c 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -19,6 +19,7 @@ enum TsigAlgorithm { HmacSha1, HmacSha256, } + /* #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ @@ -132,9 +133,26 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud } //TODO: terminar función keycheck -fn check_key(alg_name: String,key_in_rr:String,key: &[u8])-> bool { - let mut answer = true; - answer +fn check_key(alg_name: String,key_in_rr:String,key_name:String,flag_check_alg:bool)-> bool { + let mut answer = true; + + if !key_in_rr.eq(&key_name) { + answer=false; + } + return answer +} + +//Verifica que el algoritmo esté disponible, y además esté implementado +fn check_alg_name(alg_name:String, alg_list: Vec<(String,bool)>) -> bool{ + let mut answer: bool = false; + for (name,available) in alg_list { + if name.eq(&alg_name){ + if available { + answer = true; + } + } + } + return answer } //RFC 8945 5.2 y 5.4 @@ -146,7 +164,7 @@ fn check_exists_tsig_rr(add_rec: &Vec) -> bool { if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - !(filtered_tsig.len()==0) + (filtered_tsig.len()==0) } @@ -160,12 +178,12 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { let islast = if let Rdata::TSIG(data) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; - !(filtered_tsig.len()>1 || islast) + (filtered_tsig.len()>1 || islast) } #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> bool { +fn process_tsig(msg: DnsMessage, key_name: String, time: u64, avalaible_algorihtm: Vec<(String, bool)>) -> bool { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); @@ -174,14 +192,14 @@ fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> bool { //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr if check_exists_tsig_rr(&addit) { - println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + println!("RCODE 1: FORMERR"); return false; } //Debe haber un único tsig //Tsig RR debe ser el último en la sección adicional, y debe ser único if check_last_one_is_tsig(&addit) { - println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + println!("RCODE 1: FORMERR"); return false; } @@ -203,7 +221,8 @@ fn process_tsig(msg: DnsMessage, key: &[u8], time: u64) -> bool { //RFC 8945 5.2.1 let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); let key_in_rr = rr_copy.get_name().get_name(); - let cond1 = check_key(name_alg,key_in_rr,key); + let flag = check_alg_name(name_alg,available_algorithm); + let cond1 = check_key(name_alg,key_in_rr,key_name,flag); if cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return false; From 8997866e4451658fb4c3348034aa7c10aa5ba746 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 17:00:40 -0400 Subject: [PATCH 013/124] refactor --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 42cf67d3..56801e1a 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -188,7 +188,7 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key_name: String, time: u64, avalaible_algorihtm: Vec<(String, bool)>) -> bool { +fn process_tsig(msg: DnsMessage, key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> bool { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); From 46a427e48463f59c64b52f10f3946fb098fd8782 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 17:02:43 -0400 Subject: [PATCH 014/124] add: finished check_key --- src/tsig.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 56801e1a..0bafd9cb 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -140,8 +140,7 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud //TODO: terminar función keycheck fn check_key(alg_name: String,key_in_rr:String,key_name:String,flag_check_alg:bool)-> bool { let mut answer = true; - - if !key_in_rr.eq(&key_name) { + if !key_in_rr.eq(&key_name) || flag_check_alg { answer=false; } return answer From 49bc7944c88457601caec0b95a6469112efea5e9 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 19:02:04 -0400 Subject: [PATCH 015/124] fix: haciendo refactor a check_mack fix: haciendo cambios a process_tsig --- src/tsig.rs | 94 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 41 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 0bafd9cb..8ebab771 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -25,6 +25,7 @@ enum TsigErrorCode{ BADTIME = 18, } + /* #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ @@ -137,8 +138,8 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud return signature; } -//TODO: terminar función keycheck -fn check_key(alg_name: String,key_in_rr:String,key_name:String,flag_check_alg:bool)-> bool { +//Revisa si el nombre de la llave es correcto +fn check_key(alg_name: &String,key_in_rr:String,key_name:String,flag_check_alg:bool)-> bool { let mut answer = true; if !key_in_rr.eq(&key_name) || flag_check_alg { answer=false; @@ -147,10 +148,10 @@ fn check_key(alg_name: String,key_in_rr:String,key_name:String,flag_check_alg:bo } //Verifica que el algoritmo esté disponible, y además esté implementado -fn check_alg_name(alg_name:String, alg_list: Vec<(String,bool)>) -> bool{ +fn check_alg_name(alg_name:&String, alg_list: Vec<(String,bool)>) -> bool{ let mut answer: bool = false; for (name,available) in alg_list { - if name.eq(&alg_name){ + if name.eq(alg_name){ if available { answer = true; } @@ -159,6 +160,16 @@ fn check_alg_name(alg_name:String, alg_list: Vec<(String,bool)>) -> bool{ return answer } +//Solo ve los largos por ahora +fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ + let mut answer: bool = false; + let contador = 0; + if mac.len()!=new_mac.len(){ + return answer + } + return answer +} + //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr @@ -168,7 +179,7 @@ fn check_exists_tsig_rr(add_rec: &Vec) -> bool { if let Rdata::TSIG(data) = tsig.get_rdata() {true} else {false}).collect(); - (filtered_tsig.len()==0) + filtered_tsig.len()==0 } @@ -182,16 +193,14 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { let islast = if let Rdata::TSIG(data) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; - (filtered_tsig.len()>1 || islast) + filtered_tsig.len()>1 || islast } #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: DnsMessage, key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> bool { +fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> bool { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); - - //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr @@ -219,23 +228,36 @@ fn process_tsig(msg: DnsMessage, key_name: String, time: u64, available_algorit } } let nuevo_len_arcount = addit.len() as u16; - let new_header = msg.get_header(); + let mut new_header = retmsg.get_header(); new_header.set_arcount(nuevo_len_arcount); - msg.set_header(new_header); + retmsg.set_header(new_header); //RFC 8945 5.2.1 let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); let key_in_rr = rr_copy.get_name().get_name(); - let flag = check_alg_name(name_alg,available_algorithm); - let cond1 = check_key(name_alg,key_in_rr,key_name,flag); - if cond1 { + let flag = check_alg_name(&name_alg,available_algorithm); + let cond1 = check_key(&name_alg,key_in_rr,key_name,flag); + if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return false; } - //TODO: hacer los demas checkeos - //let cond2 = check_mac(); + //RFC 8945 5.2.2 + retmsg.set_additional(addit); + let fudge = tsig_rr_copy.get_fudge(); + let time_signed = tsig_rr_copy.get_time_signed(); + let mac_received = tsig_rr_copy.get_mac(); + let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; + match name_alg.as_str() { + "HMACSHA1" => new_alg_name = TsigAlgorithm::HmacSha1, + "HMACSHA256" => new_alg_name = TsigAlgorithm::HmacSha256, + &_ => println!("not supported algorithm") + } + let new_mac = sign_tsig(retmsg, key, new_alg_name, fudge, time_signed); + + let cond2 = check_mac(new_mac, key, mac_received); + if !cond2 { + println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); + } //let cond3 = check_time_values(); - //let cond4 = check_truncation_policy(); - //let rdata = rr.get_rdata(); let mut time_signed_v = 0; let mut fudge = 0; @@ -280,35 +302,25 @@ fn process_tsig(msg: DnsMessage, key_name: String, time: u64, available_algorit error_msg.add_additionals(vec); //TODO: agregar log y añadir el error TSIG 18: BADTIME println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); - return error_msg + return false } - - retmsg.set_additional(vec![]); - let mut old_head = retmsg.get_header(); - old_head.set_arcount(0); - retmsg.set_header(old_head); let algorithm = TsigAlgorithm::HmacSha256; //TODO: extraer los siguientes valores del rdata del mensaje a verificar let msg_time= SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); let msg_fudge = 1000; - //se verifica la autenticidad de la firma - let digest = sign_tsig(retmsg.clone(), key, algorithm,msg_time as u16,msg_fudge); - let digest_string = &digest; - println!("El dig stirng es: {:#?}" , digest_string); - let binding = &digest; - let rdata = rr.get_rdata(); - match rdata { - Rdata::TSIG(tsigrdata) => { - for i in 0..32 { - if tsigrdata.get_mac()[i] != binding.clone()[i] { - panic!("Wrong signature!"); - } - } - }, - _ => {panic!("Bad request")} - } + //let rdata = rr.get_rdata(); + //match rdata { + // Rdata::TSIG(tsigrdata) => { + // for i in 0..32 { + // if tsigrdata.get_mac()[i] != binding.clone()[i] { + // panic!("Wrong signature!"); + // } + // } + // }, + // _ => {panic!("Bad request")} + //} - retmsg + true } From 597f23a6da0a3e7a0657e6793fb2a6be6f16b4c6 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 19:07:34 -0400 Subject: [PATCH 016/124] refact: finished check_mac --- src/tsig.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index 8ebab771..bc53ec19 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -167,6 +167,11 @@ fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ if mac.len()!=new_mac.len(){ return answer } + for elem in mac{ + if new_mac[contador]!=elem{ + return answer + } + } return answer } From 5c7d9334a84874f55d91ca979c2a94a9e4cd82c7 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 19:13:43 -0400 Subject: [PATCH 017/124] delete: unnecessary lines --- src/tsig.rs | 43 ++----------------------------------------- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index bc53ec19..75e28646 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -263,31 +263,8 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); } //let cond3 = check_time_values(); - //let rdata = rr.get_rdata(); - let mut time_signed_v = 0; - let mut fudge = 0; - //let mut rcode =0; - //let mut n_key = String::from(""); - ////Verificar rdata - //match rdata { - // Rdata::TSIG(data) =>{ - // time_signed_v = data.get_time_signed(); - // fudge = data.get_fudge(); - // rcode = data.get_error(); - // for elem in data.get_mac(){ - // n_key+=&elem.to_string(); - // } - // } - // _ => { - // println!("Bad resource record"); - // //TODO: ver/añadir el error del print anterior, especificado en el RFC 8945 - // let error_msg = DnsMessage::format_error_msg(); - // return error_msg; - // } - // - //} - - + let time_signed_v = 0; + let fudge = 0; //Verificación de los tiempos de emisión y recepción + fudge del mensaje // Según lo especificado en el RFC 8945 5.2.3 time Check and Error Handling if (time_signed_v-(fudge as u64))>time || time>(time_signed_v+(fudge as u64)) { @@ -309,22 +286,6 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); return false } - let algorithm = TsigAlgorithm::HmacSha256; - //TODO: extraer los siguientes valores del rdata del mensaje a verificar - let msg_time= SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); - let msg_fudge = 1000; - //let rdata = rr.get_rdata(); - //match rdata { - // Rdata::TSIG(tsigrdata) => { - // for i in 0..32 { - // if tsigrdata.get_mac()[i] != binding.clone()[i] { - // panic!("Wrong signature!"); - // } - // } - // }, - // _ => {panic!("Bad request")} - //} - true } From b320d40d812966d99527fccb0d04384e720bf91c Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 19:11:26 -0400 Subject: [PATCH 018/124] Added test: check_signed_tsig --- src/tsig.rs | 68 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 75e28646..eb894849 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -297,37 +297,49 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //Sección de tests unitarios -//ToDo: Crear bien un test que funcione #[test] -fn ptsig_test(){ - let my_key = b"1201102391287592dsjshno039U021Jg"; - let my_short_key = b"1201102391287592dsjs"; - let alg: TsigAlgorithm = TsigAlgorithm::HmacSha256; - let mut dns_example_msg = - DnsMessage::new_query_message( - DomainName::new_from_string("uchile.cl".to_string()), +fn check_signed_tsig() { + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 0; + let time_signed = 0; + let id = 6502; + let mut q = DnsMessage::new_query_message( + DomainName::new_from_str("uchile.cl"), Qtype::A, - Qclass::IN, - 0, + Qclass::ANY, + 0, false, - 1); - let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); - //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia - let _signature = sign_tsig(dns_example_msg.clone(), my_key, alg,1000,time ); - let _sha1signature = sign_tsig(dns_example_msg.clone(),my_short_key, TsigAlgorithm::HmacSha1,1000, time); - let signature = match str::from_utf8(&_signature){ - Ok(v) =>v, - Err(e) =>panic!("Invalid UTF-( sequence: {}",e) - }; - let sha1signature = match str::from_utf8(&_sha1signature){ - Ok(v) =>v, - Err(e) =>panic!("Invalid UTF-( sequence: {}",e) - }; - println!("SHA-256: {}",signature); - println!("SHA-1: {}",sha1signature); + id + ); + let q_for_mac = q.clone(); + + let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed); + let mut hasher = crypto_hmac::new(Sha1::new(), key); + hasher.input(&q_for_mac.to_bytes()[..]); - //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) - //let _processed_msg = process_tsig(dns_example_msg, my_key); + let result = hasher.result(); + let mac_to_cmp = result.code(); -} + let rr = q.get_additional().pop().expect("Should be a tsig"); + match rr.get_rdata() { + Rdata::TSIG(data) => { + assert_eq!(data.get_algorithm_name(), DomainName::new_from_str("hmac-sha1")); + assert_eq!(data.get_time_signed(), time_signed); + assert_eq!(data.get_fudge() , fudge); + assert_eq!(data.get_mac_size(), 20); + assert_eq!(data.get_original_id(), id); + assert_eq!(data.get_error(), 0); + assert_eq!(data.get_other_len(), 0); + assert!(data.get_other_data().is_empty()); + }, + _ =>{ + assert!(false); + } + } + println!("Comparando el mac"); + for i in 0..mac_to_cmp.len() { + assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); + } +} \ No newline at end of file From 1f55cc6b72af2d41709b99ff9e7c0e2d38de2692 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 19:14:57 -0400 Subject: [PATCH 019/124] Refactor: ptsig_test ->sign_test --- src/tsig.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index eb894849..3cac8ea9 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -297,6 +297,33 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //Sección de tests unitarios +//ToDo: Crear bien un test que funcione +#[test] +fn sign_test(){ + let my_key = b"1201102391287592dsjshno039U021Jg"; + let my_short_key = b"1201102391287592dsjs"; + let alg: TsigAlgorithm = TsigAlgorithm::HmacSha256; + let mut dns_example_msg = + DnsMessage::new_query_message( + DomainName::new_from_string("uchile.cl".to_string()), + Qtype::A, + Qclass::IN, + 0, + false, + 1); + let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); + //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia + let _signature = sign_tsig(dns_example_msg.clone(), my_key, alg,1000,time ); + let _sha1signature = sign_tsig(dns_example_msg.clone(),my_short_key, TsigAlgorithm::HmacSha1,1000, time); + println!("SHA-256: {:?}",_signature); + println!("SHA-1: {:?}",_sha1signature); + + + //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) + //let _processed_msg = process_tsig(dns_example_msg, my_key); + +} + #[test] fn check_signed_tsig() { let key = b"1234567890"; From 31e03e49a0e98ca830dcb15fba519ace329c9618 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 19:27:14 -0400 Subject: [PATCH 020/124] Adeed Chech_signed_tsig test --- src/tsig.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index 3cac8ea9..c3ef2fc4 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -324,6 +324,52 @@ fn sign_test(){ } +#[test] +fn check_signed_tsig() { + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 0; + let time_signed = 0; + let id = 6502; + let mut q = DnsMessage::new_query_message( + DomainName::new_from_str("uchile.cl"), + Qtype::A, + Qclass::ANY, + 0, + false, + id + ); + let q_for_mac = q.clone(); + + let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed); + + let mut hasher = crypto_hmac::new(Sha1::new(), key); + hasher.input(&q_for_mac.to_bytes()[..]); + + let result = hasher.result(); + let mac_to_cmp = result.code(); + + let rr = q.get_additional().pop().expect("Should be a tsig"); + match rr.get_rdata() { + Rdata::TSIG(data) => { + assert_eq!(data.get_algorithm_name(), DomainName::new_from_str("hmac-sha1")); + assert_eq!(data.get_time_signed(), time_signed); + assert_eq!(data.get_fudge() , fudge); + assert_eq!(data.get_mac_size(), 20); + assert_eq!(data.get_original_id(), id); + assert_eq!(data.get_error(), 0); + assert_eq!(data.get_other_len(), 0); + assert!(data.get_other_data().is_empty()); + }, + _ =>{ + assert!(false); + } + } + println!("Comparando el mac"); + for i in 0..mac_to_cmp.len() { + assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); + } +} #[test] fn check_signed_tsig() { let key = b"1234567890"; From 0a0b8af7e4b4cca0d675c4e0c206d53e81c32088 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 19:29:51 -0400 Subject: [PATCH 021/124] Deleted a rpeated test --- src/tsig.rs | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index c3ef2fc4..aa4d40e3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -370,49 +370,3 @@ fn check_signed_tsig() { assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); } } -#[test] -fn check_signed_tsig() { - let key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 0; - let time_signed = 0; - let id = 6502; - let mut q = DnsMessage::new_query_message( - DomainName::new_from_str("uchile.cl"), - Qtype::A, - Qclass::ANY, - 0, - false, - id - ); - let q_for_mac = q.clone(); - - let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed); - - let mut hasher = crypto_hmac::new(Sha1::new(), key); - hasher.input(&q_for_mac.to_bytes()[..]); - - let result = hasher.result(); - let mac_to_cmp = result.code(); - - let rr = q.get_additional().pop().expect("Should be a tsig"); - match rr.get_rdata() { - Rdata::TSIG(data) => { - assert_eq!(data.get_algorithm_name(), DomainName::new_from_str("hmac-sha1")); - assert_eq!(data.get_time_signed(), time_signed); - assert_eq!(data.get_fudge() , fudge); - assert_eq!(data.get_mac_size(), 20); - assert_eq!(data.get_original_id(), id); - assert_eq!(data.get_error(), 0); - assert_eq!(data.get_other_len(), 0); - assert!(data.get_other_data().is_empty()); - }, - _ =>{ - assert!(false); - } - } - println!("Comparando el mac"); - for i in 0..mac_to_cmp.len() { - assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); - } -} \ No newline at end of file From b2c6f6b0dac718e179ce0e163355b761f378ee3e Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Fri, 17 May 2024 19:34:36 -0400 Subject: [PATCH 022/124] add: check_time_values() refactor:process_tsig() --- src/tsig.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index aa4d40e3..25831cd5 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -160,7 +160,7 @@ fn check_alg_name(alg_name:&String, alg_list: Vec<(String,bool)>) -> bool{ return answer } -//Solo ve los largos por ahora +//Verifica que los mac sean iguales fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ let mut answer: bool = false; let contador = 0; @@ -175,6 +175,12 @@ fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ return answer } +//Verifica el error de la sección 5.2.3 +fn check_time_values() -> bool { + let mut answer = false; + return answer +} + //RFC 8945 5.2 y 5.4 //verificar que existen los resource records que corresponden a tsig //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr @@ -262,7 +268,10 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); } - //let cond3 = check_time_values(); + let cond3 = check_time_values(); + if !cond3 { + println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); + } let time_signed_v = 0; let fudge = 0; //Verificación de los tiempos de emisión y recepción + fudge del mensaje From a73a51fc983e8d609a58846ae20ee8b9374fbe58 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 17 May 2024 22:33:16 -0400 Subject: [PATCH 023/124] Added TSIG integration tests (WIP) --- tests/integration_test.rs | 57 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 17bcedbc..6746125d 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,5 +1,5 @@ use std::{net::IpAddr, str::FromStr}; -use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata, resource_record::ResourceRecord}}; +use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata, resource_record::ResourceRecord},tsig}; @@ -108,6 +108,61 @@ async fn no_resource_available() { println!("{:?}", response); assert!(response.is_err()); } +/* +///RFC 8945 TSIG tests +#[tokio::test] +async fn tsig_signature() { + let sock = UdpSocket::bind("127.0.0.1:8001").expect("Puerto ocupado"); + + let mut dns_query_message = + DnsMessage::new_query_message( + DomainName::new_from_string("uchile.cl".to_string()), + Qtype::A, + Qclass::IN, + 0, + false, + 1); + let signature = dns_rust::tsig::sign_tsig(); + let digest = keyed_hash(b"alalalalalalalalalalalalalalalal", &dns_query_message.to_bytes()[..]); + let digstr = digest.to_string(); + let x = format!("hmac-md5.sig-alg.reg.int.\n51921\n1234\n32\n{}\n1234\n0\n0", digstr); + + println!("El dig stirng es: {:#?}" , digstr); + let resource_record = TSigRdata::rr_from_master_file( + x.split_whitespace(), + 56, + "IN", + String::from("uchile.cl"), + String::from("uchile.cl")); + + let mut vec = vec![]; + + vec.push(resource_record); + + dns_query_message.add_additionals(vec); + + println!("{:#?}", dns_query_message); + + let buf = dns_query_message.to_bytes(); + let s = sock.send_to(&buf, "127.0.0.1:8001").unwrap(); + let response = query_response("example.com", "UDP", "MX").await; + + if let Ok(rrs) = response { + assert_eq!(rrs.len(), 1); + if let Rdata::MX(mxdata) = rrs[0].get_rdata() { + assert_eq!( + mxdata.get_exchange(), + DomainName::new_from_str("")); + assert_eq!( + mxdata.get_preference(), + 0 + ) + } else { + panic!("Record is not MX type"); + } + } +} +*/ From e89c137829fcd547d6e8751a254fce62e7731207 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 18:44:32 -0400 Subject: [PATCH 024/124] chore: finished check_time --- src/tsig.rs | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 25831cd5..06a1fc78 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -86,7 +86,7 @@ fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u // experimental #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { +fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); @@ -100,7 +100,7 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud let mac = result.code(); //Convertir los bytes brutos a una cadena hexadecimal let mac_size = 20; - let a_name = "Hmac-Sha1".to_uppercase(); + let a_name = "Hmac-Sha1".to_lowercase(); let a_name = DomainName::new_from_string(a_name); tsig_rd.set_algorithm_name(a_name); tsig_rd.set_mac_size(mac_size); @@ -116,7 +116,7 @@ fn sign_tsig(mut query_msg: DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fud let mac = result.code(); //Convertir los bytes brutos a una cadena hexadecimal let mac_size = 32; - let a_name = "Hmac-Sha256".to_uppercase(); + let a_name = "Hmac-Sha256".to_lowercase(); let a_name = DomainName::new_from_string(a_name); tsig_rd.set_algorithm_name(a_name); tsig_rd.set_mac_size(mac_size); @@ -176,9 +176,8 @@ fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ } //Verifica el error de la sección 5.2.3 -fn check_time_values() -> bool { - let mut answer = false; - return answer +fn check_time_values(mytime: u64,fudge: u16, time: u64) -> bool { + time - (fudge as u64) > mytime || mytime > (time+(fudge as u64)) } //RFC 8945 5.2 y 5.4 @@ -258,17 +257,18 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let mac_received = tsig_rr_copy.get_mac(); let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; match name_alg.as_str() { - "HMACSHA1" => new_alg_name = TsigAlgorithm::HmacSha1, - "HMACSHA256" => new_alg_name = TsigAlgorithm::HmacSha256, + "hmacsha1" => new_alg_name = TsigAlgorithm::HmacSha1, + "hmacsha256" => new_alg_name = TsigAlgorithm::HmacSha256, &_ => println!("not supported algorithm") } - let new_mac = sign_tsig(retmsg, key, new_alg_name, fudge, time_signed); + let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed); let cond2 = check_mac(new_mac, key, mac_received); if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); } - let cond3 = check_time_values(); + let mytime = SystemTime::now().duration_since(UNIX_EPOCH).expect("no debería fallar el tiempo"); + let cond3 = check_time_values(mytime.as_secs() as u64,fudge,time_signed); if !cond3 { println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); } @@ -276,7 +276,7 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let fudge = 0; //Verificación de los tiempos de emisión y recepción + fudge del mensaje // Según lo especificado en el RFC 8945 5.2.3 time Check and Error Handling - if (time_signed_v-(fudge as u64))>time || time>(time_signed_v+(fudge as u64)) { + { let mut error_msg = DnsMessage::format_error_msg(); error_msg.get_header().set_rcode(9); let str_whitespaces = "l\n0\n0\n0\n0\n0\n18\n0"; @@ -307,31 +307,6 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //Sección de tests unitarios //ToDo: Crear bien un test que funcione -#[test] -fn sign_test(){ - let my_key = b"1201102391287592dsjshno039U021Jg"; - let my_short_key = b"1201102391287592dsjs"; - let alg: TsigAlgorithm = TsigAlgorithm::HmacSha256; - let mut dns_example_msg = - DnsMessage::new_query_message( - DomainName::new_from_string("uchile.cl".to_string()), - Qtype::A, - Qclass::IN, - 0, - false, - 1); - let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("no existo").as_secs(); - //prueba de la firma. sign_msg calcula la firma, la añade al resource record del mensaje y retorna una copia - let _signature = sign_tsig(dns_example_msg.clone(), my_key, alg,1000,time ); - let _sha1signature = sign_tsig(dns_example_msg.clone(),my_short_key, TsigAlgorithm::HmacSha1,1000, time); - println!("SHA-256: {:?}",_signature); - println!("SHA-1: {:?}",_sha1signature); - - - //prueba de process_tsig (la idea es usar la firma anterior, añadirla a dns_example_msg y verificarla con my_key) - //let _processed_msg = process_tsig(dns_example_msg, my_key); - -} #[test] fn check_signed_tsig() { From 1274ffa11c4df38833cc9eded81cc2f71fddfeb8 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 19:52:27 -0400 Subject: [PATCH 025/124] add: new test for process_tsig --- src/tsig.rs | 61 ++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 06a1fc78..916389aa 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -20,9 +20,11 @@ enum TsigAlgorithm { HmacSha256, } enum TsigErrorCode{ + NOERR = 0, BADSIG = 16, - BADDKEY = 17, + BADKEY = 17, BADTIME = 18, + FORMERR = 1, } @@ -208,7 +210,7 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> bool { +fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> (bool, TsigErrorCode) { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); //RFC 8945 5.2 y 5.4 @@ -216,14 +218,14 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr if check_exists_tsig_rr(&addit) { println!("RCODE 1: FORMERR"); - return false; + return (false, TsigErrorCode::FORMERR); } //Debe haber un único tsig //Tsig RR debe ser el último en la sección adicional, y debe ser único if check_last_one_is_tsig(&addit) { println!("RCODE 1: FORMERR"); - return false; + return (false, TsigErrorCode::FORMERR); } //sacar el último elemento del vector resource record, y disminuir elvalor de ARCOUNT @@ -248,7 +250,7 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let cond1 = check_key(&name_alg,key_in_rr,key_name,flag); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); - return false; + return (false, TsigErrorCode::BADKEY); } //RFC 8945 5.2.2 retmsg.set_additional(addit); @@ -266,36 +268,15 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let cond2 = check_mac(new_mac, key, mac_received); if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); + return (false, TsigErrorCode::BADSIG) } - let mytime = SystemTime::now().duration_since(UNIX_EPOCH).expect("no debería fallar el tiempo"); - let cond3 = check_time_values(mytime.as_secs() as u64,fudge,time_signed); + //let mytime = SystemTime::now().duration_since(UNIX_EPOCH).expect("no debería fallar el tiempo"); + let cond3 = check_time_values(time, fudge, time_signed); if !cond3 { println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); + return (false, TsigErrorCode::BADTIME) } - let time_signed_v = 0; - let fudge = 0; - //Verificación de los tiempos de emisión y recepción + fudge del mensaje - // Según lo especificado en el RFC 8945 5.2.3 time Check and Error Handling - { - let mut error_msg = DnsMessage::format_error_msg(); - error_msg.get_header().set_rcode(9); - let str_whitespaces = "l\n0\n0\n0\n0\n0\n18\n0"; - let resource_record = TSigRdata::rr_from_master_file( - str_whitespaces.split_whitespace(), - 56, - "IN", - String::from("uchile.cl"), - String::from("uchile.cl"), - ); - //TODO: agregar un 6 al campo Other Data de TSig Rdata - let mut vec = vec![]; - vec.push(resource_record); - error_msg.add_additionals(vec); - //TODO: agregar log y añadir el error TSIG 18: BADTIME - println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); - return false - } - true + (true, TsigErrorCode::NOERR) } @@ -308,6 +289,24 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //Sección de tests unitarios //ToDo: Crear bien un test que funcione +#[test] +fn check_process_tsig() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmacsha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(answer); + assert_eq!(error,TsigErrorCode::NOERR); +} #[test] fn check_signed_tsig() { let key = b"1234567890"; From 4c674c79b180372d22a2c72007173eb25e178444 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 19:53:17 -0400 Subject: [PATCH 026/124] fix: added PartialEq to tsigerrorcode --- src/tsig.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsig.rs b/src/tsig.rs index 916389aa..0821ec38 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -19,6 +19,7 @@ enum TsigAlgorithm { HmacSha1, HmacSha256, } +#[derive(PartialEq)] enum TsigErrorCode{ NOERR = 0, BADSIG = 16, From 7387202ad80d2abc0924fc9fc0dc6c37ddf83e32 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 19:54:17 -0400 Subject: [PATCH 027/124] fix: added debug to tsigcodeerror --- src/tsig.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsig.rs b/src/tsig.rs index 0821ec38..8b6f9295 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -20,6 +20,7 @@ enum TsigAlgorithm { HmacSha256, } #[derive(PartialEq)] +#[derive(Debug)] enum TsigErrorCode{ NOERR = 0, BADSIG = 16, From 880ac475aa147c3c754de563e9f8f910ab7d1ff1 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 20:13:52 -0400 Subject: [PATCH 028/124] fix: check_key didn't work as expected --- src/tsig.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 8b6f9295..2e1245c8 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -143,12 +143,8 @@ fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fu } //Revisa si el nombre de la llave es correcto -fn check_key(alg_name: &String,key_in_rr:String,key_name:String,flag_check_alg:bool)-> bool { - let mut answer = true; - if !key_in_rr.eq(&key_name) || flag_check_alg { - answer=false; - } - return answer +fn check_key(alg_name: &String,key_in_rr:String, key_name:String)-> bool { + !key_in_rr.eq(&key_name) } //Verifica que el algoritmo esté disponible, y además esté implementado @@ -249,7 +245,11 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); let key_in_rr = rr_copy.get_name().get_name(); let flag = check_alg_name(&name_alg,available_algorithm); - let cond1 = check_key(&name_alg,key_in_rr,key_name,flag); + if !flag { + println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + return (false, TsigErrorCode::BADKEY); + } + let cond1 = check_key(&name_alg,key_in_rr,key_name); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return (false, TsigErrorCode::BADKEY); @@ -261,8 +261,8 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa let mac_received = tsig_rr_copy.get_mac(); let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; match name_alg.as_str() { - "hmacsha1" => new_alg_name = TsigAlgorithm::HmacSha1, - "hmacsha256" => new_alg_name = TsigAlgorithm::HmacSha256, + "hmac-sha1" => new_alg_name = TsigAlgorithm::HmacSha1, + "hmac-sha256" => new_alg_name = TsigAlgorithm::HmacSha256, &_ => println!("not supported algorithm") } let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed); @@ -304,8 +304,10 @@ fn check_process_tsig() { //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmacsha256"),true)); + lista.push((String::from("hmac-sha256"),true)); + assert!(check_alg_name(&"hmac-sha256".to_string(), lista.clone())); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + println!("{} y {:?}",answer, error); assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); } From 13fffead72d91cfc2bb5ec6256251224649be982 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Sun, 19 May 2024 20:49:58 -0400 Subject: [PATCH 029/124] fix: bugs in process_tsig, check_alg_name, key --- src/tsig.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 2e1245c8..bdd9d182 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -143,8 +143,8 @@ fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fu } //Revisa si el nombre de la llave es correcto -fn check_key(alg_name: &String,key_in_rr:String, key_name:String)-> bool { - !key_in_rr.eq(&key_name) +fn check_key(key_in_rr:String, key_name:String)-> bool { + key_in_rr.eq(&key_name) } //Verifica que el algoritmo esté disponible, y además esté implementado @@ -161,23 +161,23 @@ fn check_alg_name(alg_name:&String, alg_list: Vec<(String,bool)>) -> bool{ } //Verifica que los mac sean iguales -fn check_mac(mut new_mac: Vec, key: &[u8], mac: Vec) -> bool{ - let mut answer: bool = false; - let contador = 0; +fn check_mac(new_mac: Vec, mac: Vec) -> bool{ if mac.len()!=new_mac.len(){ - return answer + return false } - for elem in mac{ - if new_mac[contador]!=elem{ - return answer + for i in 0..mac.len(){ + if new_mac[i]!=mac[i]{ + return false } } - return answer + true } //Verifica el error de la sección 5.2.3 fn check_time_values(mytime: u64,fudge: u16, time: u64) -> bool { - time - (fudge as u64) > mytime || mytime > (time+(fudge as u64)) + let part1 = (time - (fudge as u64)) < mytime; + let part2 = mytime < (time+(fudge as u64)); + part1 && part2 } //RFC 8945 5.2 y 5.4 @@ -249,7 +249,7 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return (false, TsigErrorCode::BADKEY); } - let cond1 = check_key(&name_alg,key_in_rr,key_name); + let cond1 = check_key(key_in_rr,key_name); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return (false, TsigErrorCode::BADKEY); @@ -267,7 +267,7 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa } let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed); - let cond2 = check_mac(new_mac, key, mac_received); + let cond2 = check_mac(new_mac, mac_received); if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); return (false, TsigErrorCode::BADSIG) @@ -307,7 +307,6 @@ fn check_process_tsig() { lista.push((String::from("hmac-sha256"),true)); assert!(check_alg_name(&"hmac-sha256".to_string(), lista.clone())); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); - println!("{} y {:?}",answer, error); assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); } From 0d23d0998c2047bd8e22b1733888ba15861f0fe6 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 10:07:49 -0400 Subject: [PATCH 030/124] add: new test for process_tsig --- src/tsig.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index bdd9d182..cd1808cc 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -291,6 +291,42 @@ fn tsig_proccesing_answer(answer_msg:DnsMessage){ //Sección de tests unitarios //ToDo: Crear bien un test que funcione +#[test] + +fn check_process_tsig_exists() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + let server_key = b"1234567890"; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::FORMERR); +} + +#[test] +fn check_process_tsig_exists2() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let alg_name2 = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + sign_tsig(&mut response, server_key, alg_name2, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::FORMERR); +} + #[test] fn check_process_tsig() { //Server process @@ -305,7 +341,6 @@ fn check_process_tsig() { let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha256"),true)); - assert!(check_alg_name(&"hmac-sha256".to_string(), lista.clone())); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); From 333336681040d371c278f50b0c1524ca4e3b960e Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 10:24:01 -0400 Subject: [PATCH 031/124] add: test for process_tsig --- src/tsig.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index cd1808cc..70702bd2 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -11,7 +11,7 @@ use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; use std::str; - +use crate::message::rdata::a_rdata::ARdata; type HmacSha256 = Hmac; //TODO: usar arreglar el funcionamiento del enum en sign_msg @@ -279,6 +279,7 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa return (false, TsigErrorCode::BADTIME) } (true, TsigErrorCode::NOERR) + } @@ -324,9 +325,35 @@ fn check_process_tsig_exists2() { lista.push((String::from("hmac-sha256"),true)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); assert!(!answer); - assert_eq!(error,TsigErrorCode::FORMERR); + assert_eq!(error, TsigErrorCode::FORMERR); } +#[test] +fn check_process_tsig_exists3(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + //necesito agregar algo más en el additional + let mut new_additional = Vec::::new(); + let a_rdata5 = Rdata::A(ARdata::new()); + let rr5 = ResourceRecord::new(a_rdata5); + new_additional.push(rr5); + response.add_additionals(new_additional); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error, TsigErrorCode::FORMERR); +} + + #[test] fn check_process_tsig() { //Server process From 575c37906796b2f5b2e92a0fcbdd057a5b1ef6f9 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 10:41:16 -0400 Subject: [PATCH 032/124] add: test for process tsig --- src/tsig.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index 70702bd2..58a124f6 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -352,6 +352,25 @@ fn check_process_tsig_exists3(){ assert!(!answer); assert_eq!(error, TsigErrorCode::FORMERR); } +#[test] +fn check_process_tsig_alg_name(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //supongamos que para este test, no está hmac-sha256 en la lista de algoritmos disponibles + lista.push((String::from("hmac-sha1"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); +} #[test] From 7d9d03eb5543d2e1a703b91f9e9a55ca2cd3b6a3 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 10:57:37 -0400 Subject: [PATCH 033/124] add: test for process tsig --- src/tsig.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 58a124f6..65f29bef 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -353,7 +353,7 @@ fn check_process_tsig_exists3(){ assert_eq!(error, TsigErrorCode::FORMERR); } #[test] -fn check_process_tsig_alg_name(){ +fn check_process_tsig_alg_name() { //Server process let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); let server_key = b"1234567890"; @@ -365,14 +365,69 @@ fn check_process_tsig_alg_name(){ //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; - //supongamos que para este test, no está hmac-sha256 en la lista de algoritmos disponibles + //suponemos que hmacsha256 no está disponible lista.push((String::from("hmac-sha1"),true)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); assert!(!answer); assert_eq!(error,TsigErrorCode::BADKEY); } +#[test] +fn check_process_tsig_alg_name2() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),false)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); +} +#[test] +fn check_process_tsig_key(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "different".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),false)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); +} - +#[test] +fn check_process_tsig_badsign(){ + // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN + let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let key = b"1234567890"; + let key_name:String = "".to_string(); + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 1000; + let time_signed = 210000000; + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha1"),false)); + let (answer,error) = process_tsig(&mut msg1, key, key_name, time_signed,lista); + assert_eq!(error,TsigErrorCode::BADSIG) +} +#[test] +fn check_proces_tsig_badtime(){ + +} #[test] fn check_process_tsig() { //Server process From 36146d1f04d28407a89bdf6f407d0182a878b609 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 10:58:31 -0400 Subject: [PATCH 034/124] add: test for process tsig --- src/tsig.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 65f29bef..20fdba24 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -410,24 +410,6 @@ fn check_process_tsig_key(){ assert_eq!(error,TsigErrorCode::BADKEY); } -#[test] -fn check_process_tsig_badsign(){ - // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN - let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let key = b"1234567890"; - let key_name:String = "".to_string(); - let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 1000; - let time_signed = 210000000; - let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmac-sha1"),false)); - let (answer,error) = process_tsig(&mut msg1, key, key_name, time_signed,lista); - assert_eq!(error,TsigErrorCode::BADSIG) -} -#[test] -fn check_proces_tsig_badtime(){ - -} #[test] fn check_process_tsig() { //Server process From 11ee7da706d9107c8a4a847f630827cb8486780a Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 11:17:20 -0400 Subject: [PATCH 035/124] add: new test for process tsig bad time --- src/tsig.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tsig.rs b/src/tsig.rs index 20fdba24..d4b33c53 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -410,6 +410,25 @@ fn check_process_tsig_key(){ assert_eq!(error,TsigErrorCode::BADKEY); } +#[test] +fn check_proces_tsig_badtime(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 22010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADTIME); +} #[test] fn check_process_tsig() { //Server process From e1104900671506089cdab3a8901399f8dc8ff296 Mon Sep 17 00:00:00 2001 From: CristobalTortugauwu Date: Mon, 20 May 2024 11:30:59 -0400 Subject: [PATCH 036/124] add: test for tsig bad sign --- src/tsig.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index d4b33c53..161598f3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -409,7 +409,26 @@ fn check_process_tsig_key(){ assert!(!answer); assert_eq!(error,TsigErrorCode::BADKEY); } - +//TODO: completar este test, hay cosas que faltan por implementar +#[test] +fn check_process_tsig_badsign(){ + // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN + let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let key = b"1234567890"; + let key_name:String = "".to_string(); + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 1000; + let time_signed = 210000000; + // se firma el mensaje con algoritmo SHA-1 + sign_tsig(& mut msg1, key, alg_name, fudge, time_signed); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha1"),true)); + lista.push((String::from("hmac-sha256"),true)); + // se verifica que el mensaje está firmado, pero se usa otra key + let key2 = b"12345678909"; + let (answer,error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista); + assert_eq!(error,TsigErrorCode::BADSIG); +} #[test] fn check_proces_tsig_badtime(){ //Server process From b6a3a9d6e5df949d709c191eb16555f81379495e Mon Sep 17 00:00:00 2001 From: Carlo Date: Mon, 20 May 2024 12:03:09 -0400 Subject: [PATCH 037/124] Added dnssec initial modules --- src/dnssec.rs | 4 ++++ src/dnssec/dnssec_encryption.rs | 1 + src/lib.rs | 1 + 3 files changed, 6 insertions(+) create mode 100644 src/dnssec.rs create mode 100644 src/dnssec/dnssec_encryption.rs diff --git a/src/dnssec.rs b/src/dnssec.rs new file mode 100644 index 00000000..256b2afa --- /dev/null +++ b/src/dnssec.rs @@ -0,0 +1,4 @@ +pub mod dnssec_encryption; + +use crate::message::resource_record::{FromBytes, ToBytes}; +use crate::tsig; \ No newline at end of file diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs new file mode 100644 index 00000000..0020b9af --- /dev/null +++ b/src/dnssec/dnssec_encryption.rs @@ -0,0 +1 @@ +use crypto; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index bd0e9fa2..4420153c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub mod async_resolver; pub mod utils; pub mod truncated_dns_message; pub mod tsig; +pub mod dnssec; From a5e9d472d568fe27e8c62b581da2b6a12b138b34 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 18:10:38 -0400 Subject: [PATCH 038/124] ADD: create_opt_rr for pseudo-rr OPT --- src/dnssec.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/dnssec.rs b/src/dnssec.rs index 256b2afa..9b5c9777 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,4 +1,40 @@ pub mod dnssec_encryption; -use crate::message::resource_record::{FromBytes, ToBytes}; -use crate::tsig; \ No newline at end of file + +use crate::domain_name::DomainName; +use crate::message::class_qclass::Qclass; +use crate::message::DnsMessage; +use crate::message::rdata::opt_rdata::OptRdata; +use crate::message::rdata::Rdata; +use crate::message::resource_record::{FromBytes, ResourceRecord, ToBytes}; +use crate::message::type_qtype::Qtype; + + +/* +The mechanism chosen for the explicit notification of the ability of +the client to accept (if not understand) DNSSEC security RRs is using +the most significant bit of the Z field on the EDNS0 OPT header in +the query. This bit is referred to as the "DNSSEC OK" (DO) bit. In +the context of the EDNS0 OPT meta-RR, the DO bit is the first bit of +the third and fourth bytes of the "extended RCODE and flags" portion +of the EDNS0 OPT meta-RR, structured as follows: + + +0 (MSB) +1 (LSB) + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 0: | EXTENDED-RCODE | VERSION | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 2: |DO| Z | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +*/ +// [0x12, 0x0, 0x80, 0x0] +fn create_opt_rr(e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { + let opt_rdata = OptRdata::new(); + let rdata = Rdata::OPT(opt_rdata); + let mut rr = ResourceRecord::new(rdata); + + let do_val: u16 = if do_bit {0x8000} else {0x0}; + let ttl: u32 = (e_rcode as u32) << 24 | (version as u32) << 16| (do_val as u32); + rr.set_ttl(ttl); + println!("EL ttl es: {:#05x?}", ttl); + rr +} From 93a2e493e61bd6e34800f8806ac8d314d9fe84d9 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 18:11:19 -0400 Subject: [PATCH 039/124] CHORE: added a function to visualize OPT rr --- src/dnssec.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dnssec.rs b/src/dnssec.rs index 9b5c9777..e0dfb92e 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -38,3 +38,12 @@ fn create_opt_rr(e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { println!("EL ttl es: {:#05x?}", ttl); rr } + +fn read_opt_rr(opt_rr: ResourceRecord) -> String { + let data = opt_rr.get_ttl().to_be_bytes(); + let (e_rcode, version) = (data[0], data[1]); + let z = u16::from_be_bytes([data[2], data[3]]); + + let do_bit = (z & 0x8000) > 0; + format!("OPT PSEUDO-RR\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") +} From 752b519cf9048ae7883d65988a42513ae371b4ce Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 18:12:09 -0400 Subject: [PATCH 040/124] ADD: function to create dns message with dnssec --- src/dnssec.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/dnssec.rs b/src/dnssec.rs index e0dfb92e..22b7a1a3 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -47,3 +47,15 @@ fn read_opt_rr(opt_rr: ResourceRecord) -> String { let do_bit = (z & 0x8000) > 0; format!("OPT PSEUDO-RR\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") } + +/* + A security-aware resolver MUST include an EDNS ([RFC2671]) OPT + pseudo-RR with the DO ([RFC3225]) bit set when sending queries. +*/ +fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { + // We create a opt rr with the do bit set to 1 + let rr = create_opt_rr(34, 2, false); + let vec = vec![rr]; + msg.add_additionals(vec); + msg +} \ No newline at end of file From 18653fef625b108e20b271d967d5d480b3cfaea4 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 18:13:09 -0400 Subject: [PATCH 041/124] CHORE: tests for visualizing dnssec opt rr --- src/dnssec.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/dnssec.rs b/src/dnssec.rs index 22b7a1a3..60f3b755 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -58,4 +58,19 @@ fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { let vec = vec![rr]; msg.add_additionals(vec); msg +} + +#[test] +fn see_dnssec_message() { + let mut query = DnsMessage::new_query_message( + DomainName::new_from_str("example.com"), + Qtype::A, + Qclass::ANY, + 1, + true, + 2000 + ); + let query= create_dns_message_with_dnssec(query); + println!("{:#?}", query); + println!("{}", read_opt_rr(query.get_additional().pop().unwrap())); } \ No newline at end of file From 59f2060705ca809edaed80b8d08147fe670cea02 Mon Sep 17 00:00:00 2001 From: Carlo Date: Tue, 21 May 2024 19:42:27 -0400 Subject: [PATCH 042/124] Refactor: Limpieza de comentarios --- src/tsig.rs | 59 ----------------------------------------------------- 1 file changed, 59 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 161598f3..adb86b44 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -30,65 +30,6 @@ enum TsigErrorCode{ } -/* -#[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -fn sign_msg_old(mut query_msg:DnsMessage,key:&[u8], alg_name:TsigAlgorithm)->&[u8]{ - let mut dig_string:&str; - let mut new_query_message = query_msg.clone(); - let mut mac_len:&str; - let mut a_name: &str; - let placeholder_hex: String; - let mut additional = query_msg.get_additional(); - //TODO: cambiar el match pattern - match alg_name { - TsigAlgorithm::HmacSha1 => { - let mut hasher = crypto_hmac::new(Sha1::new(), key); - hasher.input(&new_query_message.to_bytes()[..]); - let result = hasher.result(); - let placeholder = result.code(); - //Convertir los bytes brutos a una cadena hexadecimal - placeholder_hex = placeholder.iter().map(|b| format!("{:02x}", b)).collect(); - dig_string = &placeholder_hex; - mac_len = "20"; - a_name = "Hmac-Sha1"; - }, - TsigAlgorithm::HmacSha256 => { - let mut hasher = HmacSha256::new_from_slice(key).expect("HMAC algoritms can take keys of any size"); - hasher.update(&new_query_message.to_bytes()[..]); - let result = hasher.finalize(); - - let code_bytes = result.into_bytes(); - placeholder_hex = hex::encode(code_bytes); - dig_string = &placeholder_hex; - mac_len = "32"; - a_name = "Hmac-Sha256"; - - }, - _ => {panic!("Error: Invalid algorithm")}, - } - - //TODO: agregar los demas valores al dig_string !! Yo creo que deben llegar como argumentos - let mut dig_string: String = format!("{}.\n51921\n1234\n{}\n{}\n1234\n0\n0",a_name, mac_len, dig_string); - - //se modifica el resource record para añadir el hmac - let mut rr = additional.pop().expect("Empty Resource Record!"); - let mut rdata:Rdata= rr.get_rdata(); - match rdata { - Rdata::TSIG(mut data) =>{ - let mut mac: Vec =data.to_bytes(); - data.set_mac(mac); - } - _ => { - println!("Error: no valid rdata found!"); - } - } - let mut vec = vec![]; - vec.push(rr); - query_msg.add_additionals(vec); - return dig_string.as_bytes(); -} */ - -// experimental #[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); From 9ad4acdd50bc76ef6a9f720ea7420f6deac04729 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 20:07:10 -0400 Subject: [PATCH 043/124] FIX: fixed test msg for tsig to_bytes test --- src/message/rdata/tsig_rdata.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/message/rdata/tsig_rdata.rs b/src/message/rdata/tsig_rdata.rs index af5e7c9b..abd5f8ec 100644 --- a/src/message/rdata/tsig_rdata.rs +++ b/src/message/rdata/tsig_rdata.rs @@ -577,11 +577,33 @@ mod tsig_rdata_test { let bytes_to_test = tsig_rdata.to_bytes(); let bytes = vec![ - 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, - 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, - 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0x5B, 0xCD, 0x15, 0x4, 0xD2, 0x0, 0x4, 0xA1, 0xB2, 0xC3, 0xD4, - 0x4, 0xD2, 0x0, 0x0, 0x0, 0x0 + //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 0 + 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, + 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, + 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, + + //this is the time signed 123456789 == 0x75bcd15 + 0x0, 0x0, 0x7, 0x5B, 0xCD, 0x15, + + // this the fudge 1234 + 0x4, 0xD2, + + // this is the macsize + 0x0, 0x4, + + // this is the mac + 0xA1, 0xB2, 0xC3, 0xD4, + + // this is the original id + 0x4, 0xD2, + + // this is the error + 0x0, 0x0, + + // this is the other len + 0x0, 0x0 + + // No other data, so empty! ]; for i in 0..bytes.len() { From f54f8c24ac51fbcce226013c2a8c7b81bc64a9eb Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 20:11:12 -0400 Subject: [PATCH 044/124] CHORE: comments for clarity in tests tsig --- src/message/rdata/tsig_rdata.rs | 46 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/message/rdata/tsig_rdata.rs b/src/message/rdata/tsig_rdata.rs index abd5f8ec..0e0b310a 100644 --- a/src/message/rdata/tsig_rdata.rs +++ b/src/message/rdata/tsig_rdata.rs @@ -577,7 +577,7 @@ mod tsig_rdata_test { let bytes_to_test = tsig_rdata.to_bytes(); let bytes = vec![ - //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 0 + //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 00 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, @@ -588,22 +588,22 @@ mod tsig_rdata_test { // this the fudge 1234 0x4, 0xD2, - // this is the macsize + // this is the macsize = 4 0x0, 0x4, - // this is the mac + // this is the mac = [0xA1, 0xB2, 0xC3, 0xD4] 0xA1, 0xB2, 0xC3, 0xD4, - // this is the original id + // this is the original id = 1234 0x4, 0xD2, - // this is the error + // this is the error = 0 0x0, 0x0, - // this is the other len + // this is the other len = 0 0x0, 0x0 - // No other data, so empty! + // No other data, so its empty! ]; for i in 0..bytes.len() { @@ -614,11 +614,33 @@ mod tsig_rdata_test { #[test] fn from_bytes_test(){ let bytes = vec![ - 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, - 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, - 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0x5B, 0xCD, 0x15, 0x4, 0xD2, 0x0, 0x4, 0xA1, 0xB2, 0xC3, 0xD4, - 0x4, 0xD2, 0x0, 0x0, 0x0, 0x0 + //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 00 + 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, + 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, + 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, + + //this is the time signed 123456789 == 0x75bcd15 + 0x0, 0x0, 0x7, 0x5B, 0xCD, 0x15, + + // this the fudge 1234 + 0x4, 0xD2, + + // this is the macsize = 4 + 0x0, 0x4, + + // this is the mac = [0xA1, 0xB2, 0xC3, 0xD4] + 0xA1, 0xB2, 0xC3, 0xD4, + + // this is the original id = 1234 + 0x4, 0xD2, + + // this is the error = 0 + 0x0, 0x0, + + // this is the other len = 0 + 0x0, 0x0 + + // No other data, so its empty! ]; let tsig_rdata_result = TSigRdata::from_bytes(&bytes, &bytes); From 0a6402006156cd77ac85bb42802fb6115749d8a3 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 20:15:03 -0400 Subject: [PATCH 045/124] FIX: tsig from_bytes shifted byte in slice array --- src/message/rdata/tsig_rdata.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/message/rdata/tsig_rdata.rs b/src/message/rdata/tsig_rdata.rs index 0e0b310a..1834c43c 100644 --- a/src/message/rdata/tsig_rdata.rs +++ b/src/message/rdata/tsig_rdata.rs @@ -144,19 +144,19 @@ impl FromBytes> for TSigRdata{ tsig_rdata.set_algorithm_name(algorithm_name); - tsig_rdata.set_time_signed_from_bytes(&bytes_without_algorithm_name[1..7]); + tsig_rdata.set_time_signed_from_bytes(&bytes_without_algorithm_name[0..6]); - tsig_rdata.set_fudge_from_bytes(&bytes_without_algorithm_name[7..9]); + tsig_rdata.set_fudge_from_bytes(&bytes_without_algorithm_name[6..8]); - tsig_rdata.set_mac_size_from_bytes(&bytes_without_algorithm_name[9..11]); + tsig_rdata.set_mac_size_from_bytes(&bytes_without_algorithm_name[8..10]); let mac_size = tsig_rdata.get_mac_size(); - let mac = bytes_without_algorithm_name[11..(11 + mac_size as usize)].to_vec(); + let mac = bytes_without_algorithm_name[10..(10 + mac_size as usize)].to_vec(); tsig_rdata.set_mac(mac); - let bytes_without_mac = &bytes_without_algorithm_name[(11 + mac_size as usize)..]; + let bytes_without_mac = &bytes_without_algorithm_name[(10 + mac_size as usize)..]; tsig_rdata.set_original_id_from_bytes(&bytes_without_mac[0..2]); From 9bfb09c3dd0c104b3805b3e512e322d577675b0e Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 23:11:06 -0400 Subject: [PATCH 046/124] CHORE: some refactorings and better testing --- src/dnssec.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/dnssec.rs b/src/dnssec.rs index 60f3b755..5e72e51c 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,6 +1,7 @@ pub mod dnssec_encryption; +use std::str::FromStr; use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; use crate::message::DnsMessage; @@ -8,8 +9,10 @@ use crate::message::rdata::opt_rdata::OptRdata; use crate::message::rdata::Rdata; use crate::message::resource_record::{FromBytes, ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; +use crate::message::rcode; +use crate::message::rcode::Rcode; - +const EDNS_VERSION: u8 = 0; /* The mechanism chosen for the explicit notification of the ability of the client to accept (if not understand) DNSSEC security RRs is using @@ -44,7 +47,7 @@ fn read_opt_rr(opt_rr: ResourceRecord) -> String { let (e_rcode, version) = (data[0], data[1]); let z = u16::from_be_bytes([data[2], data[3]]); - let do_bit = (z & 0x8000) > 0; + let do_bit = ((z & 0x8000) > 0) as u8 ; format!("OPT PSEUDO-RR\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") } @@ -54,7 +57,12 @@ fn read_opt_rr(opt_rr: ResourceRecord) -> String { */ fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { // We create a opt rr with the do bit set to 1 - let rr = create_opt_rr(34, 2, false); + // with NOERR as rcode and EDNS0 + let rr = create_opt_rr( + rcode::Rcode::from_rcode_to_int(Rcode::NOERROR), + EDNS_VERSION, + true); + let vec = vec![rr]; msg.add_additionals(vec); msg @@ -62,7 +70,7 @@ fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { #[test] fn see_dnssec_message() { - let mut query = DnsMessage::new_query_message( + let query = DnsMessage::new_query_message( DomainName::new_from_str("example.com"), Qtype::A, Qclass::ANY, @@ -71,6 +79,9 @@ fn see_dnssec_message() { 2000 ); let query= create_dns_message_with_dnssec(query); - println!("{:#?}", query); - println!("{}", read_opt_rr(query.get_additional().pop().unwrap())); + assert_eq!(String::from_str + ("OPT PSEUDO-RR\n\terror code: 0\n\tversion: EDNS0\n\tuse dnssec: 1") + .expect("Not a utf8 str"), + read_opt_rr(query.get_additional().pop().expect("No OPT Record!")) + ) } \ No newline at end of file From d0bcda6ee0ad43b522c65bdf0fea14ad16b86458 Mon Sep 17 00:00:00 2001 From: Carlo Date: Tue, 21 May 2024 23:12:00 -0400 Subject: [PATCH 047/124] Refactor: reduced duplicated code with set_tsig_rd function. Declared functions as public --- src/tsig.rs | 77 +++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index adb86b44..f76c2e0e 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,4 +1,5 @@ //aquí debe ir todo lo relacionado a la implementación de tsig como módulo +use crypto::mac::MacResult; use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; use crate::message::resource_record::{self, ResourceRecord, ToBytes}; @@ -15,13 +16,13 @@ use crate::message::rdata::a_rdata::ARdata; type HmacSha256 = Hmac; //TODO: usar arreglar el funcionamiento del enum en sign_msg -enum TsigAlgorithm { +pub enum TsigAlgorithm { HmacSha1, HmacSha256, } #[derive(PartialEq)] #[derive(Debug)] -enum TsigErrorCode{ +pub enum TsigErrorCode{ NOERR = 0, BADSIG = 16, BADKEY = 17, @@ -29,46 +30,59 @@ enum TsigErrorCode{ FORMERR = 1, } +//TODO: Encontrar alguna manera de pasar una referencia Digest u Hmac de un algoritmo no especificado +// función auxiliar para evitar la redundancia de código en sign_tsig +fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: MacResult, fudge: u16, time_signed: u64, mac_size: u16) -> TSigRdata{ + let mut tsig_rd: TSigRdata = TSigRdata::new(); + let mac = result.code(); + /* + hasher.input(&new_query_message.to_bytes()[..]); + let result = hasher.result(); */ + //Convertir los bytes brutos a una cadena hexadecimal + let a_name = name.to_lowercase(); + let a_name = DomainName::new_from_string(a_name); + //añadir los valores correspondientes al tsig_rd + tsig_rd.set_algorithm_name(a_name); + tsig_rd.set_mac_size(mac_size); + tsig_rd.set_mac(mac.to_vec()); + tsig_rd.set_fudge(fudge); + tsig_rd.set_original_id(original_id); + tsig_rd.set_time_signed(time_signed); + + return tsig_rd; +} -#[doc = r"This functions signs creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { +#[doc = r"This function creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] +pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); match alg_name { TsigAlgorithm::HmacSha1 => { - let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&new_query_message.to_bytes()[..]); let result = hasher.result(); - let mac = result.code(); - //Convertir los bytes brutos a una cadena hexadecimal - let mac_size = 20; - let a_name = "Hmac-Sha1".to_lowercase(); - let a_name = DomainName::new_from_string(a_name); - tsig_rd.set_algorithm_name(a_name); - tsig_rd.set_mac_size(mac_size); - tsig_rd.set_mac(mac.to_vec()); - tsig_rd.set_fudge(fudge); - tsig_rd.set_original_id(original_id); - tsig_rd.set_time_signed(time_signed); + tsig_rd = set_tsig_rd(&new_query_message, + "Hmac-Sha1".to_lowercase(), + original_id, + result, + fudge, + time_signed, + 20); + }, TsigAlgorithm::HmacSha256 => { let mut hasher = crypto_hmac::new(Sha256::new(), key); hasher.input(&new_query_message.to_bytes()[..]); let result = hasher.result(); - let mac = result.code(); - //Convertir los bytes brutos a una cadena hexadecimal - let mac_size = 32; - let a_name = "Hmac-Sha256".to_lowercase(); - let a_name = DomainName::new_from_string(a_name); - tsig_rd.set_algorithm_name(a_name); - tsig_rd.set_mac_size(mac_size); - tsig_rd.set_mac(mac.to_vec()); - tsig_rd.set_fudge(fudge); - tsig_rd.set_original_id(original_id); - tsig_rd.set_time_signed(time_signed); + tsig_rd = set_tsig_rd(&new_query_message, + "Hmac-Sha256".to_lowercase(), + original_id, + result, + fudge, + time_signed, + 32); }, _ => {panic!("Error: Invalid algorithm")}, @@ -149,7 +163,7 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> (bool, TsigErrorCode) { +pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> (bool, TsigErrorCode) { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); //RFC 8945 5.2 y 5.4 @@ -224,17 +238,10 @@ fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, availa } -fn tsig_proccesing_answer(answer_msg:DnsMessage){ - //procesar los errores - //new_answer_msg = answer_msg.clone() -} - //Sección de tests unitarios -//ToDo: Crear bien un test que funcione #[test] - fn check_process_tsig_exists() { //Server process let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); From c831e38368054a985b1e07e6912c653f9da68a83 Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 21 May 2024 23:13:41 -0400 Subject: [PATCH 048/124] FIX: bug where does not increase arcount --- src/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message.rs b/src/message.rs index b6b20fc9..3a4b123e 100644 --- a/src/message.rs +++ b/src/message.rs @@ -615,7 +615,7 @@ impl DnsMessage { let mut msg_additionals = self.get_additional(); msg_additionals.append(&mut additionals); - self.header.set_arcount(self.header.get_arcount() + 1); + self.header.set_arcount(msg_additionals.len() as u16); self.set_additional(msg_additionals); } From 06bcb40ea4c35fe3b742bcfe23fed38475e30cce Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 22 May 2024 14:18:03 -0400 Subject: [PATCH 049/124] FIX: bug where does not increase ns & an count --- src/message.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/message.rs b/src/message.rs index 3a4b123e..b441a02f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -574,6 +574,7 @@ impl DnsMessage { let mut msg_answers = self.get_answer(); msg_answers.append(&mut answers); + self.header.set_ancount(msg_answers.len() as u16); self.set_answer(msg_answers); } @@ -599,6 +600,7 @@ impl DnsMessage { let mut msg_authorities = self.get_authority(); msg_authorities.append(&mut authorities); + self.header.set_nscount(msg_authorities.len() as u16); self.set_answer(msg_authorities); } From c2cb69954f26ad06afc6e5917fdf73ee7527baed Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:20:27 -0400 Subject: [PATCH 050/124] feat: added rrsets and sing/verify signature methods --- Cargo.toml | 1 + src/dnssec.rs | 1 + src/dnssec/dnssec_decryption.rs | 29 ++++++++++++++ src/dnssec/dnssec_encryption.rs | 67 ++++++++++++++++++++++++++++++++- src/message/rrset.rs | 62 ++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/dnssec/dnssec_decryption.rs create mode 100644 src/message/rrset.rs diff --git a/Cargo.toml b/Cargo.toml index 47110c4f..d17a210e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ async-trait = "0.1.77" sha2 = "0.10.2" hmac = "0.12.1" rust-crypto = "0.2" +base = "0.12.3" lru = "0.12.3" diff --git a/src/dnssec.rs b/src/dnssec.rs index 256b2afa..aca0bb75 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,4 +1,5 @@ pub mod dnssec_encryption; +pub mod dnssec_decryption; use crate::message::resource_record::{FromBytes, ToBytes}; use crate::tsig; \ No newline at end of file diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs new file mode 100644 index 00000000..2c3c1ab3 --- /dev/null +++ b/src/dnssec/dnssec_decryption.rs @@ -0,0 +1,29 @@ +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; + +/// RFCs: [4033, 4034, 4035, 5702] + +/// Verifies an RRset using the provided public key and RRSIG record. +/// Returns true if the verification is successful. +pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match rrsig.algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; + + public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") +} + diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs index 0020b9af..047f9d30 100644 --- a/src/dnssec/dnssec_encryption.rs +++ b/src/dnssec/dnssec_encryption.rs @@ -1 +1,66 @@ -use crypto; \ No newline at end of file +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; +use base64; + +/// RFCs: [4033, 4034, 4035, 4509] + +/// Signs a RRset using the private_key given. +/// Returns a RRSIG that contains the signature. +pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; + + let rrsig = RRSIGRdata { + type_covered: rrset.get_type(), + algorithm, + labels: rrset.get_labels(), + original_ttl: rrset.get_ttl(), + signature_expiration: get_expiration_time(), + signature_inception: get_inception_time(), + key_tag: calculate_key_tag(private_key), + signer_name: rrset.get_name().clone(), + signature: base64::encode(&signature), + }; + + Ok(rrsig) +} + +// Gets the expiration time for the signature. +fn get_expiration_time() -> u32 { + // Supposing sign validity = 1 day (86400 seconds) + let now = std::time::SystemTime::now(); + let expiration_duration = std::time::Duration::new(86400, 0); + let expiration_time = now + expiration_duration; + expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Gets the inception time for the signature. +fn get_inception_time() -> u32 { + // Assuming current time + let now = std::time::SystemTime::now(); + now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Calculates the key tag for the public key. +fn calculate_key_tag(private_key: &Rsa) -> u16 { + let public_key_der = private_key.to_public_key_der().unwrap(); + let mut hasher = Sha1::new(); + hasher.input(&public_key_der); + let hash = hasher.result_str(); + u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) +} diff --git a/src/message/rrset.rs b/src/message/rrset.rs new file mode 100644 index 00000000..15a43438 --- /dev/null +++ b/src/message/rrset.rs @@ -0,0 +1,62 @@ +use crate::message::Rtype; +use crate::message::Rclass; +use crate::message::resource_record::ResourceRecord; +use std::collections::HashSet; + +/// Represents a set of resource records (RRset). +#[derive(Debug)] +pub struct RRset { + /// The name of the domain associated with this RRset. + name: String, + /// The type of resource record in this RRset. + rtype: Rtype, + /// The class of resource record in this RRset. + rclass: Rclass, + /// The time to live (TTL) value for records in this RRset. + ttl: u32, + /// The set of resource records belonging to this RRset. + records: HashSet, +} + +impl RRset { + /// Creates a new RRset. + pub fn new(name: String, rtype: Rtype, rclass: Rclass, ttl: u32) -> RRset { + RRset { + name, + rtype, + rclass, + ttl, + records: HashSet::new(), + } + } + + /// Adds a resource record to this RRset. + pub fn add_record(&mut self, record: ResourceRecord) { + self.records.insert(record); + } + + /// Gets the name of the domain associated with this RRset. + pub fn get_name(&self) -> &String { + &self.name + } + + /// Gets the type of resource record in this RRset. + pub fn get_type(&self) -> Rtype { + self.rtype + } + + /// Gets the class of resource record in this RRset. + pub fn get_class(&self) -> Rclass { + self.rclass + } + + /// Gets the time to live (TTL) value for records in this RRset. + pub fn get_ttl(&self) -> u32 { + self.ttl + } + + /// Gets the set of resource records belonging to this RRset. + pub fn get_records(&self) -> &HashSet { + &self.records + } +} From 97e4703a5b014d4224242b9d289c874afbf45ae9 Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:33:33 -0400 Subject: [PATCH 051/124] fix: file name regarding rrset signature processes --- src/dnssec/dnssec_decryption.rs | 29 ----------- src/dnssec/dnssec_encryption.rs | 66 ------------------------- src/dnssec/rrset_signature.rs | 88 +++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 95 deletions(-) create mode 100644 src/dnssec/rrset_signature.rs diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs index 2c3c1ab3..e69de29b 100644 --- a/src/dnssec/dnssec_decryption.rs +++ b/src/dnssec/dnssec_decryption.rs @@ -1,29 +0,0 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; - -/// RFCs: [4033, 4034, 4035, 5702] - -/// Verifies an RRset using the provided public key and RRSIG record. -/// Returns true if the verification is successful. -pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match rrsig.algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; - - public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") -} - diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs index 047f9d30..e69de29b 100644 --- a/src/dnssec/dnssec_encryption.rs +++ b/src/dnssec/dnssec_encryption.rs @@ -1,66 +0,0 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; -use base64; - -/// RFCs: [4033, 4034, 4035, 4509] - -/// Signs a RRset using the private_key given. -/// Returns a RRSIG that contains the signature. -pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; - - let rrsig = RRSIGRdata { - type_covered: rrset.get_type(), - algorithm, - labels: rrset.get_labels(), - original_ttl: rrset.get_ttl(), - signature_expiration: get_expiration_time(), - signature_inception: get_inception_time(), - key_tag: calculate_key_tag(private_key), - signer_name: rrset.get_name().clone(), - signature: base64::encode(&signature), - }; - - Ok(rrsig) -} - -// Gets the expiration time for the signature. -fn get_expiration_time() -> u32 { - // Supposing sign validity = 1 day (86400 seconds) - let now = std::time::SystemTime::now(); - let expiration_duration = std::time::Duration::new(86400, 0); - let expiration_time = now + expiration_duration; - expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} - -// Gets the inception time for the signature. -fn get_inception_time() -> u32 { - // Assuming current time - let now = std::time::SystemTime::now(); - now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} - -// Calculates the key tag for the public key. -fn calculate_key_tag(private_key: &Rsa) -> u16 { - let public_key_der = private_key.to_public_key_der().unwrap(); - let mut hasher = Sha1::new(); - hasher.input(&public_key_der); - let hash = hasher.result_str(); - u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) -} diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs new file mode 100644 index 00000000..853f916c --- /dev/null +++ b/src/dnssec/rrset_signature.rs @@ -0,0 +1,88 @@ +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; +use base64; + +/// RFCs: [4033, 4034, 4035, 4509] + +/// Signs a RRset using the private_key given. +/// Returns a RRSIG that contains the signature. +pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; + + let rrsig = RRSIGRdata { + type_covered: rrset.get_type(), + algorithm, + labels: rrset.get_labels(), + original_ttl: rrset.get_ttl(), + signature_expiration: get_expiration_time(), + signature_inception: get_inception_time(), + key_tag: calculate_key_tag(private_key), + signer_name: rrset.get_name().clone(), + signature: base64::encode(&signature), + }; + + Ok(rrsig) +} + +// Gets the expiration time for the signature. +fn get_expiration_time() -> u32 { + // Supposing sign validity = 1 day (86400 seconds) + let now = std::time::SystemTime::now(); + let expiration_duration = std::time::Duration::new(86400, 0); + let expiration_time = now + expiration_duration; + expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Gets the inception time for the signature. +fn get_inception_time() -> u32 { + // Assuming current time + let now = std::time::SystemTime::now(); + now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Calculates the key tag for the public key. +fn calculate_key_tag(private_key: &Rsa) -> u16 { + let public_key_der = private_key.to_public_key_der().unwrap(); + let mut hasher = Sha1::new(); + hasher.input(&public_key_der); + let hash = hasher.result_str(); + u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) +} + +/// RFCs: [4033, 4034, 4035, 5702] + +/// Verifies an RRset using the provided public key and RRSIG record. +/// Returns true if the verification is successful. +pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match rrsig.algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; + + public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") +} + From 04447511382addc9c2a0681a22d0aa3570fad9dc Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:37:52 -0400 Subject: [PATCH 052/124] feat: added missing method get_labels --- src/message/rrset.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/message/rrset.rs b/src/message/rrset.rs index 15a43438..bca9953c 100644 --- a/src/message/rrset.rs +++ b/src/message/rrset.rs @@ -59,4 +59,9 @@ impl RRset { pub fn get_records(&self) -> &HashSet { &self.records } + + // Gets the labels of the domain associated with this RRset. + pub fn get_labels(&self) -> usize { + self.name.split('.').count() + } } From 5f751a5c3976071bcd1b3d9981ab996a938d6c71 Mon Sep 17 00:00:00 2001 From: Carlo Date: Thu, 6 Jun 2024 18:08:44 -0400 Subject: [PATCH 053/124] Added: Basic TSIG integration test . Tested with a localhost UDP server --- tests/integration_test.rs | 102 ++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 6746125d..97803302 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,5 +1,5 @@ -use std::{net::IpAddr, str::FromStr}; -use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata, resource_record::ResourceRecord},tsig}; +use std::{net::IpAddr, str::FromStr, thread, net::UdpSocket, time::Duration}; +use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata,class_qclass::Qclass, type_qtype, resource_record::ResourceRecord, header::Header, DnsMessage},tsig::{self, TsigAlgorithm}}; @@ -13,6 +13,7 @@ async fn query_response(domain_name: &str, protocol: &str, qtype: &str) -> Resul domain_name, protocol, qtype, + "IN").await; response.map(|lookup_response| lookup_response.to_vec_of_rr()) @@ -108,61 +109,66 @@ async fn no_resource_available() { println!("{:?}", response); assert!(response.is_err()); } -/* + + ///RFC 8945 TSIG tests #[tokio::test] async fn tsig_signature() { - let sock = UdpSocket::bind("127.0.0.1:8001").expect("Puerto ocupado"); - + // global test variables + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 0; + let time_signed = 0; + let id = 6502; let mut dns_query_message = DnsMessage::new_query_message( - DomainName::new_from_string("uchile.cl".to_string()), - Qtype::A, + DomainName::new_from_string("nictest.cl".to_string()), + type_qtype::Qtype::A, Qclass::IN, 0, false, - 1); - let signature = dns_rust::tsig::sign_tsig(); - let digest = keyed_hash(b"alalalalalalalalalalalalalalalal", &dns_query_message.to_bytes()[..]); - let digstr = digest.to_string(); - let x = format!("hmac-md5.sig-alg.reg.int.\n51921\n1234\n32\n{}\n1234\n0\n0", digstr); - - println!("El dig stirng es: {:#?}" , digstr); - let resource_record = TSigRdata::rr_from_master_file( - x.split_whitespace(), - 56, - "IN", - String::from("uchile.cl"), - String::from("uchile.cl")); - - let mut vec = vec![]; - - vec.push(resource_record); - - dns_query_message.add_additionals(vec); - - println!("{:#?}", dns_query_message); - + id); + let q_for_mac = dns_query_message.clone(); + //Lanzamiento de threads + //Se lanza el servidor. Recibe un mensaje sin firmar, lo firma y lo reenvía + fn host(){ + println!("I am a host"); + let udp_socket = UdpSocket::bind("127.0.0.1:8002").expect("Failed to bind to address"); + let mut buf = [0; 512]; + + match udp_socket.recv_from(&mut buf) { + + Ok((size, source)) => { + println!("Received {} bytes from {}", size, source); + let mut data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); + println!("The data is {:?}", data); + tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0); + let response = &DnsMessage::to_bytes(&data); + udp_socket + .send_to(&response, source) + .expect("Failed to send response"); + + } + Err(e) => { + eprintln!("Error receiving data: {}", e); + + } + } + + } + println!("Starting server"); + let server_handle = thread::spawn(|| { + host(); + + }); + thread::sleep(Duration::from_secs(2)); + // se instancia un socket cliente que enviará y mensajes + let client_sock = UdpSocket::bind("127.0.0.1:8001").expect("Nothing"); let buf = dns_query_message.to_bytes(); + client_sock.send_to(&buf,"127.0.0.1:8002").unwrap(); + println!("Mensaje enviado"); + server_handle.join().unwrap(); - let s = sock.send_to(&buf, "127.0.0.1:8001").unwrap(); - let response = query_response("example.com", "UDP", "MX").await; - - if let Ok(rrs) = response { - assert_eq!(rrs.len(), 1); - - if let Rdata::MX(mxdata) = rrs[0].get_rdata() { - assert_eq!( - mxdata.get_exchange(), - DomainName::new_from_str("")); - assert_eq!( - mxdata.get_preference(), - 0 - ) - } else { - panic!("Record is not MX type"); - } - } } -*/ + \ No newline at end of file From 8512bcb7292fadb05bff58ac1715d404fb6ade7e Mon Sep 17 00:00:00 2001 From: joalopez Date: Fri, 24 May 2024 16:15:26 -0400 Subject: [PATCH 054/124] FIX: added requested udp len to OPT rr. --- src/dnssec.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/dnssec.rs b/src/dnssec.rs index 5e72e51c..5de6ab80 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -4,6 +4,7 @@ pub mod dnssec_encryption; use std::str::FromStr; use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; +use crate::message::class_rclass::Rclass; use crate::message::DnsMessage; use crate::message::rdata::opt_rdata::OptRdata; use crate::message::rdata::Rdata; @@ -13,6 +14,7 @@ use crate::message::rcode; use crate::message::rcode::Rcode; const EDNS_VERSION: u8 = 0; +const REQUESTED_UDP_LEN: u16 = 4096; /* The mechanism chosen for the explicit notification of the ability of the client to accept (if not understand) DNSSEC security RRs is using @@ -29,8 +31,7 @@ of the EDNS0 OPT meta-RR, structured as follows: 2: |DO| Z | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ -// [0x12, 0x0, 0x80, 0x0] -fn create_opt_rr(e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { +fn create_opt_rr(capacity: u16 ,e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { let opt_rdata = OptRdata::new(); let rdata = Rdata::OPT(opt_rdata); let mut rr = ResourceRecord::new(rdata); @@ -38,17 +39,19 @@ fn create_opt_rr(e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { let do_val: u16 = if do_bit {0x8000} else {0x0}; let ttl: u32 = (e_rcode as u32) << 24 | (version as u32) << 16| (do_val as u32); rr.set_ttl(ttl); + rr.set_rclass(Rclass::UNKNOWN(capacity)); println!("EL ttl es: {:#05x?}", ttl); rr } fn read_opt_rr(opt_rr: ResourceRecord) -> String { + let requested_udp_len = Rclass::from_rclass_to_int(opt_rr.get_rclass()); let data = opt_rr.get_ttl().to_be_bytes(); let (e_rcode, version) = (data[0], data[1]); let z = u16::from_be_bytes([data[2], data[3]]); let do_bit = ((z & 0x8000) > 0) as u8 ; - format!("OPT PSEUDO-RR\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") + format!("OPT PSEUDO-RR\n\trequested_udp_len: {requested_udp_len}\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") } /* @@ -58,7 +61,7 @@ fn read_opt_rr(opt_rr: ResourceRecord) -> String { fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { // We create a opt rr with the do bit set to 1 // with NOERR as rcode and EDNS0 - let rr = create_opt_rr( + let rr = create_opt_rr(REQUESTED_UDP_LEN, rcode::Rcode::from_rcode_to_int(Rcode::NOERROR), EDNS_VERSION, true); @@ -73,14 +76,14 @@ fn see_dnssec_message() { let query = DnsMessage::new_query_message( DomainName::new_from_str("example.com"), Qtype::A, - Qclass::ANY, + Qclass::UNKNOWN(4096), 1, true, 2000 ); let query= create_dns_message_with_dnssec(query); assert_eq!(String::from_str - ("OPT PSEUDO-RR\n\terror code: 0\n\tversion: EDNS0\n\tuse dnssec: 1") + ("OPT PSEUDO-RR\n\trequested_udp_len: 4096\n\terror code: 0\n\tversion: EDNS0\n\tuse dnssec: 1") .expect("Not a utf8 str"), read_opt_rr(query.get_additional().pop().expect("No OPT Record!")) ) From 5eefd3b7948870d3c73276c646c5812eeaff2ed6 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 16:49:12 -0400 Subject: [PATCH 055/124] chore: remove unused dirs --- src/test/foo.rs | 0 src/test_2/foo2.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/foo.rs delete mode 100644 src/test_2/foo2.rs diff --git a/src/test/foo.rs b/src/test/foo.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/src/test_2/foo2.rs b/src/test_2/foo2.rs deleted file mode 100644 index e69de29b..00000000 From 28970a6594ca30832ff5711848ed48e6b45b9884 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 16:56:24 -0400 Subject: [PATCH 056/124] FIX: bug in from_bytes opt rdata --- src/message/rdata/opt_rdata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message/rdata/opt_rdata.rs b/src/message/rdata/opt_rdata.rs index c90d0fef..55091e2c 100644 --- a/src/message/rdata/opt_rdata.rs +++ b/src/message/rdata/opt_rdata.rs @@ -55,7 +55,7 @@ impl FromBytes> for OptRdata { opt_rdata.set_option_length(option_length); let mut option_data: Vec = Vec::new(); - for i in 4..bytes_len { + for i in 4..4 + option_length as usize { option_data.push(bytes[i]); } if option_data.len() != option_length as usize { From 7091665e8187b9824ddc95dfaa7ae9fecd5b0778 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 17:07:31 -0400 Subject: [PATCH 057/124] Refactor: added key_name arg in sign_tsig --- src/tsig.rs | 71 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index f76c2e0e..3b76b1f3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -32,7 +32,8 @@ pub enum TsigErrorCode{ } //TODO: Encontrar alguna manera de pasar una referencia Digest u Hmac de un algoritmo no especificado // función auxiliar para evitar la redundancia de código en sign_tsig -fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: MacResult, fudge: u16, time_signed: u64, mac_size: u16) -> TSigRdata{ +fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: MacResult, + fudge: u16, time_signed: u64, mac_size: u16) -> TSigRdata{ let mut tsig_rd: TSigRdata = TSigRdata::new(); let mac = result.code(); /* @@ -53,7 +54,8 @@ fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: M } #[doc = r"This function creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] -pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64) -> Vec { +pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, + fudge: u16, time_signed: u64, key_name: String) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); @@ -90,6 +92,7 @@ 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); @@ -214,13 +217,14 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av let fudge = tsig_rr_copy.get_fudge(); let time_signed = tsig_rr_copy.get_time_signed(); let mac_received = tsig_rr_copy.get_mac(); + let key_name = "".to_string(); let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; match name_alg.as_str() { "hmac-sha1" => new_alg_name = TsigAlgorithm::HmacSha1, "hmac-sha256" => new_alg_name = TsigAlgorithm::HmacSha256, &_ => println!("not supported algorithm") } - let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed); + let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed, key_name); let cond2 = check_mac(new_mac, mac_received); if !cond2 { @@ -264,8 +268,9 @@ fn check_process_tsig_exists2() { let alg_name2 = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); - sign_tsig(&mut response, server_key, alg_name2, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone()); + sign_tsig(&mut response, server_key, alg_name2, fudge, time_signed, key_name.clone()); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); @@ -284,7 +289,8 @@ fn check_process_tsig_exists3(){ let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); //necesito agregar algo más en el additional let mut new_additional = Vec::::new(); let a_rdata5 = Rdata::A(ARdata::new()); @@ -308,7 +314,8 @@ fn check_process_tsig_alg_name() { let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); @@ -327,7 +334,8 @@ fn check_process_tsig_alg_name2() { let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); @@ -346,7 +354,8 @@ fn check_process_tsig_key(){ let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); let mut response_capture = response.clone(); //Client process let key_name:String = "different".to_string(); @@ -367,34 +376,37 @@ fn check_process_tsig_badsign(){ let alg_name = TsigAlgorithm::HmacSha1; let fudge = 1000; let time_signed = 210000000; + let key_name = "".to_string(); // se firma el mensaje con algoritmo SHA-1 - sign_tsig(& mut msg1, key, alg_name, fudge, time_signed); + sign_tsig(& mut msg1, key, alg_name, fudge, time_signed, key_name); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha1"),true)); lista.push((String::from("hmac-sha256"),true)); // se verifica que el mensaje está firmado, pero se usa otra key + let key_name = "".to_string(); let key2 = b"12345678909"; let (answer,error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista); assert_eq!(error,TsigErrorCode::BADSIG); } #[test] fn check_proces_tsig_badtime(){ - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); - let mut response_capture = response.clone(); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - //suponemos que reconocemos hmac-sha256, pero no está implementado - lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 22010, lista); - assert!(!answer); - assert_eq!(error,TsigErrorCode::BADTIME); + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + let mut response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 22010, lista); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADTIME); } #[test] fn check_process_tsig() { @@ -404,7 +416,8 @@ fn check_process_tsig() { let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); @@ -430,8 +443,8 @@ fn check_signed_tsig() { id ); let q_for_mac = q.clone(); - - let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed); + let key_name = "".to_string(); + let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed, key_name); let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&q_for_mac.to_bytes()[..]); From 4725c1035d8ed83d5d1800a5458e0474b129ef39 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 17:10:43 -0400 Subject: [PATCH 058/124] Chore: removed some warnings --- src/tsig.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 3b76b1f3..e2ce896c 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -2,16 +2,14 @@ use crypto::mac::MacResult; use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; -use crate::message::resource_record::{self, ResourceRecord, ToBytes}; +use crate::message::resource_record::{ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage}; -use std::time::{SystemTime, UNIX_EPOCH}; -use crate::message::rdata::{rrsig_rdata, Rdata}; +use crate::message::rdata::{Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; -use std::str; use crate::message::rdata::a_rdata::ARdata; type HmacSha256 = Hmac; @@ -144,7 +142,7 @@ fn check_time_values(mytime: u64,fudge: u16, time: u64) -> bool { fn check_exists_tsig_rr(add_rec: &Vec) -> bool { let filtered_tsig:Vec<_> = add_rec.iter() .filter(|tsig| - if let Rdata::TSIG(data) = tsig.get_rdata() {true} + if let Rdata::TSIG(_) = tsig.get_rdata() {true} else {false}).collect(); filtered_tsig.len()==0 @@ -156,10 +154,10 @@ fn check_exists_tsig_rr(add_rec: &Vec) -> bool { fn check_last_one_is_tsig(add_rec: &Vec) -> bool { let filtered_tsig:Vec<_> = add_rec.iter() .filter(|tsig| - if let Rdata::TSIG(data) = tsig.get_rdata() {true} + if let Rdata::TSIG(_) = tsig.get_rdata() {true} else {false}).collect(); - let islast = if let Rdata::TSIG(data) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; + let islast = if let Rdata::TSIG(_) = add_rec[add_rec.len()-1].get_rdata() {false} else {true}; filtered_tsig.len()>1 || islast } @@ -372,7 +370,6 @@ fn check_process_tsig_badsign(){ // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); let key = b"1234567890"; - let key_name:String = "".to_string(); let alg_name = TsigAlgorithm::HmacSha1; let fudge = 1000; let time_signed = 210000000; From ca2cd2555e6dbe08c5d9c8f86005671ce51f6bc9 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 17:15:18 -0400 Subject: [PATCH 059/124] fix: keyname in integration test --- tests/integration_test.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 97803302..542a7559 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -142,7 +142,8 @@ async fn tsig_signature() { println!("Received {} bytes from {}", size, source); let mut data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); println!("The data is {:?}", data); - tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0); + let key_name = "".to_string(); + tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0, key_name); let response = &DnsMessage::to_bytes(&data); udp_socket .send_to(&response, source) From fc02605ac583fb21ec0bb03d6f19aa18358bd099 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 13 Jun 2024 17:28:04 -0400 Subject: [PATCH 060/124] fix: from_bytes rdata for tsig_rdata --- src/message/rdata.rs | 65 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/src/message/rdata.rs b/src/message/rdata.rs index 6d54b07f..461f7202 100644 --- a/src/message/rdata.rs +++ b/src/message/rdata.rs @@ -571,11 +571,33 @@ mod resolver_query_tests { #[test] fn to_bytes_tsigrdata(){ let expected_bytes = vec![ - 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, - 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, - 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0x5B, 0xCD, 0x15, 0x4, 0xD2, 0x0, 0x4, 0xA1, 0xB2, 0xC3, 0xD4, - 0x4, 0xD2, 0x0, 0x0, 0x0, 0x0 + //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 00 + 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, + 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, + 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, + + //this is the time signed 123456789 == 0x75bcd15 + 0x0, 0x0, 0x7, 0x5B, 0xCD, 0x15, + + // this the fudge 1234 + 0x4, 0xD2, + + // this is the macsize = 4 + 0x0, 0x4, + + // this is the mac = [0xA1, 0xB2, 0xC3, 0xD4] + 0xA1, 0xB2, 0xC3, 0xD4, + + // this is the original id = 1234 + 0x4, 0xD2, + + // this is the error = 0 + 0x0, 0x0, + + // this is the other len = 0 + 0x0, 0x0 + + // No other data, so its empty! ]; let mut tsig_rdata = TSigRdata::new(); @@ -904,11 +926,34 @@ mod resolver_query_tests { #[test] fn from_bytes_tsig_rdata(){ let data_bytes = vec![ - 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, - 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, - 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x7, 0x5B, 0xCD, 0x15, 0x4, 0xD2, 0x0, 0x4, 0xA1, 0xB2, 0xC3, 0xD4, - 0x4, 0xD2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFA, 0x0, 0x1 + //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 00 + 0x8, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x6D, 0x64, + 0x35, 0x7, 0x73, 0x69, 0x67, 0x2D, 0x61, 0x6C, 0x67, + 0x3, 0x72, 0x65, 0x67, 0x3, 0x69, 0x6E, 0x74, 0x0, + + //this is the time signed 123456789 == 0x75bcd15 + 0x0, 0x0, 0x7, 0x5B, 0xCD, 0x15, + + // this the fudge 1234 + 0x4, 0xD2, + + // this is the macsize = 4 + 0x0, 0x4, + + // this is the mac = [0xA1, 0xB2, 0xC3, 0xD4] + 0xA1, 0xB2, 0xC3, 0xD4, + + // this is the original id = 1234 + 0x4, 0xD2, + + // this is the error = 0 + 0x0, 0x0, + + // this is the other len = 0 + 0x0, 0x0, + //Extra bytes for from_bytes function + 0x0, 0xFA, 0x0, 0x1 + // No other data, so its empty! ]; let rdata = Rdata::from_bytes(&data_bytes, &data_bytes).unwrap(); let mut domain_name = DomainName::new(); From 7b3dcf8157f49429b3fef4560309b25434a83a97 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 11:59:54 -0400 Subject: [PATCH 061/124] Refactor: Started changes to headers to add ad y cd flags --- src/message/header.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 38090d47..99f2f98e 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -1,22 +1,23 @@ #[derive(Default, Clone)] /// An struct that represents a Header secction from a DNS message. -/// -/// 1 1 1 1 1 1 -/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// | ID | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// | QDCOUNT | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// | ANCOUNT | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// | NSCOUNT | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -/// | ARCOUNT | -/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// EDIT: now added bits AD CD for DNS security extensions. +/// +/// 1 1 1 1 1 1 +/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// | ID | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// | QDCOUNT | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// | ANCOUNT | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// | NSCOUNT | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +/// | ARCOUNT | +/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ #[derive (PartialEq, Debug)] pub struct Header { /// Id @@ -38,10 +39,12 @@ pub struct Header { tc: bool, // TrunCation rd: bool, // Recursion Desired ra: bool, // Recursion Available + ad: bool, // Authentic data + cd: bool, // cd data /// Reserved #[allow(dead_code)] - z: u8, + z: bool, /// Response Code /// From 6c5fbc82b3123b13501f19848a2a76af9d3517b9 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:10:22 -0400 Subject: [PATCH 062/124] added setters for ad and cd bits --- src/message/header.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 99f2f98e..18c83505 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -42,7 +42,7 @@ pub struct Header { ad: bool, // Authentic data cd: bool, // cd data - /// Reserved + /// Reserved Edit: Now z is just a flag #[allow(dead_code)] z: bool, @@ -138,6 +138,8 @@ impl Header { let tc = (bytes[2] & 0b00000010) >> 1; let rd = bytes[2] & 0b00000001; let ra = bytes[3] >> 7; + let ad = bytes[3] & 0b00100000 >> 5; + let cd = bytes[3] & 0b00010000 >> 4; let rcode = bytes[3] & 0b00001111; let qdcount = ((bytes[4] as u16) << 8) | bytes[5] as u16; let ancount = ((bytes[6] as u16) << 8) | bytes[7] as u16; @@ -152,6 +154,8 @@ impl Header { header.set_tc(tc != 0); header.set_rd(rd != 0); header.set_ra(ra != 0); + header.set_ad(ad != 0); + header.set_cd(cd != 0); header.set_rcode(rcode); header.set_qdcount(qdcount); header.set_ancount(ancount); @@ -392,7 +396,7 @@ impl Header { } // Z: A 3 bit field that MUST be zero - if self.z != 0 { + if self.z != false { return Err("Format Error: Z"); } @@ -442,6 +446,16 @@ impl Header { self.ra = ra; } + /// Sets the ad attribute with a value. + pub fn set_ad(&mut self, ra: bool) { + self.ad = ra; + } + + /// Sets the cd attribute with a value. + pub fn set_cd(&mut self, ra: bool) { + self.cd = ra; + } + /// Sets the rcode attribute with a value. pub fn set_rcode(&mut self, rcode: u8) { self.rcode = rcode; From a9195af34afab2c6c4b60154e9fad9ed8c71278e Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:10:47 -0400 Subject: [PATCH 063/124] refactor: from 0 as u8 to 0u8 --- src/message/header.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 18c83505..89459469 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -214,7 +214,7 @@ impl Header { return 0b00000100; } - return 0 as u8; + return 0u8; } /// Returns a byte that represents the field in the DNS message. @@ -227,7 +227,7 @@ impl Header { return 0b00000010; } - return 0 as u8; + return 0u8; } /// Returns a byte that represents the field in the DNS message. @@ -240,7 +240,7 @@ impl Header { return 0b00000001; } - return 0 as u8; + return 0u8; } /// Returns a byte that represents the field in the DNS message. @@ -253,7 +253,7 @@ impl Header { return 0b10000000; } - return 0 as u8; + return 0u8; } /// Gets the first byte from the qdcount attribute. From b83692bf7c6546c4ca2d8310ccec62ed4cfa6ac4 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:17:34 -0400 Subject: [PATCH 064/124] refactor: added headers --- src/message/header.rs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/message/header.rs b/src/message/header.rs index 89459469..580dd650 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -256,6 +256,32 @@ impl Header { return 0u8; } + /// Returns a byte that represents the field in the DNS message. + /// + /// See the DNS message structure in struct documentation for more info. + fn ad_to_byte(&self) -> u8 { + let ad = self.get_ad(); + + if ad { + return 0b00100000; + } + + return 0u8; + } + + /// Returns a byte that represents the field in the DNS message. + /// + /// See the DNS message structure in struct documentation for more info. + fn cd_to_byte(&self) -> u8 { + let cd = self.get_cd(); + + if cd { + return 0b00010000; + } + + return 0u8; + } + /// Gets the first byte from the qdcount attribute. fn get_first_qdcount_byte(&self) -> u8 { let header_qdcount = self.get_qdcount(); @@ -387,7 +413,7 @@ impl Header { header_bytes } - /// Checks if the header is well formed. + /// Checks if the header is well-formed. pub fn format_check(&self)-> Result{ // OP CODE: A four bit field between 0-15 @@ -519,6 +545,16 @@ impl Header { self.ra } + /// Gets the ad attribute value. + pub fn get_ad(&self) -> bool { + self.ad + } + + /// Gets the cd attribute value. + pub fn get_cd(&self) -> bool { + self.cd + } + /// Gets the `rcode` attribute value. pub fn get_rcode(&self) -> u8 { self.rcode From f4dad7a4cd25054dd1cc0c7f6a10e6acc3a436a8 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:23:07 -0400 Subject: [PATCH 065/124] refactor: changed to bytes for parsing ad cd bytes --- src/message/header.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 580dd650..c6ff0065 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -138,8 +138,8 @@ impl Header { let tc = (bytes[2] & 0b00000010) >> 1; let rd = bytes[2] & 0b00000001; let ra = bytes[3] >> 7; - let ad = bytes[3] & 0b00100000 >> 5; - let cd = bytes[3] & 0b00010000 >> 4; + let ad = (bytes[3] & 0b00100000) >> 5; + let cd = (bytes[3] & 0b00010000) >> 4; let rcode = bytes[3] & 0b00001111; let qdcount = ((bytes[4] as u16) << 8) | bytes[5] as u16; let ancount = ((bytes[6] as u16) << 8) | bytes[7] as u16; @@ -362,9 +362,11 @@ impl Header { /// Gets a byte that represents the second byte of flags section. fn get_second_flags_byte(&self) -> u8 { let ra_byte = self.ra_to_byte(); + let ad_byte = self.ad_to_byte(); + let cd_byte = self.cd_to_byte(); let rcode_byte = self.get_rcode(); - let second_byte = ra_byte | rcode_byte; + let second_byte = ra_byte | ad_byte | cd_byte | rcode_byte; second_byte } From 8be986f8ef66ea05ed787a720700f5edbe913b2b Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:27:52 -0400 Subject: [PATCH 066/124] refactor: adding tests for flags ad cd --- src/message/header.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/message/header.rs b/src/message/header.rs index c6ff0065..0c3a1d18 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -597,6 +597,8 @@ mod header_test { assert_eq!(header.tc, false); assert_eq!(header.rd, false); assert_eq!(header.ra, false); + assert_eq!(header.ad, false); + assert_eq!(header.cd, false); assert_eq!(header.rcode, 0); assert_eq!(header.qdcount, 0); assert_eq!(header.ancount, 0); @@ -688,6 +690,30 @@ mod header_test { assert_eq!(ra, true); } + #[test] + fn set_and_get_ad() { + let mut header = Header::new(); + + let mut ad = header.get_ad(); + assert_eq!(ad, false); + + header.set_ad(true); + ad = header.get_ad(); + assert_eq!(ad, true); + } + + #[test] + fn set_and_get_cd() { + let mut header = Header::new(); + + let mut cd = header.get_cd(); + assert_eq!(cd, false); + + header.set_cd(true); + cd = header.get_cd(); + assert_eq!(cd, true); + } + #[test] fn set_and_get_rcode() { let mut header = Header::new(); @@ -841,7 +867,7 @@ mod header_test { ]; let mut header = Header::from_bytes(&bytes_header); - header.z = 3; + header.z = true; header.set_rcode(16); header.set_op_code(22); From 52f56bd94572f69362fdc2b6af60fe5a6874146f Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:31:10 -0400 Subject: [PATCH 067/124] refactor: added tests for check ad cd in a header struct --- src/message/header.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 0c3a1d18..cfa007ec 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -785,13 +785,15 @@ mod header_test { header.set_qr(true); header.set_op_code(2); header.set_tc(true); + header.set_ad(true); + header.set_cd(true); header.set_rcode(5); header.set_ancount(0b0000101010100101); bytes[0] = 0b00100100; bytes[1] = 0b10010101; bytes[2] = 0b10010010; - bytes[3] = 0b00000101; + bytes[3] = 0b00110101; bytes[6] = 0b00001010; bytes[7] = 0b10100101; @@ -805,7 +807,7 @@ mod header_test { bytes[0] = 0b00100100; bytes[1] = 0b10010101; bytes[2] = 0b10010010; - bytes[3] = 0b00000101; + bytes[3] = 0b00110101; bytes[6] = 0b00001010; bytes[7] = 0b10100101; @@ -815,6 +817,8 @@ mod header_test { header.set_qr(true); header.set_op_code(2); header.set_tc(true); + header.set_ad(true); + header.set_cd(true); header.set_rcode(5); header.set_ancount(0b0000101010100101); From 11b30c3c410f916f0a4ecd2729db4adc35f8dd61 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 12:51:32 -0400 Subject: [PATCH 068/124] Chore: changed tests --- src/message.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/message.rs b/src/message.rs index b441a02f..a62b306a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -75,6 +75,8 @@ impl DnsMessage { id: u16, ) -> Self { let qr = false; + // dnssec + let ad = true; let qdcount = 1; let mut header = Header::new(); @@ -82,6 +84,7 @@ impl DnsMessage { header.set_qr(qr); header.set_op_code(op_code); header.set_rd(rd); + header.set_ad(ad); header.set_qdcount(qdcount); let mut question = Question::new(); @@ -1139,7 +1142,7 @@ mod message_test { */ let bytes: [u8; 50] = [ //test passes with this one - 0b00100100, 0b10010101, 0b10010010, 0b00000000, 0, 1, 0b00000000, 1, 0, 0, 0, 0, 4, 116, + 0b00100100, 0b10010101, 0b10010010, 0b00100000, 0, 1, 0b00000000, 1, 0, 0, 0, 0, 4, 116, 101, 115, 116, 3, 99, 111, 109, 0, 0, 16, 0, 1, 3, 100, 99, 99, 2, 99, 108, 0, 0, 16, 0, 1, 0, 0, 0b00010110, 0b00001010, 0, 6, 5, 104, 101, 108, 108, 111, ]; @@ -1157,6 +1160,7 @@ mod message_test { assert_eq!(header.get_qr(), true); assert_eq!(header.get_op_code(), 2); assert_eq!(header.get_tc(), true); + assert_eq!(header.get_ad(), true); assert_eq!(header.get_rcode(), 0); assert_eq!(header.get_ancount(), 1); @@ -1196,6 +1200,7 @@ mod message_test { header.set_qr(true); header.set_op_code(2); header.set_tc(true); + header.set_ad(true); header.set_rcode(8); header.set_ancount(0b0000000000000001); header.set_qdcount(1); @@ -1234,7 +1239,7 @@ mod message_test { let msg_bytes = &dns_msg.to_bytes(); let real_bytes: [u8; 50] = [ - 0b00100100, 0b10010101, 0b10010010, 0b00001000, 0, 1, 0b00000000, 0b00000001, 0, 0, 0, + 0b00100100, 0b10010101, 0b10010010, 0b00101000, 0, 1, 0b00000000, 0b00000001, 0, 0, 0, 0, 4, 116, 101, 115, 116, 3, 99, 111, 109, 0, 0, 5, 0, 2, 3, 100, 99, 99, 2, 99, 108, 0, 0, 16, 0, 1, 0, 0, 0b00010110, 0b00001010, 0, 6, 5, 104, 101, 108, 108, 111, ]; From 8593cf882036bb0073526d3906c73d66375d04c9 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 1 Jul 2024 13:55:22 -0400 Subject: [PATCH 069/124] fix: removed AD flag in new_query_essage, only for responses (?) --- src/message.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/message.rs b/src/message.rs index a62b306a..de385a4a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -75,8 +75,6 @@ impl DnsMessage { id: u16, ) -> Self { let qr = false; - // dnssec - let ad = true; let qdcount = 1; let mut header = Header::new(); @@ -84,7 +82,6 @@ impl DnsMessage { header.set_qr(qr); header.set_op_code(op_code); header.set_rd(rd); - header.set_ad(ad); header.set_qdcount(qdcount); let mut question = Question::new(); From 371638f4a6f805793351109fe68ee7052b097e28 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 5 Jul 2024 17:40:36 -0400 Subject: [PATCH 070/124] Refactor: created a get_digest to do a major-reactoring to the sign_tsig and process_tsig functions due to a misunderstanding of section 5.1 of RFC 8945 --- src/tsig.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index e2ce896c..3edb1724 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -4,7 +4,7 @@ use crate::domain_name::DomainName; use crate::message::class_qclass::Qclass; use crate::message::resource_record::{ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; -use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage}; +use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage, class_rclass}; use crate::message::rdata::{Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; @@ -50,16 +50,88 @@ fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: M return tsig_rd; } +#[doc = r"This function recives a DNS message and appends the TSIG variables requested by RFC 8946 4.3.3 "] +fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { + let mut res: Vec = dns_msg.clone(); + let tsig_rdata = tsig_rr.get_rdata(); + res.extend(tsig_rr.get_name().to_bytes()); + //processing TSIG RR + let rclass_bytes: u16 = u16::to_be(class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass())); + let rclass_lbyte = (rclass_bytes & 0xFF) as u8; + let rclass_ubyte = (rclass_bytes >> 8) as u8; + res.push(rclass_lbyte); + res.push(rclass_ubyte); + let rclass_ttl: u32 = u32::to_be(tsig_rr.get_ttl()); + let r_ttl1 = (rclass_ttl & 0xFF) as u8; + let r_ttl2 = (rclass_ttl >> 24) as u8; + let r_ttl3 = (rclass_ttl >>16) as u8; + let r_ttl4 = (rclass_ttl >>8) as u8; + res.push(r_ttl1); + res.push(r_ttl2); + res.push(r_ttl3); + res.push(r_ttl4); + //processing TSIG RDATA + + let tsig_rd = match tsig_rdata { + Rdata::TSIG(tsig_rd) => tsig_rd, + _ => panic!() + }; + let a_name = tsig_rd.get_algorithm_name().to_bytes(); + let tsig_rd_time_signed: u64 = u64::to_be(tsig_rd.get_time_signed()); + let tsig_rd_fudge: u16 = u16::to_be(tsig_rd.get_fudge()); + let tsig_rd_error: u16= u16::to_be(tsig_rd.get_error()); + let tsig_rd_other_len: u16 = u16::to_be(tsig_rd.get_other_len()); + let tsig_rd_other_data = tsig_rd.get_other_data(); + res.extend(a_name); + + let time_s1 = (tsig_rd_time_signed & 0xFF) as u8; + let time_s2 = (tsig_rd_time_signed >> 56) as u8; + let time_s3 = (tsig_rd_time_signed >> 48) as u8; + let time_s4 = (tsig_rd_time_signed >> 40) as u8; + let time_s5 = (tsig_rd_time_signed >> 32) as u8; + let time_s6 = (tsig_rd_time_signed >> 24) as u8; + res.push(time_s1); + res.push(time_s2); + res.push(time_s3); + res.push(time_s4); + res.push(time_s5); + res.push(time_s6); + let fudge1 = (tsig_rd_time_signed & 0xFF) as u8; + let fudge2 = (tsig_rd_time_signed >> 8) as u8; + res.push(fudge1); + res.push(fudge2); + + let error1 = (tsig_rd_error & 0xFF) as u8; + let error2 = (tsig_rd_error >> 8) as u8; + res.push(error1); + res.push(error2); + let otherl1 = (tsig_rd_other_len & 0xFF) as u8; + let otherl2 = (tsig_rd_other_len >> 8) as u8; + res.push(otherl1); + res.push(otherl2); + + res.extend(tsig_rd_other_data); + + return res; +} + +//TODO: actualizar sign_tsig usando la funcion get_digest_request +//RFC 8945, section 5.1 #[doc = r"This function creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64, key_name: String) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); + //let mut tsig_var_rr = TSIG::new(); + let mut tsig_var_rdata = TSigRdata::new(); + match alg_name { TsigAlgorithm::HmacSha1 => { + + //new_query_message.push(); let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&new_query_message.to_bytes()[..]); let result = hasher.result(); @@ -424,6 +496,7 @@ fn check_process_tsig() { assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); } +//Unitary test to verify that the signer function is properly working #[test] fn check_signed_tsig() { let key = b"1234567890"; From 7946484fb261add209fae07c3d086f75ab150384 Mon Sep 17 00:00:00 2001 From: Carlo Date: Mon, 8 Jul 2024 13:50:08 -0400 Subject: [PATCH 071/124] Refactor: Implemented set_tsig_rd into sign_tsig --- src/tsig.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 3edb1724..2ddb0943 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -50,8 +50,9 @@ fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: M return tsig_rd; } -#[doc = r"This function recives a DNS message and appends the TSIG variables requested by RFC 8946 4.3.3 "] -fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { +//TODO: crear una función para simplificar la extracción de bits paa simplificar código +#[doc = r"This function recives a DNS message and appends the TSIG variables. Requested by RFC 8945 4.3.3 "] +fn get_digest_request(dns_msg: Vec, tsig_rr: &ResourceRecord) -> Vec { let mut res: Vec = dns_msg.clone(); let tsig_rdata = tsig_rr.get_rdata(); res.extend(tsig_rr.get_name().to_bytes()); @@ -72,7 +73,6 @@ fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { res.push(r_ttl4); //processing TSIG RDATA - let tsig_rd = match tsig_rdata { Rdata::TSIG(tsig_rd) => tsig_rd, _ => panic!() @@ -124,8 +124,10 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut tsig_rd: TSigRdata = TSigRdata::new(); let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); - //let mut tsig_var_rr = TSIG::new(); + let mut resource_records = query_msg.get_additional(); + let tsig_rr = resource_records.last().unwrap(); let mut tsig_var_rdata = TSigRdata::new(); + let mut digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); match alg_name { @@ -133,7 +135,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm //new_query_message.push(); let mut hasher = crypto_hmac::new(Sha1::new(), key); - hasher.input(&new_query_message.to_bytes()[..]); + hasher.input(&digest_comp[..]); let result = hasher.result(); tsig_rd = set_tsig_rd(&new_query_message, "Hmac-Sha1".to_lowercase(), @@ -146,7 +148,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm }, TsigAlgorithm::HmacSha256 => { let mut hasher = crypto_hmac::new(Sha256::new(), key); - hasher.input(&new_query_message.to_bytes()[..]); + hasher.input(&digest_comp[..]); let result = hasher.result(); tsig_rd = set_tsig_rd(&new_query_message, "Hmac-Sha256".to_lowercase(), @@ -159,6 +161,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm }, _ => {panic!("Error: Invalid algorithm")}, } + 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)); @@ -166,6 +169,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm new_rr.set_rdlength(rr_len); let mut vec: Vec = vec![]; vec.push(new_rr); + query_msg.add_additionals(vec); return signature; } From 2615afcfd25ab4f5246bea4bc9a3c766d3b572d3 Mon Sep 17 00:00:00 2001 From: Carlo Date: Mon, 8 Jul 2024 17:23:56 -0400 Subject: [PATCH 072/124] Refact: test check_signed_tsig --- src/tsig.rs | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 2ddb0943..02ba0104 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,11 +1,14 @@ +use std::convert::TryInto; + //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; -use crate::message::class_qclass::Qclass; +use crate::message::class_qclass::{Qclass}; +use crate::message::class_rclass::Rclass; use crate::message::resource_record::{ResourceRecord, ToBytes}; use crate::message::type_qtype::Qtype; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage, class_rclass}; -use crate::message::rdata::{Rdata}; +use crate::message::rdata::{tsig_rdata, Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; @@ -52,7 +55,7 @@ fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: M } //TODO: crear una función para simplificar la extracción de bits paa simplificar código #[doc = r"This function recives a DNS message and appends the TSIG variables. Requested by RFC 8945 4.3.3 "] -fn get_digest_request(dns_msg: Vec, tsig_rr: &ResourceRecord) -> Vec { +fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { let mut res: Vec = dns_msg.clone(); let tsig_rdata = tsig_rr.get_rdata(); res.extend(tsig_rr.get_name().to_bytes()); @@ -125,7 +128,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); let mut resource_records = query_msg.get_additional(); - let tsig_rr = resource_records.last().unwrap(); + let tsig_rr = resource_records.pop().unwrap(); let mut tsig_var_rdata = TSigRdata::new(); let mut digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); @@ -508,20 +511,45 @@ fn check_signed_tsig() { let fudge = 0; let time_signed = 0; let id = 6502; + let name: String = "".to_string(); + let mac_size = 20; + let domain = DomainName::new_from_str("uchile.cl"); + //DNS message let mut q = DnsMessage::new_query_message( - DomainName::new_from_str("uchile.cl"), + domain.clone(), Qtype::A, Qclass::ANY, 0, false, id ); - let q_for_mac = q.clone(); - let key_name = "".to_string(); - let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed, key_name); + //TSIG Variables + // TSIG RDATA + let mut tsig_rd: TSigRdata = TSigRdata::new(); + tsig_rd.set_algorithm_name(domain.clone()); + tsig_rd.set_time_signed(time_signed); + tsig_rd.set_fudge(fudge); + tsig_rd.set_error(0); + tsig_rd.set_other_len(0); + // TSIG RR + let mut tsig_rr = ResourceRecord::new(Rdata::TSIG(tsig_rd)); + tsig_rr.set_name(domain.clone()); + //tsig_rr.set_rclass(Rclass::ANY); + tsig_rr.set_ttl(0); + + // append of the TSIG variables to the ADDITIONAL record in the DNS query + let mut tsig_additional = Vec::::new(); + tsig_additional.push(tsig_rr.clone()); + q.add_additionals(tsig_additional); + + 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); + // creation of the signature digest + let dig_for_mac = get_digest_request(q_for_mac.to_bytes(), tsig_rr); let mut hasher = crypto_hmac::new(Sha1::new(), key); - hasher.input(&q_for_mac.to_bytes()[..]); + hasher.input(&dig_for_mac[..]); let result = hasher.result(); let mac_to_cmp = result.code(); @@ -544,6 +572,7 @@ fn check_signed_tsig() { } println!("Comparando el mac"); for i in 0..mac_to_cmp.len() { + //println!("Comp: {} {}" ,mac_to_cmp[i], firma_a_comparar[i]); assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); } } From 8f6b0004adece60825c09eb86d2378b827206f80 Mon Sep 17 00:00:00 2001 From: Carlo Date: Mon, 8 Jul 2024 18:33:00 -0400 Subject: [PATCH 073/124] Refact: added a function to set the TSIG variables (thus, the resource record) in a DNS TSIG query to decrease redundant code --- src/tsig.rs | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 02ba0104..bc42893d 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -317,8 +317,29 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av (true, TsigErrorCode::NOERR) } +//Auxiliar function to create the TSIG variables and resource recrods +#[doc= r"This function helps to set TSIG variabes on a DNS query"] +fn set_tsig_vars(query_msg: &mut DnsMessage, alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> ResourceRecord{ + //TSIG Variables + // TSIG RDATA + let mut tsig_rd: TSigRdata = TSigRdata::new(); + tsig_rd.set_algorithm_name(DomainName::new_from_str(alg_name)); + tsig_rd.set_time_signed(time_signed); + tsig_rd.set_fudge(fudge); + tsig_rd.set_error(0); + tsig_rd.set_other_len(0); + // TSIG RR + let mut tsig_rr = ResourceRecord::new(Rdata::TSIG(tsig_rd)); + tsig_rr.set_name(DomainName::new_from_str(name)); + //tsig_rr.set_rclass(Rclass::ANY); + tsig_rr.set_ttl(0); + // append of the TSIG variables to the ADDITIONAL record in the DNS query + let mut tsig_additional = Vec::::new(); + tsig_additional.push(tsig_rr.clone()); + query_msg.add_additionals(tsig_additional); - + return tsig_rr +} //Sección de tests unitarios @@ -346,8 +367,15 @@ fn check_process_tsig_exists2() { let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); + let name = "test.com"; + set_tsig_vars(&mut response, "hmac-sha256", name, time_signed, fudge); + + // cloning response + let mut response2 = response.clone(); + + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone()); - sign_tsig(&mut response, server_key, alg_name2, fudge, time_signed, key_name.clone()); + sign_tsig(&mut response2, server_key, alg_name2, fudge, time_signed, key_name.clone()); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); @@ -523,25 +551,8 @@ fn check_signed_tsig() { false, id ); - //TSIG Variables - - // TSIG RDATA - let mut tsig_rd: TSigRdata = TSigRdata::new(); - tsig_rd.set_algorithm_name(domain.clone()); - tsig_rd.set_time_signed(time_signed); - tsig_rd.set_fudge(fudge); - tsig_rd.set_error(0); - tsig_rd.set_other_len(0); - // TSIG RR - let mut tsig_rr = ResourceRecord::new(Rdata::TSIG(tsig_rd)); - tsig_rr.set_name(domain.clone()); - //tsig_rr.set_rclass(Rclass::ANY); - tsig_rr.set_ttl(0); - - // append of the TSIG variables to the ADDITIONAL record in the DNS query - let mut tsig_additional = Vec::::new(); - tsig_additional.push(tsig_rr.clone()); - q.add_additionals(tsig_additional); + //TSIG Resource record + let mut tsig_rr = set_tsig_vars(&mut q, "hmac-sha1", &name, time_signed, fudge); let q_for_mac = q.clone(); //creation of the signature to compare From af953a11f96866d572fec40c38a09484402cf500 Mon Sep 17 00:00:00 2001 From: Carlo Date: Tue, 9 Jul 2024 12:52:00 -0400 Subject: [PATCH 074/124] Refactor: changed extraction of data & creation of resource records on sign_tsig --- src/tsig.rs | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index bc42893d..c434c67e 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,5 +1,5 @@ use std::convert::TryInto; - +use std::fmt::{self,Display,Debug}; //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; @@ -16,11 +16,20 @@ use crypto::{sha1::Sha1,sha2::Sha256}; use crate::message::rdata::a_rdata::ARdata; type HmacSha256 = Hmac; + +#[derive(Debug)] //TODO: usar arreglar el funcionamiento del enum en sign_msg pub enum TsigAlgorithm { HmacSha1, HmacSha256, } + +impl fmt::Display for TsigAlgorithm{ + fn fmt(&self, f: &mut fmt::Formatter) ->fmt::Result{ + write!(f, "{:?}", self) + } +} + #[derive(PartialEq)] #[derive(Debug)] pub enum TsigErrorCode{ @@ -128,8 +137,8 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); let mut resource_records = query_msg.get_additional(); - let tsig_rr = resource_records.pop().unwrap(); - let mut tsig_var_rdata = TSigRdata::new(); + let alg_name_str = alg_name.to_string(); + let tsig_rr= set_tsig_vars(query_msg, alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); let mut digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); match alg_name { @@ -164,7 +173,12 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm }, _ => {panic!("Error: Invalid algorithm")}, } - + if resource_records.len()>1 { + query_msg.set_additional(resource_records); + }else{ + let mut v: Vec = vec![]; + query_msg.set_additional(v); + } 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)); @@ -172,7 +186,6 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm new_rr.set_rdlength(rr_len); let mut vec: Vec = vec![]; vec.push(new_rr); - query_msg.add_additionals(vec); return signature; } @@ -318,7 +331,7 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av } //Auxiliar function to create the TSIG variables and resource recrods -#[doc= r"This function helps to set TSIG variabes on a DNS query"] +#[doc= r"This function helps to set create a partial TSIG resource record on a DNS query"] fn set_tsig_vars(query_msg: &mut DnsMessage, alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> ResourceRecord{ //TSIG Variables // TSIG RDATA @@ -333,10 +346,6 @@ fn set_tsig_vars(query_msg: &mut DnsMessage, alg_name: &str, name: &str, time_si tsig_rr.set_name(DomainName::new_from_str(name)); //tsig_rr.set_rclass(Rclass::ANY); tsig_rr.set_ttl(0); - // append of the TSIG variables to the ADDITIONAL record in the DNS query - let mut tsig_additional = Vec::::new(); - tsig_additional.push(tsig_rr.clone()); - query_msg.add_additionals(tsig_additional); return tsig_rr } @@ -368,12 +377,11 @@ fn check_process_tsig_exists2() { let time_signed = 21000; let key_name = "".to_string(); let name = "test.com"; - set_tsig_vars(&mut response, "hmac-sha256", name, time_signed, fudge); + // cloning response let mut response2 = response.clone(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone()); sign_tsig(&mut response2, server_key, alg_name2, fudge, time_signed, key_name.clone()); let mut response_capture = response.clone(); @@ -386,6 +394,7 @@ fn check_process_tsig_exists2() { assert_eq!(error, TsigErrorCode::FORMERR); } +// verificar que no se haya añadido otro resource record en el additionals luego de añadir un tsig_rr #[test] fn check_process_tsig_exists3(){ //Server process @@ -394,15 +403,18 @@ fn check_process_tsig_exists3(){ let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); - //necesito agregar algo más en el additional + let key_name = ""; + //se crea un rr TSIG que se añadirá en adittionals + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.to_string()); + + //se agrega otro resource record en el additional... let mut new_additional = Vec::::new(); let a_rdata5 = Rdata::A(ARdata::new()); let rr5 = ResourceRecord::new(a_rdata5); new_additional.push(rr5); response.add_additionals(new_additional); let mut response_capture = response.clone(); + //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; From c91b71fbca417c74043f8c6db06c555b9360c635 Mon Sep 17 00:00:00 2001 From: Carlo Date: Tue, 9 Jul 2024 12:55:49 -0400 Subject: [PATCH 075/124] Msg: Updated TODO --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index c434c67e..a1ab9241 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -128,7 +128,7 @@ fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { return res; } -//TODO: actualizar sign_tsig usando la funcion get_digest_request +//TODO: revisar que la creación del TSIG resourcerecord contenga efectivamente los campos del 8945, 4.3.3 //RFC 8945, section 5.1 #[doc = r"This function creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, From 43c3873f2fdcd3d921bfd9fb78b3bddbde2e29b0 Mon Sep 17 00:00:00 2001 From: Alonso Date: Wed, 10 Jul 2024 11:21:19 -0400 Subject: [PATCH 076/124] feat: added dnssec message processing --- Cargo.lock | 382 +++++++++++++++--------- Cargo.toml | 2 +- src/dnssec/dnssec_message_processing.rs | 39 +++ src/dnssec/rrset_signature.rs | 1 - src/message/rrset.rs | 120 +++++++- 5 files changed, 392 insertions(+), 152 deletions(-) create mode 100644 src/dnssec/dnssec_message_processing.rs diff --git a/Cargo.lock b/Cargo.lock index 219d74fd..17d77d11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -52,57 +52,58 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", @@ -111,15 +112,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ "addr2line", "cc", @@ -130,11 +131,17 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" -version = "1.3.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -147,24 +154,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -174,23 +178,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "clap" -version = "4.4.8" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -198,9 +202,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -210,9 +214,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", @@ -222,21 +226,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -273,6 +277,7 @@ name = "dns_rust" version = "0.1.0" dependencies = [ "async-trait", + "base64", "bytes", "chrono", "clap", @@ -296,15 +301,15 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -313,15 +318,15 @@ dependencies = [ [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-macro", @@ -349,9 +354,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -360,15 +365,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -376,15 +381,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -403,9 +408,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -424,26 +429,32 @@ dependencies = [ "cc", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.150" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -451,9 +462,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" @@ -466,35 +477,35 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -511,24 +522,24 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -536,22 +547,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -567,18 +578,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -662,9 +673,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ "bitflags", ] @@ -684,9 +695,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-serialize" @@ -713,9 +724,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -731,25 +742,25 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -759,9 +770,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -770,18 +781,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -801,9 +812,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.35.1" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -815,14 +826,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -854,9 +865,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" @@ -878,9 +889,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -888,9 +899,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -903,9 +914,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -913,9 +924,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -926,9 +937,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "winapi" @@ -954,11 +965,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] @@ -967,7 +978,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", ] [[package]] @@ -976,13 +996,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -991,56 +1027,104 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index d17a210e..05e94d48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ async-trait = "0.1.77" sha2 = "0.10.2" hmac = "0.12.1" rust-crypto = "0.2" -base = "0.12.3" +base64 = "0.22.1" lru = "0.12.3" diff --git a/src/dnssec/dnssec_message_processing.rs b/src/dnssec/dnssec_message_processing.rs new file mode 100644 index 00000000..17866a15 --- /dev/null +++ b/src/dnssec/dnssec_message_processing.rs @@ -0,0 +1,39 @@ +use crate::message::DnsMessage; +use crate::message::rdata::{rrsig_rdata, dnskey_rdata, ds_rdata, nsec_rdata, nsec3_rdata}; + +// DNSKEY, RRSIG, DS | NSEC, NSEC3 ? + +fn extract_dnssec_records(dns_message: &DnsMessage) -> (Vec, Vec, Vec) { + let mut dnskey_records = Vec::new(); + let mut rrsig_records = Vec::new(); + let mut ds_records = Vec::new(); + + for record in &dns_message.additional { + match record.rdata { + Rdata::DNSKEY(ref data) => { + let dnskey_rdata = DnskeyRdata::new(data.flags, data.protocol, data.algorithm, data.public_key.clone()); + dnskey_records.push(dnskey_rdata); + } + Rdata::RRSIG(ref data) => { + let rrsig_rdata = RrsigRdata::new( + data.type_covered, + data.algorithm, + data.labels, + data.original_ttl, + //datatime? expiration/inception + data.key_tag, + data.signer_name.clone(), + data.signature.clone() + ); + rrsig_records.push(rrsig_rdata); + } + Rdata::DS(ref data) => { + let ds_rdata = DsRdata::new(data.key_tag, data.algorithm, data.digest_type, data.digest.clone() + ); + ds_records.push(ds_rdata); + }, + _ => (), + } + } + (dnskey_records, rrsig_records, ds_records) +} \ No newline at end of file diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index 853f916c..d230790c 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -85,4 +85,3 @@ pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Resu public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") } - diff --git a/src/message/rrset.rs b/src/message/rrset.rs index bca9953c..00e5d0a9 100644 --- a/src/message/rrset.rs +++ b/src/message/rrset.rs @@ -60,8 +60,126 @@ impl RRset { &self.records } - // Gets the labels of the domain associated with this RRset. + /// Gets the labels of the domain associated with this RRset. pub fn get_labels(&self) -> usize { self.name.split('.').count() } + + /// Serializes the RRset to a byte array for signing. + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + for record in &self.records { + bytes.extend(record.to_bytes()); // Assuming ResourceRecord has a to_bytes method + } + bytes + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::message::Rtype; + use crate::message::Rclass; + use crate::message::resource_record::{ResourceRecord, Rdata, ARdata, NsRdata, CnameRdata}; + use std::net::IpAddr; + use std::collections::HashSet; + + #[test] + fn test_create_rrset() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_name(), &name); + assert_eq!(rrset.get_type(), Rtype::A); + assert_eq!(rrset.get_class(), Rclass::IN); + assert_eq!(rrset.get_ttl(), 3600); + assert_eq!(rrset.get_labels(), 2); + assert!(rrset.get_records().is_empty()); + } + + #[test] + fn test_add_record() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let mut rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + let mut a_rdata = Rdata::A(ARdata::new()); + match a_rdata { + Rdata::A(ref mut val) => val.set_address(IpAddr::from([127, 0, 0, 1])), + _ => unreachable!(), + } + + let record = ResourceRecord::new(a_rdata); + rrset.add_record(record); + + assert_eq!(rrset.get_records().len(), 1); + } + + #[test] + fn test_get_name() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_name(), &name); + } + + #[test] + fn test_get_type() { + let name = "example.com".to_string(); + let rtype = Rtype::NS; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_type(), Rtype::NS); + } + + #[test] + fn test_get_class() { + let name = "example.com".to_string(); + let rtype = Rtype::MX; + let rclass = Rclass::CH; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_class(), Rclass::CH); + } + + #[test] + fn test_get_ttl() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 7200; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_ttl(), 7200); + } + + #[test] + fn test_get_labels() { + let name = "sub.example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_labels(), 3); + } } From 691462bd22203938131cb64a710d55db1393d959 Mon Sep 17 00:00:00 2001 From: Carlo Date: Wed, 10 Jul 2024 13:14:54 -0400 Subject: [PATCH 077/124] Fix: deleted a faulty fragment of code in sign_tsig --- src/tsig.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index a1ab9241..30d3b2b3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -63,7 +63,8 @@ fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: M return tsig_rd; } //TODO: crear una función para simplificar la extracción de bits paa simplificar código -#[doc = r"This function recives a DNS message and appends the TSIG variables. Requested by RFC 8945 4.3.3 "] +// This function extracts the digest +#[doc = r"This function recives a DNS message and generate the digest da. Requested by RFC 8945 4.3.3 "] fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { let mut res: Vec = dns_msg.clone(); let tsig_rdata = tsig_rr.get_rdata(); @@ -173,12 +174,6 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm }, _ => {panic!("Error: Invalid algorithm")}, } - if resource_records.len()>1 { - query_msg.set_additional(resource_records); - }else{ - let mut v: Vec = vec![]; - query_msg.set_additional(v); - } 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)); @@ -377,18 +372,18 @@ fn check_process_tsig_exists2() { let time_signed = 21000; let key_name = "".to_string(); let name = "test.com"; - - // cloning response let mut response2 = response.clone(); sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone()); - sign_tsig(&mut response2, server_key, alg_name2, fudge, time_signed, key_name.clone()); let mut response_capture = response.clone(); + sign_tsig(&mut response_capture, server_key, alg_name2, fudge, time_signed, key_name.clone()); //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha256"),true)); + let (control_answer, _) = process_tsig(& response, server_key, key_name.clone(),21010, lista.clone()); + assert!(control_answer); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); assert!(!answer); assert_eq!(error, TsigErrorCode::FORMERR); @@ -563,9 +558,8 @@ fn check_signed_tsig() { false, id ); - //TSIG Resource record + //partial TSIG Resource record verify the signing process let mut tsig_rr = set_tsig_vars(&mut q, "hmac-sha1", &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); @@ -595,7 +589,6 @@ fn check_signed_tsig() { } println!("Comparando el mac"); for i in 0..mac_to_cmp.len() { - //println!("Comp: {} {}" ,mac_to_cmp[i], firma_a_comparar[i]); assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); } } From dfb8b0f847886ed87ae17b61df530bf15604d125 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 3 Jul 2024 12:00:49 -0400 Subject: [PATCH 078/124] Chore: Changed documentation z flag --- src/message/header.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message/header.rs b/src/message/header.rs index cfa007ec..e054e1dd 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -423,7 +423,7 @@ impl Header { return Err("Format Error: OP CODE"); } - // Z: A 3 bit field that MUST be zero + // Z: A z flag field MUST be zero/false if self.z != false { return Err("Format Error: Z"); } From 0bfd3dd6caa8104c71892054cc16ea79cd5ef294 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 3 Jul 2024 12:01:34 -0400 Subject: [PATCH 079/124] fix: no more using empty string in process_tsig --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 30d3b2b3..efec109a 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -302,7 +302,7 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av let fudge = tsig_rr_copy.get_fudge(); let time_signed = tsig_rr_copy.get_time_signed(); let mac_received = tsig_rr_copy.get_mac(); - let key_name = "".to_string(); + let key_name = rr_copy.get_name().get_name(); let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; match name_alg.as_str() { "hmac-sha1" => new_alg_name = TsigAlgorithm::HmacSha1, From 273d66ce253bc32bb777e3794ca92b631fa0dddb Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 10 Jul 2024 15:11:12 -0400 Subject: [PATCH 080/124] change order get_digest_request --- src/tsig.rs | 62 ++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index efec109a..b7dc60c6 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -70,16 +70,17 @@ fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { let tsig_rdata = tsig_rr.get_rdata(); res.extend(tsig_rr.get_name().to_bytes()); //processing TSIG RR - let rclass_bytes: u16 = u16::to_be(class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass())); - let rclass_lbyte = (rclass_bytes & 0xFF) as u8; + let rclass_bytes: u16 = class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass()); + let rclass_lbyte = rclass_bytes as u8; let rclass_ubyte = (rclass_bytes >> 8) as u8; - res.push(rclass_lbyte); res.push(rclass_ubyte); - let rclass_ttl: u32 = u32::to_be(tsig_rr.get_ttl()); - let r_ttl1 = (rclass_ttl & 0xFF) as u8; - let r_ttl2 = (rclass_ttl >> 24) as u8; - let r_ttl3 = (rclass_ttl >>16) as u8; - let r_ttl4 = (rclass_ttl >>8) as u8; + res.push(rclass_lbyte); + + let rclass_ttl: u32 = tsig_rr.get_ttl(); + let r_ttl1 = (rclass_ttl >> 24) as u8; + let r_ttl2 = (rclass_ttl >> 16) as u8; + let r_ttl3 = (rclass_ttl >> 8) as u8; + let r_ttl4 = rclass_ttl as u8; res.push(r_ttl1); res.push(r_ttl2); res.push(r_ttl3); @@ -91,36 +92,39 @@ fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { _ => panic!() }; let a_name = tsig_rd.get_algorithm_name().to_bytes(); - let tsig_rd_time_signed: u64 = u64::to_be(tsig_rd.get_time_signed()); - let tsig_rd_fudge: u16 = u16::to_be(tsig_rd.get_fudge()); - let tsig_rd_error: u16= u16::to_be(tsig_rd.get_error()); - let tsig_rd_other_len: u16 = u16::to_be(tsig_rd.get_other_len()); + let tsig_rd_time_signed: u64 = tsig_rd.get_time_signed(); + let tsig_rd_fudge: u16 = tsig_rd.get_fudge(); + let tsig_rd_error: u16= tsig_rd.get_error(); + let tsig_rd_other_len: u16 = tsig_rd.get_other_len(); let tsig_rd_other_data = tsig_rd.get_other_data(); + res.extend(a_name); - - let time_s1 = (tsig_rd_time_signed & 0xFF) as u8; - let time_s2 = (tsig_rd_time_signed >> 56) as u8; - let time_s3 = (tsig_rd_time_signed >> 48) as u8; - let time_s4 = (tsig_rd_time_signed >> 40) as u8; - let time_s5 = (tsig_rd_time_signed >> 32) as u8; - let time_s6 = (tsig_rd_time_signed >> 24) as u8; + + let time_s6 = (tsig_rd_time_signed) as u8; + let time_s5 = (tsig_rd_time_signed >> 8) as u8; + let time_s4 = (tsig_rd_time_signed >> 16) as u8; + let time_s3 = (tsig_rd_time_signed >> 24) as u8; + let time_s2 = (tsig_rd_time_signed >> 32) as u8; + let time_s1 = (tsig_rd_time_signed >> 40) as u8; res.push(time_s1); res.push(time_s2); res.push(time_s3); res.push(time_s4); res.push(time_s5); res.push(time_s6); - let fudge1 = (tsig_rd_time_signed & 0xFF) as u8; - let fudge2 = (tsig_rd_time_signed >> 8) as u8; + + let fudge1 = (tsig_rd_fudge >> 8) as u8; + let fudge2 = (tsig_rd_fudge ) as u8; res.push(fudge1); res.push(fudge2); - let error1 = (tsig_rd_error & 0xFF) as u8; - let error2 = (tsig_rd_error >> 8) as u8; + let error1 = (tsig_rd_error >> 8) as u8; + let error2 = (tsig_rd_error) as u8; res.push(error1); res.push(error2); - let otherl1 = (tsig_rd_other_len & 0xFF) as u8; - let otherl2 = (tsig_rd_other_len >> 8) as u8; + + let otherl1 = (tsig_rd_other_len >> 8) as u8; + let otherl2 = (tsig_rd_other_len) as u8; res.push(otherl1); res.push(otherl2); @@ -135,12 +139,11 @@ fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, fudge: u16, time_signed: u64, key_name: String) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); - let mut new_query_message = query_msg.clone(); + let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); - let mut resource_records = query_msg.get_additional(); let alg_name_str = alg_name.to_string(); let tsig_rr= set_tsig_vars(query_msg, alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); - let mut digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); + let digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); match alg_name { @@ -559,12 +562,13 @@ fn check_signed_tsig() { id ); //partial TSIG Resource record verify the signing process - let mut tsig_rr = set_tsig_vars(&mut q, "hmac-sha1", &name, time_signed, fudge); + let tsig_rr = set_tsig_vars(&mut q, "hmac-sha1", &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); // creation of the signature digest let dig_for_mac = get_digest_request(q_for_mac.to_bytes(), tsig_rr); + let dig_for_mac = dig_for_mac[0..=55].to_vec(); let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&dig_for_mac[..]); From 498bb71c6ce173916de17990e2fb492bed316955 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 10 Jul 2024 16:14:15 -0400 Subject: [PATCH 081/124] Refactor: Extracted tsig_alg_to_string function to improve code readability and reduce redundancy --- src/tsig.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index b7dc60c6..79a79ce0 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -24,9 +24,10 @@ pub enum TsigAlgorithm { HmacSha256, } -impl fmt::Display for TsigAlgorithm{ - fn fmt(&self, f: &mut fmt::Formatter) ->fmt::Result{ - write!(f, "{:?}", self) +fn tsig_alg_to_string(alg: &TsigAlgorithm) -> String { + match alg { + TsigAlgorithm::HmacSha1 => "hmac-sha1".to_string(), + TsigAlgorithm::HmacSha256 => "hmac-sha256".to_string(), } } @@ -141,7 +142,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut tsig_rd: TSigRdata = TSigRdata::new(); let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); - let alg_name_str = alg_name.to_string(); + let alg_name_str = tsig_alg_to_string(&alg_name); let tsig_rr= set_tsig_vars(query_msg, alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); let digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); @@ -154,7 +155,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm hasher.input(&digest_comp[..]); let result = hasher.result(); tsig_rd = set_tsig_rd(&new_query_message, - "Hmac-Sha1".to_lowercase(), + "hmac-sha1".to_lowercase(), original_id, result, fudge, @@ -167,7 +168,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm hasher.input(&digest_comp[..]); let result = hasher.result(); tsig_rd = set_tsig_rd(&new_query_message, - "Hmac-Sha256".to_lowercase(), + "hmac-sha256".to_lowercase(), original_id, result, fudge, @@ -562,7 +563,7 @@ fn check_signed_tsig() { id ); //partial TSIG Resource record verify the signing process - let tsig_rr = set_tsig_vars(&mut q, "hmac-sha1", &name, time_signed, fudge); + let tsig_rr = set_tsig_vars(&mut q, tsig_alg_to_string(&alg_name).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); From 581aff0693610ede81ce78fbe8e429bb0a0eb4c3 Mon Sep 17 00:00:00 2001 From: Carlo Date: Wed, 10 Jul 2024 16:39:46 -0400 Subject: [PATCH 082/124] refactor: removed the unused DNSmesages on set_tsig_vars and set_tsig_rd Deleted a unnecesary line in check_signed_tsig --- src/tsig.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 79a79ce0..72d609f5 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -43,7 +43,7 @@ pub enum TsigErrorCode{ } //TODO: Encontrar alguna manera de pasar una referencia Digest u Hmac de un algoritmo no especificado // función auxiliar para evitar la redundancia de código en sign_tsig -fn set_tsig_rd(query_msg: &DnsMessage, name: String, original_id: u16, result: MacResult, +fn set_tsig_rd(name: String, original_id: u16, result: MacResult, fudge: u16, time_signed: u64, mac_size: u16) -> TSigRdata{ let mut tsig_rd: TSigRdata = TSigRdata::new(); let mac = result.code(); @@ -143,7 +143,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); let alg_name_str = tsig_alg_to_string(&alg_name); - let tsig_rr= set_tsig_vars(query_msg, alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); + let tsig_rr= set_tsig_vars( alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); let digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); match alg_name { @@ -154,7 +154,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&digest_comp[..]); let result = hasher.result(); - tsig_rd = set_tsig_rd(&new_query_message, + tsig_rd = set_tsig_rd( "hmac-sha1".to_lowercase(), original_id, result, @@ -167,7 +167,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let mut hasher = crypto_hmac::new(Sha256::new(), key); hasher.input(&digest_comp[..]); let result = hasher.result(); - tsig_rd = set_tsig_rd(&new_query_message, + tsig_rd = set_tsig_rd( "hmac-sha256".to_lowercase(), original_id, result, @@ -331,7 +331,7 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av } //Auxiliar function to create the TSIG variables and resource recrods #[doc= r"This function helps to set create a partial TSIG resource record on a DNS query"] -fn set_tsig_vars(query_msg: &mut DnsMessage, alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> ResourceRecord{ +fn set_tsig_vars(alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> ResourceRecord{ //TSIG Variables // TSIG RDATA let mut tsig_rd: TSigRdata = TSigRdata::new(); @@ -542,7 +542,7 @@ fn check_process_tsig() { assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); } -//Unitary test to verify that the signer function is properly working +//Unitary test to verify that the signer function is working properly #[test] fn check_signed_tsig() { let key = b"1234567890"; @@ -563,13 +563,12 @@ fn check_signed_tsig() { id ); //partial TSIG Resource record verify the signing process - let tsig_rr = set_tsig_vars(&mut q, tsig_alg_to_string(&alg_name).as_str(), &name, time_signed, fudge); + let tsig_rr = set_tsig_vars(tsig_alg_to_string(&alg_name).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); // creation of the signature digest let dig_for_mac = get_digest_request(q_for_mac.to_bytes(), tsig_rr); - let dig_for_mac = dig_for_mac[0..=55].to_vec(); let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&dig_for_mac[..]); From 142ba4e8339ab9ab09688700fbfd05335fde987c Mon Sep 17 00:00:00 2001 From: Alonso Date: Thu, 11 Jul 2024 21:50:00 -0400 Subject: [PATCH 083/124] feat: added extract_dnssec_records method to message --- src/message.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/message.rs b/src/message.rs index b6b20fc9..7f2e3f6f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -894,6 +894,18 @@ impl DnsMessage { } } + pub fn extract_dnssec_records(&self) -> Vec { + let mut dnssec_records = Vec::new(); + + for record in self.additional.iter() { + if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { + dnssec_records.push(dnskey.clone()); + } + } + + dnssec_records + } + } impl fmt::Display for DnsMessage { From 9d6d40ea01a504e3938079078b8e98b8a9e9faf8 Mon Sep 17 00:00:00 2001 From: Alonso Date: Thu, 11 Jul 2024 22:04:45 -0400 Subject: [PATCH 084/124] feat: added dnssec module --- src/dnssec/dnssec.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/dnssec/dnssec.rs diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs new file mode 100644 index 00000000..fb49a618 --- /dev/null +++ b/src/dnssec/dnssec.rs @@ -0,0 +1,60 @@ +// src/dnssec.rs + +pub mod dnssec { + use super::message::{DnskeyRdata, RrsigRdata, DsRdata, DnsMessage, DnsError}; + use sha2::{Sha256, Sha512, Digest}; + use hmac::{Hmac, Mac, NewMac}; + use rust_crypto::rsa::{RSAPublicKey, RSAVerify}; + use base64::decode; + + pub fn fetch_dnskey_records(domain: &str) -> Result, DnsError> { + // Completar + Ok(vec![DnskeyRdata::new(256, 3, 8, vec![0x03, 0x01, 0x00, 0x01])]) + } + + pub fn verify_rrsig_signature( + rrsig: &RrsigRdata, + dnskey: &DnskeyRdata, + signed_data: &[u8] + ) -> Result { + rsa_verify(&dnskey.public_key, &rrsig.signature, signed_data) + } + + pub fn verify_ds_record( + ds: &DsRdata, + dnskey: &DnskeyRdata + ) -> Result { + let digest = compute_digest(ds.algorithm, &dnskey.to_bytes())?; + Ok(digest == ds.digest) + } + + fn rsa_verify( + public_key: &[u8], + signature: &[u8], + signed_data: &[u8] + ) -> Result { + let public_key = RSAPublicKey::from_der(public_key).map_err(|_| DnsError::VerificationFailed)?; + public_key.verify(signature, signed_data).map_err(|_| DnsError::VerificationFailed)?; + + Ok(true) + } + + fn compute_digest( + algorithm: u8, + data: &[u8] + ) -> Result, DnsError> { + match algorithm { + 1 => { + let mut hasher = Sha256::new(); + hasher.update(data); + Ok(hasher.finalize().to_vec()) + }, + 2 => { + let mut hasher = Sha512::new(); + hasher.update(data); + Ok(hasher.finalize().to_vec()) + }, + _ => Err(DnsError::UnsupportedAlgorithm), + } + } +} From 549c3211e4cb33583de2dbcf3eac2ef7bcdce806 Mon Sep 17 00:00:00 2001 From: Alonso Date: Fri, 12 Jul 2024 02:16:29 -0400 Subject: [PATCH 085/124] feat: added DnsErrors and decrypting --- src/dnssec/dnssec.rs | 78 +++++-------- src/dnssec/dnssec_message_processing.rs | 44 ++----- src/dnssec/rrset_signature.rs | 148 +++++++++++------------- src/message.rs | 12 -- 4 files changed, 108 insertions(+), 174 deletions(-) diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs index fb49a618..a25d22d0 100644 --- a/src/dnssec/dnssec.rs +++ b/src/dnssec/dnssec.rs @@ -1,60 +1,34 @@ -// src/dnssec.rs +use crate::client::ClientUDPConnection; +use crate::message::{DnsMessage, ResourceRecord}; +use crate::dnssec_message_processing::extract_dnssec_records; +use crate::rrset_signature::{verify_rrsig, verify_ds}; +use crate::dnskey_rdata::DnskeyRdata; +use crate::client::client_error::ClientError; +use std::net::IpAddr; +use tokio::time::Duration; -pub mod dnssec { - use super::message::{DnskeyRdata, RrsigRdata, DsRdata, DnsMessage, DnsError}; - use sha2::{Sha256, Sha512, Digest}; - use hmac::{Hmac, Mac, NewMac}; - use rust_crypto::rsa::{RSAPublicKey, RSAVerify}; - use base64::decode; +pub async fn fetch_dnskey_records(domain: &str, server_addr: IpAddr, timeout_duration: Duration) -> Result, ClientError> { + let conn = ClientUDPConnection::new(server_addr, timeout_duration); - pub fn fetch_dnskey_records(domain: &str) -> Result, DnsError> { - // Completar - Ok(vec![DnskeyRdata::new(256, 3, 8, vec![0x03, 0x01, 0x00, 0x01])]) - } - - pub fn verify_rrsig_signature( - rrsig: &RrsigRdata, - dnskey: &DnskeyRdata, - signed_data: &[u8] - ) -> Result { - rsa_verify(&dnskey.public_key, &rrsig.signature, signed_data) - } + let dns_query = DnsMessage::new_query_message( + domain.into(), + Qtype::DNSKEY, + Qclass::IN, + 0, + false, + 1, + ); - pub fn verify_ds_record( - ds: &DsRdata, - dnskey: &DnskeyRdata - ) -> Result { - let digest = compute_digest(ds.algorithm, &dnskey.to_bytes())?; - Ok(digest == ds.digest) - } + let response = conn.send(dns_query).await?; - fn rsa_verify( - public_key: &[u8], - signature: &[u8], - signed_data: &[u8] - ) -> Result { - let public_key = RSAPublicKey::from_der(public_key).map_err(|_| DnsError::VerificationFailed)?; - public_key.verify(signature, signed_data).map_err(|_| DnsError::VerificationFailed)?; + let dns_response = DnsMessage::from_bytes(&response)?; + let mut dnskey_records = Vec::new(); - Ok(true) - } - - fn compute_digest( - algorithm: u8, - data: &[u8] - ) -> Result, DnsError> { - match algorithm { - 1 => { - let mut hasher = Sha256::new(); - hasher.update(data); - Ok(hasher.finalize().to_vec()) - }, - 2 => { - let mut hasher = Sha512::new(); - hasher.update(data); - Ok(hasher.finalize().to_vec()) - }, - _ => Err(DnsError::UnsupportedAlgorithm), + for record in dns_response.get_answer() { + if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { + dnskey_records.push(dnskey.clone()); } } + + Ok(dnskey_records) } diff --git a/src/dnssec/dnssec_message_processing.rs b/src/dnssec/dnssec_message_processing.rs index 17866a15..783e32a6 100644 --- a/src/dnssec/dnssec_message_processing.rs +++ b/src/dnssec/dnssec_message_processing.rs @@ -1,39 +1,19 @@ -use crate::message::DnsMessage; -use crate::message::rdata::{rrsig_rdata, dnskey_rdata, ds_rdata, nsec_rdata, nsec3_rdata}; +use crate::message::{DnsMessage, Rdata, ResourceRecord}; -// DNSKEY, RRSIG, DS | NSEC, NSEC3 ? +pub fn extract_dnssec_records(dns_response: &DnsMessage) -> (Vec, Vec) { + let answers = dns_response.get_answer(); + let additionals = dns_response.get_additional(); -fn extract_dnssec_records(dns_message: &DnsMessage) -> (Vec, Vec, Vec) { let mut dnskey_records = Vec::new(); let mut rrsig_records = Vec::new(); - let mut ds_records = Vec::new(); - for record in &dns_message.additional { - match record.rdata { - Rdata::DNSKEY(ref data) => { - let dnskey_rdata = DnskeyRdata::new(data.flags, data.protocol, data.algorithm, data.public_key.clone()); - dnskey_records.push(dnskey_rdata); - } - Rdata::RRSIG(ref data) => { - let rrsig_rdata = RrsigRdata::new( - data.type_covered, - data.algorithm, - data.labels, - data.original_ttl, - //datatime? expiration/inception - data.key_tag, - data.signer_name.clone(), - data.signature.clone() - ); - rrsig_records.push(rrsig_rdata); - } - Rdata::DS(ref data) => { - let ds_rdata = DsRdata::new(data.key_tag, data.algorithm, data.digest_type, data.digest.clone() - ); - ds_records.push(ds_rdata); - }, - _ => (), + for record in answers.iter().chain(additionals.iter()) { + match record.get_rdata() { + Rdata::DNSKEY(_) => dnskey_records.push(record.clone()), + Rdata::RRSIG(_) => rrsig_records.push(record.clone()), + _ => {} } } - (dnskey_records, rrsig_records, ds_records) -} \ No newline at end of file + + (dnskey_records, rrsig_records) +} diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index d230790c..ff13c55a 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -1,87 +1,79 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; -use base64; +use sha2::{Sha256, Digest}; +use rust_crypto::digest::Digest as RustDigest; +use rust_crypto::sha1::Sha1; +use base64::encode; +use crate::message::rdata::{DnskeyRdata, RrsigRdata, Rdata}; +use crate::message::resource_record::ResourceRecord; +use crate::client::client_error::ClientError; -/// RFCs: [4033, 4034, 4035, 4509] +pub fn verify_rrsig(rrsig: &RrsigRdata, dnskey: &DnskeyRdata, rrset: &[ResourceRecord]) -> Result { + let mut rrsig_data = Vec::new(); + rrsig_data.extend_from_slice(&rrsig.type_covered.to_be_bytes()); + rrsig_data.push(rrsig.algorithm); + rrsig_data.push(rrsig.labels); + rrsig_data.extend_from_slice(&rrsig.original_ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.expiration.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.inception.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.key_tag.to_be_bytes()); + rrsig_data.extend_from_slice(rrsig.signer_name.to_bytes()?); -/// Signs a RRset using the private_key given. -/// Returns a RRSIG that contains the signature. -pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; - - let rrsig = RRSIGRdata { - type_covered: rrset.get_type(), - algorithm, - labels: rrset.get_labels(), - original_ttl: rrset.get_ttl(), - signature_expiration: get_expiration_time(), - signature_inception: get_inception_time(), - key_tag: calculate_key_tag(private_key), - signer_name: rrset.get_name().clone(), - signature: base64::encode(&signature), - }; - - Ok(rrsig) -} + let mut rrset_sorted = rrset.to_vec(); + rrset_sorted.sort_by(|a, b| a.name.cmp(&b.name)); -// Gets the expiration time for the signature. -fn get_expiration_time() -> u32 { - // Supposing sign validity = 1 day (86400 seconds) - let now = std::time::SystemTime::now(); - let expiration_duration = std::time::Duration::new(86400, 0); - let expiration_time = now + expiration_duration; - expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} + for rr in rrset_sorted.iter() { + rrsig_data.extend_from_slice(rr.name.to_bytes()?); + rrsig_data.extend_from_slice(&rr.ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&(rr.rdata.to_bytes().len() as u16).to_be_bytes()); + rrsig_data.extend_from_slice(&rr.rdata.to_bytes()?); + } -// Gets the inception time for the signature. -fn get_inception_time() -> u32 { - // Assuming current time - let now = std::time::SystemTime::now(); - now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} + let signature = rrsig.signature.clone(); + let mut hasher = Sha256::new(); + hasher.update(rrsig_data); + let hashed = hasher.finalize(); -// Calculates the key tag for the public key. -fn calculate_key_tag(private_key: &Rsa) -> u16 { - let public_key_der = private_key.to_public_key_der().unwrap(); - let mut hasher = Sha1::new(); - hasher.input(&public_key_der); - let hash = hasher.result_str(); - u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) + match dnskey.algorithm { + 3 => { + //DSA/SHA1 + let mut sha1 = Sha1::new(); + sha1.input(&rrsig_data); + let digest = sha1.result_str(); + Ok(digest == encode(&signature)) + }, + 5 => { + //RSA/SHA1 + let mut sha1 = Sha1::new(); + sha1.input(&rrsig_data); + let digest = sha1.result_str(); + Ok(digest == encode(&signature)) + }, + 8 => { + //RSA/SHA256 + let hashed = Sha256::digest(&rrsig_data); + Ok(encode(&hashed) == encode(&signature)) + }, + _ => Err(ClientError::new("Unknown DNSKEY algorithm")), + } } -/// RFCs: [4033, 4034, 4035, 5702] +pub fn verify_ds(ds_record: &ResourceRecord, dnskey: &DnskeyRdata) -> Result { + if let Rdata::DS(ds_rdata) = &ds_record.get_rdata() { + let dnskey_bytes = dnskey.to_bytes()?; + let hashed_key = match ds_rdata.algorithm { + 1 => { + let mut hasher = Sha1::new(); + hasher.input(&dnskey_bytes); + hasher.result_str() + }, + 2 => { + let hashed = Sha256::digest(&dnskey_bytes); + encode(&hashed) + }, + _ => return Err(ClientError::new("Unknown DS algorithm")), + }; -/// Verifies an RRset using the provided public key and RRSIG record. -/// Returns true if the verification is successful. -pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match rrsig.algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; - - public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") + Ok(ds_rdata.digest == hashed_key) + } else { + Err(ClientError::new("Provided record is not a DS record")) + } } diff --git a/src/message.rs b/src/message.rs index 7f2e3f6f..b6b20fc9 100644 --- a/src/message.rs +++ b/src/message.rs @@ -894,18 +894,6 @@ impl DnsMessage { } } - pub fn extract_dnssec_records(&self) -> Vec { - let mut dnssec_records = Vec::new(); - - for record in self.additional.iter() { - if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { - dnssec_records.push(dnskey.clone()); - } - } - - dnssec_records - } - } impl fmt::Display for DnsMessage { From 42e435b96f808b7b7b008e0a404daded06dcc135 Mon Sep 17 00:00:00 2001 From: Alonso Date: Fri, 12 Jul 2024 10:21:42 -0400 Subject: [PATCH 086/124] fix: deleted unused files --- src/dnssec/dnssec_decryption.rs | 0 src/dnssec/dnssec_encryption.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/dnssec/dnssec_decryption.rs delete mode 100644 src/dnssec/dnssec_encryption.rs diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs deleted file mode 100644 index e69de29b..00000000 From 238005d8fc64dba2ebac5b5fa7d024a34b8cd478 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 12 Jul 2024 12:00:35 -0400 Subject: [PATCH 087/124] Refact: moved the tsig-related test(s) from "integration_tests.rs" to "tsig_integration_tests.rs --- tests/integration_test.rs | 63 -------------------------------- tests/tsig_integration_tests.rs | 65 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 63 deletions(-) create mode 100644 tests/tsig_integration_tests.rs diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 542a7559..ab0dbfa3 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -110,66 +110,3 @@ async fn no_resource_available() { assert!(response.is_err()); } - -///RFC 8945 TSIG tests -#[tokio::test] -async fn tsig_signature() { - // global test variables - let key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 0; - let time_signed = 0; - let id = 6502; - let mut dns_query_message = - DnsMessage::new_query_message( - DomainName::new_from_string("nictest.cl".to_string()), - type_qtype::Qtype::A, - Qclass::IN, - 0, - false, - id); - let q_for_mac = dns_query_message.clone(); - //Lanzamiento de threads - //Se lanza el servidor. Recibe un mensaje sin firmar, lo firma y lo reenvía - fn host(){ - println!("I am a host"); - let udp_socket = UdpSocket::bind("127.0.0.1:8002").expect("Failed to bind to address"); - let mut buf = [0; 512]; - - match udp_socket.recv_from(&mut buf) { - - Ok((size, source)) => { - println!("Received {} bytes from {}", size, source); - let mut data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); - println!("The data is {:?}", data); - let key_name = "".to_string(); - tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0, key_name); - let response = &DnsMessage::to_bytes(&data); - udp_socket - .send_to(&response, source) - .expect("Failed to send response"); - - } - Err(e) => { - eprintln!("Error receiving data: {}", e); - - } - } - - } - println!("Starting server"); - let server_handle = thread::spawn(|| { - host(); - - }); - thread::sleep(Duration::from_secs(2)); - // se instancia un socket cliente que enviará y mensajes - let client_sock = UdpSocket::bind("127.0.0.1:8001").expect("Nothing"); - let buf = dns_query_message.to_bytes(); - client_sock.send_to(&buf,"127.0.0.1:8002").unwrap(); - println!("Mensaje enviado"); - server_handle.join().unwrap(); - - -} - \ No newline at end of file diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs new file mode 100644 index 00000000..7b229f23 --- /dev/null +++ b/tests/tsig_integration_tests.rs @@ -0,0 +1,65 @@ +use std::{net::IpAddr, str::FromStr, thread, net::UdpSocket, time::Duration}; +use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata,class_qclass::Qclass, type_qtype, resource_record::ResourceRecord, header::Header, DnsMessage},tsig::{self, TsigAlgorithm}}; + +///RFC 8945 TSIG tests +#[tokio::test] +async fn tsig_signature() { + // global test variables + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 0; + let time_signed = 0; + let id = 6502; + let mut dns_query_message = + DnsMessage::new_query_message( + DomainName::new_from_string("nictest.cl".to_string()), + type_qtype::Qtype::A, + Qclass::IN, + 0, + false, + id); + let q_for_mac = dns_query_message.clone(); + //Lanzamiento de threads + //Se lanza el servidor. Recibe un mensaje sin firmar, lo firma y lo reenvía + fn host(){ + println!("I am a host"); + let udp_socket = UdpSocket::bind("127.0.0.1:8002").expect("Failed to bind to address"); + let mut buf = [0; 512]; + + match udp_socket.recv_from(&mut buf) { + + Ok((size, source)) => { + println!("Received {} bytes from {}", size, source); + let mut data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); + println!("The data is {:?}", data); + let key_name = "".to_string(); + tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0, key_name); + let response = &DnsMessage::to_bytes(&data); + udp_socket + .send_to(&response, source) + .expect("Failed to send response"); + + } + Err(e) => { + eprintln!("Error receiving data: {}", e); + + } + } + + } + println!("Starting server"); + let server_handle = thread::spawn(|| { + host(); + + }); + thread::sleep(Duration::from_secs(2)); + // se instancia un socket cliente que enviará y mensajes + let client_sock = UdpSocket::bind("127.0.0.1:8001").expect("Nothing"); + let buf = dns_query_message.to_bytes(); + client_sock.send_to(&buf,"127.0.0.1:8002").unwrap(); + println!("Mensaje enviado"); + server_handle.join().unwrap(); + + +} + \ No newline at end of file From 7b9716839b971062261ee3bf22f8415a8ef97bc7 Mon Sep 17 00:00:00 2001 From: Carlo Date: Fri, 12 Jul 2024 12:20:27 -0400 Subject: [PATCH 088/124] Doc: Added RFC 8945 reference to document the tsig_signtature in tsig_integration_tests --- tests/tsig_integration_tests.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index 7b229f23..e50d3ea7 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -2,6 +2,26 @@ use std::{net::IpAddr, str::FromStr, thread, net::UdpSocket, time::Duration}; use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata,class_qclass::Qclass, type_qtype, resource_record::ResourceRecord, header::Header, DnsMessage},tsig::{self, TsigAlgorithm}}; ///RFC 8945 TSIG tests +/*This tests verifies section 5.3: + When a server has generated a response to a signed request, it signs + the response using the same algorithm and key. The server MUST NOT + generate a signed response to a request if either the key is invalid + (e.g., key name or algorithm name are unknown) or the MAC fails + validation; see Section 5.3.2 for details of responding in these + cases. + + It also MUST NOT generate a signed response to an unsigned request, + except in the case of a response to a client's unsigned TKEY request + if the secret key is established on the server side after the server + processed the client's request. Signing responses to unsigned TKEY + requests MUST be explicitly specified in the description of an + individual secret key establishment algorithm [RFC3645]. + + The digest components used to generate a TSIG on a response are: + + Request MAC + DNS Message (response) + TSIG Variables (response) */ #[tokio::test] async fn tsig_signature() { // global test variables @@ -18,7 +38,7 @@ async fn tsig_signature() { 0, false, id); - let q_for_mac = dns_query_message.clone(); + //Lanzamiento de threads //Se lanza el servidor. Recibe un mensaje sin firmar, lo firma y lo reenvía fn host(){ From 51134f38c40a79dcffb2de2466b899ba35842870 Mon Sep 17 00:00:00 2001 From: joalopez Date: Fri, 12 Jul 2024 13:58:52 -0400 Subject: [PATCH 089/124] fix/refactor: changed the logic flow of tsig (sign, process) and new functions digest --- src/tsig.rs | 253 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 146 insertions(+), 107 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 72d609f5..d2277bc1 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -66,86 +66,110 @@ fn set_tsig_rd(name: String, original_id: u16, result: MacResult, //TODO: crear una función para simplificar la extracción de bits paa simplificar código // This function extracts the digest #[doc = r"This function recives a DNS message and generate the digest da. Requested by RFC 8945 4.3.3 "] -fn get_digest_request(dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { - let mut res: Vec = dns_msg.clone(); - let tsig_rdata = tsig_rr.get_rdata(); - res.extend(tsig_rr.get_name().to_bytes()); - //processing TSIG RR - let rclass_bytes: u16 = class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass()); - let rclass_lbyte = rclass_bytes as u8; - let rclass_ubyte = (rclass_bytes >> 8) as u8; - res.push(rclass_ubyte); - res.push(rclass_lbyte); - - let rclass_ttl: u32 = tsig_rr.get_ttl(); - let r_ttl1 = (rclass_ttl >> 24) as u8; - let r_ttl2 = (rclass_ttl >> 16) as u8; - let r_ttl3 = (rclass_ttl >> 8) as u8; - let r_ttl4 = rclass_ttl as u8; - res.push(r_ttl1); - res.push(r_ttl2); - res.push(r_ttl3); - res.push(r_ttl4); - - //processing TSIG RDATA - let tsig_rd = match tsig_rdata { - Rdata::TSIG(tsig_rd) => tsig_rd, - _ => panic!() - }; - let a_name = tsig_rd.get_algorithm_name().to_bytes(); - let tsig_rd_time_signed: u64 = tsig_rd.get_time_signed(); - let tsig_rd_fudge: u16 = tsig_rd.get_fudge(); - let tsig_rd_error: u16= tsig_rd.get_error(); - let tsig_rd_other_len: u16 = tsig_rd.get_other_len(); - let tsig_rd_other_data = tsig_rd.get_other_data(); - - res.extend(a_name); - - let time_s6 = (tsig_rd_time_signed) as u8; - let time_s5 = (tsig_rd_time_signed >> 8) as u8; - let time_s4 = (tsig_rd_time_signed >> 16) as u8; - let time_s3 = (tsig_rd_time_signed >> 24) as u8; - let time_s2 = (tsig_rd_time_signed >> 32) as u8; - let time_s1 = (tsig_rd_time_signed >> 40) as u8; - res.push(time_s1); - res.push(time_s2); - res.push(time_s3); - res.push(time_s4); - res.push(time_s5); - res.push(time_s6); - - let fudge1 = (tsig_rd_fudge >> 8) as u8; - let fudge2 = (tsig_rd_fudge ) as u8; - res.push(fudge1); - res.push(fudge2); - - let error1 = (tsig_rd_error >> 8) as u8; - let error2 = (tsig_rd_error) as u8; - res.push(error1); - res.push(error2); - - let otherl1 = (tsig_rd_other_len >> 8) as u8; - let otherl2 = (tsig_rd_other_len) as u8; - res.push(otherl1); - res.push(otherl2); - - res.extend(tsig_rd_other_data); - - return res; +fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { + let mut res: Vec = vec![]; + + if (mac.len() != 0) { + res.extend(mac.clone()); + } + res.extend(dns_msg.clone()); + let tsig_rdata = tsig_rr.get_rdata(); + res.extend(tsig_rr.get_name().to_bytes()); + //The below shifts are meant to correctly retreive theby + //processing TSIG RR + let rclass_bytes: u16 = class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass()); + let rclass_ubyte = (rclass_bytes >> 8) as u8; + let rclass_lbyte = rclass_bytes as u8; + res.push(rclass_ubyte); + res.push(rclass_lbyte); + + let rclass_ttl: u32 = tsig_rr.get_ttl(); + let r_ttl1 = (rclass_ttl >> 24) as u8; + let r_ttl2 = (rclass_ttl >> 16) as u8; + let r_ttl3 = (rclass_ttl >> 8) as u8; + let r_ttl4 = rclass_ttl as u8; + res.push(r_ttl1); + res.push(r_ttl2); + res.push(r_ttl3); + res.push(r_ttl4); + + //processing TSIG RDATA + let tsig_rd = match tsig_rdata { + Rdata::TSIG(tsig_rd) => tsig_rd, + _ => panic!() + }; + let a_name = tsig_rd.get_algorithm_name().to_bytes(); + // Remember that time_signed is u48 + let tsig_rd_time_signed: u64 = tsig_rd.get_time_signed(); + let tsig_rd_fudge: u16 = tsig_rd.get_fudge(); + let tsig_rd_error: u16= tsig_rd.get_error(); + let tsig_rd_other_len: u16 = tsig_rd.get_other_len(); + let tsig_rd_other_data = tsig_rd.get_other_data(); + + res.extend(a_name); + + let time_s1 = (tsig_rd_time_signed >> 40) as u8; + let time_s2 = (tsig_rd_time_signed >> 32) as u8; + let time_s3 = (tsig_rd_time_signed >> 24) as u8; + let time_s4 = (tsig_rd_time_signed >> 16) as u8; + let time_s5 = (tsig_rd_time_signed >> 8) as u8; + let time_s6 = (tsig_rd_time_signed) as u8; + res.push(time_s1); + res.push(time_s2); + res.push(time_s3); + res.push(time_s4); + res.push(time_s5); + res.push(time_s6); + + let fudge1 = (tsig_rd_fudge >> 8) as u8; + let fudge2 = (tsig_rd_fudge) as u8; + res.push(fudge1); + res.push(fudge2); + + let error1 = (tsig_rd_error >> 8) as u8; + let error2 = (tsig_rd_error) as u8; + res.push(error1); + res.push(error2); + + let otherl1 = (tsig_rd_other_len >> 8) as u8; + let otherl2 = (tsig_rd_other_len) as u8; + res.push(otherl1); + res.push(otherl2); + + res.extend(tsig_rd_other_data); + + return res; +} + +fn digest(bytes: Vec, tsig_algorithm: TsigAlgorithm, key: Vec) -> Vec{ + match tsig_algorithm { + TsigAlgorithm::HmacSha1 => { + + //new_query_message.push(); + let mut hasher = crypto_hmac::new(Sha1::new(), &key); + hasher.input(&bytes[..]); + hasher.result().code().to_vec() + }, + TsigAlgorithm::HmacSha256 => { + let mut hasher = crypto_hmac::new(Sha256::new(), &key); + hasher.input(&bytes[..]); + hasher.result().code().to_vec() + } + } } -//TODO: revisar que la creación del TSIG resourcerecord contenga efectivamente los campos del 8945, 4.3.3 //RFC 8945, section 5.1 #[doc = r"This function creates the signature of a DnsMessage with a key in bytes and the algName that will be used to encrypt the key."] pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm, - fudge: u16, time_signed: u64, key_name: String) -> Vec { + fudge: u16, time_signed: u64, key_name: String, mac_request: Vec) -> Vec { let mut tsig_rd: TSigRdata = TSigRdata::new(); let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); let alg_name_str = tsig_alg_to_string(&alg_name); - let tsig_rr= set_tsig_vars( alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); - let digest_comp = get_digest_request(new_query_message.to_bytes(), tsig_rr); - + let tsig_rr= set_tsig_vars(alg_name_str.as_str(), key_name.as_str(), + time_signed, fudge); + let digest_comp = get_digest_request(mac_request, new_query_message.to_bytes(), + tsig_rr); match alg_name { TsigAlgorithm::HmacSha1 => { @@ -253,9 +277,9 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { filtered_tsig.len()>1 || islast } - #[doc = r"This function process a tsig message, checking for errors in the DNS message"] -pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, available_algorithm: Vec<(String, bool)>) -> (bool, TsigErrorCode) { +pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, + available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, TsigErrorCode) { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); //RFC 8945 5.2 y 5.4 @@ -281,28 +305,29 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av tsig_rr_copy = data; } _ => { - println!("error") + println!("error"); + unimplemented!("TODO: error code if last rr is not tsig; FORMERR") } } - let nuevo_len_arcount = addit.len() as u16; - let mut new_header = retmsg.get_header(); - new_header.set_arcount(nuevo_len_arcount); - retmsg.set_header(new_header); + //RFC 8945 5.2.1 - let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); let key_in_rr = rr_copy.get_name().get_name(); - let flag = check_alg_name(&name_alg,available_algorithm); + let name_alg = tsig_rr_copy.get_algorithm_name().get_name(); + + let flag = check_alg_name(&name_alg, available_algorithm); if !flag { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return (false, TsigErrorCode::BADKEY); } - let cond1 = check_key(key_in_rr,key_name); + + let cond1 = check_key(key_in_rr, key_name); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); return (false, TsigErrorCode::BADKEY); } + //RFC 8945 5.2.2 - retmsg.set_additional(addit); + //retmsg.set_additional(addit); let fudge = tsig_rr_copy.get_fudge(); let time_signed = tsig_rr_copy.get_time_signed(); let mac_received = tsig_rr_copy.get_mac(); @@ -313,9 +338,21 @@ pub fn process_tsig(msg: &DnsMessage,key:&[u8], key_name: String, time: u64, av "hmac-sha256" => new_alg_name = TsigAlgorithm::HmacSha256, &_ => println!("not supported algorithm") } - let new_mac = sign_tsig(&mut retmsg, key, new_alg_name, fudge, time_signed, key_name); - + + //let nuevo_len_arcount = addit.len() as u16; + //let mut new_header = retmsg.get_header(); + //new_header.set_arcount(nuevo_len_arcount); + //retmsg.set_header(new_header); + retmsg.set_additional(addit); + retmsg.update_header_counters(); + + // This gets the bytes to use the function and generate the digest + let bytes_to_hash = get_digest_request(mac_to_process, retmsg.to_bytes(), rr_copy); + + let new_mac = digest(bytes_to_hash, new_alg_name, key.to_vec()); + let cond2 = check_mac(new_mac, mac_received); + if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); return (false, TsigErrorCode::BADSIG) @@ -360,7 +397,7 @@ fn check_process_tsig_exists() { let mut lista :Vec<(String, bool)> = vec![]; let server_key = b"1234567890"; lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error,TsigErrorCode::FORMERR); } @@ -379,16 +416,16 @@ fn check_process_tsig_exists2() { // cloning response let mut response2 = response.clone(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone()); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone(), vec![]); let mut response_capture = response.clone(); - sign_tsig(&mut response_capture, server_key, alg_name2, fudge, time_signed, key_name.clone()); + sign_tsig(&mut response_capture, server_key, alg_name2, fudge, time_signed, key_name.clone(), vec![]); //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha256"),true)); - let (control_answer, _) = process_tsig(& response, server_key, key_name.clone(),21010, lista.clone()); + let (control_answer, _) = process_tsig(& response, server_key, key_name.clone(),21010, lista.clone(), vec![]); assert!(control_answer); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error, TsigErrorCode::FORMERR); } @@ -404,7 +441,7 @@ fn check_process_tsig_exists3(){ let time_signed = 21000; let key_name = ""; //se crea un rr TSIG que se añadirá en adittionals - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.to_string()); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.to_string(), vec![]); //se agrega otro resource record en el additional... let mut new_additional = Vec::::new(); @@ -418,7 +455,7 @@ fn check_process_tsig_exists3(){ let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error, TsigErrorCode::FORMERR); } @@ -431,14 +468,14 @@ fn check_process_tsig_alg_name() { let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; //suponemos que hmacsha256 no está disponible lista.push((String::from("hmac-sha1"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error,TsigErrorCode::BADKEY); } @@ -451,14 +488,14 @@ fn check_process_tsig_alg_name2() { let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; //suponemos que reconocemos hmac-sha256, pero no está implementado lista.push((String::from("hmac-sha256"),false)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error,TsigErrorCode::BADKEY); } @@ -471,14 +508,14 @@ fn check_process_tsig_key(){ let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); let mut response_capture = response.clone(); //Client process let key_name:String = "different".to_string(); let mut lista :Vec<(String, bool)> = vec![]; //suponemos que reconocemos hmac-sha256, pero no está implementado lista.push((String::from("hmac-sha256"),false)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); assert_eq!(error,TsigErrorCode::BADKEY); } @@ -493,14 +530,14 @@ fn check_process_tsig_badsign(){ let time_signed = 210000000; let key_name = "".to_string(); // se firma el mensaje con algoritmo SHA-1 - sign_tsig(& mut msg1, key, alg_name, fudge, time_signed, key_name); + sign_tsig(& mut msg1, key, alg_name, fudge, time_signed, key_name, vec![]); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha1"),true)); lista.push((String::from("hmac-sha256"),true)); // se verifica que el mensaje está firmado, pero se usa otra key let key_name = "".to_string(); let key2 = b"12345678909"; - let (answer,error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista); + let (answer,error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista, vec![]); assert_eq!(error,TsigErrorCode::BADSIG); } #[test] @@ -512,33 +549,35 @@ fn check_proces_tsig_badtime(){ let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); let mut response_capture = response.clone(); //Client process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; //suponemos que reconocemos hmac-sha256, pero no está implementado lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 22010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, + 22010, lista, vec![]); assert!(!answer); assert_eq!(error,TsigErrorCode::BADTIME); } #[test] fn check_process_tsig() { - //Server process + //sender process let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); let server_key = b"1234567890"; let alg_name = TsigAlgorithm::HmacSha256; let fudge = 300; let time_signed = 21000; let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); let mut response_capture = response.clone(); - //Client process + //recv process let key_name:String = "".to_string(); let mut lista :Vec<(String, bool)> = vec![]; lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, + 21010, lista, vec![]); assert!(answer); assert_eq!(error,TsigErrorCode::NOERR); } @@ -566,9 +605,9 @@ fn check_signed_tsig() { let tsig_rr = set_tsig_vars(tsig_alg_to_string(&alg_name).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); + let firma_a_comparar = sign_tsig(&mut q, key, alg_name, fudge, time_signed, name, vec![]); // creation of the signature digest - let dig_for_mac = get_digest_request(q_for_mac.to_bytes(), tsig_rr); + let dig_for_mac = get_digest_request(vec![],q_for_mac.to_bytes(), tsig_rr); let mut hasher = crypto_hmac::new(Sha1::new(), key); hasher.input(&dig_for_mac[..]); From ec6fb882cdbacbe2b9c8a329955637e4a1a59f09 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 13:19:47 -0400 Subject: [PATCH 090/124] Added a smal public function to match Strings to TsigAlgorithm --- src/tsig.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index d2277bc1..e230e62e 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -30,6 +30,14 @@ fn tsig_alg_to_string(alg: &TsigAlgorithm) -> String { TsigAlgorithm::HmacSha256 => "hmac-sha256".to_string(), } } +pub fn string_to_tsig_alg(name: String) -> TsigAlgorithm{ + let sha1 = "hmac-sha1".to_string(); + let sha256 = "hmac-sha256".to_string(); + match name{ + sha1=> TsigAlgorithm::HmacSha1, + sha256 => TsigAlgorithm::HmacSha256 + } +} #[derive(PartialEq)] #[derive(Debug)] @@ -47,9 +55,7 @@ fn set_tsig_rd(name: String, original_id: u16, result: MacResult, fudge: u16, time_signed: u64, mac_size: u16) -> TSigRdata{ let mut tsig_rd: TSigRdata = TSigRdata::new(); let mac = result.code(); - /* - hasher.input(&new_query_message.to_bytes()[..]); - let result = hasher.result(); */ + //Convertir los bytes brutos a una cadena hexadecimal let a_name = name.to_lowercase(); let a_name = DomainName::new_from_string(a_name); From 2594500d64127ff0c3406a2c0f2c3964648ac5c7 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 15:56:42 -0400 Subject: [PATCH 091/124] Test: added a basic tsig flow test in tig_integration_tests --- tests/tsig_integration_tests.rs | 125 +++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index e50d3ea7..0fdd9680 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -1,5 +1,5 @@ -use std::{net::IpAddr, str::FromStr, thread, net::UdpSocket, time::Duration}; -use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{rdata::Rdata,class_qclass::Qclass, type_qtype, resource_record::ResourceRecord, header::Header, DnsMessage},tsig::{self, TsigAlgorithm}}; +use std::{collections::HashMap, net::{IpAddr, UdpSocket}, str::FromStr, thread, time::Duration}; +use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{class_qclass::Qclass, header::Header, rdata::{tsig_rdata::TSigRdata, Rdata}, resource_record::ResourceRecord, type_qtype, DnsMessage},tsig::{self, get_digest_request, process_tsig, sign_tsig, string_to_tsig_alg, TsigAlgorithm, TsigErrorCode}}; ///RFC 8945 TSIG tests /*This tests verifies section 5.3: @@ -21,28 +21,59 @@ use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client:: Request MAC DNS Message (response) - TSIG Variables (response) */ + TSIG Variables (response) + + DISCLAIMER: Como no hay un "NameServer" implementado, se probó la firma y verififcaciónde TSIG utilizando + threads y scokets. La idea central es tener un thread recibiendo datos de localhost, el cual tiene en alguna + parte guardados pares (key, name) que serían utilizados para la autenticación (en este caso, se guardaron los + pares en un hash_map. Como se guarden no es relevante para tsig, depende de la implementación del servidor. + Lo único importante es que podamos buscar la llave asociada a un cierto nombre, de acuerdo a la solicitud que + recibamos). + En este test se verifica a nivel macro el correcto flujo de TSIG: primero se envia a un host en localhost + una query firmada, el cual verifica la integridad de la query y responde con un respuesta firmada que será verificada. +*/ #[tokio::test] async fn tsig_signature() { - // global test variables + // the key to test tsig flow. The server should had the same key let key = b"1234567890"; + // global test variables let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 0; - let time_signed = 0; + let fudge = 100; + let time_signed = 12345678; let id = 6502; + let name = "nictest.cl"; let mut dns_query_message = DnsMessage::new_query_message( - DomainName::new_from_string("nictest.cl".to_string()), + DomainName::new_from_string(name.to_string()), type_qtype::Qtype::A, Qclass::IN, 0, false, id); - - //Lanzamiento de threads - //Se lanza el servidor. Recibe un mensaje sin firmar, lo firma y lo reenvía + //lista de algoritmos disponibles. En este caso, ambos host tendrán la misma + let mut a_algs :Vec<(String, bool)> = vec![]; + a_algs.push((String::from("hmac-sha1"),true)); + a_algs.push((String::from("hmac-sha256"),true)); + + + //Código para el servidor. Recibe un mensaje firmado, lo verifica y envía una repuesta autenticada, según lo descrito en el + //RFC 8945. Este servidor tiene su propia lista de algoritmos disponibles y llaves asociadas a nombres de dominio fn host(){ println!("I am a host"); + //la lista de algoritmos del host + let mut list :Vec<(String, bool)> = vec![]; + list.push((String::from("hmac-sha1"),true)); + list.push((String::from("hmac-sha256"),true)); + + // se crean las llaves del servidor + let key1 = b"1234567890"; + let key2 = b"1034567692"; + // se mapean las llaves anteriores a un nombre. Acá deberemos buscar el nombre de lo que se reciba para utilizar la llave correcta + let mut keys = HashMap::new(); + keys.insert(DomainName::new_from_string("nictest.cl".to_string()), key1); + keys.insert(DomainName::new_from_string("example.cl".to_string()), key2); + + //se recibiran datos de otro thread a través de un socket UDP let udp_socket = UdpSocket::bind("127.0.0.1:8002").expect("Failed to bind to address"); let mut buf = [0; 512]; @@ -52,9 +83,42 @@ async fn tsig_signature() { println!("Received {} bytes from {}", size, source); let mut data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); println!("The data is {:?}", data); - let key_name = "".to_string(); - tsig::sign_tsig(&mut data, b"1234567890",TsigAlgorithm::HmacSha1,0,0, key_name); + let mut addit = data.get_additional(); + let rr = addit.pop().expect("No tsigrr"); + let mut tsig_rd = TSigRdata::new(); + let mut can_sign = false; + + match rr.get_rdata() { + Rdata::TSIG(data) =>{ + tsig_rd = data; + } + _ => { + can_sign = true; + println!("error: no TSIG rdata found!"); + } + } + //se extraen las variables TSIG necesarias. + let alg_name = tsig_rd.get_algorithm_name().get_name(); + let time =tsig_rd.get_time_signed(); + let fudge = tsig_rd.get_fudge(); + let mac = tsig_rd.get_mac(); + let name = rr.get_name(); + let key_name = name.clone().get_name(); + // se extrae la llave necesaria + let key_found = keys[&name]; + + //el servidor verifica la estructura del tsig recibido. Sumamos un pequeño delay al time para simular retraso + let (answer,error) = process_tsig(&data, key_found, key_name.clone(), time + 50, list, vec![]); + //se setea el aditional sin el ultimo resource record, para que sign_tsig lo regenere + data.set_additional(addit); + data.update_header_counters(); + // se firma el mensaje recibido con el digest de la respuesta. Notar que el vector final ahora no está vacío + sign_tsig(&mut data, key_found,string_to_tsig_alg(alg_name),fudge,time, key_name, mac); let response = &DnsMessage::to_bytes(&data); + //se verifica que la request haya pasado proces_tsig + assert_eq!(error,TsigErrorCode::NOERR); + + // se envia la respuesta si lo anterior resultó ser correcto udp_socket .send_to(&response, source) .expect("Failed to send response"); @@ -67,18 +131,55 @@ async fn tsig_signature() { } } + + //Lanzamiento de threads println!("Starting server"); let server_handle = thread::spawn(|| { host(); }); thread::sleep(Duration::from_secs(2)); + // 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![]); let buf = dns_query_message.to_bytes(); client_sock.send_to(&buf,"127.0.0.1:8002").unwrap(); println!("Mensaje enviado"); server_handle.join().unwrap(); + let mut buf = [0; 512]; + + // Ahora el cliente verifica la respuesta recibida del servidor + match client_sock.recv_from(&mut buf) { + + Ok((size, source)) => { + println!("Received {} bytes from {}", size, source); + let data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); + println!("The data is {:?}", data); + let mut additionals = data.get_additional(); + let tsig_rr = additionals.pop().expect("No tsigrr"); + let mut tsig_rd= TSigRdata::new(); + match tsig_rr.get_rdata() { + Rdata::TSIG(data) =>{ + tsig_rd = data; + } + _ => { + println!("error: no TSIG rdata found!"); + } + } + + // El cliente procesa la respuesta + let (answer, error ) = process_tsig(&data, key, name.to_string(), time_signed, a_algs, mac); + // se verifica que el mensaje haya pasado process_tsig + assert!(answer); + assert_eq!(error,TsigErrorCode::NOERR); + } + Err(e) => { + eprintln!("Error receiving data: {}", e); + + } + } } From 62831bad4a28453319d82d7f8f7fa300ac5eac2c Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 15:57:36 -0400 Subject: [PATCH 092/124] Refact: get_digest_request is a public function now --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index e230e62e..89e94d3d 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -72,7 +72,7 @@ fn set_tsig_rd(name: String, original_id: u16, result: MacResult, //TODO: crear una función para simplificar la extracción de bits paa simplificar código // This function extracts the digest #[doc = r"This function recives a DNS message and generate the digest da. Requested by RFC 8945 4.3.3 "] -fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { +pub fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { let mut res: Vec = vec![]; if (mac.len() != 0) { From 51104d5d344402e23d65a98ba2c6989223f0f97d Mon Sep 17 00:00:00 2001 From: Alonso Date: Sun, 14 Jul 2024 18:20:59 -0400 Subject: [PATCH 093/124] fix: rrset_signature --- src/dnssec/dnssec.rs | 23 +++-------------------- src/dnssec/rrset_signature.rs | 18 ++++-------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs index a25d22d0..899bf857 100644 --- a/src/dnssec/dnssec.rs +++ b/src/dnssec/dnssec.rs @@ -1,27 +1,10 @@ -use crate::client::ClientUDPConnection; -use crate::message::{DnsMessage, ResourceRecord}; +use crate::message::{DnsMessage, Rdata, ResourceRecord}; use crate::dnssec_message_processing::extract_dnssec_records; use crate::rrset_signature::{verify_rrsig, verify_ds}; -use crate::dnskey_rdata::DnskeyRdata; +use crate::message::rdata::DnskeyRdata; use crate::client::client_error::ClientError; -use std::net::IpAddr; -use tokio::time::Duration; -pub async fn fetch_dnskey_records(domain: &str, server_addr: IpAddr, timeout_duration: Duration) -> Result, ClientError> { - let conn = ClientUDPConnection::new(server_addr, timeout_duration); - - let dns_query = DnsMessage::new_query_message( - domain.into(), - Qtype::DNSKEY, - Qclass::IN, - 0, - false, - 1, - ); - - let response = conn.send(dns_query).await?; - - let dns_response = DnsMessage::from_bytes(&response)?; +pub async fn fetch_dnskey_records(dns_response: &DnsMessage) -> Result, ClientError> { let mut dnskey_records = Vec::new(); for record in dns_response.get_answer() { diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index ff13c55a..25cd1669 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -28,28 +28,18 @@ pub fn verify_rrsig(rrsig: &RrsigRdata, dnskey: &DnskeyRdata, rrset: &[ResourceR } let signature = rrsig.signature.clone(); - let mut hasher = Sha256::new(); - hasher.update(rrsig_data); - let hashed = hasher.finalize(); + let hashed = Sha256::digest(&rrsig_data); match dnskey.algorithm { - 3 => { - //DSA/SHA1 - let mut sha1 = Sha1::new(); - sha1.input(&rrsig_data); - let digest = sha1.result_str(); - Ok(digest == encode(&signature)) - }, - 5 => { - //RSA/SHA1 + 3 | 5 => { + // (DSA/RSA)/SHA1 let mut sha1 = Sha1::new(); sha1.input(&rrsig_data); let digest = sha1.result_str(); Ok(digest == encode(&signature)) }, 8 => { - //RSA/SHA256 - let hashed = Sha256::digest(&rrsig_data); + // RSA/SHA256 Ok(encode(&hashed) == encode(&signature)) }, _ => Err(ClientError::new("Unknown DNSKEY algorithm")), From 1a42a35f89e4a2742b3b4fff22152797b4654302 Mon Sep 17 00:00:00 2001 From: joalopez Date: Sun, 14 Jul 2024 19:27:59 -0400 Subject: [PATCH 094/124] fix: no more use qclass qtype --- src/dnssec.rs | 13 ++++++------- src/tsig.rs | 16 +++++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/dnssec.rs b/src/dnssec.rs index 9af4fbb6..1b7ce88f 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,18 +1,17 @@ -pub mod dnssec_encryption; -pub mod dnssec_decryption; +pub mod dnssec; + use std::str::FromStr; use crate::domain_name::DomainName; -use crate::message::class_qclass::Qclass; -use crate::message::class_rclass::Rclass; +use crate::message::rclass::Rclass; use crate::message::DnsMessage; use crate::message::rdata::opt_rdata::OptRdata; use crate::message::rdata::Rdata; use crate::message::resource_record::{FromBytes, ResourceRecord, ToBytes}; -use crate::message::type_qtype::Qtype; use crate::message::rcode; use crate::message::rcode::Rcode; +use crate::message::rrtype::Rrtype; const EDNS_VERSION: u8 = 0; const REQUESTED_UDP_LEN: u16 = 4096; @@ -76,8 +75,8 @@ fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { fn see_dnssec_message() { let query = DnsMessage::new_query_message( DomainName::new_from_str("example.com"), - Qtype::A, - Qclass::UNKNOWN(4096), + Rrtype::A, + Rclass::UNKNOWN(4096), 1, true, 2000 diff --git a/src/tsig.rs b/src/tsig.rs index 89e94d3d..97010836 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -3,17 +3,19 @@ use std::fmt::{self,Display,Debug}; //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; -use crate::message::class_qclass::{Qclass}; -use crate::message::class_rclass::Rclass; + +use crate::message::rclass::Rclass; use crate::message::resource_record::{ResourceRecord, ToBytes}; -use crate::message::type_qtype::Qtype; -use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage, class_rclass}; + +use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage,}; use crate::message::rdata::{tsig_rdata, Rdata}; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; use crate::message::rdata::a_rdata::ARdata; +use crate::message::rrtype::Rrtype; + type HmacSha256 = Hmac; @@ -83,7 +85,7 @@ pub fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecor res.extend(tsig_rr.get_name().to_bytes()); //The below shifts are meant to correctly retreive theby //processing TSIG RR - let rclass_bytes: u16 = class_rclass::Rclass::from_rclass_to_int(tsig_rr.get_rclass()); + let rclass_bytes: u16 = Rclass::from_rclass_to_int(tsig_rr.get_rclass()); let rclass_ubyte = (rclass_bytes >> 8) as u8; let rclass_lbyte = rclass_bytes as u8; res.push(rclass_ubyte); @@ -601,8 +603,8 @@ fn check_signed_tsig() { //DNS message let mut q = DnsMessage::new_query_message( domain.clone(), - Qtype::A, - Qclass::ANY, + Rrtype::A, + Rclass::ANY, 0, false, id From 67c42d34e37398b396580cf0e8b9727161f4b995 Mon Sep 17 00:00:00 2001 From: joalopez Date: Sun, 14 Jul 2024 19:55:03 -0400 Subject: [PATCH 095/124] fix: dnssec module --- src/dnssec.rs | 94 +---------------------- src/dnssec/{dnssec.rs => dnssec_fetch.rs} | 4 +- src/dnssec/dnssec_message.rs | 87 +++++++++++++++++++++ src/dnssec/rrset_signature.rs | 15 ++-- 4 files changed, 101 insertions(+), 99 deletions(-) rename src/dnssec/{dnssec.rs => dnssec_fetch.rs} (78%) create mode 100644 src/dnssec/dnssec_message.rs diff --git a/src/dnssec.rs b/src/dnssec.rs index 1b7ce88f..9f6c7239 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,90 +1,4 @@ -pub mod dnssec; - - - -use std::str::FromStr; -use crate::domain_name::DomainName; -use crate::message::rclass::Rclass; -use crate::message::DnsMessage; -use crate::message::rdata::opt_rdata::OptRdata; -use crate::message::rdata::Rdata; -use crate::message::resource_record::{FromBytes, ResourceRecord, ToBytes}; -use crate::message::rcode; -use crate::message::rcode::Rcode; -use crate::message::rrtype::Rrtype; - -const EDNS_VERSION: u8 = 0; -const REQUESTED_UDP_LEN: u16 = 4096; -/* -The mechanism chosen for the explicit notification of the ability of -the client to accept (if not understand) DNSSEC security RRs is using -the most significant bit of the Z field on the EDNS0 OPT header in -the query. This bit is referred to as the "DNSSEC OK" (DO) bit. In -the context of the EDNS0 OPT meta-RR, the DO bit is the first bit of -the third and fourth bytes of the "extended RCODE and flags" portion -of the EDNS0 OPT meta-RR, structured as follows: - - +0 (MSB) +1 (LSB) - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - 0: | EXTENDED-RCODE | VERSION | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - 2: |DO| Z | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ -fn create_opt_rr(capacity: u16 ,e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { - let opt_rdata = OptRdata::new(); - let rdata = Rdata::OPT(opt_rdata); - let mut rr = ResourceRecord::new(rdata); - - let do_val: u16 = if do_bit {0x8000} else {0x0}; - let ttl: u32 = (e_rcode as u32) << 24 | (version as u32) << 16| (do_val as u32); - rr.set_ttl(ttl); - rr.set_rclass(Rclass::UNKNOWN(capacity)); - println!("EL ttl es: {:#05x?}", ttl); - rr -} - -fn read_opt_rr(opt_rr: ResourceRecord) -> String { - let requested_udp_len = Rclass::from_rclass_to_int(opt_rr.get_rclass()); - let data = opt_rr.get_ttl().to_be_bytes(); - let (e_rcode, version) = (data[0], data[1]); - let z = u16::from_be_bytes([data[2], data[3]]); - - let do_bit = ((z & 0x8000) > 0) as u8 ; - format!("OPT PSEUDO-RR\n\trequested_udp_len: {requested_udp_len}\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") -} - -/* - A security-aware resolver MUST include an EDNS ([RFC2671]) OPT - pseudo-RR with the DO ([RFC3225]) bit set when sending queries. -*/ -fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { - // We create a opt rr with the do bit set to 1 - // with NOERR as rcode and EDNS0 - let rr = create_opt_rr(REQUESTED_UDP_LEN, - rcode::Rcode::from_rcode_to_int(Rcode::NOERROR), - EDNS_VERSION, - true); - - let vec = vec![rr]; - msg.add_additionals(vec); - msg -} - -#[test] -fn see_dnssec_message() { - let query = DnsMessage::new_query_message( - DomainName::new_from_str("example.com"), - Rrtype::A, - Rclass::UNKNOWN(4096), - 1, - true, - 2000 - ); - let query= create_dns_message_with_dnssec(query); - assert_eq!(String::from_str - ("OPT PSEUDO-RR\n\trequested_udp_len: 4096\n\terror code: 0\n\tversion: EDNS0\n\tuse dnssec: 1") - .expect("Not a utf8 str"), - read_opt_rr(query.get_additional().pop().expect("No OPT Record!")) - ) -} \ No newline at end of file +pub mod dnssec_message; +pub mod dnssec_message_processing; +pub mod dnssec_fetch; +pub mod rrset_signature; \ No newline at end of file diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec_fetch.rs similarity index 78% rename from src/dnssec/dnssec.rs rename to src/dnssec/dnssec_fetch.rs index 899bf857..24295daa 100644 --- a/src/dnssec/dnssec.rs +++ b/src/dnssec/dnssec_fetch.rs @@ -1,6 +1,6 @@ use crate::message::{DnsMessage, Rdata, ResourceRecord}; -use crate::dnssec_message_processing::extract_dnssec_records; -use crate::rrset_signature::{verify_rrsig, verify_ds}; +use crate::dnssec::dnssec_message_processing::extract_dnssec_records; +use crate::dnssec::rrset_signature::{verify_rrsig, verify_ds}; use crate::message::rdata::DnskeyRdata; use crate::client::client_error::ClientError; diff --git a/src/dnssec/dnssec_message.rs b/src/dnssec/dnssec_message.rs new file mode 100644 index 00000000..975cf6b8 --- /dev/null +++ b/src/dnssec/dnssec_message.rs @@ -0,0 +1,87 @@ + +use std::str::FromStr; +use crate::domain_name::DomainName; +use crate::message::rclass::Rclass; +use crate::message::DnsMessage; +use crate::message::rdata::opt_rdata::OptRdata; +use crate::message::rdata::Rdata; +use crate::message::resource_record::{FromBytes, ResourceRecord, ToBytes}; +use crate::message::rcode; +use crate::message::rcode::Rcode; +use crate::message::rrtype::Rrtype; + +const EDNS_VERSION: u8 = 0; +const REQUESTED_UDP_LEN: u16 = 4096; +/* +The mechanism chosen for the explicit notification of the ability of +the client to accept (if not understand) DNSSEC security RRs is using +the most significant bit of the Z field on the EDNS0 OPT header in +the query. This bit is referred to as the "DNSSEC OK" (DO) bit. In +the context of the EDNS0 OPT meta-RR, the DO bit is the first bit of +the third and fourth bytes of the "extended RCODE and flags" portion +of the EDNS0 OPT meta-RR, structured as follows: + + +0 (MSB) +1 (LSB) + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 0: | EXTENDED-RCODE | VERSION | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 2: |DO| Z | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +*/ +fn create_opt_rr(capacity: u16 ,e_rcode :u8, version: u8, do_bit: bool) -> ResourceRecord { + let opt_rdata = OptRdata::new(); + let rdata = Rdata::OPT(opt_rdata); + let mut rr = ResourceRecord::new(rdata); + + let do_val: u16 = if do_bit {0x8000} else {0x0}; + let ttl: u32 = (e_rcode as u32) << 24 | (version as u32) << 16| (do_val as u32); + rr.set_ttl(ttl); + rr.set_rclass(Rclass::UNKNOWN(capacity)); + println!("EL ttl es: {:#05x?}", ttl); + rr +} + +fn read_opt_rr(opt_rr: ResourceRecord) -> String { + let requested_udp_len = Rclass::from_rclass_to_int(opt_rr.get_rclass()); + let data = opt_rr.get_ttl().to_be_bytes(); + let (e_rcode, version) = (data[0], data[1]); + let z = u16::from_be_bytes([data[2], data[3]]); + + let do_bit = ((z & 0x8000) > 0) as u8 ; + format!("OPT PSEUDO-RR\n\trequested_udp_len: {requested_udp_len}\n\terror code: {e_rcode}\n\tversion: EDNS{version}\n\tuse dnssec: {do_bit}") +} + +/* + A security-aware resolver MUST include an EDNS ([RFC2671]) OPT + pseudo-RR with the DO ([RFC3225]) bit set when sending queries. +*/ +fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { + // We create a opt rr with the do bit set to 1 + // with NOERR as rcode and EDNS0 + let rr = create_opt_rr(REQUESTED_UDP_LEN, + rcode::Rcode::from_rcode_to_int(Rcode::NOERROR), + EDNS_VERSION, + true); + + let vec = vec![rr]; + msg.add_additionals(vec); + msg +} + +#[test] +fn see_dnssec_message() { + let query = DnsMessage::new_query_message( + DomainName::new_from_str("example.com"), + Rrtype::A, + Rclass::UNKNOWN(4096), + 1, + true, + 2000 + ); + let query= create_dns_message_with_dnssec(query); + assert_eq!(String::from_str + ("OPT PSEUDO-RR\n\trequested_udp_len: 4096\n\terror code: 0\n\tversion: EDNS0\n\tuse dnssec: 1") + .expect("Not a utf8 str"), + read_opt_rr(query.get_additional().pop().expect("No OPT Record!")) + ) +} \ No newline at end of file diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index 25cd1669..b0e9b1aa 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -1,16 +1,17 @@ use sha2::{Sha256, Digest}; -use rust_crypto::digest::Digest as RustDigest; -use rust_crypto::sha1::Sha1; +use crypto::digest::Digest as RustDigest; +use crypto::sha1::Sha1; use base64::encode; -use crate::message::rdata::{DnskeyRdata, RrsigRdata, Rdata}; +use crate::message::rdata::{DnskeyRdata, Rdata}; +use crate::message::rdata::rrsig_rdata::{RRSIGRdata}; use crate::message::resource_record::ResourceRecord; use crate::client::client_error::ClientError; -pub fn verify_rrsig(rrsig: &RrsigRdata, dnskey: &DnskeyRdata, rrset: &[ResourceRecord]) -> Result { +pub fn verify_rrsig(rrsig: &RRSIGRdata, dnskey: &DnskeyRdata, rrset: &[ResourceRecord]) -> Result { let mut rrsig_data = Vec::new(); - rrsig_data.extend_from_slice(&rrsig.type_covered.to_be_bytes()); - rrsig_data.push(rrsig.algorithm); - rrsig_data.push(rrsig.labels); + rrsig_data.extend_from_slice(&rrsig.get_type_covered().to_be_bytes()); + rrsig_data.push(rrsig.get_algorithm()); + rrsig_data.push(rrsig.get_labels()); rrsig_data.extend_from_slice(&rrsig.original_ttl.to_be_bytes()); rrsig_data.extend_from_slice(&rrsig.expiration.to_be_bytes()); rrsig_data.extend_from_slice(&rrsig.inception.to_be_bytes()); From e11700fd7084468c0d86bf5015550d561e32b912 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 20:07:35 -0400 Subject: [PATCH 096/124] Fix: fixed rrset_signature.rs --- src/dnssec/rrset_signature.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index b0e9b1aa..ca59a2cc 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -2,7 +2,8 @@ use sha2::{Sha256, Digest}; use crypto::digest::Digest as RustDigest; use crypto::sha1::Sha1; use base64::encode; -use crate::message::rdata::{DnskeyRdata, Rdata}; +use crate::message::rdata::Rdata; +use crate::message::rdata::dnskey_rdata::DnskeyRdata; use crate::message::rdata::rrsig_rdata::{RRSIGRdata}; use crate::message::resource_record::ResourceRecord; use crate::client::client_error::ClientError; @@ -12,23 +13,23 @@ pub fn verify_rrsig(rrsig: &RRSIGRdata, dnskey: &DnskeyRdata, rrset: &[ResourceR rrsig_data.extend_from_slice(&rrsig.get_type_covered().to_be_bytes()); rrsig_data.push(rrsig.get_algorithm()); rrsig_data.push(rrsig.get_labels()); - rrsig_data.extend_from_slice(&rrsig.original_ttl.to_be_bytes()); - rrsig_data.extend_from_slice(&rrsig.expiration.to_be_bytes()); - rrsig_data.extend_from_slice(&rrsig.inception.to_be_bytes()); - rrsig_data.extend_from_slice(&rrsig.key_tag.to_be_bytes()); - rrsig_data.extend_from_slice(rrsig.signer_name.to_bytes()?); + rrsig_data.extend_from_slice(&rrsig.get_original_ttl().to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.get_signature_expiration().to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.get_signature_inception().to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.get_key_tag().to_be_bytes()); + rrsig_data.extend_from_slice(rrsig.get_signer_name().to_bytes()?); let mut rrset_sorted = rrset.to_vec(); - rrset_sorted.sort_by(|a, b| a.name.cmp(&b.name)); + rrset_sorted.sort_by(|a, b| a.get_name().cmp(&b.get_name())); for rr in rrset_sorted.iter() { - rrsig_data.extend_from_slice(rr.name.to_bytes()?); - rrsig_data.extend_from_slice(&rr.ttl.to_be_bytes()); - rrsig_data.extend_from_slice(&(rr.rdata.to_bytes().len() as u16).to_be_bytes()); - rrsig_data.extend_from_slice(&rr.rdata.to_bytes()?); + rrsig_data.extend_from_slice(rr.get_name().to_bytes()?); + rrsig_data.extend_from_slice(&rr.get_ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&(rr.get_rdata().to_bytes().len() as u16).to_be_bytes()); + rrsig_data.extend_from_slice(&rr.get_rdata().to_bytes()?); } - let signature = rrsig.signature.clone(); + let signature = rrsig.get_signature().clone(); let hashed = Sha256::digest(&rrsig_data); match dnskey.algorithm { From a6157b96c40c417474327f2a93dacad9182a18e9 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 20:10:31 -0400 Subject: [PATCH 097/124] Fix: dnssec_message_procesing.rs dependecies problem --- src/dnssec/dnssec_message_processing.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dnssec/dnssec_message_processing.rs b/src/dnssec/dnssec_message_processing.rs index 783e32a6..8bbfff40 100644 --- a/src/dnssec/dnssec_message_processing.rs +++ b/src/dnssec/dnssec_message_processing.rs @@ -1,4 +1,6 @@ -use crate::message::{DnsMessage, Rdata, ResourceRecord}; +use crate::message::DnsMessage; +use crate::message::rdata::Rdata; +use crate::message::resource_record::ResourceRecord; pub fn extract_dnssec_records(dns_response: &DnsMessage) -> (Vec, Vec) { let answers = dns_response.get_answer(); From 2d5c294a6c05320dc05322032ca00eaae525fa45 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 22:56:11 -0400 Subject: [PATCH 098/124] Fix: incorporated the new Rrtype and corrected some deprecated calls --- tests/tsig_integration_tests.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index 0fdd9680..a73078f0 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -1,5 +1,7 @@ -use std::{collections::HashMap, net::{IpAddr, UdpSocket}, str::FromStr, thread, time::Duration}; -use dns_rust::{async_resolver::{config::ResolverConfig, AsyncResolver}, client::client_error::ClientError, domain_name::DomainName, message::{class_qclass::Qclass, header::Header, rdata::{tsig_rdata::TSigRdata, Rdata}, resource_record::ResourceRecord, type_qtype, DnsMessage},tsig::{self, get_digest_request, process_tsig, sign_tsig, string_to_tsig_alg, TsigAlgorithm, TsigErrorCode}}; +use std::{collections::HashMap, net:: UdpSocket, thread, time::Duration}; +use dns_rust::{domain_name::DomainName, message::{rdata::{tsig_rdata::TSigRdata, Rdata}, rrtype::Rrtype, DnsMessage},tsig::{process_tsig, sign_tsig, string_to_tsig_alg, TsigAlgorithm, TsigErrorCode}}; +use dns_rust::message::rclass::Rclass; + ///RFC 8945 TSIG tests /*This tests verifies section 5.3: @@ -45,8 +47,8 @@ async fn tsig_signature() { let mut dns_query_message = DnsMessage::new_query_message( DomainName::new_from_string(name.to_string()), - type_qtype::Qtype::A, - Qclass::IN, + Rrtype::A, + Rclass::IN, 0, false, id); @@ -86,14 +88,14 @@ async fn tsig_signature() { let mut addit = data.get_additional(); let rr = addit.pop().expect("No tsigrr"); let mut tsig_rd = TSigRdata::new(); - let mut can_sign = false; + // let mut can_sign = false; match rr.get_rdata() { Rdata::TSIG(data) =>{ tsig_rd = data; } _ => { - can_sign = true; + //can_sign = true; println!("error: no TSIG rdata found!"); } } @@ -157,18 +159,8 @@ async fn tsig_signature() { println!("Received {} bytes from {}", size, source); let data = DnsMessage::from_bytes(&buf[0..size]).unwrap(); println!("The data is {:?}", data); - let mut additionals = data.get_additional(); - let tsig_rr = additionals.pop().expect("No tsigrr"); - let mut tsig_rd= TSigRdata::new(); - match tsig_rr.get_rdata() { - Rdata::TSIG(data) =>{ - tsig_rd = data; - } - _ => { - println!("error: no TSIG rdata found!"); - } - } + // El cliente procesa la respuesta let (answer, error ) = process_tsig(&data, key, name.to_string(), time_signed, a_algs, mac); // se verifica que el mensaje haya pasado process_tsig From 814faeededd49f9746f4570062f5f1f969202333 Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 22:57:42 -0400 Subject: [PATCH 099/124] Refactor: incorporated the new Rrtype and corrected some deprecated calls --- src/dnssec/dnssec_fetch.rs | 7 +++++-- src/dnssec/dnssec_message.rs | 5 ++--- src/dnssec/rrset_signature.rs | 25 +++++++++++++------------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/dnssec/dnssec_fetch.rs b/src/dnssec/dnssec_fetch.rs index 24295daa..ccd090aa 100644 --- a/src/dnssec/dnssec_fetch.rs +++ b/src/dnssec/dnssec_fetch.rs @@ -1,7 +1,10 @@ -use crate::message::{DnsMessage, Rdata, ResourceRecord}; +use crate::message::DnsMessage; +use crate::message::rdata::Rdata; +use crate::message::rdata::dnskey_rdata::DnskeyRdata; +use crate::message::resource_record::ResourceRecord; use crate::dnssec::dnssec_message_processing::extract_dnssec_records; use crate::dnssec::rrset_signature::{verify_rrsig, verify_ds}; -use crate::message::rdata::DnskeyRdata; + use crate::client::client_error::ClientError; pub async fn fetch_dnskey_records(dns_response: &DnsMessage) -> Result, ClientError> { diff --git a/src/dnssec/dnssec_message.rs b/src/dnssec/dnssec_message.rs index 975cf6b8..3f1b4b0c 100644 --- a/src/dnssec/dnssec_message.rs +++ b/src/dnssec/dnssec_message.rs @@ -1,4 +1,3 @@ - use std::str::FromStr; use crate::domain_name::DomainName; use crate::message::rclass::Rclass; @@ -42,7 +41,7 @@ fn create_opt_rr(capacity: u16 ,e_rcode :u8, version: u8, do_bit: bool) -> Resou } fn read_opt_rr(opt_rr: ResourceRecord) -> String { - let requested_udp_len = Rclass::from_rclass_to_int(opt_rr.get_rclass()); + let requested_udp_len = Rclass::from(opt_rr.get_rclass()); let data = opt_rr.get_ttl().to_be_bytes(); let (e_rcode, version) = (data[0], data[1]); let z = u16::from_be_bytes([data[2], data[3]]); @@ -59,7 +58,7 @@ fn create_dns_message_with_dnssec(mut msg: DnsMessage) -> DnsMessage { // We create a opt rr with the do bit set to 1 // with NOERR as rcode and EDNS0 let rr = create_opt_rr(REQUESTED_UDP_LEN, - rcode::Rcode::from_rcode_to_int(Rcode::NOERROR), + Rcode::from(Rcode::NOERROR).into(), EDNS_VERSION, true); diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index ca59a2cc..d7d75447 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -4,29 +4,30 @@ use crypto::sha1::Sha1; use base64::encode; use crate::message::rdata::Rdata; use crate::message::rdata::dnskey_rdata::DnskeyRdata; -use crate::message::rdata::rrsig_rdata::{RRSIGRdata}; -use crate::message::resource_record::ResourceRecord; +use crate::message::rdata::rrsig_rdata::RRSIGRdata; +use crate::message::rrtype::Rrtype; +use crate::message::resource_record::{ResourceRecord, ToBytes}; use crate::client::client_error::ClientError; pub fn verify_rrsig(rrsig: &RRSIGRdata, dnskey: &DnskeyRdata, rrset: &[ResourceRecord]) -> Result { let mut rrsig_data = Vec::new(); - rrsig_data.extend_from_slice(&rrsig.get_type_covered().to_be_bytes()); + rrsig_data.extend_from_slice(&u16::from(rrsig.get_type_covered()).to_be_bytes()); rrsig_data.push(rrsig.get_algorithm()); rrsig_data.push(rrsig.get_labels()); rrsig_data.extend_from_slice(&rrsig.get_original_ttl().to_be_bytes()); rrsig_data.extend_from_slice(&rrsig.get_signature_expiration().to_be_bytes()); rrsig_data.extend_from_slice(&rrsig.get_signature_inception().to_be_bytes()); rrsig_data.extend_from_slice(&rrsig.get_key_tag().to_be_bytes()); - rrsig_data.extend_from_slice(rrsig.get_signer_name().to_bytes()?); + rrsig_data.extend_from_slice(&rrsig.get_signer_name().to_bytes());//Try? let mut rrset_sorted = rrset.to_vec(); rrset_sorted.sort_by(|a, b| a.get_name().cmp(&b.get_name())); for rr in rrset_sorted.iter() { - rrsig_data.extend_from_slice(rr.get_name().to_bytes()?); - rrsig_data.extend_from_slice(&rr.get_ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&rr.get_name().to_bytes()); //Try? + rrsig_data.extend_from_slice(&rr.get_ttl().to_be_bytes()); rrsig_data.extend_from_slice(&(rr.get_rdata().to_bytes().len() as u16).to_be_bytes()); - rrsig_data.extend_from_slice(&rr.get_rdata().to_bytes()?); + rrsig_data.extend_from_slice(&rr.get_rdata().to_bytes());//Try? } let signature = rrsig.get_signature().clone(); @@ -44,13 +45,13 @@ pub fn verify_rrsig(rrsig: &RRSIGRdata, dnskey: &DnskeyRdata, rrset: &[ResourceR // RSA/SHA256 Ok(encode(&hashed) == encode(&signature)) }, - _ => Err(ClientError::new("Unknown DNSKEY algorithm")), + _ => Err(ClientError::NotImplemented("Unknown DNSKEY algorithm")), } } pub fn verify_ds(ds_record: &ResourceRecord, dnskey: &DnskeyRdata) -> Result { if let Rdata::DS(ds_rdata) = &ds_record.get_rdata() { - let dnskey_bytes = dnskey.to_bytes()?; + let dnskey_bytes = dnskey.to_bytes(); //Try? let hashed_key = match ds_rdata.algorithm { 1 => { let mut hasher = Sha1::new(); @@ -61,11 +62,11 @@ pub fn verify_ds(ds_record: &ResourceRecord, dnskey: &DnskeyRdata) -> Result return Err(ClientError::new("Unknown DS algorithm")), + _ => return Err(ClientError::NotImplemented("Unknown DS algorithm")), }; - Ok(ds_rdata.digest == hashed_key) + Ok(ds_rdata.digest == hashed_key.as_bytes()) } else { - Err(ClientError::new("Provided record is not a DS record")) + Err(ClientError::FormatError("Provided record is not a DS record")) } } From afdebe2ecd8f55d412d2d6a1d358ef6e3bf151ec Mon Sep 17 00:00:00 2001 From: Carlo Date: Sun, 14 Jul 2024 22:59:27 -0400 Subject: [PATCH 100/124] Fix: line 88, changed rclass byte extracton --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 97010836..bb24bdc8 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -85,7 +85,7 @@ pub fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecor res.extend(tsig_rr.get_name().to_bytes()); //The below shifts are meant to correctly retreive theby //processing TSIG RR - let rclass_bytes: u16 = Rclass::from_rclass_to_int(tsig_rr.get_rclass()); + let rclass_bytes: u16 = Rclass::from(tsig_rr.get_rclass()).into(); let rclass_ubyte = (rclass_bytes >> 8) as u8; let rclass_lbyte = rclass_bytes as u8; res.push(rclass_ubyte); From 689601d183d950b1521bdcbb4c58df4ea8db8b11 Mon Sep 17 00:00:00 2001 From: joalopez Date: Mon, 15 Jul 2024 17:36:44 -0400 Subject: [PATCH 101/124] fix: bug tsig bytes --- src/message/rdata/tsig_rdata.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/message/rdata/tsig_rdata.rs b/src/message/rdata/tsig_rdata.rs index b6847765..6519cc05 100644 --- a/src/message/rdata/tsig_rdata.rs +++ b/src/message/rdata/tsig_rdata.rs @@ -74,6 +74,10 @@ impl ToBytes for TSigRdata{ bytes.push((time_signed >> 24) as u8); bytes.push((time_signed >> 16) as u8); + + bytes.push((time_signed >> 8) as u8); + + bytes.push((time_signed >> 0) as u8); let fudge = self.get_fudge(); @@ -557,7 +561,6 @@ mod tsig_rdata_test { } #[test] - #[ignore = "Fix test"] fn to_bytes_test(){ let mut tsig_rdata = TSigRdata::new(); @@ -611,7 +614,6 @@ mod tsig_rdata_test { } #[test] - #[ignore = "Fix test"] fn from_bytes_test(){ let bytes = vec![ //This is the string "hmac-md5.sig-alg.reg.int" in octal, terminated in 00 From 2e546aa6bf52a1047adf2b3304f01ddb948aeada Mon Sep 17 00:00:00 2001 From: joalopez Date: Tue, 16 Jul 2024 15:17:44 -0400 Subject: [PATCH 102/124] Fixed bug where does not include len when use mac in digest --- src/tsig.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index bb24bdc8..02e4551b 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -78,6 +78,10 @@ pub fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecor let mut res: Vec = vec![]; if (mac.len() != 0) { + let mac_len = mac.len() as u16; + let bytes_mac_len = mac_len.to_be_bytes(); + res.push(bytes_mac_len[0]); + res.push(bytes_mac_len[1]); res.extend(mac.clone()); } res.extend(dns_msg.clone()); @@ -328,9 +332,10 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, return (false, TsigErrorCode::BADKEY); } - let cond1 = check_key(key_in_rr, key_name); + let cond1 = check_key(key_in_rr.clone(), key_name.clone()); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); + println!("key in rr: {:?} key given {:?}", key_in_rr, key_name); return (false, TsigErrorCode::BADKEY); } From b3fbfa627594610a1b9c1693e10a45f525cb0c87 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 12:50:20 -0400 Subject: [PATCH 103/124] feat: Add immediate_process_tsig function for immediate TSIG processing --- src/tsig.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 02e4551b..d5d58af5 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -3,7 +3,7 @@ use std::fmt::{self,Display,Debug}; //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; - +use std::time::SystemTime; use crate::message::rclass::Rclass; use crate::message::resource_record::{ResourceRecord, ToBytes}; @@ -379,6 +379,14 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, (true, TsigErrorCode::NOERR) } + +pub fn immediate_process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, + available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, TsigErrorCode) { + + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + process_tsig(msg, key, key_name, time, available_algorithm, mac_to_process) +} + //Auxiliar function to create the TSIG variables and resource recrods #[doc= r"This function helps to set create a partial TSIG resource record on a DNS query"] fn set_tsig_vars(alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> ResourceRecord{ From fe8d5b409d42a711463dc48df1d00b51e55830b0 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 12:55:45 -0400 Subject: [PATCH 104/124] Refactor tsig.rs module and fix bugs --- src/tsig.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index d5d58af5..4954d582 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,5 +1,4 @@ -use std::convert::TryInto; -use std::fmt::{self,Display,Debug}; +use std::fmt::Debug; //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; @@ -8,15 +7,14 @@ use crate::message::rclass::Rclass; use crate::message::resource_record::{ResourceRecord, ToBytes}; use crate::message::{rdata::tsig_rdata::TSigRdata, DnsMessage,}; -use crate::message::rdata::{tsig_rdata, Rdata}; +use crate::message::rdata::Rdata; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; -use hmac::{Hmac, Mac}; use crypto::{sha1::Sha1,sha2::Sha256}; use crate::message::rdata::a_rdata::ARdata; use crate::message::rrtype::Rrtype; -type HmacSha256 = Hmac; + #[derive(Debug)] From cb994b5cbab963faaaaac071bc46a68aa31a47c5 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 15:07:40 -0400 Subject: [PATCH 105/124] Refactor arg set_ad and set_cd methods in header.rs --- src/message/header.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index b67ea918..8cced7eb 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -481,13 +481,13 @@ impl Header { } /// Sets the ad attribute with a value. - pub fn set_ad(&mut self, ra: bool) { - self.ad = ra; + pub fn set_ad(&mut self, ad: bool) { + self.ad = ad; } /// Sets the cd attribute with a value. - pub fn set_cd(&mut self, ra: bool) { - self.cd = ra; + pub fn set_cd(&mut self, cd: bool) { + self.cd = cd; } /// Sets the rcode attribute with a value. From 0a183bc7a9bc62b5fd9baae1f65d9bead3c6a012 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 15:09:10 -0400 Subject: [PATCH 106/124] chore: changed comments --- src/message/header.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message/header.rs b/src/message/header.rs index 8cced7eb..8cf92bd9 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -42,7 +42,7 @@ pub struct Header { rd: bool, // Recursion Desired ra: bool, // Recursion Available ad: bool, // Authentic data - cd: bool, // cd data + cd: bool, // Checking Disabled data /// Reserved Edit: Now z is just a flag #[allow(dead_code)] From fd62ab037fa524394a29cc8abf0969fe6b1984c1 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 15:09:58 -0400 Subject: [PATCH 107/124] chore: coments --- src/message/header.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 8cf92bd9..28904d60 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -41,8 +41,8 @@ pub struct Header { tc: bool, // TrunCation rd: bool, // Recursion Desired ra: bool, // Recursion Available - ad: bool, // Authentic data - cd: bool, // Checking Disabled data + ad: bool, // Authentic Data + cd: bool, // Checking Disabled /// Reserved Edit: Now z is just a flag #[allow(dead_code)] From 46e84a5f4c97214703859eb2cea2d523ed6bd8c0 Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 15:11:13 -0400 Subject: [PATCH 108/124] chore: comments --- src/message/header.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/message/header.rs b/src/message/header.rs index 28904d60..0d9b6c9b 100644 --- a/src/message/header.rs +++ b/src/message/header.rs @@ -5,8 +5,8 @@ use crate::message::rcode::Rcode; /// An struct that represents a Header secction from a DNS message. /// EDIT: now added bits AD CD for DNS security extensions. /// -/// 1 1 1 1 1 1 -/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +/// 1 1 1 1 1 1 +/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ /// | ID | /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ From 4999c981f83ee4a4e5072784f077acf5c2985fbf Mon Sep 17 00:00:00 2001 From: joalopez Date: Wed, 17 Jul 2024 16:21:01 -0400 Subject: [PATCH 109/124] Refactor tsig use ANY instead of IN --- src/message/resource_record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message/resource_record.rs b/src/message/resource_record.rs index 78017e58..64ab9a0b 100644 --- a/src/message/resource_record.rs +++ b/src/message/resource_record.rs @@ -212,7 +212,7 @@ impl ResourceRecord { Rdata::TSIG(val) => ResourceRecord { name: DomainName::new(), rtype: Rrtype::TSIG, - rclass: Rclass::IN, + rclass: Rclass::ANY, ttl: 0 as u32, rdlength: 0 as u16, rdata: Rdata::TSIG(val), From 25c75759086a7b5aa3fb8b47199a2c2459c91f96 Mon Sep 17 00:00:00 2001 From: joalopez Date: Thu, 18 Jul 2024 11:46:56 -0400 Subject: [PATCH 110/124] Refactor display format for DnsMessage and Question sections --- src/message.rs | 9 ++++++--- src/message/question.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/message.rs b/src/message.rs index 3d215afe..f820f175 100644 --- a/src/message.rs +++ b/src/message.rs @@ -686,14 +686,17 @@ impl DnsMessage { impl fmt::Display for DnsMessage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut result = String::new(); + let question = self.get_question(); let answers = self.get_answer().into_iter(); let authority = self.get_authority().into_iter(); let additional = self.get_additional().into_iter(); - result.push_str(&format!("Answer\n")); + result.push_str(&format!("Question section\n")); + result.push_str(&format!("{}\n", question)); + result.push_str(&format!("Answer section\n")); answers.for_each(|answer| result.push_str(&format!("{}\n", answer))); - result.push_str(&format!("Authority\n")); + result.push_str(&format!("Authority section\n")); authority.for_each(|authority| result.push_str(&format!("{}\n", authority))); - result.push_str(&format!("Additional\n")); + result.push_str(&format!("Additional section\n")); additional.for_each(|additional| result.push_str(&format!("{}\n", additional))); write!(f, "{}", result) } diff --git a/src/message/question.rs b/src/message/question.rs index af445d7a..bc9f4cd5 100644 --- a/src/message/question.rs +++ b/src/message/question.rs @@ -4,6 +4,8 @@ use crate::message::rclass::Rclass; use super::rrtype::Rrtype; +use std::fmt; + #[derive(Default, Clone)] /// An struct that represents the question section from a dns message /// ```text @@ -29,6 +31,20 @@ pub struct Question { rclass: Rclass, } + +impl fmt::Display for Question { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let name = self.get_qname().get_name(); + let rtype = self.get_rrtype(); + let rclass = self.get_rclass(); + + formatter.write_fmt(format_args!( + "{} {} {} ", + name, rclass, rtype + )) + } +} + // Methods impl Question { /// Creates a new Question with default values From 1af18b6e726d48cce02bd8992bd2b0d46a245475 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 11:25:53 -0400 Subject: [PATCH 111/124] delete unused variable --- src/async_resolver.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/async_resolver.rs b/src/async_resolver.rs index 3a150a9f..8495155f 100644 --- a/src/async_resolver.rs +++ b/src/async_resolver.rs @@ -313,7 +313,6 @@ impl AsyncResolver { /// answer section, it is always preferred. fn store_data_cache(&self, response: DnsMessage) { let truncated = response.get_header().get_tc(); - let rcode = response.get_header().get_rcode(); { let mut cache = self.cache.lock().unwrap(); cache.timeout(); From 4399bb7f30a3f0db847045e8cb5d3b148658bced Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 12:11:18 -0400 Subject: [PATCH 112/124] feat: Add TsigAlgorithm enum and conversions This commit adds the TsigAlgorithm enum, which represents the supported TSIG algorithms for DNS messages. It includes the HmacSha1 and HmacSha256 algorithms. The enum also provides conversions to and from strings for easy serialization and deserialization. --- src/tsig/tsig_algorithm.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/tsig/tsig_algorithm.rs diff --git a/src/tsig/tsig_algorithm.rs b/src/tsig/tsig_algorithm.rs new file mode 100644 index 00000000..5bdf4f0e --- /dev/null +++ b/src/tsig/tsig_algorithm.rs @@ -0,0 +1,25 @@ + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TsigAlgorithm { + HmacSha1, + HmacSha256, +} + +impl From for String { + fn from(alg: TsigAlgorithm) -> String { + match alg { + TsigAlgorithm::HmacSha1 => "hmac-sha1".to_string(), + TsigAlgorithm::HmacSha256 => "hmac-sha256".to_string(), + } + } +} + +impl From for TsigAlgorithm { + fn from(name: String) -> TsigAlgorithm { + match name { + name if name == "hmac-sha1" => TsigAlgorithm::HmacSha1, + name if name == "hmac-sha256" => TsigAlgorithm::HmacSha256, + _ => panic!("Invalid TsigAlgorithm"), + } + } +} \ No newline at end of file From 861f83ad0594b3d5e3b082239ea3e7c48f5f236c Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 12:11:31 -0400 Subject: [PATCH 113/124] Clean code from warnings --- src/tsig.rs | 530 +++++++++++++++++++++++++--------------------------- 1 file changed, 254 insertions(+), 276 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 4954d582..55c3cf3f 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,3 +1,5 @@ +pub mod tsig_algorithm; + use std::fmt::Debug; //aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; @@ -11,34 +13,9 @@ use crate::message::rdata::Rdata; use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use crypto::{sha1::Sha1,sha2::Sha256}; -use crate::message::rdata::a_rdata::ARdata; -use crate::message::rrtype::Rrtype; - - +use tsig_algorithm::TsigAlgorithm; -#[derive(Debug)] -//TODO: usar arreglar el funcionamiento del enum en sign_msg -pub enum TsigAlgorithm { - HmacSha1, - HmacSha256, -} - -fn tsig_alg_to_string(alg: &TsigAlgorithm) -> String { - match alg { - TsigAlgorithm::HmacSha1 => "hmac-sha1".to_string(), - TsigAlgorithm::HmacSha256 => "hmac-sha256".to_string(), - } -} -pub fn string_to_tsig_alg(name: String) -> TsigAlgorithm{ - let sha1 = "hmac-sha1".to_string(); - let sha256 = "hmac-sha256".to_string(); - match name{ - sha1=> TsigAlgorithm::HmacSha1, - sha256 => TsigAlgorithm::HmacSha256 - } -} - #[derive(PartialEq)] #[derive(Debug)] pub enum TsigErrorCode{ @@ -75,7 +52,7 @@ fn set_tsig_rd(name: String, original_id: u16, result: MacResult, pub fn get_digest_request(mac: Vec ,dns_msg: Vec, tsig_rr: ResourceRecord) -> Vec { let mut res: Vec = vec![]; - if (mac.len() != 0) { + if mac.len() != 0 { let mac_len = mac.len() as u16; let bytes_mac_len = mac_len.to_be_bytes(); res.push(bytes_mac_len[0]); @@ -172,10 +149,10 @@ fn digest(bytes: Vec, tsig_algorithm: TsigAlgorithm, key: Vec) -> Vec) -> Vec { - let mut tsig_rd: TSigRdata = TSigRdata::new(); + let tsig_rd: TSigRdata; let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); - let alg_name_str = tsig_alg_to_string(&alg_name); + let alg_name_str = String::from(alg_name); let tsig_rr= set_tsig_vars(alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); let digest_comp = get_digest_request(mac_request, new_query_message.to_bytes(), @@ -210,7 +187,6 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm 32); }, - _ => {panic!("Error: Invalid algorithm")}, } let rr_len = tsig_rd.to_bytes().len() as u16; let signature = tsig_rd.get_mac(); @@ -309,7 +285,7 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, //sacar el último elemento del vector resource record, y disminuir elvalor de ARCOUNT let rr_copy = addit.pop().expect("No tsig rr"); - let mut tsig_rr_copy = TSigRdata::new(); + let tsig_rr_copy: TSigRdata; match rr_copy.get_rdata() { Rdata::TSIG(data) =>{ tsig_rr_copy = data; @@ -342,12 +318,11 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, let fudge = tsig_rr_copy.get_fudge(); let time_signed = tsig_rr_copy.get_time_signed(); let mac_received = tsig_rr_copy.get_mac(); - let key_name = rr_copy.get_name().get_name(); let mut new_alg_name: TsigAlgorithm = TsigAlgorithm::HmacSha1; match name_alg.as_str() { "hmac-sha1" => new_alg_name = TsigAlgorithm::HmacSha1, "hmac-sha256" => new_alg_name = TsigAlgorithm::HmacSha256, - &_ => println!("not supported algorithm") + &_ => println!("Not supported algorithm") } //let nuevo_len_arcount = addit.len() as u16; @@ -407,250 +382,253 @@ fn set_tsig_vars(alg_name: &str, name: &str, time_signed: u64, fudge: u16) -> Re //Sección de tests unitarios -#[test] -fn check_process_tsig_exists() { - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - let server_key = b"1234567890"; - lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error,TsigErrorCode::FORMERR); -} +#[cfg(test)] +mod tsig_test { + use super::*; + use crate::message::rdata::a_rdata::ARdata; + use crate::message::rrtype::Rrtype; + + #[test] + fn check_process_tsig_exists() { + //Server process + let response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + let server_key = b"1234567890"; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error,TsigErrorCode::FORMERR); + } -#[test] -fn check_process_tsig_exists2() { - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let alg_name2 = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - let name = "test.com"; - // cloning response - let mut response2 = response.clone(); - - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone(), vec![]); - let mut response_capture = response.clone(); - sign_tsig(&mut response_capture, server_key, alg_name2, fudge, time_signed, key_name.clone(), vec![]); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmac-sha256"),true)); - let (control_answer, _) = process_tsig(& response, server_key, key_name.clone(),21010, lista.clone(), vec![]); - assert!(control_answer); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error, TsigErrorCode::FORMERR); -} + #[test] + fn check_process_tsig_exists2() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let alg_name2 = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.clone(), vec![]); + let mut response_capture = response.clone(); + sign_tsig(&mut response_capture, server_key, alg_name2, fudge, time_signed, key_name.clone(), vec![]); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha256"),true)); + let (control_answer, _) = process_tsig(& response, server_key, key_name.clone(),21010, lista.clone(), vec![]); + assert!(control_answer); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error, TsigErrorCode::FORMERR); + } -// verificar que no se haya añadido otro resource record en el additionals luego de añadir un tsig_rr -#[test] -fn check_process_tsig_exists3(){ - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = ""; - //se crea un rr TSIG que se añadirá en adittionals - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.to_string(), vec![]); - - //se agrega otro resource record en el additional... - let mut new_additional = Vec::::new(); - let a_rdata5 = Rdata::A(ARdata::new()); - let rr5 = ResourceRecord::new(a_rdata5); - new_additional.push(rr5); - response.add_additionals(new_additional); - let mut response_capture = response.clone(); - - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error, TsigErrorCode::FORMERR); -} -#[test] -fn check_process_tsig_alg_name() { - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); - let mut response_capture = response.clone(); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - //suponemos que hmacsha256 no está disponible - lista.push((String::from("hmac-sha1"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); -} -#[test] -fn check_process_tsig_alg_name2() { - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); - let mut response_capture = response.clone(); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - //suponemos que reconocemos hmac-sha256, pero no está implementado - lista.push((String::from("hmac-sha256"),false)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); -} -#[test] -fn check_process_tsig_key(){ - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); - let mut response_capture = response.clone(); - //Client process - let key_name:String = "different".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - //suponemos que reconocemos hmac-sha256, pero no está implementado - lista.push((String::from("hmac-sha256"),false)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); - assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); -} -//TODO: completar este test, hay cosas que faltan por implementar -#[test] -fn check_process_tsig_badsign(){ - // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN - let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 1000; - let time_signed = 210000000; - let key_name = "".to_string(); - // se firma el mensaje con algoritmo SHA-1 - sign_tsig(& mut msg1, key, alg_name, fudge, time_signed, key_name, vec![]); - let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmac-sha1"),true)); - lista.push((String::from("hmac-sha256"),true)); - // se verifica que el mensaje está firmado, pero se usa otra key - let key_name = "".to_string(); - let key2 = b"12345678909"; - let (answer,error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista, vec![]); - assert_eq!(error,TsigErrorCode::BADSIG); -} -#[test] -fn check_proces_tsig_badtime(){ - //Server process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); - let mut response_capture = response.clone(); - //Client process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - //suponemos que reconocemos hmac-sha256, pero no está implementado - lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, - 22010, lista, vec![]); - assert!(!answer); - assert_eq!(error,TsigErrorCode::BADTIME); -} -#[test] -fn check_process_tsig() { - //sender process - let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); - let server_key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha256; - let fudge = 300; - let time_signed = 21000; - let key_name = "".to_string(); - sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); - let mut response_capture = response.clone(); - //recv process - let key_name:String = "".to_string(); - let mut lista :Vec<(String, bool)> = vec![]; - lista.push((String::from("hmac-sha256"),true)); - let (answer, error) = process_tsig(& response_capture, server_key, key_name, - 21010, lista, vec![]); - assert!(answer); - assert_eq!(error,TsigErrorCode::NOERR); -} -//Unitary test to verify that the signer function is working properly -#[test] -fn check_signed_tsig() { - let key = b"1234567890"; - let alg_name = TsigAlgorithm::HmacSha1; - let fudge = 0; - let time_signed = 0; - let id = 6502; - let name: String = "".to_string(); - let mac_size = 20; - let domain = DomainName::new_from_str("uchile.cl"); - //DNS message - let mut q = DnsMessage::new_query_message( - domain.clone(), - Rrtype::A, - Rclass::ANY, - 0, - false, - id - ); - //partial TSIG Resource record verify the signing process - let tsig_rr = set_tsig_vars(tsig_alg_to_string(&alg_name).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![]); - // 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); - hasher.input(&dig_for_mac[..]); - - let result = hasher.result(); - let mac_to_cmp = result.code(); - - let rr = q.get_additional().pop().expect("Should be a tsig"); - match rr.get_rdata() { - Rdata::TSIG(data) => { - assert_eq!(data.get_algorithm_name(), DomainName::new_from_str("hmac-sha1")); - assert_eq!(data.get_time_signed(), time_signed); - assert_eq!(data.get_fudge() , fudge); - assert_eq!(data.get_mac_size(), 20); - assert_eq!(data.get_original_id(), id); - assert_eq!(data.get_error(), 0); - assert_eq!(data.get_other_len(), 0); - assert!(data.get_other_data().is_empty()); - }, - _ =>{ - assert!(false); - } + // verificar que no se haya añadido otro resource record en el additionals luego de añadir un tsig_rr + #[test] + fn check_process_tsig_exists3(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = ""; + //se crea un rr TSIG que se añadirá en adittionals + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name.to_string(), vec![]); + + //se agrega otro resource record en el additional... + let mut new_additional = Vec::::new(); + let a_rdata5 = Rdata::A(ARdata::new()); + let rr5 = ResourceRecord::new(a_rdata5); + new_additional.push(rr5); + response.add_additionals(new_additional); + let response_capture = response.clone(); + + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error, TsigErrorCode::FORMERR); } - println!("Comparando el mac"); - for i in 0..mac_to_cmp.len() { - assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); + #[test] + fn check_process_tsig_alg_name() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); + let response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que hmacsha256 no está disponible + lista.push((String::from("hmac-sha1"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); } -} + #[test] + fn check_process_tsig_alg_name2() { + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); + let response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),false)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); + } + #[test] + fn check_process_tsig_key(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); + let response_capture = response.clone(); + //Client process + let key_name:String = "different".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),false)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADKEY); + } + //TODO: completar este test, hay cosas que faltan por implementar + #[test] + fn check_process_tsig_badsign(){ + // Se establece un DnsMessage de prueba. Lo firmaremos, alteraremos la firma generada y esperamos recibir un error BADSIGN + let mut msg1 = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 1000; + let time_signed = 210000000; + let key_name = "".to_string(); + // se firma el mensaje con algoritmo SHA-1 + sign_tsig(& mut msg1, key, alg_name, fudge, time_signed, key_name, vec![]); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha1"),true)); + lista.push((String::from("hmac-sha256"),true)); + // se verifica que el mensaje está firmado, pero se usa otra key + let key_name = "".to_string(); + let key2 = b"12345678909"; + let (_, error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista, vec![]); + assert_eq!(error,TsigErrorCode::BADSIG); + } + #[test] + fn check_proces_tsig_badtime(){ + //Server process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); + let response_capture = response.clone(); + //Client process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + //suponemos que reconocemos hmac-sha256, pero no está implementado + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, + 22010, lista, vec![]); + assert!(!answer); + assert_eq!(error,TsigErrorCode::BADTIME); + } + #[test] + fn check_process_tsig() { + //sender process + let mut response = DnsMessage::new_response_message(String::from("test.com"), "NS", "IN", 1, true, 1); + let server_key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha256; + let fudge = 300; + let time_signed = 21000; + let key_name = "".to_string(); + sign_tsig(&mut response, server_key, alg_name, fudge, time_signed, key_name, vec![]); + let response_capture = response.clone(); + //recv process + let key_name:String = "".to_string(); + let mut lista :Vec<(String, bool)> = vec![]; + lista.push((String::from("hmac-sha256"),true)); + let (answer, error) = process_tsig(& response_capture, server_key, key_name, + 21010, lista, vec![]); + assert!(answer); + assert_eq!(error,TsigErrorCode::NOERR); + } + //Unitary test to verify that the signer function is working properly + #[test] + fn check_signed_tsig() { + let key = b"1234567890"; + let alg_name = TsigAlgorithm::HmacSha1; + let fudge = 0; + let time_signed = 0; + let id = 6502; + let name: String = "".to_string(); + let domain = DomainName::new_from_str("uchile.cl"); + //DNS message + let mut q = DnsMessage::new_query_message( + domain.clone(), + Rrtype::A, + Rclass::ANY, + 0, + false, + id + ); + //partial TSIG Resource record verify the signing process + let tsig_rr = set_tsig_vars(String::from(alg_name).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![]); + // 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); + hasher.input(&dig_for_mac[..]); + + let result = hasher.result(); + let mac_to_cmp = result.code(); + + let rr = q.get_additional().pop().expect("Should be a tsig"); + match rr.get_rdata() { + Rdata::TSIG(data) => { + assert_eq!(data.get_algorithm_name(), DomainName::new_from_str("hmac-sha1")); + assert_eq!(data.get_time_signed(), time_signed); + assert_eq!(data.get_fudge() , fudge); + assert_eq!(data.get_mac_size(), 20); + assert_eq!(data.get_original_id(), id); + assert_eq!(data.get_error(), 0); + assert_eq!(data.get_other_len(), 0); + assert!(data.get_other_data().is_empty()); + }, + _ =>{ + assert!(false); + } + } + println!("Comparando el mac"); + for i in 0..mac_to_cmp.len() { + assert_eq!(mac_to_cmp[i], firma_a_comparar[i]); + } + } +} \ No newline at end of file From b676c517763ef1c6da7f6fbb8909d11ac9d4a069 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 12:22:21 -0400 Subject: [PATCH 114/124] Re-order tsigErrorCode --- src/tsig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 55c3cf3f..77a3b1f3 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -20,10 +20,10 @@ use tsig_algorithm::TsigAlgorithm; #[derive(Debug)] pub enum TsigErrorCode{ NOERR = 0, + FORMERR = 1, BADSIG = 16, BADKEY = 17, BADTIME = 18, - FORMERR = 1, } //TODO: Encontrar alguna manera de pasar una referencia Digest u Hmac de un algoritmo no especificado From a7c43cd9a6048c7e48dfcf9c964711dab7e2d92b Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 12:33:01 -0400 Subject: [PATCH 115/124] chore: Refactor tsig_integration_tests.rs The code changes in this commit refactor the `tsig_integration_tests.rs` file. Specifically, the changes reorder the `tsigErrorCode` and clean the code from warnings. This commit does not introduce any new features or fix any bugs. --- tests/tsig_integration_tests.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index a73078f0..f10187db 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, net:: UdpSocket, thread, time::Duration}; -use dns_rust::{domain_name::DomainName, message::{rdata::{tsig_rdata::TSigRdata, Rdata}, rrtype::Rrtype, DnsMessage},tsig::{process_tsig, sign_tsig, string_to_tsig_alg, TsigAlgorithm, TsigErrorCode}}; +use dns_rust::{domain_name::DomainName, message::{rdata::{tsig_rdata::TSigRdata, Rdata}, rrtype::Rrtype, DnsMessage},tsig::{process_tsig, sign_tsig, TsigErrorCode}}; +use dns_rust::tsig::tsig_algorithm::TsigAlgorithm; use dns_rust::message::rclass::Rclass; @@ -110,12 +111,12 @@ async fn tsig_signature() { let key_found = keys[&name]; //el servidor verifica la estructura del tsig recibido. Sumamos un pequeño delay al time para simular retraso - let (answer,error) = process_tsig(&data, key_found, key_name.clone(), time + 50, list, vec![]); + let (_,error) = process_tsig(&data, key_found, key_name.clone(), time + 50, list, vec![]); //se setea el aditional sin el ultimo resource record, para que sign_tsig lo regenere data.set_additional(addit); data.update_header_counters(); // se firma el mensaje recibido con el digest de la respuesta. Notar que el vector final ahora no está vacío - sign_tsig(&mut data, key_found,string_to_tsig_alg(alg_name),fudge,time, key_name, mac); + sign_tsig(&mut data, key_found,TsigAlgorithm::from(alg_name),fudge,time, key_name, mac); let response = &DnsMessage::to_bytes(&data); //se verifica que la request haya pasado proces_tsig assert_eq!(error,TsigErrorCode::NOERR); From ab3b7def00f210f5ec61cd64911da48de750ed5a Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 12:56:07 -0400 Subject: [PATCH 116/124] Delete comment --- src/tsig.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tsig.rs b/src/tsig.rs index 77a3b1f3..0bd7c370 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,7 +1,6 @@ pub mod tsig_algorithm; use std::fmt::Debug; -//aquí debe ir todo lo relacionado a la implementación de tsig como módulo use crypto::mac::MacResult; use crate::domain_name::DomainName; use std::time::SystemTime; From 2f59b3620c5579e0b73621fd3e0b543cf14da919 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 13:52:56 -0400 Subject: [PATCH 117/124] add UNKNOWN to Tsig Algorithm enum --- src/tsig.rs | 10 ++++++++-- src/tsig/tsig_algorithm.rs | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index 0bd7c370..d8988ac7 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -141,6 +141,9 @@ fn digest(bytes: Vec, tsig_algorithm: TsigAlgorithm, key: Vec) -> Vec { + panic!("Unknown algorithm {}", a); + } } } @@ -151,7 +154,7 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm let tsig_rd: TSigRdata; let new_query_message = query_msg.clone(); let original_id = query_msg.get_query_id(); - let alg_name_str = String::from(alg_name); + let alg_name_str = String::from(alg_name.clone()); let tsig_rr= set_tsig_vars(alg_name_str.as_str(), key_name.as_str(), time_signed, fudge); let digest_comp = get_digest_request(mac_request, new_query_message.to_bytes(), @@ -186,6 +189,9 @@ pub fn sign_tsig(query_msg: &mut DnsMessage, key: &[u8], alg_name: TsigAlgorithm 32); }, + TsigAlgorithm::UNKNOWN(a) => { + panic!("Unknown algorithm {}", a); + } } let rr_len = tsig_rd.to_bytes().len() as u16; let signature = tsig_rd.get_mac(); @@ -597,7 +603,7 @@ mod tsig_test { id ); //partial TSIG Resource record verify the signing process - let tsig_rr = set_tsig_vars(String::from(alg_name).as_str(), &name, time_signed, fudge); + 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![]); diff --git a/src/tsig/tsig_algorithm.rs b/src/tsig/tsig_algorithm.rs index 5bdf4f0e..8701bd03 100644 --- a/src/tsig/tsig_algorithm.rs +++ b/src/tsig/tsig_algorithm.rs @@ -1,8 +1,9 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum TsigAlgorithm { HmacSha1, HmacSha256, + UNKNOWN(String), } impl From for String { @@ -10,6 +11,7 @@ impl From for String { match alg { TsigAlgorithm::HmacSha1 => "hmac-sha1".to_string(), TsigAlgorithm::HmacSha256 => "hmac-sha256".to_string(), + TsigAlgorithm::UNKNOWN(s) => s, } } } @@ -19,7 +21,7 @@ impl From for TsigAlgorithm { match name { name if name == "hmac-sha1" => TsigAlgorithm::HmacSha1, name if name == "hmac-sha256" => TsigAlgorithm::HmacSha256, - _ => panic!("Invalid TsigAlgorithm"), + _ => TsigAlgorithm::UNKNOWN(name), } } } \ No newline at end of file From e363f8a864c133c886eb083f8d3d8c48bbba7615 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 13:59:19 -0400 Subject: [PATCH 118/124] Add new RCODES --- src/message/rcode.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/message/rcode.rs b/src/message/rcode.rs index 91d3d036..a4f5d1d3 100644 --- a/src/message/rcode.rs +++ b/src/message/rcode.rs @@ -11,6 +11,9 @@ pub enum Rcode { NXDOMAIN, NOTIMP, REFUSED, + BADSIG, + BADKEY, + BADTIME, UNKNOWN(u8), } @@ -23,6 +26,9 @@ impl From for Rcode { 3 => Rcode::NXDOMAIN, 4 => Rcode::NOTIMP, 5 => Rcode::REFUSED, + 16 => Rcode::BADSIG, + 17 => Rcode::BADKEY, + 18 => Rcode::BADTIME, _ => Rcode::UNKNOWN(int), } } @@ -37,6 +43,9 @@ impl From for u8 { Rcode::NXDOMAIN => 3, Rcode::NOTIMP => 4, Rcode::REFUSED => 5, + Rcode::BADSIG => 16, + Rcode::BADKEY => 17, + Rcode::BADTIME => 18, Rcode::UNKNOWN(u8) => u8, } } @@ -69,6 +78,9 @@ impl fmt::Display for Rcode { Rcode::NXDOMAIN => "NXDOMAIN", Rcode::NOTIMP => "NOTIMP", Rcode::REFUSED => "REFUSED", + Rcode::BADSIG => "BADSIG", + Rcode::BADKEY => "BADKEY", + Rcode::BADTIME => "BADTIME", Rcode::UNKNOWN(_) => "UNKNOWN", }) } From c92bf4cf07a0285bf0f8ea23921d9c3dbcdb996a Mon Sep 17 00:00:00 2001 From: Litr0 Date: Thu, 25 Jul 2024 14:05:22 -0400 Subject: [PATCH 119/124] refactor tsig rcode enum --- src/tsig.rs | 48 +++++++++++++-------------------- tests/tsig_integration_tests.rs | 7 ++--- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/tsig.rs b/src/tsig.rs index d8988ac7..7e9ea491 100644 --- a/src/tsig.rs +++ b/src/tsig.rs @@ -1,6 +1,5 @@ pub mod tsig_algorithm; -use std::fmt::Debug; use crypto::mac::MacResult; use crate::domain_name::DomainName; use std::time::SystemTime; @@ -13,18 +12,9 @@ use crypto::hmac::Hmac as crypto_hmac; use crypto::mac::Mac as crypto_mac; use crypto::{sha1::Sha1,sha2::Sha256}; use tsig_algorithm::TsigAlgorithm; +use crate::message::rcode::Rcode; -#[derive(PartialEq)] -#[derive(Debug)] -pub enum TsigErrorCode{ - NOERR = 0, - FORMERR = 1, - BADSIG = 16, - BADKEY = 17, - BADTIME = 18, - -} //TODO: Encontrar alguna manera de pasar una referencia Digest u Hmac de un algoritmo no especificado // función auxiliar para evitar la redundancia de código en sign_tsig fn set_tsig_rd(name: String, original_id: u16, result: MacResult, @@ -270,7 +260,7 @@ fn check_last_one_is_tsig(add_rec: &Vec) -> bool { #[doc = r"This function process a tsig message, checking for errors in the DNS message"] pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, - available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, TsigErrorCode) { + available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, Rcode) { let mut retmsg = msg.clone(); let mut addit = retmsg.get_additional(); //RFC 8945 5.2 y 5.4 @@ -278,14 +268,14 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, //vector con resource records que son TSIG. Luego se Verifica si hay algún tsig rr if check_exists_tsig_rr(&addit) { println!("RCODE 1: FORMERR"); - return (false, TsigErrorCode::FORMERR); + return (false, Rcode::FORMERR); } //Debe haber un único tsig //Tsig RR debe ser el último en la sección adicional, y debe ser único if check_last_one_is_tsig(&addit) { println!("RCODE 1: FORMERR"); - return (false, TsigErrorCode::FORMERR); + return (false, Rcode::FORMERR); } //sacar el último elemento del vector resource record, y disminuir elvalor de ARCOUNT @@ -308,14 +298,14 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, let flag = check_alg_name(&name_alg, available_algorithm); if !flag { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); - return (false, TsigErrorCode::BADKEY); + return (false, Rcode::BADKEY); } let cond1 = check_key(key_in_rr.clone(), key_name.clone()); if !cond1 { println!("RCODE 9: NOAUTH\n TSIG ERROR 17: BADKEY"); println!("key in rr: {:?} key given {:?}", key_in_rr, key_name); - return (false, TsigErrorCode::BADKEY); + return (false, Rcode::BADKEY); } //RFC 8945 5.2.2 @@ -346,20 +336,20 @@ pub fn process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, time: u64, if !cond2 { println!("RCODE 9: NOAUTH\n TSIG ERROR 16: BADSIG"); - return (false, TsigErrorCode::BADSIG) + return (false, Rcode::BADSIG) } //let mytime = SystemTime::now().duration_since(UNIX_EPOCH).expect("no debería fallar el tiempo"); let cond3 = check_time_values(time, fudge, time_signed); if !cond3 { println!("RCODE 9: NOAUTH\n TSIG ERROR 18: BADTIME"); - return (false, TsigErrorCode::BADTIME) + return (false, Rcode::BADTIME) } - (true, TsigErrorCode::NOERR) + (true, Rcode::NOERROR) } pub fn immediate_process_tsig(msg: &DnsMessage, key:&[u8], key_name: String, - available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, TsigErrorCode) { + available_algorithm: Vec<(String, bool)>, mac_to_process: Vec) -> (bool, Rcode) { let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); process_tsig(msg, key, key_name, time, available_algorithm, mac_to_process) @@ -404,7 +394,7 @@ mod tsig_test { lista.push((String::from("hmac-sha256"),true)); let (answer, error) = process_tsig(& response, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error,TsigErrorCode::FORMERR); + assert_eq!(error,Rcode::FORMERR); } #[test] @@ -429,7 +419,7 @@ mod tsig_test { assert!(control_answer); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error, TsigErrorCode::FORMERR); + assert_eq!(error, Rcode::FORMERR); } // verificar que no se haya añadido otro resource record en el additionals luego de añadir un tsig_rr @@ -459,7 +449,7 @@ mod tsig_test { lista.push((String::from("hmac-sha256"),true)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error, TsigErrorCode::FORMERR); + assert_eq!(error, Rcode::FORMERR); } #[test] fn check_process_tsig_alg_name() { @@ -479,7 +469,7 @@ mod tsig_test { lista.push((String::from("hmac-sha1"),true)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); + assert_eq!(error,Rcode::BADKEY); } #[test] fn check_process_tsig_alg_name2() { @@ -499,7 +489,7 @@ mod tsig_test { lista.push((String::from("hmac-sha256"),false)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); + assert_eq!(error,Rcode::BADKEY); } #[test] fn check_process_tsig_key(){ @@ -519,7 +509,7 @@ mod tsig_test { lista.push((String::from("hmac-sha256"),false)); let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(!answer); - assert_eq!(error,TsigErrorCode::BADKEY); + assert_eq!(error,Rcode::BADKEY); } //TODO: completar este test, hay cosas que faltan por implementar #[test] @@ -540,7 +530,7 @@ mod tsig_test { let key_name = "".to_string(); let key2 = b"12345678909"; let (_, error) = process_tsig(&mut msg1, key2, key_name, time_signed,lista, vec![]); - assert_eq!(error,TsigErrorCode::BADSIG); + assert_eq!(error,Rcode::BADSIG); } #[test] fn check_proces_tsig_badtime(){ @@ -561,7 +551,7 @@ mod tsig_test { let (answer, error) = process_tsig(& response_capture, server_key, key_name, 22010, lista, vec![]); assert!(!answer); - assert_eq!(error,TsigErrorCode::BADTIME); + assert_eq!(error,Rcode::BADTIME); } #[test] fn check_process_tsig() { @@ -581,7 +571,7 @@ mod tsig_test { let (answer, error) = process_tsig(& response_capture, server_key, key_name, 21010, lista, vec![]); assert!(answer); - assert_eq!(error,TsigErrorCode::NOERR); + assert_eq!(error,Rcode::NOERROR); } //Unitary test to verify that the signer function is working properly #[test] diff --git a/tests/tsig_integration_tests.rs b/tests/tsig_integration_tests.rs index f10187db..9343f980 100644 --- a/tests/tsig_integration_tests.rs +++ b/tests/tsig_integration_tests.rs @@ -1,6 +1,7 @@ use std::{collections::HashMap, net:: UdpSocket, thread, time::Duration}; -use dns_rust::{domain_name::DomainName, message::{rdata::{tsig_rdata::TSigRdata, Rdata}, rrtype::Rrtype, DnsMessage},tsig::{process_tsig, sign_tsig, TsigErrorCode}}; +use dns_rust::{domain_name::DomainName, message::{rdata::{tsig_rdata::TSigRdata, Rdata}, rrtype::Rrtype, DnsMessage},tsig::{process_tsig, sign_tsig}}; use dns_rust::tsig::tsig_algorithm::TsigAlgorithm; +use dns_rust::message::rcode::Rcode; use dns_rust::message::rclass::Rclass; @@ -119,7 +120,7 @@ async fn tsig_signature() { sign_tsig(&mut data, key_found,TsigAlgorithm::from(alg_name),fudge,time, key_name, mac); let response = &DnsMessage::to_bytes(&data); //se verifica que la request haya pasado proces_tsig - assert_eq!(error,TsigErrorCode::NOERR); + assert_eq!(error,Rcode::NOERROR); // se envia la respuesta si lo anterior resultó ser correcto udp_socket @@ -166,7 +167,7 @@ async fn tsig_signature() { let (answer, error ) = process_tsig(&data, key, name.to_string(), time_signed, a_algs, mac); // se verifica que el mensaje haya pasado process_tsig assert!(answer); - assert_eq!(error,TsigErrorCode::NOERR); + assert_eq!(error,Rcode::NOERROR); } Err(e) => { eprintln!("Error receiving data: {}", e); From d61d76c4ae64c16e6dc5871d466ac87784a38c9c Mon Sep 17 00:00:00 2001 From: joalopez1206 Date: Thu, 25 Jul 2024 14:09:40 -0400 Subject: [PATCH 120/124] use case of library --- tests/use_case/example_with_bind9/Cargo.toml | 8 + tests/use_case/example_with_bind9/README.md | 27 ++++ tests/use_case/example_with_bind9/llave.key | 4 + tests/use_case/example_with_bind9/src/main.rs | 153 ++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 tests/use_case/example_with_bind9/Cargo.toml create mode 100644 tests/use_case/example_with_bind9/README.md create mode 100644 tests/use_case/example_with_bind9/llave.key create mode 100644 tests/use_case/example_with_bind9/src/main.rs diff --git a/tests/use_case/example_with_bind9/Cargo.toml b/tests/use_case/example_with_bind9/Cargo.toml new file mode 100644 index 00000000..6242bf72 --- /dev/null +++ b/tests/use_case/example_with_bind9/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ej_rust" +version = "0.1.0" +edition = "2021" + +[dependencies] +dns_rust = { path="../dns-rust"} +base64 = "0.22.1" diff --git a/tests/use_case/example_with_bind9/README.md b/tests/use_case/example_with_bind9/README.md new file mode 100644 index 00000000..d6c62284 --- /dev/null +++ b/tests/use_case/example_with_bind9/README.md @@ -0,0 +1,27 @@ +# Demo TSIG +Esta es la demo para tsig, es un proxy que retransmite los mensajes a el server, corre con dos pc's en la ip 192.168.100.(2|3)/24, idealmente usen un router y configuren las ip's de manera estatica. +- cliente es el 100.2, con los puertos 8887 y 8890 +- server es el 100.3 + +La llave que comparten esta en el archivo llave.key + +## recv_dig +Aqui la demo funciona como un proxy, recive un mensaje del dig, lo procesa y despues recive el mensaje de bind9, lo procesa y lo retransmitee (util para testear si funciona el parseo y la verficacion de tsig) + +comando para correr tsig con dig, ejecutar el main y en otra terminal ejecutar + +```bash +dig -p8887 @127.0.0.1 ns1.nictest -k wena.key +``` + +Y luego correr el ejemplo + +## recv_without_dig + +Esto es la demo que se vio en la presentacion. Este genera un mensaje preguntando por ns1.nictest (dominio configurado en bind9) y luego usa las funciones sign y process para verificar el tsig, lo envia, y verifica la respuesta del servidor + +Aqui es solo correr el ejemplo + +```bash +cargo run +``` diff --git a/tests/use_case/example_with_bind9/llave.key b/tests/use_case/example_with_bind9/llave.key new file mode 100644 index 00000000..054672bd --- /dev/null +++ b/tests/use_case/example_with_bind9/llave.key @@ -0,0 +1,4 @@ +key "WEIRD.NICTEST" { + algorithm hmac-sha1; + secret "7niAlAtSA70XRNgvlAB5m80ywDA="; +}; diff --git a/tests/use_case/example_with_bind9/src/main.rs b/tests/use_case/example_with_bind9/src/main.rs new file mode 100644 index 00000000..442bebd9 --- /dev/null +++ b/tests/use_case/example_with_bind9/src/main.rs @@ -0,0 +1,153 @@ +use std::net::UdpSocket; +use std::time::SystemTime; +use std::vec; +use dns_rust::domain_name::DomainName; +use dns_rust::message::rdata::Rdata; +use dns_rust::message::DnsMessage; +use dns_rust::message::{rrtype::Rrtype, rclass::Rclass}; +use dns_rust; +use base64; +use base64::Engine as _; +use dns_rust::tsig::{process_tsig, sign_tsig, TsigAlgorithm}; +use std::io::{stdin, stdout, Write}; +use std::{thread, time}; + + + +pub fn input(prompt: &str) -> String { + print!("{}", prompt); + let mut input = String::new(); + + stdout().flush().expect("Failed to flush stdout!"); + stdin().read_line(&mut input).expect("Failed to read line"); + + input.pop(); + + return input; +} +const KEY: &[u8; 28] = b"7niAlAtSA70XRNgvlAB5m80ywDA="; +//const KEY: &[u8; 28] = b"8niAlAtSA70XRNgvlAB5m80ywDA="; + +fn generate_tsig_a_query(domain :DomainName, id: u16, key_name: String, key: &[u8]) -> (DnsMessage, Vec) { + let mut dnsmsg = DnsMessage::new_query_message(domain, Rrtype::A, Rclass::IN, 0, true, id); + let mut header = dnsmsg.get_header(); + header.set_ad(true); + dnsmsg.set_header(header); + let alg_name = TsigAlgorithm::HmacSha1; + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let digest = sign_tsig(&mut dnsmsg, key, alg_name, 300, time, key_name, vec![]); + return (dnsmsg, digest); +} + + +fn recv_without_dig(){ + let three_secs = time::Duration::from_secs(4); + + let key_bytes = base64::prelude::BASE64_STANDARD.decode(KEY).unwrap(); + let mut lista_alg = vec![]; + lista_alg.push((String::from("hmac-sha1"),true)); + let domain_to_query = DomainName::new_from_str("ns1.nictest"); + let shared_key_name = "weird.nictest".to_string(); + let socket_udp = UdpSocket::bind("192.168.100.2:8890").expect("Failed to bind to address"); + println!("----------------------------------------------------------------"); + input("Generemos un mensaje con TSIG, presione enter para continuar\n"); + let (dns_msg, mac) = generate_tsig_a_query(domain_to_query, 6502, shared_key_name.clone(), &key_bytes); + + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let (val, err) = process_tsig(&dns_msg, &key_bytes, shared_key_name.clone(), time, lista_alg.clone(), vec![]); + println!("{}", &dns_msg); + if !val { + println!("Error en la validacion del mensaje"); + println!("{:?}", err); + panic!("Error en la validacion del mensaje"); + } + input("Presione enter para validar la consulta del cliente con tsig"); + println!("Validacion de la peticion OK! tsig_err {:?}", err); + println!("----------------------------------------------------------------"); + input("Presione enter para enviar el mensaje al servidor"); + println!("Enviando el mensaje al servidor..."); + thread::sleep(three_secs); + let test_bytes = dns_msg.to_bytes(); + socket_udp.send_to(&test_bytes, "192.168.100.3:53").unwrap(); + + let mut buf = [0; 2000]; + let (s, _) = socket_udp.recv_from(& mut buf).unwrap(); + println!("Recibiendo respuesta del servidor\n"); + let bytes = &buf[0..s].to_vec(); + let response = DnsMessage::from_bytes(&bytes).expect("Parseo mal!"); + println!("{}\n", &response); + input("Presione enter para validar la respuesta del servidor"); + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let (val, err) = process_tsig(&response, &key_bytes, shared_key_name.clone(), time, lista_alg, mac); + + + if !val { + println!("Error en la validacion del mensaje"); + println!("tsig_error_code: {:?}", err); + } + println!("----------------------------------------------------------------"); +} + +fn recv_dig() { + let key_bytes = base64::prelude::BASE64_STANDARD.decode(KEY).unwrap(); + let mut lista_alg = vec![]; + lista_alg.push((String::from("hmac-sha1"),true)); + + let socket_udp = UdpSocket::bind("127.0.0.1:8887").expect("Failed to bind to address"); + let socket_udp2 = UdpSocket::bind("192.168.100.2:8890").expect("Failed to bind to address"); + let mut buf = [0;1000]; + let (s, addr_in) = socket_udp.recv_from(&mut buf).unwrap(); + //println!("Llego un mensaje de largo {s}"); + let bytes = &buf[0..s].to_vec(); + let dnsmsg = DnsMessage::from_bytes(bytes).expect("Parseo mal!"); + + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let mac = vec![]; + let (a, b)= process_tsig(&dnsmsg, &key_bytes, "weird.nictest".to_string(), time, lista_alg.clone(), mac); + + println!("Verificando la query del cliente!"); + println!("bool: {:?} tsig_err: {:#?}", a, b); + println!("{:#?}",&dnsmsg); + println!("-----------------------------------------------------"); + + // println!("{:#?}", dnsmsg.get_header()); + let rrs = dnsmsg.get_additional().pop().unwrap(); + let tsig = match rrs.get_rdata() { + Rdata::TSIG(xd) => { + xd + }, + _ => panic!("xd") + }; + + + let mac = tsig.get_mac(); + let test_bytes = dnsmsg.to_bytes(); + + socket_udp2.send_to(&test_bytes, "192.168.100.3:53").unwrap(); + + let mut buf2 = [0; 2000]; + let (s2, _) = socket_udp2.recv_from(& mut buf2).unwrap(); + let bytes2 = &buf2[0..s2].to_vec(); + let dnsmsg2 = DnsMessage::from_bytes(&bytes2[0..s2]).expect("Parseo mal!"); + + // let mut response_dns_tsig_file = File::create("response_tsig_cliente.dns").unwrap(); + // response_dns_tsig_file.write_all(bytes2).expect("Error al escribir el archivo"); + + let parsed_bytes = dnsmsg2.to_bytes(); + + socket_udp.send_to(&parsed_bytes, addr_in).unwrap(); + //process_tsig(&dnsmsg2, key, key_name, time, available_algorithm, mac_to_process) + + + //panic!(); + //let bytes = general_purpose::STANDARD.decode(key).unwrap(); + let time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let (a, b)= process_tsig(&dnsmsg2, &key_bytes, "weird.nictest".to_string(), time, lista_alg, mac); + println!("Verificando la respuesta del servidor"); + println!("bool: {:?} tsig_err: {:#?}", a, b); +} + +fn main() { + //recv_dig(); + recv_without_dig() +} \ No newline at end of file From 7c9e0bd91a9a6c5cd09c841362ea43bead23ae9e Mon Sep 17 00:00:00 2001 From: Litr0 Date: Tue, 6 Aug 2024 14:20:58 -0400 Subject: [PATCH 121/124] add add_tsig to resolver --- src/async_resolver/config.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/async_resolver/config.rs b/src/async_resolver/config.rs index 19c32359..7fd739be 100644 --- a/src/async_resolver/config.rs +++ b/src/async_resolver/config.rs @@ -1,6 +1,7 @@ use crate::client::{udp_connection::ClientUDPConnection, tcp_connection::ClientTCPConnection,client_connection::ClientConnection }; use crate::client::client_connection::ConnectionProtocol; use crate::message::DnsMessage; +use crate::tsig::tsig_algorithm::TsigAlgorithm; use std::cmp::max; use std::option; use std::{net::{IpAddr,SocketAddr,Ipv4Addr}, time::Duration}; @@ -73,6 +74,14 @@ pub struct ResolverConfig { ends0_flags: u16, /// edns0 options for the resolver. ends0_options: Vec, + /// This is whether tsig is enabled or not. + tsig: bool, + /// This is the tsig keyname for the resolver. + key_name: Option, + /// This is the tsig key for the resolver. + key: Vec, + /// algorithm for the tsig key + algorithm: TsigAlgorithm, } impl ResolverConfig { @@ -113,6 +122,10 @@ impl ResolverConfig { ends0_version: 0, ends0_flags: 0, ends0_options: Vec::new(), + tsig: false, + key_name: None, + key: Vec::new(), + algorithm: TsigAlgorithm::HmacSha256, }; resolver_config } @@ -154,6 +167,10 @@ impl ResolverConfig { ends0_version: 0, ends0_flags: 0, ends0_options: Vec::new(), + tsig: false, + key_name: None, + key: Vec::new(), + algorithm: TsigAlgorithm::HmacSha256, }; resolver_config } @@ -245,6 +262,22 @@ impl ResolverConfig { message.add_edns0(Some(self.get_max_payload()), self.get_ends0_version(), self.get_ends0_flags(), Some(self.get_ends0_options())); } } + + /// add tsig to the resolver + /// + /// # Examples + /// ``` + /// let mut resolver_config = ResolverConfig::default(); + /// resolver_config.add_tsig("keyname".to_string(), b"key".to_vec(), Some(TsigAlgorithm::HmacSha256)); + /// ``` + pub fn add_tsig(&mut self, key_name: String, key: Vec, algorithm: Option) { + self.tsig = true; + self.key_name = Some(key_name); + self.key = key; + if let Some(algorithm) = algorithm { + self.algorithm = algorithm; + } + } } ///Getters From 1096f875476472e054a91cbcd6b8e6b9dab4d648 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Tue, 6 Aug 2024 16:30:30 -0400 Subject: [PATCH 122/124] 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"); From aa80f21c608c567afd99924dd2533ac27223992a Mon Sep 17 00:00:00 2001 From: Litr0 Date: Tue, 6 Aug 2024 16:40:06 -0400 Subject: [PATCH 123/124] add tsig rr form resolver to dns message --- src/async_resolver/config.rs | 16 ++++++++++++++++ src/message.rs | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/async_resolver/config.rs b/src/async_resolver/config.rs index 7fd739be..d4f20c21 100644 --- a/src/async_resolver/config.rs +++ b/src/async_resolver/config.rs @@ -3,6 +3,7 @@ use crate::client::client_connection::ConnectionProtocol; use crate::message::DnsMessage; use crate::tsig::tsig_algorithm::TsigAlgorithm; use std::cmp::max; +use std::io::SeekFrom; use std::option; use std::{net::{IpAddr,SocketAddr,Ipv4Addr}, time::Duration}; @@ -278,6 +279,21 @@ impl ResolverConfig { self.algorithm = algorithm; } } + + /// add tsig from the resolver to a dns message + /// + /// # Examples + /// ``` + /// let mut resolver_config = ResolverConfig::default(); + /// resolver_config.add_tsig("keyname".to_string(), b"key".to_vec(), Some(TsigAlgorithm::HmacSha256)); + /// let message = Message::new(); + /// resolver_config.add_tsig_to_message(&message, 300, vec![]); + /// ``` + pub fn add_tsig_to_message(&self, message: &mut DnsMessage, fudge: u16, mac_request: Vec) { + if self.tsig { + message.add_tsig(self.key.clone(), self.algorithm.clone(), fudge, self.key_name.clone(), mac_request); + } + } } ///Getters diff --git a/src/message.rs b/src/message.rs index 85e91690..baf2874b 100644 --- a/src/message.rs +++ b/src/message.rs @@ -302,11 +302,11 @@ impl DnsMessage { /// 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) { + fudge: u16, key_name: Option, 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); + fudge, time_signed, key_name.unwrap_or("".to_string()), mac_request); } /// Gets the MAC from the TSIG RR. From 25d579bf307d548bd401ade98f1650aeac4dbc44 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Tue, 6 Aug 2024 16:42:28 -0400 Subject: [PATCH 124/124] Delete unused variables --- src/async_resolver.rs | 1 - src/async_resolver/config.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/async_resolver.rs b/src/async_resolver.rs index 8495155f..acec5293 100644 --- a/src/async_resolver.rs +++ b/src/async_resolver.rs @@ -2036,7 +2036,6 @@ mod async_resolver_test { resolver.save_negative_answers(dns_response.clone()); - let rrtype_search = Rrtype::A; assert_eq!(dns_response.get_answer().len(), 0); assert_eq!(dns_response.get_additional().len(), 1); assert_eq!( diff --git a/src/async_resolver/config.rs b/src/async_resolver/config.rs index d4f20c21..6dede8a8 100644 --- a/src/async_resolver/config.rs +++ b/src/async_resolver/config.rs @@ -3,8 +3,6 @@ use crate::client::client_connection::ConnectionProtocol; use crate::message::DnsMessage; use crate::tsig::tsig_algorithm::TsigAlgorithm; use std::cmp::max; -use std::io::SeekFrom; -use std::option; use std::{net::{IpAddr,SocketAddr,Ipv4Addr}, time::Duration}; use super::server_info::ServerInfo;