diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 48 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl.xml | 43 | ||||
-rw-r--r-- | lib/ssl/src/Makefile | 23 | ||||
-rw-r--r-- | lib/ssl/src/inet_tls_dist.erl | 16 | ||||
-rw-r--r-- | lib/ssl/src/ssl.appup.src | 22 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 23 | ||||
-rw-r--r-- | lib/ssl/src/ssl_certificate.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 41 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 31 | ||||
-rw-r--r-- | lib/ssl/src/ssl_tls1.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_tls_dist_proxy.erl | 48 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 105 | ||||
-rw-r--r-- | lib/ssl/test/ssl_dist_SUITE.erl | 12 | ||||
-rw-r--r-- | lib/ssl/test/ssl_to_openssl_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/ssl/vsn.mk | 2 |
15 files changed, 339 insertions, 89 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 1e1fe0d119..a4da939d3e 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -30,7 +30,53 @@ </header> <p>This document describes the changes made to the SSL application.</p> - <section><title>SSL 5.0</title> + <section><title>SSL 5.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Robustness and improvement to distribution over SSL</p> + <p> + Fix a bug where ssl_tls_dist_proxy would crash at caller + timeout. Fix a bug where a timeout from the SSL layer + would block the distribution indefinately. Run the proxy + exclusively on the loopback interface. (Thanks to Paul + Guyot)</p> + <p> + Own Id: OTP-9915</p> + </item> + <item> + <p> + Fix setup loop of SSL TLS dist proxy</p> + <p> + Fix potential leak of processes waiting indefinately for + data from closed sockets during socket setup phase. + (Thanks to Paul Guyot)</p> + <p> + Own Id: OTP-9916</p> + </item> + <item> + <p> + Correct spelling of registered (Thanks to Richard + Carlsson)</p> + <p> + Own Id: OTP-9925</p> + </item> + <item> + <p> + Added TLS PRF function to the SSL API for generation of + additional key material from a TLS session. (Thanks to + Andreas Schultz)</p> + <p> + Own Id: OTP-10024</p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 5.0</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 50268ae206..28bf82b406 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1999</year><year>2011</year> + <year>1999</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -62,8 +62,8 @@ </c></p> <p>For valid options - see <seealso marker="kernel:inet">inet(3) </seealso> and - <seealso marker="kernel:gen_tcp">gen_tcp(3) </seealso>. + see <seealso marker="kernel:inet">inet(3)</seealso> and + <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>. </p> <p> <c>ssloption() = {verify, verify_type()} | @@ -122,6 +122,9 @@ <p> <c>hash() = md5 | sha </c></p> + <p><c>prf_random() = client_random | server_random + </c></p> + </section> <section> @@ -190,13 +193,13 @@ </item> <tag>{depth, integer()}</tag> - <item>Specifies the maximum - verification depth, i.e. how far in a chain of certificates the - verification process can proceed before the verification is - considered to fail. Peer certificate = 0, CA certificate = 1, - higher level CA certificate = 2, etc. The value 2 thus means - that a chain can at most contain peer cert, CA cert, next CA - cert, and an additional CA cert. The default value is 1. + <item> + The depth is the maximum number of non-self-issued + intermediate certificates that may follow the peer certificate + in a valid certification path. So if depth is 0 the PEER must + be signed by the trusted ROOT-CA directly, if 1 the path can + be PEER, CA, ROOT-CA, if it is 2 PEER, CA, CA, ROOT-CA and so + on. The default value is 1. </item> <tag>{verify_fun, {Verifyfun :: fun(), InitialUserState :: term()}}</tag> @@ -561,6 +564,26 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </func> <func> + <name>prf(Socket, Secret, Label, Seed, WantedLength) -> {ok, binary()} | {error, reason()}</name> + <fsummary>Use a sessions pseudo random function to generate key material.</fsummary> + <type> + <v>Socket = sslsocket()</v> + <v>Secret = binary() | master_secret</v> + <v>Label = binary()</v> + <v>Seed = [binary() | prf_random()]</v> + <v>WantedLength = non_neg_integer()</v> + </type> + <desc> + <p>Use the pseudo random function (PRF) of a TLS session to generate + additional key material. It either takes user generated values for + <c>Secret</c> and <c>Seed</c> or atoms directing it use a specific + value from the session security parameters.</p> + <p>This function can only be used with TLS connections, <c>{error, undefined}</c> + is returned for SSLv3 connections.</p> + </desc> + </func> + + <func> <name>renegotiate(Socket) -> ok | {error, Reason}</name> <fsummary> Initiates a new handshake.</fsummary> <type> diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile index dc69b53b28..f99dd8559e 100644 --- a/lib/ssl/src/Makefile +++ b/lib/ssl/src/Makefile @@ -37,6 +37,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN) # Common Macros # ---------------------------------------------------- +BEHAVIOUR_MODULES= \ + ssl_session_cache_api + MODULES= \ ssl \ ssl_alert \ @@ -53,7 +56,6 @@ MODULES= \ ssl_handshake \ ssl_manager \ ssl_session \ - ssl_session_cache_api \ ssl_session_cache \ ssl_record \ ssl_ssl2 \ @@ -66,10 +68,15 @@ INTERNAL_HRL_FILES = \ ssl_alert.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_internal.hrl \ ssl_record.hrl -ERL_FILES= $(MODULES:%=%.erl) +ERL_FILES= \ + $(MODULES:%=%.erl) \ + $(BEHAVIOUR_MODULES:%=%.erl) + TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) +BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR)) + APP_FILE= ssl.app APPUP_FILE= ssl.appup @@ -83,6 +90,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) # ---------------------------------------------------- EXTRA_ERLC_FLAGS = +warn_unused_vars ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \ + -pz $(EBIN) \ -pz $(ERL_TOP)/lib/public_key/ebin \ $(EXTRA_ERLC_FLAGS) -DVSN=\"$(VSN)\" @@ -91,6 +99,8 @@ ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \ # Targets # ---------------------------------------------------- +$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES) + debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) clean: @@ -105,6 +115,7 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk docs: + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -114,14 +125,8 @@ release_spec: opt $(INSTALL_DIR) $(RELSYSDIR)/src $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src $(INSTALL_DIR) $(RELSYSDIR)/ebin - $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) \ + $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \ $(APPUP_TARGET) $(RELSYSDIR)/ebin release_docs_spec: - - - - - - diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 115527aae0..57c859bf24 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -57,7 +57,7 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> Kernel = self(), - spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end). + spawn_opt(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]). do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> [Name, Address] = splitnode(Node, LongOrShortNames), @@ -229,9 +229,7 @@ connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Addre accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) -> common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{ allowed = Allowed, - f_address = fun(S, N) -> - ssl_tls_dist_proxy:get_remote_id(S, N) - end + f_address = fun get_remote_id/2 }). common_hs_data(Kernel, MyNode, Socket, Timer, HsData) -> @@ -273,3 +271,11 @@ common_hs_data(Kernel, MyNode, Socket, Timer, HsData) -> P = proplists:get_value(send_pend, Stats, 0), {ok, R,W,P} end}. + +get_remote_id(Socket, _Node) -> + case ssl_tls_dist_proxy:get_tcp_address(Socket) of + {ok, Address} -> + Address; + {error, _Reason} -> + ?shutdown(no_node) + end. diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 1b07e76d6a..e346b1e9e6 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,23 +1,13 @@ %% -*- erlang -*- {"%VSN%", [ - {"4.1.6", [{restart_application, ssl}]}, - {"4.1.5", [{restart_application, ssl}]}, - {"4.1.4", [{restart_application, ssl}]}, - {"4.1.3", [{restart_application, ssl}]}, - {"4.1.2", [{restart_application, ssl}]}, - {"4.1.1", [{restart_application, ssl}]}, - {"4.1", [{restart_application, ssl}]}, - {"4.0.1", [{restart_application, ssl}]} + {"5.0", [{restart_application, ssl}]}, + {<<"4\\.*">>, [{restart_application, ssl}]}, + {<<"3\\.*">>, [{restart_application, ssl}]} ], [ - {"4.1.6", [{restart_application, ssl}]}, - {"4.1.5", [{restart_application, ssl}]}, - {"4.1.4", [{restart_application, ssl}]}, - {"4.1.3", [{restart_application, ssl}]}, - {"4.1.2", [{restart_application, ssl}]}, - {"4.1.1", [{restart_application, ssl}]}, - {"4.1", [{restart_application, ssl}]}, - {"4.0.1", [{restart_application, ssl}]} + {"5.0", [{restart_application, ssl}]}, + {<<"4\\.*">>, [{restart_application, ssl}]}, + {<<"3\\.*">>, [{restart_application, ssl}]} ]}. diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index d0693445e0..0bcdffbeff 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -30,7 +30,7 @@ controlling_process/2, listen/2, pid/1, peername/1, peercert/1, recv/2, recv/3, send/2, getopts/2, setopts/2, sockname/1, versions/0, session_info/1, format_error/1, - renegotiate/1]). + renegotiate/1, prf/5]). -deprecated({pid, 1, next_major_release}). @@ -40,6 +40,12 @@ -include_lib("public_key/include/public_key.hrl"). +%% Visible in API +-export_type([connect_option/0, listen_option/0, ssl_option/0, transport_option/0, + erl_cipher_suite/0, %% From ssl_cipher.hrl + tls_atom_version/0, %% From ssl_internal.hrl + prf_random/0]). + -record(config, {ssl, %% SSL parameters inet_user, %% User set inet options emulated, %% #socket_option{} emulated @@ -67,7 +73,7 @@ -type ssl_imp() :: new | old. -type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}. - +-type prf_random() :: client_random | server_random. %%-------------------------------------------------------------------- -spec start() -> ok | {error, reason()}. @@ -414,6 +420,17 @@ versions() -> renegotiate(#sslsocket{pid = Pid, fd = new_ssl}) -> ssl_connection:renegotiation(Pid). +%%-------------------------------------------------------------------- +-spec prf(#sslsocket{}, binary() | 'master_secret', binary(), + binary() | prf_random(), non_neg_integer()) -> + {ok, binary()} | {error, reason()}. +%% +%% Description: use a ssl sessions TLS PRF to generate key material +%%-------------------------------------------------------------------- +prf(#sslsocket{pid = Pid, fd = new_ssl}, + Secret, Label, Seed, WantedLength) -> + ssl_connection:prf(Pid, Secret, Label, Seed, WantedLength). + %%--------------------------------------------------------------- -spec format_error({error, term()}) -> list(). %% diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index 61876e1158..0931b86782 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -111,7 +111,7 @@ file_to_certificats(File, DbHandle) -> {ok, List} = ssl_manager:cache_pem_file(File, DbHandle), [Bin || {'Certificate', Bin, not_encrypted} <- List]. %%-------------------------------------------------------------------- --spec validate_extension(term(), #'Extension'{} | {bad_cert, atom()} | valid, +-spec validate_extension(term(), {extension, #'Extension'{}} | {bad_cert, atom()} | valid, term()) -> {valid, term()} | {fail, tuple()} | {unknown, term()}. diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 28dd0c85d0..6c06baff98 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,7 +40,8 @@ -export([send/2, recv/3, connect/7, ssl_accept/6, handshake/2, socket_control/3, close/1, shutdown/2, new_user/2, get_opts/2, set_opts/2, info/1, session_info/1, - peer_certificate/1, sockname/1, peername/1, renegotiation/1]). + peer_certificate/1, sockname/1, peername/1, renegotiation/1, + prf/5]). %% Called by ssl_connection_sup -export([start_link/7]). @@ -273,6 +274,16 @@ peer_certificate(ConnectionPid) -> renegotiation(ConnectionPid) -> sync_send_all_state_event(ConnectionPid, renegotiate). +%%-------------------------------------------------------------------- +-spec prf(pid(), binary() | 'master_secret', binary(), + binary() | ssl:prf_random(), non_neg_integer()) -> + {ok, binary()} | {error, reason()} | {'EXIT', term()}. +%% +%% Description: use a ssl sessions TLS PRF to generate key material +%%-------------------------------------------------------------------- +prf(ConnectionPid, Secret, Label, Seed, WantedLength) -> + sync_send_all_state_event(ConnectionPid, {prf, Secret, Label, Seed, WantedLength}). + %%==================================================================== %% ssl_connection_sup API %%==================================================================== @@ -868,6 +879,32 @@ handle_sync_event(renegotiate, From, connection, State) -> handle_sync_event(renegotiate, _, StateName, State) -> {reply, {error, already_renegotiating}, StateName, State, get_timeout(State)}; +handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName, + #state{connection_states = ConnectionStates, + negotiated_version = Version} = State) -> + ConnectionState = + ssl_record:current_connection_state(ConnectionStates, read), + SecParams = ConnectionState#connection_state.security_parameters, + #security_parameters{master_secret = MasterSecret, + client_random = ClientRandom, + server_random = ServerRandom} = SecParams, + Reply = try + SecretToUse = case Secret of + _ when is_binary(Secret) -> Secret; + master_secret -> MasterSecret + end, + SeedToUse = lists:reverse( + lists:foldl(fun(X, Acc) when is_binary(X) -> [X|Acc]; + (client_random, Acc) -> [ClientRandom|Acc]; + (server_random, Acc) -> [ServerRandom|Acc] + end, [], Seed)), + ssl_handshake:prf(Version, SecretToUse, Label, SeedToUse, WantedLength) + catch + exit:_ -> {error, badarg}; + error:Reason -> {error, Reason} + end, + {reply, Reply, StateName, State, get_timeout(State)}; + handle_sync_event(info, _, StateName, #state{negotiated_version = Version, session = #session{cipher_suite = Suite}} = State) -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 371f475c85..2e0a3de182 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ finished/4, verify_connection/5, get_tls_handshake/2, decode_client_key/3, server_hello_done/0, encode_handshake/2, init_hashes/0, update_hashes/2, - decrypt_premaster_secret/2]). + decrypt_premaster_secret/2, prf/5]). -export([dec_hello_extensions/2]). @@ -188,14 +188,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef, ValidationFunAndState = case VerifyFunAndState of undefined -> - {fun(OtpCert, ExtensionOrError, SslState) -> + {fun(OtpCert, ExtensionOrVerifyResult, SslState) -> ssl_certificate:validate_extension(OtpCert, - ExtensionOrError, SslState) + ExtensionOrVerifyResult, SslState) end, Role}; {Fun, UserState0} -> - {fun(OtpCert, ExtensionOrError, {SslState, UserState}) -> + {fun(OtpCert, {extension, _} = Extension, {SslState, UserState}) -> case ssl_certificate:validate_extension(OtpCert, - ExtensionOrError, + Extension, SslState) of {valid, NewSslState} -> {valid, {NewSslState, UserState}}; @@ -204,8 +204,11 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef, SslState); {unknown, _} -> apply_user_fun(Fun, OtpCert, - ExtensionOrError, UserState, SslState) - end + Extension, UserState, SslState) + end; + (OtpCert, VerifyResult, {SslState, UserState}) -> + apply_user_fun(Fun, OtpCert, VerifyResult, UserState, + SslState) end, {Role, UserState0}} end, @@ -540,6 +543,18 @@ server_key_exchange_hash(dhe_dss, Value) -> crypto:sha(Value). %%-------------------------------------------------------------------- +-spec prf(tls_version(), binary(), binary(), [binary()], non_neg_integer()) -> + {ok, binary()} | {error, undefined}. +%% +%% Description: use the TLS PRF to generate key material +%%-------------------------------------------------------------------- +prf({3,0}, _, _, _, _) -> + {error, undefined}; +prf({3,N}, Secret, Label, Seed, WantedLength) + when N == 1; N == 2 -> + {ok, ssl_tls1:prf(Secret, Label, Seed, WantedLength)}. + +%%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length), diff --git a/lib/ssl/src/ssl_tls1.erl b/lib/ssl/src/ssl_tls1.erl index 5f9850c386..c8aae34892 100644 --- a/lib/ssl/src/ssl_tls1.erl +++ b/lib/ssl/src/ssl_tls1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -29,7 +29,7 @@ -include("ssl_record.hrl"). -export([master_secret/3, finished/3, certificate_verify/2, mac_hash/7, - setup_keys/6, suites/0]). + setup_keys/6, suites/0, prf/4]). %%==================================================================== %% Internal application API diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index d63eada571..a8476b104f 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ -module(ssl_tls_dist_proxy). --export([listen/1, accept/1, connect/2, get_remote_id/2]). +-export([listen/1, accept/1, connect/2, get_tcp_address/1]). -export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, ssl_options/2]). @@ -47,9 +47,6 @@ accept(Listen) -> connect(Ip, Port) -> gen_server:call(?MODULE, {connect, Ip, Port}, infinity). -get_remote_id(Socket, Node) -> - gen_server:call(?MODULE, {get_remote_id, {Socket,Node}}, infinity). - %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -65,8 +62,8 @@ handle_call({listen, Name}, _From, State) -> case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of {ok, Socket} -> {ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]), - TcpAddress = get_tcp_address(Socket), - WorldTcpAddress = get_tcp_address(World), + {ok, TcpAddress} = get_tcp_address(Socket), + {ok, WorldTcpAddress} = get_tcp_address(World), {_,Port} = WorldTcpAddress#net_address.address, {ok, Creation} = erl_epmd:register_node(Name, Port), {reply, {ok, {Socket, TcpAddress, Creation}}, @@ -87,17 +84,16 @@ handle_call({connect, Ip, Port}, {From, _}, State) -> receive {Pid, go_ahead, LPort} -> Res = {ok, Socket} = try_connect(LPort), - ok = gen_tcp:controlling_process(Socket, From), - flush_old_controller(From, Socket), - {reply, Res, State}; + case gen_tcp:controlling_process(Socket, From) of + {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway. + ok -> + flush_old_controller(From, Socket), + {reply, Res, State} + end; {Pid, Error} -> {reply, Error, State} end; -handle_call({get_remote_id, {Socket,_Node}}, _From, State) -> - Address = get_tcp_address(Socket), - {reply, Address, State}; - handle_call(_What, _From, State) -> {reply, ok, State}. @@ -117,14 +113,18 @@ code_change(_OldVsn, St, _Extra) -> %%% Internal functions %%-------------------------------------------------------------------- get_tcp_address(Socket) -> - {ok, Address} = inet:sockname(Socket), - {ok, Host} = inet:gethostname(), - #net_address{ + case inet:sockname(Socket) of + {ok, Address} -> + {ok, Host} = inet:gethostname(), + NetAddress = #net_address{ address = Address, host = Host, protocol = proxy, family = inet - }. + }, + {ok, NetAddress}; + {error, _} = Error -> Error + end. accept_loop(Proxy, erts = Type, Listen, Extra) -> process_flag(priority, max), @@ -178,8 +178,8 @@ setup_proxy(Ip, Port, Parent) -> Opts = get_ssl_options(client), case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of {ok, World} -> - {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, binary, {packet,?PPRE}]), - #net_address{address={_,LPort}} = get_tcp_address(ErtsL), + {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]), + {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL), Parent ! {self(), go_ahead, LPort}, case gen_tcp:accept(ErtsL) of {ok, Erts} -> @@ -194,7 +194,7 @@ setup_proxy(Ip, Port, Parent) -> setup_connection(World, ErtsListen) -> process_flag(trap_exit, true), - TcpAddress = get_tcp_address(ErtsListen), + {ok, TcpAddress} = get_tcp_address(ErtsListen), {_Addr,Port} = TcpAddress#net_address.address, {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]), ssl:setopts(World, [{active,true}, {packet,?PPRE}]), @@ -223,7 +223,11 @@ loop_conn_setup(World, Erts) -> loop_conn_setup(World, Erts); {tcp, Erts, Data} -> ssl:send(World, Data), - loop_conn_setup(World, Erts) + loop_conn_setup(World, Erts); + {tcp_closed, Erts} -> + ssl:close(World); + {ssl_closed, World} -> + gen_tcp:close(Erts) end. loop_conn(World, Erts) -> diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 527263363c..590ecf33ca 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -250,6 +250,8 @@ all() -> no_authority_key_identifier, invalid_signature_client, invalid_signature_server, cert_expired, client_with_cert_cipher_suites_handshake, + verify_fun_always_run_client, + verify_fun_always_run_server, unknown_server_ca_fail, der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer, @@ -3217,6 +3219,105 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +verify_fun_always_run_client(doc) -> + ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"]; +verify_fun_always_run_client(suite) -> + []; +verify_fun_always_run_client(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + %% If user verify fun is called correctly we fail the connection. + %% otherwise we can not tell this case apart form where we miss + %% to call users verify fun + FunAndState = {fun(_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, [ChainLen]) -> + {valid, [ChainLen + 1]}; + (_, valid_peer, [2]) -> + {fail, "verify_fun_was_always_run"}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, [0]}, + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} + | ClientOpts]}]), + %% Server error may be esslaccept or closed depending on timing + %% this is not a bug it is a circumstance of how tcp works! + receive + {Server, ServerError} -> + test_server:format("Server Error ~p~n", [ServerError]) + end, + + ssl_test_lib:check_result(Client, {error, esslconnect}). + +%%-------------------------------------------------------------------- +verify_fun_always_run_server(doc) -> + ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"]; +verify_fun_always_run_server(suite) -> + []; +verify_fun_always_run_server(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% If user verify fun is called correctly we fail the connection. + %% otherwise we can not tell this case apart form where we miss + %% to call users verify fun + FunAndState = {fun(_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, [ChainLen]) -> + {valid, [ChainLen + 1]}; + (_, valid_peer, [2]) -> + {fail, "verify_fun_was_always_run"}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, [0]}, + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} | + ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer} + | ClientOpts]}]), + + %% Client error may be esslconnect or closed depending on timing + %% this is not a bug it is a circumstance of how tcp works! + receive + {Client, ClientError} -> + test_server:format("Client Error ~p~n", [ClientError]) + end, + + ssl_test_lib:check_result(Server, {error, esslaccept}). + %%-------------------------------------------------------------------- unknown_server_ca_fail(doc) -> ["Test that the client fails if the ca is unknown in verify_peer mode"]; @@ -3924,7 +4025,7 @@ renegotiate(Socket, Data) -> end. renegotiate_reuse_session(Socket, Data) -> - %% Make sure session is registerd + %% Make sure session is registered test_server:sleep(?SLEEP), renegotiate(Socket, Data). diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 8fe55ee7a4..12d92c8ca1 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -26,7 +26,7 @@ -define(DEFAULT_TIMETRAP_SECS, 240). --define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000). +-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000). -record(node_handle, {connection_handler, @@ -120,6 +120,12 @@ basic(Config) when is_list(Config) -> pang = net_adm:ping(Node1), pang = net_adm:ping(Node2), + %% SSL nodes should not be able to communicate with the test_server node + %% either (and ping should return eventually). + TestServer = node(), + pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(TestServer) end), + pang = apply_on_ssl_node(NH2, fun () -> net_adm:ping(TestServer) end), + %% %% Check that we are able to communicate over the erlang %% distribution between the ssl nodes. @@ -380,7 +386,7 @@ mk_node_cmdline(ListenPort, Name, Args) -> %% await_ssl_node_up(Name, LSock) -> - case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of + case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of timeout -> gen_tcp:close(LSock), ?t:format("Timeout waiting for ssl node ~s to come up~n", diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index f04ab9af50..01fca1f166 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1446,8 +1446,8 @@ check_sane_openssl_renegotaite(Config) -> check_sane_openssl_sslv2(Config) -> case os:cmd("openssl version") of - "OpenSSL 1.0.0e" ++ _ -> - {skip, "Known option bug"}; + "OpenSSL 1.0.0" ++ _ -> + {skip, "sslv2 by default turned of in 1.*"}; _ -> Config end. diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 2255798f1d..0fccbfe908 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 5.0 +SSL_VSN = 5.0.1 |