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