diff options
author | Colin Watson <cjwatson@debian.org> | 2010-03-31 00:48:57 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2010-03-31 00:48:57 +0100 |
commit | d1a87e462e1db89f19cd960588d0c6b287cb5ccc (patch) | |
tree | f0d13e1687800f36a3c4322b94ac5230ad17bdbf /ssh.c | |
parent | 964476f91b66c475d5b8fa1e8b28d39a97a1b56e (diff) | |
parent | 004a7fb9c6a00b13dc98f56599918a54a3506d10 (diff) |
merge 5.4p1
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 174 |
1 files changed, 142 insertions, 32 deletions
@@ -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 | ||
109 | extern char *__progname; | 110 | extern char *__progname; |
@@ -132,6 +133,10 @@ int stdin_null_flag = 0; | |||
132 | */ | 133 | */ |
133 | int fork_after_authentication_flag = 0; | 134 | int fork_after_authentication_flag = 0; |
134 | 135 | ||
136 | /* forward stdio to remote host and port */ | ||
137 | char *stdio_forward_host = NULL; | ||
138 | int 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 | ||
872 | static void | 904 | static void |
905 | client_cleanup_stdio_fwd(int id, void *arg) | ||
906 | { | ||
907 | debug("stdio forwarding: done"); | ||
908 | cleanup_exit(0); | ||
909 | } | ||
910 | |||
911 | static int | ||
912 | client_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 | |||
932 | static void | ||
873 | ssh_init_forwarding(void) | 933 | ssh_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)); |