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

Divide seat_set_trust_status into query and update.

This complicates the API in one sense (more separate functions), but
in another sense, simplifies it (each function does something
simpler). When I start putting one Seat in front of another during SSH
proxying, the latter will be more important - in particular, it means
you can find out _whether_ a seat can support changing trust status
without having to actually attempt a destructive modification.
This commit is contained in:
Simon Tatham 2021-09-12 09:52:46 +01:00
parent c06c9c730f
commit 82177956da
16 changed files with 88 additions and 33 deletions

3
pscp.c
View File

@ -82,7 +82,8 @@ static const SeatVtable pscp_seat_vt = {
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,
.set_trust_status = nullseat_set_trust_status_vacuously,
.set_trust_status = nullseat_set_trust_status,
.can_set_trust_status = nullseat_can_set_trust_status_yes,
.verbose = cmdline_seat_verbose,
.interactive = nullseat_interactive_no,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -64,7 +64,8 @@ static const SeatVtable psftp_seat_vt = {
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,
.set_trust_status = nullseat_set_trust_status_vacuously,
.set_trust_status = nullseat_set_trust_status,
.can_set_trust_status = nullseat_can_set_trust_status_yes,
.verbose = cmdline_seat_verbose,
.interactive = nullseat_interactive_yes,
.get_cursor_position = nullseat_get_cursor_position,

22
putty.h
View File

@ -1097,13 +1097,19 @@ struct SeatVtable {
* (and hence, can be trusted if it's asking you for secrets such
* as your passphrase); false means output is coming from the
* server.
*/
void (*set_trust_status)(Seat *seat, bool trusted);
/*
* Query whether this Seat can do anything user-visible in
* response to set_trust_status.
*
* Returns true if the seat has a way to indicate this
* distinction. Returns false if not, in which case the backend
* should use a fallback defence against spoofing of PuTTY's local
* prompts by malicious servers.
*/
bool (*set_trust_status)(Seat *seat, bool trusted);
bool (*can_set_trust_status)(Seat *seat);
/*
* Ask the seat whether it would like verbose messages.
@ -1169,8 +1175,10 @@ static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)
static inline StripCtrlChars *seat_stripctrl_new(
Seat *seat, BinarySink *bs, SeatInteractionContext sic)
{ return seat->vt->stripctrl_new(seat, bs, sic); }
static inline bool seat_set_trust_status(Seat *seat, bool trusted)
{ return seat->vt->set_trust_status(seat, trusted); }
static inline void seat_set_trust_status(Seat *seat, bool trusted)
{ seat->vt->set_trust_status(seat, trusted); }
static inline bool seat_can_set_trust_status(Seat *seat)
{ return seat->vt->can_set_trust_status(seat); }
static inline bool seat_verbose(Seat *seat)
{ return seat->vt->verbose(seat); }
static inline bool seat_interactive(Seat *seat)
@ -1229,8 +1237,9 @@ bool nullseat_get_windowid(Seat *seat, long *id_out);
bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height);
StripCtrlChars *nullseat_stripctrl_new(
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
bool nullseat_set_trust_status(Seat *seat, bool trusted);
bool nullseat_set_trust_status_vacuously(Seat *seat, bool trusted);
void nullseat_set_trust_status(Seat *seat, bool trusted);
bool nullseat_can_set_trust_status_yes(Seat *seat);
bool nullseat_can_set_trust_status_no(Seat *seat);
bool nullseat_verbose_no(Seat *seat);
bool nullseat_verbose_yes(Seat *seat);
bool nullseat_interactive_no(Seat *seat);
@ -1255,7 +1264,8 @@ int console_confirm_weak_cached_hostkey(
void (*callback)(void *ctx, int result), void *ctx);
StripCtrlChars *console_stripctrl_new(
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
bool console_set_trust_status(Seat *seat, bool trusted);
void console_set_trust_status(Seat *seat, bool trusted);
bool console_can_set_trust_status(Seat *seat);
/*
* Other centralised seat functions.

View File

@ -543,5 +543,6 @@ SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan)
bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s)
{
return !seat_set_trust_status(s->ppl.seat, false);
seat_set_trust_status(s->ppl.seat, false);
return !seat_can_set_trust_status(s->ppl.seat);
}

View File

@ -500,6 +500,7 @@ void ssh2channel_send_terminal_size_change(SshChannel *sc, int w, int h)
bool ssh2_connection_need_antispoof_prompt(struct ssh2_connection_state *s)
{
bool success = seat_set_trust_status(s->ppl.seat, false);
seat_set_trust_status(s->ppl.seat, false);
bool success = seat_can_set_trust_status(s->ppl.seat);
return (!success && !ssh_is_bare(s->ppl.ssh));
}

View File

@ -125,6 +125,7 @@ static const SeatVtable server_seat_vt = {
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = nullseat_stripctrl_new,
.set_trust_status = nullseat_set_trust_status,
.can_set_trust_status = nullseat_can_set_trust_status_no,
.verbose = nullseat_verbose_no,
.interactive = nullseat_interactive_no,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -204,6 +204,7 @@ static const SeatVtable sesschan_seat_vt = {
.get_window_pixel_size = sesschan_get_window_pixel_size,
.stripctrl_new = nullseat_stripctrl_new,
.set_trust_status = nullseat_set_trust_status,
.can_set_trust_status = nullseat_can_set_trust_status_no,
.verbose = nullseat_verbose_no,
.interactive = nullseat_interactive_no,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -1950,7 +1950,8 @@ static void ssh2_userauth_antispoof_msg(
struct ssh2_userauth_state *s, const char *msg)
{
strbuf *sb = strbuf_new();
if (seat_set_trust_status(s->ppl.seat, true)) {
seat_set_trust_status(s->ppl.seat, true);
if (seat_can_set_trust_status(s->ppl.seat)) {
/*
* If the seat can directly indicate that this message is
* generated by the client, then we can just use the message

View File

@ -405,20 +405,24 @@ static int sshproxy_confirm_weak_cached_hostkey(
return 0;
}
static bool sshproxy_set_trust_status(Seat *seat, bool trusted)
static void sshproxy_set_trust_status(Seat *seat, bool trusted)
{
/*
* This is called by the proxy SSH connection, to set our Seat
* into a given trust status. We can safely do nothing here and
* return true to claim we did something (effectively eliminating
* the spoofing defences completely, by suppressing the 'press
* Return to begin session' prompt and not providing anything in
* place of it), on the basis that session I/O from the proxy SSH
* connection is never passed directly on to the end user, so a
* malicious proxy SSH server wouldn't be able to spoof our human
* in any case.
* into a given trust status. We can safely do nothing here, and
* have can_set_trust_status return true to claim we did something
* (effectively eliminating the spoofing defences completely, by
* suppressing the 'press Return to begin session' prompt and not
* providing anything in place of it), on the basis that session
* I/O from the proxy SSH connection is never passed directly on
* to the end user, so a malicious proxy SSH server wouldn't be
* able to spoof our human in any case.
*/
return true;
}
static bool sshproxy_can_set_trust_status(Seat *seat)
{
return true; /* see comment above */
}
static const SeatVtable SshProxy_seat_vt = {
@ -442,6 +446,7 @@ static const SeatVtable SshProxy_seat_vt = {
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = nullseat_stripctrl_new,
.set_trust_status = sshproxy_set_trust_status,
.can_set_trust_status = sshproxy_can_set_trust_status,
.verbose = nullseat_verbose_no,
.interactive = nullseat_interactive_no,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -321,7 +321,16 @@ int console_askappend(LogPolicy *lp, Filename *filename,
}
bool console_antispoof_prompt = true;
bool console_set_trust_status(Seat *seat, bool trusted)
void console_set_trust_status(Seat *seat, bool trusted)
{
/* Do nothing in response to a change of trust status, because
* there's nothing we can do in a console environment. However,
* the query function below will make a fiddly decision about
* whether to tell the backend to enable fallback handling. */
}
bool console_can_set_trust_status(Seat *seat)
{
if (console_batch_mode || !is_interactive() || !console_antispoof_prompt) {
/*
@ -334,8 +343,8 @@ bool console_set_trust_status(Seat *seat, bool trusted)
* prompt, the user couldn't respond to it via the terminal
* anyway.
*
* We also vacuously return success if the user has purposely
* disabled the antispoof prompt.
* We also return true without enabling any defences if the
* user has purposely disabled the antispoof prompt.
*/
return true;
}

View File

@ -407,6 +407,7 @@ static const SeatVtable plink_seat_vt = {
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,
.set_trust_status = console_set_trust_status,
.can_set_trust_status = console_can_set_trust_status,
.verbose = cmdline_seat_verbose,
.interactive = plink_seat_interactive,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -383,7 +383,8 @@ static const char *gtk_seat_get_x_display(Seat *seat);
#ifndef NOT_X_WINDOWS
static bool gtk_seat_get_windowid(Seat *seat, long *id);
#endif
static bool gtk_seat_set_trust_status(Seat *seat, bool trusted);
static void gtk_seat_set_trust_status(Seat *seat, bool trusted);
static bool gtk_seat_can_set_trust_status(Seat *seat);
static bool gtk_seat_get_cursor_position(Seat *seat, int *x, int *y);
static const SeatVtable gtk_seat_vt = {
@ -411,6 +412,7 @@ static const SeatVtable gtk_seat_vt = {
.get_window_pixel_size = gtk_seat_get_window_pixel_size,
.stripctrl_new = gtk_seat_stripctrl_new,
.set_trust_status = gtk_seat_set_trust_status,
.can_set_trust_status = gtk_seat_can_set_trust_status,
.verbose = nullseat_verbose_yes,
.interactive = nullseat_interactive_yes,
.get_cursor_position = gtk_seat_get_cursor_position,
@ -5415,10 +5417,14 @@ void new_session_window(Conf *conf, const char *geometry_string)
ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */
}
static bool gtk_seat_set_trust_status(Seat *seat, bool trusted)
static void gtk_seat_set_trust_status(Seat *seat, bool trusted)
{
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
term_set_trust_status(inst->term, trusted);
}
static bool gtk_seat_can_set_trust_status(Seat *seat)
{
return true;
}

View File

@ -35,8 +35,9 @@ bool nullseat_get_window_pixel_size(
Seat *seat, int *width, int *height) { return false; }
StripCtrlChars *nullseat_stripctrl_new(
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic) {return NULL;}
bool nullseat_set_trust_status(Seat *seat, bool tr) { return false; }
bool nullseat_set_trust_status_vacuously(Seat *seat, bool tr) { return true; }
void nullseat_set_trust_status(Seat *seat, bool trusted) {}
bool nullseat_can_set_trust_status_yes(Seat *seat) { return true; }
bool nullseat_can_set_trust_status_no(Seat *seat) { return false; }
bool nullseat_verbose_no(Seat *seat) { return false; }
bool nullseat_verbose_yes(Seat *seat) { return true; }
bool nullseat_interactive_no(Seat *seat) { return false; }

View File

@ -187,7 +187,16 @@ bool is_interactive(void)
}
bool console_antispoof_prompt = true;
bool console_set_trust_status(Seat *seat, bool trusted)
void console_set_trust_status(Seat *seat, bool trusted)
{
/* Do nothing in response to a change of trust status, because
* there's nothing we can do in a console environment. However,
* the query function below will make a fiddly decision about
* whether to tell the backend to enable fallback handling. */
}
bool console_can_set_trust_status(Seat *seat)
{
if (console_batch_mode || !is_interactive() || !console_antispoof_prompt) {
/*
@ -200,8 +209,8 @@ bool console_set_trust_status(Seat *seat, bool trusted)
* prompt, the user couldn't respond to it via the terminal
* anyway.
*
* We also vacuously return success if the user has purposely
* disabled the antispoof prompt.
* We also return true without enabling any defences if the
* user has purposely disabled the antispoof prompt.
*/
return true;
}

View File

@ -101,6 +101,7 @@ static const SeatVtable plink_seat_vt = {
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,
.set_trust_status = console_set_trust_status,
.can_set_trust_status = console_can_set_trust_status,
.verbose = cmdline_seat_verbose,
.interactive = plink_seat_interactive,
.get_cursor_position = nullseat_get_cursor_position,

View File

@ -323,7 +323,8 @@ static void win_seat_notify_remote_exit(Seat *seat);
static void win_seat_connection_fatal(Seat *seat, const char *msg);
static void win_seat_update_specials_menu(Seat *seat);
static void win_seat_set_busy_status(Seat *seat, BusyStatus status);
static bool win_seat_set_trust_status(Seat *seat, bool trusted);
static void win_seat_set_trust_status(Seat *seat, bool trusted);
static bool win_seat_can_set_trust_status(Seat *seat);
static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y);
static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y);
@ -348,6 +349,7 @@ static const SeatVtable win_seat_vt = {
.get_window_pixel_size = win_seat_get_window_pixel_size,
.stripctrl_new = win_seat_stripctrl_new,
.set_trust_status = win_seat_set_trust_status,
.can_set_trust_status = win_seat_can_set_trust_status,
.verbose = nullseat_verbose_yes,
.interactive = nullseat_interactive_yes,
.get_cursor_position = win_seat_get_cursor_position,
@ -5753,9 +5755,13 @@ static int win_seat_get_userpass_input(
return ret;
}
static bool win_seat_set_trust_status(Seat *seat, bool trusted)
static void win_seat_set_trust_status(Seat *seat, bool trusted)
{
term_set_trust_status(term, trusted);
}
static bool win_seat_can_set_trust_status(Seat *seat)
{
return true;
}