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),  | 
