xref: /titanic_50/usr/src/cmd/ssh/libssh/common/readconf.c (revision b2b3ca14272ffe2a6fc37bab2ab65b8f6702d750)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Functions for reading the configuration files.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13 /*
14  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
15  * Use is subject to license terms.
16  */
17 
18 #include "includes.h"
19 RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
20 
21 #include "ssh.h"
22 #include "xmalloc.h"
23 #include "compat.h"
24 #include "cipher.h"
25 #include "pathnames.h"
26 #include "log.h"
27 #include "readconf.h"
28 #include "match.h"
29 #include "misc.h"
30 #include "kex.h"
31 #include "mac.h"
32 
33 /* Format of the configuration file:
34 
35    # Configuration data is parsed as follows:
36    #  1. command line options
37    #  2. user-specific file
38    #  3. system-wide file
39    # Any configuration value is only changed the first time it is set.
40    # Thus, host-specific definitions should be at the beginning of the
41    # configuration file, and defaults at the end.
42 
43    # Host-specific declarations.  These may override anything above.  A single
44    # host may match multiple declarations; these are processed in the order
45    # that they are given in.
46 
47    Host *.ngs.fi ngs.fi
48      User foo
49 
50    Host fake.com
51      HostName another.host.name.real.org
52      User blaah
53      Port 34289
54      ForwardX11 no
55      ForwardAgent no
56 
57    Host books.com
58      RemoteForward 9999 shadows.cs.hut.fi:9999
59      Cipher 3des
60 
61    Host fascist.blob.com
62      Port 23123
63      User tylonen
64      RhostsAuthentication no
65      PasswordAuthentication no
66 
67    Host puukko.hut.fi
68      User t35124p
69      ProxyCommand ssh-proxy %h %p
70 
71    Host *.fr
72      PublicKeyAuthentication no
73 
74    Host *.su
75      Cipher none
76      PasswordAuthentication no
77 
78    # Defaults for various options
79    Host *
80      ForwardAgent no
81      ForwardX11 no
82      RhostsAuthentication yes
83      PasswordAuthentication yes
84      RSAAuthentication yes
85      RhostsRSAAuthentication yes
86      StrictHostKeyChecking yes
87      KeepAlives no
88      IdentityFile ~/.ssh/identity
89      Port 22
90      EscapeChar ~
91 
92 */
93 
94 /* Keyword tokens. */
95 
96 typedef enum {
97 	oBadOption,
98 	oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
99 	oRhostsAuthentication,
100 	oPasswordAuthentication, oRSAAuthentication,
101 	oChallengeResponseAuthentication, oXAuthLocation,
102 #if defined(KRB4) || defined(KRB5)
103 	oKerberosAuthentication,
104 #endif
105 #ifdef GSSAPI
106 	oGssKeyEx, oGssAuthentication, oGssDelegateCreds,
107 #ifdef GSI
108 	oGssGlobusDelegateLimitedCreds,
109 #endif /* GSI */
110 #endif /* GSSAPI */
111 #if defined(AFS) || defined(KRB5)
112 	oKerberosTgtPassing,
113 #endif
114 #ifdef AFS
115 	oAFSTokenPassing,
116 #endif
117 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
118 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
119 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
120 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
121 	oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
122 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
123 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
124 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
125 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
126 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
127 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128 	oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts,
129 	oServerAliveInterval, oServerAliveCountMax, oDisableBanner,
130 	oIgnoreIfUnknown, oRekeyLimit, oUseOpenSSLEngine,
131 	oDeprecated
132 } OpCodes;
133 
134 /* Textual representations of the tokens. */
135 
136 static struct {
137 	const char *name;
138 	OpCodes opcode;
139 } keywords[] = {
140 	{ "forwardagent", oForwardAgent },
141 	{ "forwardx11", oForwardX11 },
142 	{ "forwardx11trusted", oForwardX11Trusted },
143 	{ "xauthlocation", oXAuthLocation },
144 	{ "gatewayports", oGatewayPorts },
145 	{ "useprivilegedport", oUsePrivilegedPort },
146 	{ "rhostsauthentication", oRhostsAuthentication },
147 	{ "passwordauthentication", oPasswordAuthentication },
148 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
149 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
150 	{ "rsaauthentication", oRSAAuthentication },
151 	{ "pubkeyauthentication", oPubkeyAuthentication },
152 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
153 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
154 	{ "hostbasedauthentication", oHostbasedAuthentication },
155 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
156 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
157 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
158 #if defined(KRB4) || defined(KRB5)
159 	{ "kerberosauthentication", oKerberosAuthentication },
160 #endif
161 #ifdef GSSAPI
162 	{ "gssapikeyexchange", oGssKeyEx },
163 	{ "gssapiauthentication", oGssAuthentication },
164 	{ "gssapidelegatecredentials", oGssDelegateCreds },
165 	{ "gsskeyex", oGssKeyEx },				/* alias */
166 	{ "gssauthentication", oGssAuthentication },		/* alias */
167 	{ "gssdelegatecreds", oGssDelegateCreds },		/* alias */
168 #ifdef GSI
169 	/* For backwards compatability with old 1.2.27 client code */
170 	{ "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
171 	{ "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
172 #endif /* GSI */
173 #endif /* GSSAPI */
174 #if defined(AFS) || defined(KRB5)
175 	{ "kerberostgtpassing", oKerberosTgtPassing },
176 #endif
177 #ifdef AFS
178 	{ "afstokenpassing", oAFSTokenPassing },
179 #endif
180 	{ "fallbacktorsh", oFallBackToRsh },
181 	{ "usersh", oUseRsh },
182 	{ "identityfile", oIdentityFile },
183 	{ "identityfile2", oIdentityFile },			/* alias */
184 	{ "hostname", oHostName },
185 	{ "hostkeyalias", oHostKeyAlias },
186 	{ "proxycommand", oProxyCommand },
187 	{ "port", oPort },
188 	{ "cipher", oCipher },
189 	{ "ciphers", oCiphers },
190 	{ "macs", oMacs },
191 	{ "protocol", oProtocol },
192 	{ "remoteforward", oRemoteForward },
193 	{ "localforward", oLocalForward },
194 	{ "user", oUser },
195 	{ "host", oHost },
196 	{ "escapechar", oEscapeChar },
197 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
198 	{ "userknownhostsfile", oUserKnownHostsFile },		/* obsolete */
199 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
200 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
201 	{ "connectionattempts", oConnectionAttempts },
202 	{ "batchmode", oBatchMode },
203 	{ "checkhostip", oCheckHostIP },
204 	{ "stricthostkeychecking", oStrictHostKeyChecking },
205 	{ "compression", oCompression },
206 	{ "compressionlevel", oCompressionLevel },
207 	{ "keepalive", oKeepAlives },
208 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
209 	{ "loglevel", oLogLevel },
210 	{ "dynamicforward", oDynamicForward },
211 	{ "preferredauthentications", oPreferredAuthentications },
212 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
213 	{ "bindaddress", oBindAddress },
214 	{ "smartcarddevice", oSmartcardDevice },
215 	{ "clearallforwardings", oClearAllForwardings },
216 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
217 	{ "rekeylimit", oRekeyLimit },
218 	{ "connecttimeout", oConnectTimeout },
219 	{ "serveraliveinterval", oServerAliveInterval },
220 	{ "serveralivecountmax", oServerAliveCountMax },
221 	{ "disablebanner", oDisableBanner },
222 	{ "hashknownhosts", oHashKnownHosts },
223 	{ "ignoreifunknown", oIgnoreIfUnknown },
224 	{ "useopensslengine", oUseOpenSSLEngine },
225 	{ NULL, oBadOption }
226 };
227 
228 /*
229  * Adds a local TCP/IP port forward to options.  Never returns if there is an
230  * error.
231  */
232 
233 void
234 add_local_forward(Options *options, const Forward *newfwd)
235 {
236 	Forward *fwd;
237 #ifndef NO_IPPORT_RESERVED_CONCEPT
238 	extern uid_t original_real_uid;
239 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
240 		fatal("Privileged ports can only be forwarded by root.");
241 #endif
242 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
243 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
244 	fwd = &options->local_forwards[options->num_local_forwards++];
245 
246 	fwd->listen_host = (newfwd->listen_host == NULL) ?
247 	    NULL : xstrdup(newfwd->listen_host);
248 	fwd->listen_port = newfwd->listen_port;
249 	fwd->connect_host = xstrdup(newfwd->connect_host);
250 	fwd->connect_port = newfwd->connect_port;
251 }
252 
253 /*
254  * Adds a remote TCP/IP port forward to options.  Never returns if there is
255  * an error.
256  */
257 
258 void
259 add_remote_forward(Options *options, const Forward *newfwd)
260 {
261 	Forward *fwd;
262 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
263 		fatal("Too many remote forwards (max %d).",
264 		    SSH_MAX_FORWARDS_PER_DIRECTION);
265 	fwd = &options->remote_forwards[options->num_remote_forwards++];
266 
267 	fwd->listen_host = (newfwd->listen_host == NULL) ?
268 	    NULL : xstrdup(newfwd->listen_host);
269 	fwd->listen_port = newfwd->listen_port;
270 	fwd->connect_host = xstrdup(newfwd->connect_host);
271 	fwd->connect_port = newfwd->connect_port;
272 }
273 
274 static void
275 clear_forwardings(Options *options)
276 {
277 	int i;
278 
279 	for (i = 0; i < options->num_local_forwards; i++) {
280 		if (options->local_forwards[i].listen_host != NULL)
281 			xfree(options->local_forwards[i].listen_host);
282 		xfree(options->local_forwards[i].connect_host);
283 	}
284 	options->num_local_forwards = 0;
285 	for (i = 0; i < options->num_remote_forwards; i++) {
286 		if (options->remote_forwards[i].listen_host != NULL)
287 			xfree(options->remote_forwards[i].listen_host);
288 		xfree(options->remote_forwards[i].connect_host);
289 	}
290 	options->num_remote_forwards = 0;
291 }
292 
293 /*
294  * Returns the number of the token pointed to by cp or oBadOption.
295  */
296 
297 static OpCodes
298 parse_token(const char *cp, const char *filename, int linenum)
299 {
300 	u_int i;
301 
302 	for (i = 0; keywords[i].name; i++)
303 		if (strcasecmp(cp, keywords[i].name) == 0)
304 			return keywords[i].opcode;
305 
306 	debug("%s: line %d: unknown configuration option: %s",
307 	    filename, linenum, cp);
308 	return oBadOption;
309 }
310 
311 /*
312  * Processes a single option line as used in the configuration files. This
313  * only sets those values that have not already been set.
314  */
315 
316 int
317 process_config_line(Options *options, const char *host,
318 		    char *line, const char *filename, int linenum,
319 		    int *activep)
320 {
321 	char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
322 	int opcode, *intptr, value, scale, i;
323 	long long orig, val64;
324 	StoredOption *so;
325 	Forward fwd;
326 
327 	s = line;
328 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
329 	keyword = strdelim(&s);
330 	/* Ignore leading whitespace. */
331 	if (*keyword == '\0')
332 		keyword = strdelim(&s);
333 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
334 		return 0;
335 
336 	opcode = parse_token(keyword, filename, linenum);
337 
338 	switch (opcode) {
339 	case oBadOption:
340 		if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) {
341 			error("we can't have more than %d unknown options:",
342 			    MAX_UNKNOWN_OPTIONS);
343 			for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) {
344 				so = &options->unknown_opts[i];
345 				error("%s:%d:%s",
346 				    so->filename, so->linenum, so->keyword);
347 				xfree(so->keyword);
348 				xfree(so->filename);
349 			}
350 			fatal("too many unknown options found, can't continue");
351 		}
352 
353 		/* unknown options will be processed later */
354 		so = &options->unknown_opts[options->unknown_opts_num];
355 		so->keyword = xstrdup(keyword);
356 		so->filename = xstrdup(filename);
357 		so->linenum = linenum;
358 		options->unknown_opts_num++;
359 		return (0);
360 
361 		/* NOTREACHED */
362 	case oConnectTimeout:
363 		intptr = &options->connection_timeout;
364 parse_time:
365 		arg = strdelim(&s);
366 		if (!arg || *arg == '\0')
367 			fatal("%s line %d: missing time value.",
368 			    filename, linenum);
369 		if ((value = convtime(arg)) == -1)
370 			fatal("%s line %d: invalid time value.",
371 			    filename, linenum);
372 		if (*activep && *intptr == -1)
373 			*intptr = value;
374 		break;
375 
376 	case oForwardAgent:
377 		intptr = &options->forward_agent;
378 parse_flag:
379 		arg = strdelim(&s);
380 		if (!arg || *arg == '\0')
381 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
382 		value = 0;	/* To avoid compiler warning... */
383 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
384 			value = 1;
385 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
386 			value = 0;
387 		else
388 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
389 		if (*activep && *intptr == -1)
390 			*intptr = value;
391 		break;
392 
393 	case oForwardX11:
394 		intptr = &options->forward_x11;
395 		goto parse_flag;
396 
397 	case oForwardX11Trusted:
398 		intptr = &options->forward_x11_trusted;
399 		goto parse_flag;
400 
401 	case oGatewayPorts:
402 		intptr = &options->gateway_ports;
403 		goto parse_flag;
404 
405 	case oUsePrivilegedPort:
406 		intptr = &options->use_privileged_port;
407 		goto parse_flag;
408 
409 	case oRhostsAuthentication:
410 		intptr = &options->rhosts_authentication;
411 		goto parse_flag;
412 
413 	case oPasswordAuthentication:
414 		intptr = &options->password_authentication;
415 		goto parse_flag;
416 
417 	case oKbdInteractiveAuthentication:
418 		intptr = &options->kbd_interactive_authentication;
419 		goto parse_flag;
420 
421 	case oKbdInteractiveDevices:
422 		charptr = &options->kbd_interactive_devices;
423 		goto parse_string;
424 
425 	case oPubkeyAuthentication:
426 		intptr = &options->pubkey_authentication;
427 		goto parse_flag;
428 
429 	case oRSAAuthentication:
430 		intptr = &options->rsa_authentication;
431 		goto parse_flag;
432 
433 	case oRhostsRSAAuthentication:
434 		intptr = &options->rhosts_rsa_authentication;
435 		goto parse_flag;
436 
437 	case oHostbasedAuthentication:
438 		intptr = &options->hostbased_authentication;
439 		goto parse_flag;
440 
441 	case oChallengeResponseAuthentication:
442 		intptr = &options->challenge_response_authentication;
443 		goto parse_flag;
444 #if defined(KRB4) || defined(KRB5)
445 	case oKerberosAuthentication:
446 		intptr = &options->kerberos_authentication;
447 		goto parse_flag;
448 #endif
449 #ifdef GSSAPI
450 	case oGssKeyEx:
451 		intptr = &options->gss_keyex;
452 		goto parse_flag;
453 
454 	case oGssAuthentication:
455 		intptr = &options->gss_authentication;
456 		goto parse_flag;
457 
458 	case oGssDelegateCreds:
459 		intptr = &options->gss_deleg_creds;
460 		goto parse_flag;
461 
462 #ifdef GSI
463 	case oGssGlobusDelegateLimitedCreds:
464 		intptr = &options->gss_globus_deleg_limited_proxy;
465 		goto parse_flag;
466 #endif /* GSI */
467 
468 #endif /* GSSAPI */
469 
470 #if defined(AFS) || defined(KRB5)
471 	case oKerberosTgtPassing:
472 		intptr = &options->kerberos_tgt_passing;
473 		goto parse_flag;
474 #endif
475 #ifdef AFS
476 	case oAFSTokenPassing:
477 		intptr = &options->afs_token_passing;
478 		goto parse_flag;
479 #endif
480 	case oFallBackToRsh:
481 		intptr = &options->fallback_to_rsh;
482 		goto parse_flag;
483 
484 	case oUseRsh:
485 		intptr = &options->use_rsh;
486 		goto parse_flag;
487 
488 	case oBatchMode:
489 		intptr = &options->batch_mode;
490 		goto parse_flag;
491 
492 	case oCheckHostIP:
493 		intptr = &options->check_host_ip;
494 		goto parse_flag;
495 
496 	case oStrictHostKeyChecking:
497 		intptr = &options->strict_host_key_checking;
498 		arg = strdelim(&s);
499 		if (!arg || *arg == '\0')
500 			fatal("%.200s line %d: Missing yes/no/ask argument.",
501 			    filename, linenum);
502 		value = 0;	/* To avoid compiler warning... */
503 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
504 			value = 1;
505 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
506 			value = 0;
507 		else if (strcmp(arg, "ask") == 0)
508 			value = 2;
509 		else
510 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
511 		if (*activep && *intptr == -1)
512 			*intptr = value;
513 		break;
514 
515 	case oCompression:
516 		intptr = &options->compression;
517 		goto parse_flag;
518 
519 	case oKeepAlives:
520 		intptr = &options->keepalives;
521 		goto parse_flag;
522 
523 	case oNoHostAuthenticationForLocalhost:
524 		intptr = &options->no_host_authentication_for_localhost;
525 		goto parse_flag;
526 
527 	case oNumberOfPasswordPrompts:
528 		intptr = &options->number_of_password_prompts;
529 		goto parse_int;
530 
531 	case oCompressionLevel:
532 		intptr = &options->compression_level;
533 		goto parse_int;
534 
535 	case oRekeyLimit:
536 		arg = strdelim(&s);
537 		if (!arg || *arg == '\0')
538 			fatal("%.200s line %d: Missing argument.", filename, linenum);
539 		if (arg[0] < '0' || arg[0] > '9')
540 			fatal("%.200s line %d: Bad number.", filename, linenum);
541 		orig = val64 = strtoll(arg, &endofnumber, 10);
542 		if (arg == endofnumber)
543 			fatal("%.200s line %d: Bad number.", filename, linenum);
544 		switch (toupper(*endofnumber)) {
545 		case '\0':
546 			scale = 1;
547 			break;
548 		case 'K':
549 			scale = 1<<10;
550 			break;
551 		case 'M':
552 			scale = 1<<20;
553 			break;
554 		case 'G':
555 			scale = 1<<30;
556 			break;
557 		default:
558 			fatal("%.200s line %d: Invalid RekeyLimit suffix",
559 			    filename, linenum);
560 		}
561 		val64 *= scale;
562 		/* detect integer wrap and too-large limits */
563 		if ((val64 / scale) != orig || val64 > UINT_MAX)
564 			fatal("%.200s line %d: RekeyLimit too large",
565 			    filename, linenum);
566 		if (val64 < 16)
567 			fatal("%.200s line %d: RekeyLimit too small",
568 			    filename, linenum);
569 		if (*activep && options->rekey_limit == -1)
570 			options->rekey_limit = (u_int32_t)val64;
571 		break;
572 
573 	case oIdentityFile:
574 		arg = strdelim(&s);
575 		if (!arg || *arg == '\0')
576 			fatal("%.200s line %d: Missing argument.", filename, linenum);
577 		if (*activep) {
578 			intptr = &options->num_identity_files;
579 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
580 				fatal("%.200s line %d: Too many identity files specified (max %d).",
581 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
582 			charptr =  &options->identity_files[*intptr];
583 			*charptr = xstrdup(arg);
584 			*intptr = *intptr + 1;
585 		}
586 		break;
587 
588 	case oXAuthLocation:
589 		charptr=&options->xauth_location;
590 		goto parse_string;
591 
592 	case oUser:
593 		charptr = &options->user;
594 parse_string:
595 		arg = strdelim(&s);
596 		if (!arg || *arg == '\0')
597 			fatal("%.200s line %d: Missing argument.", filename, linenum);
598 		if (*activep && *charptr == NULL)
599 			*charptr = xstrdup(arg);
600 		break;
601 
602 	case oGlobalKnownHostsFile:
603 		charptr = &options->system_hostfile;
604 		goto parse_string;
605 
606 	case oUserKnownHostsFile:
607 		charptr = &options->user_hostfile;
608 		goto parse_string;
609 
610 	case oGlobalKnownHostsFile2:
611 		charptr = &options->system_hostfile2;
612 		goto parse_string;
613 
614 	case oUserKnownHostsFile2:
615 		charptr = &options->user_hostfile2;
616 		goto parse_string;
617 
618 	case oHostName:
619 		charptr = &options->hostname;
620 		goto parse_string;
621 
622 	case oHostKeyAlias:
623 		charptr = &options->host_key_alias;
624 		goto parse_string;
625 
626 	case oPreferredAuthentications:
627 		charptr = &options->preferred_authentications;
628 		goto parse_string;
629 
630 	case oBindAddress:
631 		charptr = &options->bind_address;
632 		goto parse_string;
633 
634 	case oSmartcardDevice:
635 		charptr = &options->smartcard_device;
636 		goto parse_string;
637 
638 	case oProxyCommand:
639 		charptr = &options->proxy_command;
640 		string = xstrdup("");
641 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
642 			string = xrealloc(string, strlen(string) + strlen(arg) + 2);
643 			strcat(string, " ");
644 			strcat(string, arg);
645 		}
646 		if (*activep && *charptr == NULL)
647 			*charptr = string;
648 		else
649 			xfree(string);
650 		return 0;
651 
652 	case oPort:
653 		intptr = &options->port;
654 parse_int:
655 		arg = strdelim(&s);
656 		if (!arg || *arg == '\0')
657 			fatal("%.200s line %d: Missing argument.", filename, linenum);
658 		if (arg[0] < '0' || arg[0] > '9')
659 			fatal("%.200s line %d: Bad number.", filename, linenum);
660 
661 		/* Octal, decimal, or hex format? */
662 		value = strtol(arg, &endofnumber, 0);
663 		if (arg == endofnumber)
664 			fatal("%.200s line %d: Bad number.", filename, linenum);
665 		if (*activep && *intptr == -1)
666 			*intptr = value;
667 		break;
668 
669 	case oConnectionAttempts:
670 		intptr = &options->connection_attempts;
671 		goto parse_int;
672 
673 	case oCipher:
674 		intptr = &options->cipher;
675 		arg = strdelim(&s);
676 		if (!arg || *arg == '\0')
677 			fatal("%.200s line %d: Missing argument.", filename, linenum);
678 		value = cipher_number(arg);
679 		if (value == -1)
680 			fatal("%.200s line %d: Bad cipher '%s'.",
681 			    filename, linenum, arg ? arg : "<NONE>");
682 		if (*activep && *intptr == -1)
683 			*intptr = value;
684 		break;
685 
686 	case oCiphers:
687 		arg = strdelim(&s);
688 		if (!arg || *arg == '\0')
689 			fatal("%.200s line %d: Missing argument.", filename, linenum);
690 		if (!ciphers_valid(arg))
691 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
692 			    filename, linenum, arg ? arg : "<NONE>");
693 		if (*activep && options->ciphers == NULL)
694 			options->ciphers = xstrdup(arg);
695 		break;
696 
697 	case oMacs:
698 		arg = strdelim(&s);
699 		if (!arg || *arg == '\0')
700 			fatal("%.200s line %d: Missing argument.", filename, linenum);
701 		if (!mac_valid(arg))
702 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
703 			    filename, linenum, arg ? arg : "<NONE>");
704 		if (*activep && options->macs == NULL)
705 			options->macs = xstrdup(arg);
706 		break;
707 
708 	case oHostKeyAlgorithms:
709 		arg = strdelim(&s);
710 		if (!arg || *arg == '\0')
711 			fatal("%.200s line %d: Missing argument.", filename, linenum);
712 		if (!key_names_valid2(arg))
713 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
714 			    filename, linenum, arg ? arg : "<NONE>");
715 		if (*activep && options->hostkeyalgorithms == NULL)
716 			options->hostkeyalgorithms = xstrdup(arg);
717 		break;
718 
719 	case oProtocol:
720 		intptr = &options->protocol;
721 		arg = strdelim(&s);
722 		if (!arg || *arg == '\0')
723 			fatal("%.200s line %d: Missing argument.", filename, linenum);
724 		value = proto_spec(arg);
725 		if (value == SSH_PROTO_UNKNOWN)
726 			fatal("%.200s line %d: Bad protocol spec '%s'.",
727 			    filename, linenum, arg ? arg : "<NONE>");
728 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
729 			*intptr = value;
730 		break;
731 
732 	case oLogLevel:
733 		intptr = (int *) &options->log_level;
734 		arg = strdelim(&s);
735 		value = log_level_number(arg);
736 		if (value == SYSLOG_LEVEL_NOT_SET)
737 			fatal("%.200s line %d: unsupported log level '%s'",
738 			    filename, linenum, arg ? arg : "<NONE>");
739 		if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
740 			*intptr = (LogLevel) value;
741 		break;
742 
743 	case oLocalForward:
744 	case oRemoteForward:
745 		arg = strdelim(&s);
746 		if (arg == NULL || *arg == '\0')
747 			fatal("%.200s line %d: Missing port argument.",
748 			    filename, linenum);
749 		arg2 = strdelim(&s);
750 		if (arg2 == NULL || *arg2 == '\0')
751 			fatal("%.200s line %d: Missing target argument.",
752 			    filename, linenum);
753 
754 		/* construct a string for parse_forward */
755 		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
756 
757 		if (parse_forward(1, &fwd, fwdarg) == 0)
758 			fatal("%.200s line %d: Bad forwarding specification.",
759 			    filename, linenum);
760 
761 		if (*activep) {
762 			if (opcode == oLocalForward)
763 				add_local_forward(options, &fwd);
764 			else if (opcode == oRemoteForward)
765 				add_remote_forward(options, &fwd);
766 		}
767 		break;
768 
769 	case oDynamicForward:
770 		arg = strdelim(&s);
771 		if (!arg || *arg == '\0')
772 			fatal("%.200s line %d: Missing port argument.",
773 			    filename, linenum);
774 
775 		if (parse_forward(0, &fwd, arg) == 0) {
776 			fatal("%.200s line %d: Bad dynamic forwarding specification.",
777 			    filename, linenum);
778 		}
779 
780 		if (*activep) {
781 			fwd.connect_host = "socks";
782 			add_local_forward(options, &fwd);
783 		}
784 		break;
785 
786 	case oClearAllForwardings:
787 		intptr = &options->clear_forwardings;
788 		goto parse_flag;
789 
790 	case oHost:
791 		*activep = 0;
792 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
793 			if (match_pattern(host, arg)) {
794 				debug("Applying options for %.100s", arg);
795 				*activep = 1;
796 				break;
797 			}
798 		/* Avoid garbage check below, as strdelim is done. */
799 		return 0;
800 
801 	case oEscapeChar:
802 		intptr = &options->escape_char;
803 		arg = strdelim(&s);
804 		if (!arg || *arg == '\0')
805 			fatal("%.200s line %d: Missing argument.", filename, linenum);
806 		if (arg[0] == '^' && arg[2] == 0 &&
807 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
808 			value = (u_char) arg[1] & 31;
809 		else if (strlen(arg) == 1)
810 			value = (u_char) arg[0];
811 		else if (strcmp(arg, "none") == 0)
812 			value = SSH_ESCAPECHAR_NONE;
813 		else {
814 			fatal("%.200s line %d: Bad escape character.",
815 			    filename, linenum);
816 			/* NOTREACHED */
817 			value = 0;	/* Avoid compiler warning. */
818 		}
819 		if (*activep && *intptr == -1)
820 			*intptr = value;
821 		break;
822 
823 	case oServerAliveInterval:
824 		intptr = &options->server_alive_interval;
825 		goto parse_time;
826 
827 	case oServerAliveCountMax:
828 		intptr = &options->server_alive_count_max;
829 		goto parse_int;
830 
831 	case oHashKnownHosts:
832 		intptr = &options->hash_known_hosts;
833 		goto parse_flag;
834 
835 	case oDisableBanner:
836 		arg = strdelim(&s);
837 		if (get_yes_no_flag(&options->disable_banner, arg, filename,
838 		    linenum, *activep) == 1)
839 			break;
840 
841 		if (strcmp(arg, "in-exec-mode") == 0)
842 			options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE;
843 		else
844 			fatal("%.200s line %d: Bad yes/no/in-exec-mode "
845 			    "argument.", filename, linenum);
846 		break;
847 
848 	case oIgnoreIfUnknown:
849 		charptr = &options->ignore_if_unknown;
850 		goto parse_string;
851 
852 	case oUseOpenSSLEngine:
853 		intptr = &options->use_openssl_engine;
854 		goto parse_flag;
855 
856 	case oDeprecated:
857 		debug("%s line %d: Deprecated option \"%s\"",
858 		    filename, linenum, keyword);
859 		return 0;
860 
861 	default:
862 		fatal("process_config_line: Unimplemented opcode %d", opcode);
863 	}
864 
865 	/* Check that there is no garbage at end of line. */
866 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
867 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
868 		     filename, linenum, arg);
869 	}
870 	return 0;
871 }
872 
873 
874 /*
875  * Reads the config file and modifies the options accordingly.  Options
876  * should already be initialized before this call.  This never returns if
877  * there is an error.  If the file does not exist, this returns 0.
878  */
879 
880 int
881 read_config_file(const char *filename, const char *host, Options *options)
882 {
883 	FILE *f;
884 	char line[1024];
885 	int active, linenum;
886 
887 	/* Open the file. */
888 	f = fopen(filename, "r");
889 	if (!f)
890 		return 0;
891 
892 	debug("Reading configuration data %.200s", filename);
893 
894 	/*
895 	 * Mark that we are now processing the options.  This flag is turned
896 	 * on/off by Host specifications.
897 	 */
898 	active = 1;
899 	linenum = 0;
900 	while (fgets(line, sizeof(line), f)) {
901 		/* Update line number counter. */
902 		linenum++;
903 		process_config_line(options, host, line, filename, linenum, &active);
904 	}
905 	fclose(f);
906 	return 1;
907 }
908 
909 /*
910  * Initializes options to special values that indicate that they have not yet
911  * been set.  Read_config_file will only set options with this value. Options
912  * are processed in the following order: command line, user config file,
913  * system config file.  Last, fill_default_options is called.
914  */
915 
916 void
917 initialize_options(Options * options)
918 {
919 	memset(options, 'X', sizeof(*options));
920 	options->forward_agent = -1;
921 	options->forward_x11 = -1;
922 	options->forward_x11_trusted = -1;
923 	options->xauth_location = NULL;
924 	options->gateway_ports = -1;
925 	options->use_privileged_port = -1;
926 	options->rhosts_authentication = -1;
927 	options->rsa_authentication = -1;
928 	options->pubkey_authentication = -1;
929 	options->challenge_response_authentication = -1;
930 #ifdef GSSAPI
931         options->gss_keyex = -1;
932         options->gss_authentication = -1;
933         options->gss_deleg_creds = -1;
934 #ifdef GSI
935         options->gss_globus_deleg_limited_proxy = -1;
936 #endif /* GSI */
937 #endif /* GSSAPI */
938 
939 #if defined(KRB4) || defined(KRB5)
940 	options->kerberos_authentication = -1;
941 #endif
942 #if defined(AFS) || defined(KRB5)
943 	options->kerberos_tgt_passing = -1;
944 #endif
945 #ifdef AFS
946 	options->afs_token_passing = -1;
947 #endif
948 	options->password_authentication = -1;
949 	options->kbd_interactive_authentication = -1;
950 	options->kbd_interactive_devices = NULL;
951 	options->rhosts_rsa_authentication = -1;
952 	options->hostbased_authentication = -1;
953 	options->batch_mode = -1;
954 	options->check_host_ip = -1;
955 	options->strict_host_key_checking = -1;
956 	options->compression = -1;
957 	options->keepalives = -1;
958 	options->compression_level = -1;
959 	options->port = -1;
960 	options->connection_attempts = -1;
961 	options->connection_timeout = -1;
962 	options->number_of_password_prompts = -1;
963 	options->cipher = -1;
964 	options->ciphers = NULL;
965 	options->macs = NULL;
966 	options->hostkeyalgorithms = NULL;
967 	options->protocol = SSH_PROTO_UNKNOWN;
968 	options->num_identity_files = 0;
969 	options->hostname = NULL;
970 	options->host_key_alias = NULL;
971 	options->proxy_command = NULL;
972 	options->user = NULL;
973 	options->escape_char = -1;
974 	options->system_hostfile = NULL;
975 	options->user_hostfile = NULL;
976 	options->system_hostfile2 = NULL;
977 	options->user_hostfile2 = NULL;
978 	options->num_local_forwards = 0;
979 	options->num_remote_forwards = 0;
980 	options->clear_forwardings = -1;
981 	options->log_level = SYSLOG_LEVEL_NOT_SET;
982 	options->preferred_authentications = NULL;
983 	options->bind_address = NULL;
984 	options->smartcard_device = NULL;
985 	options->no_host_authentication_for_localhost = -1;
986 	options->rekey_limit = -1;
987 	options->fallback_to_rsh = -1;
988 	options->use_rsh = -1;
989 	options->server_alive_interval = -1;
990 	options->server_alive_count_max = -1;
991 	options->hash_known_hosts = -1;
992 	options->ignore_if_unknown = NULL;
993 	options->unknown_opts_num = 0;
994 	options->disable_banner = -1;
995 	options->use_openssl_engine = -1;
996 }
997 
998 /*
999  * Called after processing other sources of option data, this fills those
1000  * options for which no value has been specified with their default values.
1001  */
1002 
1003 void
1004 fill_default_options(Options * options)
1005 {
1006 	int len;
1007 
1008 	if (options->forward_agent == -1)
1009 		options->forward_agent = 0;
1010 	if (options->forward_x11 == -1)
1011 		options->forward_x11 = 0;
1012 	/*
1013 	 * Unlike OpenSSH, we keep backward compatibility for '-X' option
1014 	 * which means that X11 forwarding is trusted by default.
1015 	 */
1016 	if (options->forward_x11_trusted == -1)
1017 		options->forward_x11_trusted = 1;
1018 	if (options->xauth_location == NULL)
1019 		options->xauth_location = _PATH_XAUTH;
1020 	if (options->gateway_ports == -1)
1021 		options->gateway_ports = 0;
1022 	if (options->use_privileged_port == -1)
1023 		options->use_privileged_port = 0;
1024 	if (options->rhosts_authentication == -1)
1025 		options->rhosts_authentication = 0;
1026 	if (options->rsa_authentication == -1)
1027 		options->rsa_authentication = 1;
1028 	if (options->pubkey_authentication == -1)
1029 		options->pubkey_authentication = 1;
1030 	if (options->challenge_response_authentication == -1)
1031 		options->challenge_response_authentication = 1;
1032 #ifdef GSSAPI
1033 	if (options->gss_keyex == -1)
1034 		options->gss_keyex = 1;
1035 	if (options->gss_authentication == -1)
1036 		options->gss_authentication = 1;
1037 	if (options->gss_deleg_creds == -1)
1038 		options->gss_deleg_creds = 0;
1039 #ifdef GSI
1040 	if (options->gss_globus_deleg_limited_proxy == -1)
1041 		options->gss_globus_deleg_limited_proxy = 0;
1042 #endif /* GSI */
1043 #endif /* GSSAPI */
1044 #if defined(KRB4) || defined(KRB5)
1045 	if (options->kerberos_authentication == -1)
1046 		options->kerberos_authentication = 1;
1047 #endif
1048 #if defined(AFS) || defined(KRB5)
1049 	if (options->kerberos_tgt_passing == -1)
1050 		options->kerberos_tgt_passing = 1;
1051 #endif
1052 #ifdef AFS
1053 	if (options->afs_token_passing == -1)
1054 		options->afs_token_passing = 1;
1055 #endif
1056 	if (options->password_authentication == -1)
1057 		options->password_authentication = 1;
1058 	if (options->kbd_interactive_authentication == -1)
1059 		options->kbd_interactive_authentication = 1;
1060 	if (options->rhosts_rsa_authentication == -1)
1061 		options->rhosts_rsa_authentication = 0;
1062 	if (options->hostbased_authentication == -1)
1063 		options->hostbased_authentication = 0;
1064 	if (options->batch_mode == -1)
1065 		options->batch_mode = 0;
1066 	if (options->check_host_ip == -1)
1067 		options->check_host_ip = 1;
1068 	if (options->strict_host_key_checking == -1)
1069 		options->strict_host_key_checking = 2;	/* 2 is default */
1070 	if (options->compression == -1)
1071 		options->compression = 0;
1072 	if (options->keepalives == -1)
1073 		options->keepalives = 1;
1074 	if (options->compression_level == -1)
1075 		options->compression_level = 6;
1076 	if (options->port == -1)
1077 		options->port = 0;	/* Filled in ssh_connect. */
1078 	if (options->connection_attempts == -1)
1079 		options->connection_attempts = 1;
1080 	if (options->number_of_password_prompts == -1)
1081 		options->number_of_password_prompts = 3;
1082 	/* Selected in ssh_login(). */
1083 	if (options->cipher == -1)
1084 		options->cipher = SSH_CIPHER_NOT_SET;
1085 	/* options->ciphers, default set in myproposals.h */
1086 	/* options->macs, default set in myproposals.h */
1087 	/* options->hostkeyalgorithms, default set in myproposals.h */
1088 	if (options->protocol == SSH_PROTO_UNKNOWN)
1089 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
1090 	if (options->num_identity_files == 0) {
1091 		if (options->protocol & SSH_PROTO_1) {
1092 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1093 			options->identity_files[options->num_identity_files] =
1094 			    xmalloc(len);
1095 			snprintf(options->identity_files[options->num_identity_files++],
1096 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1097 		}
1098 		if (options->protocol & SSH_PROTO_2) {
1099 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1100 			options->identity_files[options->num_identity_files] =
1101 			    xmalloc(len);
1102 			snprintf(options->identity_files[options->num_identity_files++],
1103 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1104 
1105 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1106 			options->identity_files[options->num_identity_files] =
1107 			    xmalloc(len);
1108 			snprintf(options->identity_files[options->num_identity_files++],
1109 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1110 		}
1111 	}
1112 	if (options->escape_char == -1)
1113 		options->escape_char = '~';
1114 	if (options->system_hostfile == NULL)
1115 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1116 	if (options->user_hostfile == NULL)
1117 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1118 	if (options->system_hostfile2 == NULL)
1119 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1120 	if (options->user_hostfile2 == NULL)
1121 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1122 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1123 		options->log_level = SYSLOG_LEVEL_INFO;
1124 	if (options->clear_forwardings == 1)
1125 		clear_forwardings(options);
1126 	if (options->no_host_authentication_for_localhost == -1)
1127 		options->no_host_authentication_for_localhost = 0;
1128 	if (options->rekey_limit == -1)
1129 		options->rekey_limit = 0;
1130 	if (options->fallback_to_rsh == -1)
1131 		options->fallback_to_rsh = 0;
1132 	if (options->use_rsh == -1)
1133 		options->use_rsh = 0;
1134 	if (options->server_alive_interval == -1)
1135 		options->server_alive_interval = 0;
1136 	if (options->server_alive_count_max == -1)
1137 		options->server_alive_count_max = 3;
1138 	if (options->hash_known_hosts == -1)
1139 		options->hash_known_hosts = 0;
1140 	if (options->disable_banner == -1)
1141 		options->disable_banner = 0;
1142 	if (options->use_openssl_engine == -1)
1143 		options->use_openssl_engine = 1;
1144 	/* options->proxy_command should not be set by default */
1145 	/* options->user will be set in the main program if appropriate */
1146 	/* options->hostname will be set in the main program if appropriate */
1147 	/* options->host_key_alias should not be set by default */
1148 	/* options->preferred_authentications will be set in ssh */
1149 	/* options->ignore_if_unknown should not be set by default */
1150 }
1151 
1152 /*
1153  * Parses a string containing a port forwarding specification of one of the
1154  * two forms, short or long:
1155  *
1156  *	[listenhost:]listenport
1157  *	[listenhost:]listenport:connecthost:connectport
1158  *
1159  * short forwarding specification is used for dynamic port forwarding and for
1160  * port forwarding cancelation in process_cmdline(). The function returns number
1161  * of arguments parsed or zero on any error.
1162  */
1163 int
1164 parse_forward(int long_form, Forward *fwd, const char *fwdspec)
1165 {
1166 	int i;
1167 	char *p, *cp, *fwdarg[5];
1168 
1169 	memset(fwd, '\0', sizeof(*fwd));
1170 
1171 	cp = p = xstrdup(fwdspec);
1172 
1173 	/* skip leading spaces */
1174 	while (isspace(*cp))
1175 		cp++;
1176 
1177 	for (i = 0; i < 5; ++i)
1178 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1179 			break;
1180 
1181 	if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5))
1182 		goto fail_free;
1183 
1184 	switch (i) {
1185 	case 0:
1186 		goto fail_free;
1187 
1188 	case 1:
1189 		fwd->listen_host = NULL;
1190 		fwd->listen_port = a2port(fwdarg[0]);
1191 		break;
1192 
1193 	case 2:
1194 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1195 		fwd->listen_port = a2port(fwdarg[1]);
1196 		break;
1197 
1198 	case 3:
1199 		fwd->listen_host = NULL;
1200 		fwd->listen_port = a2port(fwdarg[0]);
1201 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1202 		fwd->connect_port = a2port(fwdarg[2]);
1203 		break;
1204 
1205 	case 4:
1206 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1207 		fwd->listen_port = a2port(fwdarg[1]);
1208 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1209 		fwd->connect_port = a2port(fwdarg[3]);
1210 		break;
1211 	}
1212 
1213 	if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2))
1214 		goto fail_free;
1215 
1216 	xfree(p);
1217 	return (i);
1218 
1219 fail_free:
1220 	if (p != NULL)
1221 		xfree(p);
1222 	if (fwd->connect_host != NULL)
1223 		xfree(fwd->connect_host);
1224 	if (fwd->listen_host != NULL)
1225 		xfree(fwd->listen_host);
1226 	return (0);
1227 }
1228 
1229 /*
1230  * Process previously stored unknown options. When this function is called we
1231  * already have IgnoreIfUnknown set so finally we can decide whether each
1232  * unknown option is to be ignored or not.
1233  */
1234 void
1235 process_unknown_options(Options *options)
1236 {
1237 	StoredOption *so;
1238 	int m, i, bad_options = 0;
1239 
1240 	/* if there is no unknown option we are done */
1241 	if (options->unknown_opts_num == 0)
1242 		return;
1243 
1244 	/*
1245 	 * Now go through the list of unknown options and report any one that
1246 	 * is not explicitly listed in IgnoreIfUnknown option. If at least one
1247 	 * such as that is found it's a show stopper.
1248 	 */
1249 	for (i = 0; i < options->unknown_opts_num; ++i) {
1250 		so = &options->unknown_opts[i];
1251 		if (options->ignore_if_unknown == NULL)
1252 			m = 0;
1253 		else
1254 			m = match_pattern_list(tolowercase(so->keyword),
1255 			    options->ignore_if_unknown,
1256 			    strlen(options->ignore_if_unknown), 1);
1257 		if (m == 1) {
1258 			debug("%s: line %d: ignoring unknown option: %s",
1259 			    so->filename, so->linenum, so->keyword);
1260 		}
1261 		else {
1262 			error("%s: line %d: unknown configuration option: %s",
1263 			    so->filename, so->linenum, so->keyword);
1264 			bad_options++;
1265 		}
1266 		xfree(so->keyword);
1267 		xfree(so->filename);
1268 	}
1269 
1270 	/* exit if we found at least one unignored unknown option */
1271 	if (bad_options > 0)
1272 		fatal("terminating, %d bad configuration option(s)",
1273 		    bad_options);
1274 }
1275