summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c85
1 files changed, 52 insertions, 33 deletions
diff --git a/servconf.c b/servconf.c
index ba0a92c7b..f08e37477 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.363 2020/04/17 03:30:05 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.369 2020/08/28 03:15:52 dtucker Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -15,6 +15,7 @@
15 15
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/socket.h> 17#include <sys/socket.h>
18#include <sys/stat.h>
18#ifdef __OpenBSD__ 19#ifdef __OpenBSD__
19#include <sys/sysctl.h> 20#include <sys/sysctl.h>
20#endif 21#endif
@@ -74,8 +75,8 @@ static void add_listen_addr(ServerOptions *, const char *,
74 const char *, int); 75 const char *, int);
75static void add_one_listen_addr(ServerOptions *, const char *, 76static void add_one_listen_addr(ServerOptions *, const char *,
76 const char *, int); 77 const char *, int);
77void parse_server_config_depth(ServerOptions *options, const char *filename, 78static void parse_server_config_depth(ServerOptions *options,
78 struct sshbuf *conf, struct include_list *includes, 79 const char *filename, struct sshbuf *conf, struct include_list *includes,
79 struct connection_info *connectinfo, int flags, int *activep, int depth); 80 struct connection_info *connectinfo, int flags, int *activep, int depth);
80 81
81/* Use of privilege separation or not */ 82/* Use of privilege separation or not */
@@ -140,7 +141,7 @@ initialize_server_options(ServerOptions *options)
140 options->challenge_response_authentication = -1; 141 options->challenge_response_authentication = -1;
141 options->permit_empty_passwd = -1; 142 options->permit_empty_passwd = -1;
142 options->permit_user_env = -1; 143 options->permit_user_env = -1;
143 options->permit_user_env_whitelist = NULL; 144 options->permit_user_env_allowlist = NULL;
144 options->compression = -1; 145 options->compression = -1;
145 options->rekey_limit = -1; 146 options->rekey_limit = -1;
146 options->rekey_interval = -1; 147 options->rekey_interval = -1;
@@ -212,11 +213,11 @@ assemble_algorithms(ServerOptions *o)
212 all_key = sshkey_alg_list(0, 0, 1, ','); 213 all_key = sshkey_alg_list(0, 0, 1, ',');
213 all_sig = sshkey_alg_list(0, 1, 1, ','); 214 all_sig = sshkey_alg_list(0, 1, 1, ',');
214 /* remove unsupported algos from default lists */ 215 /* remove unsupported algos from default lists */
215 def_cipher = match_filter_whitelist(KEX_SERVER_ENCRYPT, all_cipher); 216 def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
216 def_mac = match_filter_whitelist(KEX_SERVER_MAC, all_mac); 217 def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
217 def_kex = match_filter_whitelist(KEX_SERVER_KEX, all_kex); 218 def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
218 def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); 219 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
219 def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); 220 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
220#define ASSEMBLE(what, defaults, all) \ 221#define ASSEMBLE(what, defaults, all) \
221 do { \ 222 do { \
222 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ 223 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
@@ -389,7 +390,7 @@ fill_default_server_options(ServerOptions *options)
389 options->permit_empty_passwd = 0; 390 options->permit_empty_passwd = 0;
390 if (options->permit_user_env == -1) { 391 if (options->permit_user_env == -1) {
391 options->permit_user_env = 0; 392 options->permit_user_env = 0;
392 options->permit_user_env_whitelist = NULL; 393 options->permit_user_env_allowlist = NULL;
393 } 394 }
394 if (options->compression == -1) 395 if (options->compression == -1)
395#ifdef WITH_ZLIB 396#ifdef WITH_ZLIB
@@ -494,15 +495,6 @@ fill_default_server_options(ServerOptions *options)
494 options->auth_methods[0] = NULL; 495 options->auth_methods[0] = NULL;
495 options->num_auth_methods = 0; 496 options->num_auth_methods = 0;
496 } 497 }
497
498#ifndef HAVE_MMAP
499 if (use_privsep && options->compression == 1) {
500 error("This platform does not support both privilege "
501 "separation and compression");
502 error("Compression disabled");
503 options->compression = 0;
504 }
505#endif
506} 498}
507 499
508/* Keyword tokens. */ 500/* Keyword tokens. */
@@ -550,6 +542,7 @@ typedef enum {
550#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 542#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
551#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 543#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
552#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ 544#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
545#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
553 546
554/* Textual representation of the tokens. */ 547/* Textual representation of the tokens. */
555static struct { 548static struct {
@@ -1117,6 +1110,9 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
1117 "%.100s' at line %d", ci->host, arg, line); 1110 "%.100s' at line %d", ci->host, arg, line);
1118 } else if (strcasecmp(attrib, "address") == 0) { 1111 } else if (strcasecmp(attrib, "address") == 0) {
1119 if (ci == NULL || (ci->test && ci->address == NULL)) { 1112 if (ci == NULL || (ci->test && ci->address == NULL)) {
1113 if (addr_match_list(NULL, arg) != 0)
1114 fatal("Invalid Match address argument "
1115 "'%s' at line %d", arg, line);
1120 result = 0; 1116 result = 0;
1121 continue; 1117 continue;
1122 } 1118 }
@@ -1136,6 +1132,10 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
1136 } 1132 }
1137 } else if (strcasecmp(attrib, "localaddress") == 0){ 1133 } else if (strcasecmp(attrib, "localaddress") == 0){
1138 if (ci == NULL || (ci->test && ci->laddress == NULL)) { 1134 if (ci == NULL || (ci->test && ci->laddress == NULL)) {
1135 if (addr_match_list(NULL, arg) != 0)
1136 fatal("Invalid Match localaddress "
1137 "argument '%s' at line %d", arg,
1138 line);
1139 result = 0; 1139 result = 0;
1140 continue; 1140 continue;
1141 } 1141 }
@@ -1259,7 +1259,7 @@ static const struct multistate multistate_tcpfwd[] = {
1259static int 1259static int
1260process_server_config_line_depth(ServerOptions *options, char *line, 1260process_server_config_line_depth(ServerOptions *options, char *line,
1261 const char *filename, int linenum, int *activep, 1261 const char *filename, int linenum, int *activep,
1262 struct connection_info *connectinfo, int inc_flags, int depth, 1262 struct connection_info *connectinfo, int *inc_flags, int depth,
1263 struct include_list *includes) 1263 struct include_list *includes)
1264{ 1264{
1265 char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; 1265 char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
@@ -1525,6 +1525,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
1525 continue; 1525 continue;
1526 if (strcasecmp(arg, "touch-required") == 0) 1526 if (strcasecmp(arg, "touch-required") == 0)
1527 value |= PUBKEYAUTH_TOUCH_REQUIRED; 1527 value |= PUBKEYAUTH_TOUCH_REQUIRED;
1528 else if (strcasecmp(arg, "verify-required") == 0)
1529 value |= PUBKEYAUTH_VERIFY_REQUIRED;
1528 else { 1530 else {
1529 fatal("%s line %d: unsupported " 1531 fatal("%s line %d: unsupported "
1530 "PubkeyAuthOptions option %s", 1532 "PubkeyAuthOptions option %s",
@@ -1628,7 +1630,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
1628 1630
1629 case sPermitUserEnvironment: 1631 case sPermitUserEnvironment:
1630 intptr = &options->permit_user_env; 1632 intptr = &options->permit_user_env;
1631 charptr = &options->permit_user_env_whitelist; 1633 charptr = &options->permit_user_env_allowlist;
1632 arg = strdelim(&cp); 1634 arg = strdelim(&cp);
1633 if (!arg || *arg == '\0') 1635 if (!arg || *arg == '\0')
1634 fatal("%s line %d: missing argument.", 1636 fatal("%s line %d: missing argument.",
@@ -2002,7 +2004,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2002 parse_server_config_depth(options, 2004 parse_server_config_depth(options,
2003 item->filename, item->contents, 2005 item->filename, item->contents,
2004 includes, connectinfo, 2006 includes, connectinfo,
2005 (oactive ? 0 : SSHCFG_NEVERMATCH), 2007 (*inc_flags & SSHCFG_MATCH_ONLY
2008 ? SSHCFG_MATCH_ONLY : (oactive
2009 ? 0 : SSHCFG_NEVERMATCH)),
2006 activep, depth + 1); 2010 activep, depth + 1);
2007 } 2011 }
2008 found = 1; 2012 found = 1;
@@ -2050,7 +2054,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2050 parse_server_config_depth(options, 2054 parse_server_config_depth(options,
2051 item->filename, item->contents, 2055 item->filename, item->contents,
2052 includes, connectinfo, 2056 includes, connectinfo,
2053 (oactive ? 0 : SSHCFG_NEVERMATCH), 2057 (*inc_flags & SSHCFG_MATCH_ONLY
2058 ? SSHCFG_MATCH_ONLY : (oactive
2059 ? 0 : SSHCFG_NEVERMATCH)),
2054 activep, depth + 1); 2060 activep, depth + 1);
2055 *activep = oactive; 2061 *activep = oactive;
2056 TAILQ_INSERT_TAIL(includes, item, entry); 2062 TAILQ_INSERT_TAIL(includes, item, entry);
@@ -2068,11 +2074,14 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2068 if (cmdline) 2074 if (cmdline)
2069 fatal("Match directive not supported as a command-line " 2075 fatal("Match directive not supported as a command-line "
2070 "option"); 2076 "option");
2071 value = match_cfg_line(&cp, linenum, connectinfo); 2077 value = match_cfg_line(&cp, linenum,
2078 (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
2072 if (value < 0) 2079 if (value < 0)
2073 fatal("%s line %d: Bad Match condition", filename, 2080 fatal("%s line %d: Bad Match condition", filename,
2074 linenum); 2081 linenum);
2075 *activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; 2082 *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
2083 /* The MATCH_ONLY is applicable only until the first match block */
2084 *inc_flags &= ~SSHCFG_MATCH_ONLY;
2076 break; 2085 break;
2077 2086
2078 case sPermitListen: 2087 case sPermitListen:
@@ -2375,8 +2384,10 @@ process_server_config_line(ServerOptions *options, char *line,
2375 const char *filename, int linenum, int *activep, 2384 const char *filename, int linenum, int *activep,
2376 struct connection_info *connectinfo, struct include_list *includes) 2385 struct connection_info *connectinfo, struct include_list *includes)
2377{ 2386{
2387 int inc_flags = 0;
2388
2378 return process_server_config_line_depth(options, line, filename, 2389 return process_server_config_line_depth(options, line, filename,
2379 linenum, activep, connectinfo, 0, 0, includes); 2390 linenum, activep, connectinfo, &inc_flags, 0, includes);
2380} 2391}
2381 2392
2382 2393
@@ -2385,6 +2396,7 @@ process_server_config_line(ServerOptions *options, char *line,
2385void 2396void
2386load_server_config(const char *filename, struct sshbuf *conf) 2397load_server_config(const char *filename, struct sshbuf *conf)
2387{ 2398{
2399 struct stat st;
2388 char *line = NULL, *cp; 2400 char *line = NULL, *cp;
2389 size_t linesize = 0; 2401 size_t linesize = 0;
2390 FILE *f; 2402 FILE *f;
@@ -2396,6 +2408,10 @@ load_server_config(const char *filename, struct sshbuf *conf)
2396 exit(1); 2408 exit(1);
2397 } 2409 }
2398 sshbuf_reset(conf); 2410 sshbuf_reset(conf);
2411 /* grow buffer, so realloc is avoided for large config files */
2412 if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
2413 (r = sshbuf_allocate(conf, st.st_size)) != 0)
2414 fatal("%s: allocate failed: %s", __func__, ssh_err(r));
2399 while (getline(&line, &linesize, f) != -1) { 2415 while (getline(&line, &linesize, f) != -1) {
2400 lineno++; 2416 lineno++;
2401 /* 2417 /*
@@ -2570,7 +2586,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2570#undef M_CP_STRARRAYOPT 2586#undef M_CP_STRARRAYOPT
2571 2587
2572#define SERVCONF_MAX_DEPTH 16 2588#define SERVCONF_MAX_DEPTH 16
2573void 2589static void
2574parse_server_config_depth(ServerOptions *options, const char *filename, 2590parse_server_config_depth(ServerOptions *options, const char *filename,
2575 struct sshbuf *conf, struct include_list *includes, 2591 struct sshbuf *conf, struct include_list *includes,
2576 struct connection_info *connectinfo, int flags, int *activep, int depth) 2592 struct connection_info *connectinfo, int flags, int *activep, int depth)
@@ -2581,14 +2597,15 @@ parse_server_config_depth(ServerOptions *options, const char *filename,
2581 if (depth < 0 || depth > SERVCONF_MAX_DEPTH) 2597 if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
2582 fatal("Too many recursive configuration includes"); 2598 fatal("Too many recursive configuration includes");
2583 2599
2584 debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); 2600 debug2("%s: config %s len %zu%s", __func__, filename, sshbuf_len(conf),
2601 (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
2585 2602
2586 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) 2603 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
2587 fatal("%s: sshbuf_dup_string failed", __func__); 2604 fatal("%s: sshbuf_dup_string failed", __func__);
2588 linenum = 1; 2605 linenum = 1;
2589 while ((cp = strsep(&cbuf, "\n")) != NULL) { 2606 while ((cp = strsep(&cbuf, "\n")) != NULL) {
2590 if (process_server_config_line_depth(options, cp, 2607 if (process_server_config_line_depth(options, cp,
2591 filename, linenum++, activep, connectinfo, flags, 2608 filename, linenum++, activep, connectinfo, &flags,
2592 depth, includes) != 0) 2609 depth, includes) != 0)
2593 bad_options++; 2610 bad_options++;
2594 } 2611 }
@@ -2596,7 +2613,6 @@ parse_server_config_depth(ServerOptions *options, const char *filename,
2596 if (bad_options > 0) 2613 if (bad_options > 0)
2597 fatal("%s: terminating, %d bad configuration options", 2614 fatal("%s: terminating, %d bad configuration options",
2598 filename, bad_options); 2615 filename, bad_options);
2599 process_queued_listen_addrs(options);
2600} 2616}
2601 2617
2602void 2618void
@@ -2606,7 +2622,8 @@ parse_server_config(ServerOptions *options, const char *filename,
2606{ 2622{
2607 int active = connectinfo ? 0 : 1; 2623 int active = connectinfo ? 0 : 1;
2608 parse_server_config_depth(options, filename, conf, includes, 2624 parse_server_config_depth(options, filename, conf, includes,
2609 connectinfo, 0, &active, 0); 2625 connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
2626 process_queued_listen_addrs(options);
2610} 2627}
2611 2628
2612static const char * 2629static const char *
@@ -2908,11 +2925,11 @@ dump_config(ServerOptions *o)
2908 } 2925 }
2909 printf("\n"); 2926 printf("\n");
2910 2927
2911 if (o->permit_user_env_whitelist == NULL) { 2928 if (o->permit_user_env_allowlist == NULL) {
2912 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2929 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
2913 } else { 2930 } else {
2914 printf("permituserenvironment %s\n", 2931 printf("permituserenvironment %s\n",
2915 o->permit_user_env_whitelist); 2932 o->permit_user_env_allowlist);
2916 } 2933 }
2917 2934
2918 printf("pubkeyauthoptions"); 2935 printf("pubkeyauthoptions");
@@ -2920,5 +2937,7 @@ dump_config(ServerOptions *o)
2920 printf(" none"); 2937 printf(" none");
2921 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) 2938 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
2922 printf(" touch-required"); 2939 printf(" touch-required");
2940 if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
2941 printf(" verify-required");
2923 printf("\n"); 2942 printf("\n");
2924} 2943}