mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 18:07:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| #
 | |
| # fetch the certificate that the server(s) are providing in PEM form
 | |
| #
 | |
| # args are HOST:PORT [, HOST:PORT...]
 | |
| #
 | |
| # By Bill Janssen.
 | |
| 
 | |
| import re
 | |
| import os
 | |
| import sys
 | |
| import tempfile
 | |
| 
 | |
| 
 | |
| def fetch_server_certificate (host, port):
 | |
| 
 | |
|     def subproc(cmd):
 | |
|         from subprocess import Popen, PIPE, STDOUT
 | |
|         proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
 | |
|         status = proc.wait()
 | |
|         output = proc.stdout.read()
 | |
|         return status, output
 | |
| 
 | |
|     def strip_to_x509_cert(certfile_contents, outfile=None):
 | |
|         m = re.search(br"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n"
 | |
|                       br".*[\r]*^[-]+END CERTIFICATE[-]+)$",
 | |
|                       certfile_contents, re.MULTILINE | re.DOTALL)
 | |
|         if not m:
 | |
|             return None
 | |
|         else:
 | |
|             tn = tempfile.mktemp()
 | |
|             fp = open(tn, "wb")
 | |
|             fp.write(m.group(1) + b"\n")
 | |
|             fp.close()
 | |
|             try:
 | |
|                 tn2 = (outfile or tempfile.mktemp())
 | |
|                 status, output = subproc(r'openssl x509 -in "%s" -out "%s"' %
 | |
|                                          (tn, tn2))
 | |
|                 if status != 0:
 | |
|                     raise RuntimeError('OpenSSL x509 failed with status %s and '
 | |
|                                        'output: %r' % (status, output))
 | |
|                 fp = open(tn2, 'rb')
 | |
|                 data = fp.read()
 | |
|                 fp.close()
 | |
|                 os.unlink(tn2)
 | |
|                 return data
 | |
|             finally:
 | |
|                 os.unlink(tn)
 | |
| 
 | |
|     if sys.platform.startswith("win"):
 | |
|         tfile = tempfile.mktemp()
 | |
|         fp = open(tfile, "w")
 | |
|         fp.write("quit\n")
 | |
|         fp.close()
 | |
|         try:
 | |
|             status, output = subproc(
 | |
|                 'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
 | |
|                 (host, port, tfile))
 | |
|         finally:
 | |
|             os.unlink(tfile)
 | |
|     else:
 | |
|         status, output = subproc(
 | |
|             'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
 | |
|             (host, port))
 | |
|     if status != 0:
 | |
|         raise RuntimeError('OpenSSL connect failed with status %s and '
 | |
|                            'output: %r' % (status, output))
 | |
|     certtext = strip_to_x509_cert(output)
 | |
|     if not certtext:
 | |
|         raise ValueError("Invalid response received from server at %s:%s" %
 | |
|                          (host, port))
 | |
|     return certtext
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     if len(sys.argv) < 2:
 | |
|         sys.stderr.write(
 | |
|             "Usage:  %s HOSTNAME:PORTNUMBER [, HOSTNAME:PORTNUMBER...]\n" %
 | |
|             sys.argv[0])
 | |
|         sys.exit(1)
 | |
|     for arg in sys.argv[1:]:
 | |
|         host, port = arg.split(":")
 | |
|         sys.stdout.buffer.write(fetch_server_certificate(host, int(port)))
 | |
|     sys.exit(0)
 | 
