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