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