diff options
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/dtls_handshake.erl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 41 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.hrl | 19 | ||||
-rw-r--r-- | lib/ssl/src/ssl_internal.hrl | 3 | ||||
-rw-r--r-- | lib/ssl/src/tls.erl | 9 | ||||
-rw-r--r-- | lib/ssl/src/tls_handshake.erl | 2 |
6 files changed, 61 insertions, 15 deletions
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl index 26e8ce7503..d0f9649f9f 100644 --- a/lib/ssl/src/dtls_handshake.erl +++ b/lib/ssl/src/dtls_handshake.erl @@ -46,7 +46,7 @@ client_hello(Host, Port, Cookie, ConnectionStates, SecParams = Pending#connection_state.security_parameters, CipherSuites = ssl_handshake:available_suites(UserSuites, Version), - Extensions = ssl_handshake:client_hello_extensions(Version, CipherSuites, + Extensions = ssl_handshake:client_hello_extensions(Host, Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation), Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert), diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index b18452a8f2..9142a260b1 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -53,7 +53,7 @@ select_session/10, supported_ecc/1]). %% Extensions handling --export([client_hello_extensions/5, +-export([client_hello_extensions/6, handle_client_hello_extensions/8, %% Returns server hello extensions handle_server_hello_extensions/9, select_curve/2 ]). @@ -85,7 +85,7 @@ hello_request() -> server_hello_done() -> #server_hello_done{}. -client_hello_extensions(Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation) -> +client_hello_extensions(Host, Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation) -> {EcPointFormats, EllipticCurves} = case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of true -> @@ -104,7 +104,8 @@ client_hello_extensions(Version, CipherSuites, SslOpts, ConnectionStates, Renego elliptic_curves = EllipticCurves, next_protocol_negotiation = encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector, - Renegotiation)}. + Renegotiation), + sni = sni(Host, SslOpts#ssl_options.server_name_indication)}. %%-------------------------------------------------------------------- -spec certificate(der_cert(), db_handle(), certdb_ref(), client | server) -> #certificate{} | #alert{}. @@ -641,7 +642,19 @@ encode_hello_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Res ListLen = byte_size(SignAlgoList), Len = ListLen + 2, encode_hello_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT), - ?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>). + ?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>); +encode_hello_extensions([#sni{hostname = Hostname} | Rest], Acc) -> + HostLen = length(Hostname), + HostnameBin = list_to_binary(Hostname), + % Hostname type (1 byte) + Hostname length (2 bytes) + Hostname (HostLen bytes) + ServerNameLength = 1 + 2 + HostLen, + % ServerNameListSize (2 bytes) + ServerNameLength + ExtLength = 2 + ServerNameLength, + encode_hello_extensions(Rest, <<?UINT16(?SNI_EXT), ?UINT16(ExtLength), + ?UINT16(ServerNameLength), + ?BYTE(?SNI_NAMETYPE_HOST_NAME), + ?UINT16(HostLen), HostnameBin/binary, + Acc/binary>>). enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo}, ClientRandom, ServerRandom, PrivateKey) -> @@ -1081,9 +1094,10 @@ hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo, hash_signs = HashSigns, ec_point_formats = EcPointFormats, elliptic_curves = EllipticCurves, - next_protocol_negotiation = NextProtocolNegotiation}) -> + next_protocol_negotiation = NextProtocolNegotiation, + sni = Sni}) -> [Ext || Ext <- [RenegotiationInfo, SRP, HashSigns, - EcPointFormats,EllipticCurves, NextProtocolNegotiation], Ext =/= undefined]. + EcPointFormats, EllipticCurves, NextProtocolNegotiation, Sni], Ext =/= undefined]. srp_user(#ssl_options{srp_identity = {UserName, _}}) -> #srp{username = UserName}; @@ -1145,7 +1159,20 @@ select_curve(Curves, [Curve| Rest]) -> false -> select_curve(Curves, Rest) end. - +%% RFC 6066, Section 3: Currently, the only server names supported are +%% DNS hostnames +sni(_, disable) -> + undefined; +sni(Host, undefined) -> + sni1(Host); +sni(_Host, SNIOption) -> + sni1(SNIOption). + +sni1(Hostname) -> + case inet_parse:domain(Hostname) of + false -> undefined; + true -> #sni{hostname = Hostname} + end. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl index f25b0df806..75160526b9 100644 --- a/lib/ssl/src/ssl_handshake.hrl +++ b/lib/ssl/src/ssl_handshake.hrl @@ -98,7 +98,8 @@ next_protocol_negotiation = undefined, % [binary()] srp, ec_point_formats, - elliptic_curves + elliptic_curves, + sni }). -record(server_hello, { @@ -339,6 +340,19 @@ -define(NAMED_CURVE, 3). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Server name indication RFC 6066 section 3 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(SNI_EXT, 16#0000). + +%% enum { host_name(0), (255) } NameType; +-define(SNI_NAMETYPE_HOST_NAME, 0). + +-record(sni, { + hostname = undefined + }). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Dialyzer types %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -353,6 +367,3 @@ -endif. % -ifdef(ssl_handshake). - - - diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 96e3280fb5..a582b8c290 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -115,7 +115,8 @@ erl_dist = false, next_protocols_advertised = undefined, %% [binary()], next_protocol_selector = undefined, %% fun([binary()]) -> binary()) - log_alert + log_alert, + server_name_indication = undefined }). -record(socket_options, diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl index b220a48f73..f1747dc69e 100644 --- a/lib/ssl/src/tls.erl +++ b/lib/ssl/src/tls.erl @@ -664,7 +664,8 @@ handle_options(Opts0, _Role) -> next_protocol_selector = make_next_protocol_selector( handle_option(client_preferred_next_protocols, Opts, undefined)), - log_alert = handle_option(log_alert, Opts, true) + log_alert = handle_option(log_alert, Opts, true), + server_name_indication = handle_option(server_name_indication, Opts, undefined) }, CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}), @@ -855,6 +856,12 @@ validate_option(next_protocols_advertised = Opt, Value) when is_list(Value) -> validate_option(next_protocols_advertised, undefined) -> undefined; +validate_option(server_name_indication, Value) when is_list(Value) -> + Value; +validate_option(server_name_indication, disable) -> + disable; +validate_option(server_name_indication, undefined) -> + undefined; validate_option(Opt, Value) -> throw({error, {options, {Opt, Value}}}). diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl index ecbca83e10..262f2d929f 100644 --- a/lib/ssl/src/tls_handshake.erl +++ b/lib/ssl/src/tls_handshake.erl @@ -56,7 +56,7 @@ client_hello(Host, Port, ConnectionStates, SecParams = Pending#connection_state.security_parameters, CipherSuites = ssl_handshake:available_suites(UserSuites, Version), - Extensions = ssl_handshake:client_hello_extensions(Version, CipherSuites, + Extensions = ssl_handshake:client_hello_extensions(Host, Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation), Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert), |