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