ftw 0.0.41 → 0.0.42
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 +4 -4
- data/lib/ftw/agent.rb +3 -2
- data/lib/ftw/agent/configuration.rb +16 -0
- data/lib/ftw/connection.rb +24 -6
- data/lib/ftw/protocol.rb +1 -1
- data/lib/ftw/server.rb +22 -9
- data/lib/ftw/version.rb +1 -1
- data/test/ftw/protocol.rb +13 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33fab2173e9d5a55d01c5be096be99b4a6e4c9b6
|
4
|
+
data.tar.gz: 2d5d057c20fc4bec7705143ba4010d9162623d1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cd81a35b4289d5c5f3c7aa566d4de5e4192ad2ac8343d7c74d3a13fc695ad6c719254395375448262da6ee13697ce2a066f63eaab32c069e185a4b7d8ee2c9c
|
7
|
+
data.tar.gz: 437f27db19fd9616dcec6db39d97f02e336ab0d5edeaebff14e785a70d85988a41a8a72bbd2075ccbbd2f4ce9532321277b49730a49894bd1e87681ca5c6eedd
|
data/lib/ftw/agent.rb
CHANGED
@@ -445,8 +445,9 @@ class FTW::Agent
|
|
445
445
|
@logger.error("Error in certificate_verify call", :exception => e)
|
446
446
|
end
|
447
447
|
end
|
448
|
-
|
449
|
-
|
448
|
+
ciphers = SSL_CIPHER_MAP[configuration[SSL_CIPHERS]] || configuration[SSL_CIPHERS]
|
449
|
+
connection.secure(:certificate_store => certificate_store, :verify_callback => verify_callback,
|
450
|
+
:ciphers => ciphers, :version => configuration[SSL_VERSION])
|
450
451
|
end # if secure
|
451
452
|
|
452
453
|
return connection, nil
|
@@ -12,6 +12,20 @@ module FTW::Agent::Configuration
|
|
12
12
|
# SSL: Use the system's global default certs?
|
13
13
|
SSL_USE_DEFAULT_CERTS = "ssl.use-default-certs".freeze
|
14
14
|
|
15
|
+
# SSL cipher strings
|
16
|
+
SSL_CIPHERS = "ssl.ciphers".freeze
|
17
|
+
|
18
|
+
SSL_CIPHER_MAP = {
|
19
|
+
# https://wiki.mozilla.org/Security/Server_Side_TLS
|
20
|
+
"MOZILLA_MODERN" => "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK",
|
21
|
+
"MOZILLA_INTERMEDIATE" => "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA",
|
22
|
+
"MOZILLA_OLD" => "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
|
23
|
+
}
|
24
|
+
|
25
|
+
SSL_CIPHER_DEFAULT = SSL_CIPHER_MAP["MOZILLA_MODERN"]
|
26
|
+
|
27
|
+
SSL_VERSION = "ssl.version"
|
28
|
+
|
15
29
|
private
|
16
30
|
|
17
31
|
# Get the configuration hash
|
@@ -27,6 +41,8 @@ module FTW::Agent::Configuration
|
|
27
41
|
REDIRECTION_LIMIT => 20,
|
28
42
|
SSL_TRUST_STORE => File.join(home, "ssl-trust.db"),
|
29
43
|
SSL_USE_DEFAULT_CERTS => true,
|
44
|
+
SSL_CIPHERS => SSL_CIPHER_DEFAULT,
|
45
|
+
SSL_VERSION => "TLSv1.1",
|
30
46
|
}
|
31
47
|
end # def default_configuration
|
32
48
|
|
data/lib/ftw/connection.rb
CHANGED
@@ -40,6 +40,9 @@ class FTW::Connection
|
|
40
40
|
# Secure setup timed out
|
41
41
|
class SecureHandshakeTimeout < StandardError; end
|
42
42
|
|
43
|
+
# Invalid connection configuration
|
44
|
+
class InvalidConfiguration < StandardError; end
|
45
|
+
|
43
46
|
private
|
44
47
|
|
45
48
|
# A new network connection.
|
@@ -315,13 +318,20 @@ class FTW::Connection
|
|
315
318
|
#
|
316
319
|
# * :certificate_store, an OpenSSL::X509::Store
|
317
320
|
# * :timeout, a timeout threshold in seconds.
|
321
|
+
# * :ciphers, an OpenSSL ciphers string, see `openssl ciphers` manual for details.
|
322
|
+
# * :version, any of: SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2
|
323
|
+
#
|
324
|
+
# Notes:
|
325
|
+
# * Version may depend on your platform (openssl compilation settings, JVM
|
326
|
+
# version, export restrictions, etc)
|
318
327
|
def secure(options=nil)
|
319
328
|
# Skip this if we're already secure.
|
320
329
|
return if secured?
|
321
330
|
|
322
331
|
defaults = {
|
323
332
|
:timeout => nil,
|
324
|
-
|
333
|
+
:ciphers => FTW::Agent::Configuration::SSL_CIPHER_MAP["MOZILLA_MODERN"],
|
334
|
+
:version => "TLSv1.1"
|
325
335
|
}
|
326
336
|
settings = defaults.merge(options) unless options.nil?
|
327
337
|
|
@@ -334,7 +344,7 @@ class FTW::Connection
|
|
334
344
|
|
335
345
|
# ruby-core is refusing to patch ruby's default openssl settings to be more
|
336
346
|
# secure, so let's fix that here. The next few lines setting options and
|
337
|
-
# ciphers come from jmhodges proposed patch
|
347
|
+
# ciphers come from jmhodges' proposed patch
|
338
348
|
ssloptions = OpenSSL::SSL::OP_ALL
|
339
349
|
if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
340
350
|
ssloptions &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
|
@@ -342,8 +352,15 @@ class FTW::Connection
|
|
342
352
|
if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
343
353
|
ssloptions |= OpenSSL::SSL::OP_NO_COMPRESSION
|
344
354
|
end
|
355
|
+
# https://github.com/jruby/jruby/issues/1874
|
356
|
+
version = OpenSSL::SSL::SSLContext::METHODS.find { |x| x.to_s.gsub("_",".") == settings[:version] }
|
357
|
+
raise InvalidConfiguration, "Invalid SSL/TLS version '#{settings[:version]}'" if version.nil?
|
358
|
+
sslcontext.ssl_version = version
|
359
|
+
|
360
|
+
# We have to set ciphers *after* setting ssl_version because setting
|
361
|
+
# ssl_version will reset the cipher set.
|
345
362
|
sslcontext.options = ssloptions
|
346
|
-
sslcontext.ciphers =
|
363
|
+
sslcontext.ciphers = settings[:ciphers]
|
347
364
|
|
348
365
|
sslcontext.verify_callback = proc do |*args|
|
349
366
|
@logger.debug("Verify peer via FTW::Connection#secure", :callback => settings[:verify_callback])
|
@@ -351,16 +368,17 @@ class FTW::Connection
|
|
351
368
|
settings[:verify_callback].call(*args)
|
352
369
|
end
|
353
370
|
end
|
354
|
-
sslcontext.cert_store =
|
371
|
+
sslcontext.cert_store = settings[:certificate_store]
|
372
|
+
|
355
373
|
@socket = OpenSSL::SSL::SSLSocket.new(@socket, sslcontext)
|
356
374
|
|
357
375
|
# TODO(sissel): Set up local certificat/key stuff. This is required for
|
358
376
|
# server-side ssl operation, I think.
|
359
377
|
|
360
378
|
if client?
|
361
|
-
do_secure(:connect_nonblock,
|
379
|
+
do_secure(:connect_nonblock, settings[:timeout])
|
362
380
|
else
|
363
|
-
do_secure(:accept_nonblock,
|
381
|
+
do_secure(:accept_nonblock, settings[:timeout])
|
364
382
|
end
|
365
383
|
end # def secure
|
366
384
|
|
data/lib/ftw/protocol.rb
CHANGED
data/lib/ftw/server.rb
CHANGED
@@ -26,6 +26,7 @@ class FTW::Server
|
|
26
26
|
addresses = [addresses] if !addresses.is_a?(Array)
|
27
27
|
dns = FTW::DNS.singleton
|
28
28
|
|
29
|
+
@control_lock = Mutex.new
|
29
30
|
@sockets = {}
|
30
31
|
|
31
32
|
failures = []
|
@@ -78,14 +79,23 @@ class FTW::Server
|
|
78
79
|
failures += local_failures
|
79
80
|
end
|
80
81
|
|
82
|
+
# This allows us to interrupt the #each_connection's select() later
|
83
|
+
# when anyone calls stop()
|
84
|
+
@stopper = IO.pipe
|
85
|
+
|
81
86
|
# Abort if there were failures
|
82
87
|
raise ServerSetupFailure.new(failures) if failures.any?
|
83
88
|
end # def initialize
|
84
89
|
|
85
90
|
# Stop serving.
|
86
91
|
def stop
|
87
|
-
@
|
88
|
-
|
92
|
+
@stopper[1].syswrite(".")
|
93
|
+
@stopper[1].close()
|
94
|
+
@control_lock.synchronize do
|
95
|
+
@sockets.each do |name, socket|
|
96
|
+
socket.close
|
97
|
+
end
|
98
|
+
@sockets.clear
|
89
99
|
end
|
90
100
|
end # def stop
|
91
101
|
|
@@ -93,14 +103,17 @@ class FTW::Server
|
|
93
103
|
def each_connection(&block)
|
94
104
|
# TODO(sissel): Select on all sockets
|
95
105
|
# TODO(sissel): Accept and yield to the block
|
106
|
+
stopper = @stopper[0]
|
96
107
|
while true
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
108
|
+
@control_lock.synchronize do
|
109
|
+
sockets = @sockets.values + [stopper]
|
110
|
+
read, write, error = IO.select(sockets, nil, nil, nil)
|
111
|
+
break if read.include?(stopper)
|
112
|
+
read.each do |serversocket|
|
113
|
+
socket, addrinfo = serversocket.accept
|
114
|
+
connection = FTW::Connection.from_io(socket)
|
115
|
+
yield connection
|
116
|
+
end
|
104
117
|
end
|
105
118
|
end
|
106
119
|
end # def each_connection
|
data/lib/ftw/version.rb
CHANGED
data/test/ftw/protocol.rb
CHANGED
@@ -76,4 +76,17 @@ describe FTW::Protocol do
|
|
76
76
|
assert_equal( output.io.string, "12\r\nSome example input\r\n0\r\n\r\n")
|
77
77
|
end
|
78
78
|
|
79
|
+
test "writing non ascii characters" do
|
80
|
+
protocol = Object.new
|
81
|
+
protocol.extend FTW::Protocol
|
82
|
+
|
83
|
+
output = StringIO.new
|
84
|
+
input = "è".force_encoding(Encoding::UTF_8)
|
85
|
+
|
86
|
+
protocol.write_http_body(input, output, true)
|
87
|
+
|
88
|
+
output.rewind
|
89
|
+
assert_equal( output.string, "2\r\nè\r\n0\r\n\r\n")
|
90
|
+
end
|
91
|
+
|
79
92
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ftw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.42
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Sissel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cabin
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: http_parser.rb
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: '0.6'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: '0.6'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: addressable
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|