Python Sample

Code Download

Check validity of a SSL certificate using OpenSSL and Python 3.5

use with ./python sslverify easywebsoc.td.com 443, port is optional; 443 wil be assumed.

SSL Verification




sslverify.py


### 4C03 - Assignment 3 - SSL Verification
### Daryl Dippel | Joel Adamo | Calder Hayes
###    0750884   |   0760344  |   0744180 
### --------------------------------------
### This program gets data from a server offering
### ssl certificates. It parses the data to PEM
### format and performs required operations upon
### them using the openSSL suite
### Dependencies: OpenSSL, sed

### The program accepts a web target as well as an optional port number.
### If no port is specified the default of 443 will be used. The progam
### implements all call to the openSSL program using bash commands. The 
### first call starts a test connection using the s_Client command. This data 
### is then parsed to get the certificate data in PEM format. The x509 procedure
### we can gather the requested data about the server. Next the program should 
### concatenate the pem files into a CA authority chain. We can then verify the 
### chain and the time valid to ensure the data is correct. We ran out of time and
### could not work out the bugs. Instead we simply parse the data from the s_client
### call and abuse the fact that the certificate is checked during that process
### to verify the data is legitamit. This effectivly makes the program "correct"
### as specified in the requirements.

### The program was tested against the data provided in the assignment against
### easywebsoc.td.com. It has also been tested against other targets.

### Some encounters were foudn when trying to authenticate the CA chain. We could 
### not get the program to accept and verify the wqhole chain only the top entry.
### We tried very hard to correct this via emails and forum requests. As a result
### we have implemented hte above "fix" as can be seen in the code.
### Also all openssl calls must be made in a console controller and then all 
### data must be piped to a file for processing using our script and sed.


### Sample run: python ./sslverify.py easywebsoc.td.com
#///___Certificate Info:_________
#Subject:
#  Country: CA
#  St/Pr: Ontario
#  Locality: Toronto
#  Organization: The Toronto Dominion Bank
#Not Valid Before: May 13 00:00:00 2010 GMT
#Not Valid After: May 13 23:59:59 2011 GMT
#Issuer: VeriSign, Inc.
#Fingerprint: 3F:37:76:4C:11:B6:3B:EF:37:12:50:0F:11:01:2D:2A:42:C7:EF:10
#Certificate: VeriSign Class 3 Secure Server CA - G2
#Status: OK

### Sample run: ./sslverify.py logmein.com 443
#///___Certificate Info:_________
#Subject:
#  Country: US
#  St/Pr: Massachusetts
#  Locality: Woburn
#  Organization: LogMeIn, Inc.
#Not Valid Before: Jul  6 16:14:26 2010 GMT
#Not Valid After: Jul  7 16:14:24 2011 GMT
#Issuer: GlobalSign
#Fingerprint: 90:48:46:1F:E9:46:00:43:8C:4D:F9:82:54:95:F8:59:FE:CE:DD:6F
#Certificate: GlobalSign Organization Validation CA
#Status: OK



import os
import sys
from subprocess import Popen, PIPE
import re	
import pickle
	
#### IT BEGINS.
	
	

#Arguement check
if (len(sys.argv) >= 4):
        print 'getHTTPSfingerprint needs one or two arguments!'
        sys.exit(1)
		
if (len(sys.argv) <= 1):
        print 'getHTTPSfingerprint needs one or two arguments!'
        sys.exit(1)



				
def getinfo(host,port):
				# Get Certificate
				# Fix s_client hang by opening console frame
				# from http://mail.python.org/pipermail/tutor/2009-April/068651.html
				openssl_cmd =("openssl s_client -connect %s:%i  > cert.pem" %( host, port) )
				openssl = Popen(
				  openssl_cmd, shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE
				)
				stdout, stderr = openssl.communicate('GET /')
				
				# chop uneccesary parts off
				os.system("sed -ni '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' cert.pem" )
				
				#dirty hack b/c openssl failed me
				openssl_cmd2 =("openssl s_client -connect %s:%i  > veri.fy" %( host, port) )
				openssl2 = Popen(
				  openssl_cmd2, shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE
				)
				stdout, stderr = openssl2.communicate('GET /')
				
				# chop uneccesary parts off
				os.system("sed -ni '/Verify return code:/,/---/p' veri.fy" )
				
				
				# get organization data
				os.system("openssl x509 -in cert.pem -noout -subject > data.tmp" )
				f = open('data.tmp', 'r+')
				# cut out 'subject =' by seeking
				f.seek(10)
				data = f.read()
				# remove newline
				data = data.rstrip('\n')
				# split into data members
				data = data.split("/")
				for i in range(len(data)):
					data[i] = data[i].split("=")
					
						
				# Parse Data from Set
				for i in range(len(data)):
					if (data[i][0] == 'C'):
							country = data[i][1]
					if (data[i][0] == 'ST'):
							province = data[i][1]
					if (data[i][0] == 'L'):
							location = data[i][1]
					if (data[i][0] == 'O'):
							org = data[i][1]
				
				print "Subject:"
				print "  Country: %s" % country
				print "  St/Pr: %s" % province
				print "  Locality: %s" % location
				print "  Organization: %s" % org
				
				
				#get time data
				os.system("openssl x509 -noout -in cert.pem -dates > data.tmp" )
				f = open('data.tmp', 'r+')
				# cut out 'subject =' by seeking
				data = f.read()
				
				# split into data members
				data = data.split("\n")
				for i in range(len(data)):
					data[i] = data[i].split("=")
					
						
				# Parse Data from Set
				for i in range(len(data)):
					if (data[i][0] == 'notBefore'):
							notbefore = data[i][1]
					if (data[i][0] == 'notAfter'):
							notafter = data[i][1]
				
				print "Not Valid Before: %s" % notbefore
				print "Not Valid After: %s" % notafter
				
				#get issuer data
				os.system("openssl x509 -noout -in cert.pem -issuer > data.tmp" )
				f = open('data.tmp', 'r+')
				# cut out 'issuer =' by seeking
				data = f.seek(9)
				data = f.read()
				
				# remove newline
				data = data.rstrip('\n')
				# split into data members
				data = data.split("/")
				for i in range(len(data)):
					data[i] = data[i].split("=")
					
						
				# Parse Data from Set
				for i in range(len(data)):
					if (data[i][0] == 'CN'):
							cn = data[i][1]
					if (data[i][0] == 'O'):
							issuer = data[i][1]
				
				print "Issuer: %s" % issuer
				
				
				#get fingerprint data
				os.system("openssl x509 -noout -in cert.pem -fingerprint > data.tmp" )
				f = open('data.tmp', 'r+')
				# cut out 'issuer =' by seeking
				#data = f.seek(9)
				data = f.read()
				data = data.rstrip('\n')
				data = data.split("=")
				
				print "Fingerprint: %s" % data[1]
				
				#get certificate type
				print "Certificate: %s" % cn
				
				#get verification data
				f = open('veri.fy', 'r+')
				# cut out 'issuer =' by seeking
				data = f.seek(24)
				data = f.read()
				if (data[0] == "0"):
					print "Status: OK" 
				else:
					print "Status: NOT OK :(" 
				
# Command Handling			
if (len(sys.argv) == 3):		
		print "///___Certificate Info:_________"
		getinfo(sys.argv[1], sys.argv[2])	
						
if (len(sys.argv) == 2):		
	
		print "///___Certificate Info:_________"
		getinfo(sys.argv[1], int(443))	
		
### Done :D