Skip to content

Commit

Permalink
Include peer socket IP address in errors
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Jun 15, 2021
1 parent 01b7cac commit 8a1e3f5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 4 deletions.
34 changes: 30 additions & 4 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,29 @@ ossl_ssl_s_alloc(VALUE klass)
return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
}

static VALUE
peer_ip_address(VALUE self)
{
VALUE remote_address = rb_funcall(rb_attr_get(self, id_i_io), rb_intern("remote_address"), 0);

return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0);
}

static VALUE
fallback_peer_ip_address(VALUE self, VALUE args)
{
return rb_str_new_cstr("(null)");
}

static VALUE
peeraddr_ip_str(VALUE self)
{
VALUE rb_mErrno = rb_const_get(rb_cObject, rb_intern("Errno"));
VALUE rb_eSystemCallError = rb_const_get(rb_mErrno, rb_intern("SystemCallError"));

return rb_rescue2(peer_ip_address, self, fallback_peer_ip_address, (VALUE)0, rb_eSystemCallError, NULL);
}

/*
* call-seq:
* SSLSocket.new(io) => aSSLSocket
Expand Down Expand Up @@ -1557,7 +1580,9 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
continue;
#endif
if (errno) rb_sys_fail(funcname);
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s",
funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl));

#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
case SSL_ERROR_SSL:
err = ERR_peek_last_error();
Expand All @@ -1570,13 +1595,14 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
if (!verify_msg)
verify_msg = "(null)";
ossl_clear_error(); /* let ossl_raise() not append message */
ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s: %s (%s)",
funcname, ret2, errno, SSL_state_string_long(ssl),
ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)",
funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl),
err_msg, verify_msg);
}
#endif
default:
ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s",
funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl));
}
}

Expand Down
27 changes: 27 additions & 0 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,33 @@ def test_servername_cb_raises_an_exception_on_unknown_objects
sock2.close if sock2
end

def test_accept_errors_include_peeraddr
context = OpenSSL::SSL::SSLContext.new
context.cert = @svr_cert
context.key = @svr_key

server = TCPServer.new("127.0.0.1", 0)
port = server.connect_address.ip_port

ssl_server = OpenSSL::SSL::SSLServer.new(server, context)

t = Thread.new do
assert_raise_with_message(OpenSSL::SSL::SSLError, /peeraddr=127\.0\.0\.1/) do
ssl_server.accept
end
end

begin
sock = TCPSocket.new("127.0.0.1", port)
sock.puts "abc"
ensure
sock&.close
end

assert t.join
server.close
end

def test_verify_hostname_on_connect
ctx_proc = proc { |ctx|
san = "DNS:a.example.com,DNS:*.b.example.com"
Expand Down

0 comments on commit 8a1e3f5

Please sign in to comment.