Table of Contents

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

  1. Working with the Ruby Enumerable wrapper
  2. Searching for subfields
  3. 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.rb
#----------------------------------------------------------
# xcert -  Cert stacks of all TLS sessions in capture file
#
#  usage: xcert <capture-filename>
#
#---------------------------------------------------------
require 'win32ole'
 
raise "xcert <capture-filename>" 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