Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sesschan.c')
-rw-r--r--sesschan.c787
1 files changed, 0 insertions, 787 deletions
diff --git a/sesschan.c b/sesschan.c
deleted file mode 100644
index 0cf85b3b..00000000
--- a/sesschan.c
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- * Implement the "session" channel type for the SSH server.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#include "putty.h"
-#include "ssh.h"
-#include "sshchan.h"
-#include "sshserver.h"
-#include "sftp.h"
-
-struct agentfwd {
- ConnectionLayer *cl;
- Socket *socket;
- Plug plug;
-};
-
-typedef struct sesschan {
- SshChannel *c;
-
- LogContext *parent_logctx, *child_logctx;
- Conf *conf;
- const SftpServerVtable *sftpserver_vt;
-
- LogPolicy logpolicy;
- Seat seat;
-
- bool want_pty;
- struct ssh_ttymodes ttymodes;
- int wc, hc, wp, hp;
- strbuf *termtype;
-
- bool ignoring_input;
- bool seen_eof, seen_exit;
-
- Plug xfwd_plug;
- int n_x11_sockets;
- Socket *x11_sockets[MAX_X11_SOCKETS];
-
- agentfwd *agent;
-
- Backend *backend;
-
- bufchain subsys_input;
- SftpServer *sftpsrv;
- ScpServer *scpsrv;
- const SshServerConfig *ssc;
-
- Channel chan;
-} sesschan;
-
-static void sesschan_free(Channel *chan);
-static size_t sesschan_send(
- Channel *chan, bool is_stderr, const void *, size_t);
-static void sesschan_send_eof(Channel *chan);
-static char *sesschan_log_close_msg(Channel *chan);
-static bool sesschan_want_close(Channel *, bool, bool);
-static void sesschan_set_input_wanted(Channel *chan, bool wanted);
-static bool sesschan_run_shell(Channel *chan);
-static bool sesschan_run_command(Channel *chan, ptrlen command);
-static bool sesschan_run_subsystem(Channel *chan, ptrlen subsys);
-static bool sesschan_enable_x11_forwarding(
- Channel *chan, bool oneshot, ptrlen authproto, ptrlen authdata,
- unsigned screen_number);
-static bool sesschan_enable_agent_forwarding(Channel *chan);
-static bool sesschan_allocate_pty(
- Channel *chan, ptrlen termtype, unsigned width, unsigned height,
- unsigned pixwidth, unsigned pixheight, struct ssh_ttymodes modes);
-static bool sesschan_set_env(Channel *chan, ptrlen var, ptrlen value);
-static bool sesschan_send_break(Channel *chan, unsigned length);
-static bool sesschan_send_signal(Channel *chan, ptrlen signame);
-static bool sesschan_change_window_size(
- Channel *chan, unsigned width, unsigned height,
- unsigned pixwidth, unsigned pixheight);
-
-static const ChannelVtable sesschan_channelvt = {
- .free = sesschan_free,
- .open_confirmation = chan_remotely_opened_confirmation,
- .open_failed = chan_remotely_opened_failure,
- .send = sesschan_send,
- .send_eof = sesschan_send_eof,
- .set_input_wanted = sesschan_set_input_wanted,
- .log_close_msg = sesschan_log_close_msg,
- .want_close = sesschan_want_close,
- .rcvd_exit_status = chan_no_exit_status,
- .rcvd_exit_signal = chan_no_exit_signal,
- .rcvd_exit_signal_numeric = chan_no_exit_signal_numeric,
- .run_shell = sesschan_run_shell,
- .run_command = sesschan_run_command,
- .run_subsystem = sesschan_run_subsystem,
- .enable_x11_forwarding = sesschan_enable_x11_forwarding,
- .enable_agent_forwarding = sesschan_enable_agent_forwarding,
- .allocate_pty = sesschan_allocate_pty,
- .set_env = sesschan_set_env,
- .send_break = sesschan_send_break,
- .send_signal = sesschan_send_signal,
- .change_window_size = sesschan_change_window_size,
- .request_response = chan_no_request_response,
-};
-
-static size_t sftp_chan_send(
- Channel *chan, bool is_stderr, const void *, size_t);
-static void sftp_chan_send_eof(Channel *chan);
-static char *sftp_log_close_msg(Channel *chan);
-
-static const ChannelVtable sftp_channelvt = {
- .free = sesschan_free,
- .open_confirmation = chan_remotely_opened_confirmation,
- .open_failed = chan_remotely_opened_failure,
- .send = sftp_chan_send,
- .send_eof = sftp_chan_send_eof,
- .set_input_wanted = sesschan_set_input_wanted,
- .log_close_msg = sftp_log_close_msg,
- .want_close = chan_default_want_close,
- .rcvd_exit_status = chan_no_exit_status,
- .rcvd_exit_signal = chan_no_exit_signal,
- .rcvd_exit_signal_numeric = chan_no_exit_signal_numeric,
- .run_shell = chan_no_run_shell,
- .run_command = chan_no_run_command,
- .run_subsystem = chan_no_run_subsystem,
- .enable_x11_forwarding = chan_no_enable_x11_forwarding,
- .enable_agent_forwarding = chan_no_enable_agent_forwarding,
- .allocate_pty = chan_no_allocate_pty,
- .set_env = chan_no_set_env,
- .send_break = chan_no_send_break,
- .send_signal = chan_no_send_signal,
- .change_window_size = chan_no_change_window_size,
- .request_response = chan_no_request_response,
-};
-
-static size_t scp_chan_send(
- Channel *chan, bool is_stderr, const void *, size_t);
-static void scp_chan_send_eof(Channel *chan);
-static void scp_set_input_wanted(Channel *chan, bool wanted);
-static char *scp_log_close_msg(Channel *chan);
-
-static const ChannelVtable scp_channelvt = {
- .free = sesschan_free,
- .open_confirmation = chan_remotely_opened_confirmation,
- .open_failed = chan_remotely_opened_failure,
- .send = scp_chan_send,
- .send_eof = scp_chan_send_eof,
- .set_input_wanted = scp_set_input_wanted,
- .log_close_msg = scp_log_close_msg,
- .want_close = chan_default_want_close,
- .rcvd_exit_status = chan_no_exit_status,
- .rcvd_exit_signal = chan_no_exit_signal,
- .rcvd_exit_signal_numeric = chan_no_exit_signal_numeric,
- .run_shell = chan_no_run_shell,
- .run_command = chan_no_run_command,
- .run_subsystem = chan_no_run_subsystem,
- .enable_x11_forwarding = chan_no_enable_x11_forwarding,
- .enable_agent_forwarding = chan_no_enable_agent_forwarding,
- .allocate_pty = chan_no_allocate_pty,
- .set_env = chan_no_set_env,
- .send_break = chan_no_send_break,
- .send_signal = chan_no_send_signal,
- .change_window_size = chan_no_change_window_size,
- .request_response = chan_no_request_response,
-};
-
-static void sesschan_eventlog(LogPolicy *lp, const char *event) {}
-static void sesschan_logging_error(LogPolicy *lp, const char *event) {}
-static int sesschan_askappend(
- LogPolicy *lp, Filename *filename,
- void (*callback)(void *ctx, int result), void *ctx) { return 2; }
-
-static const LogPolicyVtable sesschan_logpolicy_vt = {
- .eventlog = sesschan_eventlog,
- .askappend = sesschan_askappend,
- .logging_error = sesschan_logging_error,
- .verbose = null_lp_verbose_no,
-};
-
-static size_t sesschan_seat_output(
- Seat *, bool is_stderr, const void *, size_t);
-static bool sesschan_seat_eof(Seat *);
-static void sesschan_notify_remote_exit(Seat *seat);
-static void sesschan_connection_fatal(Seat *seat, const char *message);
-static bool sesschan_get_window_pixel_size(Seat *seat, int *w, int *h);
-
-static const SeatVtable sesschan_seat_vt = {
- .output = sesschan_seat_output,
- .eof = sesschan_seat_eof,
- .get_userpass_input = nullseat_get_userpass_input,
- .notify_remote_exit = sesschan_notify_remote_exit,
- .connection_fatal = sesschan_connection_fatal,
- .update_specials_menu = nullseat_update_specials_menu,
- .get_ttymode = nullseat_get_ttymode,
- .set_busy_status = nullseat_set_busy_status,
- .verify_ssh_host_key = nullseat_verify_ssh_host_key,
- .confirm_weak_crypto_primitive = nullseat_confirm_weak_crypto_primitive,
- .confirm_weak_cached_hostkey = nullseat_confirm_weak_cached_hostkey,
- .is_utf8 = nullseat_is_never_utf8,
- .echoedit_update = nullseat_echoedit_update,
- .get_x_display = nullseat_get_x_display,
- .get_windowid = nullseat_get_windowid,
- .get_window_pixel_size = sesschan_get_window_pixel_size,
- .stripctrl_new = nullseat_stripctrl_new,
- .set_trust_status = nullseat_set_trust_status,
- .verbose = nullseat_verbose_no,
- .interactive = nullseat_interactive_no,
- .get_cursor_position = nullseat_get_cursor_position,
-};
-
-Channel *sesschan_new(SshChannel *c, LogContext *logctx,
- const SftpServerVtable *sftpserver_vt,
- const SshServerConfig *ssc)
-{
- sesschan *sess = snew(sesschan);
- memset(sess, 0, sizeof(sesschan));
-
- sess->c = c;
- sess->chan.vt = &sesschan_channelvt;
- sess->chan.initial_fixed_window_size = 0;
- sess->parent_logctx = logctx;
- sess->ssc = ssc;
-
- /* Start with a completely default Conf */
- sess->conf = conf_new();
- load_open_settings(NULL, sess->conf);
-
- /* Set close-on-exit = true to suppress uxpty.c's "[pterm: process
- * terminated with status x]" message */
- conf_set_int(sess->conf, CONF_close_on_exit, FORCE_ON);
-
- sess->seat.vt = &sesschan_seat_vt;
- sess->logpolicy.vt = &sesschan_logpolicy_vt;
- sess->child_logctx = log_init(&sess->logpolicy, sess->conf);
-
- sess->sftpserver_vt = sftpserver_vt;
-
- bufchain_init(&sess->subsys_input);
-
- return &sess->chan;
-}
-
-static void sesschan_free(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- int i;
-
- delete_callbacks_for_context(sess);
- conf_free(sess->conf);
- if (sess->backend)
- backend_free(sess->backend);
- bufchain_clear(&sess->subsys_input);
- if (sess->sftpsrv)
- sftpsrv_free(sess->sftpsrv);
- for (i = 0; i < sess->n_x11_sockets; i++)
- sk_close(sess->x11_sockets[i]);
- if (sess->agent)
- agentfwd_free(sess->agent);
-
- sfree(sess);
-}
-
-static size_t sesschan_send(Channel *chan, bool is_stderr,
- const void *data, size_t length)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (!sess->backend || sess->ignoring_input)
- return 0;
-
- return backend_send(sess->backend, data, length);
-}
-
-static void sesschan_send_eof(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- if (sess->backend)
- backend_special(sess->backend, SS_EOF, 0);
-}
-
-static char *sesschan_log_close_msg(Channel *chan)
-{
- return dupstr("Session channel closed");
-}
-
-static void sesschan_set_input_wanted(Channel *chan, bool wanted)
-{
- /* I don't think we need to do anything here */
-}
-
-static void sesschan_start_backend(sesschan *sess, const char *cmd)
-{
- /*
- * List of environment variables that we should not pass through
- * from the login session Uppity was run in (which, it being a
- * test server, there will usually be one of). These variables
- * will be set as part of X or agent forwarding, and shouldn't be
- * confusingly set in the absence of that.
- *
- * (DISPLAY must also be cleared, but uxpty.c will do that anyway
- * when our get_x_display method returns NULL.)
- */
- static const char *const env_to_unset[] = {
- "XAUTHORITY", "SSH_AUTH_SOCK", "SSH_AGENT_PID",
- NULL /* terminator */
- };
-
- sess->backend = pty_backend_create(
- &sess->seat, sess->child_logctx, sess->conf, NULL, cmd,
- sess->ttymodes, !sess->want_pty, sess->ssc->session_starting_dir,
- env_to_unset);
- backend_size(sess->backend, sess->wc, sess->hc);
-}
-
-bool sesschan_run_shell(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (sess->backend)
- return false;
-
- sesschan_start_backend(sess, NULL);
- return true;
-}
-
-bool sesschan_run_command(Channel *chan, ptrlen command)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (sess->backend)
- return false;
-
- /* FIXME: make this possible to configure off */
- if ((sess->scpsrv = scp_recognise_exec(sess->c, sess->sftpserver_vt,
- command)) != NULL) {
- sess->chan.vt = &scp_channelvt;
- logevent(sess->parent_logctx, "Starting built-in SCP server");
- return true;
- }
-
- char *command_str = mkstr(command);
- sesschan_start_backend(sess, command_str);
- sfree(command_str);
-
- return true;
-}
-
-bool sesschan_run_subsystem(Channel *chan, ptrlen subsys)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (ptrlen_eq_string(subsys, "sftp") && sess->sftpserver_vt) {
- sess->sftpsrv = sftpsrv_new(sess->sftpserver_vt);
- sess->chan.vt = &sftp_channelvt;
- logevent(sess->parent_logctx, "Starting built-in SFTP subsystem");
- return true;
- }
-
- return false;
-}
-
-static void fwd_log(Plug *plug, PlugLogType type, SockAddr *addr, int port,
- const char *error_msg, int error_code)
-{ /* don't expect any weirdnesses from a listening socket */ }
-static void fwd_closing(Plug *plug, const char *error_msg, int error_code,
- bool calling_back)
-{ /* not here, either */ }
-
-static int xfwd_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
-{
- sesschan *sess = container_of(p, sesschan, xfwd_plug);
- Plug *plug;
- Channel *chan;
- Socket *s;
- SocketPeerInfo *pi;
- const char *err;
-
- chan = portfwd_raw_new(sess->c->cl, &plug, false);
- s = constructor(ctx, plug);
- if ((err = sk_socket_error(s)) != NULL) {
- portfwd_raw_free(chan);
- return 1;
- }
- pi = sk_peer_info(s);
- portfwd_raw_setup(chan, s, ssh_serverside_x11_open(sess->c->cl, chan, pi));
- sk_free_peer_info(pi);
-
- return 0;
-}
-
-static const PlugVtable xfwd_plugvt = {
- .log = fwd_log,
- .closing = fwd_closing,
- .accepting = xfwd_accepting,
-};
-
-bool sesschan_enable_x11_forwarding(
- Channel *chan, bool oneshot, ptrlen authproto, ptrlen authdata_hex,
- unsigned screen_number)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- strbuf *authdata_bin;
- size_t i;
- char screensuffix[32];
-
- if (oneshot)
- return false; /* not supported */
-
- snprintf(screensuffix, sizeof(screensuffix), ".%u", screen_number);
-
- /*
- * Decode the authorisation data from ASCII hex into binary.
- */
- if (authdata_hex.len % 2)
- return false; /* expected an even number of digits */
- authdata_bin = strbuf_new_nm();
- for (i = 0; i < authdata_hex.len; i += 2) {
- const unsigned char *hex = authdata_hex.ptr;
- char hexbuf[3];
-
- if (!isxdigit(hex[i]) || !isxdigit(hex[i+1])) {
- strbuf_free(authdata_bin);
- return false; /* not hex */
- }
-
- hexbuf[0] = hex[i];
- hexbuf[1] = hex[i+1];
- hexbuf[2] = '\0';
- put_byte(authdata_bin, strtoul(hexbuf, NULL, 16));
- }
-
- sess->xfwd_plug.vt = &xfwd_plugvt;
-
- sess->n_x11_sockets = platform_make_x11_server(
- &sess->xfwd_plug, appname, 10, screensuffix,
- authproto, ptrlen_from_strbuf(authdata_bin),
- sess->x11_sockets, sess->conf);
-
- strbuf_free(authdata_bin);
- return sess->n_x11_sockets != 0;
-}
-
-static int agentfwd_accepting(
- Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
-{
- agentfwd *agent = container_of(p, agentfwd, plug);
- Plug *plug;
- Channel *chan;
- Socket *s;
- const char *err;
-
- chan = portfwd_raw_new(agent->cl, &plug, false);
- s = constructor(ctx, plug);
- if ((err = sk_socket_error(s)) != NULL) {
- portfwd_raw_free(chan);
- return 1;
- }
- portfwd_raw_setup(chan, s, ssh_serverside_agent_open(agent->cl, chan));
-
- return 0;
-}
-
-static const PlugVtable agentfwd_plugvt = {
- .log = fwd_log,
- .closing = fwd_closing,
- .accepting = agentfwd_accepting,
-};
-
-agentfwd *agentfwd_new(ConnectionLayer *cl, char **socketname_out)
-{
- agentfwd *agent = snew(agentfwd);
- agent->cl = cl;
- agent->plug.vt = &agentfwd_plugvt;
-
- char *dir_prefix = dupprintf("/tmp/%s-agentfwd", appname);
- char *error = NULL, *socketname = NULL;
- agent->socket = platform_make_agent_socket(
- &agent->plug, dir_prefix, &error, &socketname);
- sfree(dir_prefix);
- sfree(error);
-
- if (!agent->socket) {
- sfree(agent);
- sfree(socketname);
- return NULL;
- }
-
- *socketname_out = socketname;
- return agent;
-}
-
-void agentfwd_free(agentfwd *agent)
-{
- if (agent->socket)
- sk_close(agent->socket);
- sfree(agent);
-}
-
-bool sesschan_enable_agent_forwarding(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- char *socketname;
-
- assert(!sess->agent);
-
- sess->agent = agentfwd_new(sess->c->cl, &socketname);
-
- if (!sess->agent)
- return false;
-
- conf_set_str_str(sess->conf, CONF_environmt, "SSH_AUTH_SOCK", socketname);
- sfree(socketname);
- return true;
-}
-
-bool sesschan_allocate_pty(
- Channel *chan, ptrlen termtype, unsigned width, unsigned height,
- unsigned pixwidth, unsigned pixheight, struct ssh_ttymodes modes)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- char *s;
-
- if (sess->want_pty)
- return false;
-
- s = mkstr(termtype);
- conf_set_str(sess->conf, CONF_termtype, s);
- sfree(s);
-
- sess->want_pty = true;
- sess->ttymodes = modes;
- sess->wc = width;
- sess->hc = height;
- sess->wp = pixwidth;
- sess->hp = pixheight;
-
- return true;
-}
-
-bool sesschan_set_env(Channel *chan, ptrlen var, ptrlen value)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- char *svar = mkstr(var), *svalue = mkstr(value);
- conf_set_str_str(sess->conf, CONF_environmt, svar, svalue);
- sfree(svar);
- sfree(svalue);
-
- return true;
-}
-
-bool sesschan_send_break(Channel *chan, unsigned length)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (sess->backend) {
- /* We ignore the break length. We could pass it through as the
- * 'arg' parameter, and have uxpty.c collect it and pass it on
- * to tcsendbreak, but since tcsendbreak in turn assigns
- * implementation-defined semantics to _its_ duration
- * parameter, this all just sounds too difficult. */
- backend_special(sess->backend, SS_BRK, 0);
- return true;
- }
- return false;
-}
-
-bool sesschan_send_signal(Channel *chan, ptrlen signame)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- /* Start with a code that definitely isn't a signal (or indeed a
- * special command at all), to indicate 'nothing matched'. */
- SessionSpecialCode code = SS_EXITMENU;
-
- #define SIGNAL_SUB(name) \
- if (ptrlen_eq_string(signame, #name)) code = SS_SIG ## name;
- #define SIGNAL_MAIN(name, text) SIGNAL_SUB(name)
- #include "sshsignals.h"
- #undef SIGNAL_MAIN
- #undef SIGNAL_SUB
-
- if (code == SS_EXITMENU)
- return false;
-
- backend_special(sess->backend, code, 0);
- return true;
-}
-
-bool sesschan_change_window_size(
- Channel *chan, unsigned width, unsigned height,
- unsigned pixwidth, unsigned pixheight)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- if (!sess->want_pty)
- return false;
-
- sess->wc = width;
- sess->hc = height;
- sess->wp = pixwidth;
- sess->hp = pixheight;
-
- if (sess->backend)
- backend_size(sess->backend, sess->wc, sess->hc);
-
- return true;
-}
-
-static size_t sesschan_seat_output(
- Seat *seat, bool is_stderr, const void *data, size_t len)
-{
- sesschan *sess = container_of(seat, sesschan, seat);
- return sshfwd_write_ext(sess->c, is_stderr, data, len);
-}
-
-static void sesschan_check_close_callback(void *vctx)
-{
- sesschan *sess = (sesschan *)vctx;
-
- /*
- * Once we've seen incoming EOF from the backend (aka EIO from the
- * pty master) and also passed on the process's exit status, we
- * should proactively initiate closure of the session channel.
- */
- if (sess->seen_eof && sess->seen_exit)
- sshfwd_initiate_close(sess->c, NULL);
-}
-
-static bool sesschan_want_close(Channel *chan, bool seen_eof, bool rcvd_eof)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- /*
- * Similarly to above, we don't want to initiate channel closure
- * until we've sent the process's exit status, _even_ if EOF of
- * the actual data stream has happened in both directions.
- */
- return (sess->seen_eof && sess->seen_exit);
-}
-
-static bool sesschan_seat_eof(Seat *seat)
-{
- sesschan *sess = container_of(seat, sesschan, seat);
-
- sshfwd_write_eof(sess->c);
- sess->seen_eof = true;
-
- queue_toplevel_callback(sesschan_check_close_callback, sess);
- return true;
-}
-
-static void sesschan_notify_remote_exit(Seat *seat)
-{
- sesschan *sess = container_of(seat, sesschan, seat);
-
- if (!sess->backend)
- return;
-
- bool got_signal = false;
- if (!sess->ssc->exit_signal_numeric) {
- char *sigmsg;
- ptrlen signame = pty_backend_exit_signame(sess->backend, &sigmsg);
-
- if (signame.len) {
- if (!sigmsg)
- sigmsg = dupstr("");
-
- sshfwd_send_exit_signal(
- sess->c, signame, false, ptrlen_from_asciz(sigmsg));
-
- got_signal = true;
- }
-
- sfree(sigmsg);
- } else {
- int signum = pty_backend_exit_signum(sess->backend);
-
- if (signum >= 0) {
- sshfwd_send_exit_signal_numeric(sess->c, signum, false,
- PTRLEN_LITERAL(""));
- got_signal = true;
- }
- }
-
- if (!got_signal)
- sshfwd_send_exit_status(sess->c, backend_exitcode(sess->backend));
-
- sess->seen_exit = true;
- queue_toplevel_callback(sesschan_check_close_callback, sess);
-}
-
-static void sesschan_connection_fatal(Seat *seat, const char *message)
-{
- sesschan *sess = container_of(seat, sesschan, seat);
-
- /* Closest translation I can think of */
- sshfwd_send_exit_signal(
- sess->c, PTRLEN_LITERAL("HUP"), false, ptrlen_from_asciz(message));
-
- sess->ignoring_input = true;
-}
-
-static bool sesschan_get_window_pixel_size(Seat *seat, int *width, int *height)
-{
- sesschan *sess = container_of(seat, sesschan, seat);
-
- *width = sess->wp;
- *height = sess->hp;
-
- return true;
-}
-
-/* ----------------------------------------------------------------------
- * Built-in SFTP subsystem.
- */
-
-static size_t sftp_chan_send(Channel *chan, bool is_stderr,
- const void *data, size_t length)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
-
- bufchain_add(&sess->subsys_input, data, length);
-
- while (bufchain_size(&sess->subsys_input) >= 4) {
- char lenbuf[4];
- unsigned pktlen;
- struct sftp_packet *pkt, *reply;
-
- bufchain_fetch(&sess->subsys_input, lenbuf, 4);
- pktlen = GET_32BIT_MSB_FIRST(lenbuf);
-
- if (bufchain_size(&sess->subsys_input) - 4 < pktlen)
- break; /* wait for more data */
-
- bufchain_consume(&sess->subsys_input, 4);
- pkt = sftp_recv_prepare(pktlen);
- bufchain_fetch_consume(&sess->subsys_input, pkt->data, pktlen);
- sftp_recv_finish(pkt);
- reply = sftp_handle_request(sess->sftpsrv, pkt);
- sftp_pkt_free(pkt);
-
- sftp_send_prepare(reply);
- sshfwd_write(sess->c, reply->data, reply->length);
- sftp_pkt_free(reply);
- }
-
- return 0;
-}
-
-static void sftp_chan_send_eof(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- sshfwd_write_eof(sess->c);
-}
-
-static char *sftp_log_close_msg(Channel *chan)
-{
- return dupstr("Session channel (SFTP) closed");
-}
-
-/* ----------------------------------------------------------------------
- * Built-in SCP subsystem.
- */
-
-static size_t scp_chan_send(Channel *chan, bool is_stderr,
- const void *data, size_t length)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- return scp_send(sess->scpsrv, data, length);
-}
-
-static void scp_chan_send_eof(Channel *chan)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- scp_eof(sess->scpsrv);
-}
-
-static char *scp_log_close_msg(Channel *chan)
-{
- return dupstr("Session channel (SCP) closed");
-}
-
-static void scp_set_input_wanted(Channel *chan, bool wanted)
-{
- sesschan *sess = container_of(chan, sesschan, chan);
- scp_throttle(sess->scpsrv, !wanted);
-}