| Current Path : /opt/cpanel/ |
| Current File : //opt/cpanel/new_list.py |
#!/usr/bin/env python3
import socket
import ssl
import struct
import uuid
import xml.etree.ElementTree as ET
from datetime import datetime
# ─── Registry credentials ─────────────────────────────────────────────
EPP_HOST = "epp.zarc.net.za"
EPP_PORT = 700
EPP_USER = "enetworks"
EPP_PASS = "36ancerg9a2"
# ─── Helper functions ─────────────────────────────────────────────────
def frame(xml: str) -> bytes:
data = xml.encode("utf-8")
return struct.pack("!I", len(data) + 4) + data
def recv_frame(sock: ssl.SSLSocket) -> str:
hdr = sock.recv(4)
if not hdr:
raise ConnectionError("socket closed while reading header")
length = struct.unpack("!I", hdr)[0]
payload = b""
while len(payload) < length - 4:
chunk = sock.recv(length - 4 - len(payload))
if not chunk:
raise ConnectionError("socket closed while reading payload")
payload += chunk
return payload.decode("utf-8")
def login_xml() -> str:
return f"""<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<login>
<clID>{EPP_USER}</clID>
<pw>{EPP_PASS}</pw>
<options><version>1.0</version><lang>en</lang></options>
<svcs>
<objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
<objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
<svcExtension><extURI>http://co.za/epp/extensions/cozadomain-1-0</extURI></svcExtension>
</svcs>
</login>
<clTRID>{uuid.uuid4()}</clTRID>
</command>
</epp>"""
def list_domains_xml() -> str:
return f"""<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<info/>
<extension>
<coza:list xmlns:coza="http://co.za/epp/extensions/cozadomain-1-0">
<coza:listDomains/>
</coza:list>
</extension>
<clTRID>{uuid.uuid4()}</clTRID>
</command>
</epp>"""
def parse_domains(xml: str):
ns = {
"coza": "http://co.za/epp/extensions/cozadomain-1-0",
}
root = ET.fromstring(xml)
for node in root.findall(".//coza:domain", ns):
name = node.findtext("coza:name", default="", namespaces=ns)
exp = node.findtext("coza:expiryDate", default="", namespaces=ns)
if exp:
try:
exp = datetime.fromisoformat(exp.replace("Z", "+00:00")).strftime("%Y-%m-%d")
except Exception:
pass
yield name, exp
# ─── Main flow ────────────────────────────────────────────────────────
def main():
ctx = ssl.create_default_context()
with socket.create_connection((EPP_HOST, EPP_PORT)) as tcp:
with ctx.wrap_socket(tcp, server_hostname=EPP_HOST) as epp:
print("[+] TLS connected")
# ---- 1. Discard greeting ------------------------------------------------
greeting = recv_frame(epp)
print("[i] Greeting received.")
# ---- 2. Login ------------------------------------------------------------
epp.sendall(frame(login_xml()))
login_resp = recv_frame(epp)
if '<result code="1000"' not in login_resp:
print("[!] Login failed:\n", login_resp)
return
print("[+] Login successful")
# ---- 3. listDomains ------------------------------------------------------
epp.sendall(frame(list_domains_xml()))
list_resp = recv_frame(epp)
domains = list(parse_domains(list_resp))
if not domains:
print("[!] No domains returned – is the listDomains extension enabled?")
print(list_resp)
return
# ---- 4. Output -----------------------------------------------------------
colw = max(len(d[0]) for d in domains) + 2
print(f"\n{'Domain':<{colw}}Expiry")
print("-" * (colw + 12))
for name, exp in sorted(domains):
print(f"{name:<{colw}}{exp}")
print(f"\nTotal domains: {len(domains)}")
if __name__ == "__main__":
main()