Skip to content

Commit 5037658

Browse files
authored
Merge pull request #1150 from rhenium/ky/ssl-servername-cb-docs-update
ssl: update docs for SSLContext#servername_cb
2 parents 6319150 + 9778ae6 commit 5037658

2 files changed

Lines changed: 53 additions & 5 deletions

File tree

‎lib/openssl/ssl.rb‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,37 @@ class SSLContext
7474
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
7575
DEFAULT_CERT_STORE.set_default_paths
7676

77-
# A callback invoked at connect time to distinguish between multiple
78-
# server names.
79-
#
80-
# The callback is invoked with an SSLSocket and a server name. The
81-
# callback must return an SSLContext for the server name or nil.
77+
# A callback invoked during the server-side handshake when the client
78+
# sends the Server Name Indication (SNI) extension.
79+
#
80+
# The callback is invoked with an SSLSocket and the server name requested
81+
# by the client as a String.
82+
#
83+
# A typical use case is to select the appropriate server certificate.
84+
# The callback can use SSLSocket#add_certificate to add certificates and
85+
# their corresponding private keys. It should return +nil+ to continue
86+
# the handshake and notify the client that the server name is accepted.
87+
#
88+
# Alternatively, the callback can return an SSLContext to switch the
89+
# context used for the connection. However, doing so is discouraged
90+
# because the underlying \OpenSSL API SSL_set_SSL_CTX() has complex and
91+
# inconsistent semantics.
92+
#
93+
# See also the man page SSL_CTX_set_tlsext_servername_callback(3).
94+
#
95+
# === Example
96+
# ctx = OpenSSL::SSL::SSLContext.new
97+
# ctx.servername_cb = proc do |ssl_socket, server_name|
98+
# if server_name == "example.com"
99+
# cert = OpenSSL::X509::Certificate.new(File.read("cert.pem"))
100+
# privkey = OpenSSL::PKey.read(File.read("cert_privkey.pem"))
101+
# ssl_socket.add_certificate(cert, privkey)
102+
# else
103+
# # Aborts the handshake with an "unrecognized_name" alert.
104+
# raise "unknown SNI hostname: #{server_name}"
105+
# end
106+
# nil
107+
# end
82108
attr_accessor :servername_cb
83109

84110
# call-seq:

‎test/openssl/test_ssl.rb‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,28 @@ def test_tlsext_hostname
11851185
end
11861186
end
11871187

1188+
def test_servername_cb_add_certificate
1189+
called = []
1190+
sctx = make_server_context
1191+
sctx.servername_cb = proc do |ssl, servername|
1192+
called << servername
1193+
ssl.add_certificate(@cli_cert, @cli_key)
1194+
nil
1195+
end
1196+
start_server(sctx) do |port|
1197+
sock = TCPSocket.new("127.0.0.1", port)
1198+
ssl = OpenSSL::SSL::SSLSocket.new(sock)
1199+
ssl.hostname = "example.org"
1200+
ssl.connect
1201+
assert_equal(@cli_cert, ssl.peer_cert)
1202+
assert_equal(["example.org"], called)
1203+
ssl.puts("abc"); ssl.gets
1204+
ensure
1205+
ssl&.close
1206+
sock&.close
1207+
end
1208+
end
1209+
11881210
def test_servername_cb_exception
11891211
server_proc = proc do |sock|
11901212
sctx = make_server_context

0 commit comments

Comments
 (0)