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