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