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