Skip to content

Instantly share code, notes, and snippets.

@ibc
Created December 1, 2011 09:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ibc/1415302 to your computer and use it in GitHub Desktop.
Save ibc/1415302 to your computer and use it in GitHub Desktop.
Script to get SIP identities from a TLS certificate following RFC 5922 section 7.1
#!/usr/bin/ruby
# Runs as follows:
#
# ~$ ruby get-sip-identities.rb PEM_FILE
require "openssl"
module TLS
def self.get_sip_identities cert
puts "DEBUG: following rules in RFC 5922 \"Domain Certificates in SIP\" section 7.1 \"Finding SIP Identities in a Certificate\""
verify_subjectAltName_DNS = true
verify_CN = true
subjectAltName_URI_sip_entries = []
subjectAltName_DNS_entries = []
sip_identities = {}
cert.extensions.each do |ext|
next if ext.oid != "subjectAltName"
verify_CN = false
ext.value.split(/,\s+/).each do |name|
if /^URI:sip:([^@]*)/i =~ name
verify_subjectAltName_DNS = false
subjectAltName_URI_sip_entries << $1.downcase
elsif verify_subjectAltName_DNS && /^DNS:(.*)/i =~ name
subjectAltName_DNS_entries << $1.downcase
end
end
end
unless verify_CN
puts "DEBUG: certificate contains 'subjectAltName' extensions, 'CommonName' ignored"
unless verify_subjectAltName_DNS
subjectAltName_URI_sip_entries.each {|domain| sip_identities[domain] = true}
puts "DEBUG: 'subjectAltName' entries of type \"URI:sip:\" found, 'subjectAltName' entries of type \"DNS\" ignored"
else
subjectAltName_DNS_entries.each {|domain| sip_identities[domain] = true}
puts "DEBUG: 'subjectAltName' entries of type \"URI:sip:\" not found, using 'subjectAltName' entries of type \"DNS\""
end
else
puts "DEBUG: no 'subjectAltName' extension found, using 'CommonName' value"
cert.subject.to_a.each do |oid, value|
if oid == "CN"
sip_identities[value.downcase] = true
break
end
end
end
return sip_identities
end
end
unless (file = ARGV[0])
$stderr.puts "ERROR: no file given as argument"
exit false
end
unless ::File.file?(file) and ::File.readable?(file)
$stderr.puts "ERROR: given file is not a readable file"
exit false
end
begin
cert = ::OpenSSL::X509::Certificate.new(::File.read(file))
rescue => e
$stderr.puts "ERROR: cannot get a PEM certificate in the given file: #{e.message} (#{e.class})"
exit false
end
sip_identities = TLS.get_sip_identities cert
puts
if sip_identities.any?
puts "SIP identities found in the certificate:"
puts
sip_identities.each_key {|name| puts " - #{name}"}
else
puts "No SIP identities found in the certificate"
end
puts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment