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