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)