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