channel.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Abstraction of the various ways to handle the local end of an SSH
  3. * connection-layer channel.
  4. */
  5. #ifndef PUTTY_SSHCHAN_H
  6. #define PUTTY_SSHCHAN_H
  7. typedef struct ChannelVtable ChannelVtable;
  8. struct ChannelVtable {
  9. void (*free)(Channel *);
  10. /* Called for channel types that were created at the same time as
  11. * we sent an outgoing CHANNEL_OPEN, when the confirmation comes
  12. * back from the server indicating that the channel has been
  13. * opened, or the failure message indicating that it hasn't,
  14. * respectively. In the latter case, this must _not_ free the
  15. * Channel structure - the client will call the free method
  16. * separately. But it might do logging or other local cleanup. */
  17. void (*open_confirmation)(Channel *);
  18. void (*open_failed)(Channel *, const char *error_text);
  19. size_t (*send)(Channel *, bool is_stderr, const void *buf, size_t len);
  20. void (*send_eof)(Channel *);
  21. void (*set_input_wanted)(Channel *, bool wanted);
  22. char *(*log_close_msg)(Channel *);
  23. bool (*want_close)(Channel *, bool sent_local_eof, bool rcvd_remote_eof);
  24. /* A method for every channel request we know of. All of these
  25. * return true for success or false for failure. */
  26. bool (*rcvd_exit_status)(Channel *, int status);
  27. bool (*rcvd_exit_signal)(
  28. Channel *chan, ptrlen signame, bool core_dumped, ptrlen msg);
  29. bool (*rcvd_exit_signal_numeric)(
  30. Channel *chan, int signum, bool core_dumped, ptrlen msg);
  31. bool (*run_shell)(Channel *chan);
  32. bool (*run_command)(Channel *chan, ptrlen command);
  33. bool (*run_subsystem)(Channel *chan, ptrlen subsys);
  34. bool (*enable_x11_forwarding)(
  35. Channel *chan, bool oneshot, ptrlen authproto, ptrlen authdata,
  36. unsigned screen_number);
  37. bool (*enable_agent_forwarding)(Channel *chan);
  38. bool (*allocate_pty)(
  39. Channel *chan, ptrlen termtype, unsigned width, unsigned height,
  40. unsigned pixwidth, unsigned pixheight, struct ssh_ttymodes modes);
  41. bool (*set_env)(Channel *chan, ptrlen var, ptrlen value);
  42. bool (*send_break)(Channel *chan, unsigned length);
  43. bool (*send_signal)(Channel *chan, ptrlen signame);
  44. bool (*change_window_size)(
  45. Channel *chan, unsigned width, unsigned height,
  46. unsigned pixwidth, unsigned pixheight);
  47. /* A method for signalling success/failure responses to channel
  48. * requests initiated from the SshChannel vtable with want_reply
  49. * true. */
  50. void (*request_response)(Channel *, bool success);
  51. };
  52. struct Channel {
  53. const struct ChannelVtable *vt;
  54. unsigned initial_fixed_window_size;
  55. };
  56. static inline void chan_free(Channel *ch)
  57. { ch->vt->free(ch); }
  58. static inline void chan_open_confirmation(Channel *ch)
  59. { ch->vt->open_confirmation(ch); }
  60. static inline void chan_open_failed(Channel *ch, const char *err)
  61. { ch->vt->open_failed(ch, err); }
  62. static inline size_t chan_send(
  63. Channel *ch, bool err, const void *buf, size_t len)
  64. { return ch->vt->send(ch, err, buf, len); }
  65. static inline void chan_send_eof(Channel *ch)
  66. { ch->vt->send_eof(ch); }
  67. static inline void chan_set_input_wanted(Channel *ch, bool wanted)
  68. { ch->vt->set_input_wanted(ch, wanted); }
  69. static inline char *chan_log_close_msg(Channel *ch)
  70. { return ch->vt->log_close_msg(ch); }
  71. static inline bool chan_want_close(Channel *ch, bool leof, bool reof)
  72. { return ch->vt->want_close(ch, leof, reof); }
  73. static inline bool chan_rcvd_exit_status(Channel *ch, int status)
  74. { return ch->vt->rcvd_exit_status(ch, status); }
  75. static inline bool chan_rcvd_exit_signal(
  76. Channel *ch, ptrlen sig, bool core, ptrlen msg)
  77. { return ch->vt->rcvd_exit_signal(ch, sig, core, msg); }
  78. static inline bool chan_rcvd_exit_signal_numeric(
  79. Channel *ch, int sig, bool core, ptrlen msg)
  80. { return ch->vt->rcvd_exit_signal_numeric(ch, sig, core, msg); }
  81. static inline bool chan_run_shell(Channel *ch)
  82. { return ch->vt->run_shell(ch); }
  83. static inline bool chan_run_command(Channel *ch, ptrlen cmd)
  84. { return ch->vt->run_command(ch, cmd); }
  85. static inline bool chan_run_subsystem(Channel *ch, ptrlen subsys)
  86. { return ch->vt->run_subsystem(ch, subsys); }
  87. static inline bool chan_enable_x11_forwarding(
  88. Channel *ch, bool oneshot, ptrlen ap, ptrlen ad, unsigned scr)
  89. { return ch->vt->enable_x11_forwarding(ch, oneshot, ap, ad, scr); }
  90. static inline bool chan_enable_agent_forwarding(Channel *ch)
  91. { return ch->vt->enable_agent_forwarding(ch); }
  92. static inline bool chan_allocate_pty(
  93. Channel *ch, ptrlen termtype, unsigned w, unsigned h,
  94. unsigned pw, unsigned ph, struct ssh_ttymodes modes)
  95. { return ch->vt->allocate_pty(ch, termtype, w, h, pw, ph, modes); }
  96. static inline bool chan_set_env(Channel *ch, ptrlen var, ptrlen value)
  97. { return ch->vt->set_env(ch, var, value); }
  98. static inline bool chan_send_break(Channel *ch, unsigned length)
  99. { return ch->vt->send_break(ch, length); }
  100. static inline bool chan_send_signal(Channel *ch, ptrlen signame)
  101. { return ch->vt->send_signal(ch, signame); }
  102. static inline bool chan_change_window_size(
  103. Channel *ch, unsigned w, unsigned h, unsigned pw, unsigned ph)
  104. { return ch->vt->change_window_size(ch, w, h, pw, ph); }
  105. static inline void chan_request_response(Channel *ch, bool success)
  106. { ch->vt->request_response(ch, success); }
  107. /*
  108. * Reusable methods you can put in vtables to give default handling of
  109. * some of those functions.
  110. */
  111. /* open_confirmation / open_failed for any channel it doesn't apply to */
  112. void chan_remotely_opened_confirmation(Channel *chan);
  113. void chan_remotely_opened_failure(Channel *chan, const char *errtext);
  114. /* want_close for any channel that wants the default behaviour of not
  115. * closing until both directions have had an EOF */
  116. bool chan_default_want_close(Channel *, bool, bool);
  117. /* default implementations that refuse all the channel requests */
  118. bool chan_no_exit_status(Channel *, int);
  119. bool chan_no_exit_signal(Channel *, ptrlen, bool, ptrlen);
  120. bool chan_no_exit_signal_numeric(Channel *, int, bool, ptrlen);
  121. bool chan_no_run_shell(Channel *chan);
  122. bool chan_no_run_command(Channel *chan, ptrlen command);
  123. bool chan_no_run_subsystem(Channel *chan, ptrlen subsys);
  124. bool chan_no_enable_x11_forwarding(
  125. Channel *chan, bool oneshot, ptrlen authproto, ptrlen authdata,
  126. unsigned screen_number);
  127. bool chan_no_enable_agent_forwarding(Channel *chan);
  128. bool chan_no_allocate_pty(
  129. Channel *chan, ptrlen termtype, unsigned width, unsigned height,
  130. unsigned pixwidth, unsigned pixheight, struct ssh_ttymodes modes);
  131. bool chan_no_set_env(Channel *chan, ptrlen var, ptrlen value);
  132. bool chan_no_send_break(Channel *chan, unsigned length);
  133. bool chan_no_send_signal(Channel *chan, ptrlen signame);
  134. bool chan_no_change_window_size(
  135. Channel *chan, unsigned width, unsigned height,
  136. unsigned pixwidth, unsigned pixheight);
  137. /* default implementation that never expects to receive a response */
  138. void chan_no_request_response(Channel *, bool);
  139. /*
  140. * Constructor for a trivial do-nothing implementation of
  141. * ChannelVtable. Used for 'zombie' channels, i.e. channels whose
  142. * proper local source of data has been shut down or otherwise stopped
  143. * existing, but the SSH side is still there and needs some kind of a
  144. * Channel implementation to talk to. In particular, the want_close
  145. * method for this channel always returns 'yes, please close this
  146. * channel asap', regardless of whether local and/or remote EOF have
  147. * been sent - indeed, even if _neither_ has.
  148. */
  149. Channel *zombiechan_new(void);
  150. /* ----------------------------------------------------------------------
  151. * This structure is owned by an SSH connection layer, and identifies
  152. * the connection layer's end of the channel, for the Channel
  153. * implementation to talk back to.
  154. */
  155. typedef struct SshChannelVtable SshChannelVtable;
  156. struct SshChannelVtable {
  157. size_t (*write)(SshChannel *c, bool is_stderr, const void *, size_t);
  158. void (*write_eof)(SshChannel *c);
  159. void (*initiate_close)(SshChannel *c, const char *err);
  160. void (*unthrottle)(SshChannel *c, size_t bufsize);
  161. Conf *(*get_conf)(SshChannel *c);
  162. void (*window_override_removed)(SshChannel *c);
  163. void (*x11_sharing_handover)(SshChannel *c,
  164. ssh_sharing_connstate *share_cs,
  165. share_channel *share_chan,
  166. const char *peer_addr, int peer_port,
  167. int endian, int protomajor, int protominor,
  168. const void *initial_data, int initial_len);
  169. /*
  170. * All the outgoing channel requests we support. Each one has a
  171. * want_reply flag, which will cause a callback to
  172. * chan_request_response when the result is available.
  173. *
  174. * The ones that return 'bool' use it to indicate that the SSH
  175. * protocol in use doesn't support this request at all.
  176. *
  177. * (It's also intentional that not all of them have a want_reply
  178. * flag: the ones that don't are because SSH-1 has no method for
  179. * signalling success or failure of that request, or because we
  180. * wouldn't do anything usefully different with the reply in any
  181. * case.)
  182. */
  183. void (*send_exit_status)(SshChannel *c, int status);
  184. void (*send_exit_signal)(
  185. SshChannel *c, ptrlen signame, bool core_dumped, ptrlen msg);
  186. void (*send_exit_signal_numeric)(
  187. SshChannel *c, int signum, bool core_dumped, ptrlen msg);
  188. void (*request_x11_forwarding)(
  189. SshChannel *c, bool want_reply, const char *authproto,
  190. const char *authdata, int screen_number, bool oneshot);
  191. void (*request_agent_forwarding)(
  192. SshChannel *c, bool want_reply);
  193. void (*request_pty)(
  194. SshChannel *c, bool want_reply, Conf *conf, int w, int h);
  195. bool (*send_env_var)(
  196. SshChannel *c, bool want_reply, const char *var, const char *value);
  197. void (*start_shell)(
  198. SshChannel *c, bool want_reply);
  199. void (*start_command)(
  200. SshChannel *c, bool want_reply, const char *command);
  201. bool (*start_subsystem)(
  202. SshChannel *c, bool want_reply, const char *subsystem);
  203. bool (*send_serial_break)(
  204. SshChannel *c, bool want_reply, int length); /* length=0 for default */
  205. bool (*send_signal)(
  206. SshChannel *c, bool want_reply, const char *signame);
  207. void (*send_terminal_size_change)(
  208. SshChannel *c, int w, int h);
  209. void (*hint_channel_is_simple)(SshChannel *c);
  210. };
  211. struct SshChannel {
  212. const struct SshChannelVtable *vt;
  213. ConnectionLayer *cl;
  214. };
  215. static inline size_t sshfwd_write_ext(
  216. SshChannel *c, bool is_stderr, const void *data, size_t len)
  217. { return c->vt->write(c, is_stderr, data, len); }
  218. static inline size_t sshfwd_write(SshChannel *c, const void *data, size_t len)
  219. { return sshfwd_write_ext(c, false, data, len); }
  220. static inline void sshfwd_write_eof(SshChannel *c)
  221. { c->vt->write_eof(c); }
  222. static inline void sshfwd_initiate_close(SshChannel *c, const char *err)
  223. { c->vt->initiate_close(c, err); }
  224. static inline void sshfwd_unthrottle(SshChannel *c, size_t bufsize)
  225. { c->vt->unthrottle(c, bufsize); }
  226. static inline Conf *sshfwd_get_conf(SshChannel *c)
  227. { return c->vt->get_conf(c); }
  228. static inline void sshfwd_window_override_removed(SshChannel *c)
  229. { c->vt->window_override_removed(c); }
  230. static inline void sshfwd_x11_sharing_handover(
  231. SshChannel *c, ssh_sharing_connstate *cs, share_channel *sch,
  232. const char *addr, int port, int endian, int maj, int min,
  233. const void *idata, int ilen)
  234. { c->vt->x11_sharing_handover(c, cs, sch, addr, port, endian,
  235. maj, min, idata, ilen); }
  236. static inline void sshfwd_send_exit_status(SshChannel *c, int status)
  237. { c->vt->send_exit_status(c, status); }
  238. static inline void sshfwd_send_exit_signal(
  239. SshChannel *c, ptrlen signame, bool core_dumped, ptrlen msg)
  240. { c->vt->send_exit_signal(c, signame, core_dumped, msg); }
  241. static inline void sshfwd_send_exit_signal_numeric(
  242. SshChannel *c, int signum, bool core_dumped, ptrlen msg)
  243. { c->vt->send_exit_signal_numeric(c, signum, core_dumped, msg); }
  244. static inline void sshfwd_request_x11_forwarding(
  245. SshChannel *c, bool want_reply, const char *proto,
  246. const char *data, int scr, bool once)
  247. { c->vt->request_x11_forwarding(c, want_reply, proto, data, scr, once); }
  248. static inline void sshfwd_request_agent_forwarding(
  249. SshChannel *c, bool want_reply)
  250. { c->vt->request_agent_forwarding(c, want_reply); }
  251. static inline void sshfwd_request_pty(
  252. SshChannel *c, bool want_reply, Conf *conf, int w, int h)
  253. { c->vt->request_pty(c, want_reply, conf, w, h); }
  254. static inline bool sshfwd_send_env_var(
  255. SshChannel *c, bool want_reply, const char *var, const char *value)
  256. { return c->vt->send_env_var(c, want_reply, var, value); }
  257. static inline void sshfwd_start_shell(
  258. SshChannel *c, bool want_reply)
  259. { c->vt->start_shell(c, want_reply); }
  260. static inline void sshfwd_start_command(
  261. SshChannel *c, bool want_reply, const char *command)
  262. { c->vt->start_command(c, want_reply, command); }
  263. static inline bool sshfwd_start_subsystem(
  264. SshChannel *c, bool want_reply, const char *subsystem)
  265. { return c->vt->start_subsystem(c, want_reply, subsystem); }
  266. static inline bool sshfwd_send_serial_break(
  267. SshChannel *c, bool want_reply, int length)
  268. { return c->vt->send_serial_break(c, want_reply, length); }
  269. static inline bool sshfwd_send_signal(
  270. SshChannel *c, bool want_reply, const char *signame)
  271. { return c->vt->send_signal(c, want_reply, signame); }
  272. static inline void sshfwd_send_terminal_size_change(
  273. SshChannel *c, int w, int h)
  274. { c->vt->send_terminal_size_change(c, w, h); }
  275. static inline void sshfwd_hint_channel_is_simple(SshChannel *c)
  276. { c->vt->hint_channel_is_simple(c); }
  277. /* ----------------------------------------------------------------------
  278. * The 'main' or primary channel of the SSH connection is special,
  279. * because it's the one that's connected directly to parts of the
  280. * frontend such as the terminal and the specials menu. So it exposes
  281. * a richer API.
  282. */
  283. mainchan *mainchan_new(
  284. PacketProtocolLayer *ppl, ConnectionLayer *cl, Conf *conf,
  285. int term_width, int term_height, bool is_simple, SshChannel **sc_out);
  286. void mainchan_get_specials(
  287. mainchan *mc, add_special_fn_t add_special, void *ctx);
  288. void mainchan_special_cmd(mainchan *mc, SessionSpecialCode code, int arg);
  289. void mainchan_terminal_size(mainchan *mc, int width, int height);
  290. #endif /* PUTTY_SSHCHAN_H */