From 746059443373b8a4cd73d85f67fe473a2c56667f Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 30 Oct 2021 17:45:38 +0100 Subject: [PATCH] Move TempSeat creation/destruction into Interactor. Previously, SshProxy dealt with creating a TempSeat to wrap the one it was borrowing from its client, and then each client in turn dealt with detecting when it had had its seat borrowed and finishing up with the TempSeat. The latter involved a lot of code duplication; the former didn't involve code duplication _yet_ (since SshProxy was the only thing doing this job), but would have once we started wanting to do interactive password prompting for other types of network proxy. Now all of that functionality is centralised into two new Interactor helper functions: interactor_borrow_seat and interactor_return_seat. --- otherbackends/raw.c | 6 ------ otherbackends/rlogin.c | 6 ------ otherbackends/supdup.c | 6 ------ otherbackends/telnet.c | 6 ------ proxy/interactor.c | 37 +++++++++++++++++++++++++++++++++++++ proxy/sshproxy.c | 34 ++++++++++++++-------------------- putty.h | 8 +++++--- ssh/ssh.c | 9 --------- 8 files changed, 56 insertions(+), 56 deletions(-) diff --git a/otherbackends/raw.c b/otherbackends/raw.c index a5b3f427..80ce8fe1 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -46,12 +46,6 @@ static void raw_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, raw->socket_connected = true; if (raw->ldisc) ldisc_check_sendok(raw->ldisc); - if (is_tempseat(raw->seat)) { - Seat *ts = raw->seat; - tempseat_flush(ts); - raw->seat = tempseat_get_real(ts); - tempseat_free(ts); - } } } diff --git a/otherbackends/rlogin.c b/otherbackends/rlogin.c index 099f115b..e626eff4 100644 --- a/otherbackends/rlogin.c +++ b/otherbackends/rlogin.c @@ -54,12 +54,6 @@ static void rlogin_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, rlogin->conf, rlogin->socket_connected); if (type == PLUGLOG_CONNECT_SUCCESS) { rlogin->socket_connected = true; - if (is_tempseat(rlogin->seat)) { - Seat *ts = rlogin->seat; - tempseat_flush(ts); - rlogin->seat = tempseat_get_real(ts); - tempseat_free(ts); - } char *ruser = get_remote_username(rlogin->conf); if (ruser) { diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index a46bfd9a..c1867086 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -570,12 +570,6 @@ static void supdup_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, supdup->socket_connected = true; if (supdup->ldisc) ldisc_check_sendok(supdup->ldisc); - if (is_tempseat(supdup->seat)) { - Seat *ts = supdup->seat; - tempseat_flush(ts); - supdup->seat = tempseat_get_real(ts); - tempseat_free(ts); - } } } diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index df23f2f2..66f7308e 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -632,12 +632,6 @@ static void telnet_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, telnet->socket_connected = true; if (telnet->ldisc) ldisc_check_sendok(telnet->ldisc); - if (is_tempseat(telnet->seat)) { - Seat *ts = telnet->seat; - tempseat_flush(ts); - telnet->seat = tempseat_get_real(ts); - tempseat_free(ts); - } } } diff --git a/proxy/interactor.c b/proxy/interactor.c index 8006ae64..ccd3e42e 100644 --- a/proxy/interactor.c +++ b/proxy/interactor.c @@ -4,6 +4,43 @@ #include "putty.h" +Seat *interactor_borrow_seat(Interactor *itr) +{ + Seat *clientseat = interactor_get_seat(itr); + if (!clientseat) + return NULL; + + /* If the client has already had its Seat borrowed, then look + * through the existing TempSeat to find the underlying one. */ + if (is_tempseat(clientseat)) + return tempseat_get_real(clientseat); + + /* Otherwise, make a new TempSeat and give that to the client. */ + Seat *tempseat = tempseat_new(clientseat); + interactor_set_seat(itr, tempseat); + return clientseat; +} + +void interactor_return_seat(Interactor *itr) +{ + Seat *tempseat = interactor_get_seat(itr); + if (!is_tempseat(tempseat)) + return; /* no-op */ + + tempseat_flush(tempseat); + Seat *realseat = tempseat_get_real(tempseat); + interactor_set_seat(itr, realseat); + tempseat_free(tempseat); + + /* + * We're about to hand this seat back to the parent Interactor to + * do its own thing with. It will typically expect to start in the + * same state as if the seat had never been borrowed, i.e. in the + * starting trust state. + */ + seat_set_trust_status(realseat, true); +} + InteractionReadySeat interactor_announce(Interactor *itr) { Seat *seat = interactor_get_seat(itr); diff --git a/proxy/sshproxy.c b/proxy/sshproxy.c index 55de65e6..5ab81e61 100644 --- a/proxy/sshproxy.c +++ b/proxy/sshproxy.c @@ -44,6 +44,7 @@ typedef struct SshProxy { Backend *backend; LogPolicy *clientlp; Seat *clientseat; + Interactor *clientitr; ProxyStderrBuf psb; Plug *plug; @@ -253,7 +254,7 @@ static void sshproxy_notify_session_started(Seat *seat) SshProxy *sp = container_of(seat, SshProxy, seat); if (sp->clientseat) - seat_set_trust_status(sp->clientseat, true); + interactor_return_seat(sp->clientitr); plug_log(sp->plug, PLUGLOG_CONNECT_SUCCESS, sp->addr, sp->port, NULL, 0); } @@ -601,28 +602,21 @@ Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname, sfree(realhost); /* - * If we've been given an Interactor by the caller, squirrel away - * things it's holding. + * If we've been given an Interactor by the caller, set ourselves + * up to work with it. */ if (clientitr) { + sp->clientitr = clientitr; + sp->clientlp = interactor_logpolicy(clientitr); - if (backvt->flags & BACKEND_NOTIFIES_SESSION_START) { - /* - * We can only keep the client's Seat if our own backend will - * tell us when to give it back. (SSH-based backends _should_ - * do that, but we check the flag here anyway.) - * - * Also, check if the client already has a TempSeat, and if - * so, don't wrap it with another one. - */ - Seat *clientseat = interactor_get_seat(clientitr); - if (is_tempseat(clientseat)) { - sp->clientseat = tempseat_get_real(clientseat); - } else { - sp->clientseat = clientseat; - interactor_set_seat(clientitr, tempseat_new(sp->clientseat)); - } - } + + /* + * We can only borrow the client's Seat if our own backend + * will tell us when to give it back. (SSH-based backends + * _should_ do that, but we check the flag here anyway.) + */ + if (backvt->flags & BACKEND_NOTIFIES_SESSION_START) + sp->clientseat = interactor_borrow_seat(clientitr); } return &sp->sock; diff --git a/putty.h b/putty.h index 5c7a01f0..edfd1171 100644 --- a/putty.h +++ b/putty.h @@ -706,6 +706,8 @@ static inline Seat *interactor_get_seat(Interactor *itr) static inline void interactor_set_seat(Interactor *itr, Seat *seat) { itr->vt->set_seat(itr, seat); } +Seat *interactor_borrow_seat(Interactor *itr); +void interactor_return_seat(Interactor *itr); InteractionReadySeat interactor_announce(Interactor *itr); /* Interactors that are Backends will find this helper function useful @@ -1468,9 +1470,9 @@ Seat *tempseat_new(Seat *real); bool is_tempseat(Seat *seat); Seat *tempseat_get_real(Seat *seat); -/* Called by the backend once the proxy connection has finished - * setting up (or failed), to pass on any buffered stuff to the real - * seat. */ +/* Called by interactor_return_seat once the proxy connection has + * finished setting up (or failed), to pass on any buffered stuff to + * the real seat. */ void tempseat_flush(Seat *ts); /* Frees a TempSeat, without flushing anything it has buffered. (Call diff --git a/ssh/ssh.c b/ssh/ssh.c index 8a70b665..ae7c1f6f 100644 --- a/ssh/ssh.c +++ b/ssh/ssh.c @@ -601,15 +601,6 @@ static void ssh_socket_log(Plug *plug, PlugLogType type, SockAddr *addr, backend_socket_log(ssh->seat, ssh->logctx, type, addr, port, error_msg, error_code, ssh->conf, ssh->session_started); - - if (type == PLUGLOG_CONNECT_SUCCESS) { - if (is_tempseat(ssh->seat)) { - Seat *ts = ssh->seat; - tempseat_flush(ts); - ssh->seat = tempseat_get_real(ts); - tempseat_free(ts); - } - } } static void ssh_closing(Plug *plug, const char *error_msg, int error_code)