3 # fetch the certificate that the server(s) are providing in PEM form
5 # args are HOST:PORT [, HOST:PORT...]
11 def fetch_server_certificate (host
, port
):
13 import re
, tempfile
, os
, ssl
16 from subprocess
import Popen
, PIPE
, STDOUT
17 proc
= Popen(cmd
, stdout
=PIPE
, stderr
=STDOUT
, shell
=True)
19 output
= proc
.stdout
.read()
22 def strip_to_x509_cert(certfile_contents
, outfile
=None):
23 m
= re
.search(r
"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n"
24 r
".*[\r]*^[-]+END CERTIFICATE[-]+)$",
25 certfile_contents
, re
.MULTILINE | re
.DOTALL
)
29 tn
= tempfile
.mktemp()
31 fp
.write(m
.group(1) + "\n")
34 tn2
= (outfile
or tempfile
.mktemp())
35 status
, output
= subproc(r
'openssl x509 -in "%s" -out "%s"' %
38 raise OperationError(status
, tsig
, output
)
47 if sys
.platform
.startswith("win"):
48 tfile
= tempfile
.mktemp()
53 status
, output
= subproc(
54 'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
59 status
, output
= subproc(
60 'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
64 certtext
= strip_to_x509_cert(output
)
66 raise ValueError("Invalid response received from server at %s:%s" %
70 if __name__
== "__main__":
73 "Usage: %s HOSTNAME:PORTNUMBER [, HOSTNAME:PORTNUMBER...]\n" %
76 for arg
in sys
.argv
[1:]:
77 host
, port
= arg
.split(":")
78 sys
.stdout
.write(fetch_server_certificate(host
, int(port
)))