xref: /titanic_41/usr/src/cmd/ssh/libssh/common/readconf.c (revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e)
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 2004 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, oGatewayPorts, oRhostsAuthentication,
101 	oPasswordAuthentication, oRSAAuthentication,
102 	oChallengeResponseAuthentication, oXAuthLocation,
103 #if defined(KRB4) || defined(KRB5)
104 	oKerberosAuthentication,
105 #endif
106 #ifdef GSSAPI
107 	oGssKeyEx, oGssAuthentication, oGssDelegateCreds,
108 #ifdef GSI
109 	oGssGlobusDelegateLimitedCreds,
110 #endif /* GSI */
111 #endif /* GSSAPI */
112 #if defined(AFS) || defined(KRB5)
113 	oKerberosTgtPassing,
114 #endif
115 #ifdef AFS
116 	oAFSTokenPassing,
117 #endif
118 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
119 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
120 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
121 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
122 	oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
123 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
124 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
125 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
126 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
127 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
128 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
129 	oFallBackToRsh, oUseRsh,
130 	oDeprecated
131 } OpCodes;
132 
133 /* Textual representations of the tokens. */
134 
135 static struct {
136 	const char *name;
137 	OpCodes opcode;
138 } keywords[] = {
139 	{ "forwardagent", oForwardAgent },
140 	{ "forwardx11", oForwardX11 },
141 	{ "xauthlocation", oXAuthLocation },
142 	{ "gatewayports", oGatewayPorts },
143 	{ "useprivilegedport", oUsePrivilegedPort },
144 	{ "rhostsauthentication", oRhostsAuthentication },
145 	{ "passwordauthentication", oPasswordAuthentication },
146 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
147 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
148 	{ "rsaauthentication", oRSAAuthentication },
149 	{ "pubkeyauthentication", oPubkeyAuthentication },
150 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
151 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
152 	{ "hostbasedauthentication", oHostbasedAuthentication },
153 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
154 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
155 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
156 #if defined(KRB4) || defined(KRB5)
157 	{ "kerberosauthentication", oKerberosAuthentication },
158 #endif
159 #ifdef GSSAPI
160 	{ "gssapikeyexchange", oGssKeyEx },
161 	{ "gssapiauthentication", oGssAuthentication },
162 	{ "gssapidelegatecredentials", oGssDelegateCreds },
163 	{ "gsskeyex", oGssKeyEx },				/* alias */
164 	{ "gssauthentication", oGssAuthentication },		/* alias */
165 	{ "gssdelegatecreds", oGssDelegateCreds },		/* alias */
166 #ifdef GSI
167 	/* For backwards compatability with old 1.2.27 client code */
168 	{ "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
169 	{ "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
170 #endif /* GSI */
171 #endif /* GSSAPI */
172 #if defined(AFS) || defined(KRB5)
173 	{ "kerberostgtpassing", oKerberosTgtPassing },
174 #endif
175 #ifdef AFS
176 	{ "afstokenpassing", oAFSTokenPassing },
177 #endif
178 	{ "fallbacktorsh", oFallBackToRsh },
179 	{ "usersh", oUseRsh },
180 	{ "identityfile", oIdentityFile },
181 	{ "identityfile2", oIdentityFile },			/* alias */
182 	{ "hostname", oHostName },
183 	{ "hostkeyalias", oHostKeyAlias },
184 	{ "proxycommand", oProxyCommand },
185 	{ "port", oPort },
186 	{ "cipher", oCipher },
187 	{ "ciphers", oCiphers },
188 	{ "macs", oMacs },
189 	{ "protocol", oProtocol },
190 	{ "remoteforward", oRemoteForward },
191 	{ "localforward", oLocalForward },
192 	{ "user", oUser },
193 	{ "host", oHost },
194 	{ "escapechar", oEscapeChar },
195 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
196 	{ "userknownhostsfile", oUserKnownHostsFile },		/* obsolete */
197 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
198 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
199 	{ "connectionattempts", oConnectionAttempts },
200 	{ "batchmode", oBatchMode },
201 	{ "checkhostip", oCheckHostIP },
202 	{ "stricthostkeychecking", oStrictHostKeyChecking },
203 	{ "compression", oCompression },
204 	{ "compressionlevel", oCompressionLevel },
205 	{ "keepalive", oKeepAlives },
206 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
207 	{ "loglevel", oLogLevel },
208 	{ "dynamicforward", oDynamicForward },
209 	{ "preferredauthentications", oPreferredAuthentications },
210 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
211 	{ "bindaddress", oBindAddress },
212 	{ "smartcarddevice", oSmartcardDevice },
213 	{ "clearallforwardings", oClearAllForwardings },
214 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
215 	{ NULL, oBadOption }
216 };
217 
218 /*
219  * Adds a local TCP/IP port forward to options.  Never returns if there is an
220  * error.
221  */
222 
223 void
224 add_local_forward(Options *options, u_short port, const char *host,
225 		  u_short host_port)
226 {
227 	Forward *fwd;
228 #ifndef NO_IPPORT_RESERVED_CONCEPT
229 	extern uid_t original_real_uid;
230 	if (port < IPPORT_RESERVED && original_real_uid != 0)
231 		fatal("Privileged ports can only be forwarded by root.");
232 #endif
233 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
234 		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
235 	fwd = &options->local_forwards[options->num_local_forwards++];
236 	fwd->port = port;
237 	fwd->host = xstrdup(host);
238 	fwd->host_port = host_port;
239 }
240 
241 /*
242  * Adds a remote TCP/IP port forward to options.  Never returns if there is
243  * an error.
244  */
245 
246 void
247 add_remote_forward(Options *options, u_short port, const char *host,
248 		   u_short host_port)
249 {
250 	Forward *fwd;
251 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
252 		fatal("Too many remote forwards (max %d).",
253 		    SSH_MAX_FORWARDS_PER_DIRECTION);
254 	fwd = &options->remote_forwards[options->num_remote_forwards++];
255 	fwd->port = port;
256 	fwd->host = xstrdup(host);
257 	fwd->host_port = host_port;
258 }
259 
260 static void
261 clear_forwardings(Options *options)
262 {
263 	int i;
264 
265 	for (i = 0; i < options->num_local_forwards; i++)
266 		xfree(options->local_forwards[i].host);
267 	options->num_local_forwards = 0;
268 	for (i = 0; i < options->num_remote_forwards; i++)
269 		xfree(options->remote_forwards[i].host);
270 	options->num_remote_forwards = 0;
271 }
272 
273 /*
274  * Returns the number of the token pointed to by cp or oBadOption.
275  */
276 
277 static OpCodes
278 parse_token(const char *cp, const char *filename, int linenum)
279 {
280 	u_int i;
281 
282 	for (i = 0; keywords[i].name; i++)
283 		if (strcasecmp(cp, keywords[i].name) == 0)
284 			return keywords[i].opcode;
285 
286 	error("%s: line %d: Bad configuration option: %s",
287 	    filename, linenum, cp);
288 	return oBadOption;
289 }
290 
291 /*
292  * Processes a single option line as used in the configuration files. This
293  * only sets those values that have not already been set.
294  */
295 
296 int
297 process_config_line(Options *options, const char *host,
298 		    char *line, const char *filename, int linenum,
299 		    int *activep)
300 {
301 	char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
302 	int opcode, *intptr, value;
303 	u_short fwd_port, fwd_host_port;
304 	char sfwd_host_port[6];
305 
306 	s = line;
307 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
308 	keyword = strdelim(&s);
309 	/* Ignore leading whitespace. */
310 	if (*keyword == '\0')
311 		keyword = strdelim(&s);
312 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
313 		return 0;
314 
315 	opcode = parse_token(keyword, filename, linenum);
316 
317 	switch (opcode) {
318 	case oBadOption:
319 		/* don't panic, but count bad options */
320 		return -1;
321 		/* NOTREACHED */
322 	case oForwardAgent:
323 		intptr = &options->forward_agent;
324 parse_flag:
325 		arg = strdelim(&s);
326 		if (!arg || *arg == '\0')
327 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
328 		value = 0;	/* To avoid compiler warning... */
329 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
330 			value = 1;
331 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
332 			value = 0;
333 		else
334 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
335 		if (*activep && *intptr == -1)
336 			*intptr = value;
337 		break;
338 
339 	case oForwardX11:
340 		intptr = &options->forward_x11;
341 		goto parse_flag;
342 
343 	case oGatewayPorts:
344 		intptr = &options->gateway_ports;
345 		goto parse_flag;
346 
347 	case oUsePrivilegedPort:
348 		intptr = &options->use_privileged_port;
349 		goto parse_flag;
350 
351 	case oRhostsAuthentication:
352 		intptr = &options->rhosts_authentication;
353 		goto parse_flag;
354 
355 	case oPasswordAuthentication:
356 		intptr = &options->password_authentication;
357 		goto parse_flag;
358 
359 	case oKbdInteractiveAuthentication:
360 		intptr = &options->kbd_interactive_authentication;
361 		goto parse_flag;
362 
363 	case oKbdInteractiveDevices:
364 		charptr = &options->kbd_interactive_devices;
365 		goto parse_string;
366 
367 	case oPubkeyAuthentication:
368 		intptr = &options->pubkey_authentication;
369 		goto parse_flag;
370 
371 	case oRSAAuthentication:
372 		intptr = &options->rsa_authentication;
373 		goto parse_flag;
374 
375 	case oRhostsRSAAuthentication:
376 		intptr = &options->rhosts_rsa_authentication;
377 		goto parse_flag;
378 
379 	case oHostbasedAuthentication:
380 		intptr = &options->hostbased_authentication;
381 		goto parse_flag;
382 
383 	case oChallengeResponseAuthentication:
384 		intptr = &options->challenge_response_authentication;
385 		goto parse_flag;
386 #if defined(KRB4) || defined(KRB5)
387 	case oKerberosAuthentication:
388 		intptr = &options->kerberos_authentication;
389 		goto parse_flag;
390 #endif
391 #ifdef GSSAPI
392 	case oGssKeyEx:
393 		intptr = &options->gss_keyex;
394 		goto parse_flag;
395 
396 	case oGssAuthentication:
397 		intptr = &options->gss_authentication;
398 		goto parse_flag;
399 
400 	case oGssDelegateCreds:
401 		intptr = &options->gss_deleg_creds;
402 		goto parse_flag;
403 
404 #ifdef GSI
405 	case oGssGlobusDelegateLimitedCreds:
406 		intptr = &options->gss_globus_deleg_limited_proxy;
407 		goto parse_flag;
408 #endif /* GSI */
409 
410 #endif /* GSSAPI */
411 
412 #if defined(AFS) || defined(KRB5)
413 	case oKerberosTgtPassing:
414 		intptr = &options->kerberos_tgt_passing;
415 		goto parse_flag;
416 #endif
417 #ifdef AFS
418 	case oAFSTokenPassing:
419 		intptr = &options->afs_token_passing;
420 		goto parse_flag;
421 #endif
422 	case oFallBackToRsh:
423 		intptr = &options->fallback_to_rsh;
424 		goto parse_flag;
425 
426 	case oUseRsh:
427 		intptr = &options->use_rsh;
428 		goto parse_flag;
429 
430 	case oBatchMode:
431 		intptr = &options->batch_mode;
432 		goto parse_flag;
433 
434 	case oCheckHostIP:
435 		intptr = &options->check_host_ip;
436 		goto parse_flag;
437 
438 	case oStrictHostKeyChecking:
439 		intptr = &options->strict_host_key_checking;
440 		arg = strdelim(&s);
441 		if (!arg || *arg == '\0')
442 			fatal("%.200s line %d: Missing yes/no/ask argument.",
443 			    filename, linenum);
444 		value = 0;	/* To avoid compiler warning... */
445 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
446 			value = 1;
447 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
448 			value = 0;
449 		else if (strcmp(arg, "ask") == 0)
450 			value = 2;
451 		else
452 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
453 		if (*activep && *intptr == -1)
454 			*intptr = value;
455 		break;
456 
457 	case oCompression:
458 		intptr = &options->compression;
459 		goto parse_flag;
460 
461 	case oKeepAlives:
462 		intptr = &options->keepalives;
463 		goto parse_flag;
464 
465 	case oNoHostAuthenticationForLocalhost:
466 		intptr = &options->no_host_authentication_for_localhost;
467 		goto parse_flag;
468 
469 	case oNumberOfPasswordPrompts:
470 		intptr = &options->number_of_password_prompts;
471 		goto parse_int;
472 
473 	case oCompressionLevel:
474 		intptr = &options->compression_level;
475 		goto parse_int;
476 
477 	case oIdentityFile:
478 		arg = strdelim(&s);
479 		if (!arg || *arg == '\0')
480 			fatal("%.200s line %d: Missing argument.", filename, linenum);
481 		if (*activep) {
482 			intptr = &options->num_identity_files;
483 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
484 				fatal("%.200s line %d: Too many identity files specified (max %d).",
485 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
486 			charptr =  &options->identity_files[*intptr];
487 			*charptr = xstrdup(arg);
488 			*intptr = *intptr + 1;
489 		}
490 		break;
491 
492 	case oXAuthLocation:
493 		charptr=&options->xauth_location;
494 		goto parse_string;
495 
496 	case oUser:
497 		charptr = &options->user;
498 parse_string:
499 		arg = strdelim(&s);
500 		if (!arg || *arg == '\0')
501 			fatal("%.200s line %d: Missing argument.", filename, linenum);
502 		if (*activep && *charptr == NULL)
503 			*charptr = xstrdup(arg);
504 		break;
505 
506 	case oGlobalKnownHostsFile:
507 		charptr = &options->system_hostfile;
508 		goto parse_string;
509 
510 	case oUserKnownHostsFile:
511 		charptr = &options->user_hostfile;
512 		goto parse_string;
513 
514 	case oGlobalKnownHostsFile2:
515 		charptr = &options->system_hostfile2;
516 		goto parse_string;
517 
518 	case oUserKnownHostsFile2:
519 		charptr = &options->user_hostfile2;
520 		goto parse_string;
521 
522 	case oHostName:
523 		charptr = &options->hostname;
524 		goto parse_string;
525 
526 	case oHostKeyAlias:
527 		charptr = &options->host_key_alias;
528 		goto parse_string;
529 
530 	case oPreferredAuthentications:
531 		charptr = &options->preferred_authentications;
532 		goto parse_string;
533 
534 	case oBindAddress:
535 		charptr = &options->bind_address;
536 		goto parse_string;
537 
538 	case oSmartcardDevice:
539 		charptr = &options->smartcard_device;
540 		goto parse_string;
541 
542 	case oProxyCommand:
543 		charptr = &options->proxy_command;
544 		string = xstrdup("");
545 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
546 			string = xrealloc(string, strlen(string) + strlen(arg) + 2);
547 			strcat(string, " ");
548 			strcat(string, arg);
549 		}
550 		if (*activep && *charptr == NULL)
551 			*charptr = string;
552 		else
553 			xfree(string);
554 		return 0;
555 
556 	case oPort:
557 		intptr = &options->port;
558 parse_int:
559 		arg = strdelim(&s);
560 		if (!arg || *arg == '\0')
561 			fatal("%.200s line %d: Missing argument.", filename, linenum);
562 		if (arg[0] < '0' || arg[0] > '9')
563 			fatal("%.200s line %d: Bad number.", filename, linenum);
564 
565 		/* Octal, decimal, or hex format? */
566 		value = strtol(arg, &endofnumber, 0);
567 		if (arg == endofnumber)
568 			fatal("%.200s line %d: Bad number.", filename, linenum);
569 		if (*activep && *intptr == -1)
570 			*intptr = value;
571 		break;
572 
573 	case oConnectionAttempts:
574 		intptr = &options->connection_attempts;
575 		goto parse_int;
576 
577 	case oCipher:
578 		intptr = &options->cipher;
579 		arg = strdelim(&s);
580 		if (!arg || *arg == '\0')
581 			fatal("%.200s line %d: Missing argument.", filename, linenum);
582 		value = cipher_number(arg);
583 		if (value == -1)
584 			fatal("%.200s line %d: Bad cipher '%s'.",
585 			    filename, linenum, arg ? arg : "<NONE>");
586 		if (*activep && *intptr == -1)
587 			*intptr = value;
588 		break;
589 
590 	case oCiphers:
591 		arg = strdelim(&s);
592 		if (!arg || *arg == '\0')
593 			fatal("%.200s line %d: Missing argument.", filename, linenum);
594 		if (!ciphers_valid(arg))
595 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
596 			    filename, linenum, arg ? arg : "<NONE>");
597 		if (*activep && options->ciphers == NULL)
598 			options->ciphers = xstrdup(arg);
599 		break;
600 
601 	case oMacs:
602 		arg = strdelim(&s);
603 		if (!arg || *arg == '\0')
604 			fatal("%.200s line %d: Missing argument.", filename, linenum);
605 		if (!mac_valid(arg))
606 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
607 			    filename, linenum, arg ? arg : "<NONE>");
608 		if (*activep && options->macs == NULL)
609 			options->macs = xstrdup(arg);
610 		break;
611 
612 	case oHostKeyAlgorithms:
613 		arg = strdelim(&s);
614 		if (!arg || *arg == '\0')
615 			fatal("%.200s line %d: Missing argument.", filename, linenum);
616 		if (!key_names_valid2(arg))
617 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
618 			    filename, linenum, arg ? arg : "<NONE>");
619 		if (*activep && options->hostkeyalgorithms == NULL)
620 			options->hostkeyalgorithms = xstrdup(arg);
621 		break;
622 
623 	case oProtocol:
624 		intptr = &options->protocol;
625 		arg = strdelim(&s);
626 		if (!arg || *arg == '\0')
627 			fatal("%.200s line %d: Missing argument.", filename, linenum);
628 		value = proto_spec(arg);
629 		if (value == SSH_PROTO_UNKNOWN)
630 			fatal("%.200s line %d: Bad protocol spec '%s'.",
631 			    filename, linenum, arg ? arg : "<NONE>");
632 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
633 			*intptr = value;
634 		break;
635 
636 	case oLogLevel:
637 		intptr = (int *) &options->log_level;
638 		arg = strdelim(&s);
639 		value = log_level_number(arg);
640 		if (value == SYSLOG_LEVEL_NOT_SET)
641 			fatal("%.200s line %d: unsupported log level '%s'",
642 			    filename, linenum, arg ? arg : "<NONE>");
643 		if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
644 			*intptr = (LogLevel) value;
645 		break;
646 
647 	case oLocalForward:
648 	case oRemoteForward:
649 		arg = strdelim(&s);
650 		if (!arg || *arg == '\0')
651 			fatal("%.200s line %d: Missing port argument.",
652 			    filename, linenum);
653 		if ((fwd_port = a2port(arg)) == 0)
654 			fatal("%.200s line %d: Bad listen port.",
655 			    filename, linenum);
656 		arg = strdelim(&s);
657 		if (!arg || *arg == '\0')
658 			fatal("%.200s line %d: Missing second argument.",
659 			    filename, linenum);
660 		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
661 		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
662 			fatal("%.200s line %d: Bad forwarding specification.",
663 			    filename, linenum);
664 		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
665 			fatal("%.200s line %d: Bad forwarding port.",
666 			    filename, linenum);
667 		if (*activep) {
668 			if (opcode == oLocalForward)
669 				add_local_forward(options, fwd_port, buf,
670 				    fwd_host_port);
671 			else if (opcode == oRemoteForward)
672 				add_remote_forward(options, fwd_port, buf,
673 				    fwd_host_port);
674 		}
675 		break;
676 
677 	case oDynamicForward:
678 		arg = strdelim(&s);
679 		if (!arg || *arg == '\0')
680 			fatal("%.200s line %d: Missing port argument.",
681 			    filename, linenum);
682 		fwd_port = a2port(arg);
683 		if (fwd_port == 0)
684 			fatal("%.200s line %d: Badly formatted port number.",
685 			    filename, linenum);
686 		if (*activep)
687 			add_local_forward(options, fwd_port, "socks4", 0);
688 		break;
689 
690 	case oClearAllForwardings:
691 		intptr = &options->clear_forwardings;
692 		goto parse_flag;
693 
694 	case oHost:
695 		*activep = 0;
696 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
697 			if (match_pattern(host, arg)) {
698 				debug("Applying options for %.100s", arg);
699 				*activep = 1;
700 				break;
701 			}
702 		/* Avoid garbage check below, as strdelim is done. */
703 		return 0;
704 
705 	case oEscapeChar:
706 		intptr = &options->escape_char;
707 		arg = strdelim(&s);
708 		if (!arg || *arg == '\0')
709 			fatal("%.200s line %d: Missing argument.", filename, linenum);
710 		if (arg[0] == '^' && arg[2] == 0 &&
711 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
712 			value = (u_char) arg[1] & 31;
713 		else if (strlen(arg) == 1)
714 			value = (u_char) arg[0];
715 		else if (strcmp(arg, "none") == 0)
716 			value = SSH_ESCAPECHAR_NONE;
717 		else {
718 			fatal("%.200s line %d: Bad escape character.",
719 			    filename, linenum);
720 			/* NOTREACHED */
721 			value = 0;	/* Avoid compiler warning. */
722 		}
723 		if (*activep && *intptr == -1)
724 			*intptr = value;
725 		break;
726 
727 	case oDeprecated:
728 		debug("%s line %d: Deprecated option \"%s\"",
729 		    filename, linenum, keyword);
730 		return 0;
731 
732 	default:
733 		fatal("process_config_line: Unimplemented opcode %d", opcode);
734 	}
735 
736 	/* Check that there is no garbage at end of line. */
737 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
738 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
739 		     filename, linenum, arg);
740 	}
741 	return 0;
742 }
743 
744 
745 /*
746  * Reads the config file and modifies the options accordingly.  Options
747  * should already be initialized before this call.  This never returns if
748  * there is an error.  If the file does not exist, this returns 0.
749  */
750 
751 int
752 read_config_file(const char *filename, const char *host, Options *options)
753 {
754 	FILE *f;
755 	char line[1024];
756 	int active, linenum;
757 	int bad_options = 0;
758 
759 	/* Open the file. */
760 	f = fopen(filename, "r");
761 	if (!f)
762 		return 0;
763 
764 	debug("Reading configuration data %.200s", filename);
765 
766 	/*
767 	 * Mark that we are now processing the options.  This flag is turned
768 	 * on/off by Host specifications.
769 	 */
770 	active = 1;
771 	linenum = 0;
772 	while (fgets(line, sizeof(line), f)) {
773 		/* Update line number counter. */
774 		linenum++;
775 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
776 			bad_options++;
777 	}
778 	fclose(f);
779 	if (bad_options > 0)
780 		fatal("%s: terminating, %d bad configuration options",
781 		    filename, bad_options);
782 	return 1;
783 }
784 
785 /*
786  * Initializes options to special values that indicate that they have not yet
787  * been set.  Read_config_file will only set options with this value. Options
788  * are processed in the following order: command line, user config file,
789  * system config file.  Last, fill_default_options is called.
790  */
791 
792 void
793 initialize_options(Options * options)
794 {
795 	memset(options, 'X', sizeof(*options));
796 	options->forward_agent = -1;
797 	options->forward_x11 = -1;
798 	options->xauth_location = NULL;
799 	options->gateway_ports = -1;
800 	options->use_privileged_port = -1;
801 	options->rhosts_authentication = -1;
802 	options->rsa_authentication = -1;
803 	options->pubkey_authentication = -1;
804 	options->challenge_response_authentication = -1;
805 #ifdef GSSAPI
806         options->gss_keyex = -1;
807         options->gss_authentication = -1;
808         options->gss_deleg_creds = -1;
809 #ifdef GSI
810         options->gss_globus_deleg_limited_proxy = -1;
811 #endif /* GSI */
812 #endif /* GSSAPI */
813 
814 #if defined(KRB4) || defined(KRB5)
815 	options->kerberos_authentication = -1;
816 #endif
817 #if defined(AFS) || defined(KRB5)
818 	options->kerberos_tgt_passing = -1;
819 #endif
820 #ifdef AFS
821 	options->afs_token_passing = -1;
822 #endif
823 	options->password_authentication = -1;
824 	options->kbd_interactive_authentication = -1;
825 	options->kbd_interactive_devices = NULL;
826 	options->rhosts_rsa_authentication = -1;
827 	options->hostbased_authentication = -1;
828 	options->batch_mode = -1;
829 	options->check_host_ip = -1;
830 	options->strict_host_key_checking = -1;
831 	options->compression = -1;
832 	options->keepalives = -1;
833 	options->compression_level = -1;
834 	options->port = -1;
835 	options->connection_attempts = -1;
836 	options->number_of_password_prompts = -1;
837 	options->cipher = -1;
838 	options->ciphers = NULL;
839 	options->macs = NULL;
840 	options->hostkeyalgorithms = NULL;
841 	options->protocol = SSH_PROTO_UNKNOWN;
842 	options->num_identity_files = 0;
843 	options->hostname = NULL;
844 	options->host_key_alias = NULL;
845 	options->proxy_command = NULL;
846 	options->user = NULL;
847 	options->escape_char = -1;
848 	options->system_hostfile = NULL;
849 	options->user_hostfile = NULL;
850 	options->system_hostfile2 = NULL;
851 	options->user_hostfile2 = NULL;
852 	options->num_local_forwards = 0;
853 	options->num_remote_forwards = 0;
854 	options->clear_forwardings = -1;
855 	options->log_level = SYSLOG_LEVEL_NOT_SET;
856 	options->preferred_authentications = NULL;
857 	options->bind_address = NULL;
858 	options->smartcard_device = NULL;
859 	options->no_host_authentication_for_localhost = - 1;
860 	options->fallback_to_rsh = -1;
861 	options->use_rsh = -1;
862 }
863 
864 /*
865  * Called after processing other sources of option data, this fills those
866  * options for which no value has been specified with their default values.
867  */
868 
869 void
870 fill_default_options(Options * options)
871 {
872 	int len;
873 
874 	if (options->forward_agent == -1)
875 		options->forward_agent = 0;
876 	if (options->forward_x11 == -1)
877 		options->forward_x11 = 0;
878 	if (options->xauth_location == NULL)
879 		options->xauth_location = _PATH_XAUTH;
880 	if (options->gateway_ports == -1)
881 		options->gateway_ports = 0;
882 	if (options->use_privileged_port == -1)
883 		options->use_privileged_port = 0;
884 	if (options->rhosts_authentication == -1)
885 		options->rhosts_authentication = 0;
886 	if (options->rsa_authentication == -1)
887 		options->rsa_authentication = 1;
888 	if (options->pubkey_authentication == -1)
889 		options->pubkey_authentication = 1;
890 	if (options->challenge_response_authentication == -1)
891 		options->challenge_response_authentication = 1;
892 #ifdef GSSAPI
893 	if (options->gss_keyex == -1)
894 		options->gss_keyex = 1;
895 	if (options->gss_authentication == -1)
896 		options->gss_authentication = 1;
897 	if (options->gss_deleg_creds == -1)
898 		options->gss_deleg_creds = 0;
899 #ifdef GSI
900 	if (options->gss_globus_deleg_limited_proxy == -1)
901 		options->gss_globus_deleg_limited_proxy = 0;
902 #endif /* GSI */
903 #endif /* GSSAPI */
904 #if defined(KRB4) || defined(KRB5)
905 	if (options->kerberos_authentication == -1)
906 		options->kerberos_authentication = 1;
907 #endif
908 #if defined(AFS) || defined(KRB5)
909 	if (options->kerberos_tgt_passing == -1)
910 		options->kerberos_tgt_passing = 1;
911 #endif
912 #ifdef AFS
913 	if (options->afs_token_passing == -1)
914 		options->afs_token_passing = 1;
915 #endif
916 	if (options->password_authentication == -1)
917 		options->password_authentication = 1;
918 	if (options->kbd_interactive_authentication == -1)
919 		options->kbd_interactive_authentication = 1;
920 	if (options->rhosts_rsa_authentication == -1)
921 		options->rhosts_rsa_authentication = 0;
922 	if (options->hostbased_authentication == -1)
923 		options->hostbased_authentication = 0;
924 	if (options->batch_mode == -1)
925 		options->batch_mode = 0;
926 	if (options->check_host_ip == -1)
927 		options->check_host_ip = 1;
928 	if (options->strict_host_key_checking == -1)
929 		options->strict_host_key_checking = 2;	/* 2 is default */
930 	if (options->compression == -1)
931 		options->compression = 0;
932 	if (options->keepalives == -1)
933 		options->keepalives = 1;
934 	if (options->compression_level == -1)
935 		options->compression_level = 6;
936 	if (options->port == -1)
937 		options->port = 0;	/* Filled in ssh_connect. */
938 	if (options->connection_attempts == -1)
939 		options->connection_attempts = 1;
940 	if (options->number_of_password_prompts == -1)
941 		options->number_of_password_prompts = 3;
942 	/* Selected in ssh_login(). */
943 	if (options->cipher == -1)
944 		options->cipher = SSH_CIPHER_NOT_SET;
945 	/* options->ciphers, default set in myproposals.h */
946 	/* options->macs, default set in myproposals.h */
947 	/* options->hostkeyalgorithms, default set in myproposals.h */
948 	if (options->protocol == SSH_PROTO_UNKNOWN)
949 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
950 	if (options->num_identity_files == 0) {
951 		if (options->protocol & SSH_PROTO_1) {
952 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
953 			options->identity_files[options->num_identity_files] =
954 			    xmalloc(len);
955 			snprintf(options->identity_files[options->num_identity_files++],
956 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
957 		}
958 		if (options->protocol & SSH_PROTO_2) {
959 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
960 			options->identity_files[options->num_identity_files] =
961 			    xmalloc(len);
962 			snprintf(options->identity_files[options->num_identity_files++],
963 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
964 
965 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
966 			options->identity_files[options->num_identity_files] =
967 			    xmalloc(len);
968 			snprintf(options->identity_files[options->num_identity_files++],
969 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
970 		}
971 	}
972 	if (options->escape_char == -1)
973 		options->escape_char = '~';
974 	if (options->system_hostfile == NULL)
975 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
976 	if (options->user_hostfile == NULL)
977 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
978 	if (options->system_hostfile2 == NULL)
979 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
980 	if (options->user_hostfile2 == NULL)
981 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
982 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
983 		options->log_level = SYSLOG_LEVEL_INFO;
984 	if (options->clear_forwardings == 1)
985 		clear_forwardings(options);
986 	if (options->no_host_authentication_for_localhost == - 1)
987 		options->no_host_authentication_for_localhost = 0;
988 	if (options->fallback_to_rsh == - 1)
989 		options->fallback_to_rsh = 0;
990 	if (options->use_rsh == - 1)
991 		options->use_rsh = 0;
992 	/* options->proxy_command should not be set by default */
993 	/* options->user will be set in the main program if appropriate */
994 	/* options->hostname will be set in the main program if appropriate */
995 	/* options->host_key_alias should not be set by default */
996 	/* options->preferred_authentications will be set in ssh */
997 }
998