From f76e7d307d26011357ac54eb1ac32823c951e8f9 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 3 Jun 2005 22:51:09 +0000 Subject: [PATCH] SSL class git-svn-id: file:///home/svn/incoming/trunk@2551 4d416f70-5f16-0410-b530-b9f4589650da --- lib/rex.rb.ts.rb | 2 + lib/rex/io/stream.rb | 2 +- lib/rex/socket/comm/local.rb | 8 +++- lib/rex/socket/parameters.rb | 14 +++++- lib/rex/socket/ssl_tcp.rb | 84 +++++++++++++++++++++++++++++++++ lib/rex/socket/ssl_tcp.rb.ut.rb | 35 ++++++++++++++ lib/rex/socket/tcp.rb | 8 ---- 7 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 lib/rex/socket/ssl_tcp.rb create mode 100644 lib/rex/socket/ssl_tcp.rb.ut.rb diff --git a/lib/rex.rb.ts.rb b/lib/rex.rb.ts.rb index 5124f1fd90..4f7e1385fc 100644 --- a/lib/rex.rb.ts.rb +++ b/lib/rex.rb.ts.rb @@ -4,6 +4,7 @@ require 'test/unit' require 'Rex' require 'Rex/Socket.rb.ut' require 'Rex/Socket/Tcp.rb.ut' +require 'Rex/Socket/SslTcp.rb.ut' require 'Rex/Socket/TcpServer.rb.ut' require 'Rex/Socket/Parameters.rb.ut' require 'Rex/Socket/Comm/Local.rb.ut' @@ -15,6 +16,7 @@ class Rex::TestSuite suite << Rex::Socket::UnitTest.suite suite << Rex::Socket::Parameters::UnitTest.suite suite << Rex::Socket::Tcp::UnitTest.suite + suite << Rex::Socket::SslTcp::UnitTest.suite suite << Rex::Socket::TcpServer::UnitTest.suite suite << Rex::Socket::Comm::Local::UnitTest.suite diff --git a/lib/rex/io/stream.rb b/lib/rex/io/stream.rb index 939a6eedb5..2a4a8c263a 100644 --- a/lib/rex/io/stream.rb +++ b/lib/rex/io/stream.rb @@ -147,7 +147,7 @@ module Stream while (has_read_data?(ltimeout)) temp = read(def_block_size) - break if (temp.empty?) + break if (temp == nil or temp.empty?) buf += temp lps += 1 diff --git a/lib/rex/socket/comm/local.rb b/lib/rex/socket/comm/local.rb index 3d82eef516..fb4b29900d 100644 --- a/lib/rex/socket/comm/local.rb +++ b/lib/rex/socket/comm/local.rb @@ -55,7 +55,13 @@ class Rex::Socket::Comm::Local case param.proto when 'tcp' - return Rex::Socket::Tcp.new(sock, param) + klass = Rex::Socket::Tcp + + if (param.ssl) + klass = Rex::Socket::SslTcp + end + + return klass.new(sock, param) end end end diff --git a/lib/rex/socket/parameters.rb b/lib/rex/socket/parameters.rb index 9c03c7b6fe..779a4ea114 100644 --- a/lib/rex/socket/parameters.rb +++ b/lib/rex/socket/parameters.rb @@ -58,11 +58,17 @@ class Rex::Socket::Parameters end if (hash['Bare']) - self.bare = true + self.bare = hash['Bare'] else self.bare = false end + if (hash['SSL']) + self.ssl = hash['SSL'] + else + self.ssl = false + end + # The protocol this socket will be using if (hash['Proto']) self.proto = hash['Proto'].downcase @@ -106,6 +112,10 @@ class Rex::Socket::Parameters return (bare == true) end + def ssl? + return ssl + end + ## # # Attributes @@ -115,7 +125,7 @@ class Rex::Socket::Parameters attr_accessor :peerhost, :peerport attr_accessor :localhost, :localport attr_accessor :proto, :server, :comm - attr_accessor :retries, :bare + attr_accessor :retries, :bare, :ssl ## # diff --git a/lib/rex/socket/ssl_tcp.rb b/lib/rex/socket/ssl_tcp.rb new file mode 100644 index 0000000000..14e7539c36 --- /dev/null +++ b/lib/rex/socket/ssl_tcp.rb @@ -0,0 +1,84 @@ +require 'openssl' +require 'Rex/Socket' +require 'Rex/IO/Stream' + +### +# +# SslTcp +# --- +# +# This class provides methods for interacting with an SSL TCP client connection. +# +### +class Rex::Socket::SslTcp < Rex::Socket::Tcp + + ## + # + # Factory + # + ## + + # + # Set the SSL flag to true and call the base class's create_param routine. + # + def self.create_param(param) + param.ssl = true + + super(param) + end + + ## + # + # Class initialization + # + ## + + def initialize(sock, params = nil) + super + + # Build the SSL connection + self.sslctx = OpenSSL::SSL::SSLContext.new + self.sslsock = OpenSSL::SSL::SSLSocket.new(sock, self.sslctx) + self.sslsock.sync_close = true + self.sslsock.connect + end + + ## + # + # Stream mixin implementations + # + ## + + def write(buf, opts = {}) + return sslsock.write(buf) + end + + def read(length = nil, opts = {}) + length = 16384 unless length + + begin + return sslsock.read(length) + rescue EOFError + return nil + end + end + + def shutdown(how = SHUT_RDWR) + return (sock.shutdown(how) == 0) + end + + def close + sslsock.close + end + + def has_read_data?(timeout = nil) + timeout = timeout.to_i if (timeout) + + return (select([ poll_fd ], nil, nil, timeout) != nil) + end + +protected + + attr_accessor :sslsock, :sslctx + +end diff --git a/lib/rex/socket/ssl_tcp.rb.ut.rb b/lib/rex/socket/ssl_tcp.rb.ut.rb new file mode 100644 index 0000000000..d2f3c67bd1 --- /dev/null +++ b/lib/rex/socket/ssl_tcp.rb.ut.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby + +$:.unshift(File.join('..', '..', File.dirname(__FILE__))) + +require 'test/unit' +require 'Rex/Socket/SslTcp' + +class Rex::Socket::SslTcp::UnitTest < Test::Unit::TestCase + + def test_ssltcp + + # Create an SslTcp instance + t = nil + assert_nothing_raised { + t = Rex::Socket::SslTcp.create( + 'PeerHost' => 'www.google.com', + 'PeerPort' => 443) + } + assert_kind_of(Rex::Socket::SslTcp, t, "valid ssl tcp") + + # Send a HEAD request and make sure we get some kind of response + head_request = "HEAD / HTTP/1.0\r\n\r\n" + + assert_equal(true, t.put(head_request), "sending head request") + + head_response = "" + + assert_nothing_raised { + head_response = t.get(nil) || "" + } + + assert_match(/^HTTP\/1./, head_response, "valid head response") + end + +end diff --git a/lib/rex/socket/tcp.rb b/lib/rex/socket/tcp.rb index bc3703cc09..b1be9cea6a 100644 --- a/lib/rex/socket/tcp.rb +++ b/lib/rex/socket/tcp.rb @@ -34,14 +34,6 @@ class Rex::Socket::Tcp < Rex::Socket # ## - def blocking=(tf) - return tf # FIXME - end - - def blocking - return true # FIXME - end - def write(buf, opts = {}) return sock.syswrite(buf) end