mainchan.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /*
  2. * SSH main session channel handling.
  3. */
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include "putty.h"
  8. #include "ssh.h"
  9. #include "ppl.h"
  10. #include "channel.h"
  11. static void mainchan_free(Channel *chan);
  12. static void mainchan_open_confirmation(Channel *chan);
  13. static void mainchan_open_failure(Channel *chan, const char *errtext);
  14. static size_t mainchan_send(
  15. Channel *chan, bool is_stderr, const void *, size_t);
  16. static void mainchan_send_eof(Channel *chan);
  17. static void mainchan_set_input_wanted(Channel *chan, bool wanted);
  18. static char *mainchan_log_close_msg(Channel *chan);
  19. static bool mainchan_rcvd_exit_status(Channel *chan, int status);
  20. static bool mainchan_rcvd_exit_signal(
  21. Channel *chan, ptrlen signame, bool core_dumped, ptrlen msg);
  22. static bool mainchan_rcvd_exit_signal_numeric(
  23. Channel *chan, int signum, bool core_dumped, ptrlen msg);
  24. static void mainchan_request_response(Channel *chan, bool success);
  25. static const ChannelVtable mainchan_channelvt = {
  26. // WINSCP
  27. /*.free =*/ mainchan_free,
  28. /*.open_confirmation =*/ mainchan_open_confirmation,
  29. /*.open_failed =*/ mainchan_open_failure,
  30. /*.send =*/ mainchan_send,
  31. /*.send_eof =*/ mainchan_send_eof,
  32. /*.set_input_wanted =*/ mainchan_set_input_wanted,
  33. /*.log_close_msg =*/ mainchan_log_close_msg,
  34. /*.want_close =*/ chan_default_want_close,
  35. /*.rcvd_exit_status =*/ mainchan_rcvd_exit_status,
  36. /*.rcvd_exit_signal =*/ mainchan_rcvd_exit_signal,
  37. /*.rcvd_exit_signal_numeric =*/ mainchan_rcvd_exit_signal_numeric,
  38. /*.run_shell =*/ chan_no_run_shell,
  39. /*.run_command =*/ chan_no_run_command,
  40. /*.run_subsystem =*/ chan_no_run_subsystem,
  41. /*.enable_x11_forwarding =*/ chan_no_enable_x11_forwarding,
  42. /*.enable_agent_forwarding =*/ chan_no_enable_agent_forwarding,
  43. /*.allocate_pty =*/ chan_no_allocate_pty,
  44. /*.set_env =*/ chan_no_set_env,
  45. /*.send_break =*/ chan_no_send_break,
  46. /*.send_signal =*/ chan_no_send_signal,
  47. /*.change_window_size =*/ chan_no_change_window_size,
  48. /*.request_response =*/ mainchan_request_response,
  49. };
  50. typedef enum MainChanType {
  51. MAINCHAN_SESSION, MAINCHAN_DIRECT_TCPIP
  52. } MainChanType;
  53. struct mainchan {
  54. SshChannel *sc;
  55. Conf *conf;
  56. PacketProtocolLayer *ppl;
  57. ConnectionLayer *cl;
  58. MainChanType type;
  59. bool is_simple;
  60. bool req_x11, req_agent, req_pty, req_cmd_primary, req_cmd_fallback;
  61. int n_req_env, n_env_replies, n_env_fails;
  62. bool eof_pending, eof_sent, got_pty, ready;
  63. int term_width, term_height;
  64. Channel chan;
  65. };
  66. mainchan *mainchan_new(
  67. PacketProtocolLayer *ppl, ConnectionLayer *cl, Conf *conf,
  68. int term_width, int term_height, bool is_simple, SshChannel **sc_out)
  69. {
  70. mainchan *mc;
  71. if (conf_get_bool(conf, CONF_ssh_no_shell))
  72. return NULL; /* no main channel at all */
  73. mc = snew(mainchan);
  74. memset(mc, 0, sizeof(mainchan));
  75. mc->ppl = ppl;
  76. mc->cl = cl;
  77. mc->conf = conf_copy(conf);
  78. mc->term_width = term_width;
  79. mc->term_height = term_height;
  80. mc->is_simple = is_simple;
  81. mc->sc = NULL;
  82. mc->chan.vt = &mainchan_channelvt;
  83. mc->chan.initial_fixed_window_size = 0;
  84. if (*conf_get_str(mc->conf, CONF_ssh_nc_host)) {
  85. const char *host = conf_get_str(mc->conf, CONF_ssh_nc_host);
  86. int port = conf_get_int(mc->conf, CONF_ssh_nc_port);
  87. mc->sc = ssh_lportfwd_open(cl, host, port, "main channel",
  88. NULL, &mc->chan);
  89. mc->type = MAINCHAN_DIRECT_TCPIP;
  90. } else {
  91. mc->sc = ssh_session_open(cl, &mc->chan);
  92. mc->type = MAINCHAN_SESSION;
  93. }
  94. if (sc_out) *sc_out = mc->sc;
  95. return mc;
  96. }
  97. static void mainchan_free(Channel *chan)
  98. {
  99. pinitassert(chan->vt == &mainchan_channelvt);
  100. mainchan *mc = container_of(chan, mainchan, chan);
  101. conf_free(mc->conf);
  102. sfree(mc);
  103. }
  104. static void mainchan_try_fallback_command(mainchan *mc);
  105. static void mainchan_ready(mainchan *mc);
  106. static void mainchan_open_confirmation(Channel *chan)
  107. {
  108. mainchan *mc = container_of(chan, mainchan, chan);
  109. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  110. seat_update_specials_menu(mc->ppl->seat);
  111. ppl_logevent("Opened main channel");
  112. seat_notify_session_started(mc->ppl->seat);
  113. if (mc->is_simple)
  114. sshfwd_hint_channel_is_simple(mc->sc);
  115. if (mc->type == MAINCHAN_SESSION) {
  116. /*
  117. * Send the CHANNEL_REQUESTS for the main session channel.
  118. */
  119. char *key, *val, *cmd;
  120. #ifndef WINSCP
  121. struct X11Display *x11disp;
  122. struct X11FakeAuth *x11auth;
  123. #endif
  124. bool retry_cmd_now = false;
  125. #ifndef WINSCP
  126. if (conf_get_bool(mc->conf, CONF_x11_forward)) {
  127. char *x11_setup_err;
  128. if ((x11disp = x11_setup_display(
  129. conf_get_str(mc->conf, CONF_x11_display),
  130. mc->conf, &x11_setup_err)) == NULL) {
  131. ppl_logevent("X11 forwarding not enabled: unable to"
  132. " initialise X display: %s", x11_setup_err);
  133. sfree(x11_setup_err);
  134. } else {
  135. x11auth = ssh_add_x11_display(
  136. mc->cl, conf_get_int(mc->conf, CONF_x11_auth), x11disp);
  137. sshfwd_request_x11_forwarding(
  138. mc->sc, true, x11auth->protoname, x11auth->datastring,
  139. x11disp->screennum, false);
  140. mc->req_x11 = true;
  141. }
  142. }
  143. #endif
  144. if (ssh_agent_forwarding_permitted(mc->cl)) {
  145. sshfwd_request_agent_forwarding(mc->sc, true);
  146. mc->req_agent = true;
  147. }
  148. if (!conf_get_bool(mc->conf, CONF_nopty)) {
  149. sshfwd_request_pty(
  150. mc->sc, true, mc->conf, mc->term_width, mc->term_height);
  151. mc->req_pty = true;
  152. }
  153. for (val = conf_get_str_strs(mc->conf, CONF_environmt, NULL, &key);
  154. val != NULL;
  155. val = conf_get_str_strs(mc->conf, CONF_environmt, key, &key)) {
  156. sshfwd_send_env_var(mc->sc, true, key, val);
  157. mc->n_req_env++;
  158. }
  159. if (mc->n_req_env)
  160. ppl_logevent("Sent %d environment variables", mc->n_req_env);
  161. /* Ignore encoding of CONF_remote_cmd so as not to disturb
  162. * legacy handling of non-UTF-8 commands */
  163. cmd = conf_get_str_ambi(mc->conf, CONF_remote_cmd, NULL);
  164. if (conf_get_bool(mc->conf, CONF_ssh_subsys)) {
  165. retry_cmd_now = !sshfwd_start_subsystem(mc->sc, true, cmd);
  166. } else if (*cmd) {
  167. sshfwd_start_command(mc->sc, true, cmd);
  168. } else {
  169. sshfwd_start_shell(mc->sc, true);
  170. }
  171. if (retry_cmd_now)
  172. mainchan_try_fallback_command(mc);
  173. else
  174. mc->req_cmd_primary = true;
  175. } else {
  176. ssh_set_ldisc_option(mc->cl, LD_ECHO, true);
  177. ssh_set_ldisc_option(mc->cl, LD_EDIT, true);
  178. mainchan_ready(mc);
  179. }
  180. }
  181. static void mainchan_try_fallback_command(mainchan *mc)
  182. {
  183. /* Ignore encoding of CONF_remote_cmd2 so as not to disturb legacy
  184. * handling of non-UTF-8 commands */
  185. const char *cmd = conf_get_str_ambi(mc->conf, CONF_remote_cmd2, NULL);
  186. if (conf_get_bool(mc->conf, CONF_ssh_subsys2)) {
  187. sshfwd_start_subsystem(mc->sc, true, cmd);
  188. } else if (*cmd) {
  189. sshfwd_start_command(mc->sc, true, cmd);
  190. } else {
  191. sshfwd_start_shell(mc->sc, true); // WINSCP
  192. }
  193. mc->req_cmd_fallback = true;
  194. }
  195. static void mainchan_request_response(Channel *chan, bool success)
  196. {
  197. pinitassert(chan->vt == &mainchan_channelvt);
  198. mainchan *mc = container_of(chan, mainchan, chan);
  199. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  200. if (mc->req_x11) {
  201. mc->req_x11 = false;
  202. if (success) {
  203. ppl_logevent("X11 forwarding enabled");
  204. ssh_enable_x_fwd(mc->cl);
  205. } else {
  206. ppl_logevent("X11 forwarding refused");
  207. }
  208. return;
  209. }
  210. if (mc->req_agent) {
  211. mc->req_agent = false;
  212. if (success) {
  213. ppl_logevent("Agent forwarding enabled");
  214. } else {
  215. ppl_logevent("Agent forwarding refused");
  216. }
  217. return;
  218. }
  219. if (mc->req_pty) {
  220. mc->req_pty = false;
  221. if (success) {
  222. ppl_logevent("Allocated pty");
  223. mc->got_pty = true;
  224. } else {
  225. ppl_logevent("Server refused to allocate pty");
  226. ppl_printf("Server refused to allocate pty\r\n");
  227. ssh_set_ldisc_option(mc->cl, LD_ECHO, true);
  228. ssh_set_ldisc_option(mc->cl, LD_EDIT, true);
  229. }
  230. return;
  231. }
  232. if (mc->n_env_replies < mc->n_req_env) {
  233. int j = mc->n_env_replies++;
  234. if (!success) {
  235. ppl_logevent("Server refused to set environment variable %s",
  236. conf_get_str_nthstrkey(mc->conf,
  237. CONF_environmt, j));
  238. mc->n_env_fails++;
  239. }
  240. if (mc->n_env_replies == mc->n_req_env) {
  241. if (mc->n_env_fails == 0) {
  242. ppl_logevent("All environment variables successfully set");
  243. } else if (mc->n_env_fails == mc->n_req_env) {
  244. ppl_logevent("All environment variables refused");
  245. ppl_printf("Server refused to set environment "
  246. "variables\r\n");
  247. } else {
  248. ppl_printf("Server refused to set all environment "
  249. "variables\r\n");
  250. }
  251. }
  252. return;
  253. }
  254. if (mc->req_cmd_primary) {
  255. mc->req_cmd_primary = false;
  256. if (success) {
  257. ppl_logevent("Started a shell/command");
  258. mainchan_ready(mc);
  259. } else if (*conf_get_str_ambi(mc->conf, CONF_remote_cmd2, NULL) || conf_get_bool(mc->conf, CONF_force_remote_cmd2)) { // WINSCP
  260. ppl_logevent("Primary command failed; attempting fallback");
  261. mainchan_try_fallback_command(mc);
  262. } else {
  263. /*
  264. * If there's no remote_cmd2 configured, then we have no
  265. * fallback command, so we've run out of options.
  266. */
  267. ssh_sw_abort_deferred(mc->ppl->ssh,
  268. "Server refused to start a shell/command");
  269. }
  270. return;
  271. }
  272. if (mc->req_cmd_fallback) {
  273. mc->req_cmd_fallback = false;
  274. if (success) {
  275. ppl_logevent("Started a shell/command");
  276. ssh_got_fallback_cmd(mc->ppl->ssh);
  277. mainchan_ready(mc);
  278. } else {
  279. ssh_sw_abort_deferred(mc->ppl->ssh,
  280. "Server refused to start a shell/command");
  281. }
  282. return;
  283. }
  284. }
  285. static void mainchan_ready(mainchan *mc)
  286. {
  287. mc->ready = true;
  288. ssh_set_wants_user_input(mc->cl, true);
  289. ssh_got_user_input(mc->cl); /* in case any is already queued */
  290. /* If an EOF arrived before we were ready, handle it now. */
  291. if (mc->eof_pending) {
  292. mc->eof_pending = false;
  293. mainchan_special_cmd(mc, SS_EOF, 0);
  294. }
  295. ssh_ldisc_update(mc->ppl->ssh);
  296. queue_idempotent_callback(&mc->ppl->ic_process_queue);
  297. }
  298. static void mainchan_open_failure(Channel *chan, const char *errtext)
  299. {
  300. pinitassert(chan->vt == &mainchan_channelvt);
  301. mainchan *mc = container_of(chan, mainchan, chan);
  302. ssh_sw_abort_deferred(mc->ppl->ssh,
  303. "Server refused to open main channel: %s", errtext);
  304. }
  305. static size_t mainchan_send(Channel *chan, bool is_stderr,
  306. const void *data, size_t length)
  307. {
  308. pinitassert(chan->vt == &mainchan_channelvt);
  309. mainchan *mc = container_of(chan, mainchan, chan);
  310. return seat_output(mc->ppl->seat, is_stderr, data, length);
  311. }
  312. static void mainchan_send_eof(Channel *chan)
  313. {
  314. pinitassert(chan->vt == &mainchan_channelvt);
  315. mainchan *mc = container_of(chan, mainchan, chan);
  316. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  317. if (!mc->eof_sent && (seat_eof(mc->ppl->seat) || mc->got_pty)) {
  318. /*
  319. * Either seat_eof told us that the front end wants us to
  320. * close the outgoing side of the connection as soon as we see
  321. * EOF from the far end, or else we've unilaterally decided to
  322. * do that because we've allocated a remote pty and hence EOF
  323. * isn't a particularly meaningful concept.
  324. */
  325. sshfwd_write_eof(mc->sc);
  326. ppl_logevent("Sent EOF message");
  327. mc->eof_sent = true;
  328. ssh_set_wants_user_input(mc->cl, false); /* stop reading from stdin */
  329. }
  330. }
  331. static void mainchan_set_input_wanted(Channel *chan, bool wanted)
  332. {
  333. pinitassert(chan->vt == &mainchan_channelvt);
  334. mainchan *mc = container_of(chan, mainchan, chan);
  335. /*
  336. * This is the main channel of the SSH session, i.e. the one tied
  337. * to the standard input (or GUI) of the primary SSH client user
  338. * interface. So ssh->send_ok is how we control whether we're
  339. * reading from that input.
  340. */
  341. ssh_set_wants_user_input(mc->cl, wanted);
  342. }
  343. static char *mainchan_log_close_msg(Channel *chan)
  344. {
  345. return dupstr("Main session channel closed");
  346. }
  347. static bool mainchan_rcvd_exit_status(Channel *chan, int status)
  348. {
  349. pinitassert(chan->vt == &mainchan_channelvt);
  350. mainchan *mc = container_of(chan, mainchan, chan);
  351. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  352. ssh_got_exitcode(mc->ppl->ssh, status);
  353. ppl_logevent("Session sent command exit status %d", status);
  354. return true;
  355. }
  356. static void mainchan_log_exit_signal_common(
  357. mainchan *mc, const char *sigdesc,
  358. bool core_dumped, ptrlen msg)
  359. {
  360. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  361. const char *core_msg = core_dumped ? " (core dumped)" : "";
  362. const char *msg_pre = (msg.len ? " (" : "");
  363. const char *msg_post = (msg.len ? ")" : "");
  364. ppl_logevent("Session exited on %s%s%s%.*s%s",
  365. sigdesc, core_msg, msg_pre, PTRLEN_PRINTF(msg), msg_post);
  366. }
  367. static bool mainchan_rcvd_exit_signal(
  368. Channel *chan, ptrlen signame, bool core_dumped, ptrlen msg)
  369. {
  370. pinitassert(chan->vt == &mainchan_channelvt);
  371. mainchan *mc = container_of(chan, mainchan, chan);
  372. int exitcode;
  373. char *signame_str;
  374. /*
  375. * Translate the signal description back into a locally meaningful
  376. * number, or 128 if the string didn't match any we recognise.
  377. */
  378. exitcode = 128;
  379. #define SIGNAL_SUB(s) \
  380. if (ptrlen_eq_string(signame, #s)) \
  381. exitcode = 128 + SIG ## s;
  382. #define SIGNAL_MAIN(s, text) SIGNAL_SUB(s)
  383. #define SIGNALS_LOCAL_ONLY
  384. #include "signal-list.h"
  385. #undef SIGNAL_SUB
  386. #undef SIGNAL_MAIN
  387. #undef SIGNALS_LOCAL_ONLY
  388. ssh_got_exitcode(mc->ppl->ssh, exitcode);
  389. if (exitcode == 128)
  390. signame_str = dupprintf("unrecognised signal \"%.*s\"",
  391. PTRLEN_PRINTF(signame));
  392. else
  393. signame_str = dupprintf("signal SIG%.*s", PTRLEN_PRINTF(signame));
  394. mainchan_log_exit_signal_common(mc, signame_str, core_dumped, msg);
  395. sfree(signame_str);
  396. return true;
  397. }
  398. static bool mainchan_rcvd_exit_signal_numeric(
  399. Channel *chan, int signum, bool core_dumped, ptrlen msg)
  400. {
  401. pinitassert(chan->vt == &mainchan_channelvt);
  402. mainchan *mc = container_of(chan, mainchan, chan);
  403. char *signum_str;
  404. ssh_got_exitcode(mc->ppl->ssh, 128 + signum);
  405. signum_str = dupprintf("signal %d", signum);
  406. mainchan_log_exit_signal_common(mc, signum_str, core_dumped, msg);
  407. sfree(signum_str);
  408. return true;
  409. }
  410. void mainchan_get_specials(
  411. mainchan *mc, add_special_fn_t add_special, void *ctx)
  412. {
  413. /* FIXME: this _does_ depend on whether these services are supported */
  414. /* WINSCP (causes linker warning and we do not use these)
  415. add_special(ctx, "Break", SS_BRK, 0);
  416. #define SIGNAL_MAIN(name, desc) \
  417. add_special(ctx, "SIG" #name " (" desc ")", SS_SIG ## name, 0);
  418. #define SIGNAL_SUB(name)
  419. #include "signal-list.h"
  420. #undef SIGNAL_MAIN
  421. #undef SIGNAL_SUB
  422. add_special(ctx, "More signals", SS_SUBMENU, 0);
  423. #define SIGNAL_MAIN(name, desc)
  424. #define SIGNAL_SUB(name) \
  425. add_special(ctx, "SIG" #name, SS_SIG ## name, 0);
  426. #include "signal-list.h"
  427. #undef SIGNAL_MAIN
  428. #undef SIGNAL_SUB
  429. add_special(ctx, NULL, SS_EXITMENU, 0);
  430. */
  431. }
  432. static const char *ssh_signal_lookup(SessionSpecialCode code)
  433. {
  434. #define SIGNAL_SUB(name) \
  435. if (code == SS_SIG ## name) return #name;
  436. #define SIGNAL_MAIN(name, desc) SIGNAL_SUB(name)
  437. #include "signal-list.h"
  438. #undef SIGNAL_MAIN
  439. #undef SIGNAL_SUB
  440. /* If none of those clauses matched, fail lookup. */
  441. return NULL;
  442. }
  443. void mainchan_special_cmd(mainchan *mc, SessionSpecialCode code, int arg)
  444. {
  445. PacketProtocolLayer *ppl = mc->ppl; /* for ppl_logevent */
  446. const char *signame;
  447. if (code == SS_EOF) {
  448. if (!mc->ready) {
  449. /*
  450. * Buffer the EOF to send as soon as the main channel is
  451. * fully set up.
  452. */
  453. mc->eof_pending = true;
  454. } else if (!mc->eof_sent) {
  455. sshfwd_write_eof(mc->sc);
  456. mc->eof_sent = true;
  457. }
  458. } else if (code == SS_BRK) {
  459. sshfwd_send_serial_break(
  460. mc->sc, false, 0 /* default break length */);
  461. } else if ((signame = ssh_signal_lookup(code)) != NULL) {
  462. /* It's a signal. */
  463. sshfwd_send_signal(mc->sc, false, signame);
  464. ppl_logevent("Sent signal SIG%s", signame);
  465. }
  466. }
  467. void mainchan_terminal_size(mainchan *mc, int width, int height)
  468. {
  469. mc->term_width = width;
  470. mc->term_height = height;
  471. if (mc->req_pty || mc->got_pty)
  472. sshfwd_send_terminal_size_change(mc->sc, width, height);
  473. }