218 lines
6.6 KiB
Rust
218 lines
6.6 KiB
Rust
use core::fmt;
|
|
use hickory_resolver::proto::{
|
|
rr::{domain, rdata::name},
|
|
xfer::dns_handle,
|
|
};
|
|
use regex::Regex;
|
|
use whois_rust::{WhoIs, WhoIsLookupOptions};
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum RegistrantType {
|
|
Registrant,
|
|
Admin,
|
|
Tech,
|
|
Billing,
|
|
}
|
|
|
|
struct RegexQuery {
|
|
re: Regex,
|
|
}
|
|
|
|
impl RegexQuery {
|
|
fn new(expression: String) -> RegexQuery {
|
|
let re = Regex::new(&expression).unwrap();
|
|
RegexQuery { re }
|
|
}
|
|
|
|
fn get_matches(&self, haystack: &str) -> Vec<String> {
|
|
let mut results = vec![];
|
|
for (_, [_, rex2]) in self.re.captures_iter(haystack).map(|c| c.extract()) {
|
|
results.push(String::from(rex2.trim()));
|
|
}
|
|
results
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct NameServer {
|
|
host: String,
|
|
}
|
|
|
|
impl NameServer {
|
|
fn new(host: String) -> NameServer {
|
|
NameServer { host }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct Registrant {
|
|
name: String,
|
|
org: String,
|
|
email: String,
|
|
rtype: RegistrantType,
|
|
}
|
|
|
|
impl fmt::Display for Registrant {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "")
|
|
}
|
|
}
|
|
|
|
impl Registrant {
|
|
fn new(name: String, org: String, email: String, rtype: RegistrantType) -> Registrant {
|
|
Registrant {
|
|
name,
|
|
org,
|
|
email,
|
|
rtype,
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Eligibility {
|
|
e_type: String,
|
|
id: String,
|
|
name: String,
|
|
}
|
|
|
|
pub struct WhoisData {
|
|
registrar: Option<String>,
|
|
domain_status: Option<String>,
|
|
registrant: Option<Vec<Registrant>>,
|
|
nameservers: Option<Vec<NameServer>>,
|
|
dnssec: Option<String>,
|
|
eligibility_type: Option<Eligibility>,
|
|
}
|
|
|
|
impl fmt::Display for WhoisData {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"Registrar: {}\nStatus: {}\nRegistrant: {:?}\nNameservers: {:?}\nDNSSEC: {}",
|
|
self.registrar.clone().unwrap(),
|
|
self.domain_status.clone().unwrap(),
|
|
self.registrant.clone().unwrap(),
|
|
self.nameservers.clone().unwrap(),
|
|
self.dnssec.clone().unwrap()
|
|
)
|
|
}
|
|
}
|
|
|
|
impl WhoisData {
|
|
pub fn new(domain: String) -> WhoisData {
|
|
let whois = WhoIs::from_path("servers.json").unwrap();
|
|
let result: String = whois
|
|
.lookup(WhoIsLookupOptions::from_string(domain).unwrap())
|
|
.unwrap();
|
|
let registrar_regex =
|
|
RegexQuery::new(String::from(r"(?i)(.*registrar:|registrar *name:)(.*)"));
|
|
let domain_status_regex =
|
|
RegexQuery::new(String::from(r"(?i)(.*domain status:|.*status:)(.*)"));
|
|
// TODO: Capture the registrant info for each type
|
|
let registrant_name_regex = RegexQuery::new(String::from(r"(?i)(registrant.*name:)(.*)"));
|
|
let registrant_org_regex =
|
|
RegexQuery::new(String::from(r"(?i)(registrant org.*:|registrant:)(.*)"));
|
|
let registrant_email_regex = RegexQuery::new(String::from(r"(?i)(registrant email:)(.*)"));
|
|
let nameserver_regex =
|
|
RegexQuery::new(String::from(r"(?i)(nameservers*:|name servers*:)(.*)"));
|
|
let dnssec_regex = RegexQuery::new(String::from(r"(?i)(.*dnssec:)(.*)"));
|
|
|
|
let registrar = WhoisData::return_regex(registrar_regex.get_matches(&result), 0);
|
|
let domain_status = WhoisData::return_regex(domain_status_regex.get_matches(&result), 0);
|
|
let reg_name = WhoisData::return_regex(registrant_name_regex.get_matches(&result), 0);
|
|
let reg_org = WhoisData::return_regex(registrant_org_regex.get_matches(&result), 0);
|
|
let reg_email = WhoisData::return_regex(registrant_email_regex.get_matches(&result), 0);
|
|
|
|
let mut nameservers = vec![];
|
|
for nameserver in nameserver_regex.get_matches(&result) {
|
|
nameservers.push(NameServer::new(nameserver));
|
|
}
|
|
let mut dnssec = dnssec_regex.get_matches(&result);
|
|
if dnssec.len() == 0 {
|
|
dnssec = vec![String::from("Failed to get DNSSEC")];
|
|
}
|
|
// println!("{:?}", registrar[0]);
|
|
WhoisData {
|
|
registrar: Some(registrar.clone()),
|
|
domain_status: Some(domain_status.clone()),
|
|
registrant: Some(vec![Registrant::new(
|
|
reg_name.clone(),
|
|
reg_org.clone(),
|
|
reg_email,
|
|
RegistrantType::Registrant,
|
|
)]),
|
|
nameservers: Some(nameservers),
|
|
dnssec: Some(dnssec[0].clone()),
|
|
eligibility_type: None,
|
|
}
|
|
}
|
|
|
|
pub fn to_vec(&self) -> Vec<String> {
|
|
let mut ret_vec: Vec<String> = vec![];
|
|
let mut registrar = String::from("Registrar: ");
|
|
registrar.push_str(&self.registrar.clone().unwrap());
|
|
ret_vec.push(registrar);
|
|
|
|
let mut domain_status = String::from("Status: ");
|
|
domain_status.push_str(&self.domain_status.clone().unwrap());
|
|
ret_vec.push(domain_status);
|
|
|
|
let mut dnssec = String::from("DNSSEC: ");
|
|
dnssec.push_str(&self.dnssec.clone().unwrap());
|
|
ret_vec.push(dnssec);
|
|
|
|
let mut registrant_type = String::new();
|
|
for registrant in &self.registrant.clone().unwrap() {
|
|
match registrant.rtype {
|
|
RegistrantType::Admin => {
|
|
registrant_type.push_str("Admin ");
|
|
}
|
|
RegistrantType::Billing => {
|
|
registrant_type.push_str("Billing ");
|
|
}
|
|
RegistrantType::Tech => {
|
|
registrant_type.push_str("Tech ");
|
|
}
|
|
RegistrantType::Registrant => {
|
|
registrant_type.push_str("Registrant ");
|
|
}
|
|
}
|
|
let mut name = registrant_type.clone();
|
|
name.push_str("Name: ");
|
|
name.push_str(®istrant.name);
|
|
ret_vec.push(name);
|
|
|
|
let mut org = registrant_type.clone();
|
|
org.push_str("Organisation: ");
|
|
org.push_str(®istrant.org);
|
|
ret_vec.push(org);
|
|
|
|
let mut email = registrant_type.clone();
|
|
email.push_str("Email: ");
|
|
email.push_str(®istrant.email);
|
|
ret_vec.push(email);
|
|
}
|
|
|
|
for nameserver in &self.nameservers.clone().unwrap() {
|
|
let mut tmp = String::from("Nameserver: ");
|
|
tmp.push_str(&nameserver.host);
|
|
ret_vec.push(tmp);
|
|
}
|
|
|
|
return ret_vec;
|
|
}
|
|
|
|
fn return_regex(caps: Vec<String>, index: usize) -> String {
|
|
let data: String;
|
|
match caps.get(index) {
|
|
Some(tmp) => {
|
|
data = tmp.to_string();
|
|
}
|
|
None => {
|
|
data = String::from("None");
|
|
}
|
|
}
|
|
data
|
|
}
|
|
}
|