aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2017-10-17 16:22:00 +0200
committerIngela Anderton Andin <[email protected]>2017-10-17 16:22:00 +0200
commit30c3930fb296f46bac334cb6a5856a747984f69d (patch)
treec34f0cc000246bbbde8ebb1ea55794cc227844c7 /lib/ssl/src
parent5b696724cc894691da09bef0675dde5e2c0adaa9 (diff)
parent290c920aca365968ebaa10a63e25fd2579bce408 (diff)
downloadotp-30c3930fb296f46bac334cb6a5856a747984f69d.tar.gz
otp-30c3930fb296f46bac334cb6a5856a747984f69d.tar.bz2
otp-30c3930fb296f46bac334cb6a5856a747984f69d.zip
Merge branch 'maint'
Diffstat (limited to 'lib/ssl/src')
-rw-r--r--lib/ssl/src/ssl.erl2
-rw-r--r--lib/ssl/src/ssl_certificate.erl38
-rw-r--r--lib/ssl/src/ssl_connection.erl11
-rw-r--r--lib/ssl/src/ssl_handshake.erl18
4 files changed, 54 insertions, 15 deletions
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 62da498e76..bb493ed14c 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1003,7 +1003,7 @@ validate_option(server_name_indication = Opt, Value) when is_list(Value) ->
validate_option(server_name_indication, undefined = Value) ->
Value;
validate_option(server_name_indication, disable) ->
- undefined;
+ disable;
validate_option(sni_hosts, []) ->
[];
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 0dd5e5c5cf..a3333d35e9 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -138,13 +138,8 @@ validate(_, {bad_cert, _} = Reason, _) ->
{fail, Reason};
validate(_, valid, UserState) ->
{valid, UserState};
-validate(Cert, valid_peer, UserState = {client, _,_, Hostname, _, _}) when Hostname =/= undefined ->
- case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}]) of
- true ->
- {valid, UserState};
- false ->
- {fail, {bad_cert, hostname_check_failed}}
- end;
+validate(Cert, valid_peer, UserState = {client, _,_, Hostname, _, _}) when Hostname =/= disable ->
+ verify_hostname(Hostname, Cert, UserState);
validate(_, valid_peer, UserState) ->
{valid, UserState}.
@@ -337,3 +332,32 @@ new_trusteded_chain(DerCert, [_ | Rest]) ->
new_trusteded_chain(DerCert, Rest);
new_trusteded_chain(_, []) ->
unknown_ca.
+
+verify_hostname({fallback, Hostname}, Cert, UserState) when is_list(Hostname) ->
+ case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}]) of
+ true ->
+ {valid, UserState};
+ false ->
+ case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}]) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end
+ end;
+
+verify_hostname({fallback, Hostname}, Cert, UserState) ->
+ case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}]) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end;
+
+verify_hostname(Hostname, Cert, UserState) ->
+ case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}]) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end.
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 56ba952e67..d83c9cb59f 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -511,12 +511,13 @@ certify(internal, #certificate{},
certify(internal, #certificate{} = Cert,
#state{negotiated_version = Version,
role = Role,
+ host = Host,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
crl_db = CRLDbInfo,
ssl_options = Opts} = State, Connection) ->
case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef,
- Opts, CRLDbInfo, Role) of
+ Opts, CRLDbInfo, Role, Host) of
{PeerCert, PublicKeyInfo} ->
handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false}, Connection);
@@ -725,6 +726,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
expecting_finished = true,
session = #session{master_secret = MasterSecret}
= Session0,
+ ssl_options = SslOpts,
connection_states = ConnectionStates0,
tls_handshake_history = Handshake0} = State, Connection) ->
case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished,
@@ -732,7 +734,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
get_current_prf(ConnectionStates0, read),
MasterSecret, Handshake0) of
verified ->
- Session = register_session(Role, Host, Port, Session0),
+ Session = register_session(Role, host_id(Role, Host, SslOpts), Port, Session0),
cipher_role(Role, Data, Session,
State#state{expecting_finished = false}, Connection);
#alert{} = Alert ->
@@ -2336,6 +2338,11 @@ register_session(server, _, Port, #session{is_resumable = new} = Session0) ->
register_session(_, _, _, Session) ->
Session. %% Already registered
+host_id(client, _Host, #ssl_options{server_name_indication = Hostname}) when is_list(Hostname) ->
+ Hostname;
+host_id(_, Host, _) ->
+ Host.
+
handle_new_session(NewId, CipherSuite, Compression,
#state{session = Session0,
protocol_cb = Connection} = State0) ->
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index fc4181a760..81d38a38e4 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -50,7 +50,7 @@
finished/5, next_protocol/1]).
%% Handle handshake messages
--export([certify/6, client_certificate_verify/6, certificate_verify/6, verify_signature/5,
+-export([certify/7, client_certificate_verify/6, certificate_verify/6, verify_signature/5,
master_secret/4, server_key_exchange_hash/2, verify_connection/6,
init_handshake_history/0, update_handshake_history/3, verify_server_key/5
]).
@@ -407,21 +407,21 @@ verify_signature(_, Hash, {HashAlgo, _SignAlg}, Signature,
%%--------------------------------------------------------------------
-spec certify(#certificate{}, db_handle(), certdb_ref(), #ssl_options{}, term(),
- client | server) -> {der_cert(), public_key_info()} | #alert{}.
+ client | server, inet:hostname() | inet:ip_address()) -> {der_cert(), public_key_info()} | #alert{}.
%%
%% Description: Handles a certificate handshake message
%%--------------------------------------------------------------------
certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
- Opts, CRLDbHandle, Role) ->
+ Opts, CRLDbHandle, Role, Host) ->
+ ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
[PeerCert | _] = ASN1Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
Opts#ssl_options.partial_chain),
ValidationFunAndState = validation_fun_and_state(Opts#ssl_options.verify_fun, Role,
- CertDbHandle, CertDbRef,
- Opts#ssl_options.server_name_indication,
+ CertDbHandle, CertDbRef, ServerName,
Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
case public_key:pkix_path_validation(TrustedCert,
CertPath,
@@ -1584,6 +1584,8 @@ select_shared_curve([Curve | Rest], Curves) ->
sni(undefined) ->
undefined;
+sni(disable) ->
+ undefined;
sni(Hostname) ->
#sni{hostname = Hostname}.
@@ -2434,3 +2436,9 @@ available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, Su
available_signature_algs(_, _, _, _) ->
undefined.
+server_name(_, _, server) ->
+ undefined; %% Not interesting to check your own name.
+server_name(undefined, Host, client) ->
+ {fallback, Host}; %% Fallback to Host argument to connect
+server_name(SNI, _, client) ->
+ SNI. %% If Server Name Indication is available