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