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