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