summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2005-09-14 12:45:47 +0000
committerColin Watson <cjwatson@debian.org>2005-09-14 12:45:47 +0000
commit9b71add4cecf753c45f5fbd6ff0913bc95b3e95d (patch)
treed4ea8fdb30c7949c6433f5277c39548ea579d4dc /clientloop.c
parented07bcbea56007ab5b218ddf3aa6a7d4e21966e0 (diff)
parent16704d57999d987fb8d9ba53379841a79f016d67 (diff)
Merge 4.2p1 to the trunk.
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c153
1 files changed, 142 insertions, 11 deletions
diff --git a/clientloop.c b/clientloop.c
index d36d816de..c9176c0d7 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.136 2005/03/10 22:01:05 deraadt 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
@@ -533,6 +638,7 @@ static void
533client_extra_session2_setup(int id, void *arg) 638client_extra_session2_setup(int id, void *arg)
534{ 639{
535 struct confirm_ctx *cctx = arg; 640 struct confirm_ctx *cctx = arg;
641 const char *display;
536 Channel *c; 642 Channel *c;
537 int i; 643 int i;
538 644
@@ -541,6 +647,24 @@ client_extra_session2_setup(int id, void *arg)
541 if ((c = channel_lookup(id)) == NULL) 647 if ((c = channel_lookup(id)) == NULL)
542 fatal("%s: no channel for id %d", __func__, id); 648 fatal("%s: no channel for id %d", __func__, id);
543 649
650 display = getenv("DISPLAY");
651 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
652 char *proto, *data;
653 /* Get reasonable local authentication information. */
654 client_x11_get_proto(display, options.xauth_location,
655 options.forward_x11_trusted, &proto, &data);
656 /* Request forwarding with authentication spoofing. */
657 debug("Requesting X11 forwarding with authentication spoofing.");
658 x11_request_forwarding_with_spoofing(id, display, proto, data);
659 /* XXX wait for reply */
660 }
661
662 if (cctx->want_agent_fwd && options.forward_agent) {
663 debug("Requesting authentication agent forwarding.");
664 channel_request_start(id, "auth-agent-req@openssh.com", 0);
665 packet_send();
666 }
667
544 client_session2_setup(id, cctx->want_tty, cctx->want_subsys, 668 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
545 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, 669 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
546 client_subsystem_reply); 670 client_subsystem_reply);
@@ -561,12 +685,12 @@ client_process_control(fd_set * readset)
561{ 685{
562 Buffer m; 686 Buffer m;
563 Channel *c; 687 Channel *c;
564 int client_fd, new_fd[3], ver, i, allowed; 688 int client_fd, new_fd[3], ver, allowed;
565 socklen_t addrlen; 689 socklen_t addrlen;
566 struct sockaddr_storage addr; 690 struct sockaddr_storage addr;
567 struct confirm_ctx *cctx; 691 struct confirm_ctx *cctx;
568 char *cmd; 692 char *cmd;
569 u_int len, env_len, command, flags; 693 u_int i, len, env_len, command, flags;
570 uid_t euid; 694 uid_t euid;
571 gid_t egid; 695 gid_t egid;
572 696
@@ -606,7 +730,7 @@ client_process_control(fd_set * readset)
606 buffer_free(&m); 730 buffer_free(&m);
607 return; 731 return;
608 } 732 }
609 if ((ver = buffer_get_char(&m)) != 1) { 733 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
610 error("%s: wrong client version %d", __func__, ver); 734 error("%s: wrong client version %d", __func__, ver);
611 buffer_free(&m); 735 buffer_free(&m);
612 close(client_fd); 736 close(client_fd);
@@ -621,13 +745,15 @@ client_process_control(fd_set * readset)
621 745
622 switch (command) { 746 switch (command) {
623 case SSHMUX_COMMAND_OPEN: 747 case SSHMUX_COMMAND_OPEN:
624 if (options.control_master == 2) 748 if (options.control_master == SSHCTL_MASTER_ASK ||
749 options.control_master == SSHCTL_MASTER_AUTO_ASK)
625 allowed = ask_permission("Allow shared connection " 750 allowed = ask_permission("Allow shared connection "
626 "to %s? ", host); 751 "to %s? ", host);
627 /* continue below */ 752 /* continue below */
628 break; 753 break;
629 case SSHMUX_COMMAND_TERMINATE: 754 case SSHMUX_COMMAND_TERMINATE:
630 if (options.control_master == 2) 755 if (options.control_master == SSHCTL_MASTER_ASK ||
756 options.control_master == SSHCTL_MASTER_AUTO_ASK)
631 allowed = ask_permission("Terminate shared connection " 757 allowed = ask_permission("Terminate shared connection "
632 "to %s? ", host); 758 "to %s? ", host);
633 if (allowed) 759 if (allowed)
@@ -638,7 +764,7 @@ client_process_control(fd_set * readset)
638 buffer_clear(&m); 764 buffer_clear(&m);
639 buffer_put_int(&m, allowed); 765 buffer_put_int(&m, allowed);
640 buffer_put_int(&m, getpid()); 766 buffer_put_int(&m, getpid());
641 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 767 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
642 error("%s: client msg_send failed", __func__); 768 error("%s: client msg_send failed", __func__);
643 close(client_fd); 769 close(client_fd);
644 buffer_free(&m); 770 buffer_free(&m);
@@ -658,7 +784,7 @@ client_process_control(fd_set * readset)
658 buffer_clear(&m); 784 buffer_clear(&m);
659 buffer_put_int(&m, allowed); 785 buffer_put_int(&m, allowed);
660 buffer_put_int(&m, getpid()); 786 buffer_put_int(&m, getpid());
661 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 787 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
662 error("%s: client msg_send failed", __func__); 788 error("%s: client msg_send failed", __func__);
663 close(client_fd); 789 close(client_fd);
664 buffer_free(&m); 790 buffer_free(&m);
@@ -679,7 +805,7 @@ client_process_control(fd_set * readset)
679 buffer_free(&m); 805 buffer_free(&m);
680 return; 806 return;
681 } 807 }
682 if ((ver = buffer_get_char(&m)) != 1) { 808 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
683 error("%s: wrong client version %d", __func__, ver); 809 error("%s: wrong client version %d", __func__, ver);
684 buffer_free(&m); 810 buffer_free(&m);
685 close(client_fd); 811 close(client_fd);
@@ -690,6 +816,8 @@ client_process_control(fd_set * readset)
690 memset(cctx, 0, sizeof(*cctx)); 816 memset(cctx, 0, sizeof(*cctx));
691 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; 817 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
692 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; 818 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
819 cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
820 cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
693 cctx->term = buffer_get_string(&m, &len); 821 cctx->term = buffer_get_string(&m, &len);
694 822
695 cmd = buffer_get_string(&m, &len); 823 cmd = buffer_get_string(&m, &len);
@@ -723,7 +851,7 @@ client_process_control(fd_set * readset)
723 851
724 /* This roundtrip is just for synchronisation of ttymodes */ 852 /* This roundtrip is just for synchronisation of ttymodes */
725 buffer_clear(&m); 853 buffer_clear(&m);
726 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { 854 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
727 error("%s: client msg_send failed", __func__); 855 error("%s: client msg_send failed", __func__);
728 close(client_fd); 856 close(client_fd);
729 close(new_fd[0]); 857 close(new_fd[0]);
@@ -871,7 +999,10 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
871 u_char ch; 999 u_char ch;
872 char *s; 1000 char *s;
873 1001
874 for (i = 0; i < len; i++) { 1002 if (len <= 0)
1003 return (0);
1004
1005 for (i = 0; i < (u_int)len; i++) {
875 /* Get one character at a time. */ 1006 /* Get one character at a time. */
876 ch = buf[i]; 1007 ch = buf[i];
877 1008