diff --git a/spec/std/openssl/ssl/server_spec.cr b/spec/std/openssl/ssl/server_spec.cr index bca500ba5424..cd3384bc32e8 100644 --- a/spec/std/openssl/ssl/server_spec.cr +++ b/spec/std/openssl/ssl/server_spec.cr @@ -76,4 +76,21 @@ describe OpenSSL::SSL::Server do end end end + + it "detects SNI hostname" do + tcp_server = TCPServer.new(0) + server_context, client_context = ssl_context_pair + + OpenSSL::SSL::Server.open tcp_server, server_context do |server| + spawn do + sleep 1 + OpenSSL::SSL::Socket::Client.open(TCPSocket.new(tcp_server.local_address.address, tcp_server.local_address.port), client_context, hostname: "example.com") do |socket| + end + end + + client = server.accept + client.hostname.should eq("example.com") + client.close + end + end end diff --git a/src/openssl/lib_ssl.cr b/src/openssl/lib_ssl.cr index 9218154f2078..d9fd3c08df28 100644 --- a/src/openssl/lib_ssl.cr +++ b/src/openssl/lib_ssl.cr @@ -155,6 +155,7 @@ lib LibSSL fun tlsv1_2_method = TLSv1_2_method : SSLMethod fun ssl_get_error = SSL_get_error(handle : SSL, ret : Int) : SSLError + fun ssl_get_servername = SSL_get_servername(ssl : SSL, host_type : TLSExt) : UInt8* fun ssl_set_bio = SSL_set_bio(handle : SSL, rbio : LibCrypto::Bio*, wbio : LibCrypto::Bio*) fun ssl_select_next_proto = SSL_select_next_proto(output : Char**, output_len : Char*, input : Char*, input_len : Int, client : Char*, client_len : Int) : Int fun ssl_ctrl = SSL_ctrl(handle : SSL, cmd : Int, larg : Long, parg : Void*) : Long diff --git a/src/openssl/ssl/socket.cr b/src/openssl/ssl/socket.cr index 7b789411182f..d2489c7d9920 100644 --- a/src/openssl/ssl/socket.cr +++ b/src/openssl/ssl/socket.cr @@ -181,4 +181,11 @@ abstract class OpenSSL::SSL::Socket < IO def unbuffered_rewind raise IO::Error.new("Can't rewind OpenSSL::SSL::Socket::Client") end + + # Returns the hostname provided through Server Name Indication (SNI) + def hostname : String? + if host_name = LibSSL.ssl_get_servername(@ssl, LibSSL::TLSExt::NAMETYPE_host_name) + String.new(host_name) + end + end end