aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/ssl_alert.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/ssl_alert.erl')
-rw-r--r--lib/ssl/src/ssl_alert.erl91
1 files changed, 69 insertions, 22 deletions
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index eb1228afa4..696a55e4b9 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -1,18 +1,19 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%
%% %CopyrightEnd%
%%
@@ -29,15 +30,25 @@
-include("ssl_alert.hrl").
-include("ssl_record.hrl").
+-include("ssl_internal.hrl").
--export([alert_txt/1, reason_code/2]).
+-export([decode/1, alert_txt/1, reason_code/2]).
%%====================================================================
%% Internal application API
%%====================================================================
+
%%--------------------------------------------------------------------
--spec reason_code(#alert{}, client | server) -> closed | esslconnect |
- esslaccept | string().
+-spec decode(binary()) -> [#alert{}] | #alert{}.
+%%
+%% Description: Decode alert(s), will return a singel own alert if peer
+%% sends garbage or too many warning alerts.
+%%--------------------------------------------------------------------
+decode(Bin) ->
+ decode(Bin, [], 0).
+
+%%--------------------------------------------------------------------
+-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}.
%%
%% Description: Returns the error reason that will be returned to the
%% user.
@@ -45,26 +56,42 @@
reason_code(#alert{description = ?CLOSE_NOTIFY}, _) ->
closed;
-reason_code(#alert{description = ?HANDSHAKE_FAILURE}, client) ->
- esslconnect;
-reason_code(#alert{description = ?HANDSHAKE_FAILURE}, server) ->
- esslaccept;
reason_code(#alert{description = Description}, _) ->
- description_txt(Description).
+ {tls_alert, description_txt(Description)}.
%%--------------------------------------------------------------------
-spec alert_txt(#alert{}) -> string().
%%
%% Description: Returns the error string for given alert.
%%--------------------------------------------------------------------
-
-alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}}) ->
+alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined}) ->
Mod ++ ":" ++ integer_to_list(Line) ++ ":" ++
- level_txt(Level) ++" "++ description_txt(Description).
+ level_txt(Level) ++" "++ description_txt(Description);
+alert_txt(#alert{reason = Reason} = Alert) ->
+ BaseTxt = alert_txt(Alert#alert{reason = undefined}),
+ FormatDepth = 9, % Some limit on printed representation of an error
+ ReasonTxt = lists:flatten(io_lib:format("~P", [Reason, FormatDepth])),
+ BaseTxt ++ " - " ++ ReasonTxt.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+
+%% It is very unlikely that an correct implementation will send more than one alert at the time
+%% So it there is more than 10 warning alerts we consider it an error
+decode(<<?BYTE(Level), ?BYTE(_), _/binary>>, _, N) when Level == ?WARNING, N > ?MAX_ALERTS ->
+ ?ALERT_REC(?FATAL, ?DECODE_ERROR, too_many_remote_alerts);
+decode(<<?BYTE(Level), ?BYTE(Description), Rest/binary>>, Acc, N) when Level == ?WARNING ->
+ Alert = ?ALERT_REC(Level, Description),
+ decode(Rest, [Alert | Acc], N + 1);
+decode(<<?BYTE(Level), ?BYTE(Description), _Rest/binary>>, Acc, _) when Level == ?FATAL->
+ Alert = ?ALERT_REC(Level, Description),
+ lists:reverse([Alert | Acc]); %% No need to decode rest fatal alert will end the connection
+decode(<<?BYTE(_Level), _/binary>>, _, _) ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, failed_to_decode_remote_alert);
+decode(<<>>, Acc, _) ->
+ lists:reverse(Acc, []).
+
level_txt(?WARNING) ->
"Warning:";
level_txt(?FATAL) ->
@@ -84,6 +111,8 @@ description_txt(?DECOMPRESSION_FAILURE) ->
"decompression failure";
description_txt(?HANDSHAKE_FAILURE) ->
"handshake failure";
+description_txt(?NO_CERTIFICATE_RESERVED) ->
+ "No certificate reserved";
description_txt(?BAD_CERTIFICATE) ->
"bad certificate";
description_txt(?UNSUPPORTED_CERTIFICATE) ->
@@ -115,4 +144,22 @@ description_txt(?INTERNAL_ERROR) ->
description_txt(?USER_CANCELED) ->
"user canceled";
description_txt(?NO_RENEGOTIATION) ->
- "no renegotiation".
+ "no renegotiation";
+description_txt(?UNSUPPORTED_EXTENSION) ->
+ "unsupported extension";
+description_txt(?CERTIFICATE_UNOBTAINABLE) ->
+ "certificate unobtainable";
+description_txt(?UNRECOGNISED_NAME) ->
+ "unrecognised name";
+description_txt(?BAD_CERTIFICATE_STATUS_RESPONSE) ->
+ "bad certificate status response";
+description_txt(?BAD_CERTIFICATE_HASH_VALUE) ->
+ "bad certificate hash value";
+description_txt(?UNKNOWN_PSK_IDENTITY) ->
+ "unknown psk identity";
+description_txt(?INAPPROPRIATE_FALLBACK) ->
+ "inappropriate fallback";
+description_txt(?NO_APPLICATION_PROTOCOL) ->
+ "no application protocol";
+description_txt(Enum) ->
+ lists:flatten(io_lib:format("unsupported/unknown alert: ~p", [Enum])).