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