summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
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 1419f9874..9acec3082 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;
@@ -388,39 +401,51 @@ again:
388 break; 401 break;
389 402
390 case 'L': 403 case 'L':
391 case 'R': 404 if (parse_forward(&fwd, optarg))
392 if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]", 405 add_local_forward(&options, &fwd);
393 sfwd_port, buf, sfwd_host_port) != 3 && 406 else {
394 sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
395 sfwd_port, buf, sfwd_host_port) != 3) {
396 fprintf(stderr, 407 fprintf(stderr,
397 "Bad forwarding specification '%s'\n", 408 "Bad local forwarding specification '%s'\n",
398 optarg); 409 optarg);
399 usage(); 410 exit(1);
400 /* NOTREACHED */
401 } 411 }
402 if ((fwd_port = a2port(sfwd_port)) == 0 || 412 break;
403 (fwd_host_port = a2port(sfwd_host_port)) == 0) { 413
414 case 'R':
415 if (parse_forward(&fwd, optarg)) {
416 add_remote_forward(&options, &fwd);
417 } else {
404 fprintf(stderr, 418 fprintf(stderr,
405 "Bad forwarding port(s) '%s'\n", optarg); 419 "Bad remote forwarding specification "
420 "'%s'\n", optarg);
406 exit(1); 421 exit(1);
407 } 422 }
408 if (opt == 'L')
409 add_local_forward(&options, fwd_port, buf,
410 fwd_host_port);
411 else if (opt == 'R')
412 add_remote_forward(&options, fwd_port, buf,
413 fwd_host_port);
414 break; 423 break;
415 424
416 case 'D': 425 case 'D':
417 fwd_port = a2port(optarg); 426 cp = p = xstrdup(optarg);
418 if (fwd_port == 0) { 427 memset(&fwd, '\0', sizeof(fwd));
428 fwd.connect_host = "socks";
429 if ((fwd.listen_host = hpdelim(&cp)) == NULL) {
430 fprintf(stderr, "Bad dynamic forwarding "
431 "specification '%.100s'\n", optarg);
432 exit(1);
433 }
434 if (cp != NULL) {
435 fwd.listen_port = a2port(cp);
436 fwd.listen_host = cleanhostname(fwd.listen_host);
437 } else {
438 fwd.listen_port = a2port(fwd.listen_host);
439 fwd.listen_host = "";
440 }
441
442 if (fwd.listen_port == 0) {
419 fprintf(stderr, "Bad dynamic port '%s'\n", 443 fprintf(stderr, "Bad dynamic port '%s'\n",
420 optarg); 444 optarg);
421 exit(1); 445 exit(1);
422 } 446 }
423 add_local_forward(&options, fwd_port, "socks", 0); 447 add_local_forward(&options, &fwd);
448 xfree(p);
424 break; 449 break;
425 450
426 case 'C': 451 case 'C':
@@ -829,14 +854,19 @@ ssh_init_forwarding(void)
829 854
830 /* Initiate local TCP/IP port forwardings. */ 855 /* Initiate local TCP/IP port forwardings. */
831 for (i = 0; i < options.num_local_forwards; i++) { 856 for (i = 0; i < options.num_local_forwards; i++) {
832 debug("Connections to local port %d forwarded to remote address %.200s:%d", 857 debug("Local connections to %.200s:%d forwarded to remote "
833 options.local_forwards[i].port, 858 "address %.200s:%d",
834 options.local_forwards[i].host, 859 (options.local_forwards[i].listen_host == NULL) ?
835 options.local_forwards[i].host_port); 860 (options.gateway_ports ? "*" : "LOCALHOST") :
861 options.local_forwards[i].listen_host,
862 options.local_forwards[i].listen_port,
863 options.local_forwards[i].connect_host,
864 options.local_forwards[i].connect_port);
836 success += channel_setup_local_fwd_listener( 865 success += channel_setup_local_fwd_listener(
837 options.local_forwards[i].port, 866 options.local_forwards[i].listen_host,
838 options.local_forwards[i].host, 867 options.local_forwards[i].listen_port,
839 options.local_forwards[i].host_port, 868 options.local_forwards[i].connect_host,
869 options.local_forwards[i].connect_port,
840 options.gateway_ports); 870 options.gateway_ports);
841 } 871 }
842 if (i > 0 && success == 0) 872 if (i > 0 && success == 0)
@@ -844,14 +874,17 @@ ssh_init_forwarding(void)
844 874
845 /* Initiate remote TCP/IP port forwardings. */ 875 /* Initiate remote TCP/IP port forwardings. */
846 for (i = 0; i < options.num_remote_forwards; i++) { 876 for (i = 0; i < options.num_remote_forwards; i++) {
847 debug("Connections to remote port %d forwarded to local address %.200s:%d", 877 debug("Remote connections from %.200s:%d forwarded to "
848 options.remote_forwards[i].port, 878 "local address %.200s:%d",
849 options.remote_forwards[i].host, 879 options.remote_forwards[i].listen_host,
850 options.remote_forwards[i].host_port); 880 options.remote_forwards[i].listen_port,
881 options.remote_forwards[i].connect_host,
882 options.remote_forwards[i].connect_port);
851 channel_request_remote_forwarding( 883 channel_request_remote_forwarding(
852 options.remote_forwards[i].port, 884 options.remote_forwards[i].listen_host,
853 options.remote_forwards[i].host, 885 options.remote_forwards[i].listen_port,
854 options.remote_forwards[i].host_port); 886 options.remote_forwards[i].connect_host,
887 options.remote_forwards[i].connect_port);
855 } 888 }
856} 889}
857 890
@@ -1027,12 +1060,12 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1027 return; 1060 return;
1028 debug("remote forward %s for: listen %d, connect %s:%d", 1061 debug("remote forward %s for: listen %d, connect %s:%d",
1029 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1062 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1030 options.remote_forwards[i].port, 1063 options.remote_forwards[i].listen_port,
1031 options.remote_forwards[i].host, 1064 options.remote_forwards[i].connect_host,
1032 options.remote_forwards[i].host_port); 1065 options.remote_forwards[i].connect_port);
1033 if (type == SSH2_MSG_REQUEST_FAILURE) 1066 if (type == SSH2_MSG_REQUEST_FAILURE)
1034 logit("Warning: remote port forwarding failed for listen port %d", 1067 logit("Warning: remote port forwarding failed for listen "
1035 options.remote_forwards[i].port); 1068 "port %d", options.remote_forwards[i].listen_port);
1036} 1069}
1037 1070
1038static void 1071static void
@@ -1249,10 +1282,20 @@ static void
1249control_client(const char *path) 1282control_client(const char *path)
1250{ 1283{
1251 struct sockaddr_un addr; 1284 struct sockaddr_un addr;
1252 int i, r, sock, exitval, num_env, addr_len; 1285 int i, r, fd, sock, exitval, num_env, addr_len;
1253 Buffer m; 1286 Buffer m;
1254 char *cp; 1287 char *term;
1255 extern char **environ; 1288 extern char **environ;
1289 u_int flags;
1290
1291 if (stdin_null_flag) {
1292 if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
1293 fatal("open(/dev/null): %s", strerror(errno));
1294 if (dup2(fd, STDIN_FILENO) == -1)
1295 fatal("dup2: %s", strerror(errno));
1296 if (fd > STDERR_FILENO)
1297 close(fd);
1298 }
1256 1299
1257 memset(&addr, '\0', sizeof(addr)); 1300 memset(&addr, '\0', sizeof(addr));
1258 addr.sun_family = AF_UNIX; 1301 addr.sun_family = AF_UNIX;
@@ -1269,26 +1312,52 @@ control_client(const char *path)
1269 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) 1312 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1)
1270 fatal("Couldn't connect to %s: %s", path, strerror(errno)); 1313 fatal("Couldn't connect to %s: %s", path, strerror(errno));
1271 1314
1272 if ((cp = getenv("TERM")) == NULL) 1315 if ((term = getenv("TERM")) == NULL)
1273 cp = ""; 1316 term = "";
1317
1318 flags = 0;
1319 if (tty_flag)
1320 flags |= SSHMUX_FLAG_TTY;
1321 if (subsystem_flag)
1322 flags |= SSHMUX_FLAG_SUBSYS;
1274 1323
1275 buffer_init(&m); 1324 buffer_init(&m);
1276 1325
1277 /* Get PID of controlee */ 1326 /* Send our command to server */
1327 buffer_put_int(&m, mux_command);
1328 buffer_put_int(&m, flags);
1329 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1330 fatal("%s: msg_send", __func__);
1331 buffer_clear(&m);
1332
1333 /* Get authorisation status and PID of controlee */
1278 if (ssh_msg_recv(sock, &m) == -1) 1334 if (ssh_msg_recv(sock, &m) == -1)
1279 fatal("%s: msg_recv", __func__); 1335 fatal("%s: msg_recv", __func__);
1280 if (buffer_get_char(&m) != 0) 1336 if (buffer_get_char(&m) != 1)
1281 fatal("%s: wrong version", __func__); 1337 fatal("%s: wrong version", __func__);
1282 /* Connection allowed? */
1283 if (buffer_get_int(&m) != 1) 1338 if (buffer_get_int(&m) != 1)
1284 fatal("Connection to master denied"); 1339 fatal("Connection to master denied");
1285 control_server_pid = buffer_get_int(&m); 1340 control_server_pid = buffer_get_int(&m);
1286 1341
1287 buffer_clear(&m); 1342 buffer_clear(&m);
1288 buffer_put_int(&m, tty_flag);
1289 buffer_put_int(&m, subsystem_flag);
1290 buffer_put_cstring(&m, cp);
1291 1343
1344 switch (mux_command) {
1345 case SSHMUX_COMMAND_ALIVE_CHECK:
1346 fprintf(stderr, "Master running (pid=%d)\r\n",
1347 control_server_pid);
1348 exit(0);
1349 case SSHMUX_COMMAND_TERMINATE:
1350 fprintf(stderr, "Exit request sent.\r\n");
1351 exit(0);
1352 case SSHMUX_COMMAND_OPEN:
1353 /* continue below */
1354 break;
1355 default:
1356 fatal("silly mux_command %d", mux_command);
1357 }
1358
1359 /* SSHMUX_COMMAND_OPEN */
1360 buffer_put_cstring(&m, term);
1292 buffer_append(&command, "\0", 1); 1361 buffer_append(&command, "\0", 1);
1293 buffer_put_cstring(&m, buffer_ptr(&command)); 1362 buffer_put_cstring(&m, buffer_ptr(&command));
1294 1363
@@ -1310,7 +1379,7 @@ control_client(const char *path)
1310 } 1379 }
1311 } 1380 }
1312 1381
1313 if (ssh_msg_send(sock, /* version */0, &m) == -1) 1382 if (ssh_msg_send(sock, /* version */1, &m) == -1)
1314 fatal("%s: msg_send", __func__); 1383 fatal("%s: msg_send", __func__);
1315 1384
1316 mm_send_fd(sock, STDIN_FILENO); 1385 mm_send_fd(sock, STDIN_FILENO);
@@ -1321,10 +1390,11 @@ control_client(const char *path)
1321 buffer_clear(&m); 1390 buffer_clear(&m);
1322 if (ssh_msg_recv(sock, &m) == -1) 1391 if (ssh_msg_recv(sock, &m) == -1)
1323 fatal("%s: msg_recv", __func__); 1392 fatal("%s: msg_recv", __func__);
1324 if (buffer_get_char(&m) != 0) 1393 if (buffer_get_char(&m) != 1)
1325 fatal("%s: master returned error", __func__); 1394 fatal("%s: wrong version", __func__);
1326 buffer_free(&m); 1395 buffer_free(&m);
1327 1396
1397 signal(SIGHUP, control_client_sighandler);
1328 signal(SIGINT, control_client_sighandler); 1398 signal(SIGINT, control_client_sighandler);
1329 signal(SIGTERM, control_client_sighandler); 1399 signal(SIGTERM, control_client_sighandler);
1330 signal(SIGWINCH, control_client_sigrelay); 1400 signal(SIGWINCH, control_client_sigrelay);