1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

seat_output: add an output type for SSH banners. (NFC)

The jump host system ought really to be treating SSH authentication
banners as a distinct thing from the standard-error session output, so
that the former can be presented to the user in the same way as the
auth banner for the main session.

This change converts the 'bool is_stderr' parameter of seat_output()
into an enumerated type with three values. For the moment, stderr and
banners are treated the same, but the plan is for that to change.
This commit is contained in:
Simon Tatham 2021-09-16 14:46:49 +01:00
parent a45ae81797
commit ac47e550c6
12 changed files with 70 additions and 43 deletions

11
pscp.c
View File

@ -60,7 +60,7 @@ const char *const appname = "PSCP";
void ldisc_echoedit_update(Ldisc *ldisc) { }
void ldisc_check_sendok(Ldisc *ldisc) { }
static size_t pscp_output(Seat *, bool is_stderr, const void *, size_t);
static size_t pscp_output(Seat *, SeatOutputType type, const void *, size_t);
static bool pscp_eof(Seat *);
static const SeatVtable pscp_seat_vt = {
@ -146,13 +146,14 @@ static PRINTF_LIKE(2, 3) void tell_user(FILE *stream, const char *fmt, ...)
static bufchain received_data;
static BinarySink *stderr_bs;
static size_t pscp_output(
Seat *seat, bool is_stderr, const void *data, size_t len)
Seat *seat, SeatOutputType type, const void *data, size_t len)
{
/*
* stderr data is just spouted to local stderr (optionally via a
* sanitiser) and otherwise ignored.
* Non-stdout data (both stderr and SSH auth banners) is just
* spouted to local stderr (optionally via a sanitiser) and
* otherwise ignored.
*/
if (is_stderr) {
if (type != SEAT_OUTPUT_STDOUT) {
put_data(stderr_bs, data, len);
return 0;
}

11
psftp.c
View File

@ -41,7 +41,7 @@ static bool sent_eof = false;
* Seat vtable.
*/
static size_t psftp_output(Seat *, bool is_stderr, const void *, size_t);
static size_t psftp_output(Seat *, SeatOutputType type, const void *, size_t);
static bool psftp_eof(Seat *);
static const SeatVtable psftp_seat_vt = {
@ -2461,13 +2461,14 @@ void ldisc_check_sendok(Ldisc *ldisc) { }
static bufchain received_data;
static BinarySink *stderr_bs;
static size_t psftp_output(
Seat *seat, bool is_stderr, const void *data, size_t len)
Seat *seat, SeatOutputType type, const void *data, size_t len)
{
/*
* stderr data is just spouted to local stderr (optionally via a
* sanitiser) and otherwise ignored.
* Non-stdout data (both stderr and SSH auth banners) is just
* spouted to local stderr (optionally via a sanitiser) and
* otherwise ignored.
*/
if (is_stderr) {
if (type != SEAT_OUTPUT_STDOUT) {
put_data(stderr_bs, data, len);
return 0;
}

35
putty.h
View File

@ -889,6 +889,10 @@ typedef enum SeatInteractionContext {
SIC_BANNER, SIC_KI_PROMPTS
} SeatInteractionContext;
typedef enum SeatOutputType {
SEAT_OUTPUT_STDOUT, SEAT_OUTPUT_STDERR, SEAT_OUTPUT_AUTH_BANNER
} SeatOutputType;
/*
* Data type 'Seat', which is an API intended to contain essentially
* everything that a back end might need to talk to its client for:
@ -901,14 +905,17 @@ struct Seat {
};
struct SeatVtable {
/*
* Provide output from the remote session. 'is_stderr' indicates
* that the output should be sent to a separate error message
* channel, if the seat has one. But combining both channels into
* one is OK too; that's what terminal-window based seats do.
* Provide output from the remote session. 'type' indicates the
* type of the output (stdout, stderr or SSH auth banner), which
* can be used to split the output into separate message channels,
* if the seat wants to handle them differently. But combining the
* channels into one is OK too; that's what terminal-window based
* seats do.
*
* The return value is the current size of the output backlog.
*/
size_t (*output)(Seat *seat, bool is_stderr, const void *data, size_t len);
size_t (*output)(Seat *seat, SeatOutputType type,
const void *data, size_t len);
/*
* Called when the back end wants to indicate that EOF has arrived
@ -1167,8 +1174,8 @@ struct SeatVtable {
};
static inline size_t seat_output(
Seat *seat, bool err, const void *data, size_t len)
{ return seat->vt->output(seat, err, data, len); }
Seat *seat, SeatOutputType type, const void *data, size_t len)
{ return seat->vt->output(seat, type, data, len); }
static inline bool seat_eof(Seat *seat)
{ return seat->vt->eof(seat); }
static inline void seat_sent(Seat *seat, size_t bufsize)
@ -1231,13 +1238,17 @@ void seat_connection_fatal(Seat *seat, const char *fmt, ...) PRINTF_LIKE(2, 3);
/* Handy aliases for seat_output which set is_stderr to a fixed value. */
static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)
{ return seat_output(seat, false, data, len); }
{ return seat_output(seat, SEAT_OUTPUT_STDOUT, data, len); }
static inline size_t seat_stdout_pl(Seat *seat, ptrlen data)
{ return seat_output(seat, false, data.ptr, data.len); }
{ return seat_output(seat, SEAT_OUTPUT_STDOUT, data.ptr, data.len); }
static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)
{ return seat_output(seat, true, data, len); }
{ return seat_output(seat, SEAT_OUTPUT_STDERR, data, len); }
static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)
{ return seat_output(seat, true, data.ptr, data.len); }
{ return seat_output(seat, SEAT_OUTPUT_STDERR, data.ptr, data.len); }
static inline size_t seat_banner(Seat *seat, const void *data, size_t len)
{ return seat_output(seat, SEAT_OUTPUT_AUTH_BANNER, data, len); }
static inline size_t seat_banner_pl(Seat *seat, ptrlen data)
{ return seat_output(seat, SEAT_OUTPUT_AUTH_BANNER, data.ptr, data.len); }
/*
* Stub methods for seat implementations that want to use the obvious
@ -1247,7 +1258,7 @@ static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)
* plausibly want to return either fixed answer 'no' or 'yes'.
*/
size_t nullseat_output(
Seat *seat, bool is_stderr, const void *data, size_t len);
Seat *seat, SeatOutputType type, const void *data, size_t len);
bool nullseat_eof(Seat *seat);
void nullseat_sent(Seat *seat, size_t bufsize);
int nullseat_get_userpass_input(Seat *seat, prompts_t *p);

