#!/usr/bin/env python3
"""Connect to the roster server and VERIFY its cert by the dialed IP, then GET the roster.

Mirrors the client's failing path: dial the roster by IP over TLS and validate the
presented certificate against that IP. Exit 0 only if the cert verifies AND the roster
XML comes back 200; exit 1 on cert-verify failure (the certificate_unknown class).

argv: <cafile> <dial_ip> <port>
"""
import socket
import ssl
import sys

cafile, dial_ip, port = sys.argv[1], sys.argv[2], int(sys.argv[3])

ctx = ssl.create_default_context(cafile=cafile)  # trust the server's self-signed cert as CA
ctx.check_hostname = True
try:
    ctx.minimum_version = ssl.TLSVersion.TLSv1
except Exception:
    pass
try:
    ctx.set_ciphers("ALL:@SECLEVEL=0")
except Exception:
    pass

try:
    raw = socket.create_connection((dial_ip, port), timeout=8)
except Exception as e:
    print(f"  CONNECT-FAIL {type(e).__name__}: {e}")
    sys.exit(2)

try:
    # server_hostname is the IP the roster is dialed by; ssl matches it against the
    # cert's iPAddress SANs — exactly the check the DNS-only cert failed.
    s = ctx.wrap_socket(raw, server_hostname=dial_ip)
except ssl.SSLCertVerificationError as e:
    print(f"  VERIFY-FAIL {e.verify_message or e}")
    sys.exit(1)
except Exception as e:
    print(f"  TLS-FAIL {type(e).__name__}: {e}")
    sys.exit(1)

try:
    ver, cipher = s.version(), s.cipher()[0]
    req = (f"GET /fifa17/fut/rosterupdate.xml HTTP/1.1\r\nHost: {dial_ip}:{port}\r\n"
           "Connection: close\r\n\r\n")
    s.sendall(req.encode())
    buf = b""
    while True:
        chunk = s.recv(4096)
        if not chunk:
            break
        buf += chunk
    s.close()
    status = buf.split(b"\r\n", 1)[0].decode(errors="replace")
    body = buf.split(b"\r\n\r\n", 1)[1] if b"\r\n\r\n" in buf else b""
    print(f"  VERIFIED  {ver} {cipher}")
    print(f"  {status}  body={len(body)}B head={body[:60]!r}")
    sys.exit(0 if status.endswith("200 OK") and body else 3)
except Exception as e:
    print(f"  GET-FAIL {type(e).__name__}: {e}")
    sys.exit(3)
