summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh.c')
-rw-r--r--ssh.c174
1 files changed, 142 insertions, 32 deletions
diff --git a/ssh.c b/ssh.c
index a72f16c63..68178ff95 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.326 2009/07/02 02:11:47 dtucker Exp $ */ 1/* $OpenBSD: ssh.c,v 1.335 2010/02/26 20:29:54 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
@@ -100,10 +100,11 @@
100#include "match.h" 100#include "match.h"
101#include "msg.h" 101#include "msg.h"
102#include "uidswap.h" 102#include "uidswap.h"
103#include "roaming.h"
103#include "version.h" 104#include "version.h"
104 105
105#ifdef SMARTCARD 106#ifdef ENABLE_PKCS11
106#include "scard.h" 107#include "ssh-pkcs11.h"
107#endif 108#endif
108 109
109extern char *__progname; 110extern char *__progname;
@@ -132,6 +133,10 @@ int stdin_null_flag = 0;
132 */ 133 */
133int fork_after_authentication_flag = 0; 134int fork_after_authentication_flag = 0;
134 135
136/* forward stdio to remote host and port */
137char *stdio_forward_host = NULL;
138int stdio_forward_port = 0;
139
135/* 140/*
136 * General data structure for command line options and options configurable 141 * General data structure for command line options and options configurable
137 * in configuration files. See readconf.h. 142 * in configuration files. See readconf.h.
@@ -182,10 +187,12 @@ usage(void)
182 fprintf(stderr, 187 fprintf(stderr,
183"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" 188"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
184" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" 189" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
185" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" 190" [-I pkcs11] [-i identity_file]\n"
191" [-L [bind_address:]port:host:hostport]\n"
186" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" 192" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
187" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" 193" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
188" [-w local_tun[:remote_tun]] [user@]hostname [command]\n" 194" [-W host:port] [-w local_tun[:remote_tun]]\n"
195" [user@]hostname [command]\n"
189 ); 196 );
190 exit(255); 197 exit(255);
191} 198}
@@ -275,7 +282,7 @@ main(int ac, char **av)
275 282
276 again: 283 again:
277 while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" 284 while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
278 "ACD:F:I:KL:MNO:PR:S:TVw:XYy")) != -1) { 285 "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
279 switch (opt) { 286 switch (opt) {
280 case '1': 287 case '1':
281 options.protocol = SSH_PROTO_1; 288 options.protocol = SSH_PROTO_1;
@@ -313,6 +320,11 @@ main(int ac, char **av)
313 options.gateway_ports = 1; 320 options.gateway_ports = 1;
314 break; 321 break;
315 case 'O': 322 case 'O':
323 if (stdio_forward_host != NULL)
324 fatal("Cannot specify multiplexing "
325 "command with -W");
326 else if (muxclient_command != 0)
327 fatal("Multiplexing command already specified");
316 if (strcmp(optarg, "check") == 0) 328 if (strcmp(optarg, "check") == 0)
317 muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; 329 muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
318 else if (strcmp(optarg, "exit") == 0) 330 else if (strcmp(optarg, "exit") == 0)
@@ -351,10 +363,10 @@ main(int ac, char **av)
351 xstrdup(optarg); 363 xstrdup(optarg);
352 break; 364 break;
353 case 'I': 365 case 'I':
354#ifdef SMARTCARD 366#ifdef ENABLE_PKCS11
355 options.smartcard_device = xstrdup(optarg); 367 options.pkcs11_provider = xstrdup(optarg);
356#else 368#else
357 fprintf(stderr, "no support for smartcards.\n"); 369 fprintf(stderr, "no support for PKCS#11.\n");
358#endif 370#endif
359 break; 371 break;
360 case 't': 372 case 't':
@@ -388,6 +400,26 @@ main(int ac, char **av)
388 exit(255); 400 exit(255);
389 } 401 }
390 break; 402 break;
403 case 'W':
404 if (stdio_forward_host != NULL)
405 fatal("stdio forward already specified");
406 if (muxclient_command != 0)
407 fatal("Cannot specify stdio forward with -O");
408 if (parse_forward(&fwd, optarg, 1, 0)) {
409 stdio_forward_host = fwd.listen_host;
410 stdio_forward_port = fwd.listen_port;
411 xfree(fwd.connect_host);
412 } else {
413 fprintf(stderr,
414 "Bad stdio forwarding specification '%s'\n",
415 optarg);
416 exit(255);
417 }
418 no_tty_flag = 1;
419 no_shell_flag = 1;
420 options.clear_forwardings = 1;
421 options.exit_on_forward_failure = 1;
422 break;
391 case 'q': 423 case 'q':
392 if (options.log_level == SYSLOG_LEVEL_QUIET) { 424 if (options.log_level == SYSLOG_LEVEL_QUIET) {
393 options.log_level = SYSLOG_LEVEL_SILENT; 425 options.log_level = SYSLOG_LEVEL_SILENT;
@@ -532,7 +564,7 @@ main(int ac, char **av)
532 ac -= optind; 564 ac -= optind;
533 av += optind; 565 av += optind;
534 566
535 if (ac > 0 && !host && **av != '-') { 567 if (ac > 0 && !host) {
536 if (strrchr(*av, '@')) { 568 if (strrchr(*av, '@')) {
537 p = xstrdup(*av); 569 p = xstrdup(*av);
538 cp = strrchr(p, '@'); 570 cp = strrchr(p, '@');
@@ -875,11 +907,48 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
875} 907}
876 908
877static void 909static void
910client_cleanup_stdio_fwd(int id, void *arg)
911{
912 debug("stdio forwarding: done");
913 cleanup_exit(0);
914}
915
916static int
917client_setup_stdio_fwd(const char *host_to_connect, u_short port_to_connect)
918{
919 Channel *c;
920 int in, out;
921
922 debug3("client_setup_stdio_fwd %s:%d", host_to_connect,
923 port_to_connect);
924
925 in = dup(STDIN_FILENO);
926 out = dup(STDOUT_FILENO);
927 if (in < 0 || out < 0)
928 fatal("channel_connect_stdio_fwd: dup() in/out failed");
929
930 if ((c = channel_connect_stdio_fwd(host_to_connect, port_to_connect,
931 in, out)) == NULL)
932 return 0;
933 channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
934 return 1;
935}
936
937static void
878ssh_init_forwarding(void) 938ssh_init_forwarding(void)
879{ 939{
880 int success = 0; 940 int success = 0;
881 int i; 941 int i;
882 942
943 if (stdio_forward_host != NULL) {
944 if (!compat20) {
945 fatal("stdio forwarding require Protocol 2");
946 }
947 if (!client_setup_stdio_fwd(stdio_forward_host,
948 stdio_forward_port))
949 fatal("Failed to connect in stdio forward mode.");
950 }
951
883 /* Initiate local TCP/IP port forwardings. */ 952 /* Initiate local TCP/IP port forwardings. */
884 for (i = 0; i < options.num_local_forwards; i++) { 953 for (i = 0; i < options.num_local_forwards; i++) {
885 debug("Local connections to %.200s:%d forwarded to remote " 954 debug("Local connections to %.200s:%d forwarded to remote "
@@ -1227,6 +1296,9 @@ ssh_session2(void)
1227 fatal("daemon() failed: %.200s", strerror(errno)); 1296 fatal("daemon() failed: %.200s", strerror(errno));
1228 } 1297 }
1229 1298
1299 if (options.use_roaming)
1300 request_roaming();
1301
1230 return client_loop(tty_flag, tty_flag ? 1302 return client_loop(tty_flag, tty_flag ?
1231 options.escape_char : SSH_ESCAPECHAR_NONE, id); 1303 options.escape_char : SSH_ESCAPECHAR_NONE, id);
1232} 1304}
@@ -1239,31 +1311,37 @@ load_public_identity_files(void)
1239 int i = 0; 1311 int i = 0;
1240 Key *public; 1312 Key *public;
1241 struct passwd *pw; 1313 struct passwd *pw;
1242#ifdef SMARTCARD 1314 u_int n_ids;
1315 char *identity_files[SSH_MAX_IDENTITY_FILES];
1316 Key *identity_keys[SSH_MAX_IDENTITY_FILES];
1317#ifdef ENABLE_PKCS11
1243 Key **keys; 1318 Key **keys;
1319 int nkeys;
1320#endif /* PKCS11 */
1244 1321
1245 if (options.smartcard_device != NULL && 1322 n_ids = 0;
1323 bzero(identity_files, sizeof(identity_files));
1324 bzero(identity_keys, sizeof(identity_keys));
1325
1326#ifdef ENABLE_PKCS11
1327 if (options.pkcs11_provider != NULL &&
1246 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 1328 options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1247 (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) { 1329 (pkcs11_init(!options.batch_mode) == 0) &&
1248 int count = 0; 1330 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
1249 for (i = 0; keys[i] != NULL; i++) { 1331 &keys)) > 0) {
1250 count++; 1332 for (i = 0; i < nkeys; i++) {
1251 memmove(&options.identity_files[1], 1333 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
1252 &options.identity_files[0], 1334 key_free(keys[i]);
1253 sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); 1335 continue;
1254 memmove(&options.identity_keys[1], 1336 }
1255 &options.identity_keys[0], 1337 identity_keys[n_ids] = keys[i];
1256 sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); 1338 identity_files[n_ids] =
1257 options.num_identity_files++; 1339 xstrdup(options.pkcs11_provider); /* XXX */
1258 options.identity_keys[0] = keys[i]; 1340 n_ids++;
1259 options.identity_files[0] = sc_get_key_label(keys[i]);
1260 } 1341 }
1261 if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
1262 options.num_identity_files = SSH_MAX_IDENTITY_FILES;
1263 i = count;
1264 xfree(keys); 1342 xfree(keys);
1265 } 1343 }
1266#endif /* SMARTCARD */ 1344#endif /* ENABLE_PKCS11 */
1267 if ((pw = getpwuid(original_real_uid)) == NULL) 1345 if ((pw = getpwuid(original_real_uid)) == NULL)
1268 fatal("load_public_identity_files: getpwuid failed"); 1346 fatal("load_public_identity_files: getpwuid failed");
1269 pwname = xstrdup(pw->pw_name); 1347 pwname = xstrdup(pw->pw_name);
@@ -1271,7 +1349,11 @@ load_public_identity_files(void)
1271 if (gethostname(thishost, sizeof(thishost)) == -1) 1349 if (gethostname(thishost, sizeof(thishost)) == -1)
1272 fatal("load_public_identity_files: gethostname: %s", 1350 fatal("load_public_identity_files: gethostname: %s",
1273 strerror(errno)); 1351 strerror(errno));
1274 for (; i < options.num_identity_files; i++) { 1352 for (i = 0; i < options.num_identity_files; i++) {
1353 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
1354 xfree(options.identity_files[i]);
1355 continue;
1356 }
1275 cp = tilde_expand_filename(options.identity_files[i], 1357 cp = tilde_expand_filename(options.identity_files[i],
1276 original_real_uid); 1358 original_real_uid);
1277 filename = percent_expand(cp, "d", pwdir, 1359 filename = percent_expand(cp, "d", pwdir,
@@ -1298,9 +1380,37 @@ load_public_identity_files(void)
1298 } 1380 }
1299 } 1381 }
1300 xfree(options.identity_files[i]); 1382 xfree(options.identity_files[i]);
1301 options.identity_files[i] = filename; 1383 identity_files[n_ids] = filename;
1302 options.identity_keys[i] = public; 1384 identity_keys[n_ids] = public;
1385
1386 if (++n_ids >= SSH_MAX_IDENTITY_FILES)
1387 continue;
1388
1389 /* Try to add the certificate variant too */
1390 xasprintf(&cp, "%s-cert", filename);
1391 public = key_load_public(cp, NULL);
1392 debug("identity file %s type %d", cp,
1393 public ? public->type : -1);
1394 if (public == NULL) {
1395 xfree(cp);
1396 continue;
1397 }
1398 if (!key_is_cert(public)) {
1399 debug("%s: key %s type %s is not a certificate",
1400 __func__, cp, key_type(public));
1401 key_free(public);
1402 xfree(cp);
1403 continue;
1404 }
1405 identity_keys[n_ids] = public;
1406 /* point to the original path, most likely the private key */
1407 identity_files[n_ids] = xstrdup(filename);
1408 n_ids++;
1303 } 1409 }
1410 options.num_identity_files = n_ids;
1411 memcpy(options.identity_files, identity_files, sizeof(identity_files));
1412 memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
1413
1304 bzero(pwname, strlen(pwname)); 1414 bzero(pwname, strlen(pwname));
1305 xfree(pwname); 1415 xfree(pwname);
1306 bzero(pwdir, strlen(pwdir)); 1416 bzero(pwdir, strlen(pwdir));