diff --git a/cli_lookup.py b/cli_lookup.py new file mode 100644 index 0000000..54f47d4 --- /dev/null +++ b/cli_lookup.py @@ -0,0 +1,11 @@ +from src.lookup import lookup +from src.type_hosts import type_hosts +from src.user_input import user_input +from src.display import display + + +if __name__ == "__main__": + hosts = user_input() + validated_hosts = type_hosts(hosts) + lookedup_hosts = lookup(validated_hosts) + display(lookedup_hosts) diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/display.py b/src/display.py new file mode 100644 index 0000000..c89cd50 --- /dev/null +++ b/src/display.py @@ -0,0 +1,25 @@ +from rich.console import Console +from rich.table import Table, errors + +def display(lookup_results): + table = Table(title="results", highlight=True, show_lines=True, row_styles=["dim", ""]) + # Remember: the dimension/column is not the host type, but the lookup result! So a whois, a DMARC, an SPF, etc. Because for one host, there are multiple lookup results (I guess???) + table.add_column('host') + table.add_column('domain registered') + table.add_column('registrar') + table.add_column('dnssec') + table.add_column('spf') + table.add_column('dmarc') + + for lookedup in lookup_results: + try: + table.add_row(str(lookedup.host), str(lookedup.whois['creation_date']), str(lookedup.whois['registrar']), str(lookedup.whois['dnssec']), lookedup.spf, lookedup.dmarc) + except errors.NotRenderableError as error: + print(error.args, lookup_results, lookedup) + table.add_section() + table.add_row("", "", "", "", "*** -all = hard fail ***", "*** p=reject (drop email)***", style="green") + table.add_row("", "", "", "", "*** ~all = hard fail ***", "*** p=quarantine (email in spam)***", style="green") + table.add_row("", "", "", "", "*** all = allow all ***", "*** p=none (ignore email)***", style="green") + + console = Console() + console.print(table) diff --git a/src/lookup.py b/src/lookup.py new file mode 100644 index 0000000..3ae8361 --- /dev/null +++ b/src/lookup.py @@ -0,0 +1,108 @@ +from whois import whois +from checkdmarc.spf import get_spf_record, SPFRecordNotFound +from checkdmarc.dmarc import get_dmarc_record, DMARCRecordNotFound +import time +import tldextract +from tqdm import tqdm +import progressbar + + +def progress_bar(): + widgets = ["TESTING A PROGRESS BAR", progressbar.Bar()] + bar = progressbar.ProgressBar(widgets=widgets).start() + return bar + + +class Lookup(object): + def __init__(self, host): + self.host = host + self.whois = dict(whois(host)) + self.dmarc = None + self.spf = None + + +def lookup(validated_hosts): + bar = progress_bar() + lookups = [] + for key, value in validated_hosts.items(): + if key == "domains": + print("[Looking up domains...]") + if any(value): + for host in tqdm(value): + lookedup = Lookup(host) + try: + lookedup.dmarc = dict(get_dmarc_record(host))["record"] + except DMARCRecordNotFound as error: + print("DMARC exception. Should start using raise :)") + lookedup.dmarc = error.args[0] + try: + lookedup.spf = dict(get_spf_record(host))["record"] + except SPFRecordNotFound as error: + print( + "SPF exception. Should start using raise :)", + error.args, + type(error.args), + error.args[0], + ) + # this 'works', as in, error.args returns some valuable detail (DNS timeout) and the host to look up. + lookedup.spf = error.args[0] + lookups.append(lookedup) + time.sleep(1) + # bar.update() + elif key == "email": + print("[Looking up email addresses...]") + if any(value): + for host in tqdm(value): + domain = str.split(host, "@")[-1] + lookedup = Lookup(domain) + try: + lookedup.dmarc = dict(get_dmarc_record(domain))["record"] + except DMARCRecordNotFound as error: + print("DMARC exception. Should start using raise :)") + try: + lookedup.spf = dict(get_spf_record(domain))["record"] + except SPFRecordNotFound as error: + print("SPF exception. Should start using raise :)", + error.args, + type(error.args), + error.args[0], + ) + lookups.append(lookedup) + time.sleep(1) + elif key == "URL": + print("[Looking up URLs...]") + if any(value): + for host in tqdm(value): + domain = tldextract.extract(host).domain + lookedup = Lookup(domain) + lookedup.dmarc = dict(get_dmarc_record(domain))["record"] + lookedup.spf = dict(get_spf_record(domain))["record"] + lookups.append(lookedup) + # TODO add VirusTotal-lookup and return score? + time.sleep(1) + elif key == "hostname": + print("Looking up hostnames...]") + if any(value): + for host in tqdm(value): + pass + elif key == "IP": + print("Looking up IPs...]") + if any(value): + for host in tqdm(value): + lookedup = Lookup(host) + lookups.append(lookup) + time.sleep(1) + + else: + print("No hosts to look up in ", key) + bar.update() + + return lookups + + +def lookup_spf(validated_hosts): + pass + + +def lookup_dmarc(validated_hosts): + pass diff --git a/src/type_hosts.py b/src/type_hosts.py new file mode 100644 index 0000000..cb04fb9 --- /dev/null +++ b/src/type_hosts.py @@ -0,0 +1,43 @@ +import validators + +def normalize(host): + domain_name, tld = "", "" + if host.startswith('www.'): + domain_name, tld = str.split(host,'.')[-2:] + normalized_domain = domain_name + '.' + tld + return normalized_domain + else: + return host + +def type_hosts(hosts): + validated_hosts = { + "URLs": [], + "domains": [], + "IPs": [], + "email": [], + "hostnames": [], + } + URLs = [] + domains = [] + IPs = [] + email = [] + hostnames = [] + for host in hosts: + if validators.url(host): + URLs.append(host) + elif validators.domain(host): + domains.append(normalize(host)) + elif validators.ipv4(host) or validators.ipv6(host): + IPs.append(host) + elif validators.email(host): + email.append(host) + elif validators.hostname(host): + hostnames.append(host) + else: + print("This is not a URL, IP, email address or hostname: ", host) + validated_hosts["URLs"].extend([i for i in URLs]) + validated_hosts["domains"].extend([i for i in domains]) + validated_hosts["IPs"].extend([i for i in IPs]) + validated_hosts["email"].extend([i for i in email]) + validated_hosts["hostnames"].extend([i for i in hostnames]) + return validated_hosts diff --git a/src/user_input.py b/src/user_input.py new file mode 100644 index 0000000..2be037a --- /dev/null +++ b/src/user_input.py @@ -0,0 +1,12 @@ +import re + +def user_input(): + while True: + hosts = str(input("Type in or copy-paste " + "one or more IP addresses, domain names " + "URLs or email addresses: " + )) + if hosts.strip() != '': + sanitized = re.split("; |, | ", hosts) + return sanitized + # break