Skip to content

Commit

Permalink
Change Events#ssl_error signature from (error, peeraddr, peercert) to…
Browse files Browse the repository at this point in the history
… (error, ssl_socket) (#2375)

* Change Events#ssl_error signature from (error, peeraddr, peercert) to (error, ssl_socket)

The method signature should include the socket, so it determines what socket info is logged

Co-authored-by: ocowchun <ocowchun@gmail.com>

* test_events.rb - add test_ssl_error

Co-authored-by: ocowchun <ocowchun@gmail.com>
Co-authored-by: Nate Berkopec <nate.berkopec@gmail.com>
  • Loading branch information
3 people committed Sep 23, 2020
1 parent bbbdfb8 commit e041d07
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 33 deletions.
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -7,6 +7,7 @@
* Your bugfix goes here (#Github Number)

* Refactor
* Change Events#ssl_error signature from (error, peeraddr, peercert) to (error, ssl_socket) (#2375)
* Remove unneeded attr_accessor statements from Server (#2373)

## 5.0.0
Expand Down
8 changes: 5 additions & 3 deletions lib/puma/events.rb
Expand Up @@ -106,10 +106,12 @@ def parse_error(error, req)
end

# An SSL error has occurred.
# +error+ an exception object, +peeraddr+ peer address,
# and +peercert+ any peer certificate (if present).
# @param error <Puma::MiniSSL::SSLError>
# @param ssl_socket <Puma::MiniSSL::Socket>
#
def ssl_error(error, peeraddr, peercert)
def ssl_error(error, ssl_socket)
peeraddr = ssl_socket.peeraddr.last rescue "<unknown>"
peercert = ssl_socket.peercert
subject = peercert ? peercert.subject : nil
@error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
end
Expand Down
15 changes: 2 additions & 13 deletions lib/puma/reactor.rb
Expand Up @@ -237,23 +237,12 @@ def run_internal

# SSL handshake failure
rescue MiniSSL::SSLError => e
@server.lowlevel_error(e, c.env)

ssl_socket = c.io
begin
addr = ssl_socket.peeraddr.last
# EINVAL can happen when browser closes socket w/security exception
rescue IOError, Errno::EINVAL
addr = "<unknown>"
end

cert = ssl_socket.peercert
@server.lowlevel_error e, c.env
@events.ssl_error e, c.io

c.close
clear_monitor mon

@events.ssl_error e, addr, cert

# The client doesn't know HTTP well
rescue HttpParserError => e
@server.lowlevel_error(e, c.env)
Expand Down
16 changes: 3 additions & 13 deletions lib/puma/server.rb
Expand Up @@ -234,13 +234,9 @@ def run(background=true)
process_now = true
end
rescue MiniSSL::SSLError => e
ssl_socket = client.io
addr = ssl_socket.peeraddr.last
cert = ssl_socket.peercert

@events.ssl_error e, client.io
client.close

@events.ssl_error e, addr, cert
rescue HttpParserError => e
client.write_error(400)
client.close
Expand Down Expand Up @@ -437,16 +433,10 @@ def process_client(client, buffer)

# SSL handshake error
rescue MiniSSL::SSLError => e
lowlevel_error(e, client.env)

ssl_socket = client.io
addr = ssl_socket.peeraddr.last
cert = ssl_socket.peercert

lowlevel_error e, client.env
@events.ssl_error e, client.io
close_socket = true

@events.ssl_error e, addr, cert

# The client doesn't know HTTP well
rescue HttpParserError => e
lowlevel_error(e, client.env)
Expand Down
39 changes: 38 additions & 1 deletion test/test_events.rb
Expand Up @@ -179,6 +179,43 @@ def test_parse_error
sleep 0.1 # important so that the previous data is sent as a packet
assert_match %r!HTTP parse error, malformed request!, events.stderr.string
assert_match %r!\("GET #{path}" - \(-\)\)!, events.stderr.string
server.stop(true)
ensure
sock.close if sock && !sock.closed?
server.stop true
end

# test_puma_server_ssl.rb checks that ssl errors are raised correctly,
# but it mocks the actual error code. This test the code, but it will
# break if the logged message changes
def test_ssl_error
events = Puma::Events.strings

ssl_mock = -> (addr, subj) {
obj = Object.new
obj.define_singleton_method(:peeraddr) { addr }
if subj
cert = Object.new
cert.define_singleton_method(:subject) { subj }
obj.define_singleton_method(:peercert) { cert }
else
obj.define_singleton_method(:peercert) { nil }
end
obj
}

events.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(['127.0.0.1'], 'test_cert')
error = events.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: 127.0.0.1"
assert_includes error, "cert: test_cert"

events.stderr.string = ''

events.ssl_error OpenSSL::SSL::SSLError, ssl_mock.call(nil, nil)
error = events.stderr.string
assert_includes error, "SSL error"
assert_includes error, "peer: <unknown>"
assert_includes error, "cert: :"

end if ::Puma::HAS_SSL
end
6 changes: 3 additions & 3 deletions test/test_puma_server_ssl.rb
Expand Up @@ -12,10 +12,10 @@
class SSLEventsHelper < ::Puma::Events
attr_accessor :addr, :cert, :error

def ssl_error(error, peeraddr, peercert)
def ssl_error(error, ssl_socket)
self.error = error
self.addr = peeraddr
self.cert = peercert
self.addr = ssl_socket.peeraddr.last rescue "<unknown>"
self.cert = ssl_socket.peercert
end
end

Expand Down

0 comments on commit e041d07

Please sign in to comment.