diff --git a/pscp.c b/pscp.c index d759fb4e..ec4dfa8a 100644 --- a/pscp.c +++ b/pscp.c @@ -67,6 +67,7 @@ static const SeatVtable pscp_seat_vt = { .eof = pscp_eof, .sent = nullseat_sent, .get_userpass_input = filexfer_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = console_connection_fatal, diff --git a/psftp.c b/psftp.c index ea52b23e..16beee56 100644 --- a/psftp.c +++ b/psftp.c @@ -49,6 +49,7 @@ static const SeatVtable psftp_seat_vt = { .eof = psftp_eof, .sent = nullseat_sent, .get_userpass_input = filexfer_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = console_connection_fatal, diff --git a/putty.h b/putty.h index 4492d515..d622574d 100644 --- a/putty.h +++ b/putty.h @@ -620,6 +620,8 @@ enum { #define BACKEND_NEEDS_TERMINAL 0x02 /* Backend must have terminal */ #define BACKEND_SUPPORTS_NC_HOST 0x04 /* Backend can honour CONF_ssh_nc_host */ +#define BACKEND_NOTIFIES_SESSION_START 0x08 /* Backend will call + seat_notify_session_started */ /* In (no)sshproxy.c */ extern const bool ssh_proxy_supported; @@ -932,6 +934,17 @@ struct SeatVtable { */ int (*get_userpass_input)(Seat *seat, prompts_t *p, bufchain *input); + /* + * Notify the seat that the main session channel has been + * successfully set up. + * + * This is only used as part of the SSH proxying system, so it's + * not necessary to implement it in all backends. A backend must + * call this if it advertises the BACKEND_NOTIFIES_SESSION_START + * flag, and otherwise, doesn't have to. + */ + void (*notify_session_started)(Seat *seat); + /* * Notify the seat that the process running at the other end of * the connection has finished. @@ -1138,6 +1151,8 @@ static inline void seat_sent(Seat *seat, size_t bufsize) static inline int seat_get_userpass_input( Seat *seat, prompts_t *p, bufchain *input) { return seat->vt->get_userpass_input(seat, p, input); } +static inline void seat_notify_session_started(Seat *seat) +{ seat->vt->notify_session_started(seat); } static inline void seat_notify_remote_exit(Seat *seat) { seat->vt->notify_remote_exit(seat); } static inline void seat_notify_remote_disconnect(Seat *seat) @@ -1212,6 +1227,7 @@ size_t nullseat_output( bool nullseat_eof(Seat *seat); void nullseat_sent(Seat *seat, size_t bufsize); int nullseat_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input); +void nullseat_notify_session_started(Seat *seat); void nullseat_notify_remote_exit(Seat *seat); void nullseat_notify_remote_disconnect(Seat *seat); void nullseat_connection_fatal(Seat *seat, const char *message); diff --git a/ssh/mainchan.c b/ssh/mainchan.c index 70033a7a..2e690547 100644 --- a/ssh/mainchan.c +++ b/ssh/mainchan.c @@ -129,6 +129,7 @@ static void mainchan_open_confirmation(Channel *chan) seat_update_specials_menu(mc->ppl->seat); ppl_logevent("Opened main channel"); + seat_notify_session_started(mc->ppl->seat); if (mc->is_simple) sshfwd_hint_channel_is_simple(mc->sc); diff --git a/ssh/server.c b/ssh/server.c index e6d7f605..1517522b 100644 --- a/ssh/server.c +++ b/ssh/server.c @@ -109,6 +109,7 @@ static const SeatVtable server_seat_vt = { .eof = nullseat_eof, .sent = nullseat_sent, .get_userpass_input = nullseat_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = nullseat_connection_fatal, diff --git a/ssh/sesschan.c b/ssh/sesschan.c index e1496023..527b7603 100644 --- a/ssh/sesschan.c +++ b/ssh/sesschan.c @@ -188,6 +188,7 @@ static const SeatVtable sesschan_seat_vt = { .eof = sesschan_seat_eof, .sent = nullseat_sent, .get_userpass_input = nullseat_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = sesschan_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = sesschan_connection_fatal, diff --git a/ssh/ssh.c b/ssh/ssh.c index 4ad10169..aee04db9 100644 --- a/ssh/ssh.c +++ b/ssh/ssh.c @@ -1230,7 +1230,7 @@ const BackendVtable ssh_backend = { .id = "ssh", .displayname = "SSH", .protocol = PROT_SSH, - .flags = BACKEND_SUPPORTS_NC_HOST, + .flags = BACKEND_SUPPORTS_NC_HOST | BACKEND_NOTIFIES_SESSION_START, .default_port = 22, }; @@ -1255,5 +1255,5 @@ const BackendVtable sshconn_backend = { .id = "ssh-connection", .displayname = "Bare ssh-connection", .protocol = PROT_SSHCONN, - .flags = BACKEND_SUPPORTS_NC_HOST, + .flags = BACKEND_SUPPORTS_NC_HOST | BACKEND_NOTIFIES_SESSION_START, }; diff --git a/sshproxy.c b/sshproxy.c index 9c6708ab..feb9b077 100644 --- a/sshproxy.c +++ b/sshproxy.c @@ -66,6 +66,7 @@ typedef struct SshProxy { bool rcvd_eof_ssh_to_socket, sent_eof_ssh_to_socket; SockAddr *addr; + int port; /* Traits implemented: we're a Socket from the point of view of * the client connection, and a Seat from the POV of the SSH @@ -245,6 +246,12 @@ static void try_send_ssh_to_socket(void *ctx) } } +static void sshproxy_notify_session_started(Seat *seat) +{ + SshProxy *sp = container_of(seat, SshProxy, seat); + plug_log(sp->plug, PLUGLOG_CONNECT_SUCCESS, sp->addr, sp->port, NULL, 0); +} + static size_t sshproxy_output(Seat *seat, bool is_stderr, const void *data, size_t len) { @@ -431,6 +438,7 @@ static const SeatVtable SshProxy_seat_vt = { .eof = sshproxy_eof, .sent = sshproxy_sent, .get_userpass_input = sshproxy_get_userpass_input, + .notify_session_started = sshproxy_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = sshproxy_notify_remote_disconnect, .connection_fatal = sshproxy_connection_fatal, @@ -470,6 +478,7 @@ Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname, bufchain_init(&sp->ssh_to_socket); sp->addr = addr; + sp->port = port; sp->conf = conf_new(); /* Try to treat proxy_hostname as the title of a saved session. If @@ -513,6 +522,14 @@ Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname, return &sp->sock; } + /* + * We also expect that the backend will announce a willingness to + * notify us that the session has started. Any backend providing + * NC_HOST should also provide this. + */ + assert(backvt->flags & BACKEND_NOTIFIES_SESSION_START && + "Backend provides NC_HOST without SESSION_START!"); + /* * Turn off SSH features we definitely don't want. It would be * awkward and counterintuitive to have the proxy SSH connection diff --git a/unix/plink.c b/unix/plink.c index a1f640a1..f8acd5ec 100644 --- a/unix/plink.c +++ b/unix/plink.c @@ -391,6 +391,7 @@ static const SeatVtable plink_seat_vt = { .eof = plink_eof, .sent = nullseat_sent, .get_userpass_input = plink_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = console_connection_fatal, diff --git a/unix/window.c b/unix/window.c index e5b541c8..cb6e831d 100644 --- a/unix/window.c +++ b/unix/window.c @@ -392,6 +392,7 @@ static const SeatVtable gtk_seat_vt = { .eof = gtk_seat_eof, .sent = nullseat_sent, .get_userpass_input = gtk_seat_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = gtk_seat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = gtk_seat_connection_fatal, diff --git a/utils/nullseat.c b/utils/nullseat.c index 5e601669..907d9176 100644 --- a/utils/nullseat.c +++ b/utils/nullseat.c @@ -10,6 +10,7 @@ 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, bufchain *input) { return 0; } +void nullseat_notify_session_started(Seat *seat) {} void nullseat_notify_remote_exit(Seat *seat) {} void nullseat_notify_remote_disconnect(Seat *seat) {} void nullseat_connection_fatal(Seat *seat, const char *message) {} diff --git a/windows/plink.c b/windows/plink.c index 5bb001be..1587cbd3 100644 --- a/windows/plink.c +++ b/windows/plink.c @@ -85,6 +85,7 @@ static const SeatVtable plink_seat_vt = { .eof = plink_eof, .sent = nullseat_sent, .get_userpass_input = plink_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = nullseat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = console_connection_fatal, diff --git a/windows/window.c b/windows/window.c index 9a273d83..6c288600 100644 --- a/windows/window.c +++ b/windows/window.c @@ -333,6 +333,7 @@ static const SeatVtable win_seat_vt = { .eof = win_seat_eof, .sent = nullseat_sent, .get_userpass_input = win_seat_get_userpass_input, + .notify_session_started = nullseat_notify_session_started, .notify_remote_exit = win_seat_notify_remote_exit, .notify_remote_disconnect = nullseat_notify_remote_disconnect, .connection_fatal = win_seat_connection_fatal,