diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/c_src/esock_openssl.c | 2 | ||||
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 6 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl.xml | 31 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl_protocol.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/using_ssl.xml | 8 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 44 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 23 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 14 | ||||
-rw-r--r-- | lib/ssl/src/ssl_internal.hrl | 3 | ||||
-rw-r--r-- | lib/ssl/src/ssl_manager.erl | 12 | ||||
-rw-r--r-- | lib/ssl/src/ssl_record.erl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl_session.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_session_cache.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_ssl2.erl | 2 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 58 | ||||
-rw-r--r-- | lib/ssl/test/ssl_packet_SUITE.erl | 302 | ||||
-rw-r--r-- | lib/ssl/test/ssl_session_cache_SUITE.erl | 21 |
17 files changed, 454 insertions, 86 deletions
diff --git a/lib/ssl/c_src/esock_openssl.c b/lib/ssl/c_src/esock_openssl.c index 2621c9934e..0bc42958f0 100644 --- a/lib/ssl/c_src/esock_openssl.c +++ b/lib/ssl/c_src/esock_openssl.c @@ -1024,7 +1024,7 @@ static void info_callback(const SSL *ssl, int where, int ret) } } -/* This function is called whenever a SSL_CTX *ctx structure is +/* This function is called whenever an SSL_CTX *ctx structure is * freed. */ static void callback_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index b2d17925fd..e090b4e1ef 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -554,7 +554,7 @@ Own Id: OTP-8224</p> </item> <item> - <p>A ssl:ssl_accept/3 could crash a connection if the + <p>An ssl:ssl_accept/3 could crash a connection if the timing was wrong.</p> <p>Removed info message if the socket closed without a proper disconnect from the ssl layer. </p> <p>ssl:send/2 is now blocking until the @@ -770,7 +770,7 @@ <item> <p> The new ssl implementation released as a alfa in this - version supports upgrading of a tcp connection to a ssl + version supports upgrading of a tcp connection to an ssl connection so that http client and servers may implement RFC 2817.</p> <p> @@ -789,7 +789,7 @@ very crippled as the control of the ssl-socket was deep down in openssl making it hard if not impossible to support all inet options, ipv6 and upgrade of a tcp - connection to a ssl connection. The alfa version has a + connection to an ssl connection. The alfa version has a few limitations that will be removed before the ssl-4.0 release. Main differences and limitations in the alfa are listed below.</p> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 566068beaf..0c4c8796be 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -35,7 +35,7 @@ <title>SSL</title> <list type="bulleted"> - <item>ssl requires the crypto an public_key applications.</item> + <item>ssl requires the crypto and public_key applications.</item> <item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0 </item> <item>For security reasons sslv2 is not supported.</item> <item>Ephemeral Diffie-Hellman cipher suites are supported @@ -216,7 +216,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | application is encountered. Additionally it will be called when a certificate is considered valid by the path validation to allow access to each certificate in the path to the user - application. Note that the it will differentiate between the + application. Note that it will differentiate between the peer certificate and CA certificates by using valid_peer or valid as the second argument to the verify fun. See <seealso marker="public_key:cert_records">the public_key User's @@ -326,10 +326,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </item> <tag>{fail_if_no_peer_cert, boolean()}</tag> - <item>Used together with {verify, verify_peer} by a ssl server. + <item>Used together with {verify, verify_peer} by an ssl server. If set to true, the server will fail if the client does not have a certificate to send, i.e. sends a empty certificate, if set to - false it will only fail if the client sends a invalid + false it will only fail if the client sends an invalid certificate (an empty certificate is considered valid). </item> @@ -343,10 +343,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | PeerCert, Compression, CipherSuite) -> boolean()}</tag> <item>Enables the ssl server to have a local policy for deciding if a session should be reused or not, - only meaning full if <c>reuse_sessions</c> is set to true. + only meaningful if <c>reuse_sessions</c> is set to true. SuggestedSessionId is a binary(), PeerCert is a DER encoded certificate, Compression is an enumeration integer - and CipherSuite of type ciphersuite(). + and CipherSuite is of type ciphersuite(). </item> </taglist> @@ -355,7 +355,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <section> <title>General</title> - <p>When a ssl socket is in active mode (the default), data from the + <p>When an ssl socket is in active mode (the default), data from the socket is delivered to the owner of the socket in the form of messages: </p> @@ -396,7 +396,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {error, Reason}</name> <fsummary> Upgrades a gen_tcp, or - equivalent, connected socket to a ssl socket. </fsummary> + equivalent, connected socket to an ssl socket. </fsummary> <type> <v>Socket = socket()</v> <v>SslOptions = [ssloption()]</v> @@ -405,7 +405,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <v>Reason = term()</v> </type> <desc> <p>Upgrades a gen_tcp, or equivalent, - connected socket to a ssl socket i.e. performs the + connected socket to an ssl socket i.e. performs the client-side ssl handshake.</p> </desc> </func> @@ -428,12 +428,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <func> <name>close(SslSocket) -> ok | {error, Reason}</name> - <fsummary>Close a ssl connection</fsummary> + <fsummary>Close an ssl connection</fsummary> <type> <v>SslSocket = sslsocket()</v> <v>Reason = term()</v> </type> - <desc><p>Close a ssl connection.</p> + <desc><p>Close an ssl connection.</p> </desc> </func> @@ -450,7 +450,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <v>Reason = term()</v> </type> <desc><p>Assigns a new controlling process to the ssl-socket. A - controlling process is the owner of a ssl-socket, and receives + controlling process is the owner of an ssl-socket, and receives all messages from the socket.</p> </desc> </func> @@ -496,14 +496,14 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <func> <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name> - <fsummary>Creates a ssl listen socket.</fsummary> + <fsummary>Creates an ssl listen socket.</fsummary> <type> <v>Port = integer()</v> <v>Options = options()</v> <v>ListenSocket = sslsocket()</v> </type> <desc> - <p>Creates a ssl listen socket.</p> + <p>Creates an ssl listen socket.</p> </desc> </func> @@ -587,6 +587,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | the socket is closed.</p> </desc> </func> + <func> <name>setopts(Socket, Options) -> ok | {error, Reason}</name> <fsummary>Set socket options.</fsummary> @@ -646,7 +647,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </type> <desc> <p> Upgrades a gen_tcp, or - equivalent, socket to a ssl socket i.e. performs the + equivalent, socket to an ssl socket i.e. performs the ssl server-side handshake.</p> <p><warning>Note that the listen socket should be in {active, false} mode before telling the client that the server is ready to upgrade diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml index 6936408881..ca5cc8bc7a 100644 --- a/lib/ssl/doc/src/ssl_protocol.xml +++ b/lib/ssl/doc/src/ssl_protocol.xml @@ -31,11 +31,11 @@ </p> <p>By default erlang ssl is run over the TCP/IP protocol even - though you could plug in an other reliable transport protocol + though you could plug in any other reliable transport protocol with the same API as gen_tcp.</p> <p>If a client and server wants to use an upgrade mechanism, such as - defined by RFC2817, to upgrade a regular TCP/IP connection to a ssl + defined by RFC2817, to upgrade a regular TCP/IP connection to an ssl connection the erlang ssl API supports this. This can be useful for things such as supporting HTTP and HTTPS on the same port and implementing virtual hosting. diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml index 605290b6f9..ab837a156a 100644 --- a/lib/ssl/doc/src/using_ssl.xml +++ b/lib/ssl/doc/src/using_ssl.xml @@ -56,7 +56,7 @@ <code type="erl">1 server> ssl:start(). ok</code> - <p>Create a ssl listen socket</p> + <p>Create an ssl listen socket</p> <code type="erl">2 server> {ok, ListenSocket} = ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]). {ok,{sslsocket, [...]}}</code> @@ -90,7 +90,7 @@ ok</code> <section> <title>Upgrade example</title> - <note><p> To upgrade a TCP/IP connection to a ssl connection the + <note><p> To upgrade a TCP/IP connection to an ssl connection the client and server have to aggre to do so. Agreement may be accompliced by using a protocol such the one used by HTTP specified in RFC 2817.</p> </note> @@ -114,7 +114,7 @@ ok</code> <code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code> <p>Make sure active is set to false before trying - to upgrade a connection to a ssl connection, otherwhise + to upgrade a connection to an ssl connection, otherwhise ssl handshake messages may be deliverd to the wrong process.</p> <code type="erl">4 server> inet:setopts(Socket, [{active, false}]). ok</code> @@ -124,7 +124,7 @@ ok</code> {certfile, "cert.pem"}, {keyfile, "key.pem"}]). {ok,{sslsocket,[...]}}</code> - <p> Upgrade to a ssl connection. Note that the client and server + <p> Upgrade to an ssl connection. Note that the client and server must agree upon the upgrade and the server must call ssl:accept/2 before the client calls ssl:connect/3.</p> <code type="erl">3 client>{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"}, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index a0aedbbbee..d1ec0c141e 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -49,9 +49,12 @@ inet_ssl, %% inet options for internal ssl socket cb %% Callback info }). --type option() :: socketoption() | ssloption() | transportoption(). --type socketoption() :: term(). %% See gen_tcp and inet, import spec later when there is one to import --type ssloption() :: {verify, verify_type()} | +-type connect_option() :: socket_connect_option() | ssl_option() | transport_option(). +-type socket_connect_option() :: gen_tcp:connect_option(). +-type listen_option() :: socket_listen_option() | ssl_option() | transport_option(). +-type socket_listen_option() :: gen_tcp:listen_option(). + +-type ssl_option() :: {verify, verify_type()} | {verify_fun, {fun(), InitialUserState::term()}} | {fail_if_no_peer_cert, boolean()} | {depth, integer()} | {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} | @@ -66,7 +69,7 @@ string(). % (according to old API) -type ssl_imp() :: new | old. --type transportoption() :: {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}. +-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}. %%-------------------------------------------------------------------- @@ -96,15 +99,15 @@ stop() -> application:stop(ssl). %%-------------------------------------------------------------------- --spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}} | +-spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), [option()] | port_num(), timeout() | list()) -> +-spec connect(host() | port(), [connect_option()] | inet:port_number(), timeout() | list()) -> {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), port_num(), list(), timeout()) -> +-spec connect(host() | port(), inet:port_number(), list(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Connect to a ssl server. +%% Description: Connect to an ssl server. %%-------------------------------------------------------------------- connect(Socket, SslOptions) when is_port(Socket) -> connect(Socket, SslOptions, infinity). @@ -148,10 +151,10 @@ connect(Host, Port, Options0, Timeout) -> end. %%-------------------------------------------------------------------- --spec listen(port_num(), [option()]) ->{ok, #sslsocket{}} | {error, reason()}. +-spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Creates a ssl listen socket. +%% Description: Creates an ssl listen socket. %%-------------------------------------------------------------------- listen(_Port, []) -> {error, enooptions}; @@ -177,7 +180,7 @@ listen(Port, Options0) -> -spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs transport accept on a ssl listen socket +%% Description: Performs transport accept on an ssl listen socket %%-------------------------------------------------------------------- transport_accept(ListenSocket) -> transport_accept(ListenSocket, infinity). @@ -214,11 +217,11 @@ transport_accept(#sslsocket{} = ListenSocket, Timeout) -> %%-------------------------------------------------------------------- -spec ssl_accept(#sslsocket{}) -> ok | {error, reason()}. --spec ssl_accept(#sslsocket{} | port(), timeout()| [option()]) -> +-spec ssl_accept(#sslsocket{} | port(), timeout()| [ssl_option() | transport_option()]) -> ok | {ok, #sslsocket{}} | {error, reason()}. --spec ssl_accept(port(), [option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}. +-spec ssl_accept(port(), [ssl_option()| transport_option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs accept on a ssl listen socket. e.i. performs +%% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- ssl_accept(ListenSocket) -> @@ -252,7 +255,7 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) -> %%-------------------------------------------------------------------- -spec close(#sslsocket{}) -> term(). %% -%% Description: Close a ssl connection +%% Description: Close an ssl connection %%-------------------------------------------------------------------- close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}) -> CbMod:close(ListenSocket); @@ -373,7 +376,7 @@ select_part(plain, Cert, Opts) -> end. %%-------------------------------------------------------------------- --spec peername(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec peername(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: same as inet:peername/1. %%-------------------------------------------------------------------- @@ -402,7 +405,8 @@ cipher_suites(openssl) -> [ssl_cipher:openssl_suite_name(S) || S <- ssl_cipher:suites(Version)]. %%-------------------------------------------------------------------- --spec getopts(#sslsocket{}, [atom()]) -> {ok, [{atom(), term()}]} | {error, reason()}. +-spec getopts(#sslsocket{}, [gen_tcp:option_name()]) -> + {ok, [gen_tcp:option()]} | {error, reason()}. %% %% Description: Gets options %%-------------------------------------------------------------------- @@ -425,7 +429,7 @@ getopts(#sslsocket{} = Socket, OptionTags) -> ssl_broker:getopts(Socket, OptionTags). %%-------------------------------------------------------------------- --spec setopts(#sslsocket{}, [proplists:property()]) -> ok | {error, reason()}. +-spec setopts(#sslsocket{}, [gen_tcp:option()]) -> ok | {error, reason()}. %% %% Description: Sets options %%-------------------------------------------------------------------- @@ -466,7 +470,7 @@ shutdown(#sslsocket{pid = Pid, fd = new_ssl}, How) -> ssl_connection:shutdown(Pid, How). %%-------------------------------------------------------------------- --spec sockname(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec sockname(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:sockname/1 %%-------------------------------------------------------------------- @@ -1003,7 +1007,7 @@ version() -> %% Only used to remove exit messages from old ssl %% First is a nonsense clause to provide some -%% backward compability for orber that uses this +%% backward compatibility for orber that uses this %% function in a none recommended way, but will %% work correctly if a valid pid is returned. pid(#sslsocket{fd = new_ssl}) -> diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 21b021afb0..cec81d551b 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -127,11 +127,11 @@ send(Pid, Data) -> recv(Pid, Length, Timeout) -> sync_send_all_state_event(Pid, {recv, Length}, Timeout). %%-------------------------------------------------------------------- --spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}}, +-spec connect(host(), inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Connect to a ssl server. +%% Description: Connect to an ssl server. %%-------------------------------------------------------------------- connect(Host, Port, Socket, Options, User, CbInfo, Timeout) -> try start_fsm(client, Host, Port, Socket, Options, User, CbInfo, @@ -141,11 +141,11 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) -> {error, ssl_not_started} end. %%-------------------------------------------------------------------- --spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}}, +-spec ssl_accept(inet:port_number(), port(), {#ssl_options{}, #socket_options{}}, pid(), tuple(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}. %% -%% Description: Performs accept on a ssl listen socket. e.i. performs +%% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- ssl_accept(Port, Socket, Opts, User, CbInfo, Timeout) -> @@ -185,7 +185,7 @@ socket_control(Socket, Pid, CbModule) -> %%-------------------------------------------------------------------- -spec close(pid()) -> ok | {error, reason()}. %% -%% Description: Close a ssl connection +%% Description: Close an ssl connection %%-------------------------------------------------------------------- close(ConnectionPid) -> case sync_send_all_state_event(ConnectionPid, close) of @@ -212,14 +212,14 @@ shutdown(ConnectionPid, How) -> new_user(ConnectionPid, User) -> sync_send_all_state_event(ConnectionPid, {new_user, User}). %%-------------------------------------------------------------------- --spec sockname(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec sockname(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:sockname/1 %%-------------------------------------------------------------------- sockname(ConnectionPid) -> sync_send_all_state_event(ConnectionPid, sockname). %%-------------------------------------------------------------------- --spec peername(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}. +-spec peername(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}. %% %% Description: Same as inet:peername/1 %%-------------------------------------------------------------------- @@ -277,7 +277,7 @@ renegotiation(ConnectionPid) -> %%==================================================================== %%-------------------------------------------------------------------- --spec start_link(atom(), host(), port_num(), port(), list(), pid(), tuple()) -> +-spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) -> {ok, pid()} | ignore | {error, reason()}. %% %% Description: Creates a gen_fsm process which calls Module:init/1 to @@ -1778,7 +1778,8 @@ format_reply(binary, _, N, Data) when N > 0 -> % Header mode format_reply(binary, _, _, Data) -> Data; format_reply(list, Packet, _, Data) - when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} -> + when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers}; Packet == httph; + Packet == httph_bin-> Data; format_reply(list, _,_, Data) -> binary_to_list(Data). @@ -2090,7 +2091,9 @@ set_socket_opts(Socket, [{packet, Packet}| Opts], SockOpts, Other) when Packet = Packet == tpkt; Packet == line; Packet == http; - Packet == http_bin -> + Packet == httph; + Packet == http_bin; + Packet == httph_bin -> set_socket_opts(Socket, Opts, SockOpts#socket_options{packet = Packet}, Other); set_socket_opts(_, [{packet, _} = Opt| _], SockOpts, _) -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 4e74aec4ac..453ea20f99 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -48,7 +48,7 @@ %% Internal application API %%==================================================================== %%-------------------------------------------------------------------- --spec client_hello(host(), port_num(), #connection_states{}, +-spec client_hello(host(), inet:port_number(), #connection_states{}, #ssl_options{}, boolean(), der_cert()) -> #client_hello{}. %% %% Description: Creates a client hello message. @@ -106,7 +106,7 @@ hello_request() -> %%-------------------------------------------------------------------- -spec hello(#server_hello{} | #client_hello{}, #ssl_options{}, - #connection_states{} | {port_num(), #session{}, db_handle(), + #connection_states{} | {inet:port_number(), #session{}, db_handle(), atom(), #connection_states{}, binary()}, boolean()) -> {tls_version(), session_id(), #connection_states{}}| {tls_version(), {resumed | new, #session{}}, @@ -383,8 +383,9 @@ master_secret(Version, #session{master_secret = Mastersecret}, ConnectionStates, Role) catch exit:Reason -> - error_logger:error_report("Key calculation failed due to ~p", - [Reason]), + Report = io_lib:format("Key calculation failed due to ~p", + [Reason]), + error_logger:error_report(Report), ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE) end; @@ -400,8 +401,9 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) -> SecParams, ConnectionStates, Role) catch exit:Reason -> - error_logger:error_report("Master secret calculation failed" - " due to ~p", [Reason]), + Report = io_lib:format("Master secret calculation failed" + " due to ~p", [Reason]), + error_logger:error_report(Report), ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE) end. diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index cc66246068..6bf1edc452 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -28,8 +28,7 @@ -type reply() :: term(). -type msg() :: term(). -type from() :: term(). --type host() :: string() | tuple(). --type port_num() :: integer(). +-type host() :: inet:ip_address() | inet:hostname(). -type session_id() :: 0 | binary(). -type tls_version() :: {integer(), integer()}. -type tls_atom_version() :: sslv3 | tlsv1. diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index b02815bfd8..725a085d1f 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -113,7 +113,7 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) -> issuer_candidate(PrevCandidateKey, DbHandle) -> ssl_certificate_db:issuer_candidate(PrevCandidateKey, DbHandle). %%-------------------------------------------------------------------- --spec client_session_id(host(), port_num(), #ssl_options{}, +-spec client_session_id(host(), inet:port_number(), #ssl_options{}, der_cert() | undefined) -> session_id(). %% %% Description: Select a session id for the client. @@ -122,7 +122,7 @@ client_session_id(Host, Port, SslOpts, OwnCert) -> call({client_session_id, Host, Port, SslOpts, OwnCert}). %%-------------------------------------------------------------------- --spec server_session_id(host(), port_num(), #ssl_options{}, +-spec server_session_id(host(), inet:port_number(), #ssl_options{}, der_cert()) -> session_id(). %% %% Description: Select a session id for the server. @@ -131,8 +131,8 @@ server_session_id(Port, SuggestedSessionId, SslOpts, OwnCert) -> call({server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}). %%-------------------------------------------------------------------- --spec register_session(port_num(), #session{}) -> ok. --spec register_session(host(), port_num(), #session{}) -> ok. +-spec register_session(inet:port_number(), #session{}) -> ok. +-spec register_session(host(), inet:port_number(), #session{}) -> ok. %% %% Description: Make the session available for reuse. %%-------------------------------------------------------------------- @@ -142,8 +142,8 @@ register_session(Host, Port, Session) -> register_session(Port, Session) -> cast({register_session, Port, Session}). %%-------------------------------------------------------------------- --spec invalidate_session(port_num(), #session{}) -> ok. --spec invalidate_session(host(), port_num(), #session{}) -> ok. +-spec invalidate_session(inet:port_number(), #session{}) -> ok. +-spec invalidate_session(host(), inet:port_number(), #session{}) -> ok. %% %% Description: Make the session unavailable for reuse. After %% a the session has been marked "is_resumable = false" for some while diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl index 4c3c0b9c58..72091fdd5f 100644 --- a/lib/ssl/src/ssl_record.erl +++ b/lib/ssl/src/ssl_record.erl @@ -342,7 +342,7 @@ get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer), get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC, version = {MajVer, MinVer}, fragment = Data} | Acc]); -%% Matches a ssl v2 client hello message. +%% Matches an ssl v2 client hello message. %% The server must be able to receive such messages, from clients that %% are willing to use ssl v3 or higher, but have ssl v2 compatibility. get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>, diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl index 85c9fcb61c..bf738649f6 100644 --- a/lib/ssl/src/ssl_session.erl +++ b/lib/ssl/src/ssl_session.erl @@ -48,7 +48,7 @@ is_new(_ClientSuggestion, _ServerDecision) -> true. %%-------------------------------------------------------------------- --spec id({host(), port_num(), #ssl_options{}}, db_handle(), atom(), +-spec id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(), undefined | binary()) -> binary(). %% %% Description: Should be called by the client side to get an id @@ -63,7 +63,7 @@ id(ClientInfo, Cache, CacheCb, OwnCert) -> end. %%-------------------------------------------------------------------- --spec id(port_num(), binary(), #ssl_options{}, db_handle(), +-spec id(inet:port_number(), binary(), #ssl_options{}, db_handle(), atom(), seconds(), binary()) -> binary(). %% %% Description: Should be called by the server side to get an id diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl index 66610817be..93969f628f 100644 --- a/lib/ssl/src/ssl_session_cache.erl +++ b/lib/ssl/src/ssl_session_cache.erl @@ -28,7 +28,7 @@ -export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3, select_session/2]). --type key() :: {{host(), port_num()}, session_id()} | {port_num(), session_id()}. +-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}. %%-------------------------------------------------------------------- -spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque) @@ -91,7 +91,7 @@ foldl(Fun, Acc0, Cache) -> ets:foldl(Fun, Acc0, Cache). %%-------------------------------------------------------------------- --spec select_session(db_handle(), {host(), port_num()} | port_num()) -> [#session{}]. +-spec select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}]. %% %% Description: Selects a session that could be reused. Should be callable %% from any process. diff --git a/lib/ssl/src/ssl_ssl2.erl b/lib/ssl/src/ssl_ssl2.erl index b1005b1acb..30a3a5fc98 100644 --- a/lib/ssl/src/ssl_ssl2.erl +++ b/lib/ssl/src/ssl_ssl2.erl @@ -20,7 +20,7 @@ %% %%---------------------------------------------------------------------- %% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher -%% will send a sslv2 hello. +%% will send an sslv2 hello. %%---------------------------------------------------------------------- -module(ssl_ssl2). diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index d9f4a76d80..8da1d947d3 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -253,11 +253,11 @@ all() -> unknown_server_ca_fail, der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer, - unknown_server_ca_accept_backwardscompatibilty, + unknown_server_ca_accept_backwardscompatibility, %%different_ca_peer_sign, no_reuses_session_server_restart_new_cert, no_reuses_session_server_restart_new_cert_file, reuseaddr, - hibernate + hibernate, connect_twice ]. groups() -> @@ -3282,11 +3282,11 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -unknown_server_ca_accept_backwardscompatibilty(doc) -> +unknown_server_ca_accept_backwardscompatibility(doc) -> ["Test that old style verify_funs will work"]; -unknown_server_ca_accept_backwardscompatibilty(suite) -> +unknown_server_ca_accept_backwardscompatibility(suite) -> []; -unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) -> +unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -3609,6 +3609,54 @@ hibernate(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- + +connect_twice(doc) -> + [""]; +connect_twice(suite) -> + []; +connect_twice(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{keepalive, true},{active, false} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{keepalive, true},{active, false} + | ClientOpts]}]), + Server ! listen, + + {Client1, #sslsocket{}} = + ssl_test_lib:start_client([return_socket, + {node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{keepalive, true},{active, false} + | ClientOpts]}]), + + test_server:format("Testcase ~p, Client ~p Server ~p ~n", + [self(), Client, Server]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:check_result(Server, ok, Client1, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ssl_test_lib:close(Client1). + + +%%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- send_recv_result(Socket) -> diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index d22d5d2954..9d2599b778 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -151,6 +151,9 @@ all() -> packet_cdr_decode, packet_cdr_decode_list, packet_http_decode, packet_http_decode_list, packet_http_bin_decode_multi, packet_http_error_passive, + packet_httph_active, packet_httph_bin_active, + packet_httph_active_once, packet_httph_bin_active_once, + packet_httph_passive, packet_httph_bin_passive, packet_line_decode, packet_line_decode_list, packet_asn1_decode, packet_asn1_decode_list, packet_tpkt_decode, packet_tpkt_decode_list, @@ -1594,7 +1597,7 @@ client_http_decode(Socket, HttpRequest) -> %%-------------------------------------------------------------------- packet_http_decode_list(doc) -> ["Test setting the packet option {packet, http}, {mode, list}" - "(Body will be litst too)"]; + "(Body will be list too)"]; packet_http_decode_list(suite) -> []; packet_http_decode_list(Config) when is_list(Config) -> @@ -1804,7 +1807,304 @@ server_http_decode_error(Socket, HttpResponse) -> assert_packet_opt(Socket, http), ok = ssl:send(Socket, HttpResponse), ok. +%%-------------------------------------------------------------------- +packet_httph_active(doc) -> + ["Test setting the packet option {packet, httph}"]; +packet_httph_active(suite) -> + []; +packet_httph_active(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_active, + []}}, + {options, [{active, true}, + {packet, httph}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +server_send_trailer(Socket, Trailer)-> + ssl:send(Socket, Trailer), + ok. + +client_http_decode_trailer_active(Socket) -> + receive + {ssl, Socket, + {http_header,36,'Content-Encoding',undefined,"gzip"}} -> + ok; + Other1 -> + exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> + ok; + Other2 -> + exit({?LINE, Other2}) + end, + ok. + +%%-------------------------------------------------------------------- +packet_httph_bin_active(doc) -> + ["Test setting the packet option {packet, httph_bin}"]; +packet_httph_bin_active(suite) -> + []; +packet_httph_bin_active(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_bin_active, + []}}, + {options, [{active, true}, + {packet, httph_bin}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +client_http_decode_trailer_bin_active(Socket) -> + receive + {ssl, Socket, + {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} -> + ok; + Other1 -> + exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> + ok; + Other2 -> + exit({?LINE, Other2}) + end, + ok. +%%-------------------------------------------------------------------- +packet_httph_active_once(doc) -> + ["Test setting the packet option {packet, httph}"]; +packet_httph_active_once(suite) -> + []; +packet_httph_active_once(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_active_once, + []}}, + {options, [{active, false}, + {packet, httph}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +client_http_decode_trailer_active_once(Socket) -> + ssl:setopts(Socket, [{active, once}]), + receive + {ssl, Socket, + {http_header,36,'Content-Encoding',undefined,"gzip"}} -> + ok; + Other1 -> + exit({?LINE, Other1}) + end, + ssl:setopts(Socket, [{active, once}]), + receive + {ssl, Socket, http_eoh} -> + ok; + Other2 -> + exit({?LINE, Other2}) + end, + ok. +%%-------------------------------------------------------------------- +packet_httph_bin_active_once(doc) -> + ["Test setting the packet option {packet, httph_bin}"]; +packet_httph_bin_active_once(suite) -> + []; +packet_httph_bin_active_once(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_bin_active_once, + []}}, + {options, [{active, false}, + {packet, httph_bin}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +client_http_decode_trailer_bin_active_once(Socket) -> + ssl:setopts(Socket, [{active, once}]), + receive + {ssl, Socket, + {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} -> + ok; + Other1 -> + exit({?LINE, Other1}) + end, + ssl:setopts(Socket, [{active, once}]), + receive + {ssl, Socket, http_eoh} -> + ok; + Other2 -> + exit({?LINE, Other2}) + end, + ok. + +%%-------------------------------------------------------------------- + +packet_httph_passive(doc) -> + ["Test setting the packet option {packet, httph}"]; +packet_httph_passive(suite) -> + []; +packet_httph_passive(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_passive, + []}}, + {options, [{active, false}, + {packet, httph}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +client_http_decode_trailer_passive(Socket) -> + {ok,{http_header,36,'Content-Encoding',undefined,"gzip"}} = ssl:recv(Socket, 0), + {ok, http_eoh} = ssl:recv(Socket, 0), + ok. + +%%-------------------------------------------------------------------- +packet_httph_bin_passive(doc) -> + ["Test setting the packet option {packet, httph_bin}"]; +packet_httph_bin_passive(suite) -> + []; +packet_httph_bin_passive(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Trailer = "Content-Encoding: gzip\r\n" + "\r\n", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_send_trailer, + [Trailer]}}, + {options, [{active, true}, binary | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode_trailer_bin_passive, + []}}, + {options, [{active, false}, + {packet, httph_bin}, + list | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +client_http_decode_trailer_bin_passive(Socket) -> + {ok,{http_header,36,'Content-Encoding',undefined,<<"gzip">>}} = ssl:recv(Socket, 0), + {ok, http_eoh} = ssl:recv(Socket, 0), + ok. %%-------------------------------------------------------------------- packet_line_decode(doc) -> diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index f80ac3c1a9..5ea45018e6 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -223,15 +223,14 @@ session_cleanup(Config)when is_list(Config) -> %% Make sure session has expired and been cleaned up check_timer(SessionTimer), - test_server:sleep(?DELAY), %% Delay time + some extra time + test_server:sleep(?DELAY *2), %% Delay time + some extra time - {status, _, _, StatusInfo1} = sys:get_status(whereis(ssl_manager)), - [_, _,_, _, Prop1] = StatusInfo1, - State1 = state(Prop1), - DelayTimer = element(7, State1), + DelayTimer = get_delay_timer(), check_timer(DelayTimer), + test_server:sleep(?SLEEP), %% Make sure clean has had to run + undefined = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}), undefined = ssl_session_cache:lookup(Cache, {Port, Id}), @@ -253,6 +252,18 @@ check_timer(Timer) -> test_server:sleep(Int), check_timer(Timer) end. + +get_delay_timer() -> + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = state(Prop), + case element(7, State) of + undefined -> + test_server:sleep(?SLEEP), + get_delay_timer(); + DelayTimer -> + DelayTimer + end. %%-------------------------------------------------------------------- session_cache_process_list(doc) -> ["Test reuse of sessions (short handshake)"]; |