diff options
author | Colin Watson <cjwatson@debian.org> | 2005-09-14 12:45:47 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2005-09-14 12:45:47 +0000 |
commit | 9b71add4cecf753c45f5fbd6ff0913bc95b3e95d (patch) | |
tree | d4ea8fdb30c7949c6433f5277c39548ea579d4dc /clientloop.c | |
parent | ed07bcbea56007ab5b218ddf3aa6a7d4e21966e0 (diff) | |
parent | 16704d57999d987fb8d9ba53379841a79f016d67 (diff) |
Merge 4.2p1 to the trunk.
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 153 |
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" |
62 | RCSID("$OpenBSD: clientloop.c,v 1.136 2005/03/10 22:01:05 deraadt Exp $"); | 62 | RCSID("$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; | |||
140 | struct confirm_ctx { | 140 | struct 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" | ||
214 | void | ||
215 | client_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 | |||
533 | client_extra_session2_setup(int id, void *arg) | 638 | client_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 | ||