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