diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 95 |
1 files changed, 50 insertions, 45 deletions
@@ -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 | |||
185 | usage(void) | 185 | usage(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 | ||
858 | static void | 873 | static 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 | |||
1307 | control_client(const char *path) | 1297 | control_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 | } |