#!/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: """ 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)