summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/servconf.c b/servconf.c
index 5f3336365..98afcfcec 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.364 2020/05/27 21:59:11 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
@@ -144,7 +145,7 @@ initialize_server_options(ServerOptions *options)
144 options->challenge_response_authentication = -1; 145 options->challenge_response_authentication = -1;
145 options->permit_empty_passwd = -1; 146 options->permit_empty_passwd = -1;
146 options->permit_user_env = -1; 147 options->permit_user_env = -1;
147 options->permit_user_env_whitelist = NULL; 148 options->permit_user_env_allowlist = NULL;
148 options->compression = -1; 149 options->compression = -1;
149 options->rekey_limit = -1; 150 options->rekey_limit = -1;
150 options->rekey_interval = -1; 151 options->rekey_interval = -1;
@@ -217,11 +218,11 @@ assemble_algorithms(ServerOptions *o)
217 all_key = sshkey_alg_list(0, 0, 1, ','); 218 all_key = sshkey_alg_list(0, 0, 1, ',');
218 all_sig = sshkey_alg_list(0, 1, 1, ','); 219 all_sig = sshkey_alg_list(0, 1, 1, ',');
219 /* remove unsupported algos from default lists */ 220 /* remove unsupported algos from default lists */
220 def_cipher = match_filter_whitelist(KEX_SERVER_ENCRYPT, all_cipher); 221 def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
221 def_mac = match_filter_whitelist(KEX_SERVER_MAC, all_mac); 222 def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
222 def_kex = match_filter_whitelist(KEX_SERVER_KEX, all_kex); 223 def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
223 def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); 224 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
224 def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); 225 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
225#define ASSEMBLE(what, defaults, all) \ 226#define ASSEMBLE(what, defaults, all) \
226 do { \ 227 do { \
227 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ 228 if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
@@ -402,7 +403,7 @@ fill_default_server_options(ServerOptions *options)
402 options->permit_empty_passwd = 0; 403 options->permit_empty_passwd = 0;
403 if (options->permit_user_env == -1) { 404 if (options->permit_user_env == -1) {
404 options->permit_user_env = 0; 405 options->permit_user_env = 0;
405 options->permit_user_env_whitelist = NULL; 406 options->permit_user_env_allowlist = NULL;
406 } 407 }
407 if (options->compression == -1) 408 if (options->compression == -1)
408#ifdef WITH_ZLIB 409#ifdef WITH_ZLIB
@@ -509,15 +510,6 @@ fill_default_server_options(ServerOptions *options)
509 options->auth_methods[0] = NULL; 510 options->auth_methods[0] = NULL;
510 options->num_auth_methods = 0; 511 options->num_auth_methods = 0;
511 } 512 }
512
513#ifndef HAVE_MMAP
514 if (use_privsep && options->compression == 1) {
515 error("This platform does not support both privilege "
516 "separation and compression");
517 error("Compression disabled");
518 options->compression = 0;
519 }
520#endif
521} 513}
522 514
523/* Keyword tokens. */ 515/* Keyword tokens. */
@@ -567,6 +559,7 @@ typedef enum {
567#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ 559#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
568#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) 560#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
569#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ 561#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
562#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
570 563
571/* Textual representation of the tokens. */ 564/* Textual representation of the tokens. */
572static struct { 565static struct {
@@ -1146,6 +1139,9 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
1146 "%.100s' at line %d", ci->host, arg, line); 1139 "%.100s' at line %d", ci->host, arg, line);
1147 } else if (strcasecmp(attrib, "address") == 0) { 1140 } else if (strcasecmp(attrib, "address") == 0) {
1148 if (ci == NULL || (ci->test && ci->address == NULL)) { 1141 if (ci == NULL || (ci->test && ci->address == NULL)) {
1142 if (addr_match_list(NULL, arg) != 0)
1143 fatal("Invalid Match address argument "
1144 "'%s' at line %d", arg, line);
1149 result = 0; 1145 result = 0;
1150 continue; 1146 continue;
1151 } 1147 }
@@ -1165,6 +1161,10 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
1165 } 1161 }
1166 } else if (strcasecmp(attrib, "localaddress") == 0){ 1162 } else if (strcasecmp(attrib, "localaddress") == 0){
1167 if (ci == NULL || (ci->test && ci->laddress == NULL)) { 1163 if (ci == NULL || (ci->test && ci->laddress == NULL)) {
1164 if (addr_match_list(NULL, arg) != 0)
1165 fatal("Invalid Match localaddress "
1166 "argument '%s' at line %d", arg,
1167 line);
1168 result = 0; 1168 result = 0;
1169 continue; 1169 continue;
1170 } 1170 }
@@ -1288,7 +1288,7 @@ static const struct multistate multistate_tcpfwd[] = {
1288static int 1288static int
1289process_server_config_line_depth(ServerOptions *options, char *line, 1289process_server_config_line_depth(ServerOptions *options, char *line,
1290 const char *filename, int linenum, int *activep, 1290 const char *filename, int linenum, int *activep,
1291 struct connection_info *connectinfo, int inc_flags, int depth, 1291 struct connection_info *connectinfo, int *inc_flags, int depth,
1292 struct include_list *includes) 1292 struct include_list *includes)
1293{ 1293{
1294 char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; 1294 char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
@@ -1554,6 +1554,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
1554 continue; 1554 continue;
1555 if (strcasecmp(arg, "touch-required") == 0) 1555 if (strcasecmp(arg, "touch-required") == 0)
1556 value |= PUBKEYAUTH_TOUCH_REQUIRED; 1556 value |= PUBKEYAUTH_TOUCH_REQUIRED;
1557 else if (strcasecmp(arg, "verify-required") == 0)
1558 value |= PUBKEYAUTH_VERIFY_REQUIRED;
1557 else { 1559 else {
1558 fatal("%s line %d: unsupported " 1560 fatal("%s line %d: unsupported "
1559 "PubkeyAuthOptions option %s", 1561 "PubkeyAuthOptions option %s",
@@ -1677,7 +1679,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
1677 1679
1678 case sPermitUserEnvironment: 1680 case sPermitUserEnvironment:
1679 intptr = &options->permit_user_env; 1681 intptr = &options->permit_user_env;
1680 charptr = &options->permit_user_env_whitelist; 1682 charptr = &options->permit_user_env_allowlist;
1681 arg = strdelim(&cp); 1683 arg = strdelim(&cp);
1682 if (!arg || *arg == '\0') 1684 if (!arg || *arg == '\0')
1683 fatal("%s line %d: missing argument.", 1685 fatal("%s line %d: missing argument.",
@@ -2051,7 +2053,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2051 parse_server_config_depth(options, 2053 parse_server_config_depth(options,
2052 item->filename, item->contents, 2054 item->filename, item->contents,
2053 includes, connectinfo, 2055 includes, connectinfo,
2054 (oactive ? 0 : SSHCFG_NEVERMATCH), 2056 (*inc_flags & SSHCFG_MATCH_ONLY
2057 ? SSHCFG_MATCH_ONLY : (oactive
2058 ? 0 : SSHCFG_NEVERMATCH)),
2055 activep, depth + 1); 2059 activep, depth + 1);
2056 } 2060 }
2057 found = 1; 2061 found = 1;
@@ -2099,7 +2103,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2099 parse_server_config_depth(options, 2103 parse_server_config_depth(options,
2100 item->filename, item->contents, 2104 item->filename, item->contents,
2101 includes, connectinfo, 2105 includes, connectinfo,
2102 (oactive ? 0 : SSHCFG_NEVERMATCH), 2106 (*inc_flags & SSHCFG_MATCH_ONLY
2107 ? SSHCFG_MATCH_ONLY : (oactive
2108 ? 0 : SSHCFG_NEVERMATCH)),
2103 activep, depth + 1); 2109 activep, depth + 1);
2104 *activep = oactive; 2110 *activep = oactive;
2105 TAILQ_INSERT_TAIL(includes, item, entry); 2111 TAILQ_INSERT_TAIL(includes, item, entry);
@@ -2117,11 +2123,14 @@ process_server_config_line_depth(ServerOptions *options, char *line,
2117 if (cmdline) 2123 if (cmdline)
2118 fatal("Match directive not supported as a command-line " 2124 fatal("Match directive not supported as a command-line "
2119 "option"); 2125 "option");
2120 value = match_cfg_line(&cp, linenum, connectinfo); 2126 value = match_cfg_line(&cp, linenum,
2127 (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
2121 if (value < 0) 2128 if (value < 0)
2122 fatal("%s line %d: Bad Match condition", filename, 2129 fatal("%s line %d: Bad Match condition", filename,
2123 linenum); 2130 linenum);
2124 *activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; 2131 *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
2132 /* The MATCH_ONLY is applicable only until the first match block */
2133 *inc_flags &= ~SSHCFG_MATCH_ONLY;
2125 break; 2134 break;
2126 2135
2127 case sPermitListen: 2136 case sPermitListen:
@@ -2428,8 +2437,10 @@ process_server_config_line(ServerOptions *options, char *line,
2428 const char *filename, int linenum, int *activep, 2437 const char *filename, int linenum, int *activep,
2429 struct connection_info *connectinfo, struct include_list *includes) 2438 struct connection_info *connectinfo, struct include_list *includes)
2430{ 2439{
2440 int inc_flags = 0;
2441
2431 return process_server_config_line_depth(options, line, filename, 2442 return process_server_config_line_depth(options, line, filename,
2432 linenum, activep, connectinfo, 0, 0, includes); 2443 linenum, activep, connectinfo, &inc_flags, 0, includes);
2433} 2444}
2434 2445
2435 2446
@@ -2438,6 +2449,7 @@ process_server_config_line(ServerOptions *options, char *line,
2438void 2449void
2439load_server_config(const char *filename, struct sshbuf *conf) 2450load_server_config(const char *filename, struct sshbuf *conf)
2440{ 2451{
2452 struct stat st;
2441 char *line = NULL, *cp; 2453 char *line = NULL, *cp;
2442 size_t linesize = 0; 2454 size_t linesize = 0;
2443 FILE *f; 2455 FILE *f;
@@ -2449,6 +2461,10 @@ load_server_config(const char *filename, struct sshbuf *conf)
2449 exit(1); 2461 exit(1);
2450 } 2462 }
2451 sshbuf_reset(conf); 2463 sshbuf_reset(conf);
2464 /* grow buffer, so realloc is avoided for large config files */
2465 if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
2466 (r = sshbuf_allocate(conf, st.st_size)) != 0)
2467 fatal("%s: allocate failed: %s", __func__, ssh_err(r));
2452 while (getline(&line, &linesize, f) != -1) { 2468 while (getline(&line, &linesize, f) != -1) {
2453 lineno++; 2469 lineno++;
2454 /* 2470 /*
@@ -2634,14 +2650,15 @@ parse_server_config_depth(ServerOptions *options, const char *filename,
2634 if (depth < 0 || depth > SERVCONF_MAX_DEPTH) 2650 if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
2635 fatal("Too many recursive configuration includes"); 2651 fatal("Too many recursive configuration includes");
2636 2652
2637 debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); 2653 debug2("%s: config %s len %zu%s", __func__, filename, sshbuf_len(conf),
2654 (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
2638 2655
2639 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) 2656 if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
2640 fatal("%s: sshbuf_dup_string failed", __func__); 2657 fatal("%s: sshbuf_dup_string failed", __func__);
2641 linenum = 1; 2658 linenum = 1;
2642 while ((cp = strsep(&cbuf, "\n")) != NULL) { 2659 while ((cp = strsep(&cbuf, "\n")) != NULL) {
2643 if (process_server_config_line_depth(options, cp, 2660 if (process_server_config_line_depth(options, cp,
2644 filename, linenum++, activep, connectinfo, flags, 2661 filename, linenum++, activep, connectinfo, &flags,
2645 depth, includes) != 0) 2662 depth, includes) != 0)
2646 bad_options++; 2663 bad_options++;
2647 } 2664 }
@@ -2658,7 +2675,7 @@ parse_server_config(ServerOptions *options, const char *filename,
2658{ 2675{
2659 int active = connectinfo ? 0 : 1; 2676 int active = connectinfo ? 0 : 1;
2660 parse_server_config_depth(options, filename, conf, includes, 2677 parse_server_config_depth(options, filename, conf, includes,
2661 connectinfo, 0, &active, 0); 2678 connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
2662 process_queued_listen_addrs(options); 2679 process_queued_listen_addrs(options);
2663} 2680}
2664 2681
@@ -2965,11 +2982,11 @@ dump_config(ServerOptions *o)
2965 } 2982 }
2966 printf("\n"); 2983 printf("\n");
2967 2984
2968 if (o->permit_user_env_whitelist == NULL) { 2985 if (o->permit_user_env_allowlist == NULL) {
2969 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2986 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
2970 } else { 2987 } else {
2971 printf("permituserenvironment %s\n", 2988 printf("permituserenvironment %s\n",
2972 o->permit_user_env_whitelist); 2989 o->permit_user_env_allowlist);
2973 } 2990 }
2974 2991
2975 printf("pubkeyauthoptions"); 2992 printf("pubkeyauthoptions");
@@ -2977,5 +2994,7 @@ dump_config(ServerOptions *o)
2977 printf(" none"); 2994 printf(" none");
2978 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) 2995 if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
2979 printf(" touch-required"); 2996 printf(" touch-required");
2997 if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
2998 printf(" verify-required");
2980 printf("\n"); 2999 printf("\n");
2981} 3000}