|
Lines 40-45
Link Here
|
| 40 |
#ifdef HAVE_UTIL_H |
40 |
#ifdef HAVE_UTIL_H |
| 41 |
#include <util.h> |
41 |
#include <util.h> |
| 42 |
#endif |
42 |
#endif |
|
|
43 |
#ifdef USE_SYSTEM_GLOB |
| 44 |
# include <glob.h> |
| 45 |
#else |
| 46 |
# include "openbsd-compat/glob.h" |
| 47 |
#endif |
| 43 |
|
48 |
|
| 44 |
#include "openbsd-compat/sys-queue.h" |
49 |
#include "openbsd-compat/sys-queue.h" |
| 45 |
#include "xmalloc.h" |
50 |
#include "xmalloc.h" |
|
Lines 74-79
static void add_one_listen_addr(ServerOptions *, const char *,
Link Here
|
| 74 |
extern int use_privsep; |
79 |
extern int use_privsep; |
| 75 |
extern struct sshbuf *cfg; |
80 |
extern struct sshbuf *cfg; |
| 76 |
|
81 |
|
|
|
82 |
#define INCLUDE_LIST_APPEND(includes, item) \ |
| 83 |
do { \ |
| 84 |
if ((includes)->count >= UINT16_MAX) \ |
| 85 |
fatal("%s: Too many included files", __func__); \ |
| 86 |
(item)->next = NULL; \ |
| 87 |
if ((includes)->start == NULL) { \ |
| 88 |
(includes)->start = (item); \ |
| 89 |
} else if ((includes)->end != NULL) { \ |
| 90 |
(includes)->end->next = (item); \ |
| 91 |
} \ |
| 92 |
(includes)->end = (item); \ |
| 93 |
(includes)->count++; \ |
| 94 |
} while (0) |
| 95 |
|
| 77 |
/* Initializes the server options to their default values. */ |
96 |
/* Initializes the server options to their default values. */ |
| 78 |
|
97 |
|
| 79 |
void |
98 |
void |
|
Lines 473-478
fill_default_server_options(ServerOptions *options)
Link Here
|
| 473 |
|
492 |
|
| 474 |
} |
493 |
} |
| 475 |
|
494 |
|
|
|
495 |
int process_server_config_line_depth(ServerOptions *options, char *line, |
| 496 |
const char *filename, int linenum, int *activep, |
| 497 |
struct connection_info *connectinfo, int inc_flags, int depth, |
| 498 |
struct include_list *includes); |
| 499 |
void parse_server_config_depth(ServerOptions *options, const char *filename, |
| 500 |
struct sshbuf *conf, struct include_list *includes, |
| 501 |
struct connection_info *connectinfo, int flags, int *activep, int depth); |
| 502 |
|
| 476 |
/* Keyword tokens. */ |
503 |
/* Keyword tokens. */ |
| 477 |
typedef enum { |
504 |
typedef enum { |
| 478 |
sBadOption, /* == unknown option */ |
505 |
sBadOption, /* == unknown option */ |
|
Lines 502-508
typedef enum {
Link Here
|
| 502 |
sAcceptEnv, sSetEnv, sPermitTunnel, |
529 |
sAcceptEnv, sSetEnv, sPermitTunnel, |
| 503 |
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, |
530 |
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, |
| 504 |
sUsePrivilegeSeparation, sAllowAgentForwarding, |
531 |
sUsePrivilegeSeparation, sAllowAgentForwarding, |
| 505 |
sHostCertificate, |
532 |
sHostCertificate, sInclude, |
| 506 |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
533 |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
| 507 |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
534 |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
| 508 |
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, |
535 |
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, |
|
Lines 518-523
typedef enum {
Link Here
|
| 518 |
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ |
545 |
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ |
| 519 |
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) |
546 |
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) |
| 520 |
|
547 |
|
|
|
548 |
#define SSHCFG_NEVERMATCH 0x04 /* Match/Host never matches; internal only */ |
| 549 |
|
| 521 |
/* Textual representation of the tokens. */ |
550 |
/* Textual representation of the tokens. */ |
| 522 |
static struct { |
551 |
static struct { |
| 523 |
const char *name; |
552 |
const char *name; |
|
Lines 644-649
static struct {
Link Here
|
| 644 |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
673 |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
| 645 |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
674 |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
| 646 |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
675 |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
|
|
676 |
{ "include", sInclude, SSHCFG_ALL }, |
| 647 |
{ "ipqos", sIPQoS, SSHCFG_ALL }, |
677 |
{ "ipqos", sIPQoS, SSHCFG_ALL }, |
| 648 |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
678 |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
| 649 |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
679 |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
|
Lines 1217-1226
static const struct multistate multistate_tcpfwd[] = {
Link Here
|
| 1217 |
int |
1247 |
int |
| 1218 |
process_server_config_line(ServerOptions *options, char *line, |
1248 |
process_server_config_line(ServerOptions *options, char *line, |
| 1219 |
const char *filename, int linenum, int *activep, |
1249 |
const char *filename, int linenum, int *activep, |
| 1220 |
struct connection_info *connectinfo) |
1250 |
struct connection_info *connectinfo, struct include_list *includes) |
|
|
1251 |
{ |
| 1252 |
return process_server_config_line_depth(options, line, filename, |
| 1253 |
linenum, activep, connectinfo, 0, 0, includes); |
| 1254 |
} |
| 1255 |
|
| 1256 |
int |
| 1257 |
process_server_config_line_depth(ServerOptions *options, char *line, |
| 1258 |
const char *filename, int linenum, int *activep, |
| 1259 |
struct connection_info *connectinfo, int inc_flags, int depth, |
| 1260 |
struct include_list *includes) |
| 1221 |
{ |
1261 |
{ |
| 1222 |
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; |
1262 |
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; |
| 1223 |
int cmdline = 0, *intptr, value, value2, n, port; |
1263 |
int cmdline = 0, *intptr, value, value2, n, port, oactive; |
| 1224 |
SyslogFacility *log_facility_ptr; |
1264 |
SyslogFacility *log_facility_ptr; |
| 1225 |
LogLevel *log_level_ptr; |
1265 |
LogLevel *log_level_ptr; |
| 1226 |
ServerOpCodes opcode; |
1266 |
ServerOpCodes opcode; |
|
Lines 1229-1234
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1229 |
long long val64; |
1269 |
long long val64; |
| 1230 |
const struct multistate *multistate_ptr; |
1270 |
const struct multistate *multistate_ptr; |
| 1231 |
const char *errstr; |
1271 |
const char *errstr; |
|
|
1272 |
struct include_item *item; |
| 1273 |
int found = 0; |
| 1274 |
glob_t gbuf; |
| 1232 |
|
1275 |
|
| 1233 |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */ |
1276 |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */ |
| 1234 |
if ((len = strlen(line)) == 0) |
1277 |
if ((len = strlen(line)) == 0) |
|
Lines 1255-1261
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1255 |
cmdline = 1; |
1298 |
cmdline = 1; |
| 1256 |
activep = &cmdline; |
1299 |
activep = &cmdline; |
| 1257 |
} |
1300 |
} |
| 1258 |
if (*activep && opcode != sMatch) |
1301 |
if (*activep && opcode != sMatch && opcode != sInclude) |
| 1259 |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
1302 |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
| 1260 |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
1303 |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
| 1261 |
if (connectinfo == NULL) { |
1304 |
if (connectinfo == NULL) { |
|
Lines 1906-1911
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1906 |
*intptr = value; |
1949 |
*intptr = value; |
| 1907 |
break; |
1950 |
break; |
| 1908 |
|
1951 |
|
|
|
1952 |
case sInclude: |
| 1953 |
if (cmdline) |
| 1954 |
fatal("Include directive not supported as a command-line " |
| 1955 |
"option"); |
| 1956 |
|
| 1957 |
value = 0; |
| 1958 |
while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { |
| 1959 |
value++; |
| 1960 |
found = 0; |
| 1961 |
if (*arg != '/' && *arg != '~') { |
| 1962 |
xasprintf(&arg2, "%s/%s", |
| 1963 |
SSHDIR, arg); |
| 1964 |
} else |
| 1965 |
arg2 = xstrdup(arg); |
| 1966 |
|
| 1967 |
/* |
| 1968 |
* don't let the Match in Included clobber |
| 1969 |
* the containing file's Match state. |
| 1970 |
*/ |
| 1971 |
oactive = *activep; |
| 1972 |
/* browse cached list of files */ |
| 1973 |
for (item = includes->start; item != NULL; item = item->next) { |
| 1974 |
if (strcmp(item->selector, arg2) == 0) { |
| 1975 |
if (item->filename != NULL) |
| 1976 |
parse_server_config_depth(options, |
| 1977 |
item->filename, item->buffer, |
| 1978 |
includes, connectinfo, |
| 1979 |
(oactive ? 0 : SSHCFG_NEVERMATCH), |
| 1980 |
activep, depth + 1); |
| 1981 |
found = 1; |
| 1982 |
*activep = oactive; |
| 1983 |
} |
| 1984 |
} |
| 1985 |
if (found != 0) { |
| 1986 |
free(arg2); |
| 1987 |
continue; |
| 1988 |
} |
| 1989 |
|
| 1990 |
/* not in cache, a new glob */ |
| 1991 |
debug3("Glob configuration file to include %s", arg2); |
| 1992 |
if (glob(arg2, 0, NULL, &gbuf) == 0) { |
| 1993 |
for (n = 0; n < gbuf.gl_pathc; n++) { |
| 1994 |
debug3("Including configuration file %s", |
| 1995 |
gbuf.gl_pathv[n]); |
| 1996 |
item = malloc(sizeof(struct include_item)); |
| 1997 |
item->selector = strdup(arg2); |
| 1998 |
item->filename = strdup(gbuf.gl_pathv[n]); |
| 1999 |
item->buffer = sshbuf_new(); |
| 2000 |
load_server_config(item->filename, |
| 2001 |
item->buffer); |
| 2002 |
parse_server_config_depth(options, |
| 2003 |
item->filename, item->buffer, |
| 2004 |
includes, connectinfo, |
| 2005 |
(oactive ? 0 : SSHCFG_NEVERMATCH), |
| 2006 |
activep, depth + 1); |
| 2007 |
|
| 2008 |
/* append item to the end of the list */ |
| 2009 |
INCLUDE_LIST_APPEND(includes, item); |
| 2010 |
*activep = oactive; |
| 2011 |
} |
| 2012 |
} else { /* no match or other error */ |
| 2013 |
/* store placeholder to avoid aditional empty globs */ |
| 2014 |
item = malloc(sizeof(struct include_item)); |
| 2015 |
item->selector = strdup(arg2); |
| 2016 |
item->filename = NULL; |
| 2017 |
item->buffer = sshbuf_new(); |
| 2018 |
/* append item to the end of the list */ |
| 2019 |
INCLUDE_LIST_APPEND(includes, item); |
| 2020 |
} |
| 2021 |
globfree(&gbuf); |
| 2022 |
free(arg2); |
| 2023 |
} |
| 2024 |
if (value == 0) |
| 2025 |
fatal("%s line %d: missing argument - file to include", |
| 2026 |
filename, linenum); |
| 2027 |
break; |
| 2028 |
|
| 1909 |
case sMatch: |
2029 |
case sMatch: |
| 1910 |
if (cmdline) |
2030 |
if (cmdline) |
| 1911 |
fatal("Match directive not supported as a command-line " |
2031 |
fatal("Match directive not supported as a command-line " |
|
Lines 1914-1920
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1914 |
if (value < 0) |
2034 |
if (value < 0) |
| 1915 |
fatal("%s line %d: Bad Match condition", filename, |
2035 |
fatal("%s line %d: Bad Match condition", filename, |
| 1916 |
linenum); |
2036 |
linenum); |
| 1917 |
*activep = value; |
2037 |
*activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; |
| 1918 |
break; |
2038 |
break; |
| 1919 |
|
2039 |
|
| 1920 |
case sPermitListen: |
2040 |
case sPermitListen: |
|
Lines 2231-2242
load_server_config(const char *filename, struct sshbuf *conf)
Link Here
|
| 2231 |
|
2351 |
|
| 2232 |
void |
2352 |
void |
| 2233 |
parse_server_match_config(ServerOptions *options, |
2353 |
parse_server_match_config(ServerOptions *options, |
| 2234 |
struct connection_info *connectinfo) |
2354 |
struct include_list *includes, struct connection_info *connectinfo) |
| 2235 |
{ |
2355 |
{ |
| 2236 |
ServerOptions mo; |
2356 |
ServerOptions mo; |
| 2237 |
|
2357 |
|
| 2238 |
initialize_server_options(&mo); |
2358 |
initialize_server_options(&mo); |
| 2239 |
parse_server_config(&mo, "reprocess config", cfg, connectinfo); |
2359 |
parse_server_config(&mo, "reprocess config", cfg, includes, |
|
|
2360 |
connectinfo); |
| 2240 |
copy_set_server_options(options, &mo, 0); |
2361 |
copy_set_server_options(options, &mo, 0); |
| 2241 |
} |
2362 |
} |
| 2242 |
|
2363 |
|
|
Lines 2381-2400
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
Link Here
|
| 2381 |
|
2502 |
|
| 2382 |
void |
2503 |
void |
| 2383 |
parse_server_config(ServerOptions *options, const char *filename, |
2504 |
parse_server_config(ServerOptions *options, const char *filename, |
| 2384 |
struct sshbuf *conf, struct connection_info *connectinfo) |
2505 |
struct sshbuf *conf, struct include_list *includes, |
|
|
2506 |
struct connection_info *connectinfo) |
| 2507 |
{ |
| 2508 |
int active = connectinfo ? 0 : 1; |
| 2509 |
parse_server_config_depth(options, filename, conf, includes, |
| 2510 |
connectinfo, 0, &active, 0); |
| 2511 |
} |
| 2512 |
|
| 2513 |
#define SERVCONF_MAX_DEPTH 16 |
| 2514 |
|
| 2515 |
void |
| 2516 |
parse_server_config_depth(ServerOptions *options, const char *filename, |
| 2517 |
struct sshbuf *conf, struct include_list *includes, |
| 2518 |
struct connection_info *connectinfo, int flags, int *activep, int depth) |
| 2385 |
{ |
2519 |
{ |
| 2386 |
int active, linenum, bad_options = 0; |
2520 |
int linenum, bad_options = 0; |
| 2387 |
char *cp, *obuf, *cbuf; |
2521 |
char *cp, *obuf, *cbuf; |
| 2388 |
|
2522 |
|
|
|
2523 |
if (depth < 0 || depth > SERVCONF_MAX_DEPTH) |
| 2524 |
fatal("Too many recursive configuration includes"); |
| 2525 |
|
| 2389 |
debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); |
2526 |
debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); |
| 2390 |
|
2527 |
|
| 2391 |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) |
2528 |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) |
| 2392 |
fatal("%s: sshbuf_dup_string failed", __func__); |
2529 |
fatal("%s: sshbuf_dup_string failed", __func__); |
| 2393 |
active = connectinfo ? 0 : 1; |
|
|
| 2394 |
linenum = 1; |
2530 |
linenum = 1; |
| 2395 |
while ((cp = strsep(&cbuf, "\n")) != NULL) { |
2531 |
while ((cp = strsep(&cbuf, "\n")) != NULL) { |
| 2396 |
if (process_server_config_line(options, cp, filename, |
2532 |
if (process_server_config_line_depth(options, cp, filename, |
| 2397 |
linenum++, &active, connectinfo) != 0) |
2533 |
linenum++, activep, connectinfo, flags, depth, includes) != 0) |
| 2398 |
bad_options++; |
2534 |
bad_options++; |
| 2399 |
} |
2535 |
} |
| 2400 |
free(obuf); |
2536 |
free(obuf); |