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 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,
754static void 757static void
755rm_env(Options *options, const char *arg, const char *filename, int linenum) 758rm_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
899static int
900parse_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);