View File

@ -177,7 +177,7 @@ static const LogPolicyVtable sesschan_logpolicy_vt = {
};
static size_t sesschan_seat_output(
Seat *, bool is_stderr, const void *, size_t);
Seat *, SeatOutputType type, const void *, size_t);
static bool sesschan_seat_eof(Seat *);
static void sesschan_notify_remote_exit(Seat *seat);
static void sesschan_connection_fatal(Seat *seat, const char *message);
@ -612,10 +612,15 @@ bool sesschan_change_window_size(
}
static size_t sesschan_seat_output(
Seat *seat, bool is_stderr, const void *data, size_t len)
Seat *seat, SeatOutputType type, const void *data, size_t len)
{
sesschan *sess = container_of(seat, sesschan, seat);
return sshfwd_write_ext(sess->c, is_stderr, data, len);
/* We don't expect anything but stdout and stderr to come here,
* because the pty backend doesn't generate auth banners */
assert(type != SEAT_OUTPUT_AUTH_BANNER);
return sshfwd_write_ext(sess->c, type == SEAT_OUTPUT_STDERR, data, len);
}
static void sesschan_check_close_callback(void *vctx)

View File

@ -530,7 +530,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
bool mid_line = false;
while (bufchain_size(&s->banner) > 0) {
ptrlen data = bufchain_prefix(&s->banner);
seat_stderr_pl(s->ppl.seat, data);
seat_banner_pl(s->ppl.seat, data);
mid_line =
(((const char *)data.ptr)[data.len-1] != '\n');
bufchain_consume(&s->banner, data.len);
@ -538,7 +538,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
bufchain_clear(&s->banner);
if (mid_line)
seat_stderr_pl(s->ppl.seat, PTRLEN_LITERAL("\r\n"));
seat_banner_pl(s->ppl.seat, PTRLEN_LITERAL("\r\n"));
if (s->banner_scc) {
seat_set_trust_status(s->ppl.seat, true);
@ -1919,6 +1919,6 @@ static void ssh2_userauth_antispoof_msg(
put_byte(sb, '-');
}
put_datapl(sb, PTRLEN_LITERAL("\r\n"));
seat_stderr_pl(s->ppl.seat, ptrlen_from_strbuf(sb));
seat_banner_pl(s->ppl.seat, ptrlen_from_strbuf(sb));
strbuf_free(sb);
}

View File

@ -254,7 +254,7 @@ static void sshproxy_notify_session_started(Seat *seat)
plug_log(sp->plug, PLUGLOG_CONNECT_SUCCESS, sp->addr, sp->port, NULL, 0);
}
static size_t sshproxy_output(Seat *seat, bool is_stderr,
static size_t sshproxy_output(Seat *seat, SeatOutputType type,
const void *data, size_t len)
{
SshProxy *sp = container_of(seat, SshProxy, seat);

View File

@ -352,8 +352,9 @@ size_t try_output(bool is_stderr)
}
static size_t plink_output(
Seat *seat, bool is_stderr, const void *data, size_t len)
Seat *seat, SeatOutputType type, const void *data, size_t len)
{
bool is_stderr = type != SEAT_OUTPUT_STDOUT;
assert(is_stderr || outgoingeof == EOF_NO);
BinarySink *bs = is_stderr ? stderr_bs : stdout_bs;

View File

@ -318,7 +318,7 @@ static char *gtk_seat_get_ttymode(Seat *seat, const char *mode)
return term_get_ttymode(inst->term, mode);
}
static size_t gtk_seat_output(Seat *seat, bool is_stderr,
static size_t gtk_seat_output(Seat *seat, SeatOutputType type,
const void *data, size_t len)
{
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);

View File

@ -5,7 +5,7 @@
#include "putty.h"
size_t nullseat_output(
Seat *seat, bool is_stderr, const void *data, size_t len) { return 0; }
Seat *seat, SeatOutputType type, const void *data, size_t len) {return 0;}
bool nullseat_eof(Seat *seat) { return true; }
void nullseat_sent(Seat *seat, size_t bufsize) {}
int nullseat_get_userpass_input(Seat *seat, prompts_t *p) { return 0; }

