summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c155
1 files changed, 143 insertions, 12 deletions
diff --git a/clientloop.c b/clientloop.c
index 1e250883f..47f3c7ecd 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.135 2005/03/01 10:09:52 djm Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.141 2005/07/16 01:35:24 djm Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -140,6 +140,8 @@ int session_ident = -1;
140struct confirm_ctx { 140struct confirm_ctx {
141 int want_tty; 141 int want_tty;
142 int want_subsys; 142 int want_subsys;
143 int want_x_fwd;
144 int want_agent_fwd;
143 Buffer cmd; 145 Buffer cmd;
144 char *term; 146 char *term;
145 struct termios tio; 147 struct termios tio;
@@ -208,6 +210,109 @@ get_current_time(void)
208 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; 210 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
209} 211}
210 212
213#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
214void
215client_x11_get_proto(const char *display, const char *xauth_path,
216 u_int trusted, char **_proto, char **_data)
217{
218 char cmd[1024];
219 char line[512];
220 char xdisplay[512];
221 static char proto[512], data[512];
222 FILE *f;
223 int got_data = 0, generated = 0, do_unlink = 0, i;
224 char *xauthdir, *xauthfile;
225 struct stat st;
226
227 xauthdir = xauthfile = NULL;
228 *_proto = proto;
229 *_data = data;
230 proto[0] = data[0] = '\0';
231
232 if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
233 debug("No xauth program.");
234 } else {
235 if (display == NULL) {
236 debug("x11_get_proto: DISPLAY not set");
237 return;
238 }
239 /*
240 * Handle FamilyLocal case where $DISPLAY does
241 * not match an authorization entry. For this we
242 * just try "xauth list unix:displaynum.screennum".
243 * XXX: "localhost" match to determine FamilyLocal
244 * is not perfect.
245 */
246 if (strncmp(display, "localhost:", 10) == 0) {
247 snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
248 display + 10);
249 display = xdisplay;
250 }
251 if (trusted == 0) {
252 xauthdir = xmalloc(MAXPATHLEN);
253 xauthfile = xmalloc(MAXPATHLEN);
254 strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
255 if (mkdtemp(xauthdir) != NULL) {
256 do_unlink = 1;
257 snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
258 xauthdir);
259 snprintf(cmd, sizeof(cmd),
260 "%s -f %s generate %s " SSH_X11_PROTO
261 " untrusted timeout 1200 2>" _PATH_DEVNULL,
262 xauth_path, xauthfile, display);
263 debug2("x11_get_proto: %s", cmd);
264 if (system(cmd) == 0)
265 generated = 1;
266 }
267 }
268 snprintf(cmd, sizeof(cmd),
269 "%s %s%s list %s . 2>" _PATH_DEVNULL,
270 xauth_path,
271 generated ? "-f " : "" ,
272 generated ? xauthfile : "",
273 display);
274 debug2("x11_get_proto: %s", cmd);
275 f = popen(cmd, "r");
276 if (f && fgets(line, sizeof(line), f) &&
277 sscanf(line, "%*s %511s %511s", proto, data) == 2)
278 got_data = 1;
279 if (f)
280 pclose(f);
281 }
282
283 if (do_unlink) {
284 unlink(xauthfile);
285 rmdir(xauthdir);
286 }
287 if (xauthdir)
288 xfree(xauthdir);
289 if (xauthfile)
290 xfree(xauthfile);
291
292 /*
293 * If we didn't get authentication data, just make up some
294 * data. The forwarding code will check the validity of the
295 * response anyway, and substitute this data. The X11
296 * server, however, will ignore this fake data and use
297 * whatever authentication mechanisms it was using otherwise
298 * for the local connection.
299 */
300 if (!got_data) {
301 u_int32_t rnd = 0;
302
303 logit("Warning: No xauth data; "
304 "using fake authentication data for X11 forwarding.");
305 strlcpy(proto, SSH_X11_PROTO, sizeof proto);
306 for (i = 0; i < 16; i++) {
307 if (i % 4 == 0)
308 rnd = arc4random();
309 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
310 rnd & 0xff);
311 rnd >>= 8;
312 }
313 }
314}
315
211/* 316/*
212 * This is called when the interactive is entered. This checks if there is 317 * This is called when the interactive is entered. This checks if there is
213 * an EOF coming on stdin. We must check this explicitly, as select() does 318 * an EOF coming on stdin. We must check this explicitly, as select() does
@@ -528,6 +633,7 @@ static void
528client_extra_session2_setup(int id, void *arg) 633client_extra_session2_setup(int id, void *arg)
529{ 634{
530 struct confirm_ctx *cctx = arg; 635 struct confirm_ctx *cctx = arg;
636 const char *display;
531 Channel *c; 637 Channel *c;
532 int i; 638 int i;
533 639
@@ -536,6 +642,24 @@ client_extra_session2_setup(int id, void *arg)
536 if ((c = channel_lookup(id)) == NULL) 642 if ((c = channel_lookup(id)) == NULL)
537 fatal("%s: no channel for id %d", __func__, id); 643 fatal("%s: no channel for id %d", __func__, id);
538 644
645 display = getenv("DISPLAY");
646 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
647 char *proto, *data;
648 /* Get reasonable local authentication information. */
649 client_x11_get_proto(display, options.xauth_location,
650 options.forward_x11_trusted, &proto, &data);
651 /* Request forwarding with authentication spoofing. */
652 debug("Requesting X11 forwarding with authentication spoofing.");
653 x11_request_forwarding_with_spoofing(id, display, proto, data);
654 /* XXX wait for reply */
655 }
656
657 if (cctx->want_agent_fwd && options.forward_agent) {
658 debug("Requesting authentication agent forwarding.");
659 channel_request_start(id, "auth-agent-req@openssh.com", 0);
660 packet_send();
661 }
662
539 client_session2_setup(id, cctx->want_tty, cctx->want_subsys, 663 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
540 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, 664 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
541 client_subsystem_reply); 665 client_subsystem_reply);
@@ -556,12 +680,12 @@ client_process_control(fd_set * readset)
556{ 680{
557 Buffer m; 681 Buffer m;
558 Channel *c; 682 Channel *c;
559 int client_fd, new_fd[3], ver, i, allowed; 683 int client_fd, new_fd[3], ver, allowed;
560 socklen_t addrlen; 684 socklen_t addrlen;
561 struct sockaddr_storage addr; 685 struct sockaddr_storage addr;
562 struct confirm_ctx *cctx; 686 struct confirm_ctx *cctx;
563 char *cmd; 687 char *cmd;
564 u_int len, env_len, command, flags; 688 u_int i, len, env_len, command, flags;
565 uid_t euid; 689 uid_t euid;
566 gid_t egid; 690 gid_t egid;
567 691
@@ -601,7 +725,7 @@ client_process_control(fd_set * readset)
601 buffer_free(&m); 725 buffer_free(&m);
602 return; 726 return;
603 } 727 }
604 if ((ver = buffer_get_char(&m)) != 1) { 728 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
605 error("%s: wrong client version %d", __func__, ver); 729 error("%s: wrong client version %d", __func__, ver);
606 buffer_free(&m); 730 buffer_free(&m);
607 close(client_fd); 731 close(client_fd);
@@ -616,24 +740,26 @@ client_process_control(fd_set * readset)
616 740
617 switch (command) { 741 switch (command) {
618 case SSHMUX_COMMAND_OPEN: 742 case SSHMUX_COMMAND_OPEN:
619 if (options.control_master == 2) 743 if (options.control_master == SSHCTL_MASTER_ASK ||
744 options.control_master == SSHCTL_MASTER_AUTO_ASK)
620 allowed = ask_permission("Allow shared connection " 745 allowed = ask_permission("Allow shared connection "
621 "to %s? ", host); 746 "to %s? ", host);
622 /* continue below */ 747 /* continue below */
623 break; 748 break;
624 case SSHMUX_COMMAND_TERMINATE: 749 case SSHMUX_COMMAND_TERMINATE:
625 if (options.control_master == 2) 750 if (options.control_master == SSHCTL_MASTER_ASK ||
751 options.control_master == SSHCTL_MASTER_AUTO_ASK)
626 allowed = ask_permission("Terminate shared connection " 752 allowed = ask_permission("Terminate shared connection "
627 "to %s? ", host); 753 "to %s? ", host);
628 if (allowed) 754 if (allowed)
629 quit_pending = 1; 755 quit_pending = 1;
630 /* FALLTHROUGH */ 756 /* FALLTHROUGH */
631 case SSHMUX_COMMAND_ALIVE_CHECK: 757 case SSHMUX_COMMAND_ALIVE_CHECK:
632 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */ 758 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
633 buffer_clear(&m); 759 buffer_clear(&m);
634 buffer_put_int(&m, allowed); 760 buffer_put_int(&m, allowed);
635 buffer_put_int(&m, getpid()); 761 buffer_put_int(&m, getpid());
636 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 762 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
637 error("%s: client msg_send failed", __func__); 763 error("%s: client msg_send failed", __func__);
638 close(client_fd); 764 close(client_fd);
639 buffer_free(&m); 765 buffer_free(&m);
@@ -653,7 +779,7 @@ client_process_control(fd_set * readset)
653 buffer_clear(&m); 779 buffer_clear(&m);
654 buffer_put_int(&m, allowed); 780 buffer_put_int(&m, allowed);
655 buffer_put_int(&m, getpid()); 781 buffer_put_int(&m, getpid());
656 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 782 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
657 error("%s: client msg_send failed", __func__); 783 error("%s: client msg_send failed", __func__);
658 close(client_fd); 784 close(client_fd);
659 buffer_free(&m); 785 buffer_free(&m);
@@ -674,7 +800,7 @@ client_process_control(fd_set * readset)
674 buffer_free(&m); 800 buffer_free(&m);
675 return; 801 return;
676 } 802 }
677 if ((ver = buffer_get_char(&m)) != 1) { 803 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
678 error("%s: wrong client version %d", __func__, ver); 804 error("%s: wrong client version %d", __func__, ver);
679 buffer_free(&m); 805 buffer_free(&m);
680 close(client_fd); 806 close(client_fd);
@@ -685,6 +811,8 @@ client_process_control(fd_set * readset)
685 memset(cctx, 0, sizeof(*cctx)); 811 memset(cctx, 0, sizeof(*cctx));
686 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; 812 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
687 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; 813 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
814 cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
815 cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
688 cctx->term = buffer_get_string(&m, &len); 816 cctx->term = buffer_get_string(&m, &len);
689 817
690 cmd = buffer_get_string(&m, &len); 818 cmd = buffer_get_string(&m, &len);
@@ -718,7 +846,7 @@ client_process_control(fd_set * readset)
718 846
719 /* This roundtrip is just for synchronisation of ttymodes */ 847 /* This roundtrip is just for synchronisation of ttymodes */
720 buffer_clear(&m); 848 buffer_clear(&m);
721 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 849 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
722 error("%s: client msg_send failed", __func__); 850 error("%s: client msg_send failed", __func__);
723 close(client_fd); 851 close(client_fd);
724 close(new_fd[0]); 852 close(new_fd[0]);
@@ -866,7 +994,10 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
866 u_char ch; 994 u_char ch;
867 char *s; 995 char *s;
868 996
869 for (i = 0; i < len; i++) { 997 if (len <= 0)
998 return (0);
999
1000 for (i = 0; i < (u_int)len; i++) {
870 /* Get one character at a time. */ 1001 /* Get one character at a time. */
871 ch = buf[i]; 1002 ch = buf[i];
872 1003