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 adfe60e4b..b9553d3e1 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 options.log_level = SYSLOG_LEVEL_QUIET; 424 options.log_level = SYSLOG_LEVEL_QUIET;
393 break; 425 break;
@@ -527,7 +559,7 @@ main(int ac, char **av)
527 ac -= optind; 559 ac -= optind;
528 av += optind; 560 av += optind;
529 561
530 if (ac > 0 && !host && **av != '-') { 562 if (ac > 0 && !host) {
531 if (strrchr(*av, '@')) { 563 if (strrchr(*av, '@')) {
532 p = xstrdup(*av); 564 p = xstrdup(*av);
533 cp = strrchr(p, '@'); 565 cp = strrchr(p, '@');
@@ -870,11 +902,48 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
870} 902}
871 903
872static void 904static void
905client_cleanup_stdio_fwd(int id, void *arg)
906{
907 debug("stdio forwarding: done");
908 cleanup_exit(0);
909}
910
911static int
912client_setup_stdio_fwd(const char *host_to_connect, u_short port_to_connect)
913{
914 Channel *c;
915 int in, out;
916
917 debug3("client_setup_stdio_fwd %s:%d", host_to_connect,
918 port_to_connect);
919
920 in = dup(STDIN_FILENO);
921 out = dup(STDOUT_FILENO);
922 if (in < 0 || out < 0)
923 fatal("channel_connect_stdio_fwd: dup() in/out failed");
924
925 if ((c = channel_connect_stdio_fwd(host_to_connect, port_to_connect,
926 in, out)) == NULL)
927 return 0;
928 channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
929 return 1;
930}
931
932static void
873ssh_init_forwarding(void) 933ssh_init_forwarding(void)
874{ 934{
875 int success = 0; 935 int success = 0;
876 int i; 936 int i;
877 937
938 if (stdio_forward_host != NULL) {
939 if (!compat20) {
940 fatal("stdio forwarding require Protocol 2");
941 }
942 if (!client_setup_stdio_fwd(stdio_forward_host,
943 stdio_forward_port))
944 fatal("Failed to connect in stdio forward mode.");
945 }
946
878 /* Initiate local TCP/IP port forwardings. */ 947 /* Initiate local TCP/IP port forwardings. */
879 for (i = 0; i < options.num_local_forwards; i++) { 948 for (i = 0; i < options.num_local_forwards; i++) {
880 debug("Local connections to %.200s:%d forwarded to remote " 949 debug("Local connections to %.200s:%d forwarded to remote "
@@ -1222,6 +1291,9 @@ ssh_session2(void)
1222 fatal("daemon() failed: %.200s", strerror(errno)); 1291 fatal("daemon() failed: %.200s", strerror(errno));
1223 } 1292 }
1224 1293
1294 if (options.use_roaming)
1295 request_roaming();
1296
1225 return client_loop(tty_flag, tty_flag ? 1297 return client_loop(tty_flag, tty_flag ?
1226 options.escape_char : SSH_ESCAPECHAR_NONE, id); 1298 options.escape_char : SSH_ESCAPECHAR_NONE, id);
1227} 1299}
@@ -1234,31 +1306,37 @@ load_public_identity_files(void)
1234 int i = 0; 1306 int i = 0;
1235 Key *public; 1307 Key *public;
1236 struct passwd *pw; 1308 struct passwd *pw;
1237#ifdef SMARTCARD 1309 u_int n_ids;
1310 char *identity_files[SSH_MAX_IDENTITY_FILES];
1311 Key *identity_keys[SSH_MAX_IDENTITY_FILES];
1312#ifdef ENABLE_PKCS11
1238 Key **keys; 1313 Key **keys;
1314 int nkeys;
1315#endif /* PKCS11 */
1239 1316
1240 if (options.smartcard_device != NULL && 1317 n_ids = 0;
1318 bzero(identity_files, sizeof(identity_files));
1319 bzero(identity_keys, sizeof(identity_keys));
1320
1321#ifdef ENABLE_PKCS11
1322 if (options.pkcs11_provider != NULL &&
1241 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 1323 options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1242 (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) { 1324 (pkcs11_init(!options.batch_mode) == 0) &&
1243 int count = 0; 1325 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
1244 for (i = 0; keys[i] != NULL; i++) { 1326 &keys)) > 0) {
1245 count++; 1327 for (i = 0; i < nkeys; i++) {
1246 memmove(&options.identity_files[1], 1328 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
1247 &options.identity_files[0], 1329 key_free(keys[i]);
1248 sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); 1330 continue;
1249 memmove(&options.identity_keys[1], 1331 }
1250 &options.identity_keys[0], 1332 identity_keys[n_ids] = keys[i];
1251 sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); 1333 identity_files[n_ids] =
1252 options.num_identity_files++; 1334 xstrdup(options.pkcs11_provider); /* XXX */
1253 options.identity_keys[0] = keys[i]; 1335 n_ids++;
1254 options.identity_files[0] = sc_get_key_label(keys[i]);
1255 } 1336 }
1256 if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
1257 options.num_identity_files = SSH_MAX_IDENTITY_FILES;
1258 i = count;
1259 xfree(keys); 1337 xfree(keys);
1260 } 1338 }
1261#endif /* SMARTCARD */ 1339#endif /* ENABLE_PKCS11 */
1262 if ((pw = getpwuid(original_real_uid)) == NULL) 1340 if ((pw = getpwuid(original_real_uid)) == NULL)
1263 fatal("load_public_identity_files: getpwuid failed"); 1341 fatal("load_public_identity_files: getpwuid failed");
1264 pwname = xstrdup(pw->pw_name); 1342 pwname = xstrdup(pw->pw_name);
@@ -1266,7 +1344,11 @@ load_public_identity_files(void)
1266 if (gethostname(thishost, sizeof(thishost)) == -1) 1344 if (gethostname(thishost, sizeof(thishost)) == -1)
1267 fatal("load_public_identity_files: gethostname: %s", 1345 fatal("load_public_identity_files: gethostname: %s",
1268 strerror(errno)); 1346 strerror(errno));
1269 for (; i < options.num_identity_files; i++) { 1347 for (i = 0; i < options.num_identity_files; i++) {
1348 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
1349 xfree(options.identity_files[i]);
1350 continue;
1351 }
1270 cp = tilde_expand_filename(options.identity_files[i], 1352 cp = tilde_expand_filename(options.identity_files[i],
1271 original_real_uid); 1353 original_real_uid);
1272 filename = percent_expand(cp, "d", pwdir, 1354 filename = percent_expand(cp, "d", pwdir,
@@ -1277,9 +1359,37 @@ load_public_identity_files(void)
1277 debug("identity file %s type %d", filename, 1359 debug("identity file %s type %d", filename,
1278 public ? public->type : -1); 1360 public ? public->type : -1);
1279 xfree(options.identity_files[i]); 1361 xfree(options.identity_files[i]);
1280 options.identity_files[i] = filename; 1362 identity_files[n_ids] = filename;
1281 options.identity_keys[i] = public; 1363 identity_keys[n_ids] = public;
1364
1365 if (++n_ids >= SSH_MAX_IDENTITY_FILES)
1366 continue;
1367
1368 /* Try to add the certificate variant too */
1369 xasprintf(&cp, "%s-cert", filename);
1370 public = key_load_public(cp, NULL);
1371 debug("identity file %s type %d", cp,
1372 public ? public->type : -1);
1373 if (public == NULL) {
1374 xfree(cp);
1375 continue;
1376 }
1377 if (!key_is_cert(public)) {
1378 debug("%s: key %s type %s is not a certificate",
1379 __func__, cp, key_type(public));
1380 key_free(public);
1381 xfree(cp);
1382 continue;
1383 }
1384 identity_keys[n_ids] = public;
1385 /* point to the original path, most likely the private key */
1386 identity_files[n_ids] = xstrdup(filename);
1387 n_ids++;
1282 } 1388 }
1389 options.num_identity_files = n_ids;
1390 memcpy(options.identity_files, identity_files, sizeof(identity_files));
1391 memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
1392
1283 bzero(pwname, strlen(pwname)); 1393 bzero(pwname, strlen(pwname));
1284 xfree(pwname); 1394 xfree(pwname);
1285 bzero(pwdir, strlen(pwdir)); 1395 bzero(pwdir, strlen(pwdir));