/Tools/ssl/get-remote-certificate.py

http://unladen-swallow.googlecode.com/ · Python · 79 lines · 65 code · 7 blank · 7 comment · 15 complexity · f9c2fad7daf4d93669ef7f56f4fc6737 MD5 · raw file

  1. #!/usr/bin/env python
  2. #
  3. # fetch the certificate that the server(s) are providing in PEM form
  4. #
  5. # args are HOST:PORT [, HOST:PORT...]
  6. #
  7. # By Bill Janssen.
  8. import sys
  9. def fetch_server_certificate (host, port):
  10. import re, tempfile, os, ssl
  11. def subproc(cmd):
  12. from subprocess import Popen, PIPE, STDOUT
  13. proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
  14. status = proc.wait()
  15. output = proc.stdout.read()
  16. return status, output
  17. def strip_to_x509_cert(certfile_contents, outfile=None):
  18. m = re.search(r"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n"
  19. r".*[\r]*^[-]+END CERTIFICATE[-]+)$",
  20. certfile_contents, re.MULTILINE | re.DOTALL)
  21. if not m:
  22. return None
  23. else:
  24. tn = tempfile.mktemp()
  25. fp = open(tn, "w")
  26. fp.write(m.group(1) + "\n")
  27. fp.close()
  28. try:
  29. tn2 = (outfile or tempfile.mktemp())
  30. status, output = subproc(r'openssl x509 -in "%s" -out "%s"' %
  31. (tn, tn2))
  32. if status != 0:
  33. raise OperationError(status, tsig, output)
  34. fp = open(tn2, 'rb')
  35. data = fp.read()
  36. fp.close()
  37. os.unlink(tn2)
  38. return data
  39. finally:
  40. os.unlink(tn)
  41. if sys.platform.startswith("win"):
  42. tfile = tempfile.mktemp()
  43. fp = open(tfile, "w")
  44. fp.write("quit\n")
  45. fp.close()
  46. try:
  47. status, output = subproc(
  48. 'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
  49. (host, port, tfile))
  50. finally:
  51. os.unlink(tfile)
  52. else:
  53. status, output = subproc(
  54. 'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
  55. (host, port))
  56. if status != 0:
  57. raise OSError(status)
  58. certtext = strip_to_x509_cert(output)
  59. if not certtext:
  60. raise ValueError("Invalid response received from server at %s:%s" %
  61. (host, port))
  62. return certtext
  63. if __name__ == "__main__":
  64. if len(sys.argv) < 2:
  65. sys.stderr.write(
  66. "Usage: %s HOSTNAME:PORTNUMBER [, HOSTNAME:PORTNUMBER...]\n" %
  67. sys.argv[0])
  68. sys.exit(1)
  69. for arg in sys.argv[1:]:
  70. host, port = arg.split(":")
  71. sys.stdout.write(fetch_server_certificate(host, int(port)))
  72. sys.exit(0)