diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 110 |
1 files changed, 82 insertions, 28 deletions
diff --git a/readconf.c b/readconf.c index ee46ad623..dc22360d1 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.239 2015/07/30 00:01:34 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.250 2016/02/08 23:40:12 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 |
@@ -137,6 +137,7 @@ typedef enum { | |||
137 | oPasswordAuthentication, oRSAAuthentication, | 137 | oPasswordAuthentication, oRSAAuthentication, |
138 | oChallengeResponseAuthentication, oXAuthLocation, | 138 | oChallengeResponseAuthentication, oXAuthLocation, |
139 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, | 139 | oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, |
140 | oCertificateFile, oAddKeysToAgent, | ||
140 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, | 141 | oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, |
141 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, | 142 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, |
142 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, | 143 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, |
@@ -155,7 +156,7 @@ typedef enum { | |||
155 | oSendEnv, oControlPath, oControlMaster, oControlPersist, | 156 | oSendEnv, oControlPath, oControlMaster, oControlPersist, |
156 | oHashKnownHosts, | 157 | oHashKnownHosts, |
157 | oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, | 158 | oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, |
158 | oVisualHostKey, oUseRoaming, | 159 | oVisualHostKey, |
159 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, | 160 | oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, |
160 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, | 161 | oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, |
161 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, | 162 | oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, |
@@ -217,6 +218,8 @@ static struct { | |||
217 | { "identityfile", oIdentityFile }, | 218 | { "identityfile", oIdentityFile }, |
218 | { "identityfile2", oIdentityFile }, /* obsolete */ | 219 | { "identityfile2", oIdentityFile }, /* obsolete */ |
219 | { "identitiesonly", oIdentitiesOnly }, | 220 | { "identitiesonly", oIdentitiesOnly }, |
221 | { "certificatefile", oCertificateFile }, | ||
222 | { "addkeystoagent", oAddKeysToAgent }, | ||
220 | { "hostname", oHostName }, | 223 | { "hostname", oHostName }, |
221 | { "hostkeyalias", oHostKeyAlias }, | 224 | { "hostkeyalias", oHostKeyAlias }, |
222 | { "proxycommand", oProxyCommand }, | 225 | { "proxycommand", oProxyCommand }, |
@@ -275,7 +278,7 @@ static struct { | |||
275 | { "localcommand", oLocalCommand }, | 278 | { "localcommand", oLocalCommand }, |
276 | { "permitlocalcommand", oPermitLocalCommand }, | 279 | { "permitlocalcommand", oPermitLocalCommand }, |
277 | { "visualhostkey", oVisualHostKey }, | 280 | { "visualhostkey", oVisualHostKey }, |
278 | { "useroaming", oUseRoaming }, | 281 | { "useroaming", oDeprecated }, |
279 | { "kexalgorithms", oKexAlgorithms }, | 282 | { "kexalgorithms", oKexAlgorithms }, |
280 | { "ipqos", oIPQoS }, | 283 | { "ipqos", oIPQoS }, |
281 | { "requesttty", oRequestTTY }, | 284 | { "requesttty", oRequestTTY }, |
@@ -383,6 +386,30 @@ clear_forwardings(Options *options) | |||
383 | } | 386 | } |
384 | 387 | ||
385 | void | 388 | void |
389 | add_certificate_file(Options *options, const char *path, int userprovided) | ||
390 | { | ||
391 | int i; | ||
392 | |||
393 | if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) | ||
394 | fatal("Too many certificate files specified (max %d)", | ||
395 | SSH_MAX_CERTIFICATE_FILES); | ||
396 | |||
397 | /* Avoid registering duplicates */ | ||
398 | for (i = 0; i < options->num_certificate_files; i++) { | ||
399 | if (options->certificate_file_userprovided[i] == userprovided && | ||
400 | strcmp(options->certificate_files[i], path) == 0) { | ||
401 | debug2("%s: ignoring duplicate key %s", __func__, path); | ||
402 | return; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | options->certificate_file_userprovided[options->num_certificate_files] = | ||
407 | userprovided; | ||
408 | options->certificate_files[options->num_certificate_files++] = | ||
409 | xstrdup(path); | ||
410 | } | ||
411 | |||
412 | void | ||
386 | add_identity_file(Options *options, const char *dir, const char *filename, | 413 | add_identity_file(Options *options, const char *dir, const char *filename, |
387 | int userprovided) | 414 | int userprovided) |
388 | { | 415 | { |
@@ -433,7 +460,7 @@ default_ssh_port(void) | |||
433 | static int | 460 | static int |
434 | execute_in_shell(const char *cmd) | 461 | execute_in_shell(const char *cmd) |
435 | { | 462 | { |
436 | char *shell, *command_string; | 463 | char *shell; |
437 | pid_t pid; | 464 | pid_t pid; |
438 | int devnull, status; | 465 | int devnull, status; |
439 | extern uid_t original_real_uid; | 466 | extern uid_t original_real_uid; |
@@ -441,12 +468,6 @@ execute_in_shell(const char *cmd) | |||
441 | if ((shell = getenv("SHELL")) == NULL) | 468 | if ((shell = getenv("SHELL")) == NULL) |
442 | shell = _PATH_BSHELL; | 469 | shell = _PATH_BSHELL; |
443 | 470 | ||
444 | /* | ||
445 | * Use "exec" to avoid "sh -c" processes on some platforms | ||
446 | * (e.g. Solaris) | ||
447 | */ | ||
448 | xasprintf(&command_string, "exec %s", cmd); | ||
449 | |||
450 | /* Need this to redirect subprocess stdin/out */ | 471 | /* Need this to redirect subprocess stdin/out */ |
451 | if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) | 472 | if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) |
452 | fatal("open(/dev/null): %s", strerror(errno)); | 473 | fatal("open(/dev/null): %s", strerror(errno)); |
@@ -471,7 +492,7 @@ execute_in_shell(const char *cmd) | |||
471 | 492 | ||
472 | argv[0] = shell; | 493 | argv[0] = shell; |
473 | argv[1] = "-c"; | 494 | argv[1] = "-c"; |
474 | argv[2] = command_string; | 495 | argv[2] = xstrdup(cmd); |
475 | argv[3] = NULL; | 496 | argv[3] = NULL; |
476 | 497 | ||
477 | execv(argv[0], argv); | 498 | execv(argv[0], argv); |
@@ -486,7 +507,6 @@ execute_in_shell(const char *cmd) | |||
486 | fatal("%s: fork: %.100s", __func__, strerror(errno)); | 507 | fatal("%s: fork: %.100s", __func__, strerror(errno)); |
487 | 508 | ||
488 | close(devnull); | 509 | close(devnull); |
489 | free(command_string); | ||
490 | 510 | ||
491 | while (waitpid(pid, &status, 0) == -1) { | 511 | while (waitpid(pid, &status, 0) == -1) { |
492 | if (errno != EINTR && errno != EAGAIN) | 512 | if (errno != EINTR && errno != EAGAIN) |
@@ -519,12 +539,15 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
519 | */ | 539 | */ |
520 | port = options->port <= 0 ? default_ssh_port() : options->port; | 540 | port = options->port <= 0 ? default_ssh_port() : options->port; |
521 | ruser = options->user == NULL ? pw->pw_name : options->user; | 541 | ruser = options->user == NULL ? pw->pw_name : options->user; |
522 | if (options->hostname != NULL) { | 542 | if (post_canon) { |
543 | host = xstrdup(options->hostname); | ||
544 | } else if (options->hostname != NULL) { | ||
523 | /* NB. Please keep in sync with ssh.c:main() */ | 545 | /* NB. Please keep in sync with ssh.c:main() */ |
524 | host = percent_expand(options->hostname, | 546 | host = percent_expand(options->hostname, |
525 | "h", host_arg, (char *)NULL); | 547 | "h", host_arg, (char *)NULL); |
526 | } else | 548 | } else { |
527 | host = xstrdup(host_arg); | 549 | host = xstrdup(host_arg); |
550 | } | ||
528 | 551 | ||
529 | debug2("checking match for '%s' host %s originally %s", | 552 | debug2("checking match for '%s' host %s originally %s", |
530 | cp, host, original_host); | 553 | cp, host, original_host); |
@@ -710,6 +733,15 @@ static const struct multistate multistate_yesnoask[] = { | |||
710 | { "ask", 2 }, | 733 | { "ask", 2 }, |
711 | { NULL, -1 } | 734 | { NULL, -1 } |
712 | }; | 735 | }; |
736 | static const struct multistate multistate_yesnoaskconfirm[] = { | ||
737 | { "true", 1 }, | ||
738 | { "false", 0 }, | ||
739 | { "yes", 1 }, | ||
740 | { "no", 0 }, | ||
741 | { "ask", 2 }, | ||
742 | { "confirm", 3 }, | ||
743 | { NULL, -1 } | ||
744 | }; | ||
713 | static const struct multistate multistate_addressfamily[] = { | 745 | static const struct multistate multistate_addressfamily[] = { |
714 | { "inet", AF_INET }, | 746 | { "inet", AF_INET }, |
715 | { "inet6", AF_INET6 }, | 747 | { "inet6", AF_INET6 }, |
@@ -984,16 +1016,12 @@ parse_time: | |||
984 | if (scan_scaled(arg, &val64) == -1) | 1016 | if (scan_scaled(arg, &val64) == -1) |
985 | fatal("%.200s line %d: Bad number '%s': %s", | 1017 | fatal("%.200s line %d: Bad number '%s': %s", |
986 | filename, linenum, arg, strerror(errno)); | 1018 | filename, linenum, arg, strerror(errno)); |
987 | /* check for too-large or too-small limits */ | ||
988 | if (val64 > UINT_MAX) | ||
989 | fatal("%.200s line %d: RekeyLimit too large", | ||
990 | filename, linenum); | ||
991 | if (val64 != 0 && val64 < 16) | 1019 | if (val64 != 0 && val64 < 16) |
992 | fatal("%.200s line %d: RekeyLimit too small", | 1020 | fatal("%.200s line %d: RekeyLimit too small", |
993 | filename, linenum); | 1021 | filename, linenum); |
994 | } | 1022 | } |
995 | if (*activep && options->rekey_limit == -1) | 1023 | if (*activep && options->rekey_limit == -1) |
996 | options->rekey_limit = (u_int32_t)val64; | 1024 | options->rekey_limit = val64; |
997 | if (s != NULL) { /* optional rekey interval present */ | 1025 | if (s != NULL) { /* optional rekey interval present */ |
998 | if (strcmp(s, "none") == 0) { | 1026 | if (strcmp(s, "none") == 0) { |
999 | (void)strdelim(&s); /* discard */ | 1027 | (void)strdelim(&s); /* discard */ |
@@ -1018,6 +1046,24 @@ parse_time: | |||
1018 | } | 1046 | } |
1019 | break; | 1047 | break; |
1020 | 1048 | ||
1049 | case oCertificateFile: | ||
1050 | arg = strdelim(&s); | ||
1051 | if (!arg || *arg == '\0') | ||
1052 | fatal("%.200s line %d: Missing argument.", | ||
1053 | filename, linenum); | ||
1054 | if (*activep) { | ||
1055 | intptr = &options->num_certificate_files; | ||
1056 | if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { | ||
1057 | fatal("%.200s line %d: Too many certificate " | ||
1058 | "files specified (max %d).", | ||
1059 | filename, linenum, | ||
1060 | SSH_MAX_CERTIFICATE_FILES); | ||
1061 | } | ||
1062 | add_certificate_file(options, arg, | ||
1063 | flags & SSHCONF_USERCONF); | ||
1064 | } | ||
1065 | break; | ||
1066 | |||
1021 | case oXAuthLocation: | 1067 | case oXAuthLocation: |
1022 | charptr=&options->xauth_location; | 1068 | charptr=&options->xauth_location; |
1023 | goto parse_string; | 1069 | goto parse_string; |
@@ -1417,10 +1463,6 @@ parse_keytypes: | |||
1417 | } | 1463 | } |
1418 | break; | 1464 | break; |
1419 | 1465 | ||
1420 | case oUseRoaming: | ||
1421 | intptr = &options->use_roaming; | ||
1422 | goto parse_flag; | ||
1423 | |||
1424 | case oRequestTTY: | 1466 | case oRequestTTY: |
1425 | intptr = &options->request_tty; | 1467 | intptr = &options->request_tty; |
1426 | multistate_ptr = multistate_requesttty; | 1468 | multistate_ptr = multistate_requesttty; |
@@ -1535,6 +1577,11 @@ parse_keytypes: | |||
1535 | charptr = &options->pubkey_key_types; | 1577 | charptr = &options->pubkey_key_types; |
1536 | goto parse_keytypes; | 1578 | goto parse_keytypes; |
1537 | 1579 | ||
1580 | case oAddKeysToAgent: | ||
1581 | intptr = &options->add_keys_to_agent; | ||
1582 | multistate_ptr = multistate_yesnoaskconfirm; | ||
1583 | goto parse_multistate; | ||
1584 | |||
1538 | case oDeprecated: | 1585 | case oDeprecated: |
1539 | debug("%s line %d: Deprecated option \"%s\"", | 1586 | debug("%s line %d: Deprecated option \"%s\"", |
1540 | filename, linenum, keyword); | 1587 | filename, linenum, keyword); |
@@ -1668,6 +1715,7 @@ initialize_options(Options * options) | |||
1668 | options->hostkeyalgorithms = NULL; | 1715 | options->hostkeyalgorithms = NULL; |
1669 | options->protocol = SSH_PROTO_UNKNOWN; | 1716 | options->protocol = SSH_PROTO_UNKNOWN; |
1670 | options->num_identity_files = 0; | 1717 | options->num_identity_files = 0; |
1718 | options->num_certificate_files = 0; | ||
1671 | options->hostname = NULL; | 1719 | options->hostname = NULL; |
1672 | options->host_key_alias = NULL; | 1720 | options->host_key_alias = NULL; |
1673 | options->proxy_command = NULL; | 1721 | options->proxy_command = NULL; |
@@ -1703,7 +1751,7 @@ initialize_options(Options * options) | |||
1703 | options->tun_remote = -1; | 1751 | options->tun_remote = -1; |
1704 | options->local_command = NULL; | 1752 | options->local_command = NULL; |
1705 | options->permit_local_command = -1; | 1753 | options->permit_local_command = -1; |
1706 | options->use_roaming = 0; | 1754 | options->add_keys_to_agent = -1; |
1707 | options->visual_host_key = -1; | 1755 | options->visual_host_key = -1; |
1708 | options->ip_qos_interactive = -1; | 1756 | options->ip_qos_interactive = -1; |
1709 | options->ip_qos_bulk = -1; | 1757 | options->ip_qos_bulk = -1; |
@@ -1814,6 +1862,8 @@ fill_default_options(Options * options) | |||
1814 | /* options->hostkeyalgorithms, default set in myproposals.h */ | 1862 | /* options->hostkeyalgorithms, default set in myproposals.h */ |
1815 | if (options->protocol == SSH_PROTO_UNKNOWN) | 1863 | if (options->protocol == SSH_PROTO_UNKNOWN) |
1816 | options->protocol = SSH_PROTO_2; | 1864 | options->protocol = SSH_PROTO_2; |
1865 | if (options->add_keys_to_agent == -1) | ||
1866 | options->add_keys_to_agent = 0; | ||
1817 | if (options->num_identity_files == 0) { | 1867 | if (options->num_identity_files == 0) { |
1818 | if (options->protocol & SSH_PROTO_1) { | 1868 | if (options->protocol & SSH_PROTO_1) { |
1819 | add_identity_file(options, "~/", | 1869 | add_identity_file(options, "~/", |
@@ -1887,7 +1937,6 @@ fill_default_options(Options * options) | |||
1887 | options->tun_remote = SSH_TUNID_ANY; | 1937 | options->tun_remote = SSH_TUNID_ANY; |
1888 | if (options->permit_local_command == -1) | 1938 | if (options->permit_local_command == -1) |
1889 | options->permit_local_command = 0; | 1939 | options->permit_local_command = 0; |
1890 | options->use_roaming = 0; | ||
1891 | if (options->visual_host_key == -1) | 1940 | if (options->visual_host_key == -1) |
1892 | options->visual_host_key = 0; | 1941 | options->visual_host_key = 0; |
1893 | if (options->ip_qos_interactive == -1) | 1942 | if (options->ip_qos_interactive == -1) |
@@ -2296,6 +2345,10 @@ dump_client_config(Options *o, const char *host) | |||
2296 | int i; | 2345 | int i; |
2297 | char vbuf[5]; | 2346 | char vbuf[5]; |
2298 | 2347 | ||
2348 | /* This is normally prepared in ssh_kex2 */ | ||
2349 | if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) | ||
2350 | fatal("%s: kex_assemble_names failed", __func__); | ||
2351 | |||
2299 | /* Most interesting options first: user, host, port */ | 2352 | /* Most interesting options first: user, host, port */ |
2300 | dump_cfg_string(oUser, o->user); | 2353 | dump_cfg_string(oUser, o->user); |
2301 | dump_cfg_string(oHostName, host); | 2354 | dump_cfg_string(oHostName, host); |
@@ -2356,7 +2409,7 @@ dump_client_config(Options *o, const char *host) | |||
2356 | dump_cfg_string(oBindAddress, o->bind_address); | 2409 | dump_cfg_string(oBindAddress, o->bind_address); |
2357 | dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); | 2410 | dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); |
2358 | dump_cfg_string(oControlPath, o->control_path); | 2411 | dump_cfg_string(oControlPath, o->control_path); |
2359 | dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); | 2412 | dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); |
2360 | dump_cfg_string(oHostKeyAlias, o->host_key_alias); | 2413 | dump_cfg_string(oHostKeyAlias, o->host_key_alias); |
2361 | dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); | 2414 | dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); |
2362 | dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); | 2415 | dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); |
@@ -2367,6 +2420,7 @@ dump_client_config(Options *o, const char *host) | |||
2367 | dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); | 2420 | dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); |
2368 | dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); | 2421 | dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); |
2369 | dump_cfg_string(oProxyCommand, o->proxy_command); | 2422 | dump_cfg_string(oProxyCommand, o->proxy_command); |
2423 | dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); | ||
2370 | dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); | 2424 | dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); |
2371 | dump_cfg_string(oXAuthLocation, o->xauth_location); | 2425 | dump_cfg_string(oXAuthLocation, o->xauth_location); |
2372 | 2426 | ||
@@ -2435,8 +2489,8 @@ dump_client_config(Options *o, const char *host) | |||
2435 | printf("%s\n", iptos2str(o->ip_qos_bulk)); | 2489 | printf("%s\n", iptos2str(o->ip_qos_bulk)); |
2436 | 2490 | ||
2437 | /* oRekeyLimit */ | 2491 | /* oRekeyLimit */ |
2438 | printf("rekeylimit %lld %d\n", | 2492 | printf("rekeylimit %llu %d\n", |
2439 | (long long)o->rekey_limit, o->rekey_interval); | 2493 | (unsigned long long)o->rekey_limit, o->rekey_interval); |
2440 | 2494 | ||
2441 | /* oStreamLocalBindMask */ | 2495 | /* oStreamLocalBindMask */ |
2442 | printf("streamlocalbindmask 0%o\n", | 2496 | printf("streamlocalbindmask 0%o\n", |