Skip to content

Commit 54fad6d

Browse files
Stefan Zegenhagenproxyles
Stefan Zegenhagen
authored andcommitted
Improve interoperability with SSH clients
This patch fixes a few problems of the SSH shell server that affect the interoperability with SSH clients in widespread use. First problem is that, whenever a channel_request message is received with want_reply=true, the reply ends up being sent to the servers channel id, not the clients channel id. This causes the client to terminate the connection. The easiest solution to the problem appears to be a new function in ssh_connection_manager.erl that translates the servers channel id before sending the reply (in the same manner as other functions do it). Second problem is in ssh_cli.erl. When an SSH client sends a window_change request between PTY allocation and starting the shell (which appears to happen with some clients), ssh_cli.erl crashes because #state.buf is yet 'undefined'. Allocating an empty buffer at PTY allocation time solves the problem. Affected SSH clients: - all clients based on SSH-2.0-TrileadSSH2Java_213 (problem #1) - SSH Term Pro (problem #2)
1 parent a24c49a commit 54fad6d

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed

lib/ssh/src/ssh_cli.erl

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ handle_ssh_msg({ssh_cm, ConnectionManager,
8181
height = not_zero(Height, 24),
8282
pixel_width = PixWidth,
8383
pixel_height = PixHeight,
84-
modes = Modes}},
84+
modes = Modes},
85+
buf = empty_buf()},
8586
set_echo(State),
8687
ssh_connection:reply_request(ConnectionManager, WantReply,
8788
success, ChannelId),

lib/ssh/src/ssh_connection.erl

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ close(ConnectionManager, ChannelId) ->
177177
%% Description: Send status replies to requests that want such replies.
178178
%%--------------------------------------------------------------------
179179
reply_request(ConnectionManager, true, Status, ChannelId) ->
180-
ConnectionManager ! {ssh_cm, self(), {Status, ChannelId}},
180+
ssh_connection_manager:reply_request(ConnectionManager, Status, ChannelId),
181181
ok;
182182
reply_request(_,false, _, _) ->
183183
ok.

lib/ssh/src/ssh_connection_manager.erl

+14-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
close/2, stop/1, send/5,
4141
send_eof/2]).
4242

43-
-export([open_channel/6, request/6, request/7, global_request/4, event/2,
43+
-export([open_channel/6, reply_request/3, request/6, request/7, global_request/4, event/2,
4444
cast/2]).
4545

4646
%% Internal application API and spawn
@@ -95,6 +95,9 @@ request(ConnectionManager, ChannelId, Type, true, Data, Timeout) ->
9595
request(ConnectionManager, ChannelId, Type, false, Data, _) ->
9696
cast(ConnectionManager, {request, ChannelId, Type, Data}).
9797

98+
reply_request(ConnectionManager, Status, ChannelId) ->
99+
cast(ConnectionManager, {reply_request, Status, ChannelId}).
100+
98101
global_request(ConnectionManager, Type, true = Reply, Data) ->
99102
case call(ConnectionManager,
100103
{global_request, self(), Type, Reply, Data}) of
@@ -443,6 +446,16 @@ handle_cast({request, ChannelId, Type, Data}, State0) ->
443446
lists:foreach(fun send_msg/1, Replies),
444447
{noreply, State};
445448

449+
handle_cast({reply_request, Status, ChannelId}, #state{connection_state =
450+
#connection{channel_cache = Cache}} = State0) ->
451+
State = case ssh_channel:cache_lookup(Cache, ChannelId) of
452+
#channel{remote_id = RemoteId} ->
453+
cm_message({Status, RemoteId}, State0);
454+
undefined ->
455+
State0
456+
end,
457+
{noreply, State};
458+
446459
handle_cast({global_request, _, _, _, _} = Request, State0) ->
447460
State = handle_global_request(Request, State0),
448461
{noreply, State};

0 commit comments

Comments
 (0)