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