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