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