| Current Path : /opt/cpanel/ |
| Current File : //opt/cpanel/zarc_dnssec.py |
import socket
import ssl
import struct
import uuid
import sys
# ----- Config -----
EPP_HOST = "epp.zarc.net.za"
EPP_PORT = 700
EPP_USER = "enetworks"
EPP_PASS = "36ancerg9a2"
# ----- EPP Helpers -----
def frame(xml_string):
xml_bytes = xml_string.encode('utf-8')
return struct.pack("!I", len(xml_bytes) + 4) + xml_bytes
def read_response(sock):
header = sock.recv(4)
if not header: return None
total_length = struct.unpack("!I", header)[0]
data = b''
while len(data) < total_length - 4:
chunk = sock.recv(total_length - 4 - len(data))
if not chunk: break
data += chunk
return data.decode('utf-8')
def build_login_xml():
"""Corrected Login XML with proper svcExtension wrapping"""
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>
<objURI>http://co.za</objURI>
<objURI>http://co.za</objURI>
<svcExtension>
<extURI>urn:ietf:params:xml:ns:secDNS-1.1</extURI>
</svcExtension>
</svcs>
</login>
<clTRID>{uuid.uuid4()}</clTRID>
</command>
</epp>"""
def build_dnssec_update_xml(domain, key_tag, alg, digest_type, digest):
"""Adds a DS record to the domain"""
return f"""<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<domain:update xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>{domain}</domain:name>
</domain:update>
</update>
<extension>
<secDNS:update xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
<secDNS:add>
<secDNS:dsData>
<secDNS:keyTag>{key_tag}</secDNS:keyTag>
<secDNS:alg>{alg}</secDNS:alg>
<secDNS:digestType>{digest_type}</secDNS:digestType>
<secDNS:digest>{digest}</secDNS:digest>
</secDNS:dsData>
</secDNS:add>
</secDNS:update>
</extension>
<clTRID>{uuid.uuid4()}</clTRID>
</command>
</epp>"""
def main():
if len(sys.argv) != 6:
print("Usage: python zarc_dnssec.py <domain> <keytag> <alg> <digest_type> <digest>")
sys.exit(1)
domain, keytag, alg, dtype, digest = sys.argv[1:]
context = ssl.create_default_context()
with socket.create_connection((EPP_HOST, EPP_PORT)) as tcp_sock:
with context.wrap_socket(tcp_sock, server_hostname=EPP_HOST) as epp_sock:
# Consume Greeting
read_response(epp_sock)
# Login
epp_sock.sendall(frame(build_login_xml()))
login_res = read_response(epp_sock)
if 'result code="1000"' not in login_res:
print("Login Failed:", login_res)
return
# Update DNSSEC
print(f"[*] Adding DS record for {domain}...")
dnssec_xml = build_dnssec_update_xml(domain, keytag, alg, dtype, digest)
epp_sock.sendall(frame(dnssec_xml))
print("[+] Response:\n", read_response(epp_sock))
if __name__ == "__main__":
main()