xref: /freebsd/crypto/openssh/servconf.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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.51 2000/09/07 20:27:53 deraadt Exp $");
14 RCSID("$FreeBSD$");
15 
16 #include "ssh.h"
17 #include "servconf.h"
18 #include "xmalloc.h"
19 #include "compat.h"
20 
21 /* add listen address */
22 void add_listen_addr(ServerOptions *options, char *addr);
23 
24 /* Initializes the server options to their default values. */
25 
26 void
27 initialize_server_options(ServerOptions *options)
28 {
29 	memset(options, 0, sizeof(*options));
30 	options->num_ports = 0;
31 	options->ports_from_cmdline = 0;
32 	options->listen_addrs = NULL;
33 	options->host_key_file = NULL;
34 	options->host_dsa_key_file = NULL;
35 	options->pid_file = NULL;
36 	options->server_key_bits = -1;
37 	options->login_grace_time = -1;
38 	options->key_regeneration_time = -1;
39 	options->permit_root_login = -1;
40 	options->ignore_rhosts = -1;
41 	options->ignore_user_known_hosts = -1;
42 	options->print_motd = -1;
43 	options->check_mail = -1;
44 	options->x11_forwarding = -1;
45 	options->x11_display_offset = -1;
46 	options->xauth_location = NULL;
47 	options->strict_modes = -1;
48 	options->keepalives = -1;
49 	options->log_facility = (SyslogFacility) - 1;
50 	options->log_level = (LogLevel) - 1;
51 	options->rhosts_authentication = -1;
52 	options->rhosts_rsa_authentication = -1;
53 	options->rsa_authentication = -1;
54 	options->dsa_authentication = -1;
55 #ifdef KRB4
56 	options->krb4_authentication = -1;
57 	options->krb4_or_local_passwd = -1;
58 	options->krb4_ticket_cleanup = -1;
59 #endif
60 #ifdef KRB5
61 	options->krb5_authentication = -1;
62 	options->krb5_tgt_passing = -1;
63 #endif /* KRB5 */
64 #ifdef AFS
65 	options->krb4_tgt_passing = -1;
66 	options->afs_token_passing = -1;
67 #endif
68 	options->password_authentication = -1;
69 #ifdef SKEY
70 	options->skey_authentication = -1;
71 #endif
72 	options->permit_empty_passwd = -1;
73 	options->use_login = -1;
74 	options->num_allow_users = 0;
75 	options->num_deny_users = 0;
76 	options->num_allow_groups = 0;
77 	options->num_deny_groups = 0;
78 	options->ciphers = NULL;
79 	options->protocol = SSH_PROTO_UNKNOWN;
80 	options->gateway_ports = -1;
81 	options->connections_per_period = 0;
82 	options->connections_period = 0;
83 	options->num_subsystems = 0;
84 	options->max_startups_begin = -1;
85 	options->max_startups_rate = -1;
86 	options->max_startups = -1;
87 }
88 
89 void
90 fill_default_server_options(ServerOptions *options)
91 {
92 	if (options->num_ports == 0)
93 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
94 	if (options->listen_addrs == NULL)
95 		add_listen_addr(options, NULL);
96 	if (options->host_key_file == NULL)
97 		options->host_key_file = HOST_KEY_FILE;
98 	if (options->host_dsa_key_file == NULL)
99 		options->host_dsa_key_file = HOST_DSA_KEY_FILE;
100 	if (options->pid_file == NULL)
101 		options->pid_file = SSH_DAEMON_PID_FILE;
102 	if (options->server_key_bits == -1)
103 		options->server_key_bits = 768;
104 	if (options->login_grace_time == -1)
105 		options->login_grace_time = 120;
106 	if (options->key_regeneration_time == -1)
107 		options->key_regeneration_time = 3600;
108 	if (options->permit_root_login == -1)
109 		options->permit_root_login = 0;			/* no */
110 	if (options->ignore_rhosts == -1)
111 		options->ignore_rhosts = 1;
112 	if (options->ignore_user_known_hosts == -1)
113 		options->ignore_user_known_hosts = 0;
114 	if (options->check_mail == -1)
115 		options->check_mail = 1;
116 	if (options->print_motd == -1)
117 		options->print_motd = 1;
118 	if (options->x11_forwarding == -1)
119 		options->x11_forwarding = 1;
120 	if (options->x11_display_offset == -1)
121 		options->x11_display_offset = 10;
122 #ifdef XAUTH_PATH
123 	if (options->xauth_location == NULL)
124 		options->xauth_location = XAUTH_PATH;
125 #endif /* XAUTH_PATH */
126 	if (options->strict_modes == -1)
127 		options->strict_modes = 1;
128 	if (options->keepalives == -1)
129 		options->keepalives = 1;
130 	if (options->log_facility == (SyslogFacility) (-1))
131 		options->log_facility = SYSLOG_FACILITY_AUTH;
132 	if (options->log_level == (LogLevel) (-1))
133 		options->log_level = SYSLOG_LEVEL_INFO;
134 	if (options->rhosts_authentication == -1)
135 		options->rhosts_authentication = 0;
136 	if (options->rhosts_rsa_authentication == -1)
137 		options->rhosts_rsa_authentication = 0;
138 	if (options->rsa_authentication == -1)
139 		options->rsa_authentication = 1;
140 	if (options->dsa_authentication == -1)
141 		options->dsa_authentication = 1;
142 #ifdef KRB4
143 	if (options->krb4_authentication == -1)
144 		options->krb4_authentication = (access(KEYFILE, R_OK) == 0);
145 	if (options->krb4_or_local_passwd == -1)
146 		options->krb4_or_local_passwd = 1;
147 	if (options->krb4_ticket_cleanup == -1)
148 		options->krb4_ticket_cleanup = 1;
149 #endif /* KRB4 */
150 #ifdef KRB5
151 	if (options->krb5_authentication == -1)
152 	  	options->krb5_authentication = 1;
153 	if (options->krb5_tgt_passing == -1)
154 	  	options->krb5_tgt_passing = 1;
155 #endif /* KRB5 */
156 #ifdef AFS
157 	if (options->krb4_tgt_passing == -1)
158 		options->krb4_tgt_passing = 0;
159 	if (options->afs_token_passing == -1)
160 		options->afs_token_passing = k_hasafs();
161 #endif /* AFS */
162 	if (options->password_authentication == -1)
163 		options->password_authentication = 1;
164 #ifdef SKEY
165 	if (options->skey_authentication == -1)
166 		options->skey_authentication = 1;
167 #endif
168 	if (options->permit_empty_passwd == -1)
169 		options->permit_empty_passwd = 0;
170 	if (options->use_login == -1)
171 		options->use_login = 0;
172 	if (options->protocol == SSH_PROTO_UNKNOWN)
173 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
174 	if (options->gateway_ports == -1)
175 		options->gateway_ports = 0;
176 	if (options->max_startups == -1)
177 		options->max_startups = 10;
178 	if (options->max_startups_rate == -1)
179 		options->max_startups_rate = 100;		/* 100% */
180 	if (options->max_startups_begin == -1)
181 		options->max_startups_begin = options->max_startups;
182 }
183 
184 /* Keyword tokens. */
185 typedef enum {
186 	sBadOption,		/* == unknown option */
187 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
188 	sPermitRootLogin, sLogFacility, sLogLevel,
189 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
190 #ifdef KRB4
191 	sKrb4Authentication, sKrb4OrLocalPasswd, sKrb4TicketCleanup,
192 #endif
193 #ifdef KRB5
194 	sKrb5Authentication, sKrb5TgtPassing,
195 #endif /* KRB5 */
196 #ifdef AFS
197 	sKrb4TgtPassing, sAFSTokenPassing,
198 #endif
199 #ifdef SKEY
200 	sSkeyAuthentication,
201 #endif
202 	sPasswordAuthentication, sListenAddress,
203 	sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
204 	sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
205 	sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
206 	sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
207 	sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
208 	sSubsystem, sMaxStartups
209 } ServerOpCodes;
210 
211 /* Textual representation of the tokens. */
212 static struct {
213 	const char *name;
214 	ServerOpCodes opcode;
215 } keywords[] = {
216 	{ "port", sPort },
217 	{ "hostkey", sHostKeyFile },
218 	{ "hostdsakey", sHostDSAKeyFile },
219  	{ "pidfile", sPidFile },
220 	{ "serverkeybits", sServerKeyBits },
221 	{ "logingracetime", sLoginGraceTime },
222 	{ "keyregenerationinterval", sKeyRegenerationTime },
223 	{ "permitrootlogin", sPermitRootLogin },
224 	{ "syslogfacility", sLogFacility },
225 	{ "loglevel", sLogLevel },
226 	{ "rhostsauthentication", sRhostsAuthentication },
227 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
228 	{ "rsaauthentication", sRSAAuthentication },
229 	{ "dsaauthentication", sDSAAuthentication },
230 #ifdef KRB4
231 	{ "kerberos4authentication", sKrb4Authentication },
232 	{ "kerberos4orlocalpasswd", sKrb4OrLocalPasswd },
233 	{ "kerberos4ticketcleanup", sKrb4TicketCleanup },
234 #endif
235 #ifdef KRB5
236 	{ "kerberos5authentication", sKrb5Authentication },
237 	{ "kerberos5tgtpassing", sKrb5TgtPassing },
238 #endif /* KRB5 */
239 #ifdef AFS
240 	{ "kerberos4tgtpassing", sKrb4TgtPassing },
241 	{ "afstokenpassing", sAFSTokenPassing },
242 #endif
243 	{ "passwordauthentication", sPasswordAuthentication },
244 #ifdef SKEY
245 	{ "skeyauthentication", sSkeyAuthentication },
246 #endif
247 	{ "checkmail", sCheckMail },
248 	{ "listenaddress", sListenAddress },
249 	{ "printmotd", sPrintMotd },
250 	{ "ignorerhosts", sIgnoreRhosts },
251 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
252 	{ "x11forwarding", sX11Forwarding },
253 	{ "x11displayoffset", sX11DisplayOffset },
254 	{ "xauthlocation", sXAuthLocation },
255 	{ "strictmodes", sStrictModes },
256 	{ "permitemptypasswords", sEmptyPasswd },
257 	{ "uselogin", sUseLogin },
258 	{ "randomseed", sRandomSeedFile },
259 	{ "keepalive", sKeepAlives },
260 	{ "allowusers", sAllowUsers },
261 	{ "denyusers", sDenyUsers },
262 	{ "allowgroups", sAllowGroups },
263 	{ "denygroups", sDenyGroups },
264 	{ "ciphers", sCiphers },
265 	{ "protocol", sProtocol },
266 	{ "gatewayports", sGatewayPorts },
267 	{ "connectionsperperiod", sConnectionsPerPeriod },
268 	{ "subsystem", sSubsystem },
269 	{ "maxstartups", sMaxStartups },
270 	{ NULL, 0 }
271 };
272 
273 /*
274  * Returns the number of the token pointed to by cp of length len. Never
275  * returns if the token is not known.
276  */
277 
278 static ServerOpCodes
279 parse_token(const char *cp, const char *filename,
280 	    int linenum)
281 {
282 	unsigned int i;
283 
284 	for (i = 0; keywords[i].name; i++)
285 		if (strcasecmp(cp, keywords[i].name) == 0)
286 			return keywords[i].opcode;
287 
288 	fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
289 		filename, linenum, cp);
290 	return sBadOption;
291 }
292 
293 /*
294  * add listen address
295  */
296 void
297 add_listen_addr(ServerOptions *options, char *addr)
298 {
299 	extern int IPv4or6;
300 	struct addrinfo hints, *ai, *aitop;
301 	char strport[NI_MAXSERV];
302 	int gaierr;
303 	int i;
304 
305 	if (options->num_ports == 0)
306 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
307 	for (i = 0; i < options->num_ports; i++) {
308 		memset(&hints, 0, sizeof(hints));
309 		hints.ai_family = IPv4or6;
310 		hints.ai_socktype = SOCK_STREAM;
311 		hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
312 		snprintf(strport, sizeof strport, "%d", options->ports[i]);
313 		if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
314 			fatal("bad addr or host: %s (%s)\n",
315 			    addr ? addr : "<NULL>",
316 			    gai_strerror(gaierr));
317 		for (ai = aitop; ai->ai_next; ai = ai->ai_next)
318 			;
319 		ai->ai_next = options->listen_addrs;
320 		options->listen_addrs = aitop;
321 	}
322 }
323 
324 /* Reads the server configuration file. */
325 
326 void
327 read_server_config(ServerOptions *options, const char *filename)
328 {
329 	FILE *f;
330 	char line[1024];
331 	char *cp, **charptr, *arg;
332 	int linenum, *intptr, value;
333 	int bad_options = 0;
334 	ServerOpCodes opcode;
335 	int i;
336 
337 	f = fopen(filename, "r");
338 	if (!f) {
339 		perror(filename);
340 		exit(1);
341 	}
342 	linenum = 0;
343 	while (fgets(line, sizeof(line), f)) {
344 		linenum++;
345 		cp = line;
346 		arg = strdelim(&cp);
347 		/* Ignore leading whitespace */
348 		if (*arg == '\0')
349 			arg = strdelim(&cp);
350 		if (!*arg || *arg == '#')
351 			continue;
352 		opcode = parse_token(arg, filename, linenum);
353 		switch (opcode) {
354 		case sBadOption:
355 			bad_options++;
356 			continue;
357 		case sPort:
358 			/* ignore ports from configfile if cmdline specifies ports */
359 			if (options->ports_from_cmdline)
360 				continue;
361 			if (options->listen_addrs != NULL)
362 				fatal("%s line %d: ports must be specified before "
363 				    "ListenAdress.\n", filename, linenum);
364 			if (options->num_ports >= MAX_PORTS)
365 				fatal("%s line %d: too many ports.\n",
366 				    filename, linenum);
367 			arg = strdelim(&cp);
368 			if (!arg || *arg == '\0')
369 				fatal("%s line %d: missing port number.\n",
370 				    filename, linenum);
371 			options->ports[options->num_ports++] = atoi(arg);
372 			break;
373 
374 		case sServerKeyBits:
375 			intptr = &options->server_key_bits;
376 parse_int:
377 			arg = strdelim(&cp);
378 			if (!arg || *arg == '\0') {
379 				fprintf(stderr, "%s line %d: missing integer value.\n",
380 					filename, linenum);
381 				exit(1);
382 			}
383 			value = atoi(arg);
384 			if (value == 0) {
385 				fprintf(stderr, "%s line %d: invalid integer value.\n",
386 					filename, linenum);
387 				exit(1);
388 			}
389 			if (*intptr == -1)
390 				*intptr = value;
391 			break;
392 
393 		case sLoginGraceTime:
394 			intptr = &options->login_grace_time;
395 			goto parse_int;
396 
397 		case sKeyRegenerationTime:
398 			intptr = &options->key_regeneration_time;
399 			goto parse_int;
400 
401 		case sListenAddress:
402 			arg = strdelim(&cp);
403 			if (!arg || *arg == '\0')
404 				fatal("%s line %d: missing inet addr.\n",
405 				    filename, linenum);
406 			add_listen_addr(options, arg);
407 			break;
408 
409 		case sHostKeyFile:
410 		case sHostDSAKeyFile:
411 			charptr = (opcode == sHostKeyFile ) ?
412 			    &options->host_key_file : &options->host_dsa_key_file;
413 parse_filename:
414 			arg = strdelim(&cp);
415 			if (!arg || *arg == '\0') {
416 				fprintf(stderr, "%s line %d: missing file name.\n",
417 				    filename, linenum);
418 				exit(1);
419 			}
420 			if (*charptr == NULL)
421 				*charptr = tilde_expand_filename(arg, getuid());
422 			break;
423 
424 		case sPidFile:
425 			charptr = &options->pid_file;
426 			goto parse_filename;
427 
428 		case sRandomSeedFile:
429 			fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
430 				filename, linenum);
431 			arg = strdelim(&cp);
432 			break;
433 
434 		case sPermitRootLogin:
435 			intptr = &options->permit_root_login;
436 			arg = strdelim(&cp);
437 			if (!arg || *arg == '\0') {
438 				fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
439 					filename, linenum);
440 				exit(1);
441 			}
442 			if (strcmp(arg, "without-password") == 0)
443 				value = 2;
444 			else if (strcmp(arg, "yes") == 0)
445 				value = 1;
446 			else if (strcmp(arg, "no") == 0)
447 				value = 0;
448 			else {
449 				fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
450 					filename, linenum, arg);
451 				exit(1);
452 			}
453 			if (*intptr == -1)
454 				*intptr = value;
455 			break;
456 
457 		case sIgnoreRhosts:
458 			intptr = &options->ignore_rhosts;
459 parse_flag:
460 			arg = strdelim(&cp);
461 			if (!arg || *arg == '\0') {
462 				fprintf(stderr, "%s line %d: missing yes/no argument.\n",
463 					filename, linenum);
464 				exit(1);
465 			}
466 			if (strcmp(arg, "yes") == 0)
467 				value = 1;
468 			else if (strcmp(arg, "no") == 0)
469 				value = 0;
470 			else {
471 				fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
472 					filename, linenum, arg);
473 				exit(1);
474 			}
475 			if (*intptr == -1)
476 				*intptr = value;
477 			break;
478 
479 		case sIgnoreUserKnownHosts:
480 			intptr = &options->ignore_user_known_hosts;
481 			goto parse_flag;
482 
483 		case sRhostsAuthentication:
484 			intptr = &options->rhosts_authentication;
485 			goto parse_flag;
486 
487 		case sRhostsRSAAuthentication:
488 			intptr = &options->rhosts_rsa_authentication;
489 			goto parse_flag;
490 
491 		case sRSAAuthentication:
492 			intptr = &options->rsa_authentication;
493 			goto parse_flag;
494 
495 		case sDSAAuthentication:
496 			intptr = &options->dsa_authentication;
497 			goto parse_flag;
498 
499 #ifdef KRB4
500 		case sKrb4Authentication:
501 			intptr = &options->krb4_authentication;
502 			goto parse_flag;
503 
504 		case sKrb4OrLocalPasswd:
505 			intptr = &options->krb4_or_local_passwd;
506 			goto parse_flag;
507 
508 		case sKrb4TicketCleanup:
509 			intptr = &options->krb4_ticket_cleanup;
510 			goto parse_flag;
511 #endif
512 
513 #ifdef KRB5
514 		case sKrb5Authentication:
515 			intptr = &options->krb5_authentication;
516 			goto parse_flag;
517 
518 		case sKrb5TgtPassing:
519 			intptr = &options->krb5_tgt_passing;
520 			goto parse_flag;
521 #endif /* KRB5 */
522 
523 #ifdef AFS
524 		case sKrb4TgtPassing:
525 			intptr = &options->krb4_tgt_passing;
526 			goto parse_flag;
527 
528 		case sAFSTokenPassing:
529 			intptr = &options->afs_token_passing;
530 			goto parse_flag;
531 #endif
532 
533 		case sPasswordAuthentication:
534 			intptr = &options->password_authentication;
535 			goto parse_flag;
536 
537 		case sCheckMail:
538 			intptr = &options->check_mail;
539 			goto parse_flag;
540 
541 #ifdef SKEY
542 		case sSkeyAuthentication:
543 			intptr = &options->skey_authentication;
544 			goto parse_flag;
545 #endif
546 
547 		case sPrintMotd:
548 			intptr = &options->print_motd;
549 			goto parse_flag;
550 
551 		case sX11Forwarding:
552 			intptr = &options->x11_forwarding;
553 			goto parse_flag;
554 
555 		case sX11DisplayOffset:
556 			intptr = &options->x11_display_offset;
557 			goto parse_int;
558 
559 		case sXAuthLocation:
560 			charptr = &options->xauth_location;
561 			goto parse_filename;
562 
563 		case sStrictModes:
564 			intptr = &options->strict_modes;
565 			goto parse_flag;
566 
567 		case sKeepAlives:
568 			intptr = &options->keepalives;
569 			goto parse_flag;
570 
571 		case sEmptyPasswd:
572 			intptr = &options->permit_empty_passwd;
573 			goto parse_flag;
574 
575 		case sUseLogin:
576 			intptr = &options->use_login;
577 			goto parse_flag;
578 
579 		case sGatewayPorts:
580 			intptr = &options->gateway_ports;
581 			goto parse_flag;
582 
583 		case sLogFacility:
584 			intptr = (int *) &options->log_facility;
585 			arg = strdelim(&cp);
586 			value = log_facility_number(arg);
587 			if (value == (SyslogFacility) - 1)
588 				fatal("%.200s line %d: unsupported log facility '%s'\n",
589 				    filename, linenum, arg ? arg : "<NONE>");
590 			if (*intptr == -1)
591 				*intptr = (SyslogFacility) value;
592 			break;
593 
594 		case sLogLevel:
595 			intptr = (int *) &options->log_level;
596 			arg = strdelim(&cp);
597 			value = log_level_number(arg);
598 			if (value == (LogLevel) - 1)
599 				fatal("%.200s line %d: unsupported log level '%s'\n",
600 				    filename, linenum, arg ? arg : "<NONE>");
601 			if (*intptr == -1)
602 				*intptr = (LogLevel) value;
603 			break;
604 
605 		case sAllowUsers:
606 			while ((arg = strdelim(&cp)) && *arg != '\0') {
607 				if (options->num_allow_users >= MAX_ALLOW_USERS)
608 					fatal("%.200s line %d: too many allow users.\n",
609 					    filename, linenum);
610 				options->allow_users[options->num_allow_users++] = xstrdup(arg);
611 			}
612 			break;
613 
614 		case sDenyUsers:
615 			while ((arg = strdelim(&cp)) && *arg != '\0') {
616 				if (options->num_deny_users >= MAX_DENY_USERS)
617 					fatal("%.200s line %d: too many deny users.\n",
618 					    filename, linenum);
619 				options->deny_users[options->num_deny_users++] = xstrdup(arg);
620 			}
621 			break;
622 
623 		case sAllowGroups:
624 			while ((arg = strdelim(&cp)) && *arg != '\0') {
625 				if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
626 					fatal("%.200s line %d: too many allow groups.\n",
627 					    filename, linenum);
628 				options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
629 			}
630 			break;
631 
632 		case sDenyGroups:
633 			while ((arg = strdelim(&cp)) && *arg != '\0') {
634 				if (options->num_deny_groups >= MAX_DENY_GROUPS)
635 					fatal("%.200s line %d: too many deny groups.\n",
636 					    filename, linenum);
637 				options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
638 			}
639 			break;
640 
641 		case sCiphers:
642 			arg = strdelim(&cp);
643 			if (!arg || *arg == '\0')
644 				fatal("%s line %d: Missing argument.", filename, linenum);
645 			if (!ciphers_valid(arg))
646 				fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
647 				    filename, linenum, arg ? arg : "<NONE>");
648 			if (options->ciphers == NULL)
649 				options->ciphers = xstrdup(arg);
650 			break;
651 
652 		case sProtocol:
653 			intptr = &options->protocol;
654 			arg = strdelim(&cp);
655 			if (!arg || *arg == '\0')
656 				fatal("%s line %d: Missing argument.", filename, linenum);
657 			value = proto_spec(arg);
658 			if (value == SSH_PROTO_UNKNOWN)
659 				fatal("%s line %d: Bad protocol spec '%s'.",
660 				      filename, linenum, arg ? arg : "<NONE>");
661 			if (*intptr == SSH_PROTO_UNKNOWN)
662 				*intptr = value;
663 			break;
664 
665 		case sConnectionsPerPeriod:
666 			arg = strdelim(&cp);
667 			if (cp == NULL)
668 				fatal("%.200s line %d: missing (>= 0) number argument.\n",
669 					filename, linenum);
670 			if (sscanf(arg, "%u/%u", &options->connections_per_period,
671 			    &options->connections_period) != 2)
672 				fatal("%.200s line %d: invalid numerical argument(s).\n",
673 				    filename, linenum);
674 			if (options->connections_per_period != 0 &&
675 			    options->connections_period == 0)
676 				fatal("%.200s line %d: invalid connections period.\n",
677 				    filename, linenum);
678 			break;
679 
680 		case sSubsystem:
681 			if(options->num_subsystems >= MAX_SUBSYSTEMS) {
682 				fatal("%s line %d: too many subsystems defined.",
683 				      filename, linenum);
684 			}
685 			arg = strdelim(&cp);
686 			if (!arg || *arg == '\0')
687 				fatal("%s line %d: Missing subsystem name.",
688 				      filename, linenum);
689 			for (i = 0; i < options->num_subsystems; i++)
690 				if(strcmp(arg, options->subsystem_name[i]) == 0)
691 					fatal("%s line %d: Subsystem '%s' already defined.",
692 					      filename, linenum, arg);
693 			options->subsystem_name[options->num_subsystems] = xstrdup(arg);
694 			arg = strdelim(&cp);
695 			if (!arg || *arg == '\0')
696 				fatal("%s line %d: Missing subsystem command.",
697 				      filename, linenum);
698 			options->subsystem_command[options->num_subsystems] = xstrdup(arg);
699 			options->num_subsystems++;
700 			break;
701 
702 		case sMaxStartups:
703 			arg = strdelim(&cp);
704 			if (!arg || *arg == '\0')
705 				fatal("%s line %d: Missing MaxStartups spec.",
706 				      filename, linenum);
707 			if (sscanf(arg, "%d:%d:%d",
708 			    &options->max_startups_begin,
709 			    &options->max_startups_rate,
710 			    &options->max_startups) == 3) {
711 				if (options->max_startups_begin >
712 				    options->max_startups ||
713 				    options->max_startups_rate > 100 ||
714 				    options->max_startups_rate < 1)
715 				fatal("%s line %d: Illegal MaxStartups spec.",
716 				      filename, linenum);
717 				break;
718 			}
719 			intptr = &options->max_startups;
720 			goto parse_int;
721 
722 		default:
723 			fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
724 				filename, linenum,arg, opcode);
725 		}
726 		if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
727 			fprintf(stderr,
728 				"%s line %d: garbage at end of line; \"%.200s\".\n",
729 				filename, linenum, arg);
730 			exit(1);
731 		}
732 	}
733 	fclose(f);
734 	if (bad_options > 0) {
735 		fatal("%.200s: terminating, %d bad configuration options\n",
736 			filename, bad_options);
737 	}
738 }
739