xref: /openbsd-src/usr.bin/ssh/servconf.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*
2  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3  *                    All rights reserved
4  *
5  * As far as I am concerned, the code I have written for this software
6  * can be used freely for any purpose.  Any derived versions of this
7  * software must be clearly marked as such, and if the derived work is
8  * incompatible with the protocol description in the RFC file, it must be
9  * called by a name other than "ssh" or "Secure Shell".
10  */
11 
12 #include "includes.h"
13 RCSID("$OpenBSD: servconf.c,v 1.123 2003/07/22 13:35:22 markus Exp $");
14 
15 #include "ssh.h"
16 #include "log.h"
17 #include "servconf.h"
18 #include "xmalloc.h"
19 #include "compat.h"
20 #include "pathnames.h"
21 #include "tildexpand.h"
22 #include "misc.h"
23 #include "cipher.h"
24 #include "kex.h"
25 #include "mac.h"
26 
27 static void add_listen_addr(ServerOptions *, char *, u_short);
28 static void add_one_listen_addr(ServerOptions *, char *, u_short);
29 
30 /* AF_UNSPEC or AF_INET or AF_INET6 */
31 extern int IPv4or6;
32 /* Use of privilege separation or not */
33 extern int use_privsep;
34 
35 /* Initializes the server options to their default values. */
36 
37 void
38 initialize_server_options(ServerOptions *options)
39 {
40 	memset(options, 0, sizeof(*options));
41 	options->num_ports = 0;
42 	options->ports_from_cmdline = 0;
43 	options->listen_addrs = NULL;
44 	options->num_host_key_files = 0;
45 	options->pid_file = NULL;
46 	options->server_key_bits = -1;
47 	options->login_grace_time = -1;
48 	options->key_regeneration_time = -1;
49 	options->permit_root_login = PERMIT_NOT_SET;
50 	options->ignore_rhosts = -1;
51 	options->ignore_user_known_hosts = -1;
52 	options->print_motd = -1;
53 	options->print_lastlog = -1;
54 	options->x11_forwarding = -1;
55 	options->x11_display_offset = -1;
56 	options->x11_use_localhost = -1;
57 	options->xauth_location = NULL;
58 	options->strict_modes = -1;
59 	options->keepalives = -1;
60 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
61 	options->log_level = SYSLOG_LEVEL_NOT_SET;
62 	options->rhosts_authentication = -1;
63 	options->rhosts_rsa_authentication = -1;
64 	options->hostbased_authentication = -1;
65 	options->hostbased_uses_name_from_packet_only = -1;
66 	options->rsa_authentication = -1;
67 	options->pubkey_authentication = -1;
68 	options->kerberos_authentication = -1;
69 	options->kerberos_or_local_passwd = -1;
70 	options->kerberos_ticket_cleanup = -1;
71 	options->kerberos_tgt_passing = -1;
72 	options->password_authentication = -1;
73 	options->kbd_interactive_authentication = -1;
74 	options->challenge_response_authentication = -1;
75 	options->permit_empty_passwd = -1;
76 	options->permit_user_env = -1;
77 	options->use_login = -1;
78 	options->compression = -1;
79 	options->allow_tcp_forwarding = -1;
80 	options->num_allow_users = 0;
81 	options->num_deny_users = 0;
82 	options->num_allow_groups = 0;
83 	options->num_deny_groups = 0;
84 	options->ciphers = NULL;
85 	options->macs = NULL;
86 	options->protocol = SSH_PROTO_UNKNOWN;
87 	options->gateway_ports = -1;
88 	options->num_subsystems = 0;
89 	options->max_startups_begin = -1;
90 	options->max_startups_rate = -1;
91 	options->max_startups = -1;
92 	options->banner = NULL;
93 	options->use_dns = -1;
94 	options->client_alive_interval = -1;
95 	options->client_alive_count_max = -1;
96 	options->authorized_keys_file = NULL;
97 	options->authorized_keys_file2 = NULL;
98 
99 	/* Needs to be accessable in many places */
100 	use_privsep = -1;
101 }
102 
103 void
104 fill_default_server_options(ServerOptions *options)
105 {
106 	if (options->protocol == SSH_PROTO_UNKNOWN)
107 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
108 	if (options->num_host_key_files == 0) {
109 		/* fill default hostkeys for protocols */
110 		if (options->protocol & SSH_PROTO_1)
111 			options->host_key_files[options->num_host_key_files++] =
112 			    _PATH_HOST_KEY_FILE;
113 		if (options->protocol & SSH_PROTO_2) {
114 			options->host_key_files[options->num_host_key_files++] =
115 			    _PATH_HOST_RSA_KEY_FILE;
116 			options->host_key_files[options->num_host_key_files++] =
117 			    _PATH_HOST_DSA_KEY_FILE;
118 		}
119 	}
120 	if (options->num_ports == 0)
121 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
122 	if (options->listen_addrs == NULL)
123 		add_listen_addr(options, NULL, 0);
124 	if (options->pid_file == NULL)
125 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
126 	if (options->server_key_bits == -1)
127 		options->server_key_bits = 768;
128 	if (options->login_grace_time == -1)
129 		options->login_grace_time = 120;
130 	if (options->key_regeneration_time == -1)
131 		options->key_regeneration_time = 3600;
132 	if (options->permit_root_login == PERMIT_NOT_SET)
133 		options->permit_root_login = PERMIT_YES;
134 	if (options->ignore_rhosts == -1)
135 		options->ignore_rhosts = 1;
136 	if (options->ignore_user_known_hosts == -1)
137 		options->ignore_user_known_hosts = 0;
138 	if (options->print_motd == -1)
139 		options->print_motd = 1;
140 	if (options->print_lastlog == -1)
141 		options->print_lastlog = 1;
142 	if (options->x11_forwarding == -1)
143 		options->x11_forwarding = 0;
144 	if (options->x11_display_offset == -1)
145 		options->x11_display_offset = 10;
146 	if (options->x11_use_localhost == -1)
147 		options->x11_use_localhost = 1;
148 	if (options->xauth_location == NULL)
149 		options->xauth_location = _PATH_XAUTH;
150 	if (options->strict_modes == -1)
151 		options->strict_modes = 1;
152 	if (options->keepalives == -1)
153 		options->keepalives = 1;
154 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
155 		options->log_facility = SYSLOG_FACILITY_AUTH;
156 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
157 		options->log_level = SYSLOG_LEVEL_INFO;
158 	if (options->rhosts_authentication == -1)
159 		options->rhosts_authentication = 0;
160 	if (options->rhosts_rsa_authentication == -1)
161 		options->rhosts_rsa_authentication = 0;
162 	if (options->hostbased_authentication == -1)
163 		options->hostbased_authentication = 0;
164 	if (options->hostbased_uses_name_from_packet_only == -1)
165 		options->hostbased_uses_name_from_packet_only = 0;
166 	if (options->rsa_authentication == -1)
167 		options->rsa_authentication = 1;
168 	if (options->pubkey_authentication == -1)
169 		options->pubkey_authentication = 1;
170 	if (options->kerberos_authentication == -1)
171 		options->kerberos_authentication = 0;
172 	if (options->kerberos_or_local_passwd == -1)
173 		options->kerberos_or_local_passwd = 1;
174 	if (options->kerberos_ticket_cleanup == -1)
175 		options->kerberos_ticket_cleanup = 1;
176 	if (options->kerberos_tgt_passing == -1)
177 		options->kerberos_tgt_passing = 0;
178 	if (options->password_authentication == -1)
179 		options->password_authentication = 1;
180 	if (options->kbd_interactive_authentication == -1)
181 		options->kbd_interactive_authentication = 0;
182 	if (options->challenge_response_authentication == -1)
183 		options->challenge_response_authentication = 1;
184 	if (options->permit_empty_passwd == -1)
185 		options->permit_empty_passwd = 0;
186 	if (options->permit_user_env == -1)
187 		options->permit_user_env = 0;
188 	if (options->use_login == -1)
189 		options->use_login = 0;
190 	if (options->compression == -1)
191 		options->compression = 1;
192 	if (options->allow_tcp_forwarding == -1)
193 		options->allow_tcp_forwarding = 1;
194 	if (options->gateway_ports == -1)
195 		options->gateway_ports = 0;
196 	if (options->max_startups == -1)
197 		options->max_startups = 10;
198 	if (options->max_startups_rate == -1)
199 		options->max_startups_rate = 100;		/* 100% */
200 	if (options->max_startups_begin == -1)
201 		options->max_startups_begin = options->max_startups;
202 	if (options->use_dns == -1)
203 		options->use_dns = 1;
204 	if (options->client_alive_interval == -1)
205 		options->client_alive_interval = 0;
206 	if (options->client_alive_count_max == -1)
207 		options->client_alive_count_max = 3;
208 	if (options->authorized_keys_file2 == NULL) {
209 		/* authorized_keys_file2 falls back to authorized_keys_file */
210 		if (options->authorized_keys_file != NULL)
211 			options->authorized_keys_file2 = options->authorized_keys_file;
212 		else
213 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
214 	}
215 	if (options->authorized_keys_file == NULL)
216 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
217 
218 	/* Turn privilege separation on by default */
219 	if (use_privsep == -1)
220 		use_privsep = 1;
221 }
222 
223 /* Keyword tokens. */
224 typedef enum {
225 	sBadOption,		/* == unknown option */
226 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
227 	sPermitRootLogin, sLogFacility, sLogLevel,
228 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
229 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
230 	sKerberosTgtPassing, sChallengeResponseAuthentication,
231 	sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
232 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
233 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
234 	sStrictModes, sEmptyPasswd, sKeepAlives,
235 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
236 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
237 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
238 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
239 	sBanner, sUseDNS, sHostbasedAuthentication,
240 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
241 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
242 	sUsePrivilegeSeparation,
243 	sDeprecated, sUnsupported
244 } ServerOpCodes;
245 
246 /* Textual representation of the tokens. */
247 static struct {
248 	const char *name;
249 	ServerOpCodes opcode;
250 } keywords[] = {
251 	{ "port", sPort },
252 	{ "hostkey", sHostKeyFile },
253 	{ "hostdsakey", sHostKeyFile },					/* alias */
254 	{ "pidfile", sPidFile },
255 	{ "serverkeybits", sServerKeyBits },
256 	{ "logingracetime", sLoginGraceTime },
257 	{ "keyregenerationinterval", sKeyRegenerationTime },
258 	{ "permitrootlogin", sPermitRootLogin },
259 	{ "syslogfacility", sLogFacility },
260 	{ "loglevel", sLogLevel },
261 	{ "rhostsauthentication", sRhostsAuthentication },
262 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
263 	{ "hostbasedauthentication", sHostbasedAuthentication },
264 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
265 	{ "rsaauthentication", sRSAAuthentication },
266 	{ "pubkeyauthentication", sPubkeyAuthentication },
267 	{ "dsaauthentication", sPubkeyAuthentication },			/* alias */
268 #ifdef KRB5
269 	{ "kerberosauthentication", sKerberosAuthentication },
270 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
271 	{ "kerberosticketcleanup", sKerberosTicketCleanup },
272 	{ "kerberostgtpassing", sKerberosTgtPassing },
273 #else
274 	{ "kerberosauthentication", sUnsupported },
275 	{ "kerberosorlocalpasswd", sUnsupported },
276 	{ "kerberosticketcleanup", sUnsupported },
277 	{ "kerberostgtpassing", sUnsupported },
278 #endif
279 	{ "afstokenpassing", sUnsupported },
280 	{ "passwordauthentication", sPasswordAuthentication },
281 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
282 	{ "challengeresponseauthentication", sChallengeResponseAuthentication },
283 	{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
284 	{ "checkmail", sDeprecated },
285 	{ "listenaddress", sListenAddress },
286 	{ "printmotd", sPrintMotd },
287 	{ "printlastlog", sPrintLastLog },
288 	{ "ignorerhosts", sIgnoreRhosts },
289 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
290 	{ "x11forwarding", sX11Forwarding },
291 	{ "x11displayoffset", sX11DisplayOffset },
292 	{ "x11uselocalhost", sX11UseLocalhost },
293 	{ "xauthlocation", sXAuthLocation },
294 	{ "strictmodes", sStrictModes },
295 	{ "permitemptypasswords", sEmptyPasswd },
296 	{ "permituserenvironment", sPermitUserEnvironment },
297 	{ "uselogin", sUseLogin },
298 	{ "compression", sCompression },
299 	{ "keepalive", sKeepAlives },
300 	{ "allowtcpforwarding", sAllowTcpForwarding },
301 	{ "allowusers", sAllowUsers },
302 	{ "denyusers", sDenyUsers },
303 	{ "allowgroups", sAllowGroups },
304 	{ "denygroups", sDenyGroups },
305 	{ "ciphers", sCiphers },
306 	{ "macs", sMacs },
307 	{ "protocol", sProtocol },
308 	{ "gatewayports", sGatewayPorts },
309 	{ "subsystem", sSubsystem },
310 	{ "maxstartups", sMaxStartups },
311 	{ "banner", sBanner },
312 	{ "usedns", sUseDNS },
313 	{ "verifyreversemapping", sDeprecated },
314 	{ "reversemappingcheck", sDeprecated },
315 	{ "clientaliveinterval", sClientAliveInterval },
316 	{ "clientalivecountmax", sClientAliveCountMax },
317 	{ "authorizedkeysfile", sAuthorizedKeysFile },
318 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
319 	{ "useprivilegeseparation", sUsePrivilegeSeparation},
320 	{ NULL, sBadOption }
321 };
322 
323 /*
324  * Returns the number of the token pointed to by cp or sBadOption.
325  */
326 
327 static ServerOpCodes
328 parse_token(const char *cp, const char *filename,
329 	    int linenum)
330 {
331 	u_int i;
332 
333 	for (i = 0; keywords[i].name; i++)
334 		if (strcasecmp(cp, keywords[i].name) == 0)
335 			return keywords[i].opcode;
336 
337 	error("%s: line %d: Bad configuration option: %s",
338 	    filename, linenum, cp);
339 	return sBadOption;
340 }
341 
342 static void
343 add_listen_addr(ServerOptions *options, char *addr, u_short port)
344 {
345 	int i;
346 
347 	if (options->num_ports == 0)
348 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
349 	if (port == 0)
350 		for (i = 0; i < options->num_ports; i++)
351 			add_one_listen_addr(options, addr, options->ports[i]);
352 	else
353 		add_one_listen_addr(options, addr, port);
354 }
355 
356 static void
357 add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
358 {
359 	struct addrinfo hints, *ai, *aitop;
360 	char strport[NI_MAXSERV];
361 	int gaierr;
362 
363 	memset(&hints, 0, sizeof(hints));
364 	hints.ai_family = IPv4or6;
365 	hints.ai_socktype = SOCK_STREAM;
366 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
367 	snprintf(strport, sizeof strport, "%u", port);
368 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
369 		fatal("bad addr or host: %s (%s)",
370 		    addr ? addr : "<NULL>",
371 		    gai_strerror(gaierr));
372 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
373 		;
374 	ai->ai_next = options->listen_addrs;
375 	options->listen_addrs = aitop;
376 }
377 
378 int
379 process_server_config_line(ServerOptions *options, char *line,
380     const char *filename, int linenum)
381 {
382 	char *cp, **charptr, *arg, *p;
383 	int *intptr, value, i, n;
384 	ServerOpCodes opcode;
385 
386 	cp = line;
387 	arg = strdelim(&cp);
388 	/* Ignore leading whitespace */
389 	if (*arg == '\0')
390 		arg = strdelim(&cp);
391 	if (!arg || !*arg || *arg == '#')
392 		return 0;
393 	intptr = NULL;
394 	charptr = NULL;
395 	opcode = parse_token(arg, filename, linenum);
396 	switch (opcode) {
397 	case sBadOption:
398 		return -1;
399 	case sPort:
400 		/* ignore ports from configfile if cmdline specifies ports */
401 		if (options->ports_from_cmdline)
402 			return 0;
403 		if (options->listen_addrs != NULL)
404 			fatal("%s line %d: ports must be specified before "
405 			    "ListenAddress.", filename, linenum);
406 		if (options->num_ports >= MAX_PORTS)
407 			fatal("%s line %d: too many ports.",
408 			    filename, linenum);
409 		arg = strdelim(&cp);
410 		if (!arg || *arg == '\0')
411 			fatal("%s line %d: missing port number.",
412 			    filename, linenum);
413 		options->ports[options->num_ports++] = a2port(arg);
414 		if (options->ports[options->num_ports-1] == 0)
415 			fatal("%s line %d: Badly formatted port number.",
416 			    filename, linenum);
417 		break;
418 
419 	case sServerKeyBits:
420 		intptr = &options->server_key_bits;
421 parse_int:
422 		arg = strdelim(&cp);
423 		if (!arg || *arg == '\0')
424 			fatal("%s line %d: missing integer value.",
425 			    filename, linenum);
426 		value = atoi(arg);
427 		if (*intptr == -1)
428 			*intptr = value;
429 		break;
430 
431 	case sLoginGraceTime:
432 		intptr = &options->login_grace_time;
433 parse_time:
434 		arg = strdelim(&cp);
435 		if (!arg || *arg == '\0')
436 			fatal("%s line %d: missing time value.",
437 			    filename, linenum);
438 		if ((value = convtime(arg)) == -1)
439 			fatal("%s line %d: invalid time value.",
440 			    filename, linenum);
441 		if (*intptr == -1)
442 			*intptr = value;
443 		break;
444 
445 	case sKeyRegenerationTime:
446 		intptr = &options->key_regeneration_time;
447 		goto parse_time;
448 
449 	case sListenAddress:
450 		arg = strdelim(&cp);
451 		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
452 			fatal("%s line %d: missing inet addr.",
453 			    filename, linenum);
454 		if (*arg == '[') {
455 			if ((p = strchr(arg, ']')) == NULL)
456 				fatal("%s line %d: bad ipv6 inet addr usage.",
457 				    filename, linenum);
458 			arg++;
459 			memmove(p, p+1, strlen(p+1)+1);
460 		} else if (((p = strchr(arg, ':')) == NULL) ||
461 			    (strchr(p+1, ':') != NULL)) {
462 			add_listen_addr(options, arg, 0);
463 			break;
464 		}
465 		if (*p == ':') {
466 			u_short port;
467 
468 			p++;
469 			if (*p == '\0')
470 				fatal("%s line %d: bad inet addr:port usage.",
471 				    filename, linenum);
472 			else {
473 				*(p-1) = '\0';
474 				if ((port = a2port(p)) == 0)
475 					fatal("%s line %d: bad port number.",
476 					    filename, linenum);
477 				add_listen_addr(options, arg, port);
478 			}
479 		} else if (*p == '\0')
480 			add_listen_addr(options, arg, 0);
481 		else
482 			fatal("%s line %d: bad inet addr usage.",
483 			    filename, linenum);
484 		break;
485 
486 	case sHostKeyFile:
487 		intptr = &options->num_host_key_files;
488 		if (*intptr >= MAX_HOSTKEYS)
489 			fatal("%s line %d: too many host keys specified (max %d).",
490 			    filename, linenum, MAX_HOSTKEYS);
491 		charptr = &options->host_key_files[*intptr];
492 parse_filename:
493 		arg = strdelim(&cp);
494 		if (!arg || *arg == '\0')
495 			fatal("%s line %d: missing file name.",
496 			    filename, linenum);
497 		if (*charptr == NULL) {
498 			*charptr = tilde_expand_filename(arg, getuid());
499 			/* increase optional counter */
500 			if (intptr != NULL)
501 				*intptr = *intptr + 1;
502 		}
503 		break;
504 
505 	case sPidFile:
506 		charptr = &options->pid_file;
507 		goto parse_filename;
508 
509 	case sPermitRootLogin:
510 		intptr = &options->permit_root_login;
511 		arg = strdelim(&cp);
512 		if (!arg || *arg == '\0')
513 			fatal("%s line %d: missing yes/"
514 			    "without-password/forced-commands-only/no "
515 			    "argument.", filename, linenum);
516 		value = 0;	/* silence compiler */
517 		if (strcmp(arg, "without-password") == 0)
518 			value = PERMIT_NO_PASSWD;
519 		else if (strcmp(arg, "forced-commands-only") == 0)
520 			value = PERMIT_FORCED_ONLY;
521 		else if (strcmp(arg, "yes") == 0)
522 			value = PERMIT_YES;
523 		else if (strcmp(arg, "no") == 0)
524 			value = PERMIT_NO;
525 		else
526 			fatal("%s line %d: Bad yes/"
527 			    "without-password/forced-commands-only/no "
528 			    "argument: %s", filename, linenum, arg);
529 		if (*intptr == -1)
530 			*intptr = value;
531 		break;
532 
533 	case sIgnoreRhosts:
534 		intptr = &options->ignore_rhosts;
535 parse_flag:
536 		arg = strdelim(&cp);
537 		if (!arg || *arg == '\0')
538 			fatal("%s line %d: missing yes/no argument.",
539 			    filename, linenum);
540 		value = 0;	/* silence compiler */
541 		if (strcmp(arg, "yes") == 0)
542 			value = 1;
543 		else if (strcmp(arg, "no") == 0)
544 			value = 0;
545 		else
546 			fatal("%s line %d: Bad yes/no argument: %s",
547 				filename, linenum, arg);
548 		if (*intptr == -1)
549 			*intptr = value;
550 		break;
551 
552 	case sIgnoreUserKnownHosts:
553 		intptr = &options->ignore_user_known_hosts;
554 		goto parse_flag;
555 
556 	case sRhostsAuthentication:
557 		intptr = &options->rhosts_authentication;
558 		goto parse_flag;
559 
560 	case sRhostsRSAAuthentication:
561 		intptr = &options->rhosts_rsa_authentication;
562 		goto parse_flag;
563 
564 	case sHostbasedAuthentication:
565 		intptr = &options->hostbased_authentication;
566 		goto parse_flag;
567 
568 	case sHostbasedUsesNameFromPacketOnly:
569 		intptr = &options->hostbased_uses_name_from_packet_only;
570 		goto parse_flag;
571 
572 	case sRSAAuthentication:
573 		intptr = &options->rsa_authentication;
574 		goto parse_flag;
575 
576 	case sPubkeyAuthentication:
577 		intptr = &options->pubkey_authentication;
578 		goto parse_flag;
579 
580 	case sKerberosAuthentication:
581 		intptr = &options->kerberos_authentication;
582 		goto parse_flag;
583 
584 	case sKerberosOrLocalPasswd:
585 		intptr = &options->kerberos_or_local_passwd;
586 		goto parse_flag;
587 
588 	case sKerberosTicketCleanup:
589 		intptr = &options->kerberos_ticket_cleanup;
590 		goto parse_flag;
591 
592 	case sKerberosTgtPassing:
593 		intptr = &options->kerberos_tgt_passing;
594 		goto parse_flag;
595 
596 	case sPasswordAuthentication:
597 		intptr = &options->password_authentication;
598 		goto parse_flag;
599 
600 	case sKbdInteractiveAuthentication:
601 		intptr = &options->kbd_interactive_authentication;
602 		goto parse_flag;
603 
604 	case sChallengeResponseAuthentication:
605 		intptr = &options->challenge_response_authentication;
606 		goto parse_flag;
607 
608 	case sPrintMotd:
609 		intptr = &options->print_motd;
610 		goto parse_flag;
611 
612 	case sPrintLastLog:
613 		intptr = &options->print_lastlog;
614 		goto parse_flag;
615 
616 	case sX11Forwarding:
617 		intptr = &options->x11_forwarding;
618 		goto parse_flag;
619 
620 	case sX11DisplayOffset:
621 		intptr = &options->x11_display_offset;
622 		goto parse_int;
623 
624 	case sX11UseLocalhost:
625 		intptr = &options->x11_use_localhost;
626 		goto parse_flag;
627 
628 	case sXAuthLocation:
629 		charptr = &options->xauth_location;
630 		goto parse_filename;
631 
632 	case sStrictModes:
633 		intptr = &options->strict_modes;
634 		goto parse_flag;
635 
636 	case sKeepAlives:
637 		intptr = &options->keepalives;
638 		goto parse_flag;
639 
640 	case sEmptyPasswd:
641 		intptr = &options->permit_empty_passwd;
642 		goto parse_flag;
643 
644 	case sPermitUserEnvironment:
645 		intptr = &options->permit_user_env;
646 		goto parse_flag;
647 
648 	case sUseLogin:
649 		intptr = &options->use_login;
650 		goto parse_flag;
651 
652 	case sCompression:
653 		intptr = &options->compression;
654 		goto parse_flag;
655 
656 	case sGatewayPorts:
657 		intptr = &options->gateway_ports;
658 		goto parse_flag;
659 
660 	case sUseDNS:
661 		intptr = &options->use_dns;
662 		goto parse_flag;
663 
664 	case sLogFacility:
665 		intptr = (int *) &options->log_facility;
666 		arg = strdelim(&cp);
667 		value = log_facility_number(arg);
668 		if (value == SYSLOG_FACILITY_NOT_SET)
669 			fatal("%.200s line %d: unsupported log facility '%s'",
670 			    filename, linenum, arg ? arg : "<NONE>");
671 		if (*intptr == -1)
672 			*intptr = (SyslogFacility) value;
673 		break;
674 
675 	case sLogLevel:
676 		intptr = (int *) &options->log_level;
677 		arg = strdelim(&cp);
678 		value = log_level_number(arg);
679 		if (value == SYSLOG_LEVEL_NOT_SET)
680 			fatal("%.200s line %d: unsupported log level '%s'",
681 			    filename, linenum, arg ? arg : "<NONE>");
682 		if (*intptr == -1)
683 			*intptr = (LogLevel) value;
684 		break;
685 
686 	case sAllowTcpForwarding:
687 		intptr = &options->allow_tcp_forwarding;
688 		goto parse_flag;
689 
690 	case sUsePrivilegeSeparation:
691 		intptr = &use_privsep;
692 		goto parse_flag;
693 
694 	case sAllowUsers:
695 		while ((arg = strdelim(&cp)) && *arg != '\0') {
696 			if (options->num_allow_users >= MAX_ALLOW_USERS)
697 				fatal("%s line %d: too many allow users.",
698 				    filename, linenum);
699 			options->allow_users[options->num_allow_users++] =
700 			    xstrdup(arg);
701 		}
702 		break;
703 
704 	case sDenyUsers:
705 		while ((arg = strdelim(&cp)) && *arg != '\0') {
706 			if (options->num_deny_users >= MAX_DENY_USERS)
707 				fatal( "%s line %d: too many deny users.",
708 				    filename, linenum);
709 			options->deny_users[options->num_deny_users++] =
710 			    xstrdup(arg);
711 		}
712 		break;
713 
714 	case sAllowGroups:
715 		while ((arg = strdelim(&cp)) && *arg != '\0') {
716 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
717 				fatal("%s line %d: too many allow groups.",
718 				    filename, linenum);
719 			options->allow_groups[options->num_allow_groups++] =
720 			    xstrdup(arg);
721 		}
722 		break;
723 
724 	case sDenyGroups:
725 		while ((arg = strdelim(&cp)) && *arg != '\0') {
726 			if (options->num_deny_groups >= MAX_DENY_GROUPS)
727 				fatal("%s line %d: too many deny groups.",
728 				    filename, linenum);
729 			options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
730 		}
731 		break;
732 
733 	case sCiphers:
734 		arg = strdelim(&cp);
735 		if (!arg || *arg == '\0')
736 			fatal("%s line %d: Missing argument.", filename, linenum);
737 		if (!ciphers_valid(arg))
738 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
739 			    filename, linenum, arg ? arg : "<NONE>");
740 		if (options->ciphers == NULL)
741 			options->ciphers = xstrdup(arg);
742 		break;
743 
744 	case sMacs:
745 		arg = strdelim(&cp);
746 		if (!arg || *arg == '\0')
747 			fatal("%s line %d: Missing argument.", filename, linenum);
748 		if (!mac_valid(arg))
749 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
750 			    filename, linenum, arg ? arg : "<NONE>");
751 		if (options->macs == NULL)
752 			options->macs = xstrdup(arg);
753 		break;
754 
755 	case sProtocol:
756 		intptr = &options->protocol;
757 		arg = strdelim(&cp);
758 		if (!arg || *arg == '\0')
759 			fatal("%s line %d: Missing argument.", filename, linenum);
760 		value = proto_spec(arg);
761 		if (value == SSH_PROTO_UNKNOWN)
762 			fatal("%s line %d: Bad protocol spec '%s'.",
763 			    filename, linenum, arg ? arg : "<NONE>");
764 		if (*intptr == SSH_PROTO_UNKNOWN)
765 			*intptr = value;
766 		break;
767 
768 	case sSubsystem:
769 		if (options->num_subsystems >= MAX_SUBSYSTEMS) {
770 			fatal("%s line %d: too many subsystems defined.",
771 			    filename, linenum);
772 		}
773 		arg = strdelim(&cp);
774 		if (!arg || *arg == '\0')
775 			fatal("%s line %d: Missing subsystem name.",
776 			    filename, linenum);
777 		for (i = 0; i < options->num_subsystems; i++)
778 			if (strcmp(arg, options->subsystem_name[i]) == 0)
779 				fatal("%s line %d: Subsystem '%s' already defined.",
780 				    filename, linenum, arg);
781 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
782 		arg = strdelim(&cp);
783 		if (!arg || *arg == '\0')
784 			fatal("%s line %d: Missing subsystem command.",
785 			    filename, linenum);
786 		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
787 		options->num_subsystems++;
788 		break;
789 
790 	case sMaxStartups:
791 		arg = strdelim(&cp);
792 		if (!arg || *arg == '\0')
793 			fatal("%s line %d: Missing MaxStartups spec.",
794 			    filename, linenum);
795 		if ((n = sscanf(arg, "%d:%d:%d",
796 		    &options->max_startups_begin,
797 		    &options->max_startups_rate,
798 		    &options->max_startups)) == 3) {
799 			if (options->max_startups_begin >
800 			    options->max_startups ||
801 			    options->max_startups_rate > 100 ||
802 			    options->max_startups_rate < 1)
803 				fatal("%s line %d: Illegal MaxStartups spec.",
804 				    filename, linenum);
805 		} else if (n != 1)
806 			fatal("%s line %d: Illegal MaxStartups spec.",
807 			    filename, linenum);
808 		else
809 			options->max_startups = options->max_startups_begin;
810 		break;
811 
812 	case sBanner:
813 		charptr = &options->banner;
814 		goto parse_filename;
815 	/*
816 	 * These options can contain %X options expanded at
817 	 * connect time, so that you can specify paths like:
818 	 *
819 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
820 	 */
821 	case sAuthorizedKeysFile:
822 	case sAuthorizedKeysFile2:
823 		charptr = (opcode == sAuthorizedKeysFile ) ?
824 		    &options->authorized_keys_file :
825 		    &options->authorized_keys_file2;
826 		goto parse_filename;
827 
828 	case sClientAliveInterval:
829 		intptr = &options->client_alive_interval;
830 		goto parse_time;
831 
832 	case sClientAliveCountMax:
833 		intptr = &options->client_alive_count_max;
834 		goto parse_int;
835 
836 	case sDeprecated:
837 		logit("%s line %d: Deprecated option %s",
838 		    filename, linenum, arg);
839 		while (arg)
840 		    arg = strdelim(&cp);
841 		break;
842 
843 	case sUnsupported:
844 		logit("%s line %d: Unsupported option %s",
845 		    filename, linenum, arg);
846 		while (arg)
847 		    arg = strdelim(&cp);
848 		break;
849 
850 	default:
851 		fatal("%s line %d: Missing handler for opcode %s (%d)",
852 		    filename, linenum, arg, opcode);
853 	}
854 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
855 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
856 		    filename, linenum, arg);
857 	return 0;
858 }
859 
860 /* Reads the server configuration file. */
861 
862 void
863 read_server_config(ServerOptions *options, const char *filename)
864 {
865 	int linenum, bad_options = 0;
866 	char line[1024];
867 	FILE *f;
868 
869 	debug2("read_server_config: filename %s", filename);
870 	f = fopen(filename, "r");
871 	if (!f) {
872 		perror(filename);
873 		exit(1);
874 	}
875 	linenum = 0;
876 	while (fgets(line, sizeof(line), f)) {
877 		/* Update line number counter. */
878 		linenum++;
879 		if (process_server_config_line(options, line, filename, linenum) != 0)
880 			bad_options++;
881 	}
882 	fclose(f);
883 	if (bad_options > 0)
884 		fatal("%s: terminating, %d bad configuration options",
885 		    filename, bad_options);
886 }
887