servconf.c revision 181097
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: head/crypto/openssh/servconf.c 181097 2008-08-01 01:13:41Z des $");
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
44static void add_listen_addr(ServerOptions *, char *, u_short);
45static void add_one_listen_addr(ServerOptions *, char *, u_short);
46
47/* Use of privilege separation or not */
48extern int use_privsep;
49extern Buffer cfg;
50
51/* Initializes the server options to their default values. */
52
53void
54initialize_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
128void
129fill_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. */
272typedef 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. */
308static 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
418static ServerOpCodes
419parse_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
435static void
436add_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
451static void
452add_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
506static int
507match_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	}
545out:
546	ga_free();
547	xfree(arg);
548	return result;
549}
550
551static int
552match_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
623int
624process_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;
695parse_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;
707parse_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];
776parse_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;
819parse_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
1294void
1295load_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
1323void
1324parse_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 */
1335void
1336copy_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
1355void
1356parse_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