summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c95
1 files changed, 50 insertions, 45 deletions
diff --git a/ssh.c b/ssh.c
index cfaa1ff22..d3a7ffc9b 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.295 2007/01/03 03:01:40 stevesk Exp $ */ 1/* $OpenBSD: ssh.c,v 1.301 2007/08/07 07:32:53 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -185,7 +185,7 @@ static void
185usage(void) 185usage(void)
186{ 186{
187 fprintf(stderr, 187 fprintf(stderr,
188"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" 188"usage: ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
189" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" 189" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
190" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" 190" [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
191" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" 191" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
@@ -272,7 +272,7 @@ main(int ac, char **av)
272 272
273 again: 273 again:
274 while ((opt = getopt(ac, av, 274 while ((opt = getopt(ac, av,
275 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XY")) != -1) { 275 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) {
276 switch (opt) { 276 switch (opt) {
277 case '1': 277 case '1':
278 options.protocol = SSH_PROTO_1; 278 options.protocol = SSH_PROTO_1;
@@ -326,6 +326,10 @@ main(int ac, char **av)
326 case 'k': 326 case 'k':
327 options.gss_deleg_creds = 0; 327 options.gss_deleg_creds = 0;
328 break; 328 break;
329 case 'K':
330 options.gss_authentication = 1;
331 options.gss_deleg_creds = 1;
332 break;
329 case 'i': 333 case 'i':
330 if (stat(optarg, &st) < 0) { 334 if (stat(optarg, &st) < 0) {
331 fprintf(stderr, "Warning: Identity file %s " 335 fprintf(stderr, "Warning: Identity file %s "
@@ -853,6 +857,17 @@ ssh_init_forwarding(void)
853 "forwarding."); 857 "forwarding.");
854 } 858 }
855 } 859 }
860
861 /* Initiate tunnel forwarding. */
862 if (options.tun_open != SSH_TUNMODE_NO) {
863 if (client_request_tun_fwd(options.tun_open,
864 options.tun_local, options.tun_remote) == -1) {
865 if (options.exit_on_forward_failure)
866 fatal("Could not request tunnel forwarding.");
867 else
868 error("Could not request tunnel forwarding.");
869 }
870 }
856} 871}
857 872
858static void 873static void
@@ -1115,33 +1130,6 @@ ssh_session2_setup(int id, void *arg)
1115 packet_send(); 1130 packet_send();
1116 } 1131 }
1117 1132
1118 if (options.tun_open != SSH_TUNMODE_NO) {
1119 Channel *c;
1120 int fd;
1121
1122 debug("Requesting tun.");
1123 if ((fd = tun_open(options.tun_local,
1124 options.tun_open)) >= 0) {
1125 c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
1126 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1127 0, "tun", 1);
1128 c->datagram = 1;
1129#if defined(SSH_TUN_FILTER)
1130 if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
1131 channel_register_filter(c->self, sys_tun_infilter,
1132 sys_tun_outfilter);
1133#endif
1134 packet_start(SSH2_MSG_CHANNEL_OPEN);
1135 packet_put_cstring("tun@openssh.com");
1136 packet_put_int(c->self);
1137 packet_put_int(c->local_window_max);
1138 packet_put_int(c->local_maxpacket);
1139 packet_put_int(options.tun_open);
1140 packet_put_int(options.tun_remote);
1141 packet_send();
1142 }
1143 }
1144
1145 client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), 1133 client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
1146 NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); 1134 NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply);
1147 1135
@@ -1201,7 +1189,6 @@ ssh_session2(void)
1201 1189
1202 /* XXX should be pre-session */ 1190 /* XXX should be pre-session */
1203 ssh_init_forwarding(); 1191 ssh_init_forwarding();
1204 ssh_control_listener();
1205 1192
1206 if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) 1193 if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1207 id = ssh_session2_open(); 1194 id = ssh_session2_open();
@@ -1211,6 +1198,9 @@ ssh_session2(void)
1211 options.permit_local_command) 1198 options.permit_local_command)
1212 ssh_local_cmd(options.local_command); 1199 ssh_local_cmd(options.local_command);
1213 1200
1201 /* Start listening for multiplex clients */
1202 ssh_control_listener();
1203
1214 /* If requested, let ssh continue in the background. */ 1204 /* If requested, let ssh continue in the background. */
1215 if (fork_after_authentication_flag) 1205 if (fork_after_authentication_flag)
1216 if (daemon(1, 1) < 0) 1206 if (daemon(1, 1) < 0)
@@ -1307,7 +1297,7 @@ static void
1307control_client(const char *path) 1297control_client(const char *path)
1308{ 1298{
1309 struct sockaddr_un addr; 1299 struct sockaddr_un addr;
1310 int i, r, fd, sock, exitval, num_env, addr_len; 1300 int i, r, fd, sock, exitval[2], num_env, addr_len;
1311 Buffer m; 1301 Buffer m;
1312 char *term; 1302 char *term;
1313 extern char **environ; 1303 extern char **environ;
@@ -1456,29 +1446,44 @@ control_client(const char *path)
1456 if (tty_flag) 1446 if (tty_flag)
1457 enter_raw_mode(); 1447 enter_raw_mode();
1458 1448
1459 /* Stick around until the controlee closes the client_fd */ 1449 /*
1460 exitval = 0; 1450 * Stick around until the controlee closes the client_fd.
1461 for (;!control_client_terminate;) { 1451 * Before it does, it is expected to write this process' exit
1462 r = read(sock, &exitval, sizeof(exitval)); 1452 * value (one int). This process must read the value and wait for
1453 * the closure of the client_fd; if this one closes early, the
1454 * multiplex master will terminate early too (possibly losing data).
1455 */
1456 exitval[0] = 0;
1457 for (i = 0; !control_client_terminate && i < (int)sizeof(exitval);) {
1458 r = read(sock, (char *)exitval + i, sizeof(exitval) - i);
1463 if (r == 0) { 1459 if (r == 0) {
1464 debug2("Received EOF from master"); 1460 debug2("Received EOF from master");
1465 break; 1461 break;
1466 } 1462 }
1467 if (r > 0) 1463 if (r == -1) {
1468 debug2("Received exit status from master %d", exitval); 1464 if (errno == EINTR)
1469 if (r == -1 && errno != EINTR) 1465 continue;
1470 fatal("%s: read %s", __func__, strerror(errno)); 1466 fatal("%s: read %s", __func__, strerror(errno));
1467 }
1468 i += r;
1471 } 1469 }
1472 1470
1473 if (control_client_terminate)
1474 debug2("Exiting on signal %d", control_client_terminate);
1475
1476 close(sock); 1471 close(sock);
1477
1478 leave_raw_mode(); 1472 leave_raw_mode();
1473 if (i > (int)sizeof(int))
1474 fatal("%s: master returned too much data (%d > %lu)",
1475 __func__, i, sizeof(int));
1476 if (control_client_terminate) {
1477 debug2("Exiting on signal %d", control_client_terminate);
1478 exitval[0] = 255;
1479 } else if (i < (int)sizeof(int)) {
1480 debug2("Control master terminated unexpectedly");
1481 exitval[0] = 255;
1482 } else
1483 debug2("Received exit status from master %d", exitval[0]);
1479 1484
1480 if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) 1485 if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
1481 fprintf(stderr, "Connection to master closed.\r\n"); 1486 fprintf(stderr, "Shared connection to %s closed.\r\n", host);
1482 1487
1483 exit(exitval); 1488 exit(exitval[0]);
1484} 1489}