diff options
Diffstat (limited to 'readconf.c')
-rw-r--r-- | readconf.c | 113 |
1 files changed, 86 insertions, 27 deletions
diff --git a/readconf.c b/readconf.c index 2afcbaeca..554efd7c9 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.329 2020/04/24 03:33:21 dtucker Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.335 2020/08/27 02:11:09 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 |
@@ -664,7 +664,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
664 | if (r == (negate ? 1 : 0)) | 664 | if (r == (negate ? 1 : 0)) |
665 | this_result = result = 0; | 665 | this_result = result = 0; |
666 | } else if (strcasecmp(attrib, "exec") == 0) { | 666 | } else if (strcasecmp(attrib, "exec") == 0) { |
667 | char *conn_hash_hex; | 667 | char *conn_hash_hex, *keyalias; |
668 | 668 | ||
669 | if (gethostname(thishost, sizeof(thishost)) == -1) | 669 | if (gethostname(thishost, sizeof(thishost)) == -1) |
670 | fatal("gethostname: %s", strerror(errno)); | 670 | fatal("gethostname: %s", strerror(errno)); |
@@ -675,12 +675,15 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
675 | (unsigned long long)pw->pw_uid); | 675 | (unsigned long long)pw->pw_uid); |
676 | conn_hash_hex = ssh_connection_hash(thishost, host, | 676 | conn_hash_hex = ssh_connection_hash(thishost, host, |
677 | portstr, ruser); | 677 | portstr, ruser); |
678 | keyalias = options->host_key_alias ? | ||
679 | options->host_key_alias : host; | ||
678 | 680 | ||
679 | cmd = percent_expand(arg, | 681 | cmd = percent_expand(arg, |
680 | "C", conn_hash_hex, | 682 | "C", conn_hash_hex, |
681 | "L", shorthost, | 683 | "L", shorthost, |
682 | "d", pw->pw_dir, | 684 | "d", pw->pw_dir, |
683 | "h", host, | 685 | "h", host, |
686 | "k", keyalias, | ||
684 | "l", thishost, | 687 | "l", thishost, |
685 | "n", original_host, | 688 | "n", original_host, |
686 | "p", portstr, | 689 | "p", portstr, |
@@ -735,7 +738,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
735 | static void | 738 | static void |
736 | rm_env(Options *options, const char *arg, const char *filename, int linenum) | 739 | rm_env(Options *options, const char *arg, const char *filename, int linenum) |
737 | { | 740 | { |
738 | int i, j; | 741 | int i, j, onum_send_env = options->num_send_env; |
739 | char *cp; | 742 | char *cp; |
740 | 743 | ||
741 | /* Remove an environment variable */ | 744 | /* Remove an environment variable */ |
@@ -758,6 +761,11 @@ rm_env(Options *options, const char *arg, const char *filename, int linenum) | |||
758 | options->num_send_env--; | 761 | options->num_send_env--; |
759 | /* NB. don't increment i */ | 762 | /* NB. don't increment i */ |
760 | } | 763 | } |
764 | if (onum_send_env != options->num_send_env) { | ||
765 | options->send_env = xrecallocarray(options->send_env, | ||
766 | onum_send_env, options->num_send_env, | ||
767 | sizeof(*options->send_env)); | ||
768 | } | ||
761 | } | 769 | } |
762 | 770 | ||
763 | /* | 771 | /* |
@@ -869,6 +877,21 @@ static const struct multistate multistate_compression[] = { | |||
869 | { NULL, -1 } | 877 | { NULL, -1 } |
870 | }; | 878 | }; |
871 | 879 | ||
880 | static int | ||
881 | parse_multistate_value(const char *arg, const char *filename, int linenum, | ||
882 | const struct multistate *multistate_ptr) | ||
883 | { | ||
884 | int i; | ||
885 | |||
886 | if (!arg || *arg == '\0') | ||
887 | fatal("%s line %d: missing argument.", filename, linenum); | ||
888 | for (i = 0; multistate_ptr[i].key != NULL; i++) { | ||
889 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) | ||
890 | return multistate_ptr[i].value; | ||
891 | } | ||
892 | return -1; | ||
893 | } | ||
894 | |||
872 | /* | 895 | /* |
873 | * Processes a single option line as used in the configuration files. This | 896 | * Processes a single option line as used in the configuration files. This |
874 | * only sets those values that have not already been set. | 897 | * only sets those values that have not already been set. |
@@ -992,19 +1015,11 @@ parse_time: | |||
992 | multistate_ptr = multistate_flag; | 1015 | multistate_ptr = multistate_flag; |
993 | parse_multistate: | 1016 | parse_multistate: |
994 | arg = strdelim(&s); | 1017 | arg = strdelim(&s); |
995 | if (!arg || *arg == '\0') | 1018 | if ((value = parse_multistate_value(arg, filename, linenum, |
996 | fatal("%s line %d: missing argument.", | 1019 | multistate_ptr)) == -1) { |
997 | filename, linenum); | ||
998 | value = -1; | ||
999 | for (i = 0; multistate_ptr[i].key != NULL; i++) { | ||
1000 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) { | ||
1001 | value = multistate_ptr[i].value; | ||
1002 | break; | ||
1003 | } | ||
1004 | } | ||
1005 | if (value == -1) | ||
1006 | fatal("%s line %d: unsupported option \"%s\".", | 1020 | fatal("%s line %d: unsupported option \"%s\".", |
1007 | filename, linenum, arg); | 1021 | filename, linenum, arg); |
1022 | } | ||
1008 | if (*activep && *intptr == -1) | 1023 | if (*activep && *intptr == -1) |
1009 | *intptr = value; | 1024 | *intptr = value; |
1010 | break; | 1025 | break; |
@@ -1792,9 +1807,30 @@ parse_keytypes: | |||
1792 | goto parse_keytypes; | 1807 | goto parse_keytypes; |
1793 | 1808 | ||
1794 | case oAddKeysToAgent: | 1809 | case oAddKeysToAgent: |
1795 | intptr = &options->add_keys_to_agent; | 1810 | arg = strdelim(&s); |
1796 | multistate_ptr = multistate_yesnoaskconfirm; | 1811 | arg2 = strdelim(&s); |
1797 | goto parse_multistate; | 1812 | value = parse_multistate_value(arg, filename, linenum, |
1813 | multistate_yesnoaskconfirm); | ||
1814 | value2 = 0; /* unlimited lifespan by default */ | ||
1815 | if (value == 3 && arg2 != NULL) { | ||
1816 | /* allow "AddKeysToAgent confirm 5m" */ | ||
1817 | if ((value2 = convtime(arg2)) == -1 || value2 > INT_MAX) | ||
1818 | fatal("%s line %d: invalid time value.", | ||
1819 | filename, linenum); | ||
1820 | } else if (value == -1 && arg2 == NULL) { | ||
1821 | if ((value2 = convtime(arg)) == -1 || value2 > INT_MAX) | ||
1822 | fatal("%s line %d: unsupported option", | ||
1823 | filename, linenum); | ||
1824 | value = 1; /* yes */ | ||
1825 | } else if (value == -1 || arg2 != NULL) { | ||
1826 | fatal("%s line %d: unsupported option", | ||
1827 | filename, linenum); | ||
1828 | } | ||
1829 | if (*activep && options->add_keys_to_agent == -1) { | ||
1830 | options->add_keys_to_agent = value; | ||
1831 | options->add_keys_to_agent_lifespan = value2; | ||
1832 | } | ||
1833 | break; | ||
1798 | 1834 | ||
1799 | case oIdentityAgent: | 1835 | case oIdentityAgent: |
1800 | charptr = &options->identity_agent; | 1836 | charptr = &options->identity_agent; |
@@ -1804,7 +1840,12 @@ parse_keytypes: | |||
1804 | filename, linenum); | 1840 | filename, linenum); |
1805 | parse_agent_path: | 1841 | parse_agent_path: |
1806 | /* Extra validation if the string represents an env var. */ | 1842 | /* Extra validation if the string represents an env var. */ |
1807 | if (arg[0] == '$' && !valid_env_name(arg + 1)) { | 1843 | if ((arg2 = dollar_expand(&r, arg)) == NULL || r) |
1844 | fatal("%.200s line %d: Invalid environment expansion " | ||
1845 | "%s.", filename, linenum, arg); | ||
1846 | free(arg2); | ||
1847 | /* check for legacy environment format */ | ||
1848 | if (arg[0] == '$' && arg[1] != '{' && !valid_env_name(arg + 1)) { | ||
1808 | fatal("%.200s line %d: Invalid environment name %s.", | 1849 | fatal("%.200s line %d: Invalid environment name %s.", |
1809 | filename, linenum, arg); | 1850 | filename, linenum, arg); |
1810 | } | 1851 | } |
@@ -2003,6 +2044,7 @@ initialize_options(Options * options) | |||
2003 | options->permit_local_command = -1; | 2044 | options->permit_local_command = -1; |
2004 | options->remote_command = NULL; | 2045 | options->remote_command = NULL; |
2005 | options->add_keys_to_agent = -1; | 2046 | options->add_keys_to_agent = -1; |
2047 | options->add_keys_to_agent_lifespan = -1; | ||
2006 | options->identity_agent = NULL; | 2048 | options->identity_agent = NULL; |
2007 | options->visual_host_key = -1; | 2049 | options->visual_host_key = -1; |
2008 | options->ip_qos_interactive = -1; | 2050 | options->ip_qos_interactive = -1; |
@@ -2110,8 +2152,10 @@ fill_default_options(Options * options) | |||
2110 | if (options->number_of_password_prompts == -1) | 2152 | if (options->number_of_password_prompts == -1) |
2111 | options->number_of_password_prompts = 3; | 2153 | options->number_of_password_prompts = 3; |
2112 | /* options->hostkeyalgorithms, default set in myproposals.h */ | 2154 | /* options->hostkeyalgorithms, default set in myproposals.h */ |
2113 | if (options->add_keys_to_agent == -1) | 2155 | if (options->add_keys_to_agent == -1) { |
2114 | options->add_keys_to_agent = 0; | 2156 | options->add_keys_to_agent = 0; |
2157 | options->add_keys_to_agent_lifespan = 0; | ||
2158 | } | ||
2115 | if (options->num_identity_files == 0) { | 2159 | if (options->num_identity_files == 0) { |
2116 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); | 2160 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); |
2117 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); | 2161 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); |
@@ -2211,11 +2255,11 @@ fill_default_options(Options * options) | |||
2211 | all_key = sshkey_alg_list(0, 0, 1, ','); | 2255 | all_key = sshkey_alg_list(0, 0, 1, ','); |
2212 | all_sig = sshkey_alg_list(0, 1, 1, ','); | 2256 | all_sig = sshkey_alg_list(0, 1, 1, ','); |
2213 | /* remove unsupported algos from default lists */ | 2257 | /* remove unsupported algos from default lists */ |
2214 | def_cipher = match_filter_whitelist(KEX_CLIENT_ENCRYPT, all_cipher); | 2258 | def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); |
2215 | def_mac = match_filter_whitelist(KEX_CLIENT_MAC, all_mac); | 2259 | def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); |
2216 | def_kex = match_filter_whitelist(KEX_CLIENT_KEX, all_kex); | 2260 | def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); |
2217 | def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); | 2261 | def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); |
2218 | def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); | 2262 | def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); |
2219 | #define ASSEMBLE(what, defaults, all) \ | 2263 | #define ASSEMBLE(what, defaults, all) \ |
2220 | do { \ | 2264 | do { \ |
2221 | if ((r = kex_assemble_names(&options->what, \ | 2265 | if ((r = kex_assemble_names(&options->what, \ |
@@ -2350,12 +2394,19 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo | |||
2350 | { | 2394 | { |
2351 | struct fwdarg fwdargs[4]; | 2395 | struct fwdarg fwdargs[4]; |
2352 | char *p, *cp; | 2396 | char *p, *cp; |
2353 | int i; | 2397 | int i, err; |
2354 | 2398 | ||
2355 | memset(fwd, 0, sizeof(*fwd)); | 2399 | memset(fwd, 0, sizeof(*fwd)); |
2356 | memset(fwdargs, 0, sizeof(fwdargs)); | 2400 | memset(fwdargs, 0, sizeof(fwdargs)); |
2357 | 2401 | ||
2358 | cp = p = xstrdup(fwdspec); | 2402 | /* |
2403 | * We expand environment variables before checking if we think they're | ||
2404 | * paths so that if ${VAR} expands to a fully qualified path it is | ||
2405 | * treated as a path. | ||
2406 | */ | ||
2407 | cp = p = dollar_expand(&err, fwdspec); | ||
2408 | if (p == NULL || err) | ||
2409 | return 0; | ||
2359 | 2410 | ||
2360 | /* skip leading spaces */ | 2411 | /* skip leading spaces */ |
2361 | while (isspace((u_char)*cp)) | 2412 | while (isspace((u_char)*cp)) |
@@ -2708,7 +2759,6 @@ dump_client_config(Options *o, const char *host) | |||
2708 | dump_cfg_int(oPort, o->port); | 2759 | dump_cfg_int(oPort, o->port); |
2709 | 2760 | ||
2710 | /* Flag options */ | 2761 | /* Flag options */ |
2711 | dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); | ||
2712 | dump_cfg_fmtint(oAddressFamily, o->address_family); | 2762 | dump_cfg_fmtint(oAddressFamily, o->address_family); |
2713 | dump_cfg_fmtint(oBatchMode, o->batch_mode); | 2763 | dump_cfg_fmtint(oBatchMode, o->batch_mode); |
2714 | dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); | 2764 | dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); |
@@ -2796,6 +2846,15 @@ dump_client_config(Options *o, const char *host) | |||
2796 | 2846 | ||
2797 | /* Special cases */ | 2847 | /* Special cases */ |
2798 | 2848 | ||
2849 | /* AddKeysToAgent */ | ||
2850 | if (o->add_keys_to_agent_lifespan <= 0) | ||
2851 | dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); | ||
2852 | else { | ||
2853 | printf("addkeystoagent%s %d\n", | ||
2854 | o->add_keys_to_agent == 3 ? " confirm" : "", | ||
2855 | o->add_keys_to_agent_lifespan); | ||
2856 | } | ||
2857 | |||
2799 | /* oForwardAgent */ | 2858 | /* oForwardAgent */ |
2800 | if (o->forward_agent_sock_path == NULL) | 2859 | if (o->forward_agent_sock_path == NULL) |
2801 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); | 2860 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); |