diff options
author | Simon Tatham <anakin@pobox.com> | 2021-09-13 19:17:20 +0300 |
---|---|---|
committer | Simon Tatham <anakin@pobox.com> | 2021-09-13 19:24:47 +0300 |
commit | 6d272ee007aab95f5bedc690371ecfcdda4fd079 (patch) | |
tree | 14aae9bb11bceb048a3449f1aa4487718561fa37 /otherbackends | |
parent | a08f953bd6c1a3d19e125c7958243b64a0136823 (diff) |
Allow new_connection to take an optional Seat. (NFC)
This is working towards allowing the subsidiary SSH connection in an
SshProxy to share the main user-facing Seat, so as to be able to pass
through interactive prompts.
This is more difficult than the similar change with LogPolicy, because
Seats are stateful. In particular, the trust-sigil status will need to
be controlled by the SshProxy until it's ready to pass over control to
the main SSH (or whatever) connection.
To make this work, I've introduced a thing called a TempSeat, which is
(yet) another Seat implementation. When a backend hands its Seat to
new_connection(), it does it in a way that allows new_connection() to
borrow it completely, and replace it in the main backend structure
with a TempSeat, which acts as a temporary placeholder. If the main
backend tries to do things like changing trust status or sending
output, the TempSeat will buffer them; later on, when the connection
is established, TempSeat will replay the changes into the real Seat.
So, in each backend, I've made the following changes:
- pass &foo->seat to new_connection, which may overwrite it with a
TempSeat.
- if it has done so (which we can tell via the is_tempseat() query
function), then we have to free the TempSeat and reinstate our main
Seat. The signal that we can do so is the PLUGLOG_CONNECT_SUCCESS
notification, which indicates that SshProxy has finished all its
connection setup work.
- we also have to remember to free the TempSeat if our backend is
disposed of without that having happened (e.g. because the
connection _doesn't_ succeed).
- in backends which have no local auth phase to worry about, ensure
we don't call seat_set_trust_status on the main Seat _before_ it
gets potentially replaced with a TempSeat. Moved some calls of
seat_set_trust_status to just after new_connection(), so that now
the initial trust status setup will go into the TempSeat (if
appropriate) and be buffered until that seat is relinquished.
In all other uses of new_connection, where we don't have a Seat
available at all, we just pass NULL.
This is NFC, because neither new_connection() nor any of its delegates
will _actually_ do this replacement yet. We're just setting up the
framework to enable it to do so in the next commit.
Diffstat (limited to 'otherbackends')
-rw-r--r-- | otherbackends/raw.c | 19 | ||||
-rw-r--r-- | otherbackends/rlogin.c | 13 | ||||
-rw-r--r-- | otherbackends/supdup.c | 13 | ||||
-rw-r--r-- | otherbackends/telnet.c | 19 |
4 files changed, 50 insertions, 14 deletions
diff --git a/otherbackends/raw.c b/otherbackends/raw.c index 638e2a50..87a136ba 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -39,8 +39,15 @@ static void raw_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, Raw *raw = container_of(plug, Raw, plug); backend_socket_log(raw->seat, raw->logctx, type, addr, port, error_msg, error_code, raw->conf, raw->socket_connected); - if (type == PLUGLOG_CONNECT_SUCCESS) + if (type == PLUGLOG_CONNECT_SUCCESS) { raw->socket_connected = true; + if (is_tempseat(raw->seat)) { + Seat *ts = raw->seat; + tempseat_flush(ts); + raw->seat = tempseat_get_real(ts); + tempseat_free(ts); + } + } } static void raw_check_close(Raw *raw) @@ -132,9 +139,6 @@ static char *raw_init(const BackendVtable *vt, Seat *seat, int addressfamily; char *loghost; - /* No local authentication phase in this protocol */ - seat_set_trust_status(seat, false); - raw = snew(Raw); raw->plug.vt = &Raw_plugvt; raw->backend.vt = vt; @@ -168,10 +172,13 @@ static char *raw_init(const BackendVtable *vt, Seat *seat, */ raw->s = new_connection(addr, *realhost, port, false, true, nodelay, keepalive, &raw->plug, conf, - log_get_policy(logctx)); + log_get_policy(logctx), &raw->seat); if ((err = sk_socket_error(raw->s)) != NULL) return dupstr(err); + /* No local authentication phase in this protocol */ + seat_set_trust_status(raw->seat, false); + loghost = conf_get_str(conf, CONF_loghost); if (*loghost) { char *colon; @@ -191,6 +198,8 @@ static void raw_free(Backend *be) { Raw *raw = container_of(be, Raw, backend); + if (is_tempseat(raw->seat)) + tempseat_free(raw->seat); if (raw->s) sk_close(raw->s); conf_free(raw->conf); diff --git a/otherbackends/rlogin.c b/otherbackends/rlogin.c index 3748e536..ecdb2c36 100644 --- a/otherbackends/rlogin.c +++ b/otherbackends/rlogin.c @@ -45,8 +45,15 @@ static void rlogin_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, backend_socket_log(rlogin->seat, rlogin->logctx, type, addr, port, error_msg, error_code, rlogin->conf, rlogin->socket_connected); - if (type == PLUGLOG_CONNECT_SUCCESS) + 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); + } + } } static void rlogin_closing(Plug *plug, const char *error_msg, int error_code, @@ -205,7 +212,7 @@ static char *rlogin_init(const BackendVtable *vt, Seat *seat, */ rlogin->s = new_connection(addr, *realhost, port, true, false, nodelay, keepalive, &rlogin->plug, conf, - log_get_policy(logctx)); + log_get_policy(logctx), &rlogin->seat); if ((err = sk_socket_error(rlogin->s)) != NULL) return dupstr(err); @@ -256,6 +263,8 @@ static void rlogin_free(Backend *be) { Rlogin *rlogin = container_of(be, Rlogin, backend); + if (is_tempseat(rlogin->seat)) + tempseat_free(rlogin->seat); if (rlogin->prompt) free_prompts(rlogin->prompt); if (rlogin->s) diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index cfa1b2ad..ae7e67f7 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -563,8 +563,15 @@ static void supdup_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, backend_socket_log(supdup->seat, supdup->logctx, type, addr, port, error_msg, error_code, supdup->conf, supdup->socket_connected); - if (type == PLUGLOG_CONNECT_SUCCESS) + if (type == PLUGLOG_CONNECT_SUCCESS) { supdup->socket_connected = true; + if (is_tempseat(supdup->seat)) { + Seat *ts = supdup->seat; + tempseat_flush(ts); + supdup->seat = tempseat_get_real(ts); + tempseat_free(ts); + } + } } static void supdup_closing(Plug *plug, const char *error_msg, int error_code, @@ -713,7 +720,7 @@ static char *supdup_init(const BackendVtable *x, Seat *seat, */ supdup->s = new_connection(addr, *realhost, port, false, true, nodelay, keepalive, &supdup->plug, supdup->conf, - log_get_policy(logctx)); + log_get_policy(logctx), &supdup->seat); if ((err = sk_socket_error(supdup->s)) != NULL) return dupstr(err); @@ -783,6 +790,8 @@ static void supdup_free(Backend *be) { Supdup *supdup = container_of(be, Supdup, backend); + if (is_tempseat(supdup->seat)) + tempseat_free(supdup->seat); if (supdup->s) sk_close(supdup->s); if (supdup->pinger) diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index b006305d..540d384c 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -626,8 +626,15 @@ static void telnet_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, backend_socket_log(telnet->seat, telnet->logctx, type, addr, port, error_msg, error_code, telnet->conf, telnet->socket_connected); - if (type == PLUGLOG_CONNECT_SUCCESS) + if (type == PLUGLOG_CONNECT_SUCCESS) { telnet->socket_connected = true; + if (is_tempseat(telnet->seat)) { + Seat *ts = telnet->seat; + tempseat_flush(ts); + telnet->seat = tempseat_get_real(ts); + tempseat_free(ts); + } + } } static void telnet_closing(Plug *plug, const char *error_msg, int error_code, @@ -698,9 +705,6 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat, char *loghost; int addressfamily; - /* No local authentication phase in this protocol */ - seat_set_trust_status(seat, false); - telnet = snew(Telnet); telnet->plug.vt = &Telnet_plugvt; telnet->backend.vt = vt; @@ -740,10 +744,13 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat, */ telnet->s = new_connection(addr, *realhost, port, false, true, nodelay, keepalive, &telnet->plug, telnet->conf, - log_get_policy(logctx)); + log_get_policy(logctx), &telnet->seat); if ((err = sk_socket_error(telnet->s)) != NULL) return dupstr(err); + /* No local authentication phase in this protocol */ + seat_set_trust_status(telnet->seat, false); + telnet->pinger = pinger_new(telnet->conf, &telnet->backend); /* @@ -797,6 +804,8 @@ static void telnet_free(Backend *be) { Telnet *telnet = container_of(be, Telnet, backend); + if (is_tempseat(telnet->seat)) + tempseat_free(telnet->seat); strbuf_free(telnet->sb_buf); if (telnet->s) sk_close(telnet->s); |