1 /*
2  * Client-specific parts of the SSH-1 connection layer.
3  */
4 
5 #include <assert.h>
6 
7 #include "putty.h"
8 #include "ssh.h"
9 #include "sshbpp.h"
10 #include "sshppl.h"
11 #include "sshchan.h"
12 #include "sshcr.h"
13 #include "ssh1connection.h"
14 
ssh1_connection_direction_specific_setup(struct ssh1_connection_state * s)15 void ssh1_connection_direction_specific_setup(
16     struct ssh1_connection_state *s)
17 {
18     if (!s->mainchan) {
19         /*
20          * Start up the main session, by telling mainchan.c to do it
21          * all just as it would in SSH-2, and translating those
22          * concepts to SSH-1's non-channel-shaped idea of the main
23          * session.
24          */
25         s->mainchan = mainchan_new(
26             &s->ppl, &s->cl, s->conf, s->term_width, s->term_height,
27             false /* is_simple */, NULL);
28     }
29 }
30 
31 typedef void (*sf_handler_fn_t)(struct ssh1_connection_state *s,
32                                 bool success, void *ctx);
33 
34 struct outstanding_succfail {
35     sf_handler_fn_t handler;
36     void *ctx;
37     struct outstanding_succfail *next;
38 
39     /*
40      * The 'trivial' flag is set if this handler is in response to a
41      * request for which the SSH-1 protocol doesn't actually specify a
42      * response packet. The client of this system (mainchan.c) will
43      * expect to get an acknowledgment regardless, so we arrange to
44      * send that ack immediately after the rest of the queue empties.
45      */
46     bool trivial;
47 };
48 
49 static void ssh1_connection_process_trivial_succfails(void *vs);
50 
ssh1_queue_succfail_handler(struct ssh1_connection_state * s,sf_handler_fn_t handler,void * ctx,bool trivial)51 static void ssh1_queue_succfail_handler(
52     struct ssh1_connection_state *s, sf_handler_fn_t handler, void *ctx,
53     bool trivial)
54 {
55     struct outstanding_succfail *osf = snew(struct outstanding_succfail);
56     osf->handler = handler;
57     osf->ctx = ctx;
58     osf->trivial = trivial;
59     osf->next = NULL;
60     if (s->succfail_tail)
61         s->succfail_tail->next = osf;
62     else
63         s->succfail_head = osf;
64     s->succfail_tail = osf;
65 
66     /* In case this one was trivial and the queue was already empty,
67      * we should make sure we run the handler promptly, and the
68      * easiest way is to queue it anyway and then run a trivials pass
69      * by callback. */
70     queue_toplevel_callback(ssh1_connection_process_trivial_succfails, s);
71 }
72 
ssh1_connection_process_succfail(struct ssh1_connection_state * s,bool success)73 static void ssh1_connection_process_succfail(
74     struct ssh1_connection_state *s, bool success)
75 {
76     struct outstanding_succfail *prevhead = s->succfail_head;
77     s->succfail_head = s->succfail_head->next;
78     if (!s->succfail_head)
79         s->succfail_tail = NULL;
80     prevhead->handler(s, success, prevhead->ctx);
81     sfree(prevhead);
82 }
83 
ssh1_connection_process_trivial_succfails(void * vs)84 static void ssh1_connection_process_trivial_succfails(void *vs)
85 {
86     struct ssh1_connection_state *s = (struct ssh1_connection_state *)vs;
87     while (s->succfail_head && s->succfail_head->trivial)
88         ssh1_connection_process_succfail(s, true);
89 }
90 
ssh1_handle_direction_specific_packet(struct ssh1_connection_state * s,PktIn * pktin)91 bool ssh1_handle_direction_specific_packet(
92     struct ssh1_connection_state *s, PktIn *pktin)
93 {
94     PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
95 
96     PktOut *pktout;
97     struct ssh1_channel *c;
98     unsigned remid;
99     struct ssh_rportfwd pf, *pfp;
100     ptrlen host, data;
101     int port;
102 
103     switch (pktin->type) {
104       case SSH1_SMSG_SUCCESS:
105       case SSH1_SMSG_FAILURE:
106         if (!s->succfail_head) {
107             ssh_remote_error(s->ppl.ssh,
108                              "Received %s with no outstanding request",
109                              ssh1_pkt_type(pktin->type));
110             return true;
111         }
112 
113         ssh1_connection_process_succfail(
114             s, pktin->type == SSH1_SMSG_SUCCESS);
115         queue_toplevel_callback(
116             ssh1_connection_process_trivial_succfails, s);
117 
118         return true;
119 
120       case SSH1_SMSG_X11_OPEN:
121         remid = get_uint32(pktin);
122 
123         /* Refuse if X11 forwarding is disabled. */
124         if (!s->X11_fwd_enabled) {
125             pktout = ssh_bpp_new_pktout(
126                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
127             put_uint32(pktout, remid);
128             pq_push(s->ppl.out_pq, pktout);
129             ppl_logevent("Rejected X11 connect request");
130         } else {
131             c = snew(struct ssh1_channel);
132             c->connlayer = s;
133             ssh1_channel_init(c);
134             c->remoteid = remid;
135             c->chan = x11_new_channel(s->x11authtree, &c->sc,
136                                       NULL, -1, false);
137             c->remoteid = remid;
138             c->halfopen = false;
139 
140             pktout = ssh_bpp_new_pktout(
141                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
142             put_uint32(pktout, c->remoteid);
143             put_uint32(pktout, c->localid);
144             pq_push(s->ppl.out_pq, pktout);
145             ppl_logevent("Opened X11 forward channel");
146         }
147 
148         return true;
149 
150       case SSH1_SMSG_AGENT_OPEN:
151         remid = get_uint32(pktin);
152 
153         /* Refuse if agent forwarding is disabled. */
154         if (!ssh_agent_forwarding_permitted(&s->cl)) {
155             pktout = ssh_bpp_new_pktout(
156                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
157             put_uint32(pktout, remid);
158             pq_push(s->ppl.out_pq, pktout);
159         } else {
160             c = snew(struct ssh1_channel);
161             c->connlayer = s;
162             ssh1_channel_init(c);
163             c->remoteid = remid;
164             c->halfopen = false;
165 
166             /*
167              * If possible, make a stream-oriented connection to the
168              * agent and set up an ordinary port-forwarding type
169              * channel over it.
170              */
171             Plug *plug;
172             Channel *ch = portfwd_raw_new(&s->cl, &plug, true);
173             Socket *skt = agent_connect(plug);
174             if (!sk_socket_error(skt)) {
175                 portfwd_raw_setup(ch, skt, &c->sc);
176                 c->chan = ch;
177             } else {
178                 portfwd_raw_free(ch);
179 
180                 /*
181                  * Otherwise, fall back to the old-fashioned system of
182                  * parsing the forwarded data stream ourselves for
183                  * message boundaries, and passing each individual
184                  * message to the one-off agent_query().
185                  */
186                 c->chan = agentf_new(&c->sc);
187             }
188 
189             pktout = ssh_bpp_new_pktout(
190                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
191             put_uint32(pktout, c->remoteid);
192             put_uint32(pktout, c->localid);
193             pq_push(s->ppl.out_pq, pktout);
194         }
195 
196         return true;
197 
198       case SSH1_MSG_PORT_OPEN:
199         remid = get_uint32(pktin);
200         host = get_string(pktin);
201         port = toint(get_uint32(pktin));
202 
203         pf.dhost = mkstr(host);
204         pf.dport = port;
205         pfp = find234(s->rportfwds, &pf, NULL);
206 
207         if (!pfp) {
208             ppl_logevent("Rejected remote port open request for %s:%d",
209                          pf.dhost, port);
210             pktout = ssh_bpp_new_pktout(
211                 s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
212             put_uint32(pktout, remid);
213             pq_push(s->ppl.out_pq, pktout);
214         } else {
215             char *err;
216 
217             c = snew(struct ssh1_channel);
218             c->connlayer = s;
219             ppl_logevent("Received remote port open request for %s:%d",
220                          pf.dhost, port);
221             err = portfwdmgr_connect(
222                 s->portfwdmgr, &c->chan, pf.dhost, port,
223                 &c->sc, pfp->addressfamily);
224 
225             if (err) {
226                 ppl_logevent("Port open failed: %s", err);
227                 sfree(err);
228                 ssh1_channel_free(c);
229                 pktout = ssh_bpp_new_pktout(
230                     s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_FAILURE);
231                 put_uint32(pktout, remid);
232                 pq_push(s->ppl.out_pq, pktout);
233             } else {
234                 ssh1_channel_init(c);
235                 c->remoteid = remid;
236                 c->halfopen = false;
237                 pktout = ssh_bpp_new_pktout(
238                     s->ppl.bpp, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION);
239                 put_uint32(pktout, c->remoteid);
240                 put_uint32(pktout, c->localid);
241                 pq_push(s->ppl.out_pq, pktout);
242                 ppl_logevent("Forwarded port opened successfully");
243             }
244         }
245 
246         sfree(pf.dhost);
247 
248         return true;
249 
250       case SSH1_SMSG_STDOUT_DATA:
251       case SSH1_SMSG_STDERR_DATA:
252         data = get_string(pktin);
253         if (!get_err(pktin)) {
254             int bufsize = seat_output(
255                 s->ppl.seat, pktin->type == SSH1_SMSG_STDERR_DATA,
256                 data.ptr, data.len);
257             if (!s->stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
258                 s->stdout_throttling = true;
259                 ssh_throttle_conn(s->ppl.ssh, +1);
260             }
261         }
262 
263         return true;
264 
265       case SSH1_SMSG_EXIT_STATUS: {
266         int exitcode = get_uint32(pktin);
267         ppl_logevent("Server sent command exit status %d", exitcode);
268         ssh_got_exitcode(s->ppl.ssh, exitcode);
269 
270         s->session_terminated = true;
271         return true;
272       }
273 
274       default:
275         return false;
276     }
277 }
278 
ssh1mainchan_succfail_wantreply(struct ssh1_connection_state * s,bool success,void * ctx)279 static void ssh1mainchan_succfail_wantreply(struct ssh1_connection_state *s,
280                                             bool success, void *ctx)
281 {
282     chan_request_response(s->mainchan_chan, success);
283 }
284 
ssh1mainchan_succfail_nowantreply(struct ssh1_connection_state * s,bool success,void * ctx)285 static void ssh1mainchan_succfail_nowantreply(struct ssh1_connection_state *s,
286                                               bool success, void *ctx)
287 {
288 }
289 
ssh1mainchan_queue_response(struct ssh1_connection_state * s,bool want_reply,bool trivial)290 static void ssh1mainchan_queue_response(struct ssh1_connection_state *s,
291                                         bool want_reply, bool trivial)
292 {
293     sf_handler_fn_t handler = (want_reply ? ssh1mainchan_succfail_wantreply :
294                                ssh1mainchan_succfail_nowantreply);
295     ssh1_queue_succfail_handler(s, handler, NULL, trivial);
296 }
297 
ssh1mainchan_request_x11_forwarding(SshChannel * sc,bool want_reply,const char * authproto,const char * authdata,int screen_number,bool oneshot)298 static void ssh1mainchan_request_x11_forwarding(
299     SshChannel *sc, bool want_reply, const char *authproto,
300     const char *authdata, int screen_number, bool oneshot)
301 {
302     struct ssh1_connection_state *s =
303         container_of(sc, struct ssh1_connection_state, mainchan_sc);
304     PktOut *pktout;
305 
306     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_X11_REQUEST_FORWARDING);
307     put_stringz(pktout, authproto);
308     put_stringz(pktout, authdata);
309     if (s->local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER)
310         put_uint32(pktout, screen_number);
311     pq_push(s->ppl.out_pq, pktout);
312 
313     ssh1mainchan_queue_response(s, want_reply, false);
314 }
315 
ssh1mainchan_request_agent_forwarding(SshChannel * sc,bool want_reply)316 static void ssh1mainchan_request_agent_forwarding(
317     SshChannel *sc, bool want_reply)
318 {
319     struct ssh1_connection_state *s =
320         container_of(sc, struct ssh1_connection_state, mainchan_sc);
321     PktOut *pktout;
322 
323     pktout = ssh_bpp_new_pktout(
324         s->ppl.bpp, SSH1_CMSG_AGENT_REQUEST_FORWARDING);
325     pq_push(s->ppl.out_pq, pktout);
326 
327     ssh1mainchan_queue_response(s, want_reply, false);
328 }
329 
ssh1mainchan_request_pty(SshChannel * sc,bool want_reply,Conf * conf,int w,int h)330 static void ssh1mainchan_request_pty(
331     SshChannel *sc, bool want_reply, Conf *conf, int w, int h)
332 {
333     struct ssh1_connection_state *s =
334         container_of(sc, struct ssh1_connection_state, mainchan_sc);
335     PktOut *pktout;
336 
337     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_REQUEST_PTY);
338     put_stringz(pktout, conf_get_str(s->conf, CONF_termtype));
339     put_uint32(pktout, h);
340     put_uint32(pktout, w);
341     put_uint32(pktout, 0); /* width in pixels */
342     put_uint32(pktout, 0); /* height in pixels */
343     write_ttymodes_to_packet(
344         BinarySink_UPCAST(pktout), 1,
345         get_ttymodes_from_conf(s->ppl.seat, conf));
346     pq_push(s->ppl.out_pq, pktout);
347 
348     ssh1mainchan_queue_response(s, want_reply, false);
349 }
350 
ssh1mainchan_send_env_var(SshChannel * sc,bool want_reply,const char * var,const char * value)351 static bool ssh1mainchan_send_env_var(
352     SshChannel *sc, bool want_reply, const char *var, const char *value)
353 {
354     return false;              /* SSH-1 doesn't support this at all */
355 }
356 
ssh1mainchan_start_shell(SshChannel * sc,bool want_reply)357 static void ssh1mainchan_start_shell(SshChannel *sc, bool want_reply)
358 {
359     struct ssh1_connection_state *s =
360         container_of(sc, struct ssh1_connection_state, mainchan_sc);
361     PktOut *pktout;
362 
363     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EXEC_SHELL);
364     pq_push(s->ppl.out_pq, pktout);
365 
366     ssh1mainchan_queue_response(s, want_reply, true);
367 }
368 
ssh1mainchan_start_command(SshChannel * sc,bool want_reply,const char * command)369 static void ssh1mainchan_start_command(
370     SshChannel *sc, bool want_reply, const char *command)
371 {
372     struct ssh1_connection_state *s =
373         container_of(sc, struct ssh1_connection_state, mainchan_sc);
374     PktOut *pktout;
375 
376     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EXEC_CMD);
377     put_stringz(pktout, command);
378     pq_push(s->ppl.out_pq, pktout);
379 
380     ssh1mainchan_queue_response(s, want_reply, true);
381 }
382 
ssh1mainchan_start_subsystem(SshChannel * sc,bool want_reply,const char * subsystem)383 static bool ssh1mainchan_start_subsystem(
384     SshChannel *sc, bool want_reply, const char *subsystem)
385 {
386     return false;              /* SSH-1 doesn't support this at all */
387 }
388 
ssh1mainchan_send_serial_break(SshChannel * sc,bool want_reply,int length)389 static bool ssh1mainchan_send_serial_break(
390     SshChannel *sc, bool want_reply, int length)
391 {
392     return false;              /* SSH-1 doesn't support this at all */
393 }
394 
ssh1mainchan_send_signal(SshChannel * sc,bool want_reply,const char * signame)395 static bool ssh1mainchan_send_signal(
396     SshChannel *sc, bool want_reply, const char *signame)
397 {
398     return false;              /* SSH-1 doesn't support this at all */
399 }
400 
ssh1mainchan_send_terminal_size_change(SshChannel * sc,int w,int h)401 static void ssh1mainchan_send_terminal_size_change(
402     SshChannel *sc, int w, int h)
403 {
404     struct ssh1_connection_state *s =
405         container_of(sc, struct ssh1_connection_state, mainchan_sc);
406     PktOut *pktout;
407 
408     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_WINDOW_SIZE);
409     put_uint32(pktout, h);
410     put_uint32(pktout, w);
411     put_uint32(pktout, 0); /* width in pixels */
412     put_uint32(pktout, 0); /* height in pixels */
413     pq_push(s->ppl.out_pq, pktout);
414 }
415 
ssh1mainchan_hint_channel_is_simple(SshChannel * sc)416 static void ssh1mainchan_hint_channel_is_simple(SshChannel *sc)
417 {
418 }
419 
ssh1mainchan_write(SshChannel * sc,bool is_stderr,const void * data,size_t len)420 static size_t ssh1mainchan_write(
421     SshChannel *sc, bool is_stderr, const void *data, size_t len)
422 {
423     struct ssh1_connection_state *s =
424         container_of(sc, struct ssh1_connection_state, mainchan_sc);
425     PktOut *pktout;
426 
427     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_STDIN_DATA);
428     put_string(pktout, data, len);
429     pq_push(s->ppl.out_pq, pktout);
430 
431     return 0;
432 }
433 
ssh1mainchan_write_eof(SshChannel * sc)434 static void ssh1mainchan_write_eof(SshChannel *sc)
435 {
436     struct ssh1_connection_state *s =
437         container_of(sc, struct ssh1_connection_state, mainchan_sc);
438     PktOut *pktout;
439 
440     pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH1_CMSG_EOF);
441     pq_push(s->ppl.out_pq, pktout);
442 }
443 
444 static const SshChannelVtable ssh1mainchan_vtable = {
445     .write = ssh1mainchan_write,
446     .write_eof = ssh1mainchan_write_eof,
447     .request_x11_forwarding = ssh1mainchan_request_x11_forwarding,
448     .request_agent_forwarding = ssh1mainchan_request_agent_forwarding,
449     .request_pty = ssh1mainchan_request_pty,
450     .send_env_var = ssh1mainchan_send_env_var,
451     .start_shell = ssh1mainchan_start_shell,
452     .start_command = ssh1mainchan_start_command,
453     .start_subsystem = ssh1mainchan_start_subsystem,
454     .send_serial_break = ssh1mainchan_send_serial_break,
455     .send_signal = ssh1mainchan_send_signal,
456     .send_terminal_size_change = ssh1mainchan_send_terminal_size_change,
457     .hint_channel_is_simple = ssh1mainchan_hint_channel_is_simple,
458     /* other methods are NULL */
459 };
460 
ssh1_session_confirm_callback(void * vctx)461 static void ssh1_session_confirm_callback(void *vctx)
462 {
463     struct ssh1_connection_state *s = (struct ssh1_connection_state *)vctx;
464     chan_open_confirmation(s->mainchan_chan);
465 }
466 
ssh1_session_open(ConnectionLayer * cl,Channel * chan)467 SshChannel *ssh1_session_open(ConnectionLayer *cl, Channel *chan)
468 {
469     struct ssh1_connection_state *s =
470         container_of(cl, struct ssh1_connection_state, cl);
471     s->mainchan_sc.vt = &ssh1mainchan_vtable;
472     s->mainchan_sc.cl = &s->cl;
473     s->mainchan_chan = chan;
474     queue_toplevel_callback(ssh1_session_confirm_callback, s);
475     return &s->mainchan_sc;
476 }
477 
ssh1_rportfwd_response(struct ssh1_connection_state * s,bool success,void * ctx)478 static void ssh1_rportfwd_response(struct ssh1_connection_state *s,
479                                    bool success, void *ctx)
480 {
481     PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
482     struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
483 
484     if (success) {
485         ppl_logevent("Remote port forwarding from %s enabled",
486                      rpf->log_description);
487     } else {
488         ppl_logevent("Remote port forwarding from %s refused",
489                      rpf->log_description);
490 
491         struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
492         assert(realpf == rpf);
493         portfwdmgr_close(s->portfwdmgr, rpf->pfr);
494         free_rportfwd(rpf);
495     }
496 }
497 
ssh1_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)498 struct ssh_rportfwd *ssh1_rportfwd_alloc(
499     ConnectionLayer *cl,
500     const char *shost, int sport, const char *dhost, int dport,
501     int addressfamily, const char *log_description, PortFwdRecord *pfr,
502     ssh_sharing_connstate *share_ctx)
503 {
504     struct ssh1_connection_state *s =
505         container_of(cl, struct ssh1_connection_state, cl);
506     struct ssh_rportfwd *rpf = snew(struct ssh_rportfwd);
507 
508     rpf->shost = dupstr(shost);
509     rpf->sport = sport;
510     rpf->dhost = dupstr(dhost);
511     rpf->dport = dport;
512     rpf->addressfamily = addressfamily;
513     rpf->log_description = dupstr(log_description);
514     rpf->pfr = pfr;
515 
516     if (add234(s->rportfwds, rpf) != rpf) {
517         free_rportfwd(rpf);
518         return NULL;
519     }
520 
521     PktOut *pktout = ssh_bpp_new_pktout(
522         s->ppl.bpp, SSH1_CMSG_PORT_FORWARD_REQUEST);
523     put_uint32(pktout, rpf->sport);
524     put_stringz(pktout, rpf->dhost);
525     put_uint32(pktout, rpf->dport);
526     pq_push(s->ppl.out_pq, pktout);
527 
528     ssh1_queue_succfail_handler(s, ssh1_rportfwd_response, rpf, false);
529 
530     return rpf;
531 }
532 
ssh1_serverside_x11_open(ConnectionLayer * cl,Channel * chan,const SocketPeerInfo * pi)533 SshChannel *ssh1_serverside_x11_open(
534     ConnectionLayer *cl, Channel *chan, const SocketPeerInfo *pi)
535 {
536     unreachable("Should never be called in the client");
537 }
538 
ssh1_serverside_agent_open(ConnectionLayer * cl,Channel * chan)539 SshChannel *ssh1_serverside_agent_open(ConnectionLayer *cl, Channel *chan)
540 {
541     unreachable("Should never be called in the client");
542 }
543 
ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state * s)544 bool ssh1_connection_need_antispoof_prompt(struct ssh1_connection_state *s)
545 {
546     return !seat_set_trust_status(s->ppl.seat, false);
547 }
548