Skip to content

Commit

Permalink
Enforcing VERIFY_PEER on the client
Browse files Browse the repository at this point in the history
The ruby client did not enforce the validation of the certificate,
opening possible man in the middle attacks on the client. This PR make sure that
the `verify_mode` is set to `VERIFY_PEER` and add the certificate to the store
for this specific connection. An integration test was added to validate
this change.

This change make the ruby client handling of connection closer to the
`logstash-forwarder` behavior, which does the verify peer per default.

Fixes #4
  • Loading branch information
ph committed Jul 30, 2015
1 parent eac67d8 commit 759fb5f
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 18 deletions.
9 changes: 1 addition & 8 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,2 @@
source 'https://rubygems.org'

gem "rspec"
gem "insist"
gem "stud"
gem "fpm"
gem "pleaserun"

gem "jruby-openssl", :platform => :jruby
gemspec
15 changes: 6 additions & 9 deletions jls-lumberjack.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ Gem::Specification.new do |gem|
gem.summary = gem.description
gem.homepage = "https://github.com/jordansissel/lumberjack"

gem.files = %w{
lib/lumberjack/server.rb
lib/lumberjack/client.rb
}
#lib/lumberjack/server2.rb
gem.files = Dir.glob("lib/**/*.rb")

gem.test_files = []
gem.test_files = Dir.glob("spec/**/*.rb")
gem.name = "jls-lumberjack"
gem.require_paths = ["lib"]
gem.version = "0.0.22"
gem.version = "0.0.23"

# This isn't used yet because the new protocol isn't ready
#gem.add_runtime_dependency "ffi-rzmq", "~> 1.0.0"
gem.add_development_dependency "flores", "0.0.5"
gem.add_development_dependency "rspec"
gem.add_development_dependency "stud"
end
14 changes: 13 additions & 1 deletion lib/lumberjack/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,19 @@ def initialize(opts={})
private
def connection_start(opts)
tcp_socket = TCPSocket.new(opts[:address], opts[:port])
@socket = OpenSSL::SSL::SSLSocket.new(tcp_socket)

certificate = OpenSSL::X509::Certificate.new(File.read(opts[:ssl_certificate]))

certificate_store = OpenSSL::X509::Store.new
certificate_store.add_cert(certificate)

ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
ssl_context.cert_store = certificate_store

# ssl_context.ca_file = opts[:ssl_certificate]

@socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
@socket.connect
@socket.syswrite(["1", "W", @window_size].pack("AAN"))
end
Expand Down
57 changes: 57 additions & 0 deletions spec/integration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# encoding: utf-8
require "lib/lumberjack/client"
require "lib/lumberjack/server"
require "stud/temporary"
require "flores/pki"
require "fileutils"
require "thread"
require "spec_helper"

describe "A client" do
let(:port) { Flores::Random.integer(1024..65335) }
let(:csr) { Flores::PKI::CertificateSigningRequest.new }
let(:key_bits) { 1024 }
let(:key) { OpenSSL::PKey::RSA.generate(key_bits, 65537) }
let(:certificate_duration) { Flores::Random.number(1..86400) }
let(:certificate_subject) { "CN=server.example.com" }
let(:certificate) { csr.create }
let(:certificate_file_crt) { "certificate.crt" }
let(:certificate_file_key) { "certificate.key" }
let(:host) { "127.0.0.1" }
let(:queue) { Queue.new }
let(:payload) { {"line" => "hello world" } }

before do
csr.subject = certificate_subject
csr.public_key = key.public_key
csr.start_time = Time.now
csr.expire_time = csr.start_time + certificate_duration
csr.signing_key = key
csr.want_signature_ability = true

expect(File).to receive(:read).twice.with(certificate_file_crt) { certificate.to_s }
expect(File).to receive(:read).with(certificate_file_key) { key.to_s }

server = Lumberjack::Server.new(:port => port,
:address => host,
:ssl_certificate => certificate_file_crt,
:ssl_key => certificate_file_key)

Thread.new do
server.run { |data| queue.push(data) }
end
end

it "should require a certificate" do
expect {
client = Lumberjack::Client.new(:port => port,
:host => host,
:addresses => host,
:ssl_certificate => certificate_file_crt)

client.write(payload)
}.not_to raise_error

expect(queue.pop).to eq(payload)
end
end

0 comments on commit 759fb5f

Please sign in to comment.