From 8d84272d80e07ae8255f14acb025c2aeee323557 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 30 Mar 2019 07:28:38 +0000 Subject: [PATCH] uxserver: option to generate numeric "exit-signal". This mimics a bug in some old SSH servers for which PuTTY contains compensation code (parsing an incoming "exit-signal" two ways and seeing which one worked). I completely rewrote that code in commit 7535f645a, as part of the BinarySource rework. Now I can finally test it sensibly. --- sesschan.c | 34 ++++++++++++++++++++++++---------- sshserver.h | 3 +++ unix/uxpty.c | 18 ++++++++++++------ unix/uxserver.c | 2 ++ 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/sesschan.c b/sesschan.c index 5a7ffcfc..39e7f7fd 100644 --- a/sesschan.c +++ b/sesschan.c @@ -608,25 +608,39 @@ static bool sesschan_seat_eof(Seat *seat) static void sesschan_notify_remote_exit(Seat *seat) { sesschan *sess = container_of(seat, sesschan, seat); - ptrlen signame; - char *sigmsg; if (!sess->backend) return; - signame = pty_backend_exit_signame(sess->backend, &sigmsg); - if (signame.len) { - if (!sigmsg) - sigmsg = dupstr(""); + bool got_signal = false; + if (!sess->ssc->exit_signal_numeric) { + char *sigmsg; + ptrlen signame = pty_backend_exit_signame(sess->backend, &sigmsg); - sshfwd_send_exit_signal( - sess->c, signame, false, ptrlen_from_asciz(sigmsg)); + if (signame.len) { + if (!sigmsg) + sigmsg = dupstr(""); - sfree(sigmsg); + sshfwd_send_exit_signal( + sess->c, signame, false, ptrlen_from_asciz(sigmsg)); + + sfree(sigmsg); + + got_signal = true; + } } else { - sshfwd_send_exit_status(sess->c, backend_exitcode(sess->backend)); + int signum = pty_backend_exit_signum(sess->backend); + + if (signum >= 0) { + sshfwd_send_exit_signal_numeric(sess->c, signum, false, + PTRLEN_LITERAL("")); + got_signal = true; + } } + if (!got_signal) + sshfwd_send_exit_status(sess->c, backend_exitcode(sess->backend)); + sess->seen_exit = true; queue_toplevel_callback(sesschan_check_close_callback, sess); } diff --git a/sshserver.h b/sshserver.h index 4df5c230..2ed06b9d 100644 --- a/sshserver.h +++ b/sshserver.h @@ -2,6 +2,8 @@ typedef struct AuthPolicy AuthPolicy; struct SshServerConfig { ptrlen banner; /* banner.ptr == NULL indicates no banner */ + + bool exit_signal_numeric; /* mimic an old server bug */ }; Plug *ssh_server_plug( @@ -94,6 +96,7 @@ Channel *sesschan_new(SshChannel *c, LogContext *logctx, Backend *pty_backend_create( Seat *seat, LogContext *logctx, Conf *conf, char **argv, const char *cmd, struct ssh_ttymodes ttymodes, bool pipes_instead_of_pty); +int pty_backend_exit_signum(Backend *be); ptrlen pty_backend_exit_signame(Backend *be, char **aux_msg); /* diff --git a/unix/uxpty.c b/unix/uxpty.c index 93721358..0c7e820c 100644 --- a/unix/uxpty.c +++ b/unix/uxpty.c @@ -1526,17 +1526,23 @@ static int pty_exitcode(Backend *be) return WEXITSTATUS(pty->exit_code); } -ptrlen pty_backend_exit_signame(Backend *be, char **aux_msg) +int pty_backend_exit_signum(Backend *be) { Pty *pty = container_of(be, Pty, backend); - int sig; - - *aux_msg = NULL; if (!pty->finished || !WIFSIGNALED(pty->exit_code)) - return PTRLEN_LITERAL(""); + return -1; - sig = WTERMSIG(pty->exit_code); + return WTERMSIG(pty->exit_code); +} + +ptrlen pty_backend_exit_signame(Backend *be, char **aux_msg) +{ + *aux_msg = NULL; + + int sig = pty_backend_exit_signum(be); + if (sig < 0) + return PTRLEN_LITERAL(""); #define TRANSLATE_SIGNAL(s) do \ { \ diff --git a/unix/uxserver.c b/unix/uxserver.c index f9da9bed..b14f93db 100644 --- a/unix/uxserver.c +++ b/unix/uxserver.c @@ -542,6 +542,8 @@ int main(int argc, char **argv) ssc.banner = ptrlen_from_strbuf(sb); } else if (longoptarg(arg, "--bannertext", &val, &argc, &argv)) { ssc.banner = ptrlen_from_asciz(val); + } else if (longoptnoarg(arg, "--exitsignum")) { + ssc.exit_signal_numeric = true; } else if (longoptarg(arg, "--sshlog", &val, &argc, &argv) || longoptarg(arg, "-sshlog", &val, &argc, &argv)) { Filename *logfile = filename_from_str(val);