From fbbf7a989750930068826dc165b8567fc1ca9a76 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Thu, 31 Aug 2017 18:31:06 +0200
Subject: ssl: Add the role (server or client) to the alert message

It is desirable to be as specific as possible in the info message, so
there can be no mistake if the alert is form the peer or generated by
us. This use to be an error message, but it is better to make it an
info message as sending an ALERT ending the connection is an expected
behaviour.
---
 lib/ssl/src/ssl_alert.erl      | 24 ++++++++++++++++++++----
 lib/ssl/src/ssl_connection.erl | 23 +++++++++++++++--------
 2 files changed, 35 insertions(+), 12 deletions(-)

(limited to 'lib')

diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index 2749feb1eb..db415a3666 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -32,7 +32,7 @@
 -include("ssl_record.hrl").
 -include("ssl_internal.hrl").
 
--export([decode/1, alert_txt/1, reason_code/2]).
+-export([decode/1, own_alert_txt/1, alert_txt/1, reason_code/2]).
 
 %%====================================================================
 %% Internal application API
@@ -59,13 +59,29 @@ reason_code(#alert{description = ?CLOSE_NOTIFY}, _) ->
 reason_code(#alert{description = Description}, _) ->
     {tls_alert, string:to_lower(description_txt(Description))}.
 
+%%--------------------------------------------------------------------
+-spec own_alert_txt(#alert{}) -> string().
+%%
+%% Description: Returns the error string for given alert generated
+%% by the erlang implementation.
+%%--------------------------------------------------------------------
+own_alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined, role = Role}) ->
+    "at " ++ Mod ++ ":" ++ integer_to_list(Line) ++ " generated " ++ string:to_upper(atom_to_list(Role)) ++ " ALERT: " ++
+        level_txt(Level) ++ description_txt(Description);
+own_alert_txt(#alert{reason = Reason} = Alert) ->
+    BaseTxt = own_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.
+
 %%--------------------------------------------------------------------
 -spec alert_txt(#alert{}) -> string().
 %%
-%% Description: Returns the error string for given alert.
+%% Description: Returns the error string for given alert received from
+%% the peer. 
 %%--------------------------------------------------------------------
-alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined, role = Role}) ->
-    "at " ++ Mod ++ ":" ++ integer_to_list(Line) ++ " " ++ string:to_upper(atom_to_list(Role)) ++ " ALERT: " ++
+alert_txt(#alert{level = Level, description = Description, reason = undefined, role = Role}) ->
+    "received " ++ string:to_upper(atom_to_list(Role)) ++ " ALERT: " ++
         level_txt(Level) ++ description_txt(Description);
 alert_txt(#alert{reason = Reason} = Alert) ->
     BaseTxt = alert_txt(Alert#alert{reason = undefined}),
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 5cd66387ae..b031d3d47b 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1144,7 +1144,8 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName,
 		    port = Port, session = Session, user_application = {_Mon, Pid},
 		    role = Role, socket_options = Opts, tracker = Tracker}) ->
     invalidate_session(Role, Host, Port, Session),
-    log_alert(SslOpts#ssl_options.log_alert,  Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+    log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), 
+              StateName, Alert#alert{role = opposite_role(Role)}),
     alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
     {stop, normal};
 
@@ -1155,7 +1156,8 @@ handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
 
 handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName, 
 	     #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection, renegotiation = {true, internal}} = State) ->
-    log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+    log_alert(SslOpts#ssl_options.log_alert, Role, 
+              Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
     handle_normal_shutdown(Alert, StateName, State),
     {stop, {shutdown, peer_close}};
 
@@ -1163,7 +1165,8 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
 	     #state{role = Role,
                     ssl_options = SslOpts, renegotiation = {true, From},
 		    protocol_cb = Connection} = State0) ->
-    log_alert(SslOpts#ssl_options.log_alert,  Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+    log_alert(SslOpts#ssl_options.log_alert,  Role,
+              Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
     gen_statem:reply(From, {error, renegotiation_rejected}),
     {Record, State} = Connection:next_record(State0),
     %% Go back to connection!
@@ -1172,7 +1175,8 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
 %% Gracefully log and ignore all other warning alerts
 handle_alert(#alert{level = ?WARNING} = Alert, StateName,
 	     #state{ssl_options = SslOpts, protocol_cb = Connection, role = Role} = State0) ->
-    log_alert(SslOpts#ssl_options.log_alert,  Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+    log_alert(SslOpts#ssl_options.log_alert,  Role,
+              Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
     {Record, State} = Connection:next_record(State0),
     Connection:next_event(StateName, Record, State).
 
@@ -2372,10 +2376,13 @@ alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connectio
 							Transport, Socket, Connection, Tracker), ReasonCode})
     end.
 
-log_alert(true, ProtocolName, StateName, Alert) ->
+log_alert(true, Role, ProtocolName, StateName, #alert{role = Role} = Alert) ->
+    Txt = ssl_alert:own_alert_txt(Alert),
+    error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+log_alert(true, Role, ProtocolName, StateName, Alert) ->
     Txt = ssl_alert:alert_txt(Alert),
-    error_logger:format("~s: In state ~p ~s\n", [ProtocolName, StateName, Txt]);
-log_alert(false, _, _, _) ->
+    error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+log_alert(false, _, _, _, _) ->
     ok.
 
 handle_own_alert(Alert, Version, StateName, 
@@ -2393,7 +2400,7 @@ handle_own_alert(Alert, Version, StateName,
 	    ignore
     end,
     try %% Try to tell the local user
-	log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = Role}),
+	log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert#alert{role = Role}),
 	handle_normal_shutdown(Alert,StateName, State)
     catch _:_ ->
 	    ok
-- 
cgit v1.2.3