summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c315
1 files changed, 243 insertions, 72 deletions
diff --git a/ssh.c b/ssh.c
index e655e68da..1419f9874 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.209 2004/03/11 10:21:17 markus Exp $"); 43RCSID("$OpenBSD: ssh.c,v 1.224 2004/07/28 09:40:29 markus Exp $");
44 44
45#include <openssl/evp.h> 45#include <openssl/evp.h>
46#include <openssl/err.h> 46#include <openssl/err.h>
@@ -53,31 +53,31 @@ RCSID("$OpenBSD: ssh.c,v 1.209 2004/03/11 10:21:17 markus Exp $");
53#include "xmalloc.h" 53#include "xmalloc.h"
54#include "packet.h" 54#include "packet.h"
55#include "buffer.h" 55#include "buffer.h"
56#include "bufaux.h"
56#include "channels.h" 57#include "channels.h"
57#include "key.h" 58#include "key.h"
58#include "authfd.h" 59#include "authfd.h"
59#include "authfile.h" 60#include "authfile.h"
60#include "pathnames.h" 61#include "pathnames.h"
62#include "dispatch.h"
61#include "clientloop.h" 63#include "clientloop.h"
62#include "log.h" 64#include "log.h"
63#include "readconf.h" 65#include "readconf.h"
64#include "sshconnect.h" 66#include "sshconnect.h"
65#include "tildexpand.h"
66#include "dispatch.h"
67#include "misc.h" 67#include "misc.h"
68#include "kex.h" 68#include "kex.h"
69#include "mac.h" 69#include "mac.h"
70#include "sshtty.h" 70#include "sshpty.h"
71#include "match.h"
72#include "msg.h"
73#include "monitor_fdpass.h"
74#include "uidswap.h"
71 75
72#ifdef SMARTCARD 76#ifdef SMARTCARD
73#include "scard.h" 77#include "scard.h"
74#endif 78#endif
75 79
76#ifdef HAVE___PROGNAME
77extern char *__progname; 80extern char *__progname;
78#else
79char *__progname;
80#endif
81 81
82/* Flag indicating whether debug mode is on. This can be set on the command line. */ 82/* Flag indicating whether debug mode is on. This can be set on the command line. */
83int debug_flag = 0; 83int debug_flag = 0;
@@ -141,16 +141,23 @@ static int client_global_request_id = 0;
141/* pid of proxycommand child process */ 141/* pid of proxycommand child process */
142pid_t proxy_command_pid = 0; 142pid_t proxy_command_pid = 0;
143 143
144/* fd to control socket */
145int control_fd = -1;
146
147/* Only used in control client mode */
148volatile sig_atomic_t control_client_terminate = 0;
149u_int control_server_pid = 0;
150
144/* Prints a help message to the user. This function never returns. */ 151/* Prints a help message to the user. This function never returns. */
145 152
146static void 153static void
147usage(void) 154usage(void)
148{ 155{
149 fprintf(stderr, 156 fprintf(stderr,
150"usage: ssh [-1246AaCfghkNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" 157"usage: ssh [-1246AaCfghkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
151" [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n" 158" [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n"
152" [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n" 159" [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n"
153" [-p port] [-R port:host:hostport] [user@]hostname [command]\n" 160" [-p port] [-R port:host:hostport] [-S ctl] [user@]hostname [command]\n"
154 ); 161 );
155 exit(1); 162 exit(1);
156} 163}
@@ -158,6 +165,7 @@ usage(void)
158static int ssh_session(void); 165static int ssh_session(void);
159static int ssh_session2(void); 166static int ssh_session2(void);
160static void load_public_identity_files(void); 167static void load_public_identity_files(void);
168static void control_client(const char *path);
161 169
162/* 170/*
163 * Main program for the ssh client. 171 * Main program for the ssh client.
@@ -228,7 +236,7 @@ main(int ac, char **av)
228 236
229again: 237again:
230 while ((opt = getopt(ac, av, 238 while ((opt = getopt(ac, av,
231 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVXY")) != -1) { 239 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNPR:S:TVXY")) != -1) {
232 switch (opt) { 240 switch (opt) {
233 case '1': 241 case '1':
234 options.protocol = SSH_PROTO_1; 242 options.protocol = SSH_PROTO_1;
@@ -337,7 +345,7 @@ again:
337 if (ciphers_valid(optarg)) { 345 if (ciphers_valid(optarg)) {
338 /* SSH2 only */ 346 /* SSH2 only */
339 options.ciphers = xstrdup(optarg); 347 options.ciphers = xstrdup(optarg);
340 options.cipher = SSH_CIPHER_ILLEGAL; 348 options.cipher = SSH_CIPHER_INVALID;
341 } else { 349 } else {
342 /* SSH1 only */ 350 /* SSH1 only */
343 options.cipher = cipher_number(optarg); 351 options.cipher = cipher_number(optarg);
@@ -364,6 +372,10 @@ again:
364 exit(1); 372 exit(1);
365 } 373 }
366 break; 374 break;
375 case 'M':
376 options.control_master =
377 (options.control_master >= 1) ? 2 : 1;
378 break;
367 case 'p': 379 case 'p':
368 options.port = a2port(optarg); 380 options.port = a2port(optarg);
369 if (options.port == 0) { 381 if (options.port == 0) {
@@ -432,6 +444,11 @@ again:
432 case 's': 444 case 's':
433 subsystem_flag = 1; 445 subsystem_flag = 1;
434 break; 446 break;
447 case 'S':
448 if (options.control_path != NULL)
449 free(options.control_path);
450 options.control_path = xstrdup(optarg);
451 break;
435 case 'b': 452 case 'b':
436 options.bind_address = optarg; 453 options.bind_address = optarg;
437 break; 454 break;
@@ -526,16 +543,17 @@ again:
526 * file if the user specifies a config file on the command line. 543 * file if the user specifies a config file on the command line.
527 */ 544 */
528 if (config != NULL) { 545 if (config != NULL) {
529 if (!read_config_file(config, host, &options)) 546 if (!read_config_file(config, host, &options, 0))
530 fatal("Can't open user config file %.100s: " 547 fatal("Can't open user config file %.100s: "
531 "%.100s", config, strerror(errno)); 548 "%.100s", config, strerror(errno));
532 } else { 549 } else {
533 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, 550 snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
534 _PATH_SSH_USER_CONFFILE); 551 _PATH_SSH_USER_CONFFILE);
535 (void)read_config_file(buf, host, &options); 552 (void)read_config_file(buf, host, &options, 1);
536 553
537 /* Read systemwide configuration file after use config. */ 554 /* Read systemwide configuration file after use config. */
538 (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); 555 (void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
556 &options, 0);
539 } 557 }
540 558
541 /* Fill configuration defaults. */ 559 /* Fill configuration defaults. */
@@ -565,6 +583,13 @@ again:
565 strcmp(options.proxy_command, "none") == 0) 583 strcmp(options.proxy_command, "none") == 0)
566 options.proxy_command = NULL; 584 options.proxy_command = NULL;
567 585
586 if (options.control_path != NULL) {
587 options.control_path = tilde_expand_filename(
588 options.control_path, original_real_uid);
589 }
590 if (options.control_path != NULL && options.control_master == 0)
591 control_client(options.control_path); /* This doesn't return */
592
568 /* Open a connection to the remote host. */ 593 /* Open a connection to the remote host. */
569 if (ssh_connect(host, &hostaddr, options.port, 594 if (ssh_connect(host, &hostaddr, options.port,
570 options.address_family, options.connection_attempts, 595 options.address_family, options.connection_attempts,
@@ -620,8 +645,10 @@ again:
620 * user's home directory if it happens to be on a NFS volume where 645 * user's home directory if it happens to be on a NFS volume where
621 * root is mapped to nobody. 646 * root is mapped to nobody.
622 */ 647 */
623 seteuid(original_real_uid); 648 if (original_effective_uid == 0) {
624 setuid(original_real_uid); 649 PRIV_START;
650 permanently_set_uid(pw);
651 }
625 652
626 /* 653 /*
627 * Now that we are back to our own permissions, create ~/.ssh 654 * Now that we are back to our own permissions, create ~/.ssh
@@ -677,6 +704,9 @@ again:
677 exit_status = compat20 ? ssh_session2() : ssh_session(); 704 exit_status = compat20 ? ssh_session2() : ssh_session();
678 packet_close(); 705 packet_close();
679 706
707 if (options.control_path != NULL && control_fd != -1)
708 unlink(options.control_path);
709
680 /* 710 /*
681 * Send SIGHUP to proxy command if used. We don't wait() in 711 * Send SIGHUP to proxy command if used. We don't wait() in
682 * case it hangs and instead rely on init to reap the child 712 * case it hangs and instead rely on init to reap the child
@@ -776,17 +806,17 @@ x11_get_proto(char **_proto, char **_data)
776 * for the local connection. 806 * for the local connection.
777 */ 807 */
778 if (!got_data) { 808 if (!got_data) {
779 u_int32_t rand = 0; 809 u_int32_t rnd = 0;
780 810
781 logit("Warning: No xauth data; " 811 logit("Warning: No xauth data; "
782 "using fake authentication data for X11 forwarding."); 812 "using fake authentication data for X11 forwarding.");
783 strlcpy(proto, SSH_X11_PROTO, sizeof proto); 813 strlcpy(proto, SSH_X11_PROTO, sizeof proto);
784 for (i = 0; i < 16; i++) { 814 for (i = 0; i < 16; i++) {
785 if (i % 4 == 0) 815 if (i % 4 == 0)
786 rand = arc4random(); 816 rnd = arc4random();
787 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", 817 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
788 rand & 0xff); 818 rnd & 0xff);
789 rand >>= 8; 819 rnd >>= 8;
790 } 820 }
791 } 821 }
792} 822}
@@ -973,7 +1003,7 @@ ssh_session(void)
973} 1003}
974 1004
975static void 1005static void
976client_subsystem_reply(int type, u_int32_t seq, void *ctxt) 1006ssh_subsystem_reply(int type, u_int32_t seq, void *ctxt)
977{ 1007{
978 int id, len; 1008 int id, len;
979 1009
@@ -1005,40 +1035,53 @@ client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
1005 options.remote_forwards[i].port); 1035 options.remote_forwards[i].port);
1006} 1036}
1007 1037
1008/* request pty/x11/agent/tcpfwd/shell for channel */
1009static void 1038static void
1010ssh_session2_setup(int id, void *arg) 1039ssh_control_listener(void)
1011{ 1040{
1012 int len; 1041 struct sockaddr_un addr;
1013 int interactive = 0; 1042 mode_t old_umask;
1014 struct termios tio; 1043 int addr_len;
1015 1044
1016 debug2("ssh_session2_setup: id %d", id); 1045 if (options.control_path == NULL || options.control_master <= 0)
1046 return;
1017 1047
1018 if (tty_flag) { 1048 memset(&addr, '\0', sizeof(addr));
1019 struct winsize ws; 1049 addr.sun_family = AF_UNIX;
1020 char *cp; 1050 addr_len = offsetof(struct sockaddr_un, sun_path) +
1021 cp = getenv("TERM"); 1051 strlen(options.control_path) + 1;
1022 if (!cp)
1023 cp = "";
1024 /* Store window size in the packet. */
1025 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
1026 memset(&ws, 0, sizeof(ws));
1027 1052
1028 channel_request_start(id, "pty-req", 0); 1053 if (strlcpy(addr.sun_path, options.control_path,
1029 packet_put_cstring(cp); 1054 sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
1030 packet_put_int(ws.ws_col); 1055 fatal("ControlPath too long");
1031 packet_put_int(ws.ws_row); 1056
1032 packet_put_int(ws.ws_xpixel); 1057 if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1033 packet_put_int(ws.ws_ypixel); 1058 fatal("%s socket(): %s\n", __func__, strerror(errno));
1034 tio = get_saved_tio(); 1059
1035 tty_make_modes(/*ignored*/ 0, &tio); 1060 old_umask = umask(0177);
1036 packet_send(); 1061 if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) {
1037 interactive = 1; 1062 control_fd = -1;
1038 /* XXX wait for reply */ 1063 if (errno == EINVAL)
1064 fatal("ControlSocket %s already exists",
1065 options.control_path);
1066 else
1067 fatal("%s bind(): %s\n", __func__, strerror(errno));
1039 } 1068 }
1040 if (options.forward_x11 && 1069 umask(old_umask);
1041 getenv("DISPLAY") != NULL) { 1070
1071 if (listen(control_fd, 64) == -1)
1072 fatal("%s listen(): %s\n", __func__, strerror(errno));
1073
1074 set_nonblock(control_fd);
1075}
1076
1077/* request pty/x11/agent/tcpfwd/shell for channel */
1078static void
1079ssh_session2_setup(int id, void *arg)
1080{
1081 extern char **environ;
1082
1083 int interactive = tty_flag;
1084 if (options.forward_x11 && getenv("DISPLAY") != NULL) {
1042 char *proto, *data; 1085 char *proto, *data;
1043 /* Get reasonable local authentication information. */ 1086 /* Get reasonable local authentication information. */
1044 x11_get_proto(&proto, &data); 1087 x11_get_proto(&proto, &data);
@@ -1056,27 +1099,8 @@ ssh_session2_setup(int id, void *arg)
1056 packet_send(); 1099 packet_send();
1057 } 1100 }
1058 1101
1059 len = buffer_len(&command); 1102 client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
1060 if (len > 0) { 1103 NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply);
1061 if (len > 900)
1062 len = 900;
1063 if (subsystem_flag) {
1064 debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
1065 channel_request_start(id, "subsystem", /*want reply*/ 1);
1066 /* register callback for reply */
1067 /* XXX we assume that client_loop has already been called */
1068 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
1069 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
1070 } else {
1071 debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command));
1072 channel_request_start(id, "exec", 0);
1073 }
1074 packet_put_string(buffer_ptr(&command), buffer_len(&command));
1075 packet_send();
1076 } else {
1077 channel_request_start(id, "shell", 0);
1078 packet_send();
1079 }
1080 1104
1081 packet_set_interactive(interactive); 1105 packet_set_interactive(interactive);
1082} 1106}
@@ -1122,7 +1146,7 @@ ssh_session2_open(void)
1122 1146
1123 channel_send_open(c->self); 1147 channel_send_open(c->self);
1124 if (!no_shell_flag) 1148 if (!no_shell_flag)
1125 channel_register_confirm(c->self, ssh_session2_setup); 1149 channel_register_confirm(c->self, ssh_session2_setup, NULL);
1126 1150
1127 return c->self; 1151 return c->self;
1128} 1152}
@@ -1134,6 +1158,7 @@ ssh_session2(void)
1134 1158
1135 /* XXX should be pre-session */ 1159 /* XXX should be pre-session */
1136 ssh_init_forwarding(); 1160 ssh_init_forwarding();
1161 ssh_control_listener();
1137 1162
1138 if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) 1163 if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1139 id = ssh_session2_open(); 1164 id = ssh_session2_open();
@@ -1187,3 +1212,149 @@ load_public_identity_files(void)
1187 options.identity_keys[i] = public; 1212 options.identity_keys[i] = public;
1188 } 1213 }
1189} 1214}
1215
1216static void
1217control_client_sighandler(int signo)
1218{
1219 control_client_terminate = signo;
1220}
1221
1222static void
1223control_client_sigrelay(int signo)
1224{
1225 if (control_server_pid > 1)
1226 kill(control_server_pid, signo);
1227}
1228
1229static int
1230env_permitted(char *env)
1231{
1232 int i;
1233 char name[1024], *cp;
1234
1235 strlcpy(name, env, sizeof(name));
1236 if ((cp = strchr(name, '=')) == NULL)
1237 return (0);
1238
1239 *cp = '\0';
1240
1241 for (i = 0; i < options.num_send_env; i++)
1242 if (match_pattern(name, options.send_env[i]))
1243 return (1);
1244
1245 return (0);
1246}
1247
1248static void
1249control_client(const char *path)
1250{
1251 struct sockaddr_un addr;
1252 int i, r, sock, exitval, num_env, addr_len;
1253 Buffer m;
1254 char *cp;
1255 extern char **environ;
1256
1257 memset(&addr, '\0', sizeof(addr));
1258 addr.sun_family = AF_UNIX;
1259 addr_len = offsetof(struct sockaddr_un, sun_path) +
1260 strlen(path) + 1;
1261
1262 if (strlcpy(addr.sun_path, path,
1263 sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
1264 fatal("ControlPath too long");
1265
1266 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1267 fatal("%s socket(): %s", __func__, strerror(errno));
1268
1269 if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1)
1270 fatal("Couldn't connect to %s: %s", path, strerror(errno));
1271
1272 if ((cp = getenv("TERM")) == NULL)
1273 cp = "";
1274
1275 buffer_init(&m);
1276
1277 /* Get PID of controlee */
1278 if (ssh_msg_recv(sock, &m) == -1)
1279 fatal("%s: msg_recv", __func__);
1280 if (buffer_get_char(&m) != 0)
1281 fatal("%s: wrong version", __func__);
1282 /* Connection allowed? */
1283 if (buffer_get_int(&m) != 1)
1284 fatal("Connection to master denied");
1285 control_server_pid = buffer_get_int(&m);
1286
1287 buffer_clear(&m);
1288 buffer_put_int(&m, tty_flag);
1289 buffer_put_int(&m, subsystem_flag);
1290 buffer_put_cstring(&m, cp);
1291
1292 buffer_append(&command, "\0", 1);
1293 buffer_put_cstring(&m, buffer_ptr(&command));
1294
1295 if (options.num_send_env == 0 || environ == NULL) {
1296 buffer_put_int(&m, 0);
1297 } else {
1298 /* Pass environment */
1299 num_env = 0;
1300 for (i = 0; environ[i] != NULL; i++)
1301 if (env_permitted(environ[i]))
1302 num_env++; /* Count */
1303
1304 buffer_put_int(&m, num_env);
1305
1306 for (i = 0; environ[i] != NULL && num_env >= 0; i++)
1307 if (env_permitted(environ[i])) {
1308 num_env--;
1309 buffer_put_cstring(&m, environ[i]);
1310 }
1311 }
1312
1313 if (ssh_msg_send(sock, /* version */0, &m) == -1)
1314 fatal("%s: msg_send", __func__);
1315
1316 mm_send_fd(sock, STDIN_FILENO);
1317 mm_send_fd(sock, STDOUT_FILENO);
1318 mm_send_fd(sock, STDERR_FILENO);
1319
1320 /* Wait for reply, so master has a chance to gather ttymodes */
1321 buffer_clear(&m);
1322 if (ssh_msg_recv(sock, &m) == -1)
1323 fatal("%s: msg_recv", __func__);
1324 if (buffer_get_char(&m) != 0)
1325 fatal("%s: master returned error", __func__);
1326 buffer_free(&m);
1327
1328 signal(SIGINT, control_client_sighandler);
1329 signal(SIGTERM, control_client_sighandler);
1330 signal(SIGWINCH, control_client_sigrelay);
1331
1332 if (tty_flag)
1333 enter_raw_mode();
1334
1335 /* Stick around until the controlee closes the client_fd */
1336 exitval = 0;
1337 for (;!control_client_terminate;) {
1338 r = read(sock, &exitval, sizeof(exitval));
1339 if (r == 0) {
1340 debug2("Received EOF from master");
1341 break;
1342 }
1343 if (r > 0)
1344 debug2("Received exit status from master %d", exitval);
1345 if (r == -1 && errno != EINTR)
1346 fatal("%s: read %s", __func__, strerror(errno));
1347 }
1348
1349 if (control_client_terminate)
1350 debug2("Exiting on signal %d", control_client_terminate);
1351
1352 close(sock);
1353
1354 leave_raw_mode();
1355
1356 if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
1357 fprintf(stderr, "Connection to master closed.\r\n");
1358
1359 exit(exitval);
1360}