summaryrefslogtreecommitdiffstats
path: root/readconf.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--readconf.c165
1 files changed, 102 insertions, 63 deletions
diff --git a/readconf.c b/readconf.c
index a2282b5..3a64a04 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.386 2024/03/04 04:13:18 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -890,6 +890,20 @@ parse_token(const char *cp, const char *filename, int linenum,
return oBadOption;
}
+static void
+free_canon_cnames(struct allowed_cname *cnames, u_int n)
+{
+ u_int i;
+
+ if (cnames == NULL || n == 0)
+ return;
+ for (i = 0; i < n; i++) {
+ free(cnames[i].source_list);
+ free(cnames[i].target_list);
+ }
+ free(cnames);
+}
+
/* Multistate option parsing */
struct multistate {
char *key;
@@ -1032,21 +1046,24 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
{
char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
char **cpptr, ***cppptr, fwdarg[256];
- u_int i, *uintptr, uvalue, max_entries = 0;
+ u_int i, *uintptr, max_entries = 0;
int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
- int remotefwd, dynamicfwd, ca_only = 0;
+ int remotefwd, dynamicfwd, ca_only = 0, found = 0;
LogLevel *log_level_ptr;
SyslogFacility *log_facility_ptr;
long long val64;
size_t len;
struct Forward fwd;
const struct multistate *multistate_ptr;
- struct allowed_cname *cname;
glob_t gl;
const char *errstr;
char **oav = NULL, **av;
int oac = 0, ac;
int ret = -1;
+ struct allowed_cname *cnames = NULL;
+ u_int ncnames = 0;
+ char **strs = NULL; /* string array arguments; freed implicitly */
+ u_int nstrs = 0;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
@@ -1662,14 +1679,13 @@ parse_pubkey_algos:
case oPermitRemoteOpen:
uintptr = &options->num_permitted_remote_opens;
cppptr = &options->permitted_remote_opens;
- uvalue = *uintptr; /* modified later */
- i = 0;
+ found = *uintptr == 0;
while ((arg = argv_next(&ac, &av)) != NULL) {
arg2 = xstrdup(arg);
/* Allow any/none only in first position */
if (strcasecmp(arg, "none") == 0 ||
strcasecmp(arg, "any") == 0) {
- if (i > 0 || ac > 0) {
+ if (nstrs > 0 || ac > 0) {
error("%s line %d: keyword %s \"%s\" "
"argument must appear alone.",
filename, linenum, keyword, arg);
@@ -1695,17 +1711,20 @@ parse_pubkey_algos:
lookup_opcode_name(opcode));
}
}
- if (*activep && uvalue == 0) {
- opt_array_append(filename, linenum,
- lookup_opcode_name(opcode),
- cppptr, uintptr, arg2);
- }
+ opt_array_append(filename, linenum,
+ lookup_opcode_name(opcode),
+ &strs, &nstrs, arg2);
free(arg2);
- i++;
}
- if (i == 0)
+ if (nstrs == 0)
fatal("%s line %d: missing %s specification",
filename, linenum, lookup_opcode_name(opcode));
+ if (found && *activep) {
+ *cppptr = strs;
+ *uintptr = nstrs;
+ strs = NULL; /* transferred */
+ nstrs = 0;
+ }
break;
case oClearAllForwardings:
@@ -1823,12 +1842,14 @@ parse_pubkey_algos:
goto parse_int;
case oSendEnv:
+ /* XXX appends to list; doesn't respect first-match-wins */
while ((arg = argv_next(&ac, &av)) != NULL) {
if (*arg == '\0' || strchr(arg, '=') != NULL) {
error("%s line %d: Invalid environment name.",
filename, linenum);
goto out;
}
+ found = 1;
if (!*activep)
continue;
if (*arg == '-') {
@@ -1840,27 +1861,38 @@ parse_pubkey_algos:
lookup_opcode_name(opcode),
&options->send_env, &options->num_send_env, arg);
}
+ if (!found) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
break;
case oSetEnv:
- value = options->num_setenv;
+ found = options->num_setenv == 0;
while ((arg = argv_next(&ac, &av)) != NULL) {
if (strchr(arg, '=') == NULL) {
error("%s line %d: Invalid SetEnv.",
filename, linenum);
goto out;
}
- if (!*activep || value != 0)
- continue;
- if (lookup_setenv_in_list(arg, options->setenv,
- options->num_setenv) != NULL) {
+ if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
debug2("%s line %d: ignoring duplicate env "
"name \"%.64s\"", filename, linenum, arg);
continue;
}
opt_array_append(filename, linenum,
lookup_opcode_name(opcode),
- &options->setenv, &options->num_setenv, arg);
+ &strs, &nstrs, arg);
+ }
+ if (nstrs == 0) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
+ if (found && *activep) {
+ options->setenv = strs;
+ options->num_setenv = nstrs;
+ strs = NULL; /* transferred */
+ nstrs = 0;
}
break;
@@ -2069,52 +2101,46 @@ parse_pubkey_algos:
goto parse_flag;
case oCanonicalDomains:
- value = options->num_canonical_domains != 0;
- i = 0;
+ found = options->num_canonical_domains == 0;
while ((arg = argv_next(&ac, &av)) != NULL) {
- if (*arg == '\0') {
- error("%s line %d: keyword %s empty argument",
- filename, linenum, keyword);
- goto out;
- }
/* Allow "none" only in first position */
if (strcasecmp(arg, "none") == 0) {
- if (i > 0 || ac > 0) {
+ if (nstrs > 0 || ac > 0) {
error("%s line %d: keyword %s \"none\" "
"argument must appear alone.",
filename, linenum, keyword);
goto out;
}
}
- i++;
if (!valid_domain(arg, 1, &errstr)) {
error("%s line %d: %s", filename, linenum,
errstr);
goto out;
}
- if (!*activep || value)
- continue;
- if (options->num_canonical_domains >=
- MAX_CANON_DOMAINS) {
- error("%s line %d: too many hostname suffixes.",
- filename, linenum);
- goto out;
- }
- options->canonical_domains[
- options->num_canonical_domains++] = xstrdup(arg);
+ opt_array_append(filename, linenum, keyword,
+ &strs, &nstrs, arg);
+ }
+ if (nstrs == 0) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
+ if (found && *activep) {
+ options->canonical_domains = strs;
+ options->num_canonical_domains = nstrs;
+ strs = NULL; /* transferred */
+ nstrs = 0;
}
break;
case oCanonicalizePermittedCNAMEs:
- value = options->num_permitted_cnames != 0;
- i = 0;
+ found = options->num_permitted_cnames == 0;
while ((arg = argv_next(&ac, &av)) != NULL) {
/*
* Either 'none' (only in first position), '*' for
* everything or 'list:list'
*/
if (strcasecmp(arg, "none") == 0) {
- if (i > 0 || ac > 0) {
+ if (ncnames > 0 || ac > 0) {
error("%s line %d: keyword %s \"none\" "
"argument must appear alone.",
filename, linenum, keyword);
@@ -2135,20 +2161,23 @@ parse_pubkey_algos:
*arg2 = '\0';
arg2++;
}
- i++;
- if (!*activep || value)
- continue;
- if (options->num_permitted_cnames >=
- MAX_CANON_DOMAINS) {
- error("%s line %d: too many permitted CNAMEs.",
- filename, linenum);
- goto out;
- }
- cname = options->permitted_cnames +
- options->num_permitted_cnames++;
- cname->source_list = xstrdup(arg);
- cname->target_list = xstrdup(arg2);
- }
+ cnames = xrecallocarray(cnames, ncnames, ncnames + 1,
+ sizeof(*cnames));
+ cnames[ncnames].source_list = xstrdup(arg);
+ cnames[ncnames].target_list = xstrdup(arg2);
+ ncnames++;
+ }
+ if (ncnames == 0) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
+ if (found && *activep) {
+ options->permitted_cnames = cnames;
+ options->num_permitted_cnames = ncnames;
+ cnames = NULL; /* transferred */
+ ncnames = 0;
+ }
+ /* un-transferred cnames is cleaned up before exit */
break;
case oCanonicalizeHostname:
@@ -2329,12 +2358,11 @@ parse_pubkey_algos:
break;
case oChannelTimeout:
- uvalue = options->num_channel_timeouts;
- i = 0;
+ found = options->num_channel_timeouts == 0;
while ((arg = argv_next(&ac, &av)) != NULL) {
/* Allow "none" only in first position */
if (strcasecmp(arg, "none") == 0) {
- if (i > 0 || ac > 0) {
+ if (nstrs > 0 || ac > 0) {
error("%s line %d: keyword %s \"none\" "
"argument must appear alone.",
filename, linenum, keyword);
@@ -2345,11 +2373,18 @@ parse_pubkey_algos:
fatal("%s line %d: invalid channel timeout %s",
filename, linenum, arg);
}
- if (!*activep || uvalue != 0)
- continue;
opt_array_append(filename, linenum, keyword,
- &options->channel_timeouts,
- &options->num_channel_timeouts, arg);
+ &strs, &nstrs, arg);
+ }
+ if (nstrs == 0) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
+ if (found && *activep) {
+ options->channel_timeouts = strs;
+ options->num_channel_timeouts = nstrs;
+ strs = NULL; /* transferred */
+ nstrs = 0;
}
break;
@@ -2381,6 +2416,8 @@ parse_pubkey_algos:
/* success */
ret = 0;
out:
+ free_canon_cnames(cnames, ncnames);
+ opt_array_free2(strs, NULL, nstrs);
argv_free(oav, oac);
return ret;
}
@@ -2711,7 +2748,9 @@ fill_default_options(Options * options)
add_identity_file(options, "~/",
_PATH_SSH_CLIENT_ID_ED25519_SK, 0);
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
+#ifdef WITH_DSA
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
+#endif
}
if (options->escape_char == -1)
options->escape_char = '~';