Module: Rex::Socket::SslTcpServer

Includes:
TcpServer
Defined in:
lib/rex/socket/ssl_tcp_server.rb

Overview

This class provides methods for interacting with an SSL wrapped TCP server. It implements the StreamServer IO interface.

Defined Under Namespace

Classes: UnitTest

Constant Summary collapse

@@loaded_openssl =
false

Constants included from Rex::Socket

MATCH_IPV4, MATCH_IPV4_PRIVATE, MATCH_IPV6

Instance Attribute Summary collapse

Attributes included from IO::StreamServer

#client_waiter, #clients, #clients_thread, #listener_thread, #on_client_close_proc, #on_client_connect_proc, #on_client_data_proc

Attributes included from Rex::Socket

#context, #ipv, #localhost, #localport, #peerhost, #peerport

Class Method Summary collapse

Instance Method Summary collapse

Methods included from IO::StreamServer

#close_client, #on_client_close, #on_client_connect, #on_client_data, #start, #stop, #wait

Methods included from Rex::Socket

addr_atoc, addr_atoi, addr_atoi_list, addr_aton, addr_ctoa, addr_itoa, addr_iton, addr_ntoa, addr_ntoi, bit2netmask, cidr_crack, compress_address, create_ip, create_tcp, create_tcp_server, create_udp, dotted_ip?, #fd, from_sockaddr, getaddress, getaddresses, gethostbyname, #getlocalname, #getpeername, #getsockname, ipv6_link_address, ipv6_mac, is_internal?, is_ipv4?, is_ipv6?, net2bitmask, portlist_to_portspec, portspec_crack, portspec_to_portlist, resolv_nbo, resolv_nbo_i, resolv_nbo_i_list, resolv_nbo_list, resolv_to_dotted, source_address, support_ipv6?, tcp_socket_pair, to_sockaddr, #type?, udp_socket_pair

Instance Attribute Details

#sslctxObject

Returns the value of attribute sslctx.



171
172
173
# File 'lib/rex/socket/ssl_tcp_server.rb', line 171

def sslctx
  @sslctx
end

Class Method Details

.create(hash = {}) ⇒ Object

Factory



31
32
33
34
35
36
# File 'lib/rex/socket/ssl_tcp_server.rb', line 31

def self.create(hash = {})
	hash['Proto']  = 'tcp'
	hash['Server'] = true
	hash['SSL']    = true
	self.create_param(Rex::Socket::Parameters.from_hash(hash))
end

.create_param(param) ⇒ Object

Wrapper around the base class’ creation method that automatically sets the parameter’s protocol to TCP and sets the server flag to true.



42
43
44
45
46
47
# File 'lib/rex/socket/ssl_tcp_server.rb', line 42

def self.create_param(param)
	param.proto  = 'tcp'
	param.server = true
	param.ssl    = true
	Rex::Socket.create_param(param)
end

Instance Method Details

#accept(opts = {}) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rex/socket/ssl_tcp_server.rb', line 55

def accept(opts = {})
	sock = super()
	return if not sock

	begin
		ssl = OpenSSL::SSL::SSLSocket.new(sock, self.sslctx)

		if not allow_nonblock?(ssl)
			ssl.accept
		else
			begin
				ssl.accept_nonblock

			# Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
			rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
					IO::select(nil, nil, nil, 0.10)
					retry

			# Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
			rescue ::Exception => e
				if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
					IO::select( [ ssl ], nil, nil, 0.10 )
					retry
				end

				if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
					IO::select( nil, [ ssl ], nil, 0.10 )
					retry
				end

				raise e
			end
		end

		sock.extend(Rex::Socket::SslTcp)
		sock.sslsock = ssl
		sock.sslctx  = self.sslctx

		return sock

	rescue ::OpenSSL::SSL::SSLError
		sock.close
		nil
	end
end

#allow_nonblock?(sock = self.sock) ⇒ Boolean

This flag determines whether to use the non-blocking openssl API calls when they are available. This is still buggy on Linux/Mac OS X, but is required on Windows

Returns:

  • (Boolean)


163
164
165
166
167
168
169
# File 'lib/rex/socket/ssl_tcp_server.rb', line 163

def allow_nonblock?(sock=self.sock)
	avail = sock.respond_to?(:accept_nonblock)
	if avail and Rex::Compat.is_windows
		return true
	end
	false
end

#initsock(params = nil) ⇒ Object

Raises:



49
50
51
52
53
# File 'lib/rex/socket/ssl_tcp_server.rb', line 49

def initsock(params = nil)
	raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
	self.sslctx  = makessl(params.ssl_cert)
	super
end

#makessl(ssl_cert = nil) ⇒ Object

Create a new ssl context. If ssl_cert is not given, generates a new key and a leaf certificate with random values.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rex/socket/ssl_tcp_server.rb', line 106

def makessl(ssl_cert=nil)

	if ssl_cert
		cert = OpenSSL::X509::Certificate.new(ssl_cert)
		key = OpenSSL::PKey::RSA.new(ssl_cert)
	else
		key = OpenSSL::PKey::RSA.new(1024){ }
		cert = OpenSSL::X509::Certificate.new
		cert.version = 2
		cert.serial = rand(0xFFFFFFFF)
		# name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
		subject = OpenSSL::X509::Name.new([
				["C","US"],
				['ST', Rex::Text.rand_state()],
				["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
				["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
				["CN", Rex::Text.rand_hostname],
			])
		issuer = OpenSSL::X509::Name.new([
				["C","US"],
				['ST', Rex::Text.rand_state()],
				["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
				["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
				["CN", Rex::Text.rand_hostname],
			])

		cert.subject = subject
		cert.issuer = issuer
		cert.not_before = Time.now - (3600 * 365)
		cert.not_after = Time.now + (3600 * 365)
		cert.public_key = key.public_key
		ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
		cert.extensions = [
			ef.create_extension("basicConstraints","CA:FALSE"),
			ef.create_extension("subjectKeyIdentifier","hash"),
			ef.create_extension("extendedKeyUsage","serverAuth"),
			ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
		]
		ef.issuer_certificate = cert
		cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
		cert.sign(key, OpenSSL::Digest::SHA1.new)
	end

	ctx = OpenSSL::SSL::SSLContext.new()
	ctx.key = key
	ctx.cert = cert

	ctx.session_id_context = Rex::Text.rand_text(16)

	return ctx
end