====== xcert.rb : Print certificate chain for all SSL connections in capture file ======
Scans the // Server Certificate // sent as part of the SSL/TLS handshake and prints the certificate chain. This sample script demonstrates
- Working with the Ruby Enumerable [[unsniff:objectref:collectionobj|wrapper]]
- Searching for subfields
- Working with name value pair fields
===== Sample output =====
C:\Users\Tom Wilson\Documents\unsniff>ruby xcert.rb may1112S2.usnf
Certificate chain for 212.149.50.181 to 192.168.1.5
www.commerzbanking.de (Commerzbank AG)
TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH)
TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH)
Cybertrust Global Root (Cybertrust, Inc)
Cybertrust Global Root (Cybertrust, Inc)
GTE CyberTrust Global Root (GTE Corporation)
Certificate chain for 174.137.42.65 to 192.168.1.5
www.wireshark.org ()
PositiveSSL CA (Comodo CA Limited)
PositiveSSL CA (Comodo CA Limited)
UTN-USERFirst-Hardware (The USERTRUST Network)
UTN-USERFirst-Hardware (The USERTRUST Network)
AddTrust External CA Root (AddTrust AB)
===== Ruby code =====
#----------------------------------------------------------
# xcert - Cert stacks of all TLS sessions in capture file
#
# usage: xcert
#
#---------------------------------------------------------
require 'win32ole'
raise "xcert " unless ARGV.length ==1
UnsniffDB = WIN32OLE.new("Unsniff.Database")
UnsniffDB.OpenForRead(ARGV[0])
# enumerable helper
class UWrap
include Enumerable
def initialize(w)
@wrapped=w
end
def each(&block)
@wrapped.each { |m| block.call(m) }
end
end
# print cert stack of each cerficate pdu
UnsniffDB.PDUIndex.each do |pdu|
next unless pdu.Description =~ /Server Certificate/
print "\nCertificate chain for " + pdu.SenderAddress + " to " + pdu.ReceiverAddress + "\n"
handshake = UWrap.new(pdu.Fields).find do |f|
hst = f.FindField("Handshake Type")
hst and hst.Value() == "11 (certificate)"
end
next unless handshake
certstack = handshake.FindField("Certificate")
certs = UWrap.new(certstack.SubFields).select { |f| f.Name == "ASN.1Cert" }
indent = 4
certs.each do |cert|
subject = cert.FindField("subject")
issuer = cert.FindField("issuer")
sub,iss = {},{}
[ [subject, sub], [issuer, iss] ].each do |a|
a[0].SubFields.each do |rdn|
case rdn.FindField("type").Value
when /commonName/
a[1][:cn]=rdn.FindField("DirectoryString").Value
;
when /organizationName/
a[1][:on]=rdn.FindField("DirectoryString").Value
;
end
end
end
print " "*indent + "#{sub[:cn]} (#{sub[:on]})\n"
print " "*(indent+1) + "#{iss[:cn]} (#{iss[:on]})\n"
indent = indent + 1
end
end
UnsniffDB.Close