Skip to content

Commit 1159380

Browse files
author
HD Moore
committed
Move X509 PEM parsing into Rex::Parser::X509Certificate
1 parent bb81107 commit 1159380

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

lib/rex/parser/x509_certificate.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# -*- coding: binary -*-
2+
3+
require 'openssl'
4+
5+
module Rex
6+
module Parser
7+
8+
###
9+
#
10+
# This class parses the contents of a PEM-encoded X509 certificate file containing
11+
# a private key, a public key, and any appended glue certificates.
12+
#
13+
###
14+
class X509Certificate
15+
16+
#
17+
# Parse a certificate in unified PEM format that contains a private key and
18+
# one or more certificates. The first certificate is the primary, while any
19+
# additional certificates are treated as intermediary certificates. This emulates
20+
# the behavior of web servers like nginx.
21+
#
22+
# @param [String] ssl_cert
23+
# @return [String, String, Array]
24+
def self.parse_pem(ssl_cert)
25+
cert = nil
26+
key = nil
27+
chain = nil
28+
29+
certs = []
30+
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
31+
if pem =~ /PRIVATE KEY/
32+
key = OpenSSL::PKey::RSA.new(pem)
33+
elsif pem =~ /CERTIFICATE/
34+
certs << OpenSSL::X509::Certificate.new(pem)
35+
end
36+
end
37+
38+
cert = certs.shift
39+
if certs.length > 0
40+
chain = certs
41+
end
42+
43+
[key, cert, chain]
44+
end
45+
46+
#
47+
# Parse a certificate in unified PEM format from a file
48+
#
49+
# @param [String] ssl_cert_file
50+
# @return [String, String, Array]
51+
def self.parse_pem_file(ssl_cert_file)
52+
data = ''
53+
::File.open(ssl_cert_file, 'rb') do |fd|
54+
data << fd.read(fd.stat.size)
55+
end
56+
parse_pem(data)
57+
end
58+
59+
end
60+
61+
end
62+
end

lib/rex/socket/ssl_tcp_server.rb

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'rex/socket'
33
require 'rex/socket/tcp_server'
44
require 'rex/io/stream_server'
5+
require 'rex/parser/x509_certificate'
56

67
###
78
#
@@ -108,25 +109,7 @@ def accept(opts = {})
108109
# @param [String] ssl_cert
109110
# @return [String, String, Array]
110111
def self.ssl_parse_pem(ssl_cert)
111-
cert = nil
112-
key = nil
113-
chain = nil
114-
115-
certs = []
116-
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
117-
if pem =~ /PRIVATE KEY/
118-
key = OpenSSL::PKey::RSA.new(pem)
119-
elsif pem =~ /CERTIFICATE/
120-
certs << OpenSSL::X509::Certificate.new(pem)
121-
end
122-
end
123-
124-
cert = certs.shift
125-
if certs.length > 0
126-
chain = certs
127-
end
128-
129-
[key, cert, chain]
112+
Rex::Parser::X509Certificate.parse_pem(ssl_cert)
130113
end
131114

132115
#

0 commit comments

Comments
 (0)