diff options
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/dtls.erl | 46 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 43 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 6 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.hrl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_internal.hrl | 10 | ||||
-rw-r--r-- | lib/ssl/src/ssl_manager.erl | 8 | ||||
-rw-r--r-- | lib/ssl/src/ssl_pkix_db.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/tls.erl | 45 | ||||
-rw-r--r-- | lib/ssl/src/tls_record.erl | 4 |
9 files changed, 95 insertions, 75 deletions
diff --git a/lib/ssl/src/dtls.erl b/lib/ssl/src/dtls.erl index 1cad9560b5..780bddeb10 100644 --- a/lib/ssl/src/dtls.erl +++ b/lib/ssl/src/dtls.erl @@ -31,25 +31,29 @@ handshake/1, handshake/2, handshake/3]). %%-------------------------------------------------------------------- +%% +%% Description: Connect to a DTLS server. +%%-------------------------------------------------------------------- + -spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} | {error, reason()}. + +connect(Socket, Options) when is_port(Socket) -> + connect(Socket, Options, infinity). + -spec connect(host() | port(), [connect_option()] | inet:port_number(), timeout() | list()) -> {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), inet:port_number(), list(), timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. - -%% -%% Description: Connect to an DTLS server. -%%-------------------------------------------------------------------- -connect(Socket, Options) when is_port(Socket) -> - connect(Socket, Options, infinity). connect(Socket, SslOptions, Timeout) when is_port(Socket) -> DTLSOpts = [{protocol, dtls} | SslOptions], ssl:connect(Socket, DTLSOpts, Timeout); connect(Host, Port, Options) -> connect(Host, Port, Options, infinity). + +-spec connect(host() | port(), inet:port_number(), list(), timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. + connect(Host, Port, Options, Timeout) -> DTLSOpts = [{protocol, dtls} | Options], ssl:connect(Host, Port, DTLSOpts, Timeout). @@ -65,38 +69,44 @@ listen(Port, Options) -> ssl:listen(Port, DTLSOpts). %%-------------------------------------------------------------------- --spec accept(#sslsocket{}) -> {ok, #sslsocket{}} | - {error, reason()}. --spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | - {error, reason()}. %% %% Description: Performs transport accept on an ssl listen socket %%-------------------------------------------------------------------- +-spec accept(#sslsocket{}) -> {ok, #sslsocket{}} | + {error, reason()}. accept(ListenSocket) -> accept(ListenSocket, infinity). + +-spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | + {error, reason()}. accept(Socket, Timeout) -> ssl:transport_accept(Socket, Timeout). %%-------------------------------------------------------------------- --spec handshake(#sslsocket{}) -> ok | {error, reason()}. --spec handshake(#sslsocket{} | port(), timeout()| [ssl_option() - | transport_option()]) -> - ok | {ok, #sslsocket{}} | {error, reason()}. --spec handshake(port(), [ssl_option()| transport_option()], timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. %% %% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- +-spec handshake(#sslsocket{}) -> ok | {error, reason()}. + handshake(ListenSocket) -> handshake(ListenSocket, infinity). + +-spec handshake(#sslsocket{} | port(), timeout()| [ssl_option() + | transport_option()]) -> + ok | {ok, #sslsocket{}} | {error, reason()}. + handshake(#sslsocket{} = Socket, Timeout) -> ssl:ssl_accept(Socket, Timeout); handshake(ListenSocket, SslOptions) when is_port(ListenSocket) -> handshake(ListenSocket, SslOptions, infinity). + +-spec handshake(port(), [ssl_option()| transport_option()], timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. + handshake(Socket, SslOptions, Timeout) when is_port(Socket) -> ssl:ssl_accept(Socket, SslOptions, Timeout). diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 7edc6554ca..c3bdeb1a54 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -626,7 +626,7 @@ handle_options(Opts0, _Role) -> user_lookup_fun = handle_option(user_lookup_fun, Opts, undefined), psk_identity = handle_option(psk_identity, Opts, undefined), srp_identity = handle_option(srp_identity, Opts, undefined), - ciphers = handle_option(ciphers, Opts, []), + ciphers = handle_cipher_option(proplists:get_value(ciphers, Opts, []), hd(Versions)), %% Server side option reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun), reuse_sessions = handle_option(reuse_sessions, Opts, true), @@ -769,15 +769,6 @@ validate_option(srp_identity, {Username, Password}) {unicode:characters_to_binary(Username), unicode:characters_to_binary(Password)}; -validate_option(ciphers, Value) when is_list(Value) -> - Version = tls_record:highest_protocol_version([]), - try cipher_suites(Version, Value) - catch - exit:_ -> - throw({error, {options, {ciphers, Value}}}); - error:_-> - throw({error, {options, {ciphers, Value}}}) - end; validate_option(reuse_session, Value) when is_function(Value) -> Value; validate_option(reuse_sessions, Value) when is_boolean(Value) -> @@ -937,16 +928,26 @@ emulated_options([Opt|Opts], Inet, Emulated) -> emulated_options([], Inet,Emulated) -> {Inet, Emulated}. -cipher_suites(Version, []) -> +handle_cipher_option(Value, Version) when is_list(Value) -> + try binary_cipher_suites(Version, Value) of + Suites -> + Suites + catch + exit:_ -> + throw({error, {options, {ciphers, Value}}}); + error:_-> + throw({error, {options, {ciphers, Value}}}) + end. +binary_cipher_suites(Version, []) -> %% Defaults to all supported suits ssl_cipher:suites(Version); -cipher_suites(Version, [{_,_,_,_}| _] = Ciphers0) -> %% Backwards compatibility +binary_cipher_suites(Version, [{_,_,_,_}| _] = Ciphers0) -> %% Backwards compatibility Ciphers = [{KeyExchange, Cipher, Hash} || {KeyExchange, Cipher, Hash, _} <- Ciphers0], - cipher_suites(Version, Ciphers); -cipher_suites(Version, [{_,_,_}| _] = Ciphers0) -> + binary_cipher_suites(Version, Ciphers); +binary_cipher_suites(Version, [{_,_,_}| _] = Ciphers0) -> Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0], - cipher_suites(Version, Ciphers); + binary_cipher_suites(Version, Ciphers); -cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> +binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> Supported0 = ssl_cipher:suites(Version) ++ ssl_cipher:anonymous_suites() ++ ssl_cipher:psk_suites(Version) @@ -954,18 +955,18 @@ cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> Supported = ssl_cipher:filter_suites(Supported0), case [Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported)] of [] -> - Supported; + Supported; %% Defaults to all supported suits Ciphers -> Ciphers end; -cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) -> +binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) -> %% Format: ["RC4-SHA","RC4-MD5"] Ciphers = [ssl_cipher:openssl_suite(C) || C <- Ciphers0], - cipher_suites(Version, Ciphers); -cipher_suites(Version, Ciphers0) -> + binary_cipher_suites(Version, Ciphers); +binary_cipher_suites(Version, Ciphers0) -> %% Format: "RC4-SHA:RC4-MD5" Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:tokens(Ciphers0, ":")], - cipher_suites(Version, Ciphers). + binary_cipher_suites(Version, Ciphers). unexpected_format(Error) -> lists:flatten(io_lib:format("Unexpected error: ~p", [Error])). diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 82106935cb..e283e6079e 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2013. All Rights Reserved. +%% Copyright Ericsson AB 2013-2014. 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 @@ -1757,12 +1757,12 @@ handle_unrecv_data(StateName, #state{socket = Socket, transport_cb = Transport, Connection:handle_close_alert(Data, StateName, State) end. -handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>}}) -> +handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cacerts = []}}) -> %% No trusted certs specified ok; handle_trusted_certs_db(#state{cert_db_ref = Ref, cert_db = CertDb, - ssl_options = #ssl_options{cacertfile = undefined}}) -> + ssl_options = #ssl_options{cacertfile = <<>>}}) -> %% Certs provided as DER directly can not be shared %% with other connections and it is safe to delete them when the connection ends. ssl_pkix_db:remove_trusted_certs(Ref, CertDb); diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index adb2e1debe..341a4217e4 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2013. All Rights Reserved. +%% Copyright Ericsson AB 2013-2014. 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 @@ -73,7 +73,7 @@ renegotiation :: undefined | {boolean(), From::term() | internal | peer}, start_or_recv_from :: term(), timer :: undefined | reference(), % start_or_recive_timer - send_queue :: queue(), + send_queue :: queue:queue(), terminated = false ::boolean(), allow_renegotiate = true ::boolean(), expecting_next_protocol_negotiation = false ::boolean(), diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 102215119d..64b89e9f95 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. 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 @@ -82,13 +82,13 @@ validate_extensions_fun, depth :: integer(), certfile :: binary(), - cert :: der_encoded(), + cert :: public_key:der_encoded(), keyfile :: binary(), - key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', der_encoded()}, + key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()}, password :: string(), - cacerts :: [der_encoded()], + cacerts :: [public_key:der_encoded()], cacertfile :: binary(), - dh :: der_encoded(), + dh :: public_key:der_encoded(), dhfile :: binary(), user_lookup_fun, % server option, fun to lookup the user psk_identity :: binary(), diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 4d5eaeb607..fbc73e0e42 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -167,27 +167,27 @@ clean_cert_db(Ref, File) -> 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. %%-------------------------------------------------------------------- +-spec register_session(host(), inet:port_number(), #session{}) -> ok. register_session(Host, Port, Session) -> cast({register_session, Host, Port, Session}). +-spec register_session(inet:port_number(), #session{}) -> ok. register_session(Port, Session) -> cast({register_session, Port, Session}). %%-------------------------------------------------------------------- --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 %% it will be safe to remove the data from the session database. %%-------------------------------------------------------------------- +-spec invalidate_session(host(), inet:port_number(), #session{}) -> ok. invalidate_session(Host, Port, Session) -> cast({invalidate_session, Host, Port, Session}). +-spec invalidate_session(inet:port_number(), #session{}) -> ok. invalidate_session(Port, Session) -> cast({invalidate_session, Port, Session}). diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl index 9de50c8f26..e59aba0618 100644 --- a/lib/ssl/src/ssl_pkix_db.erl +++ b/lib/ssl/src/ssl_pkix_db.erl @@ -115,17 +115,17 @@ add_trusted_certs(_Pid, File, [CertsDb, RefDb, PemChache] = Db) -> new_trusted_cert_entry({MD5, File}, Db) end. %%-------------------------------------------------------------------- --spec cache_pem_file({binary(), binary()}, [db_handle()]) -> {ok, term()}. --spec cache_pem_file(reference(), {binary(), binary()}, [db_handle()]) -> {ok, term()}. %% %% Description: Cache file as binary in DB %%-------------------------------------------------------------------- +-spec cache_pem_file({binary(), binary()}, [db_handle()]) -> {ok, term()}. cache_pem_file({MD5, File}, [_CertsDb, _RefDb, PemChache]) -> {ok, PemBin} = file:read_file(File), Content = public_key:pem_decode(PemBin), insert(MD5, Content, PemChache), {ok, Content}. +-spec cache_pem_file(reference(), {binary(), binary()}, [db_handle()]) -> {ok, term()}. cache_pem_file(Ref, {MD5, File}, [_CertsDb, _RefDb, PemChache]) -> {ok, PemBin} = file:read_file(File), Content = public_key:pem_decode(PemBin), diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl index 3e7b2db9c2..c829129250 100644 --- a/lib/ssl/src/tls.erl +++ b/lib/ssl/src/tls.erl @@ -30,25 +30,29 @@ handshake/1, handshake/2, handshake/3]). %%-------------------------------------------------------------------- --spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} | - {error, reason()}. --spec connect(host() | port(), [connect_option()] | inet:port_number(), - timeout() | list()) -> - {ok, #sslsocket{}} | {error, reason()}. --spec connect(host() | port(), inet:port_number(), list(), timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. - %% %% Description: Connect to an TLS server. %%-------------------------------------------------------------------- +-spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} | + {error, reason()}. + connect(Socket, Options) when is_port(Socket) -> connect(Socket, Options, infinity). + +-spec connect(host() | port(), [connect_option()] | inet:port_number(), + timeout() | list()) -> + {ok, #sslsocket{}} | {error, reason()}. + connect(Socket, SslOptions, Timeout) when is_port(Socket) -> TLSOpts = [{protocol, tls} | SslOptions], ssl:connect(Socket, TLSOpts, Timeout); connect(Host, Port, Options) -> connect(Host, Port, Options, infinity). + +-spec connect(host() | port(), inet:port_number(), list(), timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. + connect(Host, Port, Options, Timeout) -> TLSOpts = [{protocol, tls} | Options], ssl:connect(Host, Port, TLSOpts, Timeout). @@ -64,39 +68,44 @@ listen(Port, Options) -> ssl:listen(Port, TLSOpts). %%-------------------------------------------------------------------- --spec accept(#sslsocket{}) -> {ok, #sslsocket{}} | - {error, reason()}. --spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | - {error, reason()}. %% %% Description: Performs transport accept on an ssl listen socket %%-------------------------------------------------------------------- +-spec accept(#sslsocket{}) -> {ok, #sslsocket{}} | + {error, reason()}. accept(ListenSocket) -> accept(ListenSocket, infinity). + +-spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | + {error, reason()}. accept(Socket, Timeout) -> ssl:transport_accept(Socket, Timeout). %%-------------------------------------------------------------------- --spec handshake(#sslsocket{}) -> ok | {error, reason()}. --spec handshake(#sslsocket{} | port(), timeout()| [ssl_option() - | transport_option()]) -> - ok | {ok, #sslsocket{}} | {error, reason()}. --spec handshake(port(), [ssl_option()| transport_option()], timeout()) -> - {ok, #sslsocket{}} | {error, reason()}. %% %% Description: Performs accept on an ssl listen socket. e.i. performs %% ssl handshake. %%-------------------------------------------------------------------- +-spec handshake(#sslsocket{}) -> ok | {error, reason()}. + handshake(ListenSocket) -> handshake(ListenSocket, infinity). +-spec handshake(#sslsocket{} | port(), timeout()| [ssl_option() + | transport_option()]) -> + ok | {ok, #sslsocket{}} | {error, reason()}. + handshake(#sslsocket{} = Socket, Timeout) -> ssl:ssl_accept(Socket, Timeout); handshake(ListenSocket, SslOptions) when is_port(ListenSocket) -> handshake(ListenSocket, SslOptions, infinity). + +-spec handshake(port(), [ssl_option()| transport_option()], timeout()) -> + {ok, #sslsocket{}} | {error, reason()}. + handshake(Socket, SslOptions, Timeout) when is_port(Socket) -> ssl:ssl_accept(Socket, SslOptions, Timeout). diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl index 88107557a0..8c0c4f3c91 100644 --- a/lib/ssl/src/tls_record.erl +++ b/lib/ssl/src/tls_record.erl @@ -262,18 +262,18 @@ supported_protocol_versions([_|_] = Vsns) -> Vsns. %%-------------------------------------------------------------------- --spec is_acceptable_version(tls_version()) -> boolean(). --spec is_acceptable_version(tls_version(), Supported :: [tls_version()]) -> boolean(). %% %% Description: ssl version 2 is not acceptable security risks are too big. %% %%-------------------------------------------------------------------- +-spec is_acceptable_version(tls_version()) -> boolean(). is_acceptable_version({N,_}) when N >= ?LOWEST_MAJOR_SUPPORTED_VERSION -> true; is_acceptable_version(_) -> false. +-spec is_acceptable_version(tls_version(), Supported :: [tls_version()]) -> boolean(). is_acceptable_version({N,_} = Version, Versions) when N >= ?LOWEST_MAJOR_SUPPORTED_VERSION -> lists:member(Version, Versions); |