xref: /freebsd/crypto/openssh/servconf.c (revision 933ca70f8f888b7fc1b06213198ba15ca346aeca)
1511b41d2SMark Murray /*
2511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3511b41d2SMark Murray  *                    All rights reserved
4511b41d2SMark Murray  *
5c2d3a559SKris Kennaway  * As far as I am concerned, the code I have written for this software
6c2d3a559SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
7c2d3a559SKris Kennaway  * software must be clearly marked as such, and if the derived work is
8c2d3a559SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
9c2d3a559SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
10511b41d2SMark Murray  */
11511b41d2SMark Murray 
12511b41d2SMark Murray #include "includes.h"
1309958426SBrian Feldman RCSID("$OpenBSD: servconf.c,v 1.53 2000/10/14 12:12:09 markus Exp $");
14c2d3a559SKris Kennaway RCSID("$FreeBSD$");
15511b41d2SMark Murray 
16511b41d2SMark Murray #include "ssh.h"
17511b41d2SMark Murray #include "servconf.h"
18511b41d2SMark Murray #include "xmalloc.h"
19e8aafc91SKris Kennaway #include "compat.h"
20511b41d2SMark Murray 
21511b41d2SMark Murray /* add listen address */
22511b41d2SMark Murray void add_listen_addr(ServerOptions *options, char *addr);
23511b41d2SMark Murray 
24511b41d2SMark Murray /* Initializes the server options to their default values. */
25511b41d2SMark Murray 
26511b41d2SMark Murray void
27511b41d2SMark Murray initialize_server_options(ServerOptions *options)
28511b41d2SMark Murray {
29511b41d2SMark Murray 	memset(options, 0, sizeof(*options));
30511b41d2SMark Murray 	options->num_ports = 0;
31511b41d2SMark Murray 	options->ports_from_cmdline = 0;
32511b41d2SMark Murray 	options->listen_addrs = NULL;
33511b41d2SMark Murray 	options->host_key_file = NULL;
34e8aafc91SKris Kennaway 	options->host_dsa_key_file = NULL;
35e8aafc91SKris Kennaway 	options->pid_file = NULL;
36511b41d2SMark Murray 	options->server_key_bits = -1;
37511b41d2SMark Murray 	options->login_grace_time = -1;
38511b41d2SMark Murray 	options->key_regeneration_time = -1;
39511b41d2SMark Murray 	options->permit_root_login = -1;
40511b41d2SMark Murray 	options->ignore_rhosts = -1;
41511b41d2SMark Murray 	options->ignore_user_known_hosts = -1;
42511b41d2SMark Murray 	options->print_motd = -1;
43511b41d2SMark Murray 	options->check_mail = -1;
44511b41d2SMark Murray 	options->x11_forwarding = -1;
45511b41d2SMark Murray 	options->x11_display_offset = -1;
46c2d3a559SKris Kennaway 	options->xauth_location = NULL;
47511b41d2SMark Murray 	options->strict_modes = -1;
48511b41d2SMark Murray 	options->keepalives = -1;
49511b41d2SMark Murray 	options->log_facility = (SyslogFacility) - 1;
50511b41d2SMark Murray 	options->log_level = (LogLevel) - 1;
51511b41d2SMark Murray 	options->rhosts_authentication = -1;
52511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
53511b41d2SMark Murray 	options->rsa_authentication = -1;
54e8aafc91SKris Kennaway 	options->dsa_authentication = -1;
55cb96ab36SAssar Westerlund #if defined(KRB4) || defined(KRB5)
56cb96ab36SAssar Westerlund 	options->kerberos_authentication = -1;
57cb96ab36SAssar Westerlund #endif
58511b41d2SMark Murray #ifdef KRB4
59fe5fd017SMark Murray 	options->krb4_or_local_passwd = -1;
60fe5fd017SMark Murray 	options->krb4_ticket_cleanup = -1;
61511b41d2SMark Murray #endif
62fe5fd017SMark Murray #ifdef KRB5
63fe5fd017SMark Murray 	options->krb5_tgt_passing = -1;
64fe5fd017SMark Murray #endif /* KRB5 */
65511b41d2SMark Murray #ifdef AFS
66fe5fd017SMark Murray 	options->krb4_tgt_passing = -1;
67511b41d2SMark Murray 	options->afs_token_passing = -1;
68511b41d2SMark Murray #endif
69511b41d2SMark Murray 	options->password_authentication = -1;
7009958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
71511b41d2SMark Murray #ifdef SKEY
72511b41d2SMark Murray 	options->skey_authentication = -1;
73511b41d2SMark Murray #endif
74511b41d2SMark Murray 	options->permit_empty_passwd = -1;
75511b41d2SMark Murray 	options->use_login = -1;
7609958426SBrian Feldman 	options->allow_tcp_forwarding = -1;
77511b41d2SMark Murray 	options->num_allow_users = 0;
78511b41d2SMark Murray 	options->num_deny_users = 0;
79511b41d2SMark Murray 	options->num_allow_groups = 0;
80511b41d2SMark Murray 	options->num_deny_groups = 0;
81e8aafc91SKris Kennaway 	options->ciphers = NULL;
82e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
83e8aafc91SKris Kennaway 	options->gateway_ports = -1;
8442f71286SMark Murray 	options->connections_per_period = 0;
8542f71286SMark Murray 	options->connections_period = 0;
86c2d3a559SKris Kennaway 	options->num_subsystems = 0;
87c2d3a559SKris Kennaway 	options->max_startups_begin = -1;
88c2d3a559SKris Kennaway 	options->max_startups_rate = -1;
89c2d3a559SKris Kennaway 	options->max_startups = -1;
90511b41d2SMark Murray }
91511b41d2SMark Murray 
92511b41d2SMark Murray void
93511b41d2SMark Murray fill_default_server_options(ServerOptions *options)
94511b41d2SMark Murray {
95511b41d2SMark Murray 	if (options->num_ports == 0)
96511b41d2SMark Murray 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
97511b41d2SMark Murray 	if (options->listen_addrs == NULL)
98511b41d2SMark Murray 		add_listen_addr(options, NULL);
99511b41d2SMark Murray 	if (options->host_key_file == NULL)
100511b41d2SMark Murray 		options->host_key_file = HOST_KEY_FILE;
101e8aafc91SKris Kennaway 	if (options->host_dsa_key_file == NULL)
102e8aafc91SKris Kennaway 		options->host_dsa_key_file = HOST_DSA_KEY_FILE;
103e8aafc91SKris Kennaway 	if (options->pid_file == NULL)
104e8aafc91SKris Kennaway 		options->pid_file = SSH_DAEMON_PID_FILE;
105511b41d2SMark Murray 	if (options->server_key_bits == -1)
106511b41d2SMark Murray 		options->server_key_bits = 768;
107511b41d2SMark Murray 	if (options->login_grace_time == -1)
108b87db7ceSKris Kennaway 		options->login_grace_time = 120;
109511b41d2SMark Murray 	if (options->key_regeneration_time == -1)
110511b41d2SMark Murray 		options->key_regeneration_time = 3600;
111511b41d2SMark Murray 	if (options->permit_root_login == -1)
112e213d985SPeter Wemm 		options->permit_root_login = 0;			/* no */
113511b41d2SMark Murray 	if (options->ignore_rhosts == -1)
114fe5fd017SMark Murray 		options->ignore_rhosts = 1;
115511b41d2SMark Murray 	if (options->ignore_user_known_hosts == -1)
116511b41d2SMark Murray 		options->ignore_user_known_hosts = 0;
117511b41d2SMark Murray 	if (options->check_mail == -1)
118365c420eSPeter Wemm 		options->check_mail = 1;
119511b41d2SMark Murray 	if (options->print_motd == -1)
120511b41d2SMark Murray 		options->print_motd = 1;
121511b41d2SMark Murray 	if (options->x11_forwarding == -1)
1221610cd7fSKris Kennaway 		options->x11_forwarding = 1;
123511b41d2SMark Murray 	if (options->x11_display_offset == -1)
124fe5fd017SMark Murray 		options->x11_display_offset = 10;
125c2d3a559SKris Kennaway #ifdef XAUTH_PATH
126c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
127c2d3a559SKris Kennaway 		options->xauth_location = XAUTH_PATH;
128c2d3a559SKris Kennaway #endif /* XAUTH_PATH */
129511b41d2SMark Murray 	if (options->strict_modes == -1)
130511b41d2SMark Murray 		options->strict_modes = 1;
131511b41d2SMark Murray 	if (options->keepalives == -1)
132511b41d2SMark Murray 		options->keepalives = 1;
133511b41d2SMark Murray 	if (options->log_facility == (SyslogFacility) (-1))
134511b41d2SMark Murray 		options->log_facility = SYSLOG_FACILITY_AUTH;
135511b41d2SMark Murray 	if (options->log_level == (LogLevel) (-1))
136511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
137511b41d2SMark Murray 	if (options->rhosts_authentication == -1)
138511b41d2SMark Murray 		options->rhosts_authentication = 0;
139511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
140fe5fd017SMark Murray 		options->rhosts_rsa_authentication = 0;
141511b41d2SMark Murray 	if (options->rsa_authentication == -1)
142511b41d2SMark Murray 		options->rsa_authentication = 1;
143e8aafc91SKris Kennaway 	if (options->dsa_authentication == -1)
144e8aafc91SKris Kennaway 		options->dsa_authentication = 1;
145cb96ab36SAssar Westerlund #if defined(KRB4) && defined(KRB5)
146cb96ab36SAssar Westerlund 	if (options->kerberos_authentication == -1)
147cb96ab36SAssar Westerlund 		options->kerberos_authentication =
148cb96ab36SAssar Westerlund 		  (access(KEYFILE, R_OK) == 0) || (access(krb5_defkeyname, R_OK) == 0);
149cb96ab36SAssar Westerlund #elif defined(KRB4)
150cb96ab36SAssar Westerlund 	if (options->kerberos_authentication == -1)
151cb96ab36SAssar Westerlund 		options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
152cb96ab36SAssar Westerlund #elif defined(KRB5)
153cb96ab36SAssar Westerlund 	if (options->kerberos_authentication == -1)
154cb96ab36SAssar Westerlund 	  	options->kerberos_authentication = (access(krb5_defkeyname, R_OK) == 0);
155cb96ab36SAssar Westerlund #endif
156511b41d2SMark Murray #ifdef KRB4
157fe5fd017SMark Murray 	if (options->krb4_or_local_passwd == -1)
158fe5fd017SMark Murray 		options->krb4_or_local_passwd = 1;
159fe5fd017SMark Murray 	if (options->krb4_ticket_cleanup == -1)
160fe5fd017SMark Murray 		options->krb4_ticket_cleanup = 1;
161511b41d2SMark Murray #endif /* KRB4 */
162fe5fd017SMark Murray #ifdef KRB5
163fe5fd017SMark Murray 	if (options->krb5_tgt_passing == -1)
164fe5fd017SMark Murray 	  	options->krb5_tgt_passing = 1;
165fe5fd017SMark Murray #endif /* KRB5 */
166511b41d2SMark Murray #ifdef AFS
167fe5fd017SMark Murray 	if (options->krb4_tgt_passing == -1)
168fe5fd017SMark Murray 		options->krb4_tgt_passing = 0;
169511b41d2SMark Murray 	if (options->afs_token_passing == -1)
170511b41d2SMark Murray 		options->afs_token_passing = k_hasafs();
171511b41d2SMark Murray #endif /* AFS */
172511b41d2SMark Murray 	if (options->password_authentication == -1)
173511b41d2SMark Murray 		options->password_authentication = 1;
17409958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
17509958426SBrian Feldman 		options->kbd_interactive_authentication = 0;
176511b41d2SMark Murray #ifdef SKEY
177511b41d2SMark Murray 	if (options->skey_authentication == -1)
178511b41d2SMark Murray 		options->skey_authentication = 1;
179511b41d2SMark Murray #endif
180511b41d2SMark Murray 	if (options->permit_empty_passwd == -1)
181fe5fd017SMark Murray 		options->permit_empty_passwd = 0;
182511b41d2SMark Murray 	if (options->use_login == -1)
183511b41d2SMark Murray 		options->use_login = 0;
18409958426SBrian Feldman 	if (options->allow_tcp_forwarding == -1)
18509958426SBrian Feldman 		options->allow_tcp_forwarding = 1;
186e8aafc91SKris Kennaway 	if (options->protocol == SSH_PROTO_UNKNOWN)
187e8aafc91SKris Kennaway 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
188e8aafc91SKris Kennaway 	if (options->gateway_ports == -1)
189e8aafc91SKris Kennaway 		options->gateway_ports = 0;
190c2d3a559SKris Kennaway 	if (options->max_startups == -1)
191c2d3a559SKris Kennaway 		options->max_startups = 10;
192c2d3a559SKris Kennaway 	if (options->max_startups_rate == -1)
193c2d3a559SKris Kennaway 		options->max_startups_rate = 100;		/* 100% */
194c2d3a559SKris Kennaway 	if (options->max_startups_begin == -1)
195c2d3a559SKris Kennaway 		options->max_startups_begin = options->max_startups;
196511b41d2SMark Murray }
197511b41d2SMark Murray 
198511b41d2SMark Murray /* Keyword tokens. */
199511b41d2SMark Murray typedef enum {
200511b41d2SMark Murray 	sBadOption,		/* == unknown option */
201511b41d2SMark Murray 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
202511b41d2SMark Murray 	sPermitRootLogin, sLogFacility, sLogLevel,
203511b41d2SMark Murray 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
204cb96ab36SAssar Westerlund #if defined(KRB4) || defined(KRB5)
205cb96ab36SAssar Westerlund 	sKerberosAuthentication,
206cb96ab36SAssar Westerlund #endif
207511b41d2SMark Murray #ifdef KRB4
208cb96ab36SAssar Westerlund 	sKrb4OrLocalPasswd, sKrb4TicketCleanup,
209511b41d2SMark Murray #endif
210fe5fd017SMark Murray #ifdef KRB5
211cb96ab36SAssar Westerlund 	sKrb5TgtPassing,
212fe5fd017SMark Murray #endif /* KRB5 */
213511b41d2SMark Murray #ifdef AFS
214fe5fd017SMark Murray 	sKrb4TgtPassing, sAFSTokenPassing,
215511b41d2SMark Murray #endif
216511b41d2SMark Murray #ifdef SKEY
217511b41d2SMark Murray 	sSkeyAuthentication,
218511b41d2SMark Murray #endif
21909958426SBrian Feldman 	sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
220511b41d2SMark Murray 	sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
221511b41d2SMark Murray 	sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
22209958426SBrian Feldman 	sUseLogin, sAllowTcpForwarding,
22309958426SBrian Feldman 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
224e8aafc91SKris Kennaway 	sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
225c2d3a559SKris Kennaway 	sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
226933ca70fSBrian Feldman 	sSubsystem, sMaxStartups, sVersionAddendum
227511b41d2SMark Murray } ServerOpCodes;
228511b41d2SMark Murray 
229511b41d2SMark Murray /* Textual representation of the tokens. */
230511b41d2SMark Murray static struct {
231511b41d2SMark Murray 	const char *name;
232511b41d2SMark Murray 	ServerOpCodes opcode;
233511b41d2SMark Murray } keywords[] = {
234511b41d2SMark Murray 	{ "port", sPort },
235511b41d2SMark Murray 	{ "hostkey", sHostKeyFile },
236e8aafc91SKris Kennaway 	{ "hostdsakey", sHostDSAKeyFile },
237e8aafc91SKris Kennaway  	{ "pidfile", sPidFile },
238511b41d2SMark Murray 	{ "serverkeybits", sServerKeyBits },
239511b41d2SMark Murray 	{ "logingracetime", sLoginGraceTime },
240511b41d2SMark Murray 	{ "keyregenerationinterval", sKeyRegenerationTime },
241511b41d2SMark Murray 	{ "permitrootlogin", sPermitRootLogin },
242511b41d2SMark Murray 	{ "syslogfacility", sLogFacility },
243511b41d2SMark Murray 	{ "loglevel", sLogLevel },
244511b41d2SMark Murray 	{ "rhostsauthentication", sRhostsAuthentication },
245511b41d2SMark Murray 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
246511b41d2SMark Murray 	{ "rsaauthentication", sRSAAuthentication },
247e8aafc91SKris Kennaway 	{ "dsaauthentication", sDSAAuthentication },
248cb96ab36SAssar Westerlund #if defined(KRB4) || defined(KRB5)
249cb96ab36SAssar Westerlund 	{ "kerberosauthentication", sKerberosAuthentication },
250cb96ab36SAssar Westerlund #endif
251511b41d2SMark Murray #ifdef KRB4
252fe5fd017SMark Murray 	{ "kerberos4orlocalpasswd", sKrb4OrLocalPasswd },
253fe5fd017SMark Murray 	{ "kerberos4ticketcleanup", sKrb4TicketCleanup },
254511b41d2SMark Murray #endif
255fe5fd017SMark Murray #ifdef KRB5
256fe5fd017SMark Murray 	{ "kerberos5tgtpassing", sKrb5TgtPassing },
257fe5fd017SMark Murray #endif /* KRB5 */
258511b41d2SMark Murray #ifdef AFS
259fe5fd017SMark Murray 	{ "kerberos4tgtpassing", sKrb4TgtPassing },
260511b41d2SMark Murray 	{ "afstokenpassing", sAFSTokenPassing },
261511b41d2SMark Murray #endif
262511b41d2SMark Murray 	{ "passwordauthentication", sPasswordAuthentication },
26309958426SBrian Feldman 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
264511b41d2SMark Murray #ifdef SKEY
265511b41d2SMark Murray 	{ "skeyauthentication", sSkeyAuthentication },
266511b41d2SMark Murray #endif
267511b41d2SMark Murray 	{ "checkmail", sCheckMail },
268511b41d2SMark Murray 	{ "listenaddress", sListenAddress },
269511b41d2SMark Murray 	{ "printmotd", sPrintMotd },
270511b41d2SMark Murray 	{ "ignorerhosts", sIgnoreRhosts },
271511b41d2SMark Murray 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
272511b41d2SMark Murray 	{ "x11forwarding", sX11Forwarding },
273511b41d2SMark Murray 	{ "x11displayoffset", sX11DisplayOffset },
274c2d3a559SKris Kennaway 	{ "xauthlocation", sXAuthLocation },
275511b41d2SMark Murray 	{ "strictmodes", sStrictModes },
276511b41d2SMark Murray 	{ "permitemptypasswords", sEmptyPasswd },
277511b41d2SMark Murray 	{ "uselogin", sUseLogin },
278511b41d2SMark Murray 	{ "randomseed", sRandomSeedFile },
279511b41d2SMark Murray 	{ "keepalive", sKeepAlives },
28009958426SBrian Feldman 	{ "allowtcpforwarding", sAllowTcpForwarding },
281511b41d2SMark Murray 	{ "allowusers", sAllowUsers },
282511b41d2SMark Murray 	{ "denyusers", sDenyUsers },
283511b41d2SMark Murray 	{ "allowgroups", sAllowGroups },
284511b41d2SMark Murray 	{ "denygroups", sDenyGroups },
285e8aafc91SKris Kennaway 	{ "ciphers", sCiphers },
286e8aafc91SKris Kennaway 	{ "protocol", sProtocol },
287e8aafc91SKris Kennaway 	{ "gatewayports", sGatewayPorts },
28842f71286SMark Murray 	{ "connectionsperperiod", sConnectionsPerPeriod },
289c2d3a559SKris Kennaway 	{ "subsystem", sSubsystem },
290c2d3a559SKris Kennaway 	{ "maxstartups", sMaxStartups },
291933ca70fSBrian Feldman 	{ "versionaddendum", sVersionAddendum },
292511b41d2SMark Murray 	{ NULL, 0 }
293511b41d2SMark Murray };
294511b41d2SMark Murray 
295511b41d2SMark Murray /*
296511b41d2SMark Murray  * Returns the number of the token pointed to by cp of length len. Never
297511b41d2SMark Murray  * returns if the token is not known.
298511b41d2SMark Murray  */
299511b41d2SMark Murray 
300511b41d2SMark Murray static ServerOpCodes
301511b41d2SMark Murray parse_token(const char *cp, const char *filename,
302511b41d2SMark Murray 	    int linenum)
303511b41d2SMark Murray {
304511b41d2SMark Murray 	unsigned int i;
305511b41d2SMark Murray 
306511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
307511b41d2SMark Murray 		if (strcasecmp(cp, keywords[i].name) == 0)
308511b41d2SMark Murray 			return keywords[i].opcode;
309511b41d2SMark Murray 
310511b41d2SMark Murray 	fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
311511b41d2SMark Murray 		filename, linenum, cp);
312511b41d2SMark Murray 	return sBadOption;
313511b41d2SMark Murray }
314511b41d2SMark Murray 
315511b41d2SMark Murray /*
316511b41d2SMark Murray  * add listen address
317511b41d2SMark Murray  */
318511b41d2SMark Murray void
319511b41d2SMark Murray add_listen_addr(ServerOptions *options, char *addr)
320511b41d2SMark Murray {
321511b41d2SMark Murray 	extern int IPv4or6;
322511b41d2SMark Murray 	struct addrinfo hints, *ai, *aitop;
323511b41d2SMark Murray 	char strport[NI_MAXSERV];
324511b41d2SMark Murray 	int gaierr;
325511b41d2SMark Murray 	int i;
326511b41d2SMark Murray 
327511b41d2SMark Murray 	if (options->num_ports == 0)
328511b41d2SMark Murray 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
329511b41d2SMark Murray 	for (i = 0; i < options->num_ports; i++) {
330511b41d2SMark Murray 		memset(&hints, 0, sizeof(hints));
331511b41d2SMark Murray 		hints.ai_family = IPv4or6;
332511b41d2SMark Murray 		hints.ai_socktype = SOCK_STREAM;
333511b41d2SMark Murray 		hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
334511b41d2SMark Murray 		snprintf(strport, sizeof strport, "%d", options->ports[i]);
335511b41d2SMark Murray 		if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
336511b41d2SMark Murray 			fatal("bad addr or host: %s (%s)\n",
337511b41d2SMark Murray 			    addr ? addr : "<NULL>",
338511b41d2SMark Murray 			    gai_strerror(gaierr));
339511b41d2SMark Murray 		for (ai = aitop; ai->ai_next; ai = ai->ai_next)
340511b41d2SMark Murray 			;
341511b41d2SMark Murray 		ai->ai_next = options->listen_addrs;
342511b41d2SMark Murray 		options->listen_addrs = aitop;
343511b41d2SMark Murray 	}
344511b41d2SMark Murray }
345511b41d2SMark Murray 
346511b41d2SMark Murray /* Reads the server configuration file. */
347511b41d2SMark Murray 
348511b41d2SMark Murray void
349511b41d2SMark Murray read_server_config(ServerOptions *options, const char *filename)
350511b41d2SMark Murray {
351511b41d2SMark Murray 	FILE *f;
352511b41d2SMark Murray 	char line[1024];
353c2d3a559SKris Kennaway 	char *cp, **charptr, *arg;
354511b41d2SMark Murray 	int linenum, *intptr, value;
355511b41d2SMark Murray 	int bad_options = 0;
356511b41d2SMark Murray 	ServerOpCodes opcode;
357c2d3a559SKris Kennaway 	int i;
358511b41d2SMark Murray 
359511b41d2SMark Murray 	f = fopen(filename, "r");
360511b41d2SMark Murray 	if (!f) {
361511b41d2SMark Murray 		perror(filename);
362511b41d2SMark Murray 		exit(1);
363511b41d2SMark Murray 	}
364511b41d2SMark Murray 	linenum = 0;
365511b41d2SMark Murray 	while (fgets(line, sizeof(line), f)) {
366511b41d2SMark Murray 		linenum++;
367c2d3a559SKris Kennaway 		cp = line;
368c2d3a559SKris Kennaway 		arg = strdelim(&cp);
369c2d3a559SKris Kennaway 		/* Ignore leading whitespace */
370c2d3a559SKris Kennaway 		if (*arg == '\0')
371c2d3a559SKris Kennaway 			arg = strdelim(&cp);
372c2d3a559SKris Kennaway 		if (!*arg || *arg == '#')
373511b41d2SMark Murray 			continue;
374c2d3a559SKris Kennaway 		opcode = parse_token(arg, filename, linenum);
375511b41d2SMark Murray 		switch (opcode) {
376511b41d2SMark Murray 		case sBadOption:
377511b41d2SMark Murray 			bad_options++;
378511b41d2SMark Murray 			continue;
379511b41d2SMark Murray 		case sPort:
380511b41d2SMark Murray 			/* ignore ports from configfile if cmdline specifies ports */
381511b41d2SMark Murray 			if (options->ports_from_cmdline)
382511b41d2SMark Murray 				continue;
383511b41d2SMark Murray 			if (options->listen_addrs != NULL)
384511b41d2SMark Murray 				fatal("%s line %d: ports must be specified before "
385511b41d2SMark Murray 				    "ListenAdress.\n", filename, linenum);
386511b41d2SMark Murray 			if (options->num_ports >= MAX_PORTS)
387511b41d2SMark Murray 				fatal("%s line %d: too many ports.\n",
388511b41d2SMark Murray 				    filename, linenum);
389c2d3a559SKris Kennaway 			arg = strdelim(&cp);
390c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
391511b41d2SMark Murray 				fatal("%s line %d: missing port number.\n",
392511b41d2SMark Murray 				    filename, linenum);
393c2d3a559SKris Kennaway 			options->ports[options->num_ports++] = atoi(arg);
394511b41d2SMark Murray 			break;
395511b41d2SMark Murray 
396511b41d2SMark Murray 		case sServerKeyBits:
397511b41d2SMark Murray 			intptr = &options->server_key_bits;
398511b41d2SMark Murray parse_int:
399c2d3a559SKris Kennaway 			arg = strdelim(&cp);
400c2d3a559SKris Kennaway 			if (!arg || *arg == '\0') {
401511b41d2SMark Murray 				fprintf(stderr, "%s line %d: missing integer value.\n",
402511b41d2SMark Murray 					filename, linenum);
403511b41d2SMark Murray 				exit(1);
404511b41d2SMark Murray 			}
405c2d3a559SKris Kennaway 			value = atoi(arg);
406c2d3a559SKris Kennaway 			if (value == 0) {
40742f71286SMark Murray 				fprintf(stderr, "%s line %d: invalid integer value.\n",
40842f71286SMark Murray 					filename, linenum);
40942f71286SMark Murray 				exit(1);
41042f71286SMark Murray 			}
411511b41d2SMark Murray 			if (*intptr == -1)
412511b41d2SMark Murray 				*intptr = value;
413511b41d2SMark Murray 			break;
414511b41d2SMark Murray 
415511b41d2SMark Murray 		case sLoginGraceTime:
416511b41d2SMark Murray 			intptr = &options->login_grace_time;
417511b41d2SMark Murray 			goto parse_int;
418511b41d2SMark Murray 
419511b41d2SMark Murray 		case sKeyRegenerationTime:
420511b41d2SMark Murray 			intptr = &options->key_regeneration_time;
421511b41d2SMark Murray 			goto parse_int;
422511b41d2SMark Murray 
423511b41d2SMark Murray 		case sListenAddress:
424c2d3a559SKris Kennaway 			arg = strdelim(&cp);
425c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
426511b41d2SMark Murray 				fatal("%s line %d: missing inet addr.\n",
427511b41d2SMark Murray 				    filename, linenum);
428c2d3a559SKris Kennaway 			add_listen_addr(options, arg);
429511b41d2SMark Murray 			break;
430511b41d2SMark Murray 
431511b41d2SMark Murray 		case sHostKeyFile:
432e8aafc91SKris Kennaway 		case sHostDSAKeyFile:
433e8aafc91SKris Kennaway 			charptr = (opcode == sHostKeyFile ) ?
434e8aafc91SKris Kennaway 			    &options->host_key_file : &options->host_dsa_key_file;
435c2d3a559SKris Kennaway parse_filename:
436c2d3a559SKris Kennaway 			arg = strdelim(&cp);
437c2d3a559SKris Kennaway 			if (!arg || *arg == '\0') {
438e8aafc91SKris Kennaway 				fprintf(stderr, "%s line %d: missing file name.\n",
439e8aafc91SKris Kennaway 				    filename, linenum);
440e8aafc91SKris Kennaway 				exit(1);
441e8aafc91SKris Kennaway 			}
442e8aafc91SKris Kennaway 			if (*charptr == NULL)
443c2d3a559SKris Kennaway 				*charptr = tilde_expand_filename(arg, getuid());
444e8aafc91SKris Kennaway 			break;
445e8aafc91SKris Kennaway 
446e8aafc91SKris Kennaway 		case sPidFile:
447e8aafc91SKris Kennaway 			charptr = &options->pid_file;
448c2d3a559SKris Kennaway 			goto parse_filename;
449511b41d2SMark Murray 
450511b41d2SMark Murray 		case sRandomSeedFile:
451511b41d2SMark Murray 			fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
452511b41d2SMark Murray 				filename, linenum);
453c2d3a559SKris Kennaway 			arg = strdelim(&cp);
454511b41d2SMark Murray 			break;
455511b41d2SMark Murray 
456511b41d2SMark Murray 		case sPermitRootLogin:
457511b41d2SMark Murray 			intptr = &options->permit_root_login;
458c2d3a559SKris Kennaway 			arg = strdelim(&cp);
459c2d3a559SKris Kennaway 			if (!arg || *arg == '\0') {
460511b41d2SMark Murray 				fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
461511b41d2SMark Murray 					filename, linenum);
462511b41d2SMark Murray 				exit(1);
463511b41d2SMark Murray 			}
464c2d3a559SKris Kennaway 			if (strcmp(arg, "without-password") == 0)
465511b41d2SMark Murray 				value = 2;
466c2d3a559SKris Kennaway 			else if (strcmp(arg, "yes") == 0)
467511b41d2SMark Murray 				value = 1;
468c2d3a559SKris Kennaway 			else if (strcmp(arg, "no") == 0)
469511b41d2SMark Murray 				value = 0;
470511b41d2SMark Murray 			else {
471511b41d2SMark Murray 				fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
472c2d3a559SKris Kennaway 					filename, linenum, arg);
473511b41d2SMark Murray 				exit(1);
474511b41d2SMark Murray 			}
475511b41d2SMark Murray 			if (*intptr == -1)
476511b41d2SMark Murray 				*intptr = value;
477511b41d2SMark Murray 			break;
478511b41d2SMark Murray 
479511b41d2SMark Murray 		case sIgnoreRhosts:
480511b41d2SMark Murray 			intptr = &options->ignore_rhosts;
481511b41d2SMark Murray parse_flag:
482c2d3a559SKris Kennaway 			arg = strdelim(&cp);
483c2d3a559SKris Kennaway 			if (!arg || *arg == '\0') {
484511b41d2SMark Murray 				fprintf(stderr, "%s line %d: missing yes/no argument.\n",
485511b41d2SMark Murray 					filename, linenum);
486511b41d2SMark Murray 				exit(1);
487511b41d2SMark Murray 			}
488c2d3a559SKris Kennaway 			if (strcmp(arg, "yes") == 0)
489511b41d2SMark Murray 				value = 1;
490c2d3a559SKris Kennaway 			else if (strcmp(arg, "no") == 0)
491511b41d2SMark Murray 				value = 0;
492511b41d2SMark Murray 			else {
493511b41d2SMark Murray 				fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
494c2d3a559SKris Kennaway 					filename, linenum, arg);
495511b41d2SMark Murray 				exit(1);
496511b41d2SMark Murray 			}
497511b41d2SMark Murray 			if (*intptr == -1)
498511b41d2SMark Murray 				*intptr = value;
499511b41d2SMark Murray 			break;
500511b41d2SMark Murray 
501511b41d2SMark Murray 		case sIgnoreUserKnownHosts:
502511b41d2SMark Murray 			intptr = &options->ignore_user_known_hosts;
503962a3f4eSSheldon Hearn 			goto parse_flag;
504511b41d2SMark Murray 
505511b41d2SMark Murray 		case sRhostsAuthentication:
506511b41d2SMark Murray 			intptr = &options->rhosts_authentication;
507511b41d2SMark Murray 			goto parse_flag;
508511b41d2SMark Murray 
509511b41d2SMark Murray 		case sRhostsRSAAuthentication:
510511b41d2SMark Murray 			intptr = &options->rhosts_rsa_authentication;
511511b41d2SMark Murray 			goto parse_flag;
512511b41d2SMark Murray 
513511b41d2SMark Murray 		case sRSAAuthentication:
514511b41d2SMark Murray 			intptr = &options->rsa_authentication;
515511b41d2SMark Murray 			goto parse_flag;
516511b41d2SMark Murray 
517e8aafc91SKris Kennaway 		case sDSAAuthentication:
518e8aafc91SKris Kennaway 			intptr = &options->dsa_authentication;
519e8aafc91SKris Kennaway 			goto parse_flag;
520e8aafc91SKris Kennaway 
521cb96ab36SAssar Westerlund #if defined(KRB4) || defined(KRB5)
522cb96ab36SAssar Westerlund 		case sKerberosAuthentication:
523cb96ab36SAssar Westerlund 			intptr = &options->kerberos_authentication;
524511b41d2SMark Murray 			goto parse_flag;
525cb96ab36SAssar Westerlund #endif
526511b41d2SMark Murray 
527cb96ab36SAssar Westerlund #ifdef KRB4
528fe5fd017SMark Murray 		case sKrb4OrLocalPasswd:
529fe5fd017SMark Murray 			intptr = &options->krb4_or_local_passwd;
530511b41d2SMark Murray 			goto parse_flag;
531511b41d2SMark Murray 
532fe5fd017SMark Murray 		case sKrb4TicketCleanup:
533fe5fd017SMark Murray 			intptr = &options->krb4_ticket_cleanup;
534511b41d2SMark Murray 			goto parse_flag;
535511b41d2SMark Murray #endif
536511b41d2SMark Murray 
537fe5fd017SMark Murray #ifdef KRB5
538fe5fd017SMark Murray 		case sKrb5TgtPassing:
539fe5fd017SMark Murray 			intptr = &options->krb5_tgt_passing;
540fe5fd017SMark Murray 			goto parse_flag;
541fe5fd017SMark Murray #endif /* KRB5 */
542fe5fd017SMark Murray 
543511b41d2SMark Murray #ifdef AFS
544fe5fd017SMark Murray 		case sKrb4TgtPassing:
545fe5fd017SMark Murray 			intptr = &options->krb4_tgt_passing;
546511b41d2SMark Murray 			goto parse_flag;
547511b41d2SMark Murray 
548511b41d2SMark Murray 		case sAFSTokenPassing:
549511b41d2SMark Murray 			intptr = &options->afs_token_passing;
550511b41d2SMark Murray 			goto parse_flag;
551511b41d2SMark Murray #endif
552511b41d2SMark Murray 
553511b41d2SMark Murray 		case sPasswordAuthentication:
554511b41d2SMark Murray 			intptr = &options->password_authentication;
555511b41d2SMark Murray 			goto parse_flag;
556511b41d2SMark Murray 
55709958426SBrian Feldman 		case sKbdInteractiveAuthentication:
55809958426SBrian Feldman 			intptr = &options->kbd_interactive_authentication;
55909958426SBrian Feldman 			goto parse_flag;
56009958426SBrian Feldman 
561511b41d2SMark Murray 		case sCheckMail:
562511b41d2SMark Murray 			intptr = &options->check_mail;
563511b41d2SMark Murray 			goto parse_flag;
564511b41d2SMark Murray 
565511b41d2SMark Murray #ifdef SKEY
566511b41d2SMark Murray 		case sSkeyAuthentication:
567511b41d2SMark Murray 			intptr = &options->skey_authentication;
568511b41d2SMark Murray 			goto parse_flag;
569511b41d2SMark Murray #endif
570511b41d2SMark Murray 
571511b41d2SMark Murray 		case sPrintMotd:
572511b41d2SMark Murray 			intptr = &options->print_motd;
573511b41d2SMark Murray 			goto parse_flag;
574511b41d2SMark Murray 
575511b41d2SMark Murray 		case sX11Forwarding:
576511b41d2SMark Murray 			intptr = &options->x11_forwarding;
577511b41d2SMark Murray 			goto parse_flag;
578511b41d2SMark Murray 
579511b41d2SMark Murray 		case sX11DisplayOffset:
580511b41d2SMark Murray 			intptr = &options->x11_display_offset;
581511b41d2SMark Murray 			goto parse_int;
582511b41d2SMark Murray 
583c2d3a559SKris Kennaway 		case sXAuthLocation:
584c2d3a559SKris Kennaway 			charptr = &options->xauth_location;
585c2d3a559SKris Kennaway 			goto parse_filename;
586c2d3a559SKris Kennaway 
587511b41d2SMark Murray 		case sStrictModes:
588511b41d2SMark Murray 			intptr = &options->strict_modes;
589511b41d2SMark Murray 			goto parse_flag;
590511b41d2SMark Murray 
591511b41d2SMark Murray 		case sKeepAlives:
592511b41d2SMark Murray 			intptr = &options->keepalives;
593511b41d2SMark Murray 			goto parse_flag;
594511b41d2SMark Murray 
595511b41d2SMark Murray 		case sEmptyPasswd:
596511b41d2SMark Murray 			intptr = &options->permit_empty_passwd;
597511b41d2SMark Murray 			goto parse_flag;
598511b41d2SMark Murray 
599511b41d2SMark Murray 		case sUseLogin:
600511b41d2SMark Murray 			intptr = &options->use_login;
601511b41d2SMark Murray 			goto parse_flag;
602511b41d2SMark Murray 
603e8aafc91SKris Kennaway 		case sGatewayPorts:
604e8aafc91SKris Kennaway 			intptr = &options->gateway_ports;
605e8aafc91SKris Kennaway 			goto parse_flag;
606e8aafc91SKris Kennaway 
607511b41d2SMark Murray 		case sLogFacility:
608511b41d2SMark Murray 			intptr = (int *) &options->log_facility;
609c2d3a559SKris Kennaway 			arg = strdelim(&cp);
610c2d3a559SKris Kennaway 			value = log_facility_number(arg);
611511b41d2SMark Murray 			if (value == (SyslogFacility) - 1)
612511b41d2SMark Murray 				fatal("%.200s line %d: unsupported log facility '%s'\n",
613c2d3a559SKris Kennaway 				    filename, linenum, arg ? arg : "<NONE>");
614511b41d2SMark Murray 			if (*intptr == -1)
615511b41d2SMark Murray 				*intptr = (SyslogFacility) value;
616511b41d2SMark Murray 			break;
617511b41d2SMark Murray 
618511b41d2SMark Murray 		case sLogLevel:
619511b41d2SMark Murray 			intptr = (int *) &options->log_level;
620c2d3a559SKris Kennaway 			arg = strdelim(&cp);
621c2d3a559SKris Kennaway 			value = log_level_number(arg);
622511b41d2SMark Murray 			if (value == (LogLevel) - 1)
623511b41d2SMark Murray 				fatal("%.200s line %d: unsupported log level '%s'\n",
624c2d3a559SKris Kennaway 				    filename, linenum, arg ? arg : "<NONE>");
625511b41d2SMark Murray 			if (*intptr == -1)
626511b41d2SMark Murray 				*intptr = (LogLevel) value;
627511b41d2SMark Murray 			break;
628511b41d2SMark Murray 
62909958426SBrian Feldman 		case sAllowTcpForwarding:
63009958426SBrian Feldman 			intptr = &options->allow_tcp_forwarding;
63109958426SBrian Feldman 			goto parse_flag;
63209958426SBrian Feldman 
633511b41d2SMark Murray 		case sAllowUsers:
634c2d3a559SKris Kennaway 			while ((arg = strdelim(&cp)) && *arg != '\0') {
63542f71286SMark Murray 				if (options->num_allow_users >= MAX_ALLOW_USERS)
636e8aafc91SKris Kennaway 					fatal("%.200s line %d: too many allow users.\n",
637e8aafc91SKris Kennaway 					    filename, linenum);
638c2d3a559SKris Kennaway 				options->allow_users[options->num_allow_users++] = xstrdup(arg);
639511b41d2SMark Murray 			}
640511b41d2SMark Murray 			break;
641511b41d2SMark Murray 
642511b41d2SMark Murray 		case sDenyUsers:
643c2d3a559SKris Kennaway 			while ((arg = strdelim(&cp)) && *arg != '\0') {
6442803b77eSBrian Feldman 				if (options->num_deny_users >= MAX_DENY_USERS)
645e8aafc91SKris Kennaway 					fatal("%.200s line %d: too many deny users.\n",
646e8aafc91SKris Kennaway 					    filename, linenum);
647c2d3a559SKris Kennaway 				options->deny_users[options->num_deny_users++] = xstrdup(arg);
648511b41d2SMark Murray 			}
649511b41d2SMark Murray 			break;
650511b41d2SMark Murray 
651511b41d2SMark Murray 		case sAllowGroups:
652c2d3a559SKris Kennaway 			while ((arg = strdelim(&cp)) && *arg != '\0') {
65342f71286SMark Murray 				if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
654e8aafc91SKris Kennaway 					fatal("%.200s line %d: too many allow groups.\n",
655e8aafc91SKris Kennaway 					    filename, linenum);
656c2d3a559SKris Kennaway 				options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
657511b41d2SMark Murray 			}
658511b41d2SMark Murray 			break;
659511b41d2SMark Murray 
660511b41d2SMark Murray 		case sDenyGroups:
661c2d3a559SKris Kennaway 			while ((arg = strdelim(&cp)) && *arg != '\0') {
66242f71286SMark Murray 				if (options->num_deny_groups >= MAX_DENY_GROUPS)
663e8aafc91SKris Kennaway 					fatal("%.200s line %d: too many deny groups.\n",
664e8aafc91SKris Kennaway 					    filename, linenum);
665c2d3a559SKris Kennaway 				options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
666511b41d2SMark Murray 			}
667511b41d2SMark Murray 			break;
668511b41d2SMark Murray 
669e8aafc91SKris Kennaway 		case sCiphers:
670c2d3a559SKris Kennaway 			arg = strdelim(&cp);
671c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
672c322fe35SKris Kennaway 				fatal("%s line %d: Missing argument.", filename, linenum);
673c2d3a559SKris Kennaway 			if (!ciphers_valid(arg))
674e8aafc91SKris Kennaway 				fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
675c2d3a559SKris Kennaway 				    filename, linenum, arg ? arg : "<NONE>");
676e8aafc91SKris Kennaway 			if (options->ciphers == NULL)
677c2d3a559SKris Kennaway 				options->ciphers = xstrdup(arg);
678e8aafc91SKris Kennaway 			break;
679e8aafc91SKris Kennaway 
680e8aafc91SKris Kennaway 		case sProtocol:
681e8aafc91SKris Kennaway 			intptr = &options->protocol;
682c2d3a559SKris Kennaway 			arg = strdelim(&cp);
683c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
684c322fe35SKris Kennaway 				fatal("%s line %d: Missing argument.", filename, linenum);
685c2d3a559SKris Kennaway 			value = proto_spec(arg);
686e8aafc91SKris Kennaway 			if (value == SSH_PROTO_UNKNOWN)
687e8aafc91SKris Kennaway 				fatal("%s line %d: Bad protocol spec '%s'.",
688c2d3a559SKris Kennaway 				      filename, linenum, arg ? arg : "<NONE>");
689e8aafc91SKris Kennaway 			if (*intptr == SSH_PROTO_UNKNOWN)
690e8aafc91SKris Kennaway 				*intptr = value;
691e8aafc91SKris Kennaway 			break;
692e8aafc91SKris Kennaway 
69342f71286SMark Murray 		case sConnectionsPerPeriod:
6948e97fe72SPaul Saab 			(void)strdelim(&cp);
695895b03b1SBrian Feldman 			error("ConnectionsPerPeriod has been deprecated!");
69642f71286SMark Murray 			break;
69742f71286SMark Murray 
698c2d3a559SKris Kennaway 		case sSubsystem:
699c2d3a559SKris Kennaway 			if(options->num_subsystems >= MAX_SUBSYSTEMS) {
700c2d3a559SKris Kennaway 				fatal("%s line %d: too many subsystems defined.",
701c2d3a559SKris Kennaway 				      filename, linenum);
702c2d3a559SKris Kennaway 			}
703c2d3a559SKris Kennaway 			arg = strdelim(&cp);
704c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
705c2d3a559SKris Kennaway 				fatal("%s line %d: Missing subsystem name.",
706c2d3a559SKris Kennaway 				      filename, linenum);
707c2d3a559SKris Kennaway 			for (i = 0; i < options->num_subsystems; i++)
708c2d3a559SKris Kennaway 				if(strcmp(arg, options->subsystem_name[i]) == 0)
709c2d3a559SKris Kennaway 					fatal("%s line %d: Subsystem '%s' already defined.",
710c2d3a559SKris Kennaway 					      filename, linenum, arg);
711c2d3a559SKris Kennaway 			options->subsystem_name[options->num_subsystems] = xstrdup(arg);
712c2d3a559SKris Kennaway 			arg = strdelim(&cp);
713c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
714c2d3a559SKris Kennaway 				fatal("%s line %d: Missing subsystem command.",
715c2d3a559SKris Kennaway 				      filename, linenum);
716c2d3a559SKris Kennaway 			options->subsystem_command[options->num_subsystems] = xstrdup(arg);
717c2d3a559SKris Kennaway 			options->num_subsystems++;
718c2d3a559SKris Kennaway 			break;
719c2d3a559SKris Kennaway 
720c2d3a559SKris Kennaway 		case sMaxStartups:
721c2d3a559SKris Kennaway 			arg = strdelim(&cp);
722c2d3a559SKris Kennaway 			if (!arg || *arg == '\0')
723c2d3a559SKris Kennaway 				fatal("%s line %d: Missing MaxStartups spec.",
724c2d3a559SKris Kennaway 				      filename, linenum);
725c2d3a559SKris Kennaway 			if (sscanf(arg, "%d:%d:%d",
726c2d3a559SKris Kennaway 			    &options->max_startups_begin,
727c2d3a559SKris Kennaway 			    &options->max_startups_rate,
728c2d3a559SKris Kennaway 			    &options->max_startups) == 3) {
729c2d3a559SKris Kennaway 				if (options->max_startups_begin >
730c2d3a559SKris Kennaway 				    options->max_startups ||
731c2d3a559SKris Kennaway 				    options->max_startups_rate > 100 ||
732c2d3a559SKris Kennaway 				    options->max_startups_rate < 1)
733c2d3a559SKris Kennaway 				fatal("%s line %d: Illegal MaxStartups spec.",
734c2d3a559SKris Kennaway 				      filename, linenum);
735c2d3a559SKris Kennaway 				break;
736c2d3a559SKris Kennaway 			}
737c2d3a559SKris Kennaway 			intptr = &options->max_startups;
738c2d3a559SKris Kennaway 			goto parse_int;
739c2d3a559SKris Kennaway 
740933ca70fSBrian Feldman 		case sVersionAddendum:
741933ca70fSBrian Feldman 			ssh_version_set_addendum(strtok(cp, "\n"));
742933ca70fSBrian Feldman 			do
743933ca70fSBrian Feldman 				arg = strdelim(&cp);
744933ca70fSBrian Feldman 			while (arg != NULL && *arg != '\0');
745933ca70fSBrian Feldman 			break;
746933ca70fSBrian Feldman 
74742f71286SMark Murray 		default:
74842f71286SMark Murray 			fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
749c2d3a559SKris Kennaway 				filename, linenum,arg, opcode);
750511b41d2SMark Murray 		}
751c2d3a559SKris Kennaway 		if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
752c2d3a559SKris Kennaway 			fprintf(stderr,
753c2d3a559SKris Kennaway 				"%s line %d: garbage at end of line; \"%.200s\".\n",
754c2d3a559SKris Kennaway 				filename, linenum, arg);
755c2d3a559SKris Kennaway 			exit(1);
756e8aafc91SKris Kennaway 		}
757511b41d2SMark Murray 	}
758511b41d2SMark Murray 	fclose(f);
759e8aafc91SKris Kennaway 	if (bad_options > 0) {
76042f71286SMark Murray 		fatal("%.200s: terminating, %d bad configuration options\n",
761511b41d2SMark Murray 			filename, bad_options);
762511b41d2SMark Murray 	}
763e8aafc91SKris Kennaway }
764