View File

@ -17,7 +17,7 @@
typedef struct TempSeat TempSeat;
struct TempSeat {
Seat *realseat;
bufchain outputs[2]; /* stdout, stderr */
bufchain outputs[3]; /* stdout, stderr, auth banner (just in case) */
bool seen_session_started;
bool seen_remote_exit;
bool seen_remote_disconnect;
@ -33,12 +33,19 @@ struct TempSeat {
* real Seat in tempseat_flush().
*/
static size_t tempseat_output(Seat *seat, bool is_stderr, const void *data,
size_t len)
static size_t tempseat_output(Seat *seat, SeatOutputType type,
const void *data, size_t len)
{
TempSeat *ts = container_of(seat, TempSeat, seat);
bufchain_add(&ts->outputs[is_stderr], data, len);
return bufchain_size(&ts->outputs[0]) + bufchain_size(&ts->outputs[1]);
size_t index = (size_t)type;
assert(index < lenof(ts->outputs));
bufchain_add(&ts->outputs[index], data, len);
size_t total_size = 0;
for (size_t i = 0; i < lenof(ts->outputs); i++)
total_size += bufchain_size(&ts->outputs[i]);
return total_size;
}
static void tempseat_notify_session_started(Seat *seat)
@ -295,7 +302,7 @@ Seat *tempseat_new(Seat *realseat)
ts->seat.vt = &tempseat_vt;
ts->realseat = realseat;
for (unsigned i = 0; i < 2; i++)
for (size_t i = 0; i < lenof(ts->outputs); i++)
bufchain_init(&ts->outputs[i]);
return &ts->seat;
@ -327,8 +334,8 @@ void tempseat_flush(Seat *seat)
assert(seat->vt == &tempseat_vt);
TempSeat *ts = container_of(seat, TempSeat, seat);
/* Empty the stdout/stderr bufchains into the real seat */
for (unsigned i = 0; i < 2; i++) {
/* Empty the output bufchains into the real seat */
for (size_t i = 0; i < lenof(ts->outputs); i++) {
while (bufchain_size(&ts->outputs[i])) {
ptrlen pl = bufchain_prefix(&ts->outputs[i]);
seat_output(ts->realseat, i, pl.ptr, pl.len);

View File

@ -50,8 +50,9 @@ static void plink_echoedit_update(Seat *seat, bool echo, bool edit)
}
static size_t plink_output(
Seat *seat, bool is_stderr, const void *data, size_t len)
Seat *seat, SeatOutputType type, const void *data, size_t len)
{
bool is_stderr = type != SEAT_OUTPUT_STDOUT;
BinarySink *bs = is_stderr ? stderr_bs : stdout_bs;
put_data(bs, data, len);

View File

@ -315,7 +315,7 @@ static StripCtrlChars *win_seat_stripctrl_new(
}
static size_t win_seat_output(
Seat *seat, bool is_stderr, const void *, size_t);
Seat *seat, SeatOutputType type, const void *, size_t);
static bool win_seat_eof(Seat *seat);
static int win_seat_get_userpass_input(Seat *seat, prompts_t *p);
static void win_seat_notify_remote_exit(Seat *seat);
@ -5734,7 +5734,7 @@ static void flip_full_screen()
}
}
static size_t win_seat_output(Seat *seat, bool is_stderr,
static size_t win_seat_output(Seat *seat, SeatOutputType type,
const void *data, size_t len)
{
return term_data(term, data, len);