aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/ssl_handshake.erl
diff options
context:
space:
mode:
authorRaimo Niskanen <[email protected]>2016-07-19 10:55:30 +0200
committerRaimo Niskanen <[email protected]>2016-07-21 10:42:52 +0200
commita138a928849f3b68a2542f2592e95e7362217e3d (patch)
tree8690ce3064c9c75477c5ad495a61d9d30fcff2ed /lib/ssl/src/ssl_handshake.erl
parent53e7743216647d810d529e397bd3ea7278c6047c (diff)
downloadotp-a138a928849f3b68a2542f2592e95e7362217e3d.tar.gz
otp-a138a928849f3b68a2542f2592e95e7362217e3d.tar.bz2
otp-a138a928849f3b68a2542f2592e95e7362217e3d.zip
Improve version selection
Use the list of versions that the server allows and among those choose the highest version that is not higher than the client's version. Note that this chosen version might be lower than the client's version, but is used to improve interoperability. Patch suggested by Dimitry Borisov refering to RFC 5246 appendix E.1.
Diffstat (limited to 'lib/ssl/src/ssl_handshake.erl')
-rw-r--r--lib/ssl/src/ssl_handshake.erl38
1 files changed, 35 insertions, 3 deletions
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 235d6efbb6..43b0c42f8d 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1258,8 +1258,40 @@ handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
end.
select_version(RecordCB, ClientVersion, Versions) ->
- ServerVersion = RecordCB:highest_protocol_version(Versions),
- RecordCB:lowest_protocol_version(ClientVersion, ServerVersion).
+ do_select_version(RecordCB, ClientVersion, Versions).
+
+do_select_version(_, ClientVersion, []) ->
+ ClientVersion;
+do_select_version(RecordCB, ClientVersion, [Version | Versions]) ->
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client - keep looking
+ do_select_version(RecordCB, ClientVersion, Versions);
+ false ->
+ %% Version ok for client - look for a higher
+ do_select_version(RecordCB, ClientVersion, Versions, Version)
+ end.
+%%
+do_select_version(_, _, [], GoodVersion) ->
+ GoodVersion;
+do_select_version(
+ RecordCB, ClientVersion, [Version | Versions], GoodVersion) ->
+ BetterVersion =
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client
+ GoodVersion;
+ false ->
+ %% Version ok for client
+ case RecordCB:is_higher(Version, GoodVersion) of
+ true ->
+ %% Use higher version
+ Version;
+ false ->
+ GoodVersion
+ end
+ end,
+ do_select_version(RecordCB, ClientVersion, Versions, BetterVersion).
renegotiation_info(_, client, _, false) ->
#renegotiation_info{renegotiated_connection = undefined};