xref: /dragonfly/crypto/openssh/servconf.c (revision ba1276ac)
1 /* $OpenBSD: servconf.c,v 1.411 2024/06/12 22:36:00 djm Exp $ */
2 /*
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  *
6  * As far as I am concerned, the code I have written for this software
7  * can be used freely for any purpose.  Any derived versions of this
8  * software must be clearly marked as such, and if the derived work is
9  * incompatible with the protocol description in the RFC file, it must be
10  * called by a name other than "ssh" or "Secure Shell".
11  */
12 
13 #include "includes.h"
14 
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/stat.h>
18 #ifdef __OpenBSD__
19 #include <sys/sysctl.h>
20 #endif
21 
22 #include <netinet/in.h>
23 #include <netinet/in_systm.h>
24 #include <netinet/ip.h>
25 #ifdef HAVE_NET_ROUTE_H
26 #include <net/route.h>
27 #endif
28 
29 #include <ctype.h>
30 #include <netdb.h>
31 #include <pwd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <signal.h>
36 #include <unistd.h>
37 #include <limits.h>
38 #include <stdarg.h>
39 #include <errno.h>
40 #ifdef HAVE_UTIL_H
41 #include <util.h>
42 #endif
43 #ifdef USE_SYSTEM_GLOB
44 # include <glob.h>
45 #else
46 # include "openbsd-compat/glob.h"
47 #endif
48 
49 #include "openbsd-compat/sys-queue.h"
50 #include "xmalloc.h"
51 #include "ssh.h"
52 #include "log.h"
53 #include "sshbuf.h"
54 #include "misc.h"
55 #include "servconf.h"
56 #include "pathnames.h"
57 #include "cipher.h"
58 #include "sshkey.h"
59 #include "kex.h"
60 #include "mac.h"
61 #include "match.h"
62 #include "channels.h"
63 #include "groupaccess.h"
64 #include "canohost.h"
65 #include "packet.h"
66 #include "ssherr.h"
67 #include "hostfile.h"
68 #include "auth.h"
69 #include "myproposal.h"
70 #include "digest.h"
71 
72 #if !defined(SSHD_PAM_SERVICE)
73 # define SSHD_PAM_SERVICE		"sshd"
74 #endif
75 
76 static void add_listen_addr(ServerOptions *, const char *,
77     const char *, int);
78 static void add_one_listen_addr(ServerOptions *, const char *,
79     const char *, int);
80 static void parse_server_config_depth(ServerOptions *options,
81     const char *filename, struct sshbuf *conf, struct include_list *includes,
82     struct connection_info *connectinfo, int flags, int *activep, int depth);
83 
84 extern struct sshbuf *cfg;
85 
86 /* Initializes the server options to their default values. */
87 
88 void
initialize_server_options(ServerOptions * options)89 initialize_server_options(ServerOptions *options)
90 {
91 	memset(options, 0, sizeof(*options));
92 
93 	/* Portable-specific options */
94 	options->use_pam = -1;
95 	options->pam_service_name = NULL;
96 
97 	/* Standard Options */
98 	options->num_ports = 0;
99 	options->ports_from_cmdline = 0;
100 	options->queued_listen_addrs = NULL;
101 	options->num_queued_listens = 0;
102 	options->listen_addrs = NULL;
103 	options->num_listen_addrs = 0;
104 	options->address_family = -1;
105 	options->routing_domain = NULL;
106 	options->num_host_key_files = 0;
107 	options->num_host_cert_files = 0;
108 	options->host_key_agent = NULL;
109 	options->pid_file = NULL;
110 	options->login_grace_time = -1;
111 	options->permit_root_login = PERMIT_NOT_SET;
112 	options->ignore_rhosts = -1;
113 	options->ignore_user_known_hosts = -1;
114 	options->print_motd = -1;
115 	options->print_lastlog = -1;
116 	options->x11_forwarding = -1;
117 	options->x11_display_offset = -1;
118 	options->x11_use_localhost = -1;
119 	options->permit_tty = -1;
120 	options->permit_user_rc = -1;
121 	options->xauth_location = NULL;
122 	options->strict_modes = -1;
123 	options->tcp_keep_alive = -1;
124 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
125 	options->log_level = SYSLOG_LEVEL_NOT_SET;
126 	options->num_log_verbose = 0;
127 	options->log_verbose = NULL;
128 	options->hostbased_authentication = -1;
129 	options->hostbased_uses_name_from_packet_only = -1;
130 	options->hostbased_accepted_algos = NULL;
131 	options->hostkeyalgorithms = NULL;
132 	options->pubkey_authentication = -1;
133 	options->pubkey_auth_options = -1;
134 	options->pubkey_accepted_algos = NULL;
135 	options->kerberos_authentication = -1;
136 	options->kerberos_or_local_passwd = -1;
137 	options->kerberos_ticket_cleanup = -1;
138 	options->kerberos_get_afs_token = -1;
139 	options->gss_authentication=-1;
140 	options->gss_cleanup_creds = -1;
141 	options->gss_strict_acceptor = -1;
142 	options->password_authentication = -1;
143 	options->kbd_interactive_authentication = -1;
144 	options->permit_empty_passwd = -1;
145 	options->permit_user_env = -1;
146 	options->permit_user_env_allowlist = NULL;
147 	options->compression = -1;
148 	options->rekey_limit = -1;
149 	options->rekey_interval = -1;
150 	options->allow_tcp_forwarding = -1;
151 	options->allow_streamlocal_forwarding = -1;
152 	options->allow_agent_forwarding = -1;
153 	options->num_allow_users = 0;
154 	options->num_deny_users = 0;
155 	options->num_allow_groups = 0;
156 	options->num_deny_groups = 0;
157 	options->ciphers = NULL;
158 	options->macs = NULL;
159 	options->kex_algorithms = NULL;
160 	options->ca_sign_algorithms = NULL;
161 	options->fwd_opts.gateway_ports = -1;
162 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
163 	options->fwd_opts.streamlocal_bind_unlink = -1;
164 	options->num_subsystems = 0;
165 	options->max_startups_begin = -1;
166 	options->max_startups_rate = -1;
167 	options->max_startups = -1;
168 	options->per_source_max_startups = -1;
169 	options->per_source_masklen_ipv4 = -1;
170 	options->per_source_masklen_ipv6 = -1;
171 	options->per_source_penalty_exempt = NULL;
172 	options->per_source_penalty.enabled = -1;
173 	options->per_source_penalty.max_sources4 = -1;
174 	options->per_source_penalty.max_sources6 = -1;
175 	options->per_source_penalty.overflow_mode = -1;
176 	options->per_source_penalty.overflow_mode6 = -1;
177 	options->per_source_penalty.penalty_crash = -1;
178 	options->per_source_penalty.penalty_authfail = -1;
179 	options->per_source_penalty.penalty_noauth = -1;
180 	options->per_source_penalty.penalty_grace = -1;
181 	options->per_source_penalty.penalty_max = -1;
182 	options->per_source_penalty.penalty_min = -1;
183 	options->max_authtries = -1;
184 	options->max_sessions = -1;
185 	options->banner = NULL;
186 	options->use_dns = -1;
187 	options->client_alive_interval = -1;
188 	options->client_alive_count_max = -1;
189 	options->num_authkeys_files = 0;
190 	options->num_accept_env = 0;
191 	options->num_setenv = 0;
192 	options->permit_tun = -1;
193 	options->permitted_opens = NULL;
194 	options->permitted_listens = NULL;
195 	options->adm_forced_command = NULL;
196 	options->chroot_directory = NULL;
197 	options->authorized_keys_command = NULL;
198 	options->authorized_keys_command_user = NULL;
199 	options->revoked_keys_file = NULL;
200 	options->sk_provider = NULL;
201 	options->trusted_user_ca_keys = NULL;
202 	options->authorized_principals_file = NULL;
203 	options->authorized_principals_command = NULL;
204 	options->authorized_principals_command_user = NULL;
205 	options->ip_qos_interactive = -1;
206 	options->ip_qos_bulk = -1;
207 	options->version_addendum = NULL;
208 	options->fingerprint_hash = -1;
209 	options->disable_forwarding = -1;
210 	options->expose_userauth_info = -1;
211 	options->required_rsa_size = -1;
212 	options->channel_timeouts = NULL;
213 	options->num_channel_timeouts = 0;
214 	options->unused_connection_timeout = -1;
215 	options->sshd_session_path = NULL;
216 }
217 
218 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
219 static int
option_clear_or_none(const char * o)220 option_clear_or_none(const char *o)
221 {
222 	return o == NULL || strcasecmp(o, "none") == 0;
223 }
224 
225 static void
assemble_algorithms(ServerOptions * o)226 assemble_algorithms(ServerOptions *o)
227 {
228 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
229 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
230 	int r;
231 
232 	all_cipher = cipher_alg_list(',', 0);
233 	all_mac = mac_alg_list(',');
234 	all_kex = kex_alg_list(',');
235 	all_key = sshkey_alg_list(0, 0, 1, ',');
236 	all_sig = sshkey_alg_list(0, 1, 1, ',');
237 	/* remove unsupported algos from default lists */
238 	def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
239 	def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
240 	def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
241 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
242 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
243 #define ASSEMBLE(what, defaults, all) \
244 	do { \
245 		if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
246 			fatal_fr(r, "%s", #what); \
247 	} while (0)
248 	ASSEMBLE(ciphers, def_cipher, all_cipher);
249 	ASSEMBLE(macs, def_mac, all_mac);
250 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
251 	ASSEMBLE(hostkeyalgorithms, def_key, all_key);
252 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
253 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
254 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
255 #undef ASSEMBLE
256 	free(all_cipher);
257 	free(all_mac);
258 	free(all_kex);
259 	free(all_key);
260 	free(all_sig);
261 	free(def_cipher);
262 	free(def_mac);
263 	free(def_kex);
264 	free(def_key);
265 	free(def_sig);
266 }
267 
268 void
servconf_add_hostkey(const char * file,const int line,ServerOptions * options,const char * path,int userprovided)269 servconf_add_hostkey(const char *file, const int line,
270     ServerOptions *options, const char *path, int userprovided)
271 {
272 	char *apath = derelativise_path(path);
273 
274 	opt_array_append2(file, line, "HostKey",
275 	    &options->host_key_files, &options->host_key_file_userprovided,
276 	    &options->num_host_key_files, apath, userprovided);
277 	free(apath);
278 }
279 
280 void
servconf_add_hostcert(const char * file,const int line,ServerOptions * options,const char * path)281 servconf_add_hostcert(const char *file, const int line,
282     ServerOptions *options, const char *path)
283 {
284 	char *apath = derelativise_path(path);
285 
286 	opt_array_append(file, line, "HostCertificate",
287 	    &options->host_cert_files, &options->num_host_cert_files, apath);
288 	free(apath);
289 }
290 
291 void
fill_default_server_options(ServerOptions * options)292 fill_default_server_options(ServerOptions *options)
293 {
294 	u_int i;
295 
296 	/* Portable-specific options */
297 	if (options->use_pam == -1)
298 		options->use_pam = 0;
299 	if (options->pam_service_name == NULL)
300 		options->pam_service_name = xstrdup(SSHD_PAM_SERVICE);
301 
302 	/* Standard Options */
303 	if (options->num_host_key_files == 0) {
304 		/* fill default hostkeys for protocols */
305 		servconf_add_hostkey("[default]", 0, options,
306 		    _PATH_HOST_RSA_KEY_FILE, 0);
307 #ifdef OPENSSL_HAS_ECC
308 		servconf_add_hostkey("[default]", 0, options,
309 		    _PATH_HOST_ECDSA_KEY_FILE, 0);
310 #endif
311 		servconf_add_hostkey("[default]", 0, options,
312 		    _PATH_HOST_ED25519_KEY_FILE, 0);
313 #ifdef WITH_XMSS
314 		servconf_add_hostkey("[default]", 0, options,
315 		    _PATH_HOST_XMSS_KEY_FILE, 0);
316 #endif /* WITH_XMSS */
317 	}
318 	/* No certificates by default */
319 	if (options->num_ports == 0)
320 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
321 	if (options->address_family == -1)
322 		options->address_family = AF_UNSPEC;
323 	if (options->listen_addrs == NULL)
324 		add_listen_addr(options, NULL, NULL, 0);
325 	if (options->pid_file == NULL)
326 		options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
327 	if (options->moduli_file == NULL)
328 		options->moduli_file = xstrdup(_PATH_DH_MODULI);
329 	if (options->login_grace_time == -1)
330 		options->login_grace_time = 120;
331 	if (options->permit_root_login == PERMIT_NOT_SET)
332 		options->permit_root_login = PERMIT_NO_PASSWD;
333 	if (options->ignore_rhosts == -1)
334 		options->ignore_rhosts = 1;
335 	if (options->ignore_user_known_hosts == -1)
336 		options->ignore_user_known_hosts = 0;
337 	if (options->print_motd == -1)
338 		options->print_motd = 1;
339 	if (options->print_lastlog == -1)
340 		options->print_lastlog = 1;
341 	if (options->x11_forwarding == -1)
342 		options->x11_forwarding = 0;
343 	if (options->x11_display_offset == -1)
344 		options->x11_display_offset = 10;
345 	if (options->x11_use_localhost == -1)
346 		options->x11_use_localhost = 1;
347 	if (options->xauth_location == NULL)
348 		options->xauth_location = xstrdup(_PATH_XAUTH);
349 	if (options->permit_tty == -1)
350 		options->permit_tty = 1;
351 	if (options->permit_user_rc == -1)
352 		options->permit_user_rc = 1;
353 	if (options->strict_modes == -1)
354 		options->strict_modes = 1;
355 	if (options->tcp_keep_alive == -1)
356 		options->tcp_keep_alive = 1;
357 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
358 		options->log_facility = SYSLOG_FACILITY_AUTH;
359 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
360 		options->log_level = SYSLOG_LEVEL_INFO;
361 	if (options->hostbased_authentication == -1)
362 		options->hostbased_authentication = 0;
363 	if (options->hostbased_uses_name_from_packet_only == -1)
364 		options->hostbased_uses_name_from_packet_only = 0;
365 	if (options->pubkey_authentication == -1)
366 		options->pubkey_authentication = 1;
367 	if (options->pubkey_auth_options == -1)
368 		options->pubkey_auth_options = 0;
369 	if (options->kerberos_authentication == -1)
370 		options->kerberos_authentication = 0;
371 	if (options->kerberos_or_local_passwd == -1)
372 		options->kerberos_or_local_passwd = 1;
373 	if (options->kerberos_ticket_cleanup == -1)
374 		options->kerberos_ticket_cleanup = 1;
375 	if (options->kerberos_get_afs_token == -1)
376 		options->kerberos_get_afs_token = 0;
377 	if (options->gss_authentication == -1)
378 		options->gss_authentication = 0;
379 	if (options->gss_cleanup_creds == -1)
380 		options->gss_cleanup_creds = 1;
381 	if (options->gss_strict_acceptor == -1)
382 		options->gss_strict_acceptor = 1;
383 	if (options->password_authentication == -1)
384 		options->password_authentication = 1;
385 	if (options->kbd_interactive_authentication == -1)
386 		options->kbd_interactive_authentication = 1;
387 	if (options->permit_empty_passwd == -1)
388 		options->permit_empty_passwd = 0;
389 	if (options->permit_user_env == -1) {
390 		options->permit_user_env = 0;
391 		options->permit_user_env_allowlist = NULL;
392 	}
393 	if (options->compression == -1)
394 #ifdef WITH_ZLIB
395 		options->compression = COMP_DELAYED;
396 #else
397 		options->compression = COMP_NONE;
398 #endif
399 
400 	if (options->rekey_limit == -1)
401 		options->rekey_limit = 0;
402 	if (options->rekey_interval == -1)
403 		options->rekey_interval = 0;
404 	if (options->allow_tcp_forwarding == -1)
405 		options->allow_tcp_forwarding = FORWARD_ALLOW;
406 	if (options->allow_streamlocal_forwarding == -1)
407 		options->allow_streamlocal_forwarding = FORWARD_ALLOW;
408 	if (options->allow_agent_forwarding == -1)
409 		options->allow_agent_forwarding = 1;
410 	if (options->fwd_opts.gateway_ports == -1)
411 		options->fwd_opts.gateway_ports = 0;
412 	if (options->max_startups == -1)
413 		options->max_startups = 100;
414 	if (options->max_startups_rate == -1)
415 		options->max_startups_rate = 30;		/* 30% */
416 	if (options->max_startups_begin == -1)
417 		options->max_startups_begin = 10;
418 	if (options->per_source_max_startups == -1)
419 		options->per_source_max_startups = INT_MAX;
420 	if (options->per_source_masklen_ipv4 == -1)
421 		options->per_source_masklen_ipv4 = 32;
422 	if (options->per_source_masklen_ipv6 == -1)
423 		options->per_source_masklen_ipv6 = 128;
424 	if (options->per_source_penalty.enabled == -1)
425 		options->per_source_penalty.enabled = 1;
426 	if (options->per_source_penalty.max_sources4 == -1)
427 		options->per_source_penalty.max_sources4 = 65536;
428 	if (options->per_source_penalty.max_sources6 == -1)
429 		options->per_source_penalty.max_sources6 = 65536;
430 	if (options->per_source_penalty.overflow_mode == -1)
431 		options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
432 	if (options->per_source_penalty.overflow_mode6 == -1)
433 		options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode;
434 	if (options->per_source_penalty.penalty_crash == -1)
435 		options->per_source_penalty.penalty_crash = 90;
436 	if (options->per_source_penalty.penalty_grace == -1)
437 		options->per_source_penalty.penalty_grace = 20;
438 	if (options->per_source_penalty.penalty_authfail == -1)
439 		options->per_source_penalty.penalty_authfail = 5;
440 	if (options->per_source_penalty.penalty_noauth == -1)
441 		options->per_source_penalty.penalty_noauth = 1;
442 	if (options->per_source_penalty.penalty_min == -1)
443 		options->per_source_penalty.penalty_min = 15;
444 	if (options->per_source_penalty.penalty_max == -1)
445 		options->per_source_penalty.penalty_max = 600;
446 	if (options->max_authtries == -1)
447 		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
448 	if (options->max_sessions == -1)
449 		options->max_sessions = DEFAULT_SESSIONS_MAX;
450 	if (options->use_dns == -1)
451 		options->use_dns = 0;
452 	if (options->client_alive_interval == -1)
453 		options->client_alive_interval = 0;
454 	if (options->client_alive_count_max == -1)
455 		options->client_alive_count_max = 3;
456 	if (options->num_authkeys_files == 0) {
457 		opt_array_append("[default]", 0, "AuthorizedKeysFiles",
458 		    &options->authorized_keys_files,
459 		    &options->num_authkeys_files,
460 		    _PATH_SSH_USER_PERMITTED_KEYS);
461 		opt_array_append("[default]", 0, "AuthorizedKeysFiles",
462 		    &options->authorized_keys_files,
463 		    &options->num_authkeys_files,
464 		    _PATH_SSH_USER_PERMITTED_KEYS2);
465 	}
466 	if (options->permit_tun == -1)
467 		options->permit_tun = SSH_TUNMODE_NO;
468 	if (options->ip_qos_interactive == -1)
469 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
470 	if (options->ip_qos_bulk == -1)
471 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
472 	if (options->version_addendum == NULL)
473 		options->version_addendum = xstrdup("");
474 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
475 		options->fwd_opts.streamlocal_bind_mask = 0177;
476 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
477 		options->fwd_opts.streamlocal_bind_unlink = 0;
478 	if (options->fingerprint_hash == -1)
479 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
480 	if (options->disable_forwarding == -1)
481 		options->disable_forwarding = 0;
482 	if (options->expose_userauth_info == -1)
483 		options->expose_userauth_info = 0;
484 	if (options->sk_provider == NULL)
485 		options->sk_provider = xstrdup("internal");
486 	if (options->required_rsa_size == -1)
487 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
488 	if (options->unused_connection_timeout == -1)
489 		options->unused_connection_timeout = 0;
490 	if (options->sshd_session_path == NULL)
491 		options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION);
492 
493 	assemble_algorithms(options);
494 
495 #define CLEAR_ON_NONE(v) \
496 	do { \
497 		if (option_clear_or_none(v)) { \
498 			free(v); \
499 			v = NULL; \
500 		} \
501 	} while(0)
502 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
503 	do { \
504 		if (options->nv == 1 && \
505 		    strcasecmp(options->v[0], none) == 0) { \
506 			free(options->v[0]); \
507 			free(options->v); \
508 			options->v = NULL; \
509 			options->nv = 0; \
510 		} \
511 	} while (0)
512 	CLEAR_ON_NONE(options->pid_file);
513 	CLEAR_ON_NONE(options->xauth_location);
514 	CLEAR_ON_NONE(options->banner);
515 	CLEAR_ON_NONE(options->trusted_user_ca_keys);
516 	CLEAR_ON_NONE(options->revoked_keys_file);
517 	CLEAR_ON_NONE(options->sk_provider);
518 	CLEAR_ON_NONE(options->authorized_principals_file);
519 	CLEAR_ON_NONE(options->adm_forced_command);
520 	CLEAR_ON_NONE(options->chroot_directory);
521 	CLEAR_ON_NONE(options->routing_domain);
522 	CLEAR_ON_NONE(options->host_key_agent);
523 	CLEAR_ON_NONE(options->per_source_penalty_exempt);
524 
525 	for (i = 0; i < options->num_host_key_files; i++)
526 		CLEAR_ON_NONE(options->host_key_files[i]);
527 	for (i = 0; i < options->num_host_cert_files; i++)
528 		CLEAR_ON_NONE(options->host_cert_files[i]);
529 
530 	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
531 	CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any");
532 #undef CLEAR_ON_NONE
533 #undef CLEAR_ON_NONE_ARRAY
534 }
535 
536 /* Keyword tokens. */
537 typedef enum {
538 	sBadOption,		/* == unknown option */
539 	/* Portable-specific options */
540 	sUsePAM, sPAMServiceName,
541 	/* Standard Options */
542 	sPort, sHostKeyFile, sLoginGraceTime,
543 	sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
544 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
545 	sKerberosGetAFSToken, sPasswordAuthentication,
546 	sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
547 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
548 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
549 	sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
550 	sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
551 	sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
552 	sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile,
553 	sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms,
554 	sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
555 	sBanner, sUseDNS, sHostbasedAuthentication,
556 	sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms,
557 	sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
558 	sPerSourcePenalties, sPerSourcePenaltyExemptList,
559 	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
560 	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
561 	sAcceptEnv, sSetEnv, sPermitTunnel,
562 	sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
563 	sUsePrivilegeSeparation, sAllowAgentForwarding,
564 	sHostCertificate, sInclude,
565 	sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
566 	sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
567 	sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
568 	sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
569 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
570 	sStreamLocalBindMask, sStreamLocalBindUnlink,
571 	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
572 	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
573 	sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
574 	sSshdSessionPath,
575 	sDeprecated, sIgnore, sUnsupported
576 } ServerOpCodes;
577 
578 #define SSHCFG_GLOBAL		0x01	/* allowed in main section of config */
579 #define SSHCFG_MATCH		0x02	/* allowed inside a Match section */
580 #define SSHCFG_ALL		(SSHCFG_GLOBAL|SSHCFG_MATCH)
581 #define SSHCFG_NEVERMATCH	0x04  /* Match never matches; internal only */
582 #define SSHCFG_MATCH_ONLY	0x08  /* Match only in conditional blocks; internal only */
583 
584 /* Textual representation of the tokens. */
585 static struct {
586 	const char *name;
587 	ServerOpCodes opcode;
588 	u_int flags;
589 } keywords[] = {
590 	/* Portable-specific options */
591 #ifdef USE_PAM
592 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
593 	{ "pamservicename", sPAMServiceName, SSHCFG_ALL },
594 #else
595 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
596 	{ "pamservicename", sUnsupported, SSHCFG_ALL },
597 #endif
598 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
599 	/* Standard Options */
600 	{ "port", sPort, SSHCFG_GLOBAL },
601 	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
602 	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },		/* alias */
603 	{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
604 	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
605 	{ "modulifile", sModuliFile, SSHCFG_GLOBAL },
606 	{ "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
607 	{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
608 	{ "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
609 	{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
610 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
611 	{ "loglevel", sLogLevel, SSHCFG_ALL },
612 	{ "logverbose", sLogVerbose, SSHCFG_ALL },
613 	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
614 	{ "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
615 	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
616 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
617 	{ "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL },
618 	{ "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
619 	{ "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
620 	{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
621 	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
622 	{ "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL },
623 	{ "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
624 	{ "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
625 	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
626 #ifdef KRB5
627 	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
628 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
629 	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
630 #ifdef USE_AFS
631 	{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
632 #else
633 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
634 #endif
635 #else
636 	{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
637 	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
638 	{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
639 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
640 #endif
641 	{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
642 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
643 #ifdef GSSAPI
644 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
645 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
646 	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
647 #else
648 	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
649 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
650 	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
651 #endif
652 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
653 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
654 	{ "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
655 	{ "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
656 	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
657 	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
658 	{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
659 	{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
660 #ifdef DISABLE_LASTLOG
661 	{ "printlastlog", sUnsupported, SSHCFG_GLOBAL },
662 #else
663 	{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
664 #endif
665 	{ "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL },
666 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
667 	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
668 	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
669 	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
670 	{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
671 	{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
672 	{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
673 	{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
674 	{ "uselogin", sDeprecated, SSHCFG_GLOBAL },
675 	{ "compression", sCompression, SSHCFG_GLOBAL },
676 	{ "rekeylimit", sRekeyLimit, SSHCFG_ALL },
677 	{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
678 	{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },	/* obsolete alias */
679 	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
680 	{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
681 	{ "allowusers", sAllowUsers, SSHCFG_ALL },
682 	{ "denyusers", sDenyUsers, SSHCFG_ALL },
683 	{ "allowgroups", sAllowGroups, SSHCFG_ALL },
684 	{ "denygroups", sDenyGroups, SSHCFG_ALL },
685 	{ "ciphers", sCiphers, SSHCFG_GLOBAL },
686 	{ "macs", sMacs, SSHCFG_GLOBAL },
687 	{ "protocol", sIgnore, SSHCFG_GLOBAL },
688 	{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
689 	{ "subsystem", sSubsystem, SSHCFG_ALL },
690 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
691 	{ "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL },
692 	{ "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL },
693 	{ "persourcepenalties", sPerSourcePenalties, SSHCFG_GLOBAL },
694 	{ "persourcepenaltyexemptlist", sPerSourcePenaltyExemptList, SSHCFG_GLOBAL },
695 	{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
696 	{ "maxsessions", sMaxSessions, SSHCFG_ALL },
697 	{ "banner", sBanner, SSHCFG_ALL },
698 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
699 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
700 	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
701 	{ "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
702 	{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
703 	{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
704 	{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
705 	{ "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
706 	{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
707 	{ "setenv", sSetEnv, SSHCFG_ALL },
708 	{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
709 	{ "permittty", sPermitTTY, SSHCFG_ALL },
710 	{ "permituserrc", sPermitUserRC, SSHCFG_ALL },
711 	{ "match", sMatch, SSHCFG_ALL },
712 	{ "permitopen", sPermitOpen, SSHCFG_ALL },
713 	{ "permitlisten", sPermitListen, SSHCFG_ALL },
714 	{ "forcecommand", sForceCommand, SSHCFG_ALL },
715 	{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
716 	{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
717 	{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
718 	{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
719 	{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
720 	{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
721 	{ "include", sInclude, SSHCFG_ALL },
722 	{ "ipqos", sIPQoS, SSHCFG_ALL },
723 	{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
724 	{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
725 	{ "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
726 	{ "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
727 	{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
728 	{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
729 	{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
730 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
731 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
732 	{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
733 	{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
734 	{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
735 	{ "rdomain", sRDomain, SSHCFG_ALL },
736 	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
737 	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
738 	{ "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
739 	{ "channeltimeout", sChannelTimeout, SSHCFG_ALL },
740 	{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
741 	{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
742 	{ NULL, sBadOption, 0 }
743 };
744 
745 static struct {
746 	int val;
747 	char *text;
748 } tunmode_desc[] = {
749 	{ SSH_TUNMODE_NO, "no" },
750 	{ SSH_TUNMODE_POINTOPOINT, "point-to-point" },
751 	{ SSH_TUNMODE_ETHERNET, "ethernet" },
752 	{ SSH_TUNMODE_YES, "yes" },
753 	{ -1, NULL }
754 };
755 
756 /* Returns an opcode name from its number */
757 
758 static const char *
lookup_opcode_name(ServerOpCodes code)759 lookup_opcode_name(ServerOpCodes code)
760 {
761 	u_int i;
762 
763 	for (i = 0; keywords[i].name != NULL; i++)
764 		if (keywords[i].opcode == code)
765 			return(keywords[i].name);
766 	return "UNKNOWN";
767 }
768 
769 
770 /*
771  * Returns the number of the token pointed to by cp or sBadOption.
772  */
773 
774 static ServerOpCodes
parse_token(const char * cp,const char * filename,int linenum,u_int * flags)775 parse_token(const char *cp, const char *filename,
776 	    int linenum, u_int *flags)
777 {
778 	u_int i;
779 
780 	for (i = 0; keywords[i].name; i++)
781 		if (strcasecmp(cp, keywords[i].name) == 0) {
782 			*flags = keywords[i].flags;
783 			return keywords[i].opcode;
784 		}
785 
786 	error("%s: line %d: Bad configuration option: %s",
787 	    filename, linenum, cp);
788 	return sBadOption;
789 }
790 
791 char *
derelativise_path(const char * path)792 derelativise_path(const char *path)
793 {
794 	char *expanded, *ret, cwd[PATH_MAX];
795 
796 	if (strcasecmp(path, "none") == 0)
797 		return xstrdup("none");
798 	expanded = tilde_expand_filename(path, getuid());
799 	if (path_absolute(expanded))
800 		return expanded;
801 	if (getcwd(cwd, sizeof(cwd)) == NULL)
802 		fatal_f("getcwd: %s", strerror(errno));
803 	xasprintf(&ret, "%s/%s", cwd, expanded);
804 	free(expanded);
805 	return ret;
806 }
807 
808 static void
add_listen_addr(ServerOptions * options,const char * addr,const char * rdomain,int port)809 add_listen_addr(ServerOptions *options, const char *addr,
810     const char *rdomain, int port)
811 {
812 	u_int i;
813 
814 	if (port > 0)
815 		add_one_listen_addr(options, addr, rdomain, port);
816 	else {
817 		for (i = 0; i < options->num_ports; i++) {
818 			add_one_listen_addr(options, addr, rdomain,
819 			    options->ports[i]);
820 		}
821 	}
822 }
823 
824 static void
add_one_listen_addr(ServerOptions * options,const char * addr,const char * rdomain,int port)825 add_one_listen_addr(ServerOptions *options, const char *addr,
826     const char *rdomain, int port)
827 {
828 	struct addrinfo hints, *ai, *aitop;
829 	char strport[NI_MAXSERV];
830 	int gaierr;
831 	u_int i;
832 
833 	/* Find listen_addrs entry for this rdomain */
834 	for (i = 0; i < options->num_listen_addrs; i++) {
835 		if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
836 			break;
837 		if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
838 			continue;
839 		if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
840 			break;
841 	}
842 	if (i >= options->num_listen_addrs) {
843 		/* No entry for this rdomain; allocate one */
844 		if (i >= INT_MAX)
845 			fatal_f("too many listen addresses");
846 		options->listen_addrs = xrecallocarray(options->listen_addrs,
847 		    options->num_listen_addrs, options->num_listen_addrs + 1,
848 		    sizeof(*options->listen_addrs));
849 		i = options->num_listen_addrs++;
850 		if (rdomain != NULL)
851 			options->listen_addrs[i].rdomain = xstrdup(rdomain);
852 	}
853 	/* options->listen_addrs[i] points to the addresses for this rdomain */
854 
855 	memset(&hints, 0, sizeof(hints));
856 	hints.ai_family = options->address_family;
857 	hints.ai_socktype = SOCK_STREAM;
858 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
859 	snprintf(strport, sizeof strport, "%d", port);
860 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
861 		fatal("bad addr or host: %s (%s)",
862 		    addr ? addr : "<NULL>",
863 		    ssh_gai_strerror(gaierr));
864 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
865 		;
866 	ai->ai_next = options->listen_addrs[i].addrs;
867 	options->listen_addrs[i].addrs = aitop;
868 }
869 
870 /* Returns nonzero if the routing domain name is valid */
871 static int
valid_rdomain(const char * name)872 valid_rdomain(const char *name)
873 {
874 #if defined(HAVE_SYS_VALID_RDOMAIN)
875 	return sys_valid_rdomain(name);
876 #elif defined(__OpenBSD__)
877 	const char *errstr;
878 	long long num;
879 	struct rt_tableinfo info;
880 	int mib[6];
881 	size_t miblen = sizeof(mib);
882 
883 	if (name == NULL)
884 		return 1;
885 
886 	num = strtonum(name, 0, 255, &errstr);
887 	if (errstr != NULL)
888 		return 0;
889 
890 	/* Check whether the table actually exists */
891 	memset(mib, 0, sizeof(mib));
892 	mib[0] = CTL_NET;
893 	mib[1] = PF_ROUTE;
894 	mib[4] = NET_RT_TABLE;
895 	mib[5] = (int)num;
896 	if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
897 		return 0;
898 
899 	return 1;
900 #else /* defined(__OpenBSD__) */
901 	error("Routing domains are not supported on this platform");
902 	return 0;
903 #endif
904 }
905 
906 /*
907  * Queue a ListenAddress to be processed once we have all of the Ports
908  * and AddressFamily options.
909  */
910 static void
queue_listen_addr(ServerOptions * options,const char * addr,const char * rdomain,int port)911 queue_listen_addr(ServerOptions *options, const char *addr,
912     const char *rdomain, int port)
913 {
914 	struct queued_listenaddr *qla;
915 
916 	options->queued_listen_addrs = xrecallocarray(
917 	    options->queued_listen_addrs,
918 	    options->num_queued_listens, options->num_queued_listens + 1,
919 	    sizeof(*options->queued_listen_addrs));
920 	qla = &options->queued_listen_addrs[options->num_queued_listens++];
921 	qla->addr = xstrdup(addr);
922 	qla->port = port;
923 	qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
924 }
925 
926 /*
927  * Process queued (text) ListenAddress entries.
928  */
929 static void
process_queued_listen_addrs(ServerOptions * options)930 process_queued_listen_addrs(ServerOptions *options)
931 {
932 	u_int i;
933 	struct queued_listenaddr *qla;
934 
935 	if (options->num_ports == 0)
936 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
937 	if (options->address_family == -1)
938 		options->address_family = AF_UNSPEC;
939 
940 	for (i = 0; i < options->num_queued_listens; i++) {
941 		qla = &options->queued_listen_addrs[i];
942 		add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
943 		free(qla->addr);
944 		free(qla->rdomain);
945 	}
946 	free(options->queued_listen_addrs);
947 	options->queued_listen_addrs = NULL;
948 	options->num_queued_listens = 0;
949 }
950 
951 /*
952  * The strategy for the Match blocks is that the config file is parsed twice.
953  *
954  * The first time is at startup.  activep is initialized to 1 and the
955  * directives in the global context are processed and acted on.  Hitting a
956  * Match directive unsets activep and the directives inside the block are
957  * checked for syntax only.
958  *
959  * The second time is after a connection has been established but before
960  * authentication.  activep is initialized to 2 and global config directives
961  * are ignored since they have already been processed.  If the criteria in a
962  * Match block is met, activep is set and the subsequent directives
963  * processed and actioned until EOF or another Match block unsets it.  Any
964  * options set are copied into the main server config.
965  *
966  * Potential additions/improvements:
967  *  - Add Match support for pre-kex directives, eg. Ciphers.
968  *
969  *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
970  *	Match Address 192.168.0.*
971  *		Tag trusted
972  *	Match Group wheel
973  *		Tag trusted
974  *	Match Tag trusted
975  *		AllowTcpForwarding yes
976  *		GatewayPorts clientspecified
977  *		[...]
978  *
979  *  - Add a PermittedChannelRequests directive
980  *	Match Group shell
981  *		PermittedChannelRequests session,forwarded-tcpip
982  */
983 
984 static int
match_cfg_line_group(const char * grps,int line,const char * user)985 match_cfg_line_group(const char *grps, int line, const char *user)
986 {
987 	int result = 0;
988 	struct passwd *pw;
989 
990 	if (user == NULL)
991 		goto out;
992 
993 	if ((pw = getpwnam(user)) == NULL) {
994 		debug("Can't match group at line %d because user %.100s does "
995 		    "not exist", line, user);
996 	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
997 		debug("Can't Match group because user %.100s not in any group "
998 		    "at line %d", user, line);
999 	} else if (ga_match_pattern_list(grps) != 1) {
1000 		debug("user %.100s does not match group list %.100s at line %d",
1001 		    user, grps, line);
1002 	} else {
1003 		debug("user %.100s matched group list %.100s at line %d", user,
1004 		    grps, line);
1005 		result = 1;
1006 	}
1007 out:
1008 	ga_free();
1009 	return result;
1010 }
1011 
1012 static void
match_test_missing_fatal(const char * criteria,const char * attrib)1013 match_test_missing_fatal(const char *criteria, const char *attrib)
1014 {
1015 	fatal("'Match %s' in configuration but '%s' not in connection "
1016 	    "test specification.", criteria, attrib);
1017 }
1018 
1019 /*
1020  * All of the attributes on a single Match line are ANDed together, so we need
1021  * to check every attribute and set the result to zero if any attribute does
1022  * not match.
1023  */
1024 static int
match_cfg_line(char ** condition,int line,struct connection_info * ci)1025 match_cfg_line(char **condition, int line, struct connection_info *ci)
1026 {
1027 	int result = 1, attributes = 0, port;
1028 	char *arg, *attrib, *cp = *condition;
1029 
1030 	if (ci == NULL)
1031 		debug3("checking syntax for 'Match %s'", cp);
1032 	else
1033 		debug3("checking match for '%s' user %s host %s addr %s "
1034 		    "laddr %s lport %d", cp, ci->user ? ci->user : "(null)",
1035 		    ci->host ? ci->host : "(null)",
1036 		    ci->address ? ci->address : "(null)",
1037 		    ci->laddress ? ci->laddress : "(null)", ci->lport);
1038 
1039 	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
1040 		/* Terminate on comment */
1041 		if (*attrib == '#') {
1042 			cp = NULL; /* mark all arguments consumed */
1043 			break;
1044 		}
1045 		arg = NULL;
1046 		attributes++;
1047 		/* Criterion "all" has no argument and must appear alone */
1048 		if (strcasecmp(attrib, "all") == 0) {
1049 			if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
1050 			    *arg != '\0' && *arg != '#')) {
1051 				error("'all' cannot be combined with other "
1052 				    "Match attributes");
1053 				return -1;
1054 			}
1055 			if (arg != NULL && *arg == '#')
1056 				cp = NULL; /* mark all arguments consumed */
1057 			*condition = cp;
1058 			return 1;
1059 		}
1060 		/* All other criteria require an argument */
1061 		if ((arg = strdelim(&cp)) == NULL ||
1062 		    *arg == '\0' || *arg == '#') {
1063 			error("Missing Match criteria for %s", attrib);
1064 			return -1;
1065 		}
1066 		if (strcasecmp(attrib, "user") == 0) {
1067 			if (ci == NULL || (ci->test && ci->user == NULL)) {
1068 				result = 0;
1069 				continue;
1070 			}
1071 			if (ci->user == NULL)
1072 				match_test_missing_fatal("User", "user");
1073 			if (match_usergroup_pattern_list(ci->user, arg) != 1)
1074 				result = 0;
1075 			else
1076 				debug("user %.100s matched 'User %.100s' at "
1077 				    "line %d", ci->user, arg, line);
1078 		} else if (strcasecmp(attrib, "group") == 0) {
1079 			if (ci == NULL || (ci->test && ci->user == NULL)) {
1080 				result = 0;
1081 				continue;
1082 			}
1083 			if (ci->user == NULL)
1084 				match_test_missing_fatal("Group", "user");
1085 			switch (match_cfg_line_group(arg, line, ci->user)) {
1086 			case -1:
1087 				return -1;
1088 			case 0:
1089 				result = 0;
1090 			}
1091 		} else if (strcasecmp(attrib, "host") == 0) {
1092 			if (ci == NULL || (ci->test && ci->host == NULL)) {
1093 				result = 0;
1094 				continue;
1095 			}
1096 			if (ci->host == NULL)
1097 				match_test_missing_fatal("Host", "host");
1098 			if (match_hostname(ci->host, arg) != 1)
1099 				result = 0;
1100 			else
1101 				debug("connection from %.100s matched 'Host "
1102 				    "%.100s' at line %d", ci->host, arg, line);
1103 		} else if (strcasecmp(attrib, "address") == 0) {
1104 			if (ci == NULL || (ci->test && ci->address == NULL)) {
1105 				if (addr_match_list(NULL, arg) != 0)
1106 					fatal("Invalid Match address argument "
1107 					    "'%s' at line %d", arg, line);
1108 				result = 0;
1109 				continue;
1110 			}
1111 			if (ci->address == NULL)
1112 				match_test_missing_fatal("Address", "addr");
1113 			switch (addr_match_list(ci->address, arg)) {
1114 			case 1:
1115 				debug("connection from %.100s matched 'Address "
1116 				    "%.100s' at line %d", ci->address, arg, line);
1117 				break;
1118 			case 0:
1119 			case -1:
1120 				result = 0;
1121 				break;
1122 			case -2:
1123 				return -1;
1124 			}
1125 		} else if (strcasecmp(attrib, "localaddress") == 0){
1126 			if (ci == NULL || (ci->test && ci->laddress == NULL)) {
1127 				if (addr_match_list(NULL, arg) != 0)
1128 					fatal("Invalid Match localaddress "
1129 					    "argument '%s' at line %d", arg,
1130 					    line);
1131 				result = 0;
1132 				continue;
1133 			}
1134 			if (ci->laddress == NULL)
1135 				match_test_missing_fatal("LocalAddress",
1136 				    "laddr");
1137 			switch (addr_match_list(ci->laddress, arg)) {
1138 			case 1:
1139 				debug("connection from %.100s matched "
1140 				    "'LocalAddress %.100s' at line %d",
1141 				    ci->laddress, arg, line);
1142 				break;
1143 			case 0:
1144 			case -1:
1145 				result = 0;
1146 				break;
1147 			case -2:
1148 				return -1;
1149 			}
1150 		} else if (strcasecmp(attrib, "localport") == 0) {
1151 			if ((port = a2port(arg)) == -1) {
1152 				error("Invalid LocalPort '%s' on Match line",
1153 				    arg);
1154 				return -1;
1155 			}
1156 			if (ci == NULL || (ci->test && ci->lport == -1)) {
1157 				result = 0;
1158 				continue;
1159 			}
1160 			if (ci->lport == 0)
1161 				match_test_missing_fatal("LocalPort", "lport");
1162 			/* TODO support port lists */
1163 			if (port == ci->lport)
1164 				debug("connection from %.100s matched "
1165 				    "'LocalPort %d' at line %d",
1166 				    ci->laddress, port, line);
1167 			else
1168 				result = 0;
1169 		} else if (strcasecmp(attrib, "rdomain") == 0) {
1170 			if (ci == NULL || (ci->test && ci->rdomain == NULL)) {
1171 				result = 0;
1172 				continue;
1173 			}
1174 			if (ci->rdomain == NULL)
1175 				match_test_missing_fatal("RDomain", "rdomain");
1176 			if (match_pattern_list(ci->rdomain, arg, 0) != 1)
1177 				result = 0;
1178 			else
1179 				debug("user %.100s matched 'RDomain %.100s' at "
1180 				    "line %d", ci->rdomain, arg, line);
1181 		} else {
1182 			error("Unsupported Match attribute %s", attrib);
1183 			return -1;
1184 		}
1185 	}
1186 	if (attributes == 0) {
1187 		error("One or more attributes required for Match");
1188 		return -1;
1189 	}
1190 	if (ci != NULL)
1191 		debug3("match %sfound", result ? "" : "not ");
1192 	*condition = cp;
1193 	return result;
1194 }
1195 
1196 #define WHITESPACE " \t\r\n"
1197 
1198 /* Multistate option parsing */
1199 struct multistate {
1200 	char *key;
1201 	int value;
1202 };
1203 static const struct multistate multistate_flag[] = {
1204 	{ "yes",			1 },
1205 	{ "no",				0 },
1206 	{ NULL, -1 }
1207 };
1208 static const struct multistate multistate_ignore_rhosts[] = {
1209 	{ "yes",			IGNORE_RHOSTS_YES },
1210 	{ "no",				IGNORE_RHOSTS_NO },
1211 	{ "shosts-only",		IGNORE_RHOSTS_SHOSTS },
1212 	{ NULL, -1 }
1213 };
1214 static const struct multistate multistate_addressfamily[] = {
1215 	{ "inet",			AF_INET },
1216 	{ "inet6",			AF_INET6 },
1217 	{ "any",			AF_UNSPEC },
1218 	{ NULL, -1 }
1219 };
1220 static const struct multistate multistate_permitrootlogin[] = {
1221 	{ "without-password",		PERMIT_NO_PASSWD },
1222 	{ "prohibit-password",		PERMIT_NO_PASSWD },
1223 	{ "forced-commands-only",	PERMIT_FORCED_ONLY },
1224 	{ "yes",			PERMIT_YES },
1225 	{ "no",				PERMIT_NO },
1226 	{ NULL, -1 }
1227 };
1228 static const struct multistate multistate_compression[] = {
1229 #ifdef WITH_ZLIB
1230 	{ "yes",			COMP_DELAYED },
1231 	{ "delayed",			COMP_DELAYED },
1232 #endif
1233 	{ "no",				COMP_NONE },
1234 	{ NULL, -1 }
1235 };
1236 static const struct multistate multistate_gatewayports[] = {
1237 	{ "clientspecified",		2 },
1238 	{ "yes",			1 },
1239 	{ "no",				0 },
1240 	{ NULL, -1 }
1241 };
1242 static const struct multistate multistate_tcpfwd[] = {
1243 	{ "yes",			FORWARD_ALLOW },
1244 	{ "all",			FORWARD_ALLOW },
1245 	{ "no",				FORWARD_DENY },
1246 	{ "remote",			FORWARD_REMOTE },
1247 	{ "local",			FORWARD_LOCAL },
1248 	{ NULL, -1 }
1249 };
1250 
1251 static int
process_server_config_line_depth(ServerOptions * options,char * line,const char * filename,int linenum,int * activep,struct connection_info * connectinfo,int * inc_flags,int depth,struct include_list * includes)1252 process_server_config_line_depth(ServerOptions *options, char *line,
1253     const char *filename, int linenum, int *activep,
1254     struct connection_info *connectinfo, int *inc_flags, int depth,
1255     struct include_list *includes)
1256 {
1257 	char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword;
1258 	int cmdline = 0, *intptr, value, value2, n, port, oactive, r;
1259 	int ca_only = 0, found = 0;
1260 	SyslogFacility *log_facility_ptr;
1261 	LogLevel *log_level_ptr;
1262 	ServerOpCodes opcode;
1263 	u_int i, *uintptr, flags = 0;
1264 	size_t len;
1265 	long long val64;
1266 	const struct multistate *multistate_ptr;
1267 	const char *errstr;
1268 	struct include_item *item;
1269 	glob_t gbuf;
1270 	char **oav = NULL, **av;
1271 	int oac = 0, ac;
1272 	int ret = -1;
1273 	char **strs = NULL; /* string array arguments; freed implicitly */
1274 	u_int nstrs = 0;
1275 
1276 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1277 	if ((len = strlen(line)) == 0)
1278 		return 0;
1279 	for (len--; len > 0; len--) {
1280 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
1281 			break;
1282 		line[len] = '\0';
1283 	}
1284 
1285 	str = line;
1286 	if ((keyword = strdelim(&str)) == NULL)
1287 		return 0;
1288 	/* Ignore leading whitespace */
1289 	if (*keyword == '\0')
1290 		keyword = strdelim(&str);
1291 	if (!keyword || !*keyword || *keyword == '#')
1292 		return 0;
1293 	if (str == NULL || *str == '\0') {
1294 		error("%s line %d: no argument after keyword \"%s\"",
1295 		    filename, linenum, keyword);
1296 		return -1;
1297 	}
1298 	intptr = NULL;
1299 	charptr = NULL;
1300 	opcode = parse_token(keyword, filename, linenum, &flags);
1301 
1302 	if (argv_split(str, &oac, &oav, 1) != 0) {
1303 		error("%s line %d: invalid quotes", filename, linenum);
1304 		return -1;
1305 	}
1306 	ac = oac;
1307 	av = oav;
1308 
1309 	if (activep == NULL) { /* We are processing a command line directive */
1310 		cmdline = 1;
1311 		activep = &cmdline;
1312 	}
1313 	if (*activep && opcode != sMatch && opcode != sInclude)
1314 		debug3("%s:%d setting %s %s", filename, linenum, keyword, str);
1315 	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
1316 		if (connectinfo == NULL) {
1317 			fatal("%s line %d: Directive '%s' is not allowed "
1318 			    "within a Match block", filename, linenum, keyword);
1319 		} else { /* this is a directive we have already processed */
1320 			ret = 0;
1321 			goto out;
1322 		}
1323 	}
1324 
1325 	switch (opcode) {
1326 	/* Portable-specific options */
1327 	case sUsePAM:
1328 		intptr = &options->use_pam;
1329 		goto parse_flag;
1330 	case sPAMServiceName:
1331 		charptr = &options->pam_service_name;
1332 		arg = argv_next(&ac, &av);
1333 		if (!arg || *arg == '\0') {
1334 			fatal("%s line %d: missing argument.",
1335 			    filename, linenum);
1336 		}
1337 		if (*activep && *charptr == NULL)
1338 			*charptr = xstrdup(arg);
1339 		break;
1340 
1341 	/* Standard Options */
1342 	case sBadOption:
1343 		goto out;
1344 	case sPort:
1345 		/* ignore ports from configfile if cmdline specifies ports */
1346 		if (options->ports_from_cmdline) {
1347 			argv_consume(&ac);
1348 			break;
1349 		}
1350 		if (options->num_ports >= MAX_PORTS)
1351 			fatal("%s line %d: too many ports.",
1352 			    filename, linenum);
1353 		arg = argv_next(&ac, &av);
1354 		if (!arg || *arg == '\0')
1355 			fatal("%s line %d: missing port number.",
1356 			    filename, linenum);
1357 		options->ports[options->num_ports++] = a2port(arg);
1358 		if (options->ports[options->num_ports-1] <= 0)
1359 			fatal("%s line %d: Badly formatted port number.",
1360 			    filename, linenum);
1361 		break;
1362 
1363 	case sLoginGraceTime:
1364 		intptr = &options->login_grace_time;
1365  parse_time:
1366 		arg = argv_next(&ac, &av);
1367 		if (!arg || *arg == '\0')
1368 			fatal("%s line %d: missing time value.",
1369 			    filename, linenum);
1370 		if ((value = convtime(arg)) == -1)
1371 			fatal("%s line %d: invalid time value.",
1372 			    filename, linenum);
1373 		if (*activep && *intptr == -1)
1374 			*intptr = value;
1375 		break;
1376 
1377 	case sListenAddress:
1378 		arg = argv_next(&ac, &av);
1379 		if (arg == NULL || *arg == '\0')
1380 			fatal("%s line %d: missing address",
1381 			    filename, linenum);
1382 		/* check for bare IPv6 address: no "[]" and 2 or more ":" */
1383 		if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
1384 		    && strchr(p+1, ':') != NULL) {
1385 			port = 0;
1386 			p = arg;
1387 		} else {
1388 			arg2 = NULL;
1389 			p = hpdelim(&arg);
1390 			if (p == NULL)
1391 				fatal("%s line %d: bad address:port usage",
1392 				    filename, linenum);
1393 			p = cleanhostname(p);
1394 			if (arg == NULL)
1395 				port = 0;
1396 			else if ((port = a2port(arg)) <= 0)
1397 				fatal("%s line %d: bad port number",
1398 				    filename, linenum);
1399 		}
1400 		/* Optional routing table */
1401 		arg2 = NULL;
1402 		if ((arg = argv_next(&ac, &av)) != NULL) {
1403 			if (strcmp(arg, "rdomain") != 0 ||
1404 			    (arg2 = argv_next(&ac, &av)) == NULL)
1405 				fatal("%s line %d: bad ListenAddress syntax",
1406 				    filename, linenum);
1407 			if (!valid_rdomain(arg2))
1408 				fatal("%s line %d: bad routing domain",
1409 				    filename, linenum);
1410 		}
1411 		queue_listen_addr(options, p, arg2, port);
1412 
1413 		break;
1414 
1415 	case sAddressFamily:
1416 		intptr = &options->address_family;
1417 		multistate_ptr = multistate_addressfamily;
1418  parse_multistate:
1419 		arg = argv_next(&ac, &av);
1420 		if (!arg || *arg == '\0')
1421 			fatal("%s line %d: missing argument.",
1422 			    filename, linenum);
1423 		value = -1;
1424 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1425 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1426 				value = multistate_ptr[i].value;
1427 				break;
1428 			}
1429 		}
1430 		if (value == -1)
1431 			fatal("%s line %d: unsupported option \"%s\".",
1432 			    filename, linenum, arg);
1433 		if (*activep && *intptr == -1)
1434 			*intptr = value;
1435 		break;
1436 
1437 	case sHostKeyFile:
1438 		arg = argv_next(&ac, &av);
1439 		if (!arg || *arg == '\0')
1440 			fatal("%s line %d: missing file name.",
1441 			    filename, linenum);
1442 		if (*activep) {
1443 			servconf_add_hostkey(filename, linenum,
1444 			    options, arg, 1);
1445 		}
1446 		break;
1447 
1448 	case sHostKeyAgent:
1449 		charptr = &options->host_key_agent;
1450 		arg = argv_next(&ac, &av);
1451 		if (!arg || *arg == '\0')
1452 			fatal("%s line %d: missing socket name.",
1453 			    filename, linenum);
1454 		if (*activep && *charptr == NULL)
1455 			*charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ?
1456 			    xstrdup(arg) : derelativise_path(arg);
1457 		break;
1458 
1459 	case sHostCertificate:
1460 		arg = argv_next(&ac, &av);
1461 		if (!arg || *arg == '\0')
1462 			fatal("%s line %d: missing file name.",
1463 			    filename, linenum);
1464 		if (*activep)
1465 			servconf_add_hostcert(filename, linenum, options, arg);
1466 		break;
1467 
1468 	case sPidFile:
1469 		charptr = &options->pid_file;
1470  parse_filename:
1471 		arg = argv_next(&ac, &av);
1472 		if (!arg || *arg == '\0')
1473 			fatal("%s line %d: missing file name.",
1474 			    filename, linenum);
1475 		if (*activep && *charptr == NULL) {
1476 			*charptr = derelativise_path(arg);
1477 			/* increase optional counter */
1478 			if (intptr != NULL)
1479 				*intptr = *intptr + 1;
1480 		}
1481 		break;
1482 
1483 	case sModuliFile:
1484 		charptr = &options->moduli_file;
1485 		goto parse_filename;
1486 
1487 	case sPermitRootLogin:
1488 		intptr = &options->permit_root_login;
1489 		multistate_ptr = multistate_permitrootlogin;
1490 		goto parse_multistate;
1491 
1492 	case sIgnoreRhosts:
1493 		intptr = &options->ignore_rhosts;
1494 		multistate_ptr = multistate_ignore_rhosts;
1495 		goto parse_multistate;
1496 
1497 	case sIgnoreUserKnownHosts:
1498 		intptr = &options->ignore_user_known_hosts;
1499  parse_flag:
1500 		multistate_ptr = multistate_flag;
1501 		goto parse_multistate;
1502 
1503 	case sHostbasedAuthentication:
1504 		intptr = &options->hostbased_authentication;
1505 		goto parse_flag;
1506 
1507 	case sHostbasedUsesNameFromPacketOnly:
1508 		intptr = &options->hostbased_uses_name_from_packet_only;
1509 		goto parse_flag;
1510 
1511 	case sHostbasedAcceptedAlgorithms:
1512 		charptr = &options->hostbased_accepted_algos;
1513 		ca_only = 0;
1514  parse_pubkey_algos:
1515 		arg = argv_next(&ac, &av);
1516 		if (!arg || *arg == '\0')
1517 			fatal("%s line %d: Missing argument.",
1518 			    filename, linenum);
1519 		if (*arg != '-' &&
1520 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1521 		    arg + 1 : arg, 1, ca_only))
1522 			fatal("%s line %d: Bad key types '%s'.",
1523 			    filename, linenum, arg ? arg : "<NONE>");
1524 		if (*activep && *charptr == NULL)
1525 			*charptr = xstrdup(arg);
1526 		break;
1527 
1528 	case sHostKeyAlgorithms:
1529 		charptr = &options->hostkeyalgorithms;
1530 		ca_only = 0;
1531 		goto parse_pubkey_algos;
1532 
1533 	case sCASignatureAlgorithms:
1534 		charptr = &options->ca_sign_algorithms;
1535 		ca_only = 1;
1536 		goto parse_pubkey_algos;
1537 
1538 	case sPubkeyAuthentication:
1539 		intptr = &options->pubkey_authentication;
1540 		ca_only = 0;
1541 		goto parse_flag;
1542 
1543 	case sPubkeyAcceptedAlgorithms:
1544 		charptr = &options->pubkey_accepted_algos;
1545 		ca_only = 0;
1546 		goto parse_pubkey_algos;
1547 
1548 	case sPubkeyAuthOptions:
1549 		intptr = &options->pubkey_auth_options;
1550 		value = 0;
1551 		while ((arg = argv_next(&ac, &av)) != NULL) {
1552 			if (strcasecmp(arg, "none") == 0)
1553 				continue;
1554 			if (strcasecmp(arg, "touch-required") == 0)
1555 				value |= PUBKEYAUTH_TOUCH_REQUIRED;
1556 			else if (strcasecmp(arg, "verify-required") == 0)
1557 				value |= PUBKEYAUTH_VERIFY_REQUIRED;
1558 			else {
1559 				error("%s line %d: unsupported %s option %s",
1560 				    filename, linenum, keyword, arg);
1561 				goto out;
1562 			}
1563 		}
1564 		if (*activep && *intptr == -1)
1565 			*intptr = value;
1566 		break;
1567 
1568 	case sKerberosAuthentication:
1569 		intptr = &options->kerberos_authentication;
1570 		goto parse_flag;
1571 
1572 	case sKerberosOrLocalPasswd:
1573 		intptr = &options->kerberos_or_local_passwd;
1574 		goto parse_flag;
1575 
1576 	case sKerberosTicketCleanup:
1577 		intptr = &options->kerberos_ticket_cleanup;
1578 		goto parse_flag;
1579 
1580 	case sKerberosGetAFSToken:
1581 		intptr = &options->kerberos_get_afs_token;
1582 		goto parse_flag;
1583 
1584 	case sGssAuthentication:
1585 		intptr = &options->gss_authentication;
1586 		goto parse_flag;
1587 
1588 	case sGssCleanupCreds:
1589 		intptr = &options->gss_cleanup_creds;
1590 		goto parse_flag;
1591 
1592 	case sGssStrictAcceptor:
1593 		intptr = &options->gss_strict_acceptor;
1594 		goto parse_flag;
1595 
1596 	case sPasswordAuthentication:
1597 		intptr = &options->password_authentication;
1598 		goto parse_flag;
1599 
1600 	case sKbdInteractiveAuthentication:
1601 		intptr = &options->kbd_interactive_authentication;
1602 		goto parse_flag;
1603 
1604 	case sPrintMotd:
1605 		intptr = &options->print_motd;
1606 		goto parse_flag;
1607 
1608 	case sPrintLastLog:
1609 		intptr = &options->print_lastlog;
1610 		goto parse_flag;
1611 
1612 	case sX11Forwarding:
1613 		intptr = &options->x11_forwarding;
1614 		goto parse_flag;
1615 
1616 	case sX11DisplayOffset:
1617 		intptr = &options->x11_display_offset;
1618  parse_int:
1619 		arg = argv_next(&ac, &av);
1620 		if ((errstr = atoi_err(arg, &value)) != NULL)
1621 			fatal("%s line %d: %s integer value %s.",
1622 			    filename, linenum, keyword, errstr);
1623 		if (*activep && *intptr == -1)
1624 			*intptr = value;
1625 		break;
1626 
1627 	case sX11UseLocalhost:
1628 		intptr = &options->x11_use_localhost;
1629 		goto parse_flag;
1630 
1631 	case sXAuthLocation:
1632 		charptr = &options->xauth_location;
1633 		goto parse_filename;
1634 
1635 	case sPermitTTY:
1636 		intptr = &options->permit_tty;
1637 		goto parse_flag;
1638 
1639 	case sPermitUserRC:
1640 		intptr = &options->permit_user_rc;
1641 		goto parse_flag;
1642 
1643 	case sStrictModes:
1644 		intptr = &options->strict_modes;
1645 		goto parse_flag;
1646 
1647 	case sTCPKeepAlive:
1648 		intptr = &options->tcp_keep_alive;
1649 		goto parse_flag;
1650 
1651 	case sEmptyPasswd:
1652 		intptr = &options->permit_empty_passwd;
1653 		goto parse_flag;
1654 
1655 	case sPermitUserEnvironment:
1656 		intptr = &options->permit_user_env;
1657 		charptr = &options->permit_user_env_allowlist;
1658 		arg = argv_next(&ac, &av);
1659 		if (!arg || *arg == '\0')
1660 			fatal("%s line %d: %s missing argument.",
1661 			    filename, linenum, keyword);
1662 		value = 0;
1663 		p = NULL;
1664 		if (strcmp(arg, "yes") == 0)
1665 			value = 1;
1666 		else if (strcmp(arg, "no") == 0)
1667 			value = 0;
1668 		else {
1669 			/* Pattern-list specified */
1670 			value = 1;
1671 			p = xstrdup(arg);
1672 		}
1673 		if (*activep && *intptr == -1) {
1674 			*intptr = value;
1675 			*charptr = p;
1676 			p = NULL;
1677 		}
1678 		free(p);
1679 		break;
1680 
1681 	case sCompression:
1682 		intptr = &options->compression;
1683 		multistate_ptr = multistate_compression;
1684 		goto parse_multistate;
1685 
1686 	case sRekeyLimit:
1687 		arg = argv_next(&ac, &av);
1688 		if (!arg || *arg == '\0')
1689 			fatal("%s line %d: %s missing argument.",
1690 			    filename, linenum, keyword);
1691 		if (strcmp(arg, "default") == 0) {
1692 			val64 = 0;
1693 		} else {
1694 			if (scan_scaled(arg, &val64) == -1)
1695 				fatal("%.200s line %d: Bad %s number '%s': %s",
1696 				    filename, linenum, keyword,
1697 				    arg, strerror(errno));
1698 			if (val64 != 0 && val64 < 16)
1699 				fatal("%.200s line %d: %s too small",
1700 				    filename, linenum, keyword);
1701 		}
1702 		if (*activep && options->rekey_limit == -1)
1703 			options->rekey_limit = val64;
1704 		if (ac != 0) { /* optional rekey interval present */
1705 			if (strcmp(av[0], "none") == 0) {
1706 				(void)argv_next(&ac, &av);	/* discard */
1707 				break;
1708 			}
1709 			intptr = &options->rekey_interval;
1710 			goto parse_time;
1711 		}
1712 		break;
1713 
1714 	case sGatewayPorts:
1715 		intptr = &options->fwd_opts.gateway_ports;
1716 		multistate_ptr = multistate_gatewayports;
1717 		goto parse_multistate;
1718 
1719 	case sUseDNS:
1720 		intptr = &options->use_dns;
1721 		goto parse_flag;
1722 
1723 	case sLogFacility:
1724 		log_facility_ptr = &options->log_facility;
1725 		arg = argv_next(&ac, &av);
1726 		value = log_facility_number(arg);
1727 		if (value == SYSLOG_FACILITY_NOT_SET)
1728 			fatal("%.200s line %d: unsupported log facility '%s'",
1729 			    filename, linenum, arg ? arg : "<NONE>");
1730 		if (*log_facility_ptr == -1)
1731 			*log_facility_ptr = (SyslogFacility) value;
1732 		break;
1733 
1734 	case sLogLevel:
1735 		log_level_ptr = &options->log_level;
1736 		arg = argv_next(&ac, &av);
1737 		value = log_level_number(arg);
1738 		if (value == SYSLOG_LEVEL_NOT_SET)
1739 			fatal("%.200s line %d: unsupported log level '%s'",
1740 			    filename, linenum, arg ? arg : "<NONE>");
1741 		if (*activep && *log_level_ptr == -1)
1742 			*log_level_ptr = (LogLevel) value;
1743 		break;
1744 
1745 	case sLogVerbose:
1746 		found = options->num_log_verbose == 0;
1747 		while ((arg = argv_next(&ac, &av)) != NULL) {
1748 			if (*arg == '\0') {
1749 				error("%s line %d: keyword %s empty argument",
1750 				    filename, linenum, keyword);
1751 				goto out;
1752 			}
1753 			/* Allow "none" only in first position */
1754 			if (strcasecmp(arg, "none") == 0) {
1755 				if (nstrs > 0 || ac > 0) {
1756 					error("%s line %d: keyword %s \"none\" "
1757 					    "argument must appear alone.",
1758 					    filename, linenum, keyword);
1759 					goto out;
1760 				}
1761 			}
1762 			opt_array_append(filename, linenum, keyword,
1763 			    &strs, &nstrs, arg);
1764 		}
1765 		if (nstrs == 0) {
1766 			fatal("%s line %d: no %s specified",
1767 			    filename, linenum, keyword);
1768 		}
1769 		if (found && *activep) {
1770 			options->log_verbose = strs;
1771 			options->num_log_verbose = nstrs;
1772 			strs = NULL; /* transferred */
1773 			nstrs = 0;
1774 		}
1775 		break;
1776 
1777 	case sAllowTcpForwarding:
1778 		intptr = &options->allow_tcp_forwarding;
1779 		multistate_ptr = multistate_tcpfwd;
1780 		goto parse_multistate;
1781 
1782 	case sAllowStreamLocalForwarding:
1783 		intptr = &options->allow_streamlocal_forwarding;
1784 		multistate_ptr = multistate_tcpfwd;
1785 		goto parse_multistate;
1786 
1787 	case sAllowAgentForwarding:
1788 		intptr = &options->allow_agent_forwarding;
1789 		goto parse_flag;
1790 
1791 	case sDisableForwarding:
1792 		intptr = &options->disable_forwarding;
1793 		goto parse_flag;
1794 
1795 	case sAllowUsers:
1796 		chararrayptr = &options->allow_users;
1797 		uintptr = &options->num_allow_users;
1798  parse_allowdenyusers:
1799 		/* XXX appends to list; doesn't respect first-match-wins */
1800 		while ((arg = argv_next(&ac, &av)) != NULL) {
1801 			if (*arg == '\0' ||
1802 			    match_user(NULL, NULL, NULL, arg) == -1)
1803 				fatal("%s line %d: invalid %s pattern: \"%s\"",
1804 				    filename, linenum, keyword, arg);
1805 			found = 1;
1806 			if (!*activep)
1807 				continue;
1808 			opt_array_append(filename, linenum, keyword,
1809 			    chararrayptr, uintptr, arg);
1810 		}
1811 		if (!found) {
1812 			fatal("%s line %d: no %s specified",
1813 			    filename, linenum, keyword);
1814 		}
1815 		break;
1816 
1817 	case sDenyUsers:
1818 		chararrayptr = &options->deny_users;
1819 		uintptr = &options->num_deny_users;
1820 		goto parse_allowdenyusers;
1821 
1822 	case sAllowGroups:
1823 		chararrayptr = &options->allow_groups;
1824 		uintptr = &options->num_allow_groups;
1825 		/* XXX appends to list; doesn't respect first-match-wins */
1826  parse_allowdenygroups:
1827 		while ((arg = argv_next(&ac, &av)) != NULL) {
1828 			if (*arg == '\0')
1829 				fatal("%s line %d: empty %s pattern",
1830 				    filename, linenum, keyword);
1831 			found = 1;
1832 			if (!*activep)
1833 				continue;
1834 			opt_array_append(filename, linenum, keyword,
1835 			    chararrayptr, uintptr, arg);
1836 		}
1837 		if (!found) {
1838 			fatal("%s line %d: no %s specified",
1839 			    filename, linenum, keyword);
1840 		}
1841 		break;
1842 
1843 	case sDenyGroups:
1844 		chararrayptr = &options->deny_groups;
1845 		uintptr = &options->num_deny_groups;
1846 		goto parse_allowdenygroups;
1847 
1848 	case sCiphers:
1849 		arg = argv_next(&ac, &av);
1850 		if (!arg || *arg == '\0')
1851 			fatal("%s line %d: %s missing argument.",
1852 			    filename, linenum, keyword);
1853 		if (*arg != '-' &&
1854 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
1855 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1856 			    filename, linenum, arg ? arg : "<NONE>");
1857 		if (options->ciphers == NULL)
1858 			options->ciphers = xstrdup(arg);
1859 		break;
1860 
1861 	case sMacs:
1862 		arg = argv_next(&ac, &av);
1863 		if (!arg || *arg == '\0')
1864 			fatal("%s line %d: %s missing argument.",
1865 			    filename, linenum, keyword);
1866 		if (*arg != '-' &&
1867 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
1868 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1869 			    filename, linenum, arg ? arg : "<NONE>");
1870 		if (options->macs == NULL)
1871 			options->macs = xstrdup(arg);
1872 		break;
1873 
1874 	case sKexAlgorithms:
1875 		arg = argv_next(&ac, &av);
1876 		if (!arg || *arg == '\0')
1877 			fatal("%s line %d: %s missing argument.",
1878 			    filename, linenum, keyword);
1879 		if (*arg != '-' &&
1880 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1881 		    arg + 1 : arg))
1882 			fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
1883 			    filename, linenum, arg ? arg : "<NONE>");
1884 		if (options->kex_algorithms == NULL)
1885 			options->kex_algorithms = xstrdup(arg);
1886 		break;
1887 
1888 	case sSubsystem:
1889 		arg = argv_next(&ac, &av);
1890 		if (!arg || *arg == '\0')
1891 			fatal("%s line %d: %s missing argument.",
1892 			    filename, linenum, keyword);
1893 		if (!*activep) {
1894 			argv_consume(&ac);
1895 			break;
1896 		}
1897 		found = 0;
1898 		for (i = 0; i < options->num_subsystems; i++) {
1899 			if (strcmp(arg, options->subsystem_name[i]) == 0) {
1900 				found = 1;
1901 				break;
1902 			}
1903 		}
1904 		if (found) {
1905 			debug("%s line %d: Subsystem '%s' already defined.",
1906 			    filename, linenum, arg);
1907 			argv_consume(&ac);
1908 			break;
1909 		}
1910 		options->subsystem_name = xrecallocarray(
1911 		    options->subsystem_name, options->num_subsystems,
1912 		    options->num_subsystems + 1,
1913 		    sizeof(*options->subsystem_name));
1914 		options->subsystem_command = xrecallocarray(
1915 		    options->subsystem_command, options->num_subsystems,
1916 		    options->num_subsystems + 1,
1917 		    sizeof(*options->subsystem_command));
1918 		options->subsystem_args = xrecallocarray(
1919 		    options->subsystem_args, options->num_subsystems,
1920 		    options->num_subsystems + 1,
1921 		    sizeof(*options->subsystem_args));
1922 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1923 		arg = argv_next(&ac, &av);
1924 		if (!arg || *arg == '\0') {
1925 			fatal("%s line %d: Missing subsystem command.",
1926 			    filename, linenum);
1927 		}
1928 		options->subsystem_command[options->num_subsystems] =
1929 		    xstrdup(arg);
1930 		/* Collect arguments (separate to executable) */
1931 		arg = argv_assemble(1, &arg); /* quote command correctly */
1932 		arg2 = argv_assemble(ac, av); /* rest of command */
1933 		xasprintf(&options->subsystem_args[options->num_subsystems],
1934 		    "%s%s%s", arg, *arg2 == '\0' ? "" : " ", arg2);
1935 		free(arg2);
1936 		argv_consume(&ac);
1937 		options->num_subsystems++;
1938 		break;
1939 
1940 	case sMaxStartups:
1941 		arg = argv_next(&ac, &av);
1942 		if (!arg || *arg == '\0')
1943 			fatal("%s line %d: %s missing argument.",
1944 			    filename, linenum, keyword);
1945 		if ((n = sscanf(arg, "%d:%d:%d",
1946 		    &options->max_startups_begin,
1947 		    &options->max_startups_rate,
1948 		    &options->max_startups)) == 3) {
1949 			if (options->max_startups_begin >
1950 			    options->max_startups ||
1951 			    options->max_startups_rate > 100 ||
1952 			    options->max_startups_rate < 1)
1953 				fatal("%s line %d: Invalid %s spec.",
1954 				    filename, linenum, keyword);
1955 		} else if (n != 1)
1956 			fatal("%s line %d: Invalid %s spec.",
1957 			    filename, linenum, keyword);
1958 		else
1959 			options->max_startups = options->max_startups_begin;
1960 		if (options->max_startups <= 0 ||
1961 		    options->max_startups_begin <= 0)
1962 			fatal("%s line %d: Invalid %s spec.",
1963 			    filename, linenum, keyword);
1964 		break;
1965 
1966 	case sPerSourceNetBlockSize:
1967 		arg = argv_next(&ac, &av);
1968 		if (!arg || *arg == '\0')
1969 			fatal("%s line %d: %s missing argument.",
1970 			    filename, linenum, keyword);
1971 		switch (n = sscanf(arg, "%d:%d", &value, &value2)) {
1972 		case 2:
1973 			if (value2 < 0 || value2 > 128)
1974 				n = -1;
1975 			/* FALLTHROUGH */
1976 		case 1:
1977 			if (value < 0 || value > 32)
1978 				n = -1;
1979 		}
1980 		if (n != 1 && n != 2)
1981 			fatal("%s line %d: Invalid %s spec.",
1982 			    filename, linenum, keyword);
1983 		if (*activep) {
1984 			options->per_source_masklen_ipv4 = value;
1985 			options->per_source_masklen_ipv6 = value2;
1986 		}
1987 		break;
1988 
1989 	case sPerSourceMaxStartups:
1990 		arg = argv_next(&ac, &av);
1991 		if (!arg || *arg == '\0')
1992 			fatal("%s line %d: %s missing argument.",
1993 			    filename, linenum, keyword);
1994 		if (strcmp(arg, "none") == 0) { /* no limit */
1995 			value = INT_MAX;
1996 		} else {
1997 			if ((errstr = atoi_err(arg, &value)) != NULL)
1998 				fatal("%s line %d: %s integer value %s.",
1999 				    filename, linenum, keyword, errstr);
2000 		}
2001 		if (*activep && options->per_source_max_startups == -1)
2002 			options->per_source_max_startups = value;
2003 		break;
2004 
2005 	case sPerSourcePenaltyExemptList:
2006 		charptr = &options->per_source_penalty_exempt;
2007 		arg = argv_next(&ac, &av);
2008 		if (!arg || *arg == '\0')
2009 			fatal("%s line %d: missing argument.",
2010 			    filename, linenum);
2011 		if (addr_match_list(NULL, arg) != 0) {
2012 			fatal("%s line %d: keyword %s "
2013 			    "invalid address argument.",
2014 			    filename, linenum, keyword);
2015 		}
2016 		if (*activep && *charptr == NULL)
2017 			*charptr = xstrdup(arg);
2018 		break;
2019 
2020 	case sPerSourcePenalties:
2021 		while ((arg = argv_next(&ac, &av)) != NULL) {
2022 			found = 1;
2023 			value = -1;
2024 			value2 = 0;
2025 			p = NULL;
2026 			/* Allow no/yes only in first position */
2027 			if (strcasecmp(arg, "no") == 0 ||
2028 			    (value2 = (strcasecmp(arg, "yes") == 0))) {
2029 				if (ac > 0) {
2030 					fatal("%s line %d: keyword %s \"%s\" "
2031 					    "argument must appear alone.",
2032 					    filename, linenum, keyword, arg);
2033 				}
2034 				if (*activep &&
2035 				    options->per_source_penalty.enabled == -1)
2036 					options->per_source_penalty.enabled = value2;
2037 				continue;
2038 			} else if (strncmp(arg, "crash:", 6) == 0) {
2039 				p = arg + 6;
2040 				intptr = &options->per_source_penalty.penalty_crash;
2041 			} else if (strncmp(arg, "authfail:", 9) == 0) {
2042 				p = arg + 9;
2043 				intptr = &options->per_source_penalty.penalty_authfail;
2044 			} else if (strncmp(arg, "noauth:", 7) == 0) {
2045 				p = arg + 7;
2046 				intptr = &options->per_source_penalty.penalty_noauth;
2047 			} else if (strncmp(arg, "grace-exceeded:", 15) == 0) {
2048 				p = arg + 15;
2049 				intptr = &options->per_source_penalty.penalty_grace;
2050 			} else if (strncmp(arg, "max:", 4) == 0) {
2051 				p = arg + 4;
2052 				intptr = &options->per_source_penalty.penalty_max;
2053 			} else if (strncmp(arg, "min:", 4) == 0) {
2054 				p = arg + 4;
2055 				intptr = &options->per_source_penalty.penalty_min;
2056 			} else if (strncmp(arg, "max-sources4:", 13) == 0) {
2057 				intptr = &options->per_source_penalty.max_sources4;
2058 				if ((errstr = atoi_err(arg+13, &value)) != NULL)
2059 					fatal("%s line %d: %s value %s.",
2060 					    filename, linenum, keyword, errstr);
2061 			} else if (strncmp(arg, "max-sources6:", 13) == 0) {
2062 				intptr = &options->per_source_penalty.max_sources6;
2063 				if ((errstr = atoi_err(arg+13, &value)) != NULL)
2064 					fatal("%s line %d: %s value %s.",
2065 					    filename, linenum, keyword, errstr);
2066 			} else if (strcmp(arg, "overflow:deny-all") == 0) {
2067 				intptr = &options->per_source_penalty.overflow_mode;
2068 				value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL;
2069 			} else if (strcmp(arg, "overflow:permissive") == 0) {
2070 				intptr = &options->per_source_penalty.overflow_mode;
2071 				value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
2072 			} else if (strcmp(arg, "overflow6:deny-all") == 0) {
2073 				intptr = &options->per_source_penalty.overflow_mode6;
2074 				value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL;
2075 			} else if (strcmp(arg, "overflow6:permissive") == 0) {
2076 				intptr = &options->per_source_penalty.overflow_mode6;
2077 				value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE;
2078 			} else {
2079 				fatal("%s line %d: unsupported %s keyword %s",
2080 				    filename, linenum, keyword, arg);
2081 			}
2082 			/* If no value was parsed above, assume it's a time */
2083 			if (value == -1 && (value = convtime(p)) == -1) {
2084 				fatal("%s line %d: invalid %s time value.",
2085 				    filename, linenum, keyword);
2086 			}
2087 			if (*activep && *intptr == -1) {
2088 				*intptr = value;
2089 				/* any option implicitly enables penalties */
2090 				options->per_source_penalty.enabled = 1;
2091 			}
2092 		}
2093 		if (!found) {
2094 			fatal("%s line %d: no %s specified",
2095 			    filename, linenum, keyword);
2096 		}
2097 		break;
2098 
2099 	case sMaxAuthTries:
2100 		intptr = &options->max_authtries;
2101 		goto parse_int;
2102 
2103 	case sMaxSessions:
2104 		intptr = &options->max_sessions;
2105 		goto parse_int;
2106 
2107 	case sBanner:
2108 		charptr = &options->banner;
2109 		goto parse_filename;
2110 
2111 	/*
2112 	 * These options can contain %X options expanded at
2113 	 * connect time, so that you can specify paths like:
2114 	 *
2115 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
2116 	 */
2117 	case sAuthorizedKeysFile:
2118 		found = options->num_authkeys_files == 0;
2119 		while ((arg = argv_next(&ac, &av)) != NULL) {
2120 			if (*arg == '\0') {
2121 				error("%s line %d: keyword %s empty argument",
2122 				    filename, linenum, keyword);
2123 				goto out;
2124 			}
2125 			arg2 = tilde_expand_filename(arg, getuid());
2126 			opt_array_append(filename, linenum, keyword,
2127 			    &strs, &nstrs, arg2);
2128 			free(arg2);
2129 		}
2130 		if (nstrs == 0) {
2131 			fatal("%s line %d: no %s specified",
2132 			    filename, linenum, keyword);
2133 		}
2134 		if (found && *activep) {
2135 			options->authorized_keys_files = strs;
2136 			options->num_authkeys_files = nstrs;
2137 			strs = NULL; /* transferred */
2138 			nstrs = 0;
2139 		}
2140 		break;
2141 
2142 	case sAuthorizedPrincipalsFile:
2143 		charptr = &options->authorized_principals_file;
2144 		arg = argv_next(&ac, &av);
2145 		if (!arg || *arg == '\0')
2146 			fatal("%s line %d: %s missing argument.",
2147 			    filename, linenum, keyword);
2148 		if (*activep && *charptr == NULL) {
2149 			*charptr = tilde_expand_filename(arg, getuid());
2150 			/* increase optional counter */
2151 			if (intptr != NULL)
2152 				*intptr = *intptr + 1;
2153 		}
2154 		break;
2155 
2156 	case sClientAliveInterval:
2157 		intptr = &options->client_alive_interval;
2158 		goto parse_time;
2159 
2160 	case sClientAliveCountMax:
2161 		intptr = &options->client_alive_count_max;
2162 		goto parse_int;
2163 
2164 	case sAcceptEnv:
2165 		/* XXX appends to list; doesn't respect first-match-wins */
2166 		while ((arg = argv_next(&ac, &av)) != NULL) {
2167 			if (*arg == '\0' || strchr(arg, '=') != NULL)
2168 				fatal("%s line %d: Invalid environment name.",
2169 				    filename, linenum);
2170 			found = 1;
2171 			if (!*activep)
2172 				continue;
2173 			opt_array_append(filename, linenum, keyword,
2174 			    &options->accept_env, &options->num_accept_env,
2175 			    arg);
2176 		}
2177 		if (!found) {
2178 			fatal("%s line %d: no %s specified",
2179 			    filename, linenum, keyword);
2180 		}
2181 		break;
2182 
2183 	case sSetEnv:
2184 		found = options->num_setenv == 0;
2185 		while ((arg = argv_next(&ac, &av)) != NULL) {
2186 			if (*arg == '\0' || strchr(arg, '=') == NULL)
2187 				fatal("%s line %d: Invalid environment.",
2188 				    filename, linenum);
2189 			if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
2190 				debug2("%s line %d: ignoring duplicate env "
2191 				    "name \"%.64s\"", filename, linenum, arg);
2192 				continue;
2193 			}
2194 			opt_array_append(filename, linenum, keyword,
2195 			    &strs, &nstrs, arg);
2196 		}
2197 		if (nstrs == 0) {
2198 			fatal("%s line %d: no %s specified",
2199 			    filename, linenum, keyword);
2200 		}
2201 		if (found && *activep) {
2202 			options->setenv = strs;
2203 			options->num_setenv = nstrs;
2204 			strs = NULL; /* transferred */
2205 			nstrs = 0;
2206 		}
2207 		break;
2208 
2209 	case sPermitTunnel:
2210 		intptr = &options->permit_tun;
2211 		arg = argv_next(&ac, &av);
2212 		if (!arg || *arg == '\0')
2213 			fatal("%s line %d: %s missing argument.",
2214 			    filename, linenum, keyword);
2215 		value = -1;
2216 		for (i = 0; tunmode_desc[i].val != -1; i++)
2217 			if (strcmp(tunmode_desc[i].text, arg) == 0) {
2218 				value = tunmode_desc[i].val;
2219 				break;
2220 			}
2221 		if (value == -1)
2222 			fatal("%s line %d: bad %s argument %s",
2223 			    filename, linenum, keyword, arg);
2224 		if (*activep && *intptr == -1)
2225 			*intptr = value;
2226 		break;
2227 
2228 	case sInclude:
2229 		if (cmdline) {
2230 			fatal("Include directive not supported as a "
2231 			    "command-line option");
2232 		}
2233 		value = 0;
2234 		while ((arg2 = argv_next(&ac, &av)) != NULL) {
2235 			if (*arg2 == '\0') {
2236 				error("%s line %d: keyword %s empty argument",
2237 				    filename, linenum, keyword);
2238 				goto out;
2239 			}
2240 			value++;
2241 			found = 0;
2242 			if (*arg2 != '/' && *arg2 != '~') {
2243 				xasprintf(&arg, "%s/%s", SSHDIR, arg2);
2244 			} else
2245 				arg = xstrdup(arg2);
2246 
2247 			/*
2248 			 * Don't let included files clobber the containing
2249 			 * file's Match state.
2250 			 */
2251 			oactive = *activep;
2252 
2253 			/* consult cache of include files */
2254 			TAILQ_FOREACH(item, includes, entry) {
2255 				if (strcmp(item->selector, arg) != 0)
2256 					continue;
2257 				if (item->filename != NULL) {
2258 					parse_server_config_depth(options,
2259 					    item->filename, item->contents,
2260 					    includes, connectinfo,
2261 					    (*inc_flags & SSHCFG_MATCH_ONLY
2262 					        ? SSHCFG_MATCH_ONLY : (oactive
2263 					            ? 0 : SSHCFG_NEVERMATCH)),
2264 					    activep, depth + 1);
2265 				}
2266 				found = 1;
2267 				*activep = oactive;
2268 			}
2269 			if (found != 0) {
2270 				free(arg);
2271 				continue;
2272 			}
2273 
2274 			/* requested glob was not in cache */
2275 			debug2("%s line %d: new include %s",
2276 			    filename, linenum, arg);
2277 			if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
2278 				if (r != GLOB_NOMATCH) {
2279 					fatal("%s line %d: include \"%s\" glob "
2280 					    "failed", filename, linenum, arg);
2281 				}
2282 				/*
2283 				 * If no entry matched then record a
2284 				 * placeholder to skip later glob calls.
2285 				 */
2286 				debug2("%s line %d: no match for %s",
2287 				    filename, linenum, arg);
2288 				item = xcalloc(1, sizeof(*item));
2289 				item->selector = strdup(arg);
2290 				TAILQ_INSERT_TAIL(includes,
2291 				    item, entry);
2292 			}
2293 			if (gbuf.gl_pathc > INT_MAX)
2294 				fatal_f("too many glob results");
2295 			for (n = 0; n < (int)gbuf.gl_pathc; n++) {
2296 				debug2("%s line %d: including %s",
2297 				    filename, linenum, gbuf.gl_pathv[n]);
2298 				item = xcalloc(1, sizeof(*item));
2299 				item->selector = strdup(arg);
2300 				item->filename = strdup(gbuf.gl_pathv[n]);
2301 				if ((item->contents = sshbuf_new()) == NULL)
2302 					fatal_f("sshbuf_new failed");
2303 				load_server_config(item->filename,
2304 				    item->contents);
2305 				parse_server_config_depth(options,
2306 				    item->filename, item->contents,
2307 				    includes, connectinfo,
2308 				    (*inc_flags & SSHCFG_MATCH_ONLY
2309 				        ? SSHCFG_MATCH_ONLY : (oactive
2310 				            ? 0 : SSHCFG_NEVERMATCH)),
2311 				    activep, depth + 1);
2312 				*activep = oactive;
2313 				TAILQ_INSERT_TAIL(includes, item, entry);
2314 			}
2315 			globfree(&gbuf);
2316 			free(arg);
2317 		}
2318 		if (value == 0) {
2319 			fatal("%s line %d: %s missing filename argument",
2320 			    filename, linenum, keyword);
2321 		}
2322 		break;
2323 
2324 	case sMatch:
2325 		if (cmdline)
2326 			fatal("Match directive not supported as a command-line "
2327 			    "option");
2328 		value = match_cfg_line(&str, linenum,
2329 		    (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
2330 		if (value < 0)
2331 			fatal("%s line %d: Bad Match condition", filename,
2332 			    linenum);
2333 		*activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
2334 		/*
2335 		 * The MATCH_ONLY flag is applicable only until the first
2336 		 * match block.
2337 		 */
2338 		*inc_flags &= ~SSHCFG_MATCH_ONLY;
2339 		/*
2340 		 * If match_cfg_line() didn't consume all its arguments then
2341 		 * arrange for the extra arguments check below to fail.
2342 		 */
2343 		if (str == NULL || *str == '\0')
2344 			argv_consume(&ac);
2345 		break;
2346 
2347 	case sPermitListen:
2348 	case sPermitOpen:
2349 		if (opcode == sPermitListen) {
2350 			uintptr = &options->num_permitted_listens;
2351 			chararrayptr = &options->permitted_listens;
2352 		} else {
2353 			uintptr = &options->num_permitted_opens;
2354 			chararrayptr = &options->permitted_opens;
2355 		}
2356 		found = *uintptr == 0;
2357 		while ((arg = argv_next(&ac, &av)) != NULL) {
2358 			if (strcmp(arg, "any") == 0 ||
2359 			    strcmp(arg, "none") == 0) {
2360 				if (nstrs != 0) {
2361 					fatal("%s line %d: %s must appear "
2362 					    "alone on a %s line.",
2363 					    filename, linenum, arg, keyword);
2364 				}
2365 				opt_array_append(filename, linenum, keyword,
2366 				    &strs, &nstrs, arg);
2367 				continue;
2368 			}
2369 
2370 			if (opcode == sPermitListen &&
2371 			    strchr(arg, ':') == NULL) {
2372 				/*
2373 				 * Allow bare port number for PermitListen
2374 				 * to indicate a wildcard listen host.
2375 				 */
2376 				xasprintf(&arg2, "*:%s", arg);
2377 			} else {
2378 				arg2 = xstrdup(arg);
2379 				p = hpdelim(&arg);
2380 				if (p == NULL) {
2381 					fatal("%s line %d: %s missing host",
2382 					    filename, linenum, keyword);
2383 				}
2384 				p = cleanhostname(p);
2385 			}
2386 			if (arg == NULL ||
2387 			    ((port = permitopen_port(arg)) < 0)) {
2388 				fatal("%s line %d: %s bad port number",
2389 				    filename, linenum, keyword);
2390 			}
2391 			opt_array_append(filename, linenum, keyword,
2392 			    &strs, &nstrs, arg2);
2393 			free(arg2);
2394 		}
2395 		if (nstrs == 0) {
2396 			fatal("%s line %d: %s missing argument.",
2397 			    filename, linenum, keyword);
2398 		}
2399 		if (found && *activep) {
2400 			*chararrayptr = strs;
2401 			*uintptr = nstrs;
2402 			strs = NULL; /* transferred */
2403 			nstrs = 0;
2404 		}
2405 		break;
2406 
2407 	case sForceCommand:
2408 		if (str == NULL || *str == '\0')
2409 			fatal("%s line %d: %s missing argument.",
2410 			    filename, linenum, keyword);
2411 		len = strspn(str, WHITESPACE);
2412 		if (*activep && options->adm_forced_command == NULL)
2413 			options->adm_forced_command = xstrdup(str + len);
2414 		argv_consume(&ac);
2415 		break;
2416 
2417 	case sChrootDirectory:
2418 		charptr = &options->chroot_directory;
2419 
2420 		arg = argv_next(&ac, &av);
2421 		if (!arg || *arg == '\0')
2422 			fatal("%s line %d: %s missing argument.",
2423 			    filename, linenum, keyword);
2424 		if (*activep && *charptr == NULL)
2425 			*charptr = xstrdup(arg);
2426 		break;
2427 
2428 	case sTrustedUserCAKeys:
2429 		charptr = &options->trusted_user_ca_keys;
2430 		goto parse_filename;
2431 
2432 	case sRevokedKeys:
2433 		charptr = &options->revoked_keys_file;
2434 		goto parse_filename;
2435 
2436 	case sSecurityKeyProvider:
2437 		charptr = &options->sk_provider;
2438 		arg = argv_next(&ac, &av);
2439 		if (!arg || *arg == '\0')
2440 			fatal("%s line %d: %s missing argument.",
2441 			    filename, linenum, keyword);
2442 		if (*activep && *charptr == NULL) {
2443 			*charptr = strcasecmp(arg, "internal") == 0 ?
2444 			    xstrdup(arg) : derelativise_path(arg);
2445 			/* increase optional counter */
2446 			if (intptr != NULL)
2447 				*intptr = *intptr + 1;
2448 		}
2449 		break;
2450 
2451 	case sIPQoS:
2452 		arg = argv_next(&ac, &av);
2453 		if (!arg || *arg == '\0')
2454 			fatal("%s line %d: %s missing argument.",
2455 			    filename, linenum, keyword);
2456 		if ((value = parse_ipqos(arg)) == -1)
2457 			fatal("%s line %d: Bad %s value: %s",
2458 			    filename, linenum, keyword, arg);
2459 		arg = argv_next(&ac, &av);
2460 		if (arg == NULL)
2461 			value2 = value;
2462 		else if ((value2 = parse_ipqos(arg)) == -1)
2463 			fatal("%s line %d: Bad %s value: %s",
2464 			    filename, linenum, keyword, arg);
2465 		if (*activep) {
2466 			options->ip_qos_interactive = value;
2467 			options->ip_qos_bulk = value2;
2468 		}
2469 		break;
2470 
2471 	case sVersionAddendum:
2472 		if (str == NULL || *str == '\0')
2473 			fatal("%s line %d: %s missing argument.",
2474 			    filename, linenum, keyword);
2475 		len = strspn(str, WHITESPACE);
2476 		if (strchr(str + len, '\r') != NULL) {
2477 			fatal("%.200s line %d: Invalid %s argument",
2478 			    filename, linenum, keyword);
2479 		}
2480 		if ((arg = strchr(line, '#')) != NULL) {
2481 			*arg = '\0';
2482 			rtrim(line);
2483 		}
2484 		if (*activep && options->version_addendum == NULL) {
2485 			if (strcasecmp(str + len, "none") == 0)
2486 				options->version_addendum = xstrdup("");
2487 			else
2488 				options->version_addendum = xstrdup(str + len);
2489 		}
2490 		argv_consume(&ac);
2491 		break;
2492 
2493 	case sAuthorizedKeysCommand:
2494 		charptr = &options->authorized_keys_command;
2495  parse_command:
2496 		len = strspn(str, WHITESPACE);
2497 		if (str[len] != '/' && strcasecmp(str + len, "none") != 0) {
2498 			fatal("%.200s line %d: %s must be an absolute path",
2499 			    filename, linenum, keyword);
2500 		}
2501 		if (*activep && *charptr == NULL)
2502 			*charptr = xstrdup(str + len);
2503 		argv_consume(&ac);
2504 		break;
2505 
2506 	case sAuthorizedKeysCommandUser:
2507 		charptr = &options->authorized_keys_command_user;
2508  parse_localuser:
2509 		arg = argv_next(&ac, &av);
2510 		if (!arg || *arg == '\0') {
2511 			fatal("%s line %d: missing %s argument.",
2512 			    filename, linenum, keyword);
2513 		}
2514 		if (*activep && *charptr == NULL)
2515 			*charptr = xstrdup(arg);
2516 		break;
2517 
2518 	case sAuthorizedPrincipalsCommand:
2519 		charptr = &options->authorized_principals_command;
2520 		goto parse_command;
2521 
2522 	case sAuthorizedPrincipalsCommandUser:
2523 		charptr = &options->authorized_principals_command_user;
2524 		goto parse_localuser;
2525 
2526 	case sAuthenticationMethods:
2527 		found = options->num_auth_methods == 0;
2528 		value = 0; /* seen "any" pseudo-method */
2529 		while ((arg = argv_next(&ac, &av)) != NULL) {
2530 			if (strcmp(arg, "any") == 0) {
2531 				if (nstrs > 0) {
2532 					fatal("%s line %d: \"any\" must "
2533 					    "appear alone in %s",
2534 					    filename, linenum, keyword);
2535 				}
2536 				value = 1;
2537 			} else if (value) {
2538 				fatal("%s line %d: \"any\" must appear "
2539 				    "alone in %s", filename, linenum, keyword);
2540 			} else if (auth2_methods_valid(arg, 0) != 0) {
2541 				fatal("%s line %d: invalid %s method list.",
2542 				    filename, linenum, keyword);
2543 			}
2544 			opt_array_append(filename, linenum, keyword,
2545 			    &strs, &nstrs, arg);
2546 		}
2547 		if (nstrs == 0) {
2548 			fatal("%s line %d: no %s specified",
2549 			    filename, linenum, keyword);
2550 		}
2551 		if (found && *activep) {
2552 			options->auth_methods = strs;
2553 			options->num_auth_methods = nstrs;
2554 			strs = NULL; /* transferred */
2555 			nstrs = 0;
2556 		}
2557 		break;
2558 
2559 	case sStreamLocalBindMask:
2560 		arg = argv_next(&ac, &av);
2561 		if (!arg || *arg == '\0')
2562 			fatal("%s line %d: %s missing argument.",
2563 			    filename, linenum, keyword);
2564 		/* Parse mode in octal format */
2565 		value = strtol(arg, &p, 8);
2566 		if (arg == p || value < 0 || value > 0777)
2567 			fatal("%s line %d: Invalid %s.",
2568 			    filename, linenum, keyword);
2569 		if (*activep)
2570 			options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2571 		break;
2572 
2573 	case sStreamLocalBindUnlink:
2574 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2575 		goto parse_flag;
2576 
2577 	case sFingerprintHash:
2578 		arg = argv_next(&ac, &av);
2579 		if (!arg || *arg == '\0')
2580 			fatal("%s line %d: %s missing argument.",
2581 			    filename, linenum, keyword);
2582 		if ((value = ssh_digest_alg_by_name(arg)) == -1)
2583 			fatal("%.200s line %d: Invalid %s algorithm \"%s\".",
2584 			    filename, linenum, keyword, arg);
2585 		if (*activep)
2586 			options->fingerprint_hash = value;
2587 		break;
2588 
2589 	case sExposeAuthInfo:
2590 		intptr = &options->expose_userauth_info;
2591 		goto parse_flag;
2592 
2593 	case sRDomain:
2594 #if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
2595 		fatal("%s line %d: setting RDomain not supported on this "
2596 		    "platform.", filename, linenum);
2597 #endif
2598 		charptr = &options->routing_domain;
2599 		arg = argv_next(&ac, &av);
2600 		if (!arg || *arg == '\0')
2601 			fatal("%s line %d: %s missing argument.",
2602 			    filename, linenum, keyword);
2603 		if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
2604 		    !valid_rdomain(arg))
2605 			fatal("%s line %d: invalid routing domain",
2606 			    filename, linenum);
2607 		if (*activep && *charptr == NULL)
2608 			*charptr = xstrdup(arg);
2609 		break;
2610 
2611 	case sRequiredRSASize:
2612 		intptr = &options->required_rsa_size;
2613 		goto parse_int;
2614 
2615 	case sChannelTimeout:
2616 		found = options->num_channel_timeouts == 0;
2617 		while ((arg = argv_next(&ac, &av)) != NULL) {
2618 			/* Allow "none" only in first position */
2619 			if (strcasecmp(arg, "none") == 0) {
2620 				if (nstrs > 0 || ac > 0) {
2621 					error("%s line %d: keyword %s \"none\" "
2622 					    "argument must appear alone.",
2623 					    filename, linenum, keyword);
2624 					goto out;
2625 				}
2626 			} else if (parse_pattern_interval(arg,
2627 			    NULL, NULL) != 0) {
2628 				fatal("%s line %d: invalid channel timeout %s",
2629 				    filename, linenum, arg);
2630 			}
2631 			opt_array_append(filename, linenum, keyword,
2632 			    &strs, &nstrs, arg);
2633 		}
2634 		if (nstrs == 0) {
2635 			fatal("%s line %d: no %s specified",
2636 			    filename, linenum, keyword);
2637 		}
2638 		if (found && *activep) {
2639 			options->channel_timeouts = strs;
2640 			options->num_channel_timeouts = nstrs;
2641 			strs = NULL; /* transferred */
2642 			nstrs = 0;
2643 		}
2644 		break;
2645 
2646 	case sUnusedConnectionTimeout:
2647 		intptr = &options->unused_connection_timeout;
2648 		/* peek at first arg for "none" so we can reuse parse_time */
2649 		if (av[0] != NULL && strcasecmp(av[0], "none") == 0) {
2650 			(void)argv_next(&ac, &av); /* consume arg */
2651 			if (*activep)
2652 				*intptr = 0;
2653 			break;
2654 		}
2655 		goto parse_time;
2656 
2657 	case sSshdSessionPath:
2658 		charptr = &options->sshd_session_path;
2659 		goto parse_filename;
2660 
2661 	case sDeprecated:
2662 	case sIgnore:
2663 	case sUnsupported:
2664 		do_log2(opcode == sIgnore ?
2665 		    SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
2666 		    "%s line %d: %s option %s", filename, linenum,
2667 		    opcode == sUnsupported ? "Unsupported" : "Deprecated",
2668 		    keyword);
2669 		argv_consume(&ac);
2670 		break;
2671 
2672 	default:
2673 		fatal("%s line %d: Missing handler for opcode %s (%d)",
2674 		    filename, linenum, keyword, opcode);
2675 	}
2676 	/* Check that there is no garbage at end of line. */
2677 	if (ac > 0) {
2678 		error("%.200s line %d: keyword %s extra arguments "
2679 		    "at end of line", filename, linenum, keyword);
2680 		goto out;
2681 	}
2682 
2683 	/* success */
2684 	ret = 0;
2685  out:
2686 	opt_array_free2(strs, NULL, nstrs);
2687 	argv_free(oav, oac);
2688 	return ret;
2689 }
2690 
2691 int
process_server_config_line(ServerOptions * options,char * line,const char * filename,int linenum,int * activep,struct connection_info * connectinfo,struct include_list * includes)2692 process_server_config_line(ServerOptions *options, char *line,
2693     const char *filename, int linenum, int *activep,
2694     struct connection_info *connectinfo, struct include_list *includes)
2695 {
2696 	int inc_flags = 0;
2697 
2698 	return process_server_config_line_depth(options, line, filename,
2699 	    linenum, activep, connectinfo, &inc_flags, 0, includes);
2700 }
2701 
2702 
2703 /* Reads the server configuration file. */
2704 
2705 void
load_server_config(const char * filename,struct sshbuf * conf)2706 load_server_config(const char *filename, struct sshbuf *conf)
2707 {
2708 	struct stat st;
2709 	char *line = NULL, *cp;
2710 	size_t linesize = 0;
2711 	FILE *f;
2712 	int r;
2713 
2714 	debug2_f("filename %s", filename);
2715 	if ((f = fopen(filename, "r")) == NULL) {
2716 		perror(filename);
2717 		exit(1);
2718 	}
2719 	sshbuf_reset(conf);
2720 	/* grow buffer, so realloc is avoided for large config files */
2721 	if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
2722 	    (r = sshbuf_allocate(conf, st.st_size)) != 0)
2723 		fatal_fr(r, "allocate");
2724 	while (getline(&line, &linesize, f) != -1) {
2725 		/*
2726 		 * Strip whitespace
2727 		 * NB - preserve newlines, they are needed to reproduce
2728 		 * line numbers later for error messages
2729 		 */
2730 		cp = line + strspn(line, " \t\r");
2731 		if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
2732 			fatal_fr(r, "sshbuf_put");
2733 	}
2734 	free(line);
2735 	if ((r = sshbuf_put_u8(conf, 0)) != 0)
2736 		fatal_fr(r, "sshbuf_put_u8");
2737 	fclose(f);
2738 	debug2_f("done config len = %zu", sshbuf_len(conf));
2739 }
2740 
2741 void
parse_server_match_config(ServerOptions * options,struct include_list * includes,struct connection_info * connectinfo)2742 parse_server_match_config(ServerOptions *options,
2743    struct include_list *includes, struct connection_info *connectinfo)
2744 {
2745 	ServerOptions mo;
2746 
2747 	initialize_server_options(&mo);
2748 	parse_server_config(&mo, "reprocess config", cfg, includes,
2749 	    connectinfo, 0);
2750 	copy_set_server_options(options, &mo, 0);
2751 }
2752 
parse_server_match_testspec(struct connection_info * ci,char * spec)2753 int parse_server_match_testspec(struct connection_info *ci, char *spec)
2754 {
2755 	char *p;
2756 
2757 	while ((p = strsep(&spec, ",")) && *p != '\0') {
2758 		if (strncmp(p, "addr=", 5) == 0) {
2759 			ci->address = xstrdup(p + 5);
2760 		} else if (strncmp(p, "host=", 5) == 0) {
2761 			ci->host = xstrdup(p + 5);
2762 		} else if (strncmp(p, "user=", 5) == 0) {
2763 			ci->user = xstrdup(p + 5);
2764 		} else if (strncmp(p, "laddr=", 6) == 0) {
2765 			ci->laddress = xstrdup(p + 6);
2766 		} else if (strncmp(p, "rdomain=", 8) == 0) {
2767 			ci->rdomain = xstrdup(p + 8);
2768 		} else if (strncmp(p, "lport=", 6) == 0) {
2769 			ci->lport = a2port(p + 6);
2770 			if (ci->lport == -1) {
2771 				fprintf(stderr, "Invalid port '%s' in test mode"
2772 				    " specification %s\n", p+6, p);
2773 				return -1;
2774 			}
2775 		} else {
2776 			fprintf(stderr, "Invalid test mode specification %s\n",
2777 			    p);
2778 			return -1;
2779 		}
2780 	}
2781 	return 0;
2782 }
2783 
2784 void
servconf_merge_subsystems(ServerOptions * dst,ServerOptions * src)2785 servconf_merge_subsystems(ServerOptions *dst, ServerOptions *src)
2786 {
2787 	u_int i, j, found;
2788 
2789 	for (i = 0; i < src->num_subsystems; i++) {
2790 		found = 0;
2791 		for (j = 0; j < dst->num_subsystems; j++) {
2792 			if (strcmp(src->subsystem_name[i],
2793 			    dst->subsystem_name[j]) == 0) {
2794 				found = 1;
2795 				break;
2796 			}
2797 		}
2798 		if (found) {
2799 			debug_f("override \"%s\"", dst->subsystem_name[j]);
2800 			free(dst->subsystem_command[j]);
2801 			free(dst->subsystem_args[j]);
2802 			dst->subsystem_command[j] =
2803 			    xstrdup(src->subsystem_command[i]);
2804 			dst->subsystem_args[j] =
2805 			    xstrdup(src->subsystem_args[i]);
2806 			continue;
2807 		}
2808 		debug_f("add \"%s\"", src->subsystem_name[i]);
2809 		dst->subsystem_name = xrecallocarray(
2810 		    dst->subsystem_name, dst->num_subsystems,
2811 		    dst->num_subsystems + 1, sizeof(*dst->subsystem_name));
2812 		dst->subsystem_command = xrecallocarray(
2813 		    dst->subsystem_command, dst->num_subsystems,
2814 		    dst->num_subsystems + 1, sizeof(*dst->subsystem_command));
2815 		dst->subsystem_args = xrecallocarray(
2816 		    dst->subsystem_args, dst->num_subsystems,
2817 		    dst->num_subsystems + 1, sizeof(*dst->subsystem_args));
2818 		j = dst->num_subsystems++;
2819 		dst->subsystem_name[j] = xstrdup(src->subsystem_name[i]);
2820 		dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]);
2821 		dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]);
2822 	}
2823 }
2824 
2825 /*
2826  * Copy any supported values that are set.
2827  *
2828  * If the preauth flag is set, we do not bother copying the string or
2829  * array values that are not used pre-authentication, because any that we
2830  * do use must be explicitly sent in mm_getpwnamallow().
2831  */
2832 void
copy_set_server_options(ServerOptions * dst,ServerOptions * src,int preauth)2833 copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
2834 {
2835 #define M_CP_INTOPT(n) do {\
2836 	if (src->n != -1) \
2837 		dst->n = src->n; \
2838 } while (0)
2839 
2840 	M_CP_INTOPT(password_authentication);
2841 	M_CP_INTOPT(gss_authentication);
2842 	M_CP_INTOPT(pubkey_authentication);
2843 	M_CP_INTOPT(pubkey_auth_options);
2844 	M_CP_INTOPT(kerberos_authentication);
2845 	M_CP_INTOPT(hostbased_authentication);
2846 	M_CP_INTOPT(hostbased_uses_name_from_packet_only);
2847 	M_CP_INTOPT(kbd_interactive_authentication);
2848 	M_CP_INTOPT(permit_root_login);
2849 	M_CP_INTOPT(permit_empty_passwd);
2850 	M_CP_INTOPT(ignore_rhosts);
2851 
2852 	M_CP_INTOPT(allow_tcp_forwarding);
2853 	M_CP_INTOPT(allow_streamlocal_forwarding);
2854 	M_CP_INTOPT(allow_agent_forwarding);
2855 	M_CP_INTOPT(disable_forwarding);
2856 	M_CP_INTOPT(expose_userauth_info);
2857 	M_CP_INTOPT(permit_tun);
2858 	M_CP_INTOPT(fwd_opts.gateway_ports);
2859 	M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
2860 	M_CP_INTOPT(x11_display_offset);
2861 	M_CP_INTOPT(x11_forwarding);
2862 	M_CP_INTOPT(x11_use_localhost);
2863 	M_CP_INTOPT(permit_tty);
2864 	M_CP_INTOPT(permit_user_rc);
2865 	M_CP_INTOPT(max_sessions);
2866 	M_CP_INTOPT(max_authtries);
2867 	M_CP_INTOPT(client_alive_count_max);
2868 	M_CP_INTOPT(client_alive_interval);
2869 	M_CP_INTOPT(ip_qos_interactive);
2870 	M_CP_INTOPT(ip_qos_bulk);
2871 	M_CP_INTOPT(rekey_limit);
2872 	M_CP_INTOPT(rekey_interval);
2873 	M_CP_INTOPT(log_level);
2874 	M_CP_INTOPT(required_rsa_size);
2875 	M_CP_INTOPT(unused_connection_timeout);
2876 
2877 	/*
2878 	 * The bind_mask is a mode_t that may be unsigned, so we can't use
2879 	 * M_CP_INTOPT - it does a signed comparison that causes compiler
2880 	 * warnings.
2881 	 */
2882 	if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
2883 		dst->fwd_opts.streamlocal_bind_mask =
2884 		    src->fwd_opts.streamlocal_bind_mask;
2885 	}
2886 
2887 	/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
2888 #define M_CP_STROPT(n) do {\
2889 	if (src->n != NULL && dst->n != src->n) { \
2890 		free(dst->n); \
2891 		dst->n = src->n; \
2892 	} \
2893 } while(0)
2894 #define M_CP_STRARRAYOPT(s, num_s) do {\
2895 	u_int i; \
2896 	if (src->num_s != 0) { \
2897 		for (i = 0; i < dst->num_s; i++) \
2898 			free(dst->s[i]); \
2899 		free(dst->s); \
2900 		dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
2901 		for (i = 0; i < src->num_s; i++) \
2902 			dst->s[i] = xstrdup(src->s[i]); \
2903 		dst->num_s = src->num_s; \
2904 	} \
2905 } while(0)
2906 
2907 	/* See comment in servconf.h */
2908 	COPY_MATCH_STRING_OPTS();
2909 
2910 	/* Arguments that accept '+...' need to be expanded */
2911 	assemble_algorithms(dst);
2912 
2913 	/*
2914 	 * The only things that should be below this point are string options
2915 	 * which are only used after authentication.
2916 	 */
2917 	if (preauth)
2918 		return;
2919 
2920 	/* These options may be "none" to clear a global setting */
2921 	M_CP_STROPT(adm_forced_command);
2922 	if (option_clear_or_none(dst->adm_forced_command)) {
2923 		free(dst->adm_forced_command);
2924 		dst->adm_forced_command = NULL;
2925 	}
2926 	M_CP_STROPT(chroot_directory);
2927 	if (option_clear_or_none(dst->chroot_directory)) {
2928 		free(dst->chroot_directory);
2929 		dst->chroot_directory = NULL;
2930 	}
2931 
2932 	/* Subsystems require merging. */
2933 	servconf_merge_subsystems(dst, src);
2934 }
2935 
2936 #undef M_CP_INTOPT
2937 #undef M_CP_STROPT
2938 #undef M_CP_STRARRAYOPT
2939 
2940 #define SERVCONF_MAX_DEPTH	16
2941 static void
parse_server_config_depth(ServerOptions * options,const char * filename,struct sshbuf * conf,struct include_list * includes,struct connection_info * connectinfo,int flags,int * activep,int depth)2942 parse_server_config_depth(ServerOptions *options, const char *filename,
2943     struct sshbuf *conf, struct include_list *includes,
2944     struct connection_info *connectinfo, int flags, int *activep, int depth)
2945 {
2946 	int linenum, bad_options = 0;
2947 	char *cp, *obuf, *cbuf;
2948 
2949 	if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
2950 		fatal("Too many recursive configuration includes");
2951 
2952 	debug2_f("config %s len %zu%s", filename, sshbuf_len(conf),
2953 	    (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
2954 
2955 	if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
2956 		fatal_f("sshbuf_dup_string failed");
2957 	linenum = 1;
2958 	while ((cp = strsep(&cbuf, "\n")) != NULL) {
2959 		if (process_server_config_line_depth(options, cp,
2960 		    filename, linenum++, activep, connectinfo, &flags,
2961 		    depth, includes) != 0)
2962 			bad_options++;
2963 	}
2964 	free(obuf);
2965 	if (bad_options > 0)
2966 		fatal("%s: terminating, %d bad configuration options",
2967 		    filename, bad_options);
2968 }
2969 
2970 void
parse_server_config(ServerOptions * options,const char * filename,struct sshbuf * conf,struct include_list * includes,struct connection_info * connectinfo,int reexec)2971 parse_server_config(ServerOptions *options, const char *filename,
2972     struct sshbuf *conf, struct include_list *includes,
2973     struct connection_info *connectinfo, int reexec)
2974 {
2975 	int active = connectinfo ? 0 : 1;
2976 	parse_server_config_depth(options, filename, conf, includes,
2977 	    connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
2978 	if (!reexec)
2979 		process_queued_listen_addrs(options);
2980 }
2981 
2982 static const char *
fmt_multistate_int(int val,const struct multistate * m)2983 fmt_multistate_int(int val, const struct multistate *m)
2984 {
2985 	u_int i;
2986 
2987 	for (i = 0; m[i].key != NULL; i++) {
2988 		if (m[i].value == val)
2989 			return m[i].key;
2990 	}
2991 	return "UNKNOWN";
2992 }
2993 
2994 static const char *
fmt_intarg(ServerOpCodes code,int val)2995 fmt_intarg(ServerOpCodes code, int val)
2996 {
2997 	if (val == -1)
2998 		return "unset";
2999 	switch (code) {
3000 	case sAddressFamily:
3001 		return fmt_multistate_int(val, multistate_addressfamily);
3002 	case sPermitRootLogin:
3003 		return fmt_multistate_int(val, multistate_permitrootlogin);
3004 	case sGatewayPorts:
3005 		return fmt_multistate_int(val, multistate_gatewayports);
3006 	case sCompression:
3007 		return fmt_multistate_int(val, multistate_compression);
3008 	case sAllowTcpForwarding:
3009 		return fmt_multistate_int(val, multistate_tcpfwd);
3010 	case sAllowStreamLocalForwarding:
3011 		return fmt_multistate_int(val, multistate_tcpfwd);
3012 	case sIgnoreRhosts:
3013 		return fmt_multistate_int(val, multistate_ignore_rhosts);
3014 	case sFingerprintHash:
3015 		return ssh_digest_alg_name(val);
3016 	default:
3017 		switch (val) {
3018 		case 0:
3019 			return "no";
3020 		case 1:
3021 			return "yes";
3022 		default:
3023 			return "UNKNOWN";
3024 		}
3025 	}
3026 }
3027 
3028 static void
dump_cfg_int(ServerOpCodes code,int val)3029 dump_cfg_int(ServerOpCodes code, int val)
3030 {
3031 	if (code == sUnusedConnectionTimeout && val == 0) {
3032 		printf("%s none\n", lookup_opcode_name(code));
3033 		return;
3034 	}
3035 	printf("%s %d\n", lookup_opcode_name(code), val);
3036 }
3037 
3038 static void
dump_cfg_oct(ServerOpCodes code,int val)3039 dump_cfg_oct(ServerOpCodes code, int val)
3040 {
3041 	printf("%s 0%o\n", lookup_opcode_name(code), val);
3042 }
3043 
3044 static void
dump_cfg_fmtint(ServerOpCodes code,int val)3045 dump_cfg_fmtint(ServerOpCodes code, int val)
3046 {
3047 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3048 }
3049 
3050 static void
dump_cfg_string(ServerOpCodes code,const char * val)3051 dump_cfg_string(ServerOpCodes code, const char *val)
3052 {
3053 	printf("%s %s\n", lookup_opcode_name(code),
3054 	    val == NULL ? "none" : val);
3055 }
3056 
3057 static void
dump_cfg_strarray(ServerOpCodes code,u_int count,char ** vals)3058 dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
3059 {
3060 	u_int i;
3061 
3062 	for (i = 0; i < count; i++)
3063 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3064 }
3065 
3066 static void
dump_cfg_strarray_oneline(ServerOpCodes code,u_int count,char ** vals)3067 dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
3068 {
3069 	u_int i;
3070 
3071 	switch (code) {
3072 	case sAuthenticationMethods:
3073 	case sChannelTimeout:
3074 		break;
3075 	default:
3076 		if (count <= 0)
3077 			return;
3078 		break;
3079 	}
3080 
3081 	printf("%s", lookup_opcode_name(code));
3082 	for (i = 0; i < count; i++)
3083 		printf(" %s",  vals[i]);
3084 	if (code == sAuthenticationMethods && count == 0)
3085 		printf(" any");
3086 	else if (code == sChannelTimeout && count == 0)
3087 		printf(" none");
3088 	printf("\n");
3089 }
3090 
3091 static char *
format_listen_addrs(struct listenaddr * la)3092 format_listen_addrs(struct listenaddr *la)
3093 {
3094 	int r;
3095 	struct addrinfo *ai;
3096 	char addr[NI_MAXHOST], port[NI_MAXSERV];
3097 	char *laddr1 = xstrdup(""), *laddr2 = NULL;
3098 
3099 	/*
3100 	 * ListenAddress must be after Port.  add_one_listen_addr pushes
3101 	 * addresses onto a stack, so to maintain ordering we need to
3102 	 * print these in reverse order.
3103 	 */
3104 	for (ai = la->addrs; ai; ai = ai->ai_next) {
3105 		if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
3106 		    sizeof(addr), port, sizeof(port),
3107 		    NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
3108 			error("getnameinfo: %.100s", ssh_gai_strerror(r));
3109 			continue;
3110 		}
3111 		laddr2 = laddr1;
3112 		if (ai->ai_family == AF_INET6) {
3113 			xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
3114 			    addr, port,
3115 			    la->rdomain == NULL ? "" : " rdomain ",
3116 			    la->rdomain == NULL ? "" : la->rdomain,
3117 			    laddr2);
3118 		} else {
3119 			xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
3120 			    addr, port,
3121 			    la->rdomain == NULL ? "" : " rdomain ",
3122 			    la->rdomain == NULL ? "" : la->rdomain,
3123 			    laddr2);
3124 		}
3125 		free(laddr2);
3126 	}
3127 	return laddr1;
3128 }
3129 
3130 void
dump_config(ServerOptions * o)3131 dump_config(ServerOptions *o)
3132 {
3133 	char *s;
3134 	u_int i;
3135 
3136 	/* these are usually at the top of the config */
3137 	for (i = 0; i < o->num_ports; i++)
3138 		printf("port %d\n", o->ports[i]);
3139 	dump_cfg_fmtint(sAddressFamily, o->address_family);
3140 
3141 	for (i = 0; i < o->num_listen_addrs; i++) {
3142 		s = format_listen_addrs(&o->listen_addrs[i]);
3143 		printf("%s", s);
3144 		free(s);
3145 	}
3146 
3147 	/* integer arguments */
3148 #ifdef USE_PAM
3149 	dump_cfg_fmtint(sUsePAM, o->use_pam);
3150 	dump_cfg_string(sPAMServiceName, o->pam_service_name);
3151 #endif
3152 	dump_cfg_int(sLoginGraceTime, o->login_grace_time);
3153 	dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
3154 	dump_cfg_int(sMaxAuthTries, o->max_authtries);
3155 	dump_cfg_int(sMaxSessions, o->max_sessions);
3156 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
3157 	dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
3158 	dump_cfg_int(sRequiredRSASize, o->required_rsa_size);
3159 	dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
3160 	dump_cfg_int(sUnusedConnectionTimeout, o->unused_connection_timeout);
3161 
3162 	/* formatted integer arguments */
3163 	dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
3164 	dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
3165 	dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
3166 	dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
3167 	dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
3168 	    o->hostbased_uses_name_from_packet_only);
3169 	dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
3170 #ifdef KRB5
3171 	dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
3172 	dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
3173 	dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
3174 # ifdef USE_AFS
3175 	dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
3176 # endif
3177 #endif
3178 #ifdef GSSAPI
3179 	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
3180 	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
3181 #endif
3182 	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
3183 	dump_cfg_fmtint(sKbdInteractiveAuthentication,
3184 	    o->kbd_interactive_authentication);
3185 	dump_cfg_fmtint(sPrintMotd, o->print_motd);
3186 #ifndef DISABLE_LASTLOG
3187 	dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
3188 #endif
3189 	dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
3190 	dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
3191 	dump_cfg_fmtint(sPermitTTY, o->permit_tty);
3192 	dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
3193 	dump_cfg_fmtint(sStrictModes, o->strict_modes);
3194 	dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
3195 	dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
3196 	dump_cfg_fmtint(sCompression, o->compression);
3197 	dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
3198 	dump_cfg_fmtint(sUseDNS, o->use_dns);
3199 	dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
3200 	dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
3201 	dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
3202 	dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
3203 	dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3204 	dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
3205 	dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
3206 
3207 	/* string arguments */
3208 	dump_cfg_string(sPidFile, o->pid_file);
3209 	dump_cfg_string(sModuliFile, o->moduli_file);
3210 	dump_cfg_string(sXAuthLocation, o->xauth_location);
3211 	dump_cfg_string(sCiphers, o->ciphers);
3212 	dump_cfg_string(sMacs, o->macs);
3213 	dump_cfg_string(sBanner, o->banner);
3214 	dump_cfg_string(sForceCommand, o->adm_forced_command);
3215 	dump_cfg_string(sChrootDirectory, o->chroot_directory);
3216 	dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
3217 	dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
3218 	dump_cfg_string(sSecurityKeyProvider, o->sk_provider);
3219 	dump_cfg_string(sAuthorizedPrincipalsFile,
3220 	    o->authorized_principals_file);
3221 	dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
3222 	    ? "none" : o->version_addendum);
3223 	dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
3224 	dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
3225 	dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
3226 	dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
3227 	dump_cfg_string(sHostKeyAgent, o->host_key_agent);
3228 	dump_cfg_string(sKexAlgorithms, o->kex_algorithms);
3229 	dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms);
3230 	dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3231 	dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms);
3232 	dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3233 #if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
3234 	dump_cfg_string(sRDomain, o->routing_domain);
3235 #endif
3236 	dump_cfg_string(sSshdSessionPath, o->sshd_session_path);
3237 	dump_cfg_string(sPerSourcePenaltyExemptList, o->per_source_penalty_exempt);
3238 
3239 	/* string arguments requiring a lookup */
3240 	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
3241 	dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
3242 
3243 	/* string array arguments */
3244 	dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
3245 	    o->authorized_keys_files);
3246 	dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
3247 	    o->host_key_files);
3248 	dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
3249 	    o->host_cert_files);
3250 	dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
3251 	dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
3252 	dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
3253 	dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
3254 	dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
3255 	dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
3256 	dump_cfg_strarray_oneline(sAuthenticationMethods,
3257 	    o->num_auth_methods, o->auth_methods);
3258 	dump_cfg_strarray_oneline(sLogVerbose,
3259 	    o->num_log_verbose, o->log_verbose);
3260 	dump_cfg_strarray_oneline(sChannelTimeout,
3261 	    o->num_channel_timeouts, o->channel_timeouts);
3262 
3263 	/* other arguments */
3264 	for (i = 0; i < o->num_subsystems; i++)
3265 		printf("subsystem %s %s\n", o->subsystem_name[i],
3266 		    o->subsystem_args[i]);
3267 
3268 	printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
3269 	    o->max_startups_rate, o->max_startups);
3270 	printf("persourcemaxstartups ");
3271 	if (o->per_source_max_startups == INT_MAX)
3272 		printf("none\n");
3273 	else
3274 		printf("%d\n", o->per_source_max_startups);
3275 	printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4,
3276 	    o->per_source_masklen_ipv6);
3277 
3278 	s = NULL;
3279 	for (i = 0; tunmode_desc[i].val != -1; i++) {
3280 		if (tunmode_desc[i].val == o->permit_tun) {
3281 			s = tunmode_desc[i].text;
3282 			break;
3283 		}
3284 	}
3285 	dump_cfg_string(sPermitTunnel, s);
3286 
3287 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3288 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3289 
3290 	printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
3291 	    o->rekey_interval);
3292 
3293 	printf("permitopen");
3294 	if (o->num_permitted_opens == 0)
3295 		printf(" any");
3296 	else {
3297 		for (i = 0; i < o->num_permitted_opens; i++)
3298 			printf(" %s", o->permitted_opens[i]);
3299 	}
3300 	printf("\n");
3301 	printf("permitlisten");
3302 	if (o->num_permitted_listens == 0)
3303 		printf(" any");
3304 	else {
3305 		for (i = 0; i < o->num_permitted_listens; i++)
3306 			printf(" %s", o->permitted_listens[i]);
3307 	}
3308 	printf("\n");
3309 
3310 	if (o->permit_user_env_allowlist == NULL) {
3311 		dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
3312 	} else {
3313 		printf("permituserenvironment %s\n",
3314 		    o->permit_user_env_allowlist);
3315 	}
3316 
3317 	printf("pubkeyauthoptions");
3318 	if (o->pubkey_auth_options == 0)
3319 		printf(" none");
3320 	if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
3321 		printf(" touch-required");
3322 	if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
3323 		printf(" verify-required");
3324 	printf("\n");
3325 
3326 	if (o->per_source_penalty.enabled) {
3327 		printf("persourcepenalties crash:%d authfail:%d noauth:%d "
3328 		    "grace-exceeded:%d max:%d min:%d max-sources4:%d "
3329 		    "max-sources6:%d overflow:%s overflow6:%s\n",
3330 		    o->per_source_penalty.penalty_crash,
3331 		    o->per_source_penalty.penalty_authfail,
3332 		    o->per_source_penalty.penalty_noauth,
3333 		    o->per_source_penalty.penalty_grace,
3334 		    o->per_source_penalty.penalty_max,
3335 		    o->per_source_penalty.penalty_min,
3336 		    o->per_source_penalty.max_sources4,
3337 		    o->per_source_penalty.max_sources6,
3338 		    o->per_source_penalty.overflow_mode ==
3339 		    PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ?
3340 		    "deny-all" : "permissive",
3341 		    o->per_source_penalty.overflow_mode6 ==
3342 		    PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ?
3343 		    "deny-all" : "permissive");
3344 	} else
3345 		printf("persourcepenalties no\n");
3346 }
3347