summaryrefslogtreecommitdiff
path: root/readconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'readconf.c')
-rw-r--r--readconf.c113
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,
735static void 738static void
736rm_env(Options *options, const char *arg, const char *filename, int linenum) 739rm_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
880static int
881parse_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);