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 9a646dcaa..c60df5602 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 |
@@ -683,7 +683,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
683 | if (r == (negate ? 1 : 0)) | 683 | if (r == (negate ? 1 : 0)) |
684 | this_result = result = 0; | 684 | this_result = result = 0; |
685 | } else if (strcasecmp(attrib, "exec") == 0) { | 685 | } else if (strcasecmp(attrib, "exec") == 0) { |
686 | char *conn_hash_hex; | 686 | char *conn_hash_hex, *keyalias; |
687 | 687 | ||
688 | if (gethostname(thishost, sizeof(thishost)) == -1) | 688 | if (gethostname(thishost, sizeof(thishost)) == -1) |
689 | fatal("gethostname: %s", strerror(errno)); | 689 | fatal("gethostname: %s", strerror(errno)); |
@@ -694,12 +694,15 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
694 | (unsigned long long)pw->pw_uid); | 694 | (unsigned long long)pw->pw_uid); |
695 | conn_hash_hex = ssh_connection_hash(thishost, host, | 695 | conn_hash_hex = ssh_connection_hash(thishost, host, |
696 | portstr, ruser); | 696 | portstr, ruser); |
697 | keyalias = options->host_key_alias ? | ||
698 | options->host_key_alias : host; | ||
697 | 699 | ||
698 | cmd = percent_expand(arg, | 700 | cmd = percent_expand(arg, |
699 | "C", conn_hash_hex, | 701 | "C", conn_hash_hex, |
700 | "L", shorthost, | 702 | "L", shorthost, |
701 | "d", pw->pw_dir, | 703 | "d", pw->pw_dir, |
702 | "h", host, | 704 | "h", host, |
705 | "k", keyalias, | ||
703 | "l", thishost, | 706 | "l", thishost, |
704 | "n", original_host, | 707 | "n", original_host, |
705 | "p", portstr, | 708 | "p", portstr, |
@@ -754,7 +757,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, | |||
754 | static void | 757 | static void |
755 | rm_env(Options *options, const char *arg, const char *filename, int linenum) | 758 | rm_env(Options *options, const char *arg, const char *filename, int linenum) |
756 | { | 759 | { |
757 | int i, j; | 760 | int i, j, onum_send_env = options->num_send_env; |
758 | char *cp; | 761 | char *cp; |
759 | 762 | ||
760 | /* Remove an environment variable */ | 763 | /* Remove an environment variable */ |
@@ -777,6 +780,11 @@ rm_env(Options *options, const char *arg, const char *filename, int linenum) | |||
777 | options->num_send_env--; | 780 | options->num_send_env--; |
778 | /* NB. don't increment i */ | 781 | /* NB. don't increment i */ |
779 | } | 782 | } |
783 | if (onum_send_env != options->num_send_env) { | ||
784 | options->send_env = xrecallocarray(options->send_env, | ||
785 | onum_send_env, options->num_send_env, | ||
786 | sizeof(*options->send_env)); | ||
787 | } | ||
780 | } | 788 | } |
781 | 789 | ||
782 | /* | 790 | /* |
@@ -888,6 +896,21 @@ static const struct multistate multistate_compression[] = { | |||
888 | { NULL, -1 } | 896 | { NULL, -1 } |
889 | }; | 897 | }; |
890 | 898 | ||
899 | static int | ||
900 | parse_multistate_value(const char *arg, const char *filename, int linenum, | ||
901 | const struct multistate *multistate_ptr) | ||
902 | { | ||
903 | int i; | ||
904 | |||
905 | if (!arg || *arg == '\0') | ||
906 | fatal("%s line %d: missing argument.", filename, linenum); | ||
907 | for (i = 0; multistate_ptr[i].key != NULL; i++) { | ||
908 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) | ||
909 | return multistate_ptr[i].value; | ||
910 | } | ||
911 | return -1; | ||
912 | } | ||
913 | |||
891 | /* | 914 | /* |
892 | * Processes a single option line as used in the configuration files. This | 915 | * Processes a single option line as used in the configuration files. This |
893 | * only sets those values that have not already been set. | 916 | * only sets those values that have not already been set. |
@@ -1011,19 +1034,11 @@ parse_time: | |||
1011 | multistate_ptr = multistate_flag; | 1034 | multistate_ptr = multistate_flag; |
1012 | parse_multistate: | 1035 | parse_multistate: |
1013 | arg = strdelim(&s); | 1036 | arg = strdelim(&s); |
1014 | if (!arg || *arg == '\0') | 1037 | if ((value = parse_multistate_value(arg, filename, linenum, |
1015 | fatal("%s line %d: missing argument.", | 1038 | multistate_ptr)) == -1) { |
1016 | filename, linenum); | ||
1017 | value = -1; | ||
1018 | for (i = 0; multistate_ptr[i].key != NULL; i++) { | ||
1019 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) { | ||
1020 | value = multistate_ptr[i].value; | ||
1021 | break; | ||
1022 | } | ||
1023 | } | ||
1024 | if (value == -1) | ||
1025 | fatal("%s line %d: unsupported option \"%s\".", | 1039 | fatal("%s line %d: unsupported option \"%s\".", |
1026 | filename, linenum, arg); | 1040 | filename, linenum, arg); |
1041 | } | ||
1027 | if (*activep && *intptr == -1) | 1042 | if (*activep && *intptr == -1) |
1028 | *intptr = value; | 1043 | *intptr = value; |
1029 | break; | 1044 | break; |
@@ -1845,9 +1860,30 @@ parse_keytypes: | |||
1845 | goto parse_keytypes; | 1860 | goto parse_keytypes; |
1846 | 1861 | ||
1847 | case oAddKeysToAgent: | 1862 | case oAddKeysToAgent: |
1848 | intptr = &options->add_keys_to_agent; | 1863 | arg = strdelim(&s); |
1849 | multistate_ptr = multistate_yesnoaskconfirm; | 1864 | arg2 = strdelim(&s); |
1850 | goto parse_multistate; | 1865 | value = parse_multistate_value(arg, filename, linenum, |
1866 | multistate_yesnoaskconfirm); | ||
1867 | value2 = 0; /* unlimited lifespan by default */ | ||
1868 | if (value == 3 && arg2 != NULL) { | ||
1869 | /* allow "AddKeysToAgent confirm 5m" */ | ||
1870 | if ((value2 = convtime(arg2)) == -1 || value2 > INT_MAX) | ||
1871 | fatal("%s line %d: invalid time value.", | ||
1872 | filename, linenum); | ||
1873 | } else if (value == -1 && arg2 == NULL) { | ||
1874 | if ((value2 = convtime(arg)) == -1 || value2 > INT_MAX) | ||
1875 | fatal("%s line %d: unsupported option", | ||
1876 | filename, linenum); | ||
1877 | value = 1; /* yes */ | ||
1878 | } else if (value == -1 || arg2 != NULL) { | ||
1879 | fatal("%s line %d: unsupported option", | ||
1880 | filename, linenum); | ||
1881 | } | ||
1882 | if (*activep && options->add_keys_to_agent == -1) { | ||
1883 | options->add_keys_to_agent = value; | ||
1884 | options->add_keys_to_agent_lifespan = value2; | ||
1885 | } | ||
1886 | break; | ||
1851 | 1887 | ||
1852 | case oIdentityAgent: | 1888 | case oIdentityAgent: |
1853 | charptr = &options->identity_agent; | 1889 | charptr = &options->identity_agent; |
@@ -1857,7 +1893,12 @@ parse_keytypes: | |||
1857 | filename, linenum); | 1893 | filename, linenum); |
1858 | parse_agent_path: | 1894 | parse_agent_path: |
1859 | /* Extra validation if the string represents an env var. */ | 1895 | /* Extra validation if the string represents an env var. */ |
1860 | if (arg[0] == '$' && !valid_env_name(arg + 1)) { | 1896 | if ((arg2 = dollar_expand(&r, arg)) == NULL || r) |
1897 | fatal("%.200s line %d: Invalid environment expansion " | ||
1898 | "%s.", filename, linenum, arg); | ||
1899 | free(arg2); | ||
1900 | /* check for legacy environment format */ | ||
1901 | if (arg[0] == '$' && arg[1] != '{' && !valid_env_name(arg + 1)) { | ||
1861 | fatal("%.200s line %d: Invalid environment name %s.", | 1902 | fatal("%.200s line %d: Invalid environment name %s.", |
1862 | filename, linenum, arg); | 1903 | filename, linenum, arg); |
1863 | } | 1904 | } |
@@ -2061,6 +2102,7 @@ initialize_options(Options * options) | |||
2061 | options->permit_local_command = -1; | 2102 | options->permit_local_command = -1; |
2062 | options->remote_command = NULL; | 2103 | options->remote_command = NULL; |
2063 | options->add_keys_to_agent = -1; | 2104 | options->add_keys_to_agent = -1; |
2105 | options->add_keys_to_agent_lifespan = -1; | ||
2064 | options->identity_agent = NULL; | 2106 | options->identity_agent = NULL; |
2065 | options->visual_host_key = -1; | 2107 | options->visual_host_key = -1; |
2066 | options->ip_qos_interactive = -1; | 2108 | options->ip_qos_interactive = -1; |
@@ -2178,8 +2220,10 @@ fill_default_options(Options * options) | |||
2178 | if (options->number_of_password_prompts == -1) | 2220 | if (options->number_of_password_prompts == -1) |
2179 | options->number_of_password_prompts = 3; | 2221 | options->number_of_password_prompts = 3; |
2180 | /* options->hostkeyalgorithms, default set in myproposals.h */ | 2222 | /* options->hostkeyalgorithms, default set in myproposals.h */ |
2181 | if (options->add_keys_to_agent == -1) | 2223 | if (options->add_keys_to_agent == -1) { |
2182 | options->add_keys_to_agent = 0; | 2224 | options->add_keys_to_agent = 0; |
2225 | options->add_keys_to_agent_lifespan = 0; | ||
2226 | } | ||
2183 | if (options->num_identity_files == 0) { | 2227 | if (options->num_identity_files == 0) { |
2184 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); | 2228 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); |
2185 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); | 2229 | add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); |
@@ -2284,11 +2328,11 @@ fill_default_options(Options * options) | |||
2284 | all_key = sshkey_alg_list(0, 0, 1, ','); | 2328 | all_key = sshkey_alg_list(0, 0, 1, ','); |
2285 | all_sig = sshkey_alg_list(0, 1, 1, ','); | 2329 | all_sig = sshkey_alg_list(0, 1, 1, ','); |
2286 | /* remove unsupported algos from default lists */ | 2330 | /* remove unsupported algos from default lists */ |
2287 | def_cipher = match_filter_whitelist(KEX_CLIENT_ENCRYPT, all_cipher); | 2331 | def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); |
2288 | def_mac = match_filter_whitelist(KEX_CLIENT_MAC, all_mac); | 2332 | def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); |
2289 | def_kex = match_filter_whitelist(KEX_CLIENT_KEX, all_kex); | 2333 | def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); |
2290 | def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); | 2334 | def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); |
2291 | def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); | 2335 | def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); |
2292 | #define ASSEMBLE(what, defaults, all) \ | 2336 | #define ASSEMBLE(what, defaults, all) \ |
2293 | do { \ | 2337 | do { \ |
2294 | if ((r = kex_assemble_names(&options->what, \ | 2338 | if ((r = kex_assemble_names(&options->what, \ |
@@ -2423,12 +2467,19 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo | |||
2423 | { | 2467 | { |
2424 | struct fwdarg fwdargs[4]; | 2468 | struct fwdarg fwdargs[4]; |
2425 | char *p, *cp; | 2469 | char *p, *cp; |
2426 | int i; | 2470 | int i, err; |
2427 | 2471 | ||
2428 | memset(fwd, 0, sizeof(*fwd)); | 2472 | memset(fwd, 0, sizeof(*fwd)); |
2429 | memset(fwdargs, 0, sizeof(fwdargs)); | 2473 | memset(fwdargs, 0, sizeof(fwdargs)); |
2430 | 2474 | ||
2431 | cp = p = xstrdup(fwdspec); | 2475 | /* |
2476 | * We expand environment variables before checking if we think they're | ||
2477 | * paths so that if ${VAR} expands to a fully qualified path it is | ||
2478 | * treated as a path. | ||
2479 | */ | ||
2480 | cp = p = dollar_expand(&err, fwdspec); | ||
2481 | if (p == NULL || err) | ||
2482 | return 0; | ||
2432 | 2483 | ||
2433 | /* skip leading spaces */ | 2484 | /* skip leading spaces */ |
2434 | while (isspace((u_char)*cp)) | 2485 | while (isspace((u_char)*cp)) |
@@ -2781,7 +2832,6 @@ dump_client_config(Options *o, const char *host) | |||
2781 | dump_cfg_int(oPort, o->port); | 2832 | dump_cfg_int(oPort, o->port); |
2782 | 2833 | ||
2783 | /* Flag options */ | 2834 | /* Flag options */ |
2784 | dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); | ||
2785 | dump_cfg_fmtint(oAddressFamily, o->address_family); | 2835 | dump_cfg_fmtint(oAddressFamily, o->address_family); |
2786 | dump_cfg_fmtint(oBatchMode, o->batch_mode); | 2836 | dump_cfg_fmtint(oBatchMode, o->batch_mode); |
2787 | dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); | 2837 | dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); |
@@ -2876,6 +2926,15 @@ dump_client_config(Options *o, const char *host) | |||
2876 | 2926 | ||
2877 | /* Special cases */ | 2927 | /* Special cases */ |
2878 | 2928 | ||
2929 | /* AddKeysToAgent */ | ||
2930 | if (o->add_keys_to_agent_lifespan <= 0) | ||
2931 | dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); | ||
2932 | else { | ||
2933 | printf("addkeystoagent%s %d\n", | ||
2934 | o->add_keys_to_agent == 3 ? " confirm" : "", | ||
2935 | o->add_keys_to_agent_lifespan); | ||
2936 | } | ||
2937 | |||
2879 | /* oForwardAgent */ | 2938 | /* oForwardAgent */ |
2880 | if (o->forward_agent_sock_path == NULL) | 2939 | if (o->forward_agent_sock_path == NULL) |
2881 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); | 2940 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); |