ftw 0.0.41 → 0.0.42
Sign up to get free protection for your applications and to get access to all the features.
- 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
|