#!/usr/bin/env python
import json
import os
import colorama
from termcolor import colored

'''
Quick script to format the result of a batch scan of TestSSL:
    bash testssl.sh --file commands.txt
    python generate-report-testssl.py

Where "commands.txt" contains:
-s -p -U --quiet -oJ host1.json host1:443
-s -p -U --quiet -oJ host2.json host2:443

TestSSL scan results must be in JSON format using the "-oJ" parameter.

The script process all TestSSL JSON reports found in the current execution folder.

Dependencies:
    pip install colorama termcolor
'''
INFORMATIONAL_SEVERITY = ["OK", "INFO"]
SEVERITY_COLOR_MAPPING = {"CRITICAL": "red", "HIGH": "red", "MEDIUM": "yellow", "LOW": "cyan"}


def get_color(severity):
    sev = severity.upper()
    severity_color = "white"
    if sev in SEVERITY_COLOR_MAPPING:
        severity_color = SEVERITY_COLOR_MAPPING[sev]
    return severity_color


def process_host(json_file):
    findings = []
    buffer = []
    lines = []
    with open(json_file, mode="r", encoding="utf-8") as f:
        content = f.read()
    if "testssl.sh" in content and "scanResult" in content:
        json_data = json.loads(content)
        scan_results = json_data["scanResult"]
        for scan_result in scan_results:
            findings.clear()
            buffer.clear()
            for protocol in scan_result["protocols"]:
                if protocol["severity"].upper() not in INFORMATIONAL_SEVERITY:
                    severity_color = get_color(protocol["severity"])
                    id = colored(protocol["id"], severity_color)
                    desc = protocol["finding"]
                    findings.append(f"{id:<30} => {desc}")
            if len(findings) > 0:
                buffer.append("[*] Deprecated protocols identified:")
                buffer.append("\n".join(findings))
            findings.clear()
            for vulnerability in scan_result["vulnerabilities"]:
                if vulnerability["severity"].upper() not in INFORMATIONAL_SEVERITY:
                    severity_color = get_color(vulnerability["severity"])
                    id = colored(vulnerability["id"], severity_color)
                    desc = vulnerability["finding"]
                    cve = ""
                    if "cve" in vulnerability:
                        cve = "(" + vulnerability["cve"] + ")"
                    findings.append(f"{id:<30} => {desc} {cve}")
            if len(findings) > 0:
                buffer.append("[*] Vulnerabilities identified:")
                buffer.append("\n".join(findings))
            if len(buffer) > 0:
                host = scan_result["targetHost"] + ":" + scan_result["port"] + " (rDNS: " + scan_result["rDNS"] + ")"
                lines.append(colored(f"[+] Host {host}", "green"))
                lines.extend(buffer)
                lines.append("")
    if len(lines) > 0:
        print("\n".join(lines))


colorama.init()
json_files = [f for f in os.listdir() if os.path.isfile(f) and f.endswith(".json")]
if len(json_files) == 0:
    print(colored("[!] No TestSSL JSON scan report found in the current folder!", "red"))
else:
    for json_file in json_files:
        process_host(json_file)
