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(&registrant.name);
ret_vec.push(name);
let mut org = registrant_type.clone();
org.push_str("Organisation: ");
org.push_str(&registrant.org);
ret_vec.push(org);
let mut email = registrant_type.clone();
email.push_str("Email: ");
email.push_str(&registrant.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
}
}