summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2005-05-25 11:01:01 +0000
committerColin Watson <cjwatson@debian.org>2005-05-25 11:01:01 +0000
commite88de75a1a236779a10e8ccbcc51d25308be8840 (patch)
tree7495477a2a7d0cac17a9fcded020b6ea816182ef /ssh.c
parent30a0f9443782cd9d7308acd09430bf586186aa55 (diff)
parent5d05471f6657646d1d6500c7c43134462c407ee6 (diff)
Merge 4.0p1 to the trunk.
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c196
1 files changed, 133 insertions, 63 deletions
diff --git a/ssh.c b/ssh.c
index 0a2f8f711..1b03543c3 100644
--- a/ssh.c
+++ b/ssh.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: ssh.c,v 1.224 2004/07/28 09:40:29 markus Exp $"); 43RCSID("$OpenBSD: ssh.c,v 1.233 2005/03/01 17:22:06 jmc Exp $");
44 44
45#include <openssl/evp.h> 45#include <openssl/evp.h>
46#include <openssl/err.h> 46#include <openssl/err.h>
@@ -144,6 +144,9 @@ pid_t proxy_command_pid = 0;
144/* fd to control socket */ 144/* fd to control socket */
145int control_fd = -1; 145int control_fd = -1;
146 146
147/* Multiplexing control command */
148static u_int mux_command = SSHMUX_COMMAND_OPEN;
149
147/* Only used in control client mode */ 150/* Only used in control client mode */
148volatile sig_atomic_t control_client_terminate = 0; 151volatile sig_atomic_t control_client_terminate = 0;
149u_int control_server_pid = 0; 152u_int control_server_pid = 0;
@@ -154,10 +157,12 @@ static void
154usage(void) 157usage(void)
155{ 158{
156 fprintf(stderr, 159 fprintf(stderr,
157"usage: ssh [-1246AaCfghkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" 160"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
158" [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n" 161" [-D port] [-e escape_char] [-F configfile]\n"
159" [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n" 162" [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
160" [-p port] [-R port:host:hostport] [-S ctl] [user@]hostname [command]\n" 163" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
164" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
165" [user@]hostname [command]\n"
161 ); 166 );
162 exit(1); 167 exit(1);
163} 168}
@@ -174,14 +179,13 @@ int
174main(int ac, char **av) 179main(int ac, char **av)
175{ 180{
176 int i, opt, exit_status; 181 int i, opt, exit_status;
177 u_short fwd_port, fwd_host_port;
178 char sfwd_port[6], sfwd_host_port[6];
179 char *p, *cp, *line, buf[256]; 182 char *p, *cp, *line, buf[256];
180 struct stat st; 183 struct stat st;
181 struct passwd *pw; 184 struct passwd *pw;
182 int dummy; 185 int dummy;
183 extern int optind, optreset; 186 extern int optind, optreset;
184 extern char *optarg; 187 extern char *optarg;
188 Forward fwd;
185 189
186 __progname = ssh_get_progname(av[0]); 190 __progname = ssh_get_progname(av[0]);
187 init_rng(); 191 init_rng();
@@ -236,7 +240,7 @@ main(int ac, char **av)
236 240
237again: 241again:
238 while ((opt = getopt(ac, av, 242 while ((opt = getopt(ac, av,
239 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNPR:S:TVXY")) != -1) { 243 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
240 switch (opt) { 244 switch (opt) {
241 case '1': 245 case '1':
242 options.protocol = SSH_PROTO_1; 246 options.protocol = SSH_PROTO_1;
@@ -270,6 +274,14 @@ again:
270 case 'g': 274 case 'g':
271 options.gateway_ports = 1; 275 options.gateway_ports = 1;
272 break; 276 break;
277 case 'O':
278 if (strcmp(optarg, "check") == 0)
279 mux_command = SSHMUX_COMMAND_ALIVE_CHECK;
280 else if (strcmp(optarg, "exit") == 0)
281 mux_command = SSHMUX_COMMAND_TERMINATE;
282 else
283 fatal("Invalid multiplex command.");
284 break;
273 case 'P': /* deprecated */ 285 case 'P': /* deprecated */
274 options.use_privileged_port = 0; 286 options.use_privileged_port = 0;
275 break; 287 break;
@@ -285,7 +297,8 @@ again:
285 case 'i': 297 case 'i':
286 if (stat(optarg, &st) < 0) { 298 if (stat(optarg, &st) < 0) {
287 fprintf(stderr, "Warning: Identity file %s " 299 fprintf(stderr, "Warning: Identity file %s "
288 "does not exist.\n", optarg); 300 "not accessible: %s.\n", optarg,
301 strerror(errno));
289 break; 302 break;
290 } 303 }
291 if (options.num_identity_files >= 304 if (options.num_identity_files >=
@@ -316,10 +329,10 @@ again:
316 options.log_level++; 329 options.log_level++;
317 break; 330 break;
318 } 331 }
319 /* fallthrough */ 332 /* FALLTHROUGH */
320 case 'V': 333 case 'V':
321 fprintf(stderr, "%s, %s\n", 334 fprintf(stderr, "%s, %s\n",
322 SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); 335 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
323 if (opt == 'V') 336 if (opt == 'V')
324 exit(0); 337 exit(0);
325 break; 338 break;
@@ -393,39 +406,51 @@ again:
393 break; 406 break;
394 407
395 case 'L': 408 case 'L':
396 case 'R': 409 if (parse_forward(&fwd, optarg))
397 if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]", 410 add_local_forward(&options, &fwd);
398 sfwd_port, buf, sfwd_host_port) != 3 && 411 else {
399 sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
400 sfwd_port, buf, sfwd_host_port) != 3) {
401 fprintf(stderr, 412 fprintf(stderr,
402 "Bad forwarding specification '%s'\n", 413 "Bad local forwarding specification '%s'\n",
403 optarg); 414 optarg);
404 usage(); 415 exit(1);
405 /* NOTREACHED */
406 } 416 }
407 if ((fwd_port = a2port(sfwd_port)) == 0 || 417 break;
408 (fwd_host_port = a2port(sfwd_host_port)) == 0) { 418
419 case 'R':
420 if (parse_forward(&fwd, optarg)) {
421 add_remote_forward(&options, &fwd);
422 } else {
409 fprintf(stderr, 423 fprintf(stderr,
410 "Bad forwarding port(s) '%s'\n", optarg); 424 "Bad remote forwarding specification "
425 "'%s'\n", optarg);
411 exit(1); 426 exit(1);
412 } 427 }
413 if (opt == 'L')
414 add_local_forward(&options, fwd_port, buf,
415 fwd_host_port);
416 else if (opt == 'R')
417 add_remote_forward(&options, fwd_port, buf,
418 fwd_host_port);
419 break; 428 break;
420 429
421 case 'D': 430 case 'D':
422 fwd_port = a2port(optarg); 431 cp = p = xstrdup(optarg);
423 if (fwd_port == 0) { 432 memset(&fwd, '\0', sizeof(fwd));
433 fwd.connect_host = "socks";
434 if ((fwd.listen_host = hpdelim(&cp)) == NULL) {
435 fprintf(stderr, "Bad dynamic forwarding "
436 "specification '%.100s'\n", optarg);
437 exit(1);
438 }
439 if (cp != NULL) {
440 fwd.listen_port = a2port(cp);
441 fwd.listen_host = cleanhostname(fwd.listen_host);
442 } else {
443 fwd.listen_port = a2port(fwd.listen_host);
444 fwd.listen_host = "";
445 }
446
447 if (fwd.listen_port == 0) {
424 fprintf(stderr, "Bad dynamic port '%s'\n", 448 fprintf(stderr, "Bad dynamic port '%s'\n",
425 optarg); 449 optarg);
426 exit(1); 450 exit(1);
427 } 451 }
428 add_local_forward(&options, fwd_port, "socks", 0); 452 add_local_forward(&options, &fwd);
453 xfree(p);
429 break; 454 break;
430 455
431 case 'C': 456 case 'C':
@@ -834,14 +859,19 @@ ssh_init_forwarding(void)
834 859
835 /* Initiate local TCP/IP port forwardings. */ 860 /* Initiate local TCP/IP port forwardings. */
836 for (i = 0; i < options.num_local_forwards; i++) { 861 for (i = 0; i < options.num_local_forwards; i++) {
837 debug("Connections to local port %d forwarded to remote address %.200s:%d", 862 debug("Local connections to %.200s:%d forwarded to remote "
838 options.local_forwards[i].port, 863 "address %.200s:%d",
839 options.local_forwards[i].host, 864 (options.local_forwards[i].listen_host == NULL) ?
840 options.local_forwards[i].host_port); 865 (options.gateway_ports ? "*" : "LOCALHOST") :
866 options.local_forwards[i].listen_host,
867 options.local_forwards[i].listen_port,
868 options.local_forwards[i].connect_host,
869 options.local_forwards[i].connect_port);
841 success += channel_setup_local_fwd_listener( 870 success += channel_setup_local_fwd_listener(
842 options.local_forwards[i].port, 871 options.local_forwards[i].listen_host,
843 options.local_forwards[i].host, 872 options.local_forwards[i].listen_port,
844 options.local_forwards[i].host_port, 873 options.local_forwards[i].connect_host,
874 options.local_forwards[i].connect_port,
845 options.gateway_ports); 875 options.gateway_ports);
846 } 876 }
847 if (i > 0 && success == 0) 877 if (i > 0 && success == 0)
@@ -849,14 +879,17 @@ ssh_init_forwarding(void)
849 879
850 /* Initiate remote TCP/IP port forwardings. */ 880 /* Initiate remote TCP/IP port forwardings. */
851 for (i = 0; i < options.num_remote_forwards; i++) { 881 for (i = 0; i < options.num_remote_forwards; i++) {
852 debug("Connections to remote port %d forwarded to local address %.200s:%d", 882 debug("Remote connections from %.200s:%d forwarded to "
853 options.remote_forwards[i].port, 883 "local address %.200s:%d",
854 options.remote_forwards[i].host, 884 options.remote_forwards[i].listen_host,
855 options.remote_forwards[i].host_port); 885 options.remote_forwards[i].listen_port,
886 options.remote_forwards[i].connect_host,
887 options.remote_forwards[i].connect_port);
856 channel_request_remote_forwarding( 888 channel_request_remote_forwarding(
857 options.remote_forwards[i].port, 889 options.remote_forwards[i].listen_host,
858 options.remote_forwards[i].host, 890 options.remote_forwards[i].listen_port,
859 options.remote_forwards[i].host_port); 891 options.remote_forwards[i].connect_host,
892 options.remote_forwards[i].connect_port);
860 } 893 }
861} 894}
862 895
@@ -1032,12 +1065,12 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1032 return; 1065 return;
1033 debug("remote forward %s for: listen %d, connect %s:%d", 1066 debug("remote forward %s for: listen %d, connect %s:%d",
1034 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1067 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1035 options.remote_forwards[i].port, 1068 options.remote_forwards[i].listen_port,
1036 options.remote_forwards[i].host, 1069 options.remote_forwards[i].connect_host,
1037 options.remote_forwards[i].host_port); 1070 options.remote_forwards[i].connect_port);
1038 if (type == SSH2_MSG_REQUEST_FAILURE) 1071 if (type == SSH2_MSG_REQUEST_FAILURE)
1039 logit("Warning: remote port forwarding failed for listen port %d", 1072 logit("Warning: remote port forwarding failed for listen "
1040 options.remote_forwards[i].port); 1073 "port %d", options.remote_forwards[i].listen_port);
1041} 1074}
1042 1075
1043static void 1076static void
@@ -1254,10 +1287,20 @@ static void
1254control_client(const char *path) 1287control_client(const char *path)
1255{ 1288{
1256 struct sockaddr_un addr; 1289 struct sockaddr_un addr;
1257 int i, r, sock, exitval, num_env, addr_len; 1290 int i, r, fd, sock, exitval, num_env, addr_len;
1258 Buffer m; 1291 Buffer m;
1259 char *cp; 1292 char *term;
1260 extern char **environ; 1293 extern char **environ;
1294 u_int flags;
1295
1296 if (stdin_null_flag) {
1297 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
1298 fatal("open(/dev/null): %s", strerror(errno));
1299 if (dup2(fd, STDIN_FILENO) == -1)
1300 fatal("dup2: %s", strerror(errno));
1301 if (fd > STDERR_FILENO)
1302 close(fd);
1303 }
1261 1304
1262 memset(&addr, '\0', sizeof(addr)); 1305 memset(&addr, '\0', sizeof(addr));
1263 addr.sun_family = AF_UNIX; 1306 addr.sun_family = AF_UNIX;
@@ -1274,26 +1317,52 @@ control_client(const char *path)
1274 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) 1317 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1)
1275 fatal("Couldn't connect to %s: %s", path, strerror(errno)); 1318 fatal("Couldn't connect to %s: %s", path, strerror(errno));
1276 1319
1277 if ((cp = getenv("TERM")) == NULL) 1320 if ((term = getenv("TERM")) == NULL)
1278 cp = ""; 1321 term = "";
1322
1323 flags = 0;
1324 if (tty_flag)
1325 flags |= SSHMUX_FLAG_TTY;
1326 if (subsystem_flag)
1327 flags |= SSHMUX_FLAG_SUBSYS;
1279 1328
1280 buffer_init(&m); 1329 buffer_init(&m);
1281 1330
1282 /* Get PID of controlee */ 1331 /* Send our command to server */
1332 buffer_put_int(&m, mux_command);
1333 buffer_put_int(&m, flags);
1334 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1335 fatal("%s: msg_send", __func__);
1336 buffer_clear(&m);
1337
1338 /* Get authorisation status and PID of controlee */
1283 if (ssh_msg_recv(sock, &m) == -1) 1339 if (ssh_msg_recv(sock, &m) == -1)
1284 fatal("%s: msg_recv", __func__); 1340 fatal("%s: msg_recv", __func__);
1285 if (buffer_get_char(&m) != 0) 1341 if (buffer_get_char(&m) != 1)
1286 fatal("%s: wrong version", __func__); 1342 fatal("%s: wrong version", __func__);
1287 /* Connection allowed? */
1288 if (buffer_get_int(&m) != 1) 1343 if (buffer_get_int(&m) != 1)
1289 fatal("Connection to master denied"); 1344 fatal("Connection to master denied");
1290 control_server_pid = buffer_get_int(&m); 1345 control_server_pid = buffer_get_int(&m);
1291 1346
1292 buffer_clear(&m); 1347 buffer_clear(&m);
1293 buffer_put_int(&m, tty_flag);
1294 buffer_put_int(&m, subsystem_flag);
1295 buffer_put_cstring(&m, cp);
1296 1348
1349 switch (mux_command) {
1350 case SSHMUX_COMMAND_ALIVE_CHECK:
1351 fprintf(stderr, "Master running (pid=%d)\r\n",
1352 control_server_pid);
1353 exit(0);
1354 case SSHMUX_COMMAND_TERMINATE:
1355 fprintf(stderr, "Exit request sent.\r\n");
1356 exit(0);
1357 case SSHMUX_COMMAND_OPEN:
1358 /* continue below */
1359 break;
1360 default:
1361 fatal("silly mux_command %d", mux_command);
1362 }
1363
1364 /* SSHMUX_COMMAND_OPEN */
1365 buffer_put_cstring(&m, term);
1297 buffer_append(&command, "\0", 1); 1366 buffer_append(&command, "\0", 1);
1298 buffer_put_cstring(&m, buffer_ptr(&command)); 1367 buffer_put_cstring(&m, buffer_ptr(&command));
1299 1368
@@ -1315,7 +1384,7 @@ control_client(const char *path)
1315 } 1384 }
1316 } 1385 }
1317 1386
1318 if (ssh_msg_send(sock, /* version */0, &m) == -1) 1387 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1319 fatal("%s: msg_send", __func__); 1388 fatal("%s: msg_send", __func__);
1320 1389
1321 mm_send_fd(sock, STDIN_FILENO); 1390 mm_send_fd(sock, STDIN_FILENO);
@@ -1326,10 +1395,11 @@ control_client(const char *path)
1326 buffer_clear(&m); 1395 buffer_clear(&m);
1327 if (ssh_msg_recv(sock, &m) == -1) 1396 if (ssh_msg_recv(sock, &m) == -1)
1328 fatal("%s: msg_recv", __func__); 1397 fatal("%s: msg_recv", __func__);
1329 if (buffer_get_char(&m) != 0) 1398 if (buffer_get_char(&m) != 1)
1330 fatal("%s: master returned error", __func__); 1399 fatal("%s: wrong version", __func__);
1331 buffer_free(&m); 1400 buffer_free(&m);
1332 1401
1402 signal(SIGHUP, control_client_sighandler);
1333 signal(SIGINT, control_client_sighandler); 1403 signal(SIGINT, control_client_sighandler);
1334 signal(SIGTERM, control_client_sighandler); 1404 signal(SIGTERM, control_client_sighandler);
1335 signal(SIGWINCH, control_client_sigrelay); 1405 signal(SIGWINCH, control_client_sigrelay);