Recently, as I work my way through learning bits of rust, I have been thinking that I should in corporate some form of input validation for domains.
Today I will look at two crates.
Initially I thought I would make validation part of the decon-spf crate. Though I think I would prefer to keep the crate simple and clean. To this end I have decided that validation is not the role of the crate itself. The reality is this crate is an experiment and is intended to parse and deconstruct existing SPF records.
Crates
publicsuffix
I am using version 1.5.4 which can be found on crates.io.
Example
use publicsuffix::List;
fn main() {
let list = List::fetch().unwrap();
let case1 = "_i-am-not-so-very-long.example.com";
let items = case1.split(".");
println!("Case1:");
for i in items.into_iter() {
println!("label Name: {}", i);
println!("label Len : {}", i.len());
}
let domain = list.parse_dns_name(case1);
match domain {
Err(_) => println!("Invalid Domain"),
Ok(result) => {
println!("test: {}", result);
}
}
let case2 = "_i-am-a-very-long-long-string-of-text-that-should-not-be-allowed.example.com";
let items = case2.split(".");
println!("Case2:");
for i in items.into_iter() {
println!("label Name: {}", i);
println!("label Len : {}", i.len());
}
let domain = list.parse_dns_name(case2);
match domain {
Err(_) => println!("Invalid Domain"),
Ok(result) => {
println!("test: {}", result);
}
}
}
Output
Case1:
label Name: _i-am-not-so-very-long
label Len : 22
label Name: example
label Len : 7
label Name: com
label Len : 3
test: _i-am-not-so-very-long.example.com
Case2:
label Name: _i-am-a-very-long-long-string-of-text-that-should-not-be-allowed
label Len : 64
label Name: example
label Len : 7
label Name: com
label Len : 3
Invalid Domain
addr
I am using version 0.14.0 which can be found on crates.io.
Please also note that I am using parse_dns_name
and not parse_domain_name
. The difference being parse_domain_name
does not allow for addictional characters per RFC1034 which covers host and domain records. There is more flexibity allowed when specifying resource type records. See StackOverFlow.
Example
use addr::parser::DnsName;
use addr::psl::List;
fn main() {
let domain1 = List.parse_dns_name("_spf.example.com").unwrap();
println!("Domain1 Valid: {}", domain1);
let domain2 = "_i-am-a-very-long-long-string-of-text-that-should-not-be-allowed.example.com";
let validity = List.parse_dns_name(domain2);
match validity {
Err(_) => {
let mut c = 1;
println!("Invalid Domain");
let labels = domain2.split(".").into_iter();
for label in labels {
if label.len() > 63 {
println!("Label exceeds max length of 63!");
}
println!("label{}: len {} Str {}", c, label.len(), label);
c += 1;
}
}
Ok(domain) => println!("valid Domain: {}", domain),
}
}
Output
Domain1 Valid: _spf.example.com
Invalid Domain
Label exceeds max length of 63!
label1: len 64 Str _i-am-a-very-long-long-string-of-text-that-should-not-be-allowed
label2: len 7 Str example
label3: len 3 Str com
Closing
I hope this information is useful.