#!/usr/bin/python3
#   Filename: hosthunter.py
#   Module: HostHunter
#   Author: Andreas Georgiou (@superhedgy)

import socket
# Standard Libraries
import ssl

# External Libraries
import OpenSSL
import dns.resolver
import requests
import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_OPTIONAL
context.load_default_certs()


# ssl_grabber Function
def ssl_grabber(resolved_ip, port):
    try:
        cert = ssl.get_server_certificate((resolved_ip.address, port))
        x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
        cert_hostname = x509.get_subject().CN

        # Add New HostNames to List
        for host in cert_hostname.split('\n'):
            # print(host)
            if (host == "") or (host in resolved_ip.hostname):
                pass
            else:
                try:
                    resolved_ip.hostname.append(host)
                except:
                    pass
    except (urllib3.exceptions.ReadTimeoutError, requests.ConnectionError, urllib3.connection.ConnectionError,
            urllib3.exceptions.MaxRetryError, urllib3.exceptions.ConnectTimeoutError, urllib3.exceptions.TimeoutError,
            socket.error, socket.timeout) as e:
        pass


# r_dns Function
def r_dns(targetIP):
    try:
        hostname = socket.gethostbyaddr(targetIP.address)
        if hostname[0] is not "":
            targetIP.hostname.append(hostname[0])
        # print("[Debug] r_dns result " + hostname[0]) ## Debug Statement
    except:
        pass


# query_api Function
def query_api(hostx):
    try:
        url = "https://api.hackertarget.com/reverseiplookup/?q="
        r2 = requests.get(url + hostx.resolved_ips[0].address, verify=False).text
        if (r2.find("No DNS A records found") == -1) and (
                r2.find("API count exceeded") == -1 and r2.find("error") == -1):
            for host in r2.split('\n'):
                if (host == "") or (host in hostx.hname):
                    pass
                else:
                    hostx.hname.append(host)
        # Add API count exceed detection
        else:
            pass
    except (
    requests.exceptions.ConnectionError, urllib3.connection.ConnectionError, urllib3.exceptions.ConnectTimeoutError,
    urllib3.exceptions.MaxRetryError, urllib3.exceptions.TimeoutError, socket.error, socket.timeout):
        print("error", "query_api failed, connecting with HackerTarget.com API", 1)


def org_finder(hostx):
    target = hostx.primary_domain

    try:
        cert = ssl.get_server_certificate((target, 443))
        x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
        orgName = x509.get_subject().organizationName
        unit = x509.get_subject().organizationalUnitName
        hostx.orgName = str(orgName)
    except:
        pass


#  dnsloopkup Function
def dnslookup(hostx):
    try:
        url = "https://api.hackertarget.com/dnslookup/?q="
        r2 = requests.get(url + hostx.primary_domain, verify=False).text
        if (r2.find("No DNS A records found") == -1) and (
                r2.find("API count exceeded") == -1 and r2.find("error") == -1):
            hostx.dnsrecords = r2.splitlines()
            # Add API count exceed detection
            for record in hostx.dnsrecords:
                word = record.rsplit('\t')
                try:
                    if (word[0] == "TXT") and ("v=spf1" in word[1]):
                        hostx.spf = True
                except:
                    pass
            if hostx.spf is None:
                hostx.spf = False
        else:
            pass
    except (
    requests.exceptions.ConnectionError, urllib3.connection.ConnectionError, urllib3.exceptions.ConnectTimeoutError,
    urllib3.exceptions.MaxRetryError, urllib3.exceptions.TimeoutError, socket.error, socket.timeout):
        print("error", " dnslookup failed, connecting with HackerTarget.com API", 1)


def dnsquery(hostx):
    try:
        response = dns.resolver.query('_dmarc' + '.' + hostx.primary_domain, 'TXT')

        for rdata in response:
            dmarc_record = str(rdata).replace(' ', '')
            if "v=DMARC" in dmarc_record:
                if ";p=reject;" in dmarc_record:
                    hostx.dmarc_status = "Primary Domain is not Spoofable. "
                elif ";p=quarantine;" in dmarc_record:
                    hostx.dmarc_status = "Primary Domain accepts spoofed emails but they will be marked as suspicious. "
                elif ";p=none;" in dmarc_record:
                    hostx.dmarc_status = "Primary Domain allows Email Spoofing. "

                if ";sp=none;" in dmarc_record:
                    hostx.dmarc_status += "Subdomains allow Email Spoofing."
                elif ";sp=reject;" in dmarc_record:
                    hostx.dmarc_status += "SubDomains are not Spoofable."
                elif ";sp=quarantine;" in dmarc_record:
                    hostx.dmarc_status += "SubDomains will accept spoofed emails but they will be marked as suspicious."
            else:
                hostx.dmarc_status = "Spoofable Email Domain."

            hostx.dmarc.append(str(rdata))
    except:
        hostx.dmarc = []

    try:
        hostx.mx = dns.resolver.query(hostx.primary_domain, 'MX')
    except:
        pass


def active(hostx, count):
    for ip in hostx.resolved_ips:
        ssl_grabber(ip, "443")  # SSL
        ssl_grabber(ip, "993")  # IMAP - SSL
        ssl_grabber(ip, "22")  # FTPs - SSL

        count.hostnames += len(ip.hostname)  # Updates Counter