blob: 99023d136b20bed0b1b83bb3c33fca9a779887aa [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 *
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 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100015
16#include "includes.h"
Damien Miller98c7ad62000-03-09 21:27:49 +110017RCSID("$Id: readconf.c,v 1.8 2000/03/09 10:27:51 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100018
19#include "ssh.h"
20#include "cipher.h"
21#include "readconf.h"
22#include "xmalloc.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
Damien Miller95def091999-11-25 00:26:21 +110089typedef enum {
90 oBadOption,
91 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
92 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
93 oSkeyAuthentication,
Damien Millerd4a8b7e1999-10-27 13:42:43 +100094#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +110095 oKerberosAuthentication,
Damien Millerd4a8b7e1999-10-27 13:42:43 +100096#endif /* KRB4 */
97#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +110098 oKerberosTgtPassing, oAFSTokenPassing,
Damien Millerd4a8b7e1999-10-27 13:42:43 +100099#endif
Damien Miller95def091999-11-25 00:26:21 +1100100 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
101 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
102 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
103 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
104 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
105 oUsePrivilegedPort, oLogLevel
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000106} OpCodes;
107
108/* Textual representations of the tokens. */
109
Damien Miller95def091999-11-25 00:26:21 +1100110static struct {
111 const char *name;
112 OpCodes opcode;
113} keywords[] = {
114 { "forwardagent", oForwardAgent },
115 { "forwardx11", oForwardX11 },
116 { "gatewayports", oGatewayPorts },
117 { "useprivilegedport", oUsePrivilegedPort },
118 { "rhostsauthentication", oRhostsAuthentication },
119 { "passwordauthentication", oPasswordAuthentication },
120 { "rsaauthentication", oRSAAuthentication },
121 { "skeyauthentication", oSkeyAuthentication },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000122#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100123 { "kerberosauthentication", oKerberosAuthentication },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000124#endif /* KRB4 */
125#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100126 { "kerberostgtpassing", oKerberosTgtPassing },
127 { "afstokenpassing", oAFSTokenPassing },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000128#endif
Damien Miller95def091999-11-25 00:26:21 +1100129 { "fallbacktorsh", oFallBackToRsh },
130 { "usersh", oUseRsh },
131 { "identityfile", oIdentityFile },
132 { "hostname", oHostName },
133 { "proxycommand", oProxyCommand },
134 { "port", oPort },
135 { "cipher", oCipher },
136 { "remoteforward", oRemoteForward },
137 { "localforward", oLocalForward },
138 { "user", oUser },
139 { "host", oHost },
140 { "escapechar", oEscapeChar },
141 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
142 { "globalknownhostsfile", oGlobalKnownHostsFile },
143 { "userknownhostsfile", oUserKnownHostsFile },
144 { "connectionattempts", oConnectionAttempts },
145 { "batchmode", oBatchMode },
146 { "checkhostip", oCheckHostIP },
147 { "stricthostkeychecking", oStrictHostKeyChecking },
148 { "compression", oCompression },
149 { "compressionlevel", oCompressionLevel },
150 { "keepalive", oKeepAlives },
151 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
152 { "tisauthentication", oTISAuthentication },
153 { "loglevel", oLogLevel },
154 { NULL, 0 }
Damien Miller5ce662a1999-11-11 17:57:39 +1100155};
156
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000157/* Characters considered whitespace in strtok calls. */
158#define WHITESPACE " \t\r\n"
159
160
Damien Miller5428f641999-11-25 11:54:57 +1100161/*
162 * Adds a local TCP/IP port forward to options. Never returns if there is an
163 * error.
164 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000165
Damien Miller95def091999-11-25 00:26:21 +1100166void
Damien Milleraae6c611999-12-06 11:47:28 +1100167add_local_forward(Options *options, u_short port, const char *host,
168 u_short host_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000169{
Damien Miller95def091999-11-25 00:26:21 +1100170 Forward *fwd;
171 extern uid_t original_real_uid;
Damien Miller95def091999-11-25 00:26:21 +1100172 if (port < IPPORT_RESERVED && original_real_uid != 0)
173 fatal("Privileged ports can only be forwarded by root.\n");
174 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
175 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
176 fwd = &options->local_forwards[options->num_local_forwards++];
177 fwd->port = port;
178 fwd->host = xstrdup(host);
179 fwd->host_port = host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000180}
181
Damien Miller5428f641999-11-25 11:54:57 +1100182/*
183 * Adds a remote TCP/IP port forward to options. Never returns if there is
184 * an error.
185 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000186
Damien Miller95def091999-11-25 00:26:21 +1100187void
Damien Milleraae6c611999-12-06 11:47:28 +1100188add_remote_forward(Options *options, u_short port, const char *host,
189 u_short host_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000190{
Damien Miller95def091999-11-25 00:26:21 +1100191 Forward *fwd;
192 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
193 fatal("Too many remote forwards (max %d).",
194 SSH_MAX_FORWARDS_PER_DIRECTION);
195 fwd = &options->remote_forwards[options->num_remote_forwards++];
196 fwd->port = port;
197 fwd->host = xstrdup(host);
198 fwd->host_port = host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000199}
200
Damien Miller5428f641999-11-25 11:54:57 +1100201/*
202 * Returns the number of the token pointed to by cp of length len. Never
203 * returns if the token is not known.
204 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000205
Damien Miller95def091999-11-25 00:26:21 +1100206static OpCodes
207parse_token(const char *cp, const char *filename, int linenum)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000208{
Damien Miller95def091999-11-25 00:26:21 +1100209 unsigned int i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000210
Damien Miller95def091999-11-25 00:26:21 +1100211 for (i = 0; keywords[i].name; i++)
Damien Miller5428f641999-11-25 11:54:57 +1100212 if (strcasecmp(cp, keywords[i].name) == 0)
Damien Miller95def091999-11-25 00:26:21 +1100213 return keywords[i].opcode;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000214
Damien Miller95def091999-11-25 00:26:21 +1100215 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
216 filename, linenum, cp);
217 return oBadOption;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000218}
219
Damien Miller5428f641999-11-25 11:54:57 +1100220/*
221 * Processes a single option line as used in the configuration files. This
222 * only sets those values that have not already been set.
223 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000224
Damien Miller2ccf6611999-11-15 15:25:10 +1100225int
226process_config_line(Options *options, const char *host,
Damien Miller95def091999-11-25 00:26:21 +1100227 char *line, const char *filename, int linenum,
228 int *activep)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000229{
Damien Miller5428f641999-11-25 11:54:57 +1100230 char buf[256], *cp, *string, **charptr, *cp2;
Damien Milleraae6c611999-12-06 11:47:28 +1100231 int opcode, *intptr, value;
232 u_short fwd_port, fwd_host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000233
Damien Miller95def091999-11-25 00:26:21 +1100234 /* Skip leading whitespace. */
235 cp = line + strspn(line, WHITESPACE);
236 if (!*cp || *cp == '\n' || *cp == '#')
237 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000238
Damien Miller5428f641999-11-25 11:54:57 +1100239 /* Get the keyword. (Each line is supposed to begin with a keyword). */
Damien Miller95def091999-11-25 00:26:21 +1100240 cp = strtok(cp, WHITESPACE);
Damien Miller95def091999-11-25 00:26:21 +1100241 opcode = parse_token(cp, filename, linenum);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000242
Damien Miller95def091999-11-25 00:26:21 +1100243 switch (opcode) {
244 case oBadOption:
Damien Miller5428f641999-11-25 11:54:57 +1100245 /* don't panic, but count bad options */
246 return -1;
Damien Miller95def091999-11-25 00:26:21 +1100247 /* NOTREACHED */
248 case oForwardAgent:
249 intptr = &options->forward_agent;
250parse_flag:
251 cp = strtok(NULL, WHITESPACE);
252 if (!cp)
253 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
254 value = 0; /* To avoid compiler warning... */
255 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
256 value = 1;
257 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
258 value = 0;
259 else
260 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
261 if (*activep && *intptr == -1)
262 *intptr = value;
263 break;
264
265 case oForwardX11:
266 intptr = &options->forward_x11;
267 goto parse_flag;
268
269 case oGatewayPorts:
270 intptr = &options->gateway_ports;
271 goto parse_flag;
272
273 case oUsePrivilegedPort:
274 intptr = &options->use_privileged_port;
275 goto parse_flag;
276
277 case oRhostsAuthentication:
278 intptr = &options->rhosts_authentication;
279 goto parse_flag;
280
281 case oPasswordAuthentication:
282 intptr = &options->password_authentication;
283 goto parse_flag;
284
285 case oRSAAuthentication:
286 intptr = &options->rsa_authentication;
287 goto parse_flag;
288
289 case oRhostsRSAAuthentication:
290 intptr = &options->rhosts_rsa_authentication;
291 goto parse_flag;
292
293 case oTISAuthentication:
294 /* fallthrough, there is no difference on the client side */
295 case oSkeyAuthentication:
296 intptr = &options->skey_authentication;
297 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000298
299#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100300 case oKerberosAuthentication:
301 intptr = &options->kerberos_authentication;
302 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000303#endif /* KRB4 */
304
305#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100306 case oKerberosTgtPassing:
307 intptr = &options->kerberos_tgt_passing;
308 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000309
Damien Miller95def091999-11-25 00:26:21 +1100310 case oAFSTokenPassing:
311 intptr = &options->afs_token_passing;
312 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000313#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000314
Damien Miller95def091999-11-25 00:26:21 +1100315 case oFallBackToRsh:
316 intptr = &options->fallback_to_rsh;
317 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000318
Damien Miller95def091999-11-25 00:26:21 +1100319 case oUseRsh:
320 intptr = &options->use_rsh;
321 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000322
Damien Miller95def091999-11-25 00:26:21 +1100323 case oBatchMode:
324 intptr = &options->batch_mode;
325 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000326
Damien Miller95def091999-11-25 00:26:21 +1100327 case oCheckHostIP:
328 intptr = &options->check_host_ip;
329 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000330
Damien Miller95def091999-11-25 00:26:21 +1100331 case oStrictHostKeyChecking:
332 intptr = &options->strict_host_key_checking;
333 cp = strtok(NULL, WHITESPACE);
334 if (!cp)
335 fatal("%.200s line %d: Missing yes/no argument.",
336 filename, linenum);
337 value = 0; /* To avoid compiler warning... */
338 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
339 value = 1;
340 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
341 value = 0;
342 else if (strcmp(cp, "ask") == 0)
343 value = 2;
344 else
345 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
346 if (*activep && *intptr == -1)
347 *intptr = value;
348 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000349
Damien Miller95def091999-11-25 00:26:21 +1100350 case oCompression:
351 intptr = &options->compression;
352 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000353
Damien Miller95def091999-11-25 00:26:21 +1100354 case oKeepAlives:
355 intptr = &options->keepalives;
356 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000357
Damien Miller95def091999-11-25 00:26:21 +1100358 case oNumberOfPasswordPrompts:
359 intptr = &options->number_of_password_prompts;
360 goto parse_int;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000361
Damien Miller95def091999-11-25 00:26:21 +1100362 case oCompressionLevel:
363 intptr = &options->compression_level;
364 goto parse_int;
365
366 case oIdentityFile:
367 cp = strtok(NULL, WHITESPACE);
368 if (!cp)
369 fatal("%.200s line %d: Missing argument.", filename, linenum);
370 if (*activep) {
371 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
372 fatal("%.200s line %d: Too many identity files specified (max %d).",
373 filename, linenum, SSH_MAX_IDENTITY_FILES);
374 options->identity_files[options->num_identity_files++] = xstrdup(cp);
375 }
376 break;
377
378 case oUser:
379 charptr = &options->user;
380parse_string:
381 cp = strtok(NULL, WHITESPACE);
382 if (!cp)
383 fatal("%.200s line %d: Missing argument.", filename, linenum);
384 if (*activep && *charptr == NULL)
385 *charptr = xstrdup(cp);
386 break;
387
388 case oGlobalKnownHostsFile:
389 charptr = &options->system_hostfile;
390 goto parse_string;
391
392 case oUserKnownHostsFile:
393 charptr = &options->user_hostfile;
394 goto parse_string;
395
396 case oHostName:
397 charptr = &options->hostname;
398 goto parse_string;
399
400 case oProxyCommand:
401 charptr = &options->proxy_command;
402 string = xstrdup("");
403 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
404 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
405 strcat(string, " ");
406 strcat(string, cp);
407 }
408 if (*activep && *charptr == NULL)
409 *charptr = string;
410 else
411 xfree(string);
412 return 0;
413
414 case oPort:
415 intptr = &options->port;
416parse_int:
417 cp = strtok(NULL, WHITESPACE);
418 if (!cp)
419 fatal("%.200s line %d: Missing argument.", filename, linenum);
420 if (cp[0] < '0' || cp[0] > '9')
421 fatal("%.200s line %d: Bad number.", filename, linenum);
Damien Miller5428f641999-11-25 11:54:57 +1100422
423 /* Octal, decimal, or hex format? */
424 value = strtol(cp, &cp2, 0);
425 if (cp == cp2)
426 fatal("%.200s line %d: Bad number.", filename, linenum);
Damien Miller95def091999-11-25 00:26:21 +1100427 if (*activep && *intptr == -1)
428 *intptr = value;
429 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000430
Damien Miller95def091999-11-25 00:26:21 +1100431 case oConnectionAttempts:
432 intptr = &options->connection_attempts;
433 goto parse_int;
Damien Miller5ce662a1999-11-11 17:57:39 +1100434
Damien Miller95def091999-11-25 00:26:21 +1100435 case oCipher:
436 intptr = &options->cipher;
437 cp = strtok(NULL, WHITESPACE);
438 value = cipher_number(cp);
439 if (value == -1)
440 fatal("%.200s line %d: Bad cipher '%s'.",
441 filename, linenum, cp ? cp : "<NONE>");
442 if (*activep && *intptr == -1)
443 *intptr = value;
444 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000445
Damien Miller95def091999-11-25 00:26:21 +1100446 case oLogLevel:
447 intptr = (int *) &options->log_level;
448 cp = strtok(NULL, WHITESPACE);
449 value = log_level_number(cp);
450 if (value == (LogLevel) - 1)
451 fatal("%.200s line %d: unsupported log level '%s'\n",
452 filename, linenum, cp ? cp : "<NONE>");
453 if (*activep && (LogLevel) * intptr == -1)
454 *intptr = (LogLevel) value;
455 break;
456
457 case oRemoteForward:
458 cp = strtok(NULL, WHITESPACE);
459 if (!cp)
460 fatal("%.200s line %d: Missing argument.", filename, linenum);
461 if (cp[0] < '0' || cp[0] > '9')
462 fatal("%.200s line %d: Badly formatted port number.",
463 filename, linenum);
464 fwd_port = atoi(cp);
465 cp = strtok(NULL, WHITESPACE);
466 if (!cp)
467 fatal("%.200s line %d: Missing second argument.",
468 filename, linenum);
Damien Milleraae6c611999-12-06 11:47:28 +1100469 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
Damien Miller95def091999-11-25 00:26:21 +1100470 fatal("%.200s line %d: Badly formatted host:port.",
471 filename, linenum);
472 if (*activep)
473 add_remote_forward(options, fwd_port, buf, fwd_host_port);
474 break;
475
476 case oLocalForward:
477 cp = strtok(NULL, WHITESPACE);
478 if (!cp)
479 fatal("%.200s line %d: Missing argument.", filename, linenum);
480 if (cp[0] < '0' || cp[0] > '9')
481 fatal("%.200s line %d: Badly formatted port number.",
482 filename, linenum);
483 fwd_port = atoi(cp);
484 cp = strtok(NULL, WHITESPACE);
485 if (!cp)
486 fatal("%.200s line %d: Missing second argument.",
487 filename, linenum);
Damien Milleraae6c611999-12-06 11:47:28 +1100488 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
Damien Miller95def091999-11-25 00:26:21 +1100489 fatal("%.200s line %d: Badly formatted host:port.",
490 filename, linenum);
491 if (*activep)
492 add_local_forward(options, fwd_port, buf, fwd_host_port);
493 break;
494
495 case oHost:
496 *activep = 0;
497 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
498 if (match_pattern(host, cp)) {
499 debug("Applying options for %.100s", cp);
500 *activep = 1;
501 break;
502 }
Damien Miller5428f641999-11-25 11:54:57 +1100503 /* Avoid garbage check below, as strtok already returned NULL. */
Damien Miller95def091999-11-25 00:26:21 +1100504 return 0;
505
506 case oEscapeChar:
507 intptr = &options->escape_char;
508 cp = strtok(NULL, WHITESPACE);
509 if (!cp)
510 fatal("%.200s line %d: Missing argument.", filename, linenum);
511 if (cp[0] == '^' && cp[2] == 0 &&
512 (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
513 value = (unsigned char) cp[1] & 31;
514 else if (strlen(cp) == 1)
515 value = (unsigned char) cp[0];
516 else if (strcmp(cp, "none") == 0)
517 value = -2;
518 else {
519 fatal("%.200s line %d: Bad escape character.",
520 filename, linenum);
521 /* NOTREACHED */
522 value = 0; /* Avoid compiler warning. */
523 }
524 if (*activep && *intptr == -1)
525 *intptr = value;
526 break;
527
528 default:
529 fatal("process_config_line: Unimplemented opcode %d", opcode);
530 }
531
532 /* Check that there is no garbage at end of line. */
533 if (strtok(NULL, WHITESPACE) != NULL)
534 fatal("%.200s line %d: garbage at end of line.",
535 filename, linenum);
536 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000537}
538
539
Damien Miller5428f641999-11-25 11:54:57 +1100540/*
541 * Reads the config file and modifies the options accordingly. Options
542 * should already be initialized before this call. This never returns if
543 * there is an error. If the file does not exist, this returns immediately.
544 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000545
Damien Miller95def091999-11-25 00:26:21 +1100546void
547read_config_file(const char *filename, const char *host, Options *options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000548{
Damien Miller95def091999-11-25 00:26:21 +1100549 FILE *f;
550 char line[1024];
551 int active, linenum;
552 int bad_options = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000553
Damien Miller95def091999-11-25 00:26:21 +1100554 /* Open the file. */
555 f = fopen(filename, "r");
556 if (!f)
557 return;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000558
Damien Miller95def091999-11-25 00:26:21 +1100559 debug("Reading configuration data %.200s", filename);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000560
Damien Miller5428f641999-11-25 11:54:57 +1100561 /*
562 * Mark that we are now processing the options. This flag is turned
563 * on/off by Host specifications.
564 */
Damien Miller95def091999-11-25 00:26:21 +1100565 active = 1;
566 linenum = 0;
567 while (fgets(line, sizeof(line), f)) {
568 /* Update line number counter. */
569 linenum++;
570 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
571 bad_options++;
572 }
573 fclose(f);
574 if (bad_options > 0)
575 fatal("%s: terminating, %d bad configuration options\n",
576 filename, bad_options);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000577}
578
Damien Miller5428f641999-11-25 11:54:57 +1100579/*
580 * Initializes options to special values that indicate that they have not yet
581 * been set. Read_config_file will only set options with this value. Options
582 * are processed in the following order: command line, user config file,
583 * system config file. Last, fill_default_options is called.
584 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000585
Damien Miller95def091999-11-25 00:26:21 +1100586void
587initialize_options(Options * options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000588{
Damien Miller95def091999-11-25 00:26:21 +1100589 memset(options, 'X', sizeof(*options));
590 options->forward_agent = -1;
591 options->forward_x11 = -1;
592 options->gateway_ports = -1;
593 options->use_privileged_port = -1;
594 options->rhosts_authentication = -1;
595 options->rsa_authentication = -1;
596 options->skey_authentication = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000597#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100598 options->kerberos_authentication = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000599#endif
600#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100601 options->kerberos_tgt_passing = -1;
602 options->afs_token_passing = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000603#endif
Damien Miller95def091999-11-25 00:26:21 +1100604 options->password_authentication = -1;
605 options->rhosts_rsa_authentication = -1;
606 options->fallback_to_rsh = -1;
607 options->use_rsh = -1;
608 options->batch_mode = -1;
609 options->check_host_ip = -1;
610 options->strict_host_key_checking = -1;
611 options->compression = -1;
612 options->keepalives = -1;
613 options->compression_level = -1;
614 options->port = -1;
615 options->connection_attempts = -1;
616 options->number_of_password_prompts = -1;
617 options->cipher = -1;
618 options->num_identity_files = 0;
619 options->hostname = NULL;
620 options->proxy_command = NULL;
621 options->user = NULL;
622 options->escape_char = -1;
623 options->system_hostfile = NULL;
624 options->user_hostfile = NULL;
625 options->num_local_forwards = 0;
626 options->num_remote_forwards = 0;
627 options->log_level = (LogLevel) - 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000628}
629
Damien Miller5428f641999-11-25 11:54:57 +1100630/*
631 * Called after processing other sources of option data, this fills those
632 * options for which no value has been specified with their default values.
633 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000634
Damien Miller95def091999-11-25 00:26:21 +1100635void
636fill_default_options(Options * options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000637{
Damien Miller95def091999-11-25 00:26:21 +1100638 if (options->forward_agent == -1)
639 options->forward_agent = 1;
640 if (options->forward_x11 == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100641 options->forward_x11 = 0;
Damien Miller95def091999-11-25 00:26:21 +1100642 if (options->gateway_ports == -1)
643 options->gateway_ports = 0;
644 if (options->use_privileged_port == -1)
645 options->use_privileged_port = 1;
646 if (options->rhosts_authentication == -1)
647 options->rhosts_authentication = 1;
648 if (options->rsa_authentication == -1)
649 options->rsa_authentication = 1;
650 if (options->skey_authentication == -1)
651 options->skey_authentication = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000652#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100653 if (options->kerberos_authentication == -1)
654 options->kerberos_authentication = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000655#endif /* KRB4 */
656#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100657 if (options->kerberos_tgt_passing == -1)
658 options->kerberos_tgt_passing = 1;
659 if (options->afs_token_passing == -1)
660 options->afs_token_passing = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000661#endif /* AFS */
Damien Miller95def091999-11-25 00:26:21 +1100662 if (options->password_authentication == -1)
663 options->password_authentication = 1;
664 if (options->rhosts_rsa_authentication == -1)
665 options->rhosts_rsa_authentication = 1;
666 if (options->fallback_to_rsh == -1)
667 options->fallback_to_rsh = 1;
668 if (options->use_rsh == -1)
669 options->use_rsh = 0;
670 if (options->batch_mode == -1)
671 options->batch_mode = 0;
672 if (options->check_host_ip == -1)
673 options->check_host_ip = 1;
674 if (options->strict_host_key_checking == -1)
675 options->strict_host_key_checking = 2; /* 2 is default */
676 if (options->compression == -1)
677 options->compression = 0;
678 if (options->keepalives == -1)
679 options->keepalives = 1;
680 if (options->compression_level == -1)
681 options->compression_level = 6;
682 if (options->port == -1)
683 options->port = 0; /* Filled in ssh_connect. */
684 if (options->connection_attempts == -1)
685 options->connection_attempts = 4;
686 if (options->number_of_password_prompts == -1)
687 options->number_of_password_prompts = 3;
688 /* Selected in ssh_login(). */
689 if (options->cipher == -1)
690 options->cipher = SSH_CIPHER_NOT_SET;
691 if (options->num_identity_files == 0) {
692 options->identity_files[0] =
693 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
694 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
695 options->num_identity_files = 1;
696 }
697 if (options->escape_char == -1)
698 options->escape_char = '~';
699 if (options->system_hostfile == NULL)
700 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
701 if (options->user_hostfile == NULL)
702 options->user_hostfile = SSH_USER_HOSTFILE;
703 if (options->log_level == (LogLevel) - 1)
704 options->log_level = SYSLOG_LEVEL_INFO;
705 /* options->proxy_command should not be set by default */
706 /* options->user will be set in the main program if appropriate */
707 /* options->hostname will be set in the main program if appropriate */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000708}