From 4c77ba8dc635903adb90e5b4cec787839fe64007 Mon Sep 17 00:00:00 2001 From: Dobore Date: Wed, 24 Apr 2024 13:13:23 -0400 Subject: [PATCH 01/93] 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 02/93] 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 03/93] 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 04/93] 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 05/93] 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 06/93] 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 07/93] 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 08/93] =?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 09/93] 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 10/93] 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 11/93] 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 12/93] =?UTF-8?q?Terminado=20check=5Falg=5Fname,=20y=20agr?= =?UTF-8?q?egamos=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 13/93] 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 14/93] 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 15/93] 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 16/93] 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 17/93] 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 18/93] 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 19/93] 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 20/93] 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 21/93] 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 22/93] 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 23/93] 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 24/93] 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 25/93] 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 26/93] 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 27/93] 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 28/93] 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 29/93] 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 30/93] 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 31/93] 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 32/93] 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 33/93] 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 34/93] 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 35/93] 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 36/93] 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 37/93] 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 38/93] 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 39/93] 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 40/93] 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 41/93] 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 42/93] 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 43/93] 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 44/93] 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 45/93] 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 46/93] 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 47/93] 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 48/93] 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 49/93] 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 50/93] 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 51/93] 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 52/93] 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 53/93] 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 54/93] 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 55/93] 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 56/93] 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 57/93] 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 58/93] 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 59/93] 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 60/93] 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 61/93] 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 62/93] 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 63/93] 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 64/93] 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 65/93] 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 66/93] 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 67/93] 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 68/93] 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 69/93] 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 70/93] 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 71/93] 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 72/93] 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 73/93] 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 74/93] 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 75/93] 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 76/93] 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 77/93] 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 78/93] 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 79/93] 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 80/93] 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 81/93] 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 82/93] 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 83/93] 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 84/93] 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 85/93] 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 86/93] 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 87/93] 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 88/93] 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 89/93] 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 90/93] 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 91/93] 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 92/93] 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 93/93] 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")),