2 * Client-specific parts of the SSH-2 connection layer.
13 #include "ssh2connection.h"
15 static ChanopenResult
chan_open_x11(
16 struct ssh2_connection_state
*s
, SshChannel
*sc
,
17 ptrlen peeraddr
, int peerport
)
19 PacketProtocolLayer
*ppl
= &s
->ppl
; /* for ppl_logevent */
23 ppl_logevent("Received X11 connect request from %.*s:%d",
24 PTRLEN_PRINTF(peeraddr
), peerport
);
26 if (!s
->X11_fwd_enabled
&& !s
->connshare
) {
27 CHANOPEN_RETURN_FAILURE(
28 SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
,
29 ("X11 forwarding is not enabled"));
32 peeraddr_str
= peeraddr
.ptr
? mkstr(peeraddr
) : NULL
;
34 s
->x11authtree
, sc
, peeraddr_str
, peerport
, s
->connshare
!= NULL
);
36 ppl_logevent("Opened X11 forward channel");
37 CHANOPEN_RETURN_SUCCESS(ch
);
40 static ChanopenResult
chan_open_forwarded_tcpip(
41 struct ssh2_connection_state
*s
, SshChannel
*sc
,
42 ptrlen fwdaddr
, int fwdport
, ptrlen peeraddr
, int peerport
)
44 PacketProtocolLayer
*ppl
= &s
->ppl
; /* for ppl_logevent */
45 struct ssh_rportfwd pf
, *realpf
;
49 ppl_logevent("Received remote port %.*s:%d open request from %.*s:%d",
50 PTRLEN_PRINTF(fwdaddr
), fwdport
,
51 PTRLEN_PRINTF(peeraddr
), peerport
);
53 pf
.shost
= mkstr(fwdaddr
);
55 realpf
= find234(s
->rportfwds
, &pf
, NULL
);
59 CHANOPEN_RETURN_FAILURE(
60 SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
,
61 ("Remote port is not recognised"));
64 if (realpf
->share_ctx
) {
66 * This port forwarding is on behalf of a connection-sharing
69 CHANOPEN_RETURN_DOWNSTREAM(realpf
->share_ctx
);
72 err
= portfwdmgr_connect(
73 s
->portfwdmgr
, &ch
, realpf
->dhost
, realpf
->dport
,
74 sc
, realpf
->addressfamily
);
75 ppl_logevent("Attempting to forward remote port to %s:%d",
76 realpf
->dhost
, realpf
->dport
);
78 ppl_logevent("Port open failed: %s", err
);
80 CHANOPEN_RETURN_FAILURE(
81 SSH2_OPEN_CONNECT_FAILED
,
82 ("Port open failed"));
85 ppl_logevent("Forwarded port opened successfully");
86 CHANOPEN_RETURN_SUCCESS(ch
);
89 static ChanopenResult
chan_open_auth_agent(
90 struct ssh2_connection_state
*s
, SshChannel
*sc
)
92 if (!ssh_agent_forwarding_permitted(&s
->cl
)) {
93 CHANOPEN_RETURN_FAILURE(
94 SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
,
95 ("Agent forwarding is not enabled"));
99 * If possible, make a stream-oriented connection to the agent and
100 * set up an ordinary port-forwarding type channel over it.
103 Channel
*ch
= portfwd_raw_new(&s
->cl
, &plug
, true);
104 Socket
*skt
= agent_connect(plug
);
106 if (!sk_socket_error(skt
)) {
107 portfwd_raw_setup(ch
, skt
, sc
);
108 CHANOPEN_RETURN_SUCCESS(ch
);
110 portfwd_raw_free(ch
);
112 * Otherwise, fall back to the old-fashioned system of parsing the
113 * forwarded data stream ourselves for message boundaries, and
114 * passing each individual message to the one-off agent_query().
116 CHANOPEN_RETURN_SUCCESS(agentf_new(sc
));
120 ChanopenResult
ssh2_connection_parse_channel_open(
121 struct ssh2_connection_state
*s
, ptrlen type
,
122 PktIn
*pktin
, SshChannel
*sc
)
124 if (ptrlen_eq_string(type
, "x11")) {
125 ptrlen peeraddr
= get_string(pktin
);
126 int peerport
= get_uint32(pktin
);
128 return chan_open_x11(s
, sc
, peeraddr
, peerport
);
129 } else if (ptrlen_eq_string(type
, "forwarded-tcpip")) {
130 ptrlen fwdaddr
= get_string(pktin
);
131 int fwdport
= toint(get_uint32(pktin
));
132 ptrlen peeraddr
= get_string(pktin
);
133 int peerport
= toint(get_uint32(pktin
));
135 return chan_open_forwarded_tcpip(
136 s
, sc
, fwdaddr
, fwdport
, peeraddr
, peerport
);
137 } else if (ptrlen_eq_string(type
, "auth-agent@openssh.com")) {
138 return chan_open_auth_agent(s
, sc
);
140 CHANOPEN_RETURN_FAILURE(
141 SSH2_OPEN_UNKNOWN_CHANNEL_TYPE
,
142 ("Unsupported channel type requested"));
146 bool ssh2_connection_parse_global_request(
147 struct ssh2_connection_state
*s
, ptrlen type
, PktIn
*pktin
)
150 * We don't know of any global requests that an SSH client needs
156 PktOut
*ssh2_portfwd_chanopen(
157 struct ssh2_connection_state
*s
, struct ssh2_channel
*c
,
158 const char *hostname
, int port
,
159 const char *description
, const SocketPeerInfo
*peerinfo
)
161 PacketProtocolLayer
*ppl
= &s
->ppl
; /* for ppl_logevent */
165 * In client mode, this function is called by portfwdmgr in
166 * response to PortListeners that were set up in
167 * portfwdmgr_config, which means that the hostname and port
168 * parameters will indicate the host we want to tell the server to
172 ppl_logevent("Opening connection to %s:%d for %s",
173 hostname
, port
, description
);
175 pktout
= ssh2_chanopen_init(c
, "direct-tcpip");
177 char *trimmed_host
= host_strduptrim(hostname
);
178 put_stringz(pktout
, trimmed_host
);
181 put_uint32(pktout
, port
);
184 * We make up values for the originator data; partly it's too much
185 * hassle to keep track, and partly I'm not convinced the server
186 * should be told details like that about my local network
187 * configuration. The "originator IP address" is syntactically a
188 * numeric IP address, and some servers (e.g., Tectia) get upset
189 * if it doesn't match this syntax.
191 put_stringz(pktout
, "0.0.0.0");
192 put_uint32(pktout
, 0);
197 static int ssh2_rportfwd_cmp(void *av
, void *bv
)
199 struct ssh_rportfwd
*a
= (struct ssh_rportfwd
*) av
;
200 struct ssh_rportfwd
*b
= (struct ssh_rportfwd
*) bv
;
202 if ( (i
= strcmp(a
->shost
, b
->shost
)) != 0)
203 return i
< 0 ? -1 : +1;
204 if (a
->sport
> b
->sport
)
206 if (a
->sport
< b
->sport
)
211 static void ssh2_rportfwd_globreq_response(struct ssh2_connection_state
*s
,
212 PktIn
*pktin
, void *ctx
)
214 PacketProtocolLayer
*ppl
= &s
->ppl
; /* for ppl_logevent */
215 struct ssh_rportfwd
*rpf
= (struct ssh_rportfwd
*)ctx
;
217 if (pktin
->type
== SSH2_MSG_REQUEST_SUCCESS
) {
218 ppl_logevent("Remote port forwarding from %s enabled",
219 rpf
->log_description
);
221 ppl_logevent("Remote port forwarding from %s refused",
222 rpf
->log_description
);
224 struct ssh_rportfwd
*realpf
= del234(s
->rportfwds
, rpf
);
225 assert(realpf
== rpf
);
226 portfwdmgr_close(s
->portfwdmgr
, rpf
->pfr
);
231 struct ssh_rportfwd
*ssh2_rportfwd_alloc(
233 const char *shost
, int sport
, const char *dhost
, int dport
,
234 int addressfamily
, const char *log_description
, PortFwdRecord
*pfr
,
235 ssh_sharing_connstate
*share_ctx
)
237 struct ssh2_connection_state
*s
=
238 container_of(cl
, struct ssh2_connection_state
, cl
);
239 struct ssh_rportfwd
*rpf
= snew(struct ssh_rportfwd
);
242 s
->rportfwds
= newtree234(ssh2_rportfwd_cmp
);
244 rpf
->shost
= dupstr(shost
);
246 rpf
->dhost
= dupstr(dhost
);
248 rpf
->addressfamily
= addressfamily
;
249 rpf
->log_description
= dupstr(log_description
);
251 rpf
->share_ctx
= share_ctx
;
253 if (add234(s
->rportfwds
, rpf
) != rpf
) {
258 if (!rpf
->share_ctx
) {
259 PktOut
*pktout
= ssh_bpp_new_pktout(
260 s
->ppl
.bpp
, SSH2_MSG_GLOBAL_REQUEST
);
261 put_stringz(pktout
, "tcpip-forward");
262 put_bool(pktout
, true); /* want reply */
263 put_stringz(pktout
, rpf
->shost
);
264 put_uint32(pktout
, rpf
->sport
);
265 pq_push(s
->ppl
.out_pq
, pktout
);
267 ssh2_queue_global_request_handler(
268 s
, ssh2_rportfwd_globreq_response
, rpf
);
274 void ssh2_rportfwd_remove(ConnectionLayer
*cl
, struct ssh_rportfwd
*rpf
)
276 struct ssh2_connection_state
*s
=
277 container_of(cl
, struct ssh2_connection_state
, cl
);
279 if (rpf
->share_ctx
) {
281 * We don't manufacture a cancel-tcpip-forward message for
282 * remote port forwardings being removed on behalf of a
283 * downstream; we just pass through the one the downstream
287 PktOut
*pktout
= ssh_bpp_new_pktout(
288 s
->ppl
.bpp
, SSH2_MSG_GLOBAL_REQUEST
);
289 put_stringz(pktout
, "cancel-tcpip-forward");
290 put_bool(pktout
, false); /* _don't_ want reply */
291 put_stringz(pktout
, rpf
->shost
);
292 put_uint32(pktout
, rpf
->sport
);
293 pq_push(s
->ppl
.out_pq
, pktout
);
296 assert(s
->rportfwds
);
297 struct ssh_rportfwd
*realpf
= del234(s
->rportfwds
, rpf
);
298 assert(realpf
== rpf
);
302 SshChannel
*ssh2_session_open(ConnectionLayer
*cl
, Channel
*chan
)
304 struct ssh2_connection_state
*s
=
305 container_of(cl
, struct ssh2_connection_state
, cl
);
306 PacketProtocolLayer
*ppl
= &s
->ppl
; /* for ppl_logevent */
307 struct ssh2_channel
*c
= snew(struct ssh2_channel
);
311 ssh2_channel_init(c
);
315 ppl_logevent("Opening main session channel");
317 pktout
= ssh2_chanopen_init(c
, "session");
318 pq_push(s
->ppl
.out_pq
, pktout
);
323 SshChannel
*ssh2_serverside_x11_open(
324 ConnectionLayer
*cl
, Channel
*chan
, const SocketPeerInfo
*pi
)
326 unreachable("Should never be called in the client");
329 SshChannel
*ssh2_serverside_agent_open(ConnectionLayer
*cl
, Channel
*chan
)
331 unreachable("Should never be called in the client");
334 static void ssh2_channel_response(
335 struct ssh2_channel
*c
, PktIn
*pkt
, void *ctx
)
337 /* If pkt==NULL (because this handler has been called in response
338 * to CHANNEL_CLOSE arriving while the request was still
339 * outstanding), we treat that the same as CHANNEL_FAILURE. */
340 chan_request_response(c
->chan
,
341 pkt
&& pkt
->type
== SSH2_MSG_CHANNEL_SUCCESS
);
344 void ssh2channel_start_shell(SshChannel
*sc
, bool want_reply
)
346 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
347 struct ssh2_connection_state
*s
= c
->connlayer
;
349 PktOut
*pktout
= ssh2_chanreq_init(
350 c
, "shell", want_reply
? ssh2_channel_response
: NULL
, NULL
);
351 pq_push(s
->ppl
.out_pq
, pktout
);
354 void ssh2channel_start_command(
355 SshChannel
*sc
, bool want_reply
, const char *command
)
357 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
358 struct ssh2_connection_state
*s
= c
->connlayer
;
360 PktOut
*pktout
= ssh2_chanreq_init(
361 c
, "exec", want_reply
? ssh2_channel_response
: NULL
, NULL
);
362 put_stringz(pktout
, command
);
363 pq_push(s
->ppl
.out_pq
, pktout
);
366 bool ssh2channel_start_subsystem(
367 SshChannel
*sc
, bool want_reply
, const char *subsystem
)
369 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
370 struct ssh2_connection_state
*s
= c
->connlayer
;
372 PktOut
*pktout
= ssh2_chanreq_init(
373 c
, "subsystem", want_reply
? ssh2_channel_response
: NULL
, NULL
);
374 put_stringz(pktout
, subsystem
);
375 pq_push(s
->ppl
.out_pq
, pktout
);
380 void ssh2channel_send_exit_status(SshChannel
*sc
, int status
)
382 unreachable("Should never be called in the client");
385 void ssh2channel_send_exit_signal(
386 SshChannel
*sc
, ptrlen signame
, bool core_dumped
, ptrlen msg
)
388 unreachable("Should never be called in the client");
391 void ssh2channel_send_exit_signal_numeric(
392 SshChannel
*sc
, int signum
, bool core_dumped
, ptrlen msg
)
394 unreachable("Should never be called in the client");
397 void ssh2channel_request_x11_forwarding(
398 SshChannel
*sc
, bool want_reply
, const char *authproto
,
399 const char *authdata
, int screen_number
, bool oneshot
)
401 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
402 struct ssh2_connection_state
*s
= c
->connlayer
;
404 PktOut
*pktout
= ssh2_chanreq_init(
405 c
, "x11-req", want_reply
? ssh2_channel_response
: NULL
, NULL
);
406 put_bool(pktout
, oneshot
);
407 put_stringz(pktout
, authproto
);
408 put_stringz(pktout
, authdata
);
409 put_uint32(pktout
, screen_number
);
410 pq_push(s
->ppl
.out_pq
, pktout
);
413 void ssh2channel_request_agent_forwarding(SshChannel
*sc
, bool want_reply
)
415 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
416 struct ssh2_connection_state
*s
= c
->connlayer
;
418 PktOut
*pktout
= ssh2_chanreq_init(
419 c
, "auth-agent-req@openssh.com",
420 want_reply
? ssh2_channel_response
: NULL
, NULL
);
421 pq_push(s
->ppl
.out_pq
, pktout
);
424 void ssh2channel_request_pty(
425 SshChannel
*sc
, bool want_reply
, Conf
*conf
, int w
, int h
)
427 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
428 struct ssh2_connection_state
*s
= c
->connlayer
;
431 PktOut
*pktout
= ssh2_chanreq_init(
432 c
, "pty-req", want_reply
? ssh2_channel_response
: NULL
, NULL
);
433 put_stringz(pktout
, conf_get_str(conf
, CONF_termtype
));
434 put_uint32(pktout
, w
);
435 put_uint32(pktout
, h
);
436 put_uint32(pktout
, 0); /* pixel width */
437 put_uint32(pktout
, 0); /* pixel height */
438 modebuf
= strbuf_new();
439 write_ttymodes_to_packet(
440 BinarySink_UPCAST(modebuf
), 2,
441 get_ttymodes_from_conf(s
->ppl
.seat
, conf
));
442 put_stringsb(pktout
, modebuf
);
443 pq_push(s
->ppl
.out_pq
, pktout
);
446 bool ssh2channel_send_env_var(
447 SshChannel
*sc
, bool want_reply
, const char *var
, const char *value
)
449 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
450 struct ssh2_connection_state
*s
= c
->connlayer
;
452 PktOut
*pktout
= ssh2_chanreq_init(
453 c
, "env", want_reply
? ssh2_channel_response
: NULL
, NULL
);
454 put_stringz(pktout
, var
);
455 put_stringz(pktout
, value
);
456 pq_push(s
->ppl
.out_pq
, pktout
);
461 bool ssh2channel_send_serial_break(SshChannel
*sc
, bool want_reply
, int length
)
463 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
464 struct ssh2_connection_state
*s
= c
->connlayer
;
466 PktOut
*pktout
= ssh2_chanreq_init(
467 c
, "break", want_reply
? ssh2_channel_response
: NULL
, NULL
);
468 put_uint32(pktout
, length
);
469 pq_push(s
->ppl
.out_pq
, pktout
);
474 bool ssh2channel_send_signal(
475 SshChannel
*sc
, bool want_reply
, const char *signame
)
477 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
478 struct ssh2_connection_state
*s
= c
->connlayer
;
480 PktOut
*pktout
= ssh2_chanreq_init(
481 c
, "signal", want_reply
? ssh2_channel_response
: NULL
, NULL
);
482 put_stringz(pktout
, signame
);
483 pq_push(s
->ppl
.out_pq
, pktout
);
488 void ssh2channel_send_terminal_size_change(SshChannel
*sc
, int w
, int h
)
490 struct ssh2_channel
*c
= container_of(sc
, struct ssh2_channel
, sc
);
491 struct ssh2_connection_state
*s
= c
->connlayer
;
493 PktOut
*pktout
= ssh2_chanreq_init(c
, "window-change", NULL
, NULL
);
494 put_uint32(pktout
, w
);
495 put_uint32(pktout
, h
);
496 put_uint32(pktout
, 0); /* pixel width */
497 put_uint32(pktout
, 0); /* pixel height */
498 pq_push(s
->ppl
.out_pq
, pktout
);
501 bool ssh2_connection_need_antispoof_prompt(struct ssh2_connection_state
*s
)
503 bool success
= seat_set_trust_status(s
->ppl
.seat
, false);
504 return (!success
&& !ssh_is_bare(s
->ppl
.ssh
));