#!/usr/bin/env python3 """STARTTLS probe for Prosody/XMPP servers (c2s 5222 default, --s2s uses jabber:server for 5269). Usage: starttls_probe.py [--s2s] Verifies: stream features -> starttls -> -> TLS handshake -> cert subject/issuer/SAN. Reason to exist: `openssl s_client -starttls xmpp` reports "no peer certificate"/Cipher NONE on Prosody 0.11 even when TLS works fine (false negative). Exit 0 with "TLS OK" = c2s/s2s STARTTLS fully working with a trusted cert. """ import socket, ssl, sys, time HOST = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1" PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 5222 DOMAIN = sys.argv[3] if len(sys.argv) > 3 else "nixg.ru" S2S = "--s2s" in sys.argv NS = "jabber:server" if S2S else "jabber:client" s = socket.create_connection((HOST, PORT), timeout=10) s.settimeout(8) def recv(): data = s.recv(8192) print(" <<", data.decode(errors="replace")[:300].replace("\n", " ")) return data s.sendall( ("" % (DOMAIN, NS)).encode() ) time.sleep(1) recv() s.sendall(b"") time.sleep(1) recv() ctx = ssl.create_default_context() tls = ctx.wrap_socket(s, server_hostname=DOMAIN) print("TLS OK:", tls.cipher()[0], tls.version()) try: cert = tls.getpeercert() print("SUBJECT:", cert["subject"]) print("ISSUER:", cert["issuer"]) print("SAN:", cert.get("subjectAltName")) except Exception as e: print("cert verification issue:", e) tls.close()