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