]>
git.siccegge.de Git - dane-monitoring-plugins.git/blob - check_dane/xmpp.py
9452f8eed6f935f74294ee1e8525a7801554ca25
5 from __future__
import print_function
10 from ssl
import SSLContext
, PROTOCOL_TLSv1_2
, CERT_REQUIRED
11 from socket
import socket
13 from check_dane
.tlsa
import get_tlsa_records
14 from check_dane
.cert
import add_certificate_options
15 from check_dane
.abstract
import DaneChecker
16 from check_dane
.resolve
import Resolver
, srv_lookup
18 XMPP_OPEN
= ("<stream:stream xmlns='jabber:{0}' xmlns:stream='"
19 "http://etherx.jabber.org/streams' xmlns:tls='http://www.ietf.org/rfc/"
20 "rfc2595.txt' to='{1}' xml:lang='en' version='1.0'>")
21 XMPP_CLOSE
= "</stream:stream>"
22 XMPP_STARTTLS
= "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
24 class XmppDaneChecker(DaneChecker
):
25 def _init_connection(self
, family
, host
, port
):
27 logging
.debug("Connecting to %s:%d", host
, port
)
29 connection
= socket(family
=family
)
30 connection
.connect((host
, port
))
32 connection
.sendall(XMPP_OPEN
.format(self
.servicetype
, self
._hostname
).encode())
33 answer
= connection
.recv(4096)
36 if not b
'</stream:features>' in answer
:
37 answer
= connection
.recv(4096)
40 connection
.sendall(XMPP_STARTTLS
.encode())
41 answer
= connection
.recv(4096)
44 print(host
, self
._hostname
)
45 connection
= self
._sslcontext
.wrap_socket(connection
, server_hostname
=self
._hostname
)
46 connection
.do_handshake()
48 connection
.sendall(XMPP_OPEN
.format(self
.servicetype
, self
._hostname
).encode())
49 answer
= connection
.recv(4096)
52 if not b
'</stream:features>' in answer
:
53 answer
= connection
.recv(4096)
65 def servicetype(self
):
69 def _gather_certificates(self
):
71 for (host
, port
), meta
in self
._endpoints
:
74 self
._type
= meta
['type']
75 result
.update(DaneChecker
._gather
_certificates
(self
))
80 def _gather_records(self
):
82 for (host
, port
), _
in self
._endpoints
:
83 print(repr((host
, port
)))
84 result
.update(get_tlsa_records(self
._resolver
, "_%d._tcp.%s" % (port
, host
)))
89 def _close_connection(self
, connection
):
90 connection
.send(XMPP_CLOSE
.encode())
91 answer
= connection
.recv(512)
100 self
._hostname
= None
101 DaneChecker
.__init
__(self
)
104 def set_args(self
, args
):
105 DaneChecker
.set_args(self
, args
)
107 sslcontext
= SSLContext(PROTOCOL_TLSv1_2
)
108 sslcontext
.verify_mode
= CERT_REQUIRED
109 sslcontext
.load_verify_locations(args
.castore
)
111 cresolver
= Resolver(args
.ancor
)
112 self
._sslcontext
= sslcontext
114 self
._hostname
= args
.Host
.encode('idna').decode()
117 for endpoint
, meta
in srv_lookup("_xmpp-client._tcp.%s" %
120 meta
['type'] = 'client'
121 endpoints
.append((endpoint
, meta
))
123 for endpoint
, meta
in srv_lookup("_xmpp-server._tcp.%s" %
126 meta
['type'] = 'server'
127 endpoints
.append((endpoint
, meta
))
129 self
._endpoints
= endpoints
132 def generate_menu(self
, argparser
):
133 DaneChecker
.generate_menu(self
, argparser
)
134 group
= argparser
.add_mutually_exclusive_group()
135 group
.add_argument("--s2s", action
="store_true",
136 help="Only check server-to-server connections")
137 group
.add_argument("--c2s", action
="store_true",
138 help="Only check client-to-server connections")
139 argparser
.add_argument("-p", "--port",
140 action
="store", type=int, default
=0,
147 logging
.basicConfig(format
='%(levelname)5s %(message)s')
148 checker
= XmppDaneChecker()
149 parser
= argparse
.ArgumentParser()
151 parser
.add_argument("--verbose", action
="store_true")
152 parser
.add_argument("--quiet", action
="store_true")
154 checker
.generate_menu(parser
)
155 add_certificate_options(parser
)
157 args
= parser
.parse_args()
158 checker
.set_args(args
)
161 logging
.getLogger().setLevel(logging
.DEBUG
)
163 logging
.getLogger().setLevel(logging
.WARNING
)
165 logging
.getLogger().setLevel(logging
.INFO
)
167 return checker
.check()
170 if __name__
== '__main__':