ruby-tls 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/EM-LICENSE +60 -0
- data/README.md +69 -0
- data/Rakefile +19 -0
- data/ext/Rakefile +18 -0
- data/ext/tls/page.cpp +107 -0
- data/ext/tls/page.h +62 -0
- data/ext/tls/ssl.cpp +591 -0
- data/ext/tls/ssl.h +130 -0
- data/lib/ruby-tls.rb +7 -0
- data/lib/ruby-tls/connection.rb +121 -0
- data/lib/ruby-tls/ext.rb +32 -0
- data/lib/ruby-tls/version.rb +3 -0
- data/ruby-tls.gemspec +32 -0
- data/spec/client.crt +31 -0
- data/spec/client.key +51 -0
- data/spec/comms_spec.rb +147 -0
- data/spec/verify_spec.rb +118 -0
- metadata +125 -0
data/ext/tls/ssl.h
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id$
|
4
|
+
|
5
|
+
File: ssl.h
|
6
|
+
Date: 30Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: blackhedd
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of either: 1) the GNU General Public License
|
13
|
+
as published by the Free Software Foundation; either version 2 of the
|
14
|
+
License, or (at your option) any later version; or 2) Ruby's License.
|
15
|
+
|
16
|
+
See the file COPYING for complete licensing information.
|
17
|
+
|
18
|
+
*****************************************************************************/
|
19
|
+
|
20
|
+
|
21
|
+
#ifndef __SslBox__H_
|
22
|
+
#define __SslBox__H_
|
23
|
+
|
24
|
+
#include <iostream>
|
25
|
+
#include <string>
|
26
|
+
|
27
|
+
#include <openssl/ssl.h>
|
28
|
+
#include <openssl/err.h>
|
29
|
+
|
30
|
+
#include <assert.h>
|
31
|
+
|
32
|
+
#include "page.h"
|
33
|
+
|
34
|
+
using namespace std;
|
35
|
+
|
36
|
+
|
37
|
+
/******************
|
38
|
+
class SslContext_t
|
39
|
+
******************/
|
40
|
+
|
41
|
+
class SslContext_t
|
42
|
+
{
|
43
|
+
public:
|
44
|
+
SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile);
|
45
|
+
virtual ~SslContext_t();
|
46
|
+
|
47
|
+
private:
|
48
|
+
static bool bLibraryInitialized;
|
49
|
+
|
50
|
+
private:
|
51
|
+
bool bIsServer;
|
52
|
+
SSL_CTX *pCtx;
|
53
|
+
|
54
|
+
EVP_PKEY *PrivateKey;
|
55
|
+
X509 *Certificate;
|
56
|
+
|
57
|
+
friend class SslBox_t;
|
58
|
+
};
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
typedef struct tls_state_s tls_state_t;
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
/**************
|
68
|
+
class SslBox_t
|
69
|
+
**************/
|
70
|
+
|
71
|
+
class SslBox_t
|
72
|
+
{
|
73
|
+
public:
|
74
|
+
SslBox_t (tls_state_t *tls_state, bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer);
|
75
|
+
virtual ~SslBox_t();
|
76
|
+
|
77
|
+
int PutPlaintext (const char*, int);
|
78
|
+
int GetPlaintext (char*, int);
|
79
|
+
|
80
|
+
bool PutCiphertext (const char*, int);
|
81
|
+
bool CanGetCiphertext();
|
82
|
+
int GetCiphertext (char*, int);
|
83
|
+
bool IsHandshakeCompleted() { return bHandshakeCompleted; }
|
84
|
+
|
85
|
+
X509 *GetPeerCert();
|
86
|
+
|
87
|
+
void Shutdown();
|
88
|
+
|
89
|
+
protected:
|
90
|
+
SslContext_t *Context;
|
91
|
+
|
92
|
+
bool bIsServer;
|
93
|
+
bool bHandshakeCompleted;
|
94
|
+
bool bVerifyPeer;
|
95
|
+
SSL *pSSL;
|
96
|
+
BIO *pbioRead;
|
97
|
+
BIO *pbioWrite;
|
98
|
+
|
99
|
+
PageList OutboundQ;
|
100
|
+
};
|
101
|
+
|
102
|
+
|
103
|
+
typedef void (*ssl_close_cb)(const tls_state_t*);
|
104
|
+
typedef int (*ssl_verify_cb)(const tls_state_t*, const char *cert);
|
105
|
+
typedef void (*ssl_dispatch_cb)(const tls_state_t*, const char *buffer, int size);
|
106
|
+
typedef void (*ssl_transmit_cb)(const tls_state_t*, const char *buffer, int size);
|
107
|
+
typedef void (*ssl_handshake_cb)(const tls_state_t*);
|
108
|
+
|
109
|
+
struct tls_state_s {
|
110
|
+
int handshake_signaled;
|
111
|
+
|
112
|
+
ssl_close_cb close_cb;
|
113
|
+
ssl_verify_cb verify_cb;
|
114
|
+
ssl_dispatch_cb dispatch_cb;
|
115
|
+
ssl_transmit_cb transmit_cb;
|
116
|
+
ssl_handshake_cb handshake_cb;
|
117
|
+
|
118
|
+
SslBox_t* SslBox;
|
119
|
+
};
|
120
|
+
|
121
|
+
|
122
|
+
extern "C" int ssl_verify_wrapper(int preverify_ok, X509_STORE_CTX *ctx);
|
123
|
+
|
124
|
+
extern "C" void start_tls(tls_state_t *tls_state, bool bIsServer, const char *PrivateKeyFilename, const char *CertChainFilename, bool bSslVerifyPeer);
|
125
|
+
extern "C" void decrypt_data(tls_state_t *tls_state, const char *buffer, int size);
|
126
|
+
extern "C" void encrypt_data(tls_state_t *tls_state, const char *data, int length);
|
127
|
+
extern "C" X509 *get_peer_cert(tls_state_t *tls_state);
|
128
|
+
|
129
|
+
|
130
|
+
#endif // __SslBox__H_
|
data/lib/ruby-tls.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
|
2
|
+
module RubyTls
|
3
|
+
class Connection
|
4
|
+
CALLBACKS = [:close_cb, :verify_cb, :dispatch_cb, :transmit_cb, :handshake_cb]
|
5
|
+
|
6
|
+
#
|
7
|
+
# Initializes the State instance.
|
8
|
+
#
|
9
|
+
def initialize(callback_obj = nil)
|
10
|
+
@state = ::RubyTls::State.new
|
11
|
+
@callbacks = {} # so GC doesn't clean them up on java
|
12
|
+
@started = false
|
13
|
+
|
14
|
+
if not callback_obj.nil?
|
15
|
+
CALLBACKS.each do |callback|
|
16
|
+
self.__send__(callback, &callback_obj.method(callback)) if callback_obj.respond_to? callback
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
yield self if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
def close_cb(&block)
|
24
|
+
cb = Callback.new(@callbacks, &block)
|
25
|
+
@callbacks[:close_cb] = cb
|
26
|
+
@state[:close_cb] = cb
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_cb
|
30
|
+
cb = ::FFI::Function.new(:int, [::RubyTls::State.ptr, :string]) do |state, cert|
|
31
|
+
begin
|
32
|
+
yield(cert) == true ? 1 : 0
|
33
|
+
rescue
|
34
|
+
# TODO:: Provide some debugging output
|
35
|
+
0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@callbacks[:verify_cb] = cb
|
39
|
+
@state[:verify_cb] = cb
|
40
|
+
end
|
41
|
+
|
42
|
+
def dispatch_cb(&block)
|
43
|
+
cb = DataCallback.new(@callbacks, &block)
|
44
|
+
@callbacks[:dispatch_cb] = cb
|
45
|
+
@state[:dispatch_cb] = cb
|
46
|
+
end
|
47
|
+
|
48
|
+
def transmit_cb(&block)
|
49
|
+
cb = DataCallback.new(@callbacks, &block)
|
50
|
+
@callbacks[:transmit_cb] = cb
|
51
|
+
@state[:transmit_cb] = cb
|
52
|
+
end
|
53
|
+
|
54
|
+
def handshake_cb(&block)
|
55
|
+
cb = Callback.new(@callbacks, &block)
|
56
|
+
@callbacks[:handshake_cb] = cb
|
57
|
+
@state[:handshake_cb] = cb
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def start(args = {})
|
62
|
+
return if @started
|
63
|
+
|
64
|
+
server, priv_key, cert_chain, verify_peer = args.values_at(:server, :private_key_file, :cert_chain_file, :verify_peer)
|
65
|
+
[priv_key, cert_chain].each do |file|
|
66
|
+
next if file.nil? or file.empty?
|
67
|
+
raise FileNotFoundException,
|
68
|
+
"Could not find #{file} to start tls" unless File.exists? file
|
69
|
+
end
|
70
|
+
|
71
|
+
@started = true
|
72
|
+
::RubyTls.start_tls(@state, server || false, priv_key || '', cert_chain || '', verify_peer || !!@callbacks[:verify_cb])
|
73
|
+
end
|
74
|
+
|
75
|
+
def encrypt(data)
|
76
|
+
return unless @started
|
77
|
+
::RubyTls.encrypt_data(@state, data, data.length)
|
78
|
+
end
|
79
|
+
|
80
|
+
def decrypt(data)
|
81
|
+
return unless @started
|
82
|
+
::RubyTls.decrypt_data(@state, data, data.length)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
|
89
|
+
class Callback < ::FFI::Function
|
90
|
+
#
|
91
|
+
# Creates a new Parser callback.
|
92
|
+
#
|
93
|
+
def self.new(callbacks)
|
94
|
+
super(:void, [::RubyTls::State.ptr]) do |state|
|
95
|
+
begin
|
96
|
+
yield
|
97
|
+
rescue => e
|
98
|
+
# shutdown the connection on error
|
99
|
+
# TODO:: Provide some debugging output
|
100
|
+
callbacks[:close_cb].call state
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class DataCallback < ::FFI::Function
|
107
|
+
def self.new(callbacks)
|
108
|
+
super(:void, [::RubyTls::State.ptr, :pointer, :int]) do |state, buffer, length|
|
109
|
+
begin
|
110
|
+
data = buffer.get_bytes(0, length)
|
111
|
+
yield(data)
|
112
|
+
rescue => e
|
113
|
+
# shutdown the connection on error
|
114
|
+
# TODO:: Provide some debugging output
|
115
|
+
callbacks[:close_cb].call state
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/ruby-tls/ext.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'ffi-compiler/loader'
|
3
|
+
|
4
|
+
module RubyTls
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib FFI::Compiler::Loader.find('ruby-tls-ext')
|
7
|
+
|
8
|
+
|
9
|
+
callback :ssl_close_cb, [:pointer], :void
|
10
|
+
callback :ssl_verify_cb, [:pointer, :string], :int
|
11
|
+
callback :ssl_dispatch_cb, [:pointer, :pointer, :int], :void
|
12
|
+
callback :ssl_transmit_cb, [:pointer, :pointer, :int], :void
|
13
|
+
callback :ssl_handshake_cb, [:pointer], :void
|
14
|
+
|
15
|
+
class State < FFI::Struct
|
16
|
+
layout :handshake_sig, :int,
|
17
|
+
|
18
|
+
:close_cb, :ssl_close_cb,
|
19
|
+
:verify_cb, :ssl_verify_cb, # Optional
|
20
|
+
:dispatch_cb, :ssl_dispatch_cb,
|
21
|
+
:transmit_cb, :ssl_transmit_cb,
|
22
|
+
:handshake_cb, :ssl_handshake_cb, # Optional unless first to send data
|
23
|
+
|
24
|
+
:ssl_box, :pointer
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
attach_function :start_tls, [State.by_ref, :bool, :string, :string, :bool], :void, :blocking => true
|
29
|
+
attach_function :decrypt_data, [State.by_ref, :pointer, :int], :void, :blocking => true
|
30
|
+
attach_function :encrypt_data, [State.by_ref, :pointer, :int], :void, :blocking => true
|
31
|
+
#attach_function :get_peer_cert, [], :int, :blocking => true
|
32
|
+
end
|
data/ruby-tls.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ruby-tls/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ruby-tls"
|
7
|
+
s.version = RubyTls::VERSION
|
8
|
+
s.authors = ["Stephen von Takach"]
|
9
|
+
s.email = ["steve@cotag.me"]
|
10
|
+
s.license = 'MIT'
|
11
|
+
s.homepage = "https://github.com/cotag/ruby-tls"
|
12
|
+
s.summary = "Abstract TLS for Ruby"
|
13
|
+
s.description = <<-EOF
|
14
|
+
Allows transport layers outside Ruby TCP be secured.
|
15
|
+
EOF
|
16
|
+
|
17
|
+
|
18
|
+
s.add_dependency 'ffi-compiler', '>= 0.0.2'
|
19
|
+
s.add_dependency 'rake'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'yard'
|
23
|
+
|
24
|
+
|
25
|
+
s.files = Dir["{lib}/**/*"] + %w(Rakefile ruby-tls.gemspec README.md EM-LICENSE)
|
26
|
+
s.files += ["ext/tls/ssl.cpp", "ext/tls/ssl.h", "ext/tls/page.cpp", "ext/tls/page.h"]
|
27
|
+
s.test_files = Dir["spec/**/*"]
|
28
|
+
s.extra_rdoc_files = ["README.md"]
|
29
|
+
|
30
|
+
s.extensions << "ext/Rakefile"
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
end
|
data/spec/client.crt
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIFRDCCAywCAQEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCRU0xFTATBgNV
|
3
|
+
BAgTDEV2ZW50TWFjaGluZTEVMBMGA1UEChMMRXZlbnRNYWNoaW5lMRQwEgYDVQQL
|
4
|
+
EwtEZXZlbG9wbWVudDEVMBMGA1UEAxMMRXZlbnRNYWNoaW5lMB4XDTA5MDMyOTAy
|
5
|
+
MzE0NloXDTEwMDMyOTAyMzE0NlowaDELMAkGA1UEBhMCRU0xFTATBgNVBAgTDEV2
|
6
|
+
ZW50TWFjaGluZTEVMBMGA1UEChMMRXZlbnRNYWNoaW5lMRQwEgYDVQQLEwtEZXZl
|
7
|
+
bG9wbWVudDEVMBMGA1UEAxMMRXZlbnRNYWNoaW5lMIICIjANBgkqhkiG9w0BAQEF
|
8
|
+
AAOCAg8AMIICCgKCAgEAv1FSOIX1z7CQtVBFlrB0A3/V29T+22STKKmiRWYkKL5b
|
9
|
+
+hkrp9IZ5J4phZHgUVM2VDPOO2Oc2PU6dlGGZISg+UPERunTogxQKezCV0vcE9cK
|
10
|
+
OwzxCFDRvv5rK8aKMscfBLbNKocAXywuRRQmdxPiVRzbyPrl+qCr/EDLXAX3D77l
|
11
|
+
S8n2AwDg19VyI+IgFUE+Dy5e1eLoY6nV+Mq+vNXdn3ttF3t+ngac5pj5Q9h+pD5p
|
12
|
+
67baDHSnf/7cy2fa/LKrLolVHQR9G2K6cEfeM99NtcsMbkoPs4iI3FA05OVTQHXg
|
13
|
+
C8C8cRxrb9APl95I/ep65OIaCJgcdYxJ3QD3qOtQo6/NQsGnjbyiUxaEpjfqyT1N
|
14
|
+
uzWD81Q8uXGNS8yD6dDynt/lseBjyp2nfC3uQ5fY18VdIcu0MJ9pezBUKrNuhlsy
|
15
|
+
XXEZ2DXj4sY8QOvIcBqSB/zmS1nGEK55xrtkaiaNrY8fe8wRVpcPLxy+P225NFw+
|
16
|
+
B69FJRA0Lj6Jt9BM4hV/3MSIEWwTVhuw4E02ywDYTzz1wq3ITf0tsbIPn0hXQMxD
|
17
|
+
ohhAoKioM6u+yHtqsxD0eYaAWmHTVn5oDvOSGpvCpBfWHyA7FP5UQak0fKABEAgK
|
18
|
+
iQYEnb294AXwXymJttfGTIV/Ne4tLN5dIpNma8UO8rlThlcr6xnTQDbR3gkTDRsC
|
19
|
+
AwEAATANBgkqhkiG9w0BAQUFAAOCAgEAj7J8fy1LUWoVWnrXDAC9jwJ1nI/YjoSU
|
20
|
+
6ywke3o04+nZC5S+dPnuVy+HAwsU940CoNvP6RStI/bH6JL+NIqEFmwM3M8xIEWV
|
21
|
+
MYVPkfvQUxxGvDnaY7vv93u+6Q77HV3qlhAQBHChyuXyO7TG3+WzsiT9AnBNtAP0
|
22
|
+
4jClt5kCAQXLO/p0SFEZQ8Ru9SM8d1i73Z0VDVzs8jYWlBhiherSgbw1xK4wBOpJ
|
23
|
+
43XmjZsBSrDpiAXd07Ak3UL2GjfT7eStgebL3UIe39ThE/s/+l43bh0M6WbOBvyQ
|
24
|
+
i/rZ50kd1GvN0xnZhtv07hIJWO85FGWi7Oet8AzdUZJ17v1Md/f2vdhPVTFN9q+w
|
25
|
+
mQ6LxjackqCvaJaQfBEbqsn2Tklxk4tZuDioiQbOElT2e6vljQVJWIfNx38Ny2LM
|
26
|
+
aiXQPQu+4CI7meAh5gXM5nyJGbZvRPsxj89CqYzyHCYs5HBP3AsviBvn26ziOF+c
|
27
|
+
544VmHd9HkIv8UTC29hh+R64RlgMQQQdaXFaUrFPTs/do0k8n/c2bPc0iTdfi5Q2
|
28
|
+
gq6Vi8q6Ay5wGgTtRRbn/mWKuCFjEh94z6pF9Xr06NX0PuEOdf+Ls9vI5vz6G0w6
|
29
|
+
0Li7devEN7EKBY+7Mcjg918yq9i5tEiMkUgT68788t3fTC+4iUQ5fDtdrHsaOlIR
|
30
|
+
8bs/XQVNE/s=
|
31
|
+
-----END CERTIFICATE-----
|
data/spec/client.key
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
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
|
51
|
+
-----END RSA PRIVATE KEY-----
|
data/spec/comms_spec.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'ruby-tls'
|
2
|
+
|
3
|
+
describe RubyTls do
|
4
|
+
|
5
|
+
|
6
|
+
describe RubyTls::State do
|
7
|
+
before :each do
|
8
|
+
@client = RubyTls::State.new
|
9
|
+
@server = RubyTls::State.new
|
10
|
+
|
11
|
+
@server_started = false
|
12
|
+
@server_stop = false
|
13
|
+
@client_stop = false
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
it "should be able to send and receive encrypted comms" do
|
18
|
+
@server_data = []
|
19
|
+
@client_data = []
|
20
|
+
@interleaved = []
|
21
|
+
|
22
|
+
|
23
|
+
@client[:close_cb] = proc {
|
24
|
+
@client_data << 'client stopped'
|
25
|
+
@interleaved << 'client stopped'
|
26
|
+
@client_stop = true
|
27
|
+
}
|
28
|
+
@client[:dispatch_cb] = proc { |state, data, len|
|
29
|
+
@client_data << data.read_string(len)
|
30
|
+
@interleaved << data.read_string(len)
|
31
|
+
}
|
32
|
+
@client[:transmit_cb] = proc { |state, data, len|
|
33
|
+
if not @server_started
|
34
|
+
@server_started = true
|
35
|
+
RubyTls.start_tls(@server, true, '', '', false)
|
36
|
+
end
|
37
|
+
data = data.get_bytes(0, len)
|
38
|
+
RubyTls.decrypt_data(@server, data, data.length) unless @client_stop
|
39
|
+
}
|
40
|
+
@client[:handshake_cb] = proc { |state|
|
41
|
+
@client_data << 'ready'
|
42
|
+
@interleaved << 'client ready'
|
43
|
+
|
44
|
+
sending = 'client request'
|
45
|
+
RubyTls.encrypt_data(@client, sending, sending.length) unless @client_stop
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
@server[:close_cb] = proc {
|
50
|
+
@server_data << 'server stop'
|
51
|
+
@interleaved << 'server stop'
|
52
|
+
@server_stop = true
|
53
|
+
}
|
54
|
+
@server[:dispatch_cb] = proc { |state, data, len|
|
55
|
+
@server_data << data.read_string(len)
|
56
|
+
@interleaved << data.read_string(len)
|
57
|
+
|
58
|
+
sending = 'server response'
|
59
|
+
RubyTls.encrypt_data(@server, sending, sending.length) unless @server_stop
|
60
|
+
}
|
61
|
+
@server[:transmit_cb] = proc { |state, data, len|
|
62
|
+
data = data.get_bytes(0, len)
|
63
|
+
RubyTls.decrypt_data(@client, data, data.length) unless @server_stop
|
64
|
+
}
|
65
|
+
@server[:handshake_cb] = proc { |state|
|
66
|
+
@server_data << 'ready'
|
67
|
+
@interleaved << 'server ready'
|
68
|
+
}
|
69
|
+
|
70
|
+
RubyTls.start_tls(@client, false, '', '', false)
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
@client_data.should == ['ready', 'server response']
|
75
|
+
@server_data.should == ['ready', 'client request']
|
76
|
+
@interleaved.should == ['server ready', 'client ready', 'client request', 'server response']
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe RubyTls::Connection do
|
81
|
+
before :each do
|
82
|
+
@client = RubyTls::Connection.new
|
83
|
+
@server = RubyTls::Connection.new
|
84
|
+
|
85
|
+
@server_started = false
|
86
|
+
@server_stop = false
|
87
|
+
@client_stop = false
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be able to send and receive encrypted comms" do
|
91
|
+
@server_data = []
|
92
|
+
@client_data = []
|
93
|
+
@interleaved = []
|
94
|
+
|
95
|
+
|
96
|
+
@client.close_cb do
|
97
|
+
@client_data << 'client stopped'
|
98
|
+
@interleaved << 'client stopped'
|
99
|
+
@client_stop = true
|
100
|
+
end
|
101
|
+
@client.dispatch_cb do |data|
|
102
|
+
@client_data << data
|
103
|
+
@interleaved << data
|
104
|
+
end
|
105
|
+
@client.transmit_cb do |data|
|
106
|
+
if not @server_started
|
107
|
+
@server_started = true
|
108
|
+
@server.start(:server => true)
|
109
|
+
end
|
110
|
+
@server.decrypt(data) unless @client_stop
|
111
|
+
end
|
112
|
+
@client.handshake_cb do
|
113
|
+
@client_data << 'ready'
|
114
|
+
@interleaved << 'client ready'
|
115
|
+
|
116
|
+
@client.encrypt('client request') unless @client_stop
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
@server.close_cb do
|
121
|
+
@server_data << 'server stop'
|
122
|
+
@interleaved << 'server stop'
|
123
|
+
@server_stop = true
|
124
|
+
end
|
125
|
+
@server.dispatch_cb do |data|
|
126
|
+
@server_data << data
|
127
|
+
@interleaved << data
|
128
|
+
@server.encrypt('server response') unless @server_stop
|
129
|
+
end
|
130
|
+
@server.transmit_cb do |data|
|
131
|
+
@client.decrypt(data) unless @server_stop
|
132
|
+
end
|
133
|
+
@server.handshake_cb do
|
134
|
+
@server_data << 'ready'
|
135
|
+
@interleaved << 'server ready'
|
136
|
+
end
|
137
|
+
|
138
|
+
@client.start
|
139
|
+
|
140
|
+
|
141
|
+
@client_data.should == ['ready', 'server response']
|
142
|
+
@server_data.should == ['ready', 'client request']
|
143
|
+
@interleaved.should == ['server ready', 'client ready', 'client request', 'server response']
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|