diff options
Diffstat (limited to 'ssh/connection2.h')
-rw-r--r-- | ssh/connection2.h | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/ssh/connection2.h b/ssh/connection2.h new file mode 100644 index 00000000..54c3ebf9 --- /dev/null +++ b/ssh/connection2.h @@ -0,0 +1,236 @@ +#ifndef PUTTY_SSH2CONNECTION_H +#define PUTTY_SSH2CONNECTION_H + +struct outstanding_channel_request; +struct outstanding_global_request; + +struct ssh2_connection_state { + int crState; + + ssh_sharing_state *connshare; + char *peer_verstring; + + mainchan *mainchan; + SshChannel *mainchan_sc; + bool ldisc_opts[LD_N_OPTIONS]; + int session_attempt, session_status; + int term_width, term_height; + bool want_user_input; + bufchain *user_input; + + bool ssh_is_simple; + bool persistent; + bool started; + + Conf *conf; + + tree234 *channels; /* indexed by local id */ + bool all_channels_throttled; + + bool X11_fwd_enabled; + tree234 *x11authtree; + + bool got_pty; + + tree234 *rportfwds; + PortFwdManager *portfwdmgr; + bool portfwdmgr_configured; + + prompts_t *antispoof_prompt; + SeatPromptResult antispoof_ret; + + const SftpServerVtable *sftpserver_vt; + const SshServerConfig *ssc; + + /* + * These store the list of global requests that we're waiting for + * replies to. (REQUEST_FAILURE doesn't come with any indication + * of what message caused it, so we have to keep track of the + * queue ourselves.) + */ + struct outstanding_global_request *globreq_head, *globreq_tail; + + ConnectionLayer cl; + PacketProtocolLayer ppl; +}; + +typedef void (*gr_handler_fn_t)(struct ssh2_connection_state *s, + PktIn *pktin, void *ctx); +void ssh2_queue_global_request_handler( + struct ssh2_connection_state *s, gr_handler_fn_t handler, void *ctx); + +struct ssh2_channel { + struct ssh2_connection_state *connlayer; + + unsigned remoteid, localid; + int type; + /* True if we opened this channel but server hasn't confirmed. */ + bool halfopen; + + /* Bitmap of whether we've sent/received CHANNEL_EOF and + * CHANNEL_CLOSE. */ +#define CLOSES_SENT_EOF 1 +#define CLOSES_SENT_CLOSE 2 +#define CLOSES_RCVD_EOF 4 +#define CLOSES_RCVD_CLOSE 8 + int closes; + + /* + * This flag indicates that an EOF is pending on the outgoing side + * of the channel: that is, wherever we're getting the data for + * this channel has sent us some data followed by EOF. We can't + * actually send the EOF until we've finished sending the data, so + * we set this flag instead to remind us to do so once our buffer + * is clear. + */ + bool pending_eof; + + /* + * True if this channel is causing the underlying connection to be + * throttled. + */ + bool throttling_conn; + + /* + * True if we currently have backed-up data on the direction of + * this channel pointing out of the SSH connection, and therefore + * would prefer the 'Channel' implementation not to read further + * local input if possible. + */ + bool throttled_by_backlog; + + bufchain outbuffer, errbuffer; + unsigned remwindow, remmaxpkt; + /* locwindow is signed so we can cope with excess data. */ + int locwindow, locmaxwin; + /* + * remlocwin is the amount of local window that we think + * the remote end had available to it after it sent the + * last data packet or window adjust ack. + */ + int remlocwin; + + /* + * These store the list of channel requests that we're waiting for + * replies to. (CHANNEL_FAILURE doesn't come with any indication + * of what message caused it, so we have to keep track of the + * queue ourselves.) + */ + struct outstanding_channel_request *chanreq_head, *chanreq_tail; + + enum { THROTTLED, UNTHROTTLING, UNTHROTTLED } throttle_state; + + ssh_sharing_connstate *sharectx; /* sharing context, if this is a + * downstream channel */ + Channel *chan; /* handle the client side of this channel, if not */ + SshChannel sc; /* entry point for chan to talk back to */ +}; + +typedef void (*cr_handler_fn_t)(struct ssh2_channel *, PktIn *, void *); + +void ssh2_channel_init(struct ssh2_channel *c); +PktOut *ssh2_chanreq_init(struct ssh2_channel *c, const char *type, + cr_handler_fn_t handler, void *ctx); + +typedef enum ChanopenOutcome { + CHANOPEN_RESULT_FAILURE, + CHANOPEN_RESULT_SUCCESS, + CHANOPEN_RESULT_DOWNSTREAM, +} ChanopenOutcome; + +typedef struct ChanopenResult { + ChanopenOutcome outcome; + union { + struct { + char *wire_message; /* must be freed by recipient */ + unsigned reason_code; + } failure; + struct { + Channel *channel; + } success; + struct { + ssh_sharing_connstate *share_ctx; + } downstream; + } u; +} ChanopenResult; + +PktOut *ssh2_chanopen_init(struct ssh2_channel *c, const char *type); + +PktOut *ssh2_portfwd_chanopen( + struct ssh2_connection_state *s, struct ssh2_channel *c, + const char *hostname, int port, + const char *description, const SocketPeerInfo *peerinfo); + +struct ssh_rportfwd *ssh2_rportfwd_alloc( + ConnectionLayer *cl, + const char *shost, int sport, const char *dhost, int dport, + int addressfamily, const char *log_description, PortFwdRecord *pfr, + ssh_sharing_connstate *share_ctx); +void ssh2_rportfwd_remove( + ConnectionLayer *cl, struct ssh_rportfwd *rpf); +SshChannel *ssh2_session_open(ConnectionLayer *cl, Channel *chan); +SshChannel *ssh2_serverside_x11_open( + ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi); +SshChannel *ssh2_serverside_agent_open(ConnectionLayer *cl, Channel *chan); + +void ssh2channel_send_exit_status(SshChannel *c, int status); +void ssh2channel_send_exit_signal( + SshChannel *c, ptrlen signame, bool core_dumped, ptrlen msg); +void ssh2channel_send_exit_signal_numeric( + SshChannel *c, int signum, bool core_dumped, ptrlen msg); +void ssh2channel_request_x11_forwarding( + SshChannel *c, bool want_reply, const char *authproto, + const char *authdata, int screen_number, bool oneshot); +void ssh2channel_request_agent_forwarding(SshChannel *c, bool want_reply); +void ssh2channel_request_pty( + SshChannel *c, bool want_reply, Conf *conf, int w, int h); +bool ssh2channel_send_env_var( + SshChannel *c, bool want_reply, const char *var, const char *value); +void ssh2channel_start_shell(SshChannel *c, bool want_reply); +void ssh2channel_start_command( + SshChannel *c, bool want_reply, const char *command); +bool ssh2channel_start_subsystem( + SshChannel *c, bool want_reply, const char *subsystem); +bool ssh2channel_send_env_var( + SshChannel *c, bool want_reply, const char *var, const char *value); +bool ssh2channel_send_serial_break( + SshChannel *c, bool want_reply, int length); +bool ssh2channel_send_signal( + SshChannel *c, bool want_reply, const char *signame); +void ssh2channel_send_terminal_size_change(SshChannel *c, int w, int h); + +#define CHANOPEN_RETURN_FAILURE(code, msgparams) do \ + { \ + ChanopenResult toret; \ + toret.outcome = CHANOPEN_RESULT_FAILURE; \ + toret.u.failure.reason_code = code; \ + toret.u.failure.wire_message = dupprintf msgparams; \ + return toret; \ + } while (0) + +#define CHANOPEN_RETURN_SUCCESS(chan) do \ + { \ + ChanopenResult toret; \ + toret.outcome = CHANOPEN_RESULT_SUCCESS; \ + toret.u.success.channel = chan; \ + return toret; \ + } while (0) + +#define CHANOPEN_RETURN_DOWNSTREAM(shctx) do \ + { \ + ChanopenResult toret; \ + toret.outcome = CHANOPEN_RESULT_DOWNSTREAM; \ + toret.u.downstream.share_ctx = shctx; \ + return toret; \ + } while (0) + +ChanopenResult ssh2_connection_parse_channel_open( + struct ssh2_connection_state *s, ptrlen type, + PktIn *pktin, SshChannel *sc); + +bool ssh2_connection_parse_global_request( + struct ssh2_connection_state *s, ptrlen type, PktIn *pktin); + +bool ssh2_connection_need_antispoof_prompt(struct ssh2_connection_state *s); + +#endif /* PUTTY_SSH2CONNECTION_H */ |