xmpp-20190420.py (Código fuente)

#!/usr/bin/env python3

# This code is in the Public Domain.
# You can do with it whatever you want.
#
# 2018 jcea@jcea.es - https://www.jcea.es/


import socket
import ssl
import base64

import dns.resolver

jid = 'TU JID'
clave = 'TU CLAVE'

usuario, dominio = jid.split('@')
dns = dns.resolver.query(f'_xmpp-client._tcp.{dominio}', 'SRV')
srv = min(dns.response.answer[0].items, key=lambda x: x.priority)

s = socket.socket()
s.connect((srv.target.to_text(), srv.port))

s.send(f"""<stream:stream
from='{jid}'
to='{dominio}'
version='1.0'
xml:lang='en'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'>
""".encode('utf-8'))
print(s.recv(9999))

s.send(b"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>")
print(s.recv(9999))

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS)
ssl_context.verify_mode = ssl.CERT_REQUIRED
ssl_context.check_hostname = True
ssl_context.load_default_certs()
s = ssl_context.wrap_socket(s, server_hostname=dominio)

print('\nPasamos a TLS\n')

s.send(f"""<stream:stream
from='{jid}'
to='{dominio}'
version='1.0'
xml:lang='en'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'>
""".encode('utf-8'))
print(s.recv(9999))

s.send(b"""
<auth mechanism='PLAIN'
xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</auth>
""" % base64.b64encode(f'{jid}\0{usuario}\0{clave}'.encode('utf-8')))
print(s.recv(9999))

s.send(f"""<stream:stream
from='{jid}'
to='{dominio}'
version='1.0'
xml:lang='en'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'>
""".encode('utf-8'))
print(s.recv(9999))

s.send(b"""
<iq id='qwdc' type='set'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>DUMMY</resource>
</bind>
</iq>
""")
print(s.recv(9999))

print("\nPreguntamos por qué extensiones soporta el servidor\n")

s.send(f"""
<iq from='{jid}' to='{dominio}' type='get' id='abcd'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
""".encode('utf-8'))
print(s.recv(9999))

# READ:
# https://blog.jcea.es/posts/20190417-xmpp_isode_subscription_cleaning.html

print("\nEnviamos la purga\n")
s.send(b"""
<iq type='set' id='purge-subscribe'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <purge node='http://isode.com/subscribe'/>
  </pubsub>
</iq>
""")

print(s.recv(9999))