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