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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ceb0fdc8f63693a96433f7417afb19330140af2
4
- data.tar.gz: e037a78814a02848e72c92da450b338d0d190737
3
+ metadata.gz: 33fab2173e9d5a55d01c5be096be99b4a6e4c9b6
4
+ data.tar.gz: 2d5d057c20fc4bec7705143ba4010d9162623d1f
5
5
  SHA512:
6
- metadata.gz: a683de29fb0919b548d7162198943bc164fc35b66d8f8ec6d750fbe51808c3cf8078591ae3e2ccc256b0cc80d2a07153f933b9e73e66f819b1908d15337399e3
7
- data.tar.gz: 5b210be8cfd33f284b5355cc2832b5ccdc1fbe464f081710c5e90f813424e1844eaddb2b3f1f5832ae74eee2a37c5c9c34c5ff4d13f21511a4b32a5b97439335
6
+ metadata.gz: 1cd81a35b4289d5c5f3c7aa566d4de5e4192ad2ac8343d7c74d3a13fc695ad6c719254395375448262da6ee13697ce2a066f63eaab32c069e185a4b7d8ee2c9c
7
+ data.tar.gz: 437f27db19fd9616dcec6db39d97f02e336ab0d5edeaebff14e785a70d85988a41a8a72bbd2075ccbbd2f4ce9532321277b49730a49894bd1e87681ca5c6eedd
@@ -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
- connection.secure(:certificate_store => certificate_store,
449
- :verify_callback => verify_callback)
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
 
@@ -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
- #:certificate_store => OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
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 = "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2"
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 = options[:certificate_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, options[:timeout])
379
+ do_secure(:connect_nonblock, settings[:timeout])
362
380
  else
363
- do_secure(:accept_nonblock, options[:timeout])
381
+ do_secure(:accept_nonblock, settings[:timeout])
364
382
  end
365
383
  end # def secure
366
384
 
@@ -109,7 +109,7 @@ module FTW::Protocol
109
109
  def write_all(io, string)
110
110
  while string.bytesize > 0
111
111
  w = io.write(string)
112
- string = string[w..-1]
112
+ string = string.byteslice(w..-1)
113
113
  end
114
114
  end # def write_all
115
115
 
@@ -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
- @sockets.each do |name, socket|
88
- socket.close
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
- sockets = @sockets.values
98
- read, write, error = IO.select(sockets, nil, nil, nil)
99
- read.each do |serversocket|
100
- #p serversocket.methods.sort
101
- socket, addrinfo = serversocket.accept
102
- connection = FTW::Connection.from_io(socket)
103
- yield connection
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
@@ -3,5 +3,5 @@ require "ftw/namespace"
3
3
  # :nodoc:
4
4
  module FTW
5
5
  # The version of this library
6
- VERSION = "0.0.41"
6
+ VERSION = "0.0.42"
7
7
  end
@@ -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.41
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-13 00:00:00.000000000 Z
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.5.3
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.5.3
40
+ version: '0.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: addressable
43
43
  requirement: !ruby/object:Gem::Requirement