xref: /freebsd/crypto/openssh/servconf.c (revision acd3428b7d3e94cef0e1881c868cb4b131d4ff41)
1 /* $OpenBSD: servconf.c,v 1.165 2006/08/14 12:40:25 dtucker Exp $ */
2 /*
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  *
6  * As far as I am concerned, the code I have written for this software
7  * can be used freely for any purpose.  Any derived versions of this
8  * software must be clearly marked as such, and if the derived work is
9  * incompatible with the protocol description in the RFC file, it must be
10  * called by a name other than "ssh" or "Secure Shell".
11  */
12 
13 #include "includes.h"
14 __RCSID("$FreeBSD$");
15 
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 
19 #include <netdb.h>
20 #include <pwd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <stdarg.h>
27 
28 #include "xmalloc.h"
29 #include "ssh.h"
30 #include "log.h"
31 #include "buffer.h"
32 #include "servconf.h"
33 #include "compat.h"
34 #include "pathnames.h"
35 #include "misc.h"
36 #include "cipher.h"
37 #include "key.h"
38 #include "kex.h"
39 #include "mac.h"
40 #include "match.h"
41 #include "channels.h"
42 #include "groupaccess.h"
43 
44 static void add_listen_addr(ServerOptions *, char *, u_short);
45 static void add_one_listen_addr(ServerOptions *, char *, u_short);
46 
47 /* Use of privilege separation or not */
48 extern int use_privsep;
49 extern Buffer cfg;
50 
51 /* Initializes the server options to their default values. */
52 
53 void
54 initialize_server_options(ServerOptions *options)
55 {
56 	memset(options, 0, sizeof(*options));
57 
58 	/* Portable-specific options */
59 	options->use_pam = -1;
60 
61 	/* Standard Options */
62 	options->num_ports = 0;
63 	options->ports_from_cmdline = 0;
64 	options->listen_addrs = NULL;
65 	options->address_family = -1;
66 	options->num_host_key_files = 0;
67 	options->pid_file = NULL;
68 	options->server_key_bits = -1;
69 	options->login_grace_time = -1;
70 	options->key_regeneration_time = -1;
71 	options->permit_root_login = PERMIT_NOT_SET;
72 	options->ignore_rhosts = -1;
73 	options->ignore_user_known_hosts = -1;
74 	options->print_motd = -1;
75 	options->print_lastlog = -1;
76 	options->x11_forwarding = -1;
77 	options->x11_display_offset = -1;
78 	options->x11_use_localhost = -1;
79 	options->xauth_location = NULL;
80 	options->strict_modes = -1;
81 	options->tcp_keep_alive = -1;
82 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
83 	options->log_level = SYSLOG_LEVEL_NOT_SET;
84 	options->rhosts_rsa_authentication = -1;
85 	options->hostbased_authentication = -1;
86 	options->hostbased_uses_name_from_packet_only = -1;
87 	options->rsa_authentication = -1;
88 	options->pubkey_authentication = -1;
89 	options->kerberos_authentication = -1;
90 	options->kerberos_or_local_passwd = -1;
91 	options->kerberos_ticket_cleanup = -1;
92 	options->kerberos_get_afs_token = -1;
93 	options->gss_authentication=-1;
94 	options->gss_cleanup_creds = -1;
95 	options->password_authentication = -1;
96 	options->kbd_interactive_authentication = -1;
97 	options->challenge_response_authentication = -1;
98 	options->permit_empty_passwd = -1;
99 	options->permit_user_env = -1;
100 	options->use_login = -1;
101 	options->compression = -1;
102 	options->allow_tcp_forwarding = -1;
103 	options->num_allow_users = 0;
104 	options->num_deny_users = 0;
105 	options->num_allow_groups = 0;
106 	options->num_deny_groups = 0;
107 	options->ciphers = NULL;
108 	options->macs = NULL;
109 	options->protocol = SSH_PROTO_UNKNOWN;
110 	options->gateway_ports = -1;
111 	options->num_subsystems = 0;
112 	options->max_startups_begin = -1;
113 	options->max_startups_rate = -1;
114 	options->max_startups = -1;
115 	options->max_authtries = -1;
116 	options->banner = NULL;
117 	options->use_dns = -1;
118 	options->client_alive_interval = -1;
119 	options->client_alive_count_max = -1;
120 	options->authorized_keys_file = NULL;
121 	options->authorized_keys_file2 = NULL;
122 	options->num_accept_env = 0;
123 	options->permit_tun = -1;
124 	options->num_permitted_opens = -1;
125 	options->adm_forced_command = NULL;
126 }
127 
128 void
129 fill_default_server_options(ServerOptions *options)
130 {
131 	/* Portable-specific options */
132 	if (options->use_pam == -1)
133 		options->use_pam = 1;
134 
135 	/* Standard Options */
136 	if (options->protocol == SSH_PROTO_UNKNOWN)
137 		options->protocol = SSH_PROTO_2;
138 	if (options->num_host_key_files == 0) {
139 		/* fill default hostkeys for protocols */
140 		if (options->protocol & SSH_PROTO_1)
141 			options->host_key_files[options->num_host_key_files++] =
142 			    _PATH_HOST_KEY_FILE;
143 		if (options->protocol & SSH_PROTO_2) {
144 			options->host_key_files[options->num_host_key_files++] =
145 			    _PATH_HOST_DSA_KEY_FILE;
146 		}
147 	}
148 	if (options->num_ports == 0)
149 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
150 	if (options->listen_addrs == NULL)
151 		add_listen_addr(options, NULL, 0);
152 	if (options->pid_file == NULL)
153 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
154 	if (options->server_key_bits == -1)
155 		options->server_key_bits = 768;
156 	if (options->login_grace_time == -1)
157 		options->login_grace_time = 120;
158 	if (options->key_regeneration_time == -1)
159 		options->key_regeneration_time = 3600;
160 	if (options->permit_root_login == PERMIT_NOT_SET)
161 		options->permit_root_login = PERMIT_NO;
162 	if (options->ignore_rhosts == -1)
163 		options->ignore_rhosts = 1;
164 	if (options->ignore_user_known_hosts == -1)
165 		options->ignore_user_known_hosts = 0;
166 	if (options->print_motd == -1)
167 		options->print_motd = 1;
168 	if (options->print_lastlog == -1)
169 		options->print_lastlog = 1;
170 	if (options->x11_forwarding == -1)
171 		options->x11_forwarding = 1;
172 	if (options->x11_display_offset == -1)
173 		options->x11_display_offset = 10;
174 	if (options->x11_use_localhost == -1)
175 		options->x11_use_localhost = 1;
176 	if (options->xauth_location == NULL)
177 		options->xauth_location = _PATH_XAUTH;
178 	if (options->strict_modes == -1)
179 		options->strict_modes = 1;
180 	if (options->tcp_keep_alive == -1)
181 		options->tcp_keep_alive = 1;
182 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
183 		options->log_facility = SYSLOG_FACILITY_AUTH;
184 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
185 		options->log_level = SYSLOG_LEVEL_INFO;
186 	if (options->rhosts_rsa_authentication == -1)
187 		options->rhosts_rsa_authentication = 0;
188 	if (options->hostbased_authentication == -1)
189 		options->hostbased_authentication = 0;
190 	if (options->hostbased_uses_name_from_packet_only == -1)
191 		options->hostbased_uses_name_from_packet_only = 0;
192 	if (options->rsa_authentication == -1)
193 		options->rsa_authentication = 1;
194 	if (options->pubkey_authentication == -1)
195 		options->pubkey_authentication = 1;
196 	if (options->kerberos_authentication == -1)
197 		options->kerberos_authentication = 0;
198 	if (options->kerberos_or_local_passwd == -1)
199 		options->kerberos_or_local_passwd = 1;
200 	if (options->kerberos_ticket_cleanup == -1)
201 		options->kerberos_ticket_cleanup = 1;
202 	if (options->kerberos_get_afs_token == -1)
203 		options->kerberos_get_afs_token = 0;
204 	if (options->gss_authentication == -1)
205 		options->gss_authentication = 0;
206 	if (options->gss_cleanup_creds == -1)
207 		options->gss_cleanup_creds = 1;
208 	if (options->password_authentication == -1)
209 #ifdef USE_PAM
210 		options->password_authentication = 0;
211 #else
212 		options->password_authentication = 1;
213 #endif
214 	if (options->kbd_interactive_authentication == -1)
215 		options->kbd_interactive_authentication = 0;
216 	if (options->challenge_response_authentication == -1)
217 		options->challenge_response_authentication = 1;
218 	if (options->permit_empty_passwd == -1)
219 		options->permit_empty_passwd = 0;
220 	if (options->permit_user_env == -1)
221 		options->permit_user_env = 0;
222 	if (options->use_login == -1)
223 		options->use_login = 0;
224 	if (options->compression == -1)
225 		options->compression = COMP_DELAYED;
226 	if (options->allow_tcp_forwarding == -1)
227 		options->allow_tcp_forwarding = 1;
228 	if (options->gateway_ports == -1)
229 		options->gateway_ports = 0;
230 	if (options->max_startups == -1)
231 		options->max_startups = 10;
232 	if (options->max_startups_rate == -1)
233 		options->max_startups_rate = 100;		/* 100% */
234 	if (options->max_startups_begin == -1)
235 		options->max_startups_begin = options->max_startups;
236 	if (options->max_authtries == -1)
237 		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
238 	if (options->use_dns == -1)
239 		options->use_dns = 1;
240 	if (options->client_alive_interval == -1)
241 		options->client_alive_interval = 0;
242 	if (options->client_alive_count_max == -1)
243 		options->client_alive_count_max = 3;
244 	if (options->authorized_keys_file2 == NULL) {
245 		/* authorized_keys_file2 falls back to authorized_keys_file */
246 		if (options->authorized_keys_file != NULL)
247 			options->authorized_keys_file2 = options->authorized_keys_file;
248 		else
249 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
250 	}
251 	if (options->authorized_keys_file == NULL)
252 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
253 	if (options->permit_tun == -1)
254 		options->permit_tun = SSH_TUNMODE_NO;
255 
256 	/* Turn privilege separation on by default */
257 	if (use_privsep == -1)
258 		use_privsep = 1;
259 
260 #ifndef HAVE_MMAP
261 	if (use_privsep && options->compression == 1) {
262 		error("This platform does not support both privilege "
263 		    "separation and compression");
264 		error("Compression disabled");
265 		options->compression = 0;
266 	}
267 #endif
268 
269 }
270 
271 /* Keyword tokens. */
272 typedef enum {
273 	sBadOption,		/* == unknown option */
274 	/* Portable-specific options */
275 	sUsePAM,
276 	/* Standard Options */
277 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
278 	sPermitRootLogin, sLogFacility, sLogLevel,
279 	sRhostsRSAAuthentication, sRSAAuthentication,
280 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
281 	sKerberosGetAFSToken,
282 	sKerberosTgtPassing, sChallengeResponseAuthentication,
283 	sPasswordAuthentication, sKbdInteractiveAuthentication,
284 	sListenAddress, sAddressFamily,
285 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
286 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
287 	sStrictModes, sEmptyPasswd, sTCPKeepAlive,
288 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
289 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
290 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
291 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
292 	sMaxStartups, sMaxAuthTries,
293 	sBanner, sUseDNS, sHostbasedAuthentication,
294 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
295 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
296 	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
297 	sMatch, sPermitOpen, sForceCommand,
298 	sUsePrivilegeSeparation,
299 	sVersionAddendum,
300 	sDeprecated, sUnsupported
301 } ServerOpCodes;
302 
303 #define SSHCFG_GLOBAL	0x01	/* allowed in main section of sshd_config */
304 #define SSHCFG_MATCH	0x02	/* allowed inside a Match section */
305 #define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
306 
307 /* Textual representation of the tokens. */
308 static struct {
309 	const char *name;
310 	ServerOpCodes opcode;
311 	u_int flags;
312 } keywords[] = {
313 	/* Portable-specific options */
314 #ifdef USE_PAM
315 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
316 #else
317 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
318 #endif
319 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
320 	/* Standard Options */
321 	{ "port", sPort, SSHCFG_GLOBAL },
322 	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
323 	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },		/* alias */
324 	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
325 	{ "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
326 	{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
327 	{ "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
328 	{ "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
329 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
330 	{ "loglevel", sLogLevel, SSHCFG_GLOBAL },
331 	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
332 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
333 	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
334 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
335 	{ "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
336 	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
337 	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },	/* alias */
338 #ifdef KRB5
339 	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
340 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
341 	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
342 #ifdef USE_AFS
343 	{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
344 #else
345 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
346 #endif
347 #else
348 	{ "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
349 	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
350 	{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
351 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
352 #endif
353 	{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
354 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
355 #ifdef GSSAPI
356 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
357 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
358 #else
359 	{ "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
360 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
361 #endif
362 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
363 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
364 	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
365 	{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
366 	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
367 	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
368 	{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
369 	{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
370 	{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
371 	{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
372 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
373 	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
374 	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
375 	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
376 	{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
377 	{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
378 	{ "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
379 	{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
380 	{ "uselogin", sUseLogin, SSHCFG_GLOBAL },
381 	{ "compression", sCompression, SSHCFG_GLOBAL },
382 	{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
383 	{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },	/* obsolete alias */
384 	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
385 	{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
386 	{ "denyusers", sDenyUsers, SSHCFG_GLOBAL },
387 	{ "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
388 	{ "denygroups", sDenyGroups, SSHCFG_GLOBAL },
389 	{ "ciphers", sCiphers, SSHCFG_GLOBAL },
390 	{ "macs", sMacs, SSHCFG_GLOBAL },
391 	{ "protocol", sProtocol, SSHCFG_GLOBAL },
392 	{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
393 	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
394 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
395 	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
396 	{ "banner", sBanner, SSHCFG_GLOBAL },
397 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
398 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
399 	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
400 	{ "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
401 	{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
402 	{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
403 	{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
404 	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
405 	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
406 	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
407  	{ "match", sMatch, SSHCFG_ALL },
408 	{ "permitopen", sPermitOpen, SSHCFG_ALL },
409 	{ "forcecommand", sForceCommand, SSHCFG_ALL },
410 	{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
411 	{ NULL, sBadOption, 0 }
412 };
413 
414 /*
415  * Returns the number of the token pointed to by cp or sBadOption.
416  */
417 
418 static ServerOpCodes
419 parse_token(const char *cp, const char *filename,
420 	    int linenum, u_int *flags)
421 {
422 	u_int i;
423 
424 	for (i = 0; keywords[i].name; i++)
425 		if (strcasecmp(cp, keywords[i].name) == 0) {
426 			*flags = keywords[i].flags;
427 			return keywords[i].opcode;
428 		}
429 
430 	error("%s: line %d: Bad configuration option: %s",
431 	    filename, linenum, cp);
432 	return sBadOption;
433 }
434 
435 static void
436 add_listen_addr(ServerOptions *options, char *addr, u_short port)
437 {
438 	u_int i;
439 
440 	if (options->num_ports == 0)
441 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
442 	if (options->address_family == -1)
443 		options->address_family = AF_UNSPEC;
444 	if (port == 0)
445 		for (i = 0; i < options->num_ports; i++)
446 			add_one_listen_addr(options, addr, options->ports[i]);
447 	else
448 		add_one_listen_addr(options, addr, port);
449 }
450 
451 static void
452 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
453 {
454 	struct addrinfo hints, *ai, *aitop;
455 	char strport[NI_MAXSERV];
456 	int gaierr;
457 
458 	memset(&hints, 0, sizeof(hints));
459 	hints.ai_family = options->address_family;
460 	hints.ai_socktype = SOCK_STREAM;
461 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
462 	snprintf(strport, sizeof strport, "%u", port);
463 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
464 		fatal("bad addr or host: %s (%s)",
465 		    addr ? addr : "<NULL>",
466 		    gai_strerror(gaierr));
467 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
468 		;
469 	ai->ai_next = options->listen_addrs;
470 	options->listen_addrs = aitop;
471 }
472 
473 /*
474  * The strategy for the Match blocks is that the config file is parsed twice.
475  *
476  * The first time is at startup.  activep is initialized to 1 and the
477  * directives in the global context are processed and acted on.  Hitting a
478  * Match directive unsets activep and the directives inside the block are
479  * checked for syntax only.
480  *
481  * The second time is after a connection has been established but before
482  * authentication.  activep is initialized to 2 and global config directives
483  * are ignored since they have already been processed.  If the criteria in a
484  * Match block is met, activep is set and the subsequent directives
485  * processed and actioned until EOF or another Match block unsets it.  Any
486  * options set are copied into the main server config.
487  *
488  * Potential additions/improvements:
489  *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
490  *
491  *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
492  *	Match Address 192.168.0.*
493  *		Tag trusted
494  *	Match Group wheel
495  *		Tag trusted
496  *	Match Tag trusted
497  *		AllowTcpForwarding yes
498  *		GatewayPorts clientspecified
499  *		[...]
500  *
501  *  - Add a PermittedChannelRequests directive
502  *	Match Group shell
503  *		PermittedChannelRequests session,forwarded-tcpip
504  */
505 
506 static int
507 match_cfg_line_group(const char *grps, int line, const char *user)
508 {
509 	int result = 0;
510 	u_int ngrps = 0;
511 	char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
512 	struct passwd *pw;
513 
514 	/*
515 	 * Even if we do not have a user yet, we still need to check for
516 	 * valid syntax.
517 	 */
518 	arg = cp = xstrdup(grps);
519 	while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
520 		if (ngrps >= MAX_MATCH_GROUPS) {
521 			error("line %d: too many groups in Match Group", line);
522 			result = -1;
523 			goto out;
524 		}
525 		grplist[ngrps++] = p;
526 	}
527 
528 	if (user == NULL)
529 		goto out;
530 
531 	if ((pw = getpwnam(user)) == NULL) {
532 		debug("Can't match group at line %d because user %.100s does "
533 		    "not exist", line, user);
534 	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
535 		debug("Can't Match group because user %.100s not in any group "
536 		    "at line %d", user, line);
537 	} else if (ga_match(grplist, ngrps) != 1) {
538 		debug("user %.100s does not match group %.100s at line %d",
539 		    user, arg, line);
540 	} else {
541 		debug("user %.100s matched group %.100s at line %d", user,
542 		    arg, line);
543 		result = 1;
544 	}
545 out:
546 	ga_free();
547 	xfree(arg);
548 	return result;
549 }
550 
551 static int
552 match_cfg_line(char **condition, int line, const char *user, const char *host,
553     const char *address)
554 {
555 	int result = 1;
556 	char *arg, *attrib, *cp = *condition;
557 	size_t len;
558 
559 	if (user == NULL)
560 		debug3("checking syntax for 'Match %s'", cp);
561 	else
562 		debug3("checking match for '%s' user %s host %s addr %s", cp,
563 		    user ? user : "(null)", host ? host : "(null)",
564 		    address ? address : "(null)");
565 
566 	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
567 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
568 			error("Missing Match criteria for %s", attrib);
569 			return -1;
570 		}
571 		len = strlen(arg);
572 		if (strcasecmp(attrib, "user") == 0) {
573 			if (!user) {
574 				result = 0;
575 				continue;
576 			}
577 			if (match_pattern_list(user, arg, len, 0) != 1)
578 				result = 0;
579 			else
580 				debug("user %.100s matched 'User %.100s' at "
581 				    "line %d", user, arg, line);
582 		} else if (strcasecmp(attrib, "group") == 0) {
583 			switch (match_cfg_line_group(arg, line, user)) {
584 			case -1:
585 				return -1;
586 			case 0:
587 				result = 0;
588 			}
589 		} else if (strcasecmp(attrib, "host") == 0) {
590 			if (!host) {
591 				result = 0;
592 				continue;
593 			}
594 			if (match_hostname(host, arg, len) != 1)
595 				result = 0;
596 			else
597 				debug("connection from %.100s matched 'Host "
598 				    "%.100s' at line %d", host, arg, line);
599 		} else if (strcasecmp(attrib, "address") == 0) {
600 			debug("address '%s' arg '%s'", address, arg);
601 			if (!address) {
602 				result = 0;
603 				continue;
604 			}
605 			if (match_hostname(address, arg, len) != 1)
606 				result = 0;
607 			else
608 				debug("connection from %.100s matched 'Address "
609 				    "%.100s' at line %d", address, arg, line);
610 		} else {
611 			error("Unsupported Match attribute %s", attrib);
612 			return -1;
613 		}
614 	}
615 	if (user != NULL)
616 		debug3("match %sfound", result ? "" : "not ");
617 	*condition = cp;
618 	return result;
619 }
620 
621 #define WHITESPACE " \t\r\n"
622 
623 int
624 process_server_config_line(ServerOptions *options, char *line,
625     const char *filename, int linenum, int *activep, const char *user,
626     const char *host, const char *address)
627 {
628 	char *cp, **charptr, *arg, *p;
629 	int cmdline = 0, *intptr, value, n;
630 	ServerOpCodes opcode;
631 	u_short port;
632 	u_int i, flags = 0;
633 	size_t len;
634 
635 	cp = line;
636 	if ((arg = strdelim(&cp)) == NULL)
637 		return 0;
638 	/* Ignore leading whitespace */
639 	if (*arg == '\0')
640 		arg = strdelim(&cp);
641 	if (!arg || !*arg || *arg == '#')
642 		return 0;
643 	intptr = NULL;
644 	charptr = NULL;
645 	opcode = parse_token(arg, filename, linenum, &flags);
646 
647 	if (activep == NULL) { /* We are processing a command line directive */
648 		cmdline = 1;
649 		activep = &cmdline;
650 	}
651 	if (*activep && opcode != sMatch)
652 		debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
653 	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
654 		if (user == NULL) {
655 			fatal("%s line %d: Directive '%s' is not allowed "
656 			    "within a Match block", filename, linenum, arg);
657 		} else { /* this is a directive we have already processed */
658 			while (arg)
659 				arg = strdelim(&cp);
660 			return 0;
661 		}
662 	}
663 
664 	switch (opcode) {
665 	/* Portable-specific options */
666 	case sUsePAM:
667 		intptr = &options->use_pam;
668 		goto parse_flag;
669 
670 	/* Standard Options */
671 	case sBadOption:
672 		return -1;
673 	case sPort:
674 		/* ignore ports from configfile if cmdline specifies ports */
675 		if (options->ports_from_cmdline)
676 			return 0;
677 		if (options->listen_addrs != NULL)
678 			fatal("%s line %d: ports must be specified before "
679 			    "ListenAddress.", filename, linenum);
680 		if (options->num_ports >= MAX_PORTS)
681 			fatal("%s line %d: too many ports.",
682 			    filename, linenum);
683 		arg = strdelim(&cp);
684 		if (!arg || *arg == '\0')
685 			fatal("%s line %d: missing port number.",
686 			    filename, linenum);
687 		options->ports[options->num_ports++] = a2port(arg);
688 		if (options->ports[options->num_ports-1] == 0)
689 			fatal("%s line %d: Badly formatted port number.",
690 			    filename, linenum);
691 		break;
692 
693 	case sServerKeyBits:
694 		intptr = &options->server_key_bits;
695 parse_int:
696 		arg = strdelim(&cp);
697 		if (!arg || *arg == '\0')
698 			fatal("%s line %d: missing integer value.",
699 			    filename, linenum);
700 		value = atoi(arg);
701 		if (*activep && *intptr == -1)
702 			*intptr = value;
703 		break;
704 
705 	case sLoginGraceTime:
706 		intptr = &options->login_grace_time;
707 parse_time:
708 		arg = strdelim(&cp);
709 		if (!arg || *arg == '\0')
710 			fatal("%s line %d: missing time value.",
711 			    filename, linenum);
712 		if ((value = convtime(arg)) == -1)
713 			fatal("%s line %d: invalid time value.",
714 			    filename, linenum);
715 		if (*intptr == -1)
716 			*intptr = value;
717 		break;
718 
719 	case sKeyRegenerationTime:
720 		intptr = &options->key_regeneration_time;
721 		goto parse_time;
722 
723 	case sListenAddress:
724 		arg = strdelim(&cp);
725 		if (arg == NULL || *arg == '\0')
726 			fatal("%s line %d: missing address",
727 			    filename, linenum);
728 		/* check for bare IPv6 address: no "[]" and 2 or more ":" */
729 		if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
730 		    && strchr(p+1, ':') != NULL) {
731 			add_listen_addr(options, arg, 0);
732 			break;
733 		}
734 		p = hpdelim(&arg);
735 		if (p == NULL)
736 			fatal("%s line %d: bad address:port usage",
737 			    filename, linenum);
738 		p = cleanhostname(p);
739 		if (arg == NULL)
740 			port = 0;
741 		else if ((port = a2port(arg)) == 0)
742 			fatal("%s line %d: bad port number", filename, linenum);
743 
744 		add_listen_addr(options, p, port);
745 
746 		break;
747 
748 	case sAddressFamily:
749 		arg = strdelim(&cp);
750 		if (!arg || *arg == '\0')
751 			fatal("%s line %d: missing address family.",
752 			    filename, linenum);
753 		intptr = &options->address_family;
754 		if (options->listen_addrs != NULL)
755 			fatal("%s line %d: address family must be specified before "
756 			    "ListenAddress.", filename, linenum);
757 		if (strcasecmp(arg, "inet") == 0)
758 			value = AF_INET;
759 		else if (strcasecmp(arg, "inet6") == 0)
760 			value = AF_INET6;
761 		else if (strcasecmp(arg, "any") == 0)
762 			value = AF_UNSPEC;
763 		else
764 			fatal("%s line %d: unsupported address family \"%s\".",
765 			    filename, linenum, arg);
766 		if (*intptr == -1)
767 			*intptr = value;
768 		break;
769 
770 	case sHostKeyFile:
771 		intptr = &options->num_host_key_files;
772 		if (*intptr >= MAX_HOSTKEYS)
773 			fatal("%s line %d: too many host keys specified (max %d).",
774 			    filename, linenum, MAX_HOSTKEYS);
775 		charptr = &options->host_key_files[*intptr];
776 parse_filename:
777 		arg = strdelim(&cp);
778 		if (!arg || *arg == '\0')
779 			fatal("%s line %d: missing file name.",
780 			    filename, linenum);
781 		if (*activep && *charptr == NULL) {
782 			*charptr = tilde_expand_filename(arg, getuid());
783 			/* increase optional counter */
784 			if (intptr != NULL)
785 				*intptr = *intptr + 1;
786 		}
787 		break;
788 
789 	case sPidFile:
790 		charptr = &options->pid_file;
791 		goto parse_filename;
792 
793 	case sPermitRootLogin:
794 		intptr = &options->permit_root_login;
795 		arg = strdelim(&cp);
796 		if (!arg || *arg == '\0')
797 			fatal("%s line %d: missing yes/"
798 			    "without-password/forced-commands-only/no "
799 			    "argument.", filename, linenum);
800 		value = 0;	/* silence compiler */
801 		if (strcmp(arg, "without-password") == 0)
802 			value = PERMIT_NO_PASSWD;
803 		else if (strcmp(arg, "forced-commands-only") == 0)
804 			value = PERMIT_FORCED_ONLY;
805 		else if (strcmp(arg, "yes") == 0)
806 			value = PERMIT_YES;
807 		else if (strcmp(arg, "no") == 0)
808 			value = PERMIT_NO;
809 		else
810 			fatal("%s line %d: Bad yes/"
811 			    "without-password/forced-commands-only/no "
812 			    "argument: %s", filename, linenum, arg);
813 		if (*intptr == -1)
814 			*intptr = value;
815 		break;
816 
817 	case sIgnoreRhosts:
818 		intptr = &options->ignore_rhosts;
819 parse_flag:
820 		arg = strdelim(&cp);
821 		if (!arg || *arg == '\0')
822 			fatal("%s line %d: missing yes/no argument.",
823 			    filename, linenum);
824 		value = 0;	/* silence compiler */
825 		if (strcmp(arg, "yes") == 0)
826 			value = 1;
827 		else if (strcmp(arg, "no") == 0)
828 			value = 0;
829 		else
830 			fatal("%s line %d: Bad yes/no argument: %s",
831 				filename, linenum, arg);
832 		if (*activep && *intptr == -1)
833 			*intptr = value;
834 		break;
835 
836 	case sIgnoreUserKnownHosts:
837 		intptr = &options->ignore_user_known_hosts;
838 		goto parse_flag;
839 
840 	case sRhostsRSAAuthentication:
841 		intptr = &options->rhosts_rsa_authentication;
842 		goto parse_flag;
843 
844 	case sHostbasedAuthentication:
845 		intptr = &options->hostbased_authentication;
846 		goto parse_flag;
847 
848 	case sHostbasedUsesNameFromPacketOnly:
849 		intptr = &options->hostbased_uses_name_from_packet_only;
850 		goto parse_flag;
851 
852 	case sRSAAuthentication:
853 		intptr = &options->rsa_authentication;
854 		goto parse_flag;
855 
856 	case sPubkeyAuthentication:
857 		intptr = &options->pubkey_authentication;
858 		goto parse_flag;
859 
860 	case sKerberosAuthentication:
861 		intptr = &options->kerberos_authentication;
862 		goto parse_flag;
863 
864 	case sKerberosOrLocalPasswd:
865 		intptr = &options->kerberos_or_local_passwd;
866 		goto parse_flag;
867 
868 	case sKerberosTicketCleanup:
869 		intptr = &options->kerberos_ticket_cleanup;
870 		goto parse_flag;
871 
872 	case sKerberosGetAFSToken:
873 		intptr = &options->kerberos_get_afs_token;
874 		goto parse_flag;
875 
876 	case sGssAuthentication:
877 		intptr = &options->gss_authentication;
878 		goto parse_flag;
879 
880 	case sGssCleanupCreds:
881 		intptr = &options->gss_cleanup_creds;
882 		goto parse_flag;
883 
884 	case sPasswordAuthentication:
885 		intptr = &options->password_authentication;
886 		goto parse_flag;
887 
888 	case sKbdInteractiveAuthentication:
889 		intptr = &options->kbd_interactive_authentication;
890 		goto parse_flag;
891 
892 	case sChallengeResponseAuthentication:
893 		intptr = &options->challenge_response_authentication;
894 		goto parse_flag;
895 
896 	case sPrintMotd:
897 		intptr = &options->print_motd;
898 		goto parse_flag;
899 
900 	case sPrintLastLog:
901 		intptr = &options->print_lastlog;
902 		goto parse_flag;
903 
904 	case sX11Forwarding:
905 		intptr = &options->x11_forwarding;
906 		goto parse_flag;
907 
908 	case sX11DisplayOffset:
909 		intptr = &options->x11_display_offset;
910 		goto parse_int;
911 
912 	case sX11UseLocalhost:
913 		intptr = &options->x11_use_localhost;
914 		goto parse_flag;
915 
916 	case sXAuthLocation:
917 		charptr = &options->xauth_location;
918 		goto parse_filename;
919 
920 	case sStrictModes:
921 		intptr = &options->strict_modes;
922 		goto parse_flag;
923 
924 	case sTCPKeepAlive:
925 		intptr = &options->tcp_keep_alive;
926 		goto parse_flag;
927 
928 	case sEmptyPasswd:
929 		intptr = &options->permit_empty_passwd;
930 		goto parse_flag;
931 
932 	case sPermitUserEnvironment:
933 		intptr = &options->permit_user_env;
934 		goto parse_flag;
935 
936 	case sUseLogin:
937 		intptr = &options->use_login;
938 		goto parse_flag;
939 
940 	case sCompression:
941 		intptr = &options->compression;
942 		arg = strdelim(&cp);
943 		if (!arg || *arg == '\0')
944 			fatal("%s line %d: missing yes/no/delayed "
945 			    "argument.", filename, linenum);
946 		value = 0;	/* silence compiler */
947 		if (strcmp(arg, "delayed") == 0)
948 			value = COMP_DELAYED;
949 		else if (strcmp(arg, "yes") == 0)
950 			value = COMP_ZLIB;
951 		else if (strcmp(arg, "no") == 0)
952 			value = COMP_NONE;
953 		else
954 			fatal("%s line %d: Bad yes/no/delayed "
955 			    "argument: %s", filename, linenum, arg);
956 		if (*intptr == -1)
957 			*intptr = value;
958 		break;
959 
960 	case sGatewayPorts:
961 		intptr = &options->gateway_ports;
962 		arg = strdelim(&cp);
963 		if (!arg || *arg == '\0')
964 			fatal("%s line %d: missing yes/no/clientspecified "
965 			    "argument.", filename, linenum);
966 		value = 0;	/* silence compiler */
967 		if (strcmp(arg, "clientspecified") == 0)
968 			value = 2;
969 		else if (strcmp(arg, "yes") == 0)
970 			value = 1;
971 		else if (strcmp(arg, "no") == 0)
972 			value = 0;
973 		else
974 			fatal("%s line %d: Bad yes/no/clientspecified "
975 			    "argument: %s", filename, linenum, arg);
976 		if (*intptr == -1)
977 			*intptr = value;
978 		break;
979 
980 	case sUseDNS:
981 		intptr = &options->use_dns;
982 		goto parse_flag;
983 
984 	case sLogFacility:
985 		intptr = (int *) &options->log_facility;
986 		arg = strdelim(&cp);
987 		value = log_facility_number(arg);
988 		if (value == SYSLOG_FACILITY_NOT_SET)
989 			fatal("%.200s line %d: unsupported log facility '%s'",
990 			    filename, linenum, arg ? arg : "<NONE>");
991 		if (*intptr == -1)
992 			*intptr = (SyslogFacility) value;
993 		break;
994 
995 	case sLogLevel:
996 		intptr = (int *) &options->log_level;
997 		arg = strdelim(&cp);
998 		value = log_level_number(arg);
999 		if (value == SYSLOG_LEVEL_NOT_SET)
1000 			fatal("%.200s line %d: unsupported log level '%s'",
1001 			    filename, linenum, arg ? arg : "<NONE>");
1002 		if (*intptr == -1)
1003 			*intptr = (LogLevel) value;
1004 		break;
1005 
1006 	case sAllowTcpForwarding:
1007 		intptr = &options->allow_tcp_forwarding;
1008 		goto parse_flag;
1009 
1010 	case sUsePrivilegeSeparation:
1011 		intptr = &use_privsep;
1012 		goto parse_flag;
1013 
1014 	case sAllowUsers:
1015 		while ((arg = strdelim(&cp)) && *arg != '\0') {
1016 			if (options->num_allow_users >= MAX_ALLOW_USERS)
1017 				fatal("%s line %d: too many allow users.",
1018 				    filename, linenum);
1019 			options->allow_users[options->num_allow_users++] =
1020 			    xstrdup(arg);
1021 		}
1022 		break;
1023 
1024 	case sDenyUsers:
1025 		while ((arg = strdelim(&cp)) && *arg != '\0') {
1026 			if (options->num_deny_users >= MAX_DENY_USERS)
1027 				fatal("%s line %d: too many deny users.",
1028 				    filename, linenum);
1029 			options->deny_users[options->num_deny_users++] =
1030 			    xstrdup(arg);
1031 		}
1032 		break;
1033 
1034 	case sAllowGroups:
1035 		while ((arg = strdelim(&cp)) && *arg != '\0') {
1036 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1037 				fatal("%s line %d: too many allow groups.",
1038 				    filename, linenum);
1039 			options->allow_groups[options->num_allow_groups++] =
1040 			    xstrdup(arg);
1041 		}
1042 		break;
1043 
1044 	case sDenyGroups:
1045 		while ((arg = strdelim(&cp)) && *arg != '\0') {
1046 			if (options->num_deny_groups >= MAX_DENY_GROUPS)
1047 				fatal("%s line %d: too many deny groups.",
1048 				    filename, linenum);
1049 			options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1050 		}
1051 		break;
1052 
1053 	case sCiphers:
1054 		arg = strdelim(&cp);
1055 		if (!arg || *arg == '\0')
1056 			fatal("%s line %d: Missing argument.", filename, linenum);
1057 		if (!ciphers_valid(arg))
1058 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1059 			    filename, linenum, arg ? arg : "<NONE>");
1060 		if (options->ciphers == NULL)
1061 			options->ciphers = xstrdup(arg);
1062 		break;
1063 
1064 	case sMacs:
1065 		arg = strdelim(&cp);
1066 		if (!arg || *arg == '\0')
1067 			fatal("%s line %d: Missing argument.", filename, linenum);
1068 		if (!mac_valid(arg))
1069 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1070 			    filename, linenum, arg ? arg : "<NONE>");
1071 		if (options->macs == NULL)
1072 			options->macs = xstrdup(arg);
1073 		break;
1074 
1075 	case sProtocol:
1076 		intptr = &options->protocol;
1077 		arg = strdelim(&cp);
1078 		if (!arg || *arg == '\0')
1079 			fatal("%s line %d: Missing argument.", filename, linenum);
1080 		value = proto_spec(arg);
1081 		if (value == SSH_PROTO_UNKNOWN)
1082 			fatal("%s line %d: Bad protocol spec '%s'.",
1083 			    filename, linenum, arg ? arg : "<NONE>");
1084 		if (*intptr == SSH_PROTO_UNKNOWN)
1085 			*intptr = value;
1086 		break;
1087 
1088 	case sSubsystem:
1089 		if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1090 			fatal("%s line %d: too many subsystems defined.",
1091 			    filename, linenum);
1092 		}
1093 		arg = strdelim(&cp);
1094 		if (!arg || *arg == '\0')
1095 			fatal("%s line %d: Missing subsystem name.",
1096 			    filename, linenum);
1097 		if (!*activep) {
1098 			arg = strdelim(&cp);
1099 			break;
1100 		}
1101 		for (i = 0; i < options->num_subsystems; i++)
1102 			if (strcmp(arg, options->subsystem_name[i]) == 0)
1103 				fatal("%s line %d: Subsystem '%s' already defined.",
1104 				    filename, linenum, arg);
1105 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1106 		arg = strdelim(&cp);
1107 		if (!arg || *arg == '\0')
1108 			fatal("%s line %d: Missing subsystem command.",
1109 			    filename, linenum);
1110 		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1111 
1112 		/* Collect arguments (separate to executable) */
1113 		p = xstrdup(arg);
1114 		len = strlen(p) + 1;
1115 		while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1116 			len += 1 + strlen(arg);
1117 			p = xrealloc(p, 1, len);
1118 			strlcat(p, " ", len);
1119 			strlcat(p, arg, len);
1120 		}
1121 		options->subsystem_args[options->num_subsystems] = p;
1122 		options->num_subsystems++;
1123 		break;
1124 
1125 	case sMaxStartups:
1126 		arg = strdelim(&cp);
1127 		if (!arg || *arg == '\0')
1128 			fatal("%s line %d: Missing MaxStartups spec.",
1129 			    filename, linenum);
1130 		if ((n = sscanf(arg, "%d:%d:%d",
1131 		    &options->max_startups_begin,
1132 		    &options->max_startups_rate,
1133 		    &options->max_startups)) == 3) {
1134 			if (options->max_startups_begin >
1135 			    options->max_startups ||
1136 			    options->max_startups_rate > 100 ||
1137 			    options->max_startups_rate < 1)
1138 				fatal("%s line %d: Illegal MaxStartups spec.",
1139 				    filename, linenum);
1140 		} else if (n != 1)
1141 			fatal("%s line %d: Illegal MaxStartups spec.",
1142 			    filename, linenum);
1143 		else
1144 			options->max_startups = options->max_startups_begin;
1145 		break;
1146 
1147 	case sMaxAuthTries:
1148 		intptr = &options->max_authtries;
1149 		goto parse_int;
1150 
1151 	case sBanner:
1152 		charptr = &options->banner;
1153 		goto parse_filename;
1154 	/*
1155 	 * These options can contain %X options expanded at
1156 	 * connect time, so that you can specify paths like:
1157 	 *
1158 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
1159 	 */
1160 	case sAuthorizedKeysFile:
1161 	case sAuthorizedKeysFile2:
1162 		charptr = (opcode == sAuthorizedKeysFile) ?
1163 		    &options->authorized_keys_file :
1164 		    &options->authorized_keys_file2;
1165 		goto parse_filename;
1166 
1167 	case sClientAliveInterval:
1168 		intptr = &options->client_alive_interval;
1169 		goto parse_time;
1170 
1171 	case sClientAliveCountMax:
1172 		intptr = &options->client_alive_count_max;
1173 		goto parse_int;
1174 
1175 	case sAcceptEnv:
1176 		while ((arg = strdelim(&cp)) && *arg != '\0') {
1177 			if (strchr(arg, '=') != NULL)
1178 				fatal("%s line %d: Invalid environment name.",
1179 				    filename, linenum);
1180 			if (options->num_accept_env >= MAX_ACCEPT_ENV)
1181 				fatal("%s line %d: too many allow env.",
1182 				    filename, linenum);
1183 			if (!*activep)
1184 				break;
1185 			options->accept_env[options->num_accept_env++] =
1186 			    xstrdup(arg);
1187 		}
1188 		break;
1189 
1190 	case sPermitTunnel:
1191 		intptr = &options->permit_tun;
1192 		arg = strdelim(&cp);
1193 		if (!arg || *arg == '\0')
1194 			fatal("%s line %d: Missing yes/point-to-point/"
1195 			    "ethernet/no argument.", filename, linenum);
1196 		value = 0;	/* silence compiler */
1197 		if (strcasecmp(arg, "ethernet") == 0)
1198 			value = SSH_TUNMODE_ETHERNET;
1199 		else if (strcasecmp(arg, "point-to-point") == 0)
1200 			value = SSH_TUNMODE_POINTOPOINT;
1201 		else if (strcasecmp(arg, "yes") == 0)
1202 			value = SSH_TUNMODE_YES;
1203 		else if (strcasecmp(arg, "no") == 0)
1204 			value = SSH_TUNMODE_NO;
1205 		else
1206 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1207 			    "no argument: %s", filename, linenum, arg);
1208 		if (*intptr == -1)
1209 			*intptr = value;
1210 		break;
1211 
1212 	case sMatch:
1213 		if (cmdline)
1214 			fatal("Match directive not supported as a command-line "
1215 			   "option");
1216 		value = match_cfg_line(&cp, linenum, user, host, address);
1217 		if (value < 0)
1218 			fatal("%s line %d: Bad Match condition", filename,
1219 			    linenum);
1220 		*activep = value;
1221 		break;
1222 
1223 	case sPermitOpen:
1224 		arg = strdelim(&cp);
1225 		if (!arg || *arg == '\0')
1226 			fatal("%s line %d: missing PermitOpen specification",
1227 			    filename, linenum);
1228 		if (strcmp(arg, "any") == 0) {
1229 			if (*activep) {
1230 				channel_clear_adm_permitted_opens();
1231 				options->num_permitted_opens = 0;
1232 			}
1233 			break;
1234 		}
1235 		for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1236 			p = hpdelim(&arg);
1237 			if (p == NULL)
1238 				fatal("%s line %d: missing host in PermitOpen",
1239 				    filename, linenum);
1240 			p = cleanhostname(p);
1241 			if (arg == NULL || (port = a2port(arg)) == 0)
1242 				fatal("%s line %d: bad port number in "
1243 				    "PermitOpen", filename, linenum);
1244 			if (*activep && options->num_permitted_opens == -1) {
1245 				channel_clear_adm_permitted_opens();
1246 				options->num_permitted_opens =
1247 				    channel_add_adm_permitted_opens(p, port);
1248 			}
1249 		}
1250 		break;
1251 
1252 	case sForceCommand:
1253 		if (cp == NULL)
1254 			fatal("%.200s line %d: Missing argument.", filename,
1255 			    linenum);
1256 		len = strspn(cp, WHITESPACE);
1257 		if (*activep && options->adm_forced_command == NULL)
1258 			options->adm_forced_command = xstrdup(cp + len);
1259 		return 0;
1260 
1261 	case sVersionAddendum:
1262                 ssh_version_set_addendum(strtok(cp, "\n"));
1263                 do {
1264                         arg = strdelim(&cp);
1265                 } while (arg != NULL && *arg != '\0');
1266 		break;
1267 
1268 	case sDeprecated:
1269 		logit("%s line %d: Deprecated option %s",
1270 		    filename, linenum, arg);
1271 		while (arg)
1272 		    arg = strdelim(&cp);
1273 		break;
1274 
1275 	case sUnsupported:
1276 		logit("%s line %d: Unsupported option %s",
1277 		    filename, linenum, arg);
1278 		while (arg)
1279 		    arg = strdelim(&cp);
1280 		break;
1281 
1282 	default:
1283 		fatal("%s line %d: Missing handler for opcode %s (%d)",
1284 		    filename, linenum, arg, opcode);
1285 	}
1286 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1287 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
1288 		    filename, linenum, arg);
1289 	return 0;
1290 }
1291 
1292 /* Reads the server configuration file. */
1293 
1294 void
1295 load_server_config(const char *filename, Buffer *conf)
1296 {
1297 	char line[1024], *cp;
1298 	FILE *f;
1299 
1300 	debug2("%s: filename %s", __func__, filename);
1301 	if ((f = fopen(filename, "r")) == NULL) {
1302 		perror(filename);
1303 		exit(1);
1304 	}
1305 	buffer_clear(conf);
1306 	while (fgets(line, sizeof(line), f)) {
1307 		/*
1308 		 * Trim out comments and strip whitespace
1309 		 * NB - preserve newlines, they are needed to reproduce
1310 		 * line numbers later for error messages
1311 		 */
1312 		if ((cp = strchr(line, '#')) != NULL)
1313 			memcpy(cp, "\n", 2);
1314 		cp = line + strspn(line, " \t\r");
1315 
1316 		buffer_append(conf, cp, strlen(cp));
1317 	}
1318 	buffer_append(conf, "\0", 1);
1319 	fclose(f);
1320 	debug2("%s: done config len = %d", __func__, buffer_len(conf));
1321 }
1322 
1323 void
1324 parse_server_match_config(ServerOptions *options, const char *user,
1325     const char *host, const char *address)
1326 {
1327 	ServerOptions mo;
1328 
1329 	initialize_server_options(&mo);
1330 	parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1331 	copy_set_server_options(options, &mo);
1332 }
1333 
1334 /* Copy any (supported) values that are set */
1335 void
1336 copy_set_server_options(ServerOptions *dst, ServerOptions *src)
1337 {
1338 	if (src->allow_tcp_forwarding != -1)
1339 		dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
1340 	if (src->gateway_ports != -1)
1341 		dst->gateway_ports = src->gateway_ports;
1342 	if (src->adm_forced_command != NULL) {
1343 		if (dst->adm_forced_command != NULL)
1344 			xfree(dst->adm_forced_command);
1345 		dst->adm_forced_command = src->adm_forced_command;
1346 	}
1347 	if (src->x11_display_offset != -1)
1348 		dst->x11_display_offset = src->x11_display_offset;
1349 	if (src->x11_forwarding != -1)
1350 		dst->x11_forwarding = src->x11_forwarding;
1351 	if (src->x11_use_localhost != -1)
1352 		dst->x11_use_localhost = src->x11_use_localhost;
1353 }
1354 
1355 void
1356 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1357     const char *user, const char *host, const char *address)
1358 {
1359 	int active, linenum, bad_options = 0;
1360 	char *cp, *obuf, *cbuf;
1361 
1362 	debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1363 
1364 	obuf = cbuf = xstrdup(buffer_ptr(conf));
1365 	active = user ? 0 : 1;
1366 	linenum = 1;
1367 	while ((cp = strsep(&cbuf, "\n")) != NULL) {
1368 		if (process_server_config_line(options, cp, filename,
1369 		    linenum++, &active, user, host, address) != 0)
1370 			bad_options++;
1371 	}
1372 	xfree(obuf);
1373 	if (bad_options > 0)
1374 		fatal("%s: terminating, %d bad configuration options",
1375 		    filename, bad_options);
1376 }
1377