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