about summary refs log tree commit homepage
path: root/test/test_ssl.rb
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2014-11-29 04:08:54 +0000
committerEric Wong <e@80x24.org>2014-12-02 02:10:12 +0000
commit65a903181cd5cdd78b4df7eacc1c574f0ef8e95c (patch)
tree2887d483c14b975bdab99e6150e8a4bdf6a4e619 /test/test_ssl.rb
parenta1dba8aa91a533870c44ec0b695391f16be9a71f (diff)
downloadyahns-65a903181cd5cdd78b4df7eacc1c574f0ef8e95c.tar.gz
The current CA model and code quality of OpenSSL have long put me off
from supporting TLS; however but efforts such as "Let's Encrypt"
and the fallout from Heartbleed give me hope for the future.

This implements, as much as possible, a "hands-off" approach to TLS
support via OpenSSL.  This implementation allows us to shift
responsibility away from us to users and upstreams (the Ruby 'openssl'
extension maintainers, software packagers, and OpenSSL project itself).

This is also perhaps the easiest way for now for us, while being most
powerful for users.  It requires users to configure their own OpenSSL
context object which we'll use as-is.

This context object is used as the :ssl_ctx parameter to the "listen"
directive in the yahns configuration file:

	require 'openssl' # we will not do this for the user, even
        ctx = OpenSSL::SSL::SSLContext.new
	# user must configure ctx here...
	listen 443, ssl_ctx: ctx

This way, in case we support GnuTLS or other TLS libraries, there'll
be less confusion as to what a user is actually using.

Note: this feature requires Ruby 2.1 and later for non-kgio
{read,write}_nonblock(.. exception: false) support.
Diffstat (limited to 'test/test_ssl.rb')
-rw-r--r--test/test_ssl.rb66
1 files changed, 66 insertions, 0 deletions
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
new file mode 100644
index 0000000..890cf58
--- /dev/null
+++ b/test/test_ssl.rb
@@ -0,0 +1,66 @@
+# Copyright (C) 2014,  all contributors <yahns-public@yhbt.net>
+# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require_relative 'server_helper'
+require 'openssl'
+class TestSSL < Testcase
+  ENV["N"].to_i > 1 and parallelize_me!
+  include ServerHelper
+
+  # copied from test/openssl/utils.rb in Ruby:
+
+  TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
+pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
+AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
+-----END DH PARAMETERS-----
+  _end_of_pem_
+
+  TEST_KEY_DH1024.priv_key = OpenSSL::BN.new("48561834C67E65FFD2A9B47F41" \
+     "E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2" \
+     "CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB4" \
+     "51E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672E" \
+     "EF3EF13AB47A15275FC2836F3AC74CEA", 16)
+
+  def setup
+    server_helper_setup
+  end
+
+  def teardown
+    server_helper_teardown
+  end
+
+  def ssl_client(host, port)
+    ctx = OpenSSL::SSL::SSLContext.new
+    ctx.ciphers = "ADH"
+    s = TCPSocket.new(host, port)
+    ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
+    ssl.connect
+    ssl.sync_close = true
+    ssl
+  end
+
+  def test_ssl_basic
+    err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
+    host, port = @srv.addr[3], @srv.addr[1]
+    ctx = OpenSSL::SSL::SSLContext.new
+    ctx.ciphers = "ADH"
+    ctx.tmp_dh_callback = proc { TEST_KEY_DH1024 }
+
+    pid = mkserver(cfg) do
+      cfg.instance_eval do
+        ru = lambda { |_| [ 200, {'Content-Length'=>'2'}, ['HI'] ] }
+        app(:rack, ru) { listen "#{host}:#{port}", ssl_ctx: ctx }
+        logger(Logger.new(err.path))
+      end
+    end
+    client = ssl_client(host, port)
+    client.write("GET / HTTP/1.0\r\n\r\n")
+    head, body = client.read.split("\r\n\r\n", 2)
+    assert_equal "HI", body
+    assert_match %r{\AHTTP/1\.\d 200 OK\r\n}, head
+  ensure
+    client.close if client
+    quit_wait(pid)
+  end
+end if defined?(OpenSSL)