
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##


require 'msf/core'
require 'rex/socket/ssl_tcp'


class Metasploit3 < Msf::Auxiliary

	include Msf::Exploit::Remote::Tcp
	include Msf::Auxiliary::WMAPScanServer
	include Msf::Auxiliary::Scanner

	def initialize
		super(
			'Name'        => 'HTTP SSL Certificate Checker',
			'Version'     => '$Revision: 7321 $',
			'Author'      => 'nebulus',
			'License'     => MSF_LICENSE,
			'Description' => %q{
				This module will check the certificate of the specified web servers
				to ensure the subject and issuer match the supplied pattern and that the certificate
				is not expired.
			}
		)

		register_options(
		[
			Opt::RPORT(443),
			OptString.new('ISSUER', [ true,  "Show a warning if the Issuer doesn't match this regex", '.*']),
			OptBool.new('SHOWALL', [ false, "Show all certificates regardless of match", false]),
		], self.class)
	end

	# Fingerprint a single host
	def run_host(ip)

		begin
			ssock = connect(false, {'SSL' => true})
			cert  = OpenSSL::X509::Certificate.new(ssock.peer_cert)
			ssock.close

			if(not cert)
				print_status("#{ip} No certificate subject or CN found")
				return
			end

			issuer_pattern = Regexp.new(datastore['ISSUER'], Regexp::EXTENDED, 'n')
			sub = cert.subject.to_a

			before_d = "#{cert.not_before}".split
			before_t = before_d[3].split(":")
			after_d = "#{cert.not_after}".split
			after_t = after_d[3].split(":")
			before = Time.utc(before_d[5],before_d[1],before_d[2],before_t[0],before_t[1],before_t[3])
			after = Time.utc(after_d[5],after_d[1],after_d[2],after_t[0],after_t[1],after_t[3])

			now = Time.now
			a = now <=> before
			b = now <=> after

			vhostn = 'EMPTY'
			sub.each do |n|
				if n[0] == 'CN'
					vhostn = n[1]
				end
			end

			if ( not "#{cert.issuer}" =~ /#{issuer_pattern}/)
				print_status("WARNING (Issuer): #{ip} / #{vhostn} : #{cert.issuer}" )
			end
			print_status("#{ip} / #{vhostn} Issuer: #{cert.issuer}") if datastore['SHOWALL']

			if ( a < 1 or b > 0 )
				print_status("WARNING (Expired): #{ip} / #{vhostn} : Cert is expired/invalid: Before: " + before.to_s + " After " + after.to_s)
			end
			print_status("#{ip} / #{vhostn} Before: " + before.to_s + " After: " + after.to_s + " Now: " + now.to_s)  if datastore['SHOWALL']

		rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
		rescue ::Timeout::Error, ::Errno::EPIPE
		end
	end

end

