blob: bb420ac05af371ab5d51a77168f2f50eaba825b6 [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 Millerb38eff82000-04-01 11:09:21 +100017RCSID("$Id: readconf.c,v 1.9 2000/04/01 01:09:25 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100018
19#include "ssh.h"
20#include "cipher.h"
21#include "readconf.h"
Damien Millerb38eff82000-04-01 11:09:21 +100022#include "match.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100023#include "xmalloc.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
Damien Miller95def091999-11-25 00:26:21 +110090typedef enum {
91 oBadOption,
92 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
93 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
94 oSkeyAuthentication,
Damien Millerd4a8b7e1999-10-27 13:42:43 +100095#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +110096 oKerberosAuthentication,
Damien Millerd4a8b7e1999-10-27 13:42:43 +100097#endif /* KRB4 */
98#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +110099 oKerberosTgtPassing, oAFSTokenPassing,
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000100#endif
Damien Miller95def091999-11-25 00:26:21 +1100101 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
102 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
103 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
104 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
105 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
106 oUsePrivilegedPort, oLogLevel
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000107} OpCodes;
108
109/* Textual representations of the tokens. */
110
Damien Miller95def091999-11-25 00:26:21 +1100111static struct {
112 const char *name;
113 OpCodes opcode;
114} keywords[] = {
115 { "forwardagent", oForwardAgent },
116 { "forwardx11", oForwardX11 },
117 { "gatewayports", oGatewayPorts },
118 { "useprivilegedport", oUsePrivilegedPort },
119 { "rhostsauthentication", oRhostsAuthentication },
120 { "passwordauthentication", oPasswordAuthentication },
121 { "rsaauthentication", oRSAAuthentication },
122 { "skeyauthentication", oSkeyAuthentication },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000123#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100124 { "kerberosauthentication", oKerberosAuthentication },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000125#endif /* KRB4 */
126#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100127 { "kerberostgtpassing", oKerberosTgtPassing },
128 { "afstokenpassing", oAFSTokenPassing },
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000129#endif
Damien Miller95def091999-11-25 00:26:21 +1100130 { "fallbacktorsh", oFallBackToRsh },
131 { "usersh", oUseRsh },
132 { "identityfile", oIdentityFile },
133 { "hostname", oHostName },
134 { "proxycommand", oProxyCommand },
135 { "port", oPort },
136 { "cipher", oCipher },
137 { "remoteforward", oRemoteForward },
138 { "localforward", oLocalForward },
139 { "user", oUser },
140 { "host", oHost },
141 { "escapechar", oEscapeChar },
142 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
143 { "globalknownhostsfile", oGlobalKnownHostsFile },
144 { "userknownhostsfile", oUserKnownHostsFile },
145 { "connectionattempts", oConnectionAttempts },
146 { "batchmode", oBatchMode },
147 { "checkhostip", oCheckHostIP },
148 { "stricthostkeychecking", oStrictHostKeyChecking },
149 { "compression", oCompression },
150 { "compressionlevel", oCompressionLevel },
151 { "keepalive", oKeepAlives },
152 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
153 { "tisauthentication", oTISAuthentication },
154 { "loglevel", oLogLevel },
155 { NULL, 0 }
Damien Miller5ce662a1999-11-11 17:57:39 +1100156};
157
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000158/* Characters considered whitespace in strtok calls. */
159#define WHITESPACE " \t\r\n"
160
161
Damien Miller5428f641999-11-25 11:54:57 +1100162/*
163 * Adds a local TCP/IP port forward to options. Never returns if there is an
164 * error.
165 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000166
Damien Miller95def091999-11-25 00:26:21 +1100167void
Damien Milleraae6c611999-12-06 11:47:28 +1100168add_local_forward(Options *options, u_short port, const char *host,
169 u_short host_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000170{
Damien Miller95def091999-11-25 00:26:21 +1100171 Forward *fwd;
172 extern uid_t original_real_uid;
Damien Miller95def091999-11-25 00:26:21 +1100173 if (port < IPPORT_RESERVED && original_real_uid != 0)
174 fatal("Privileged ports can only be forwarded by root.\n");
175 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
176 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
177 fwd = &options->local_forwards[options->num_local_forwards++];
178 fwd->port = port;
179 fwd->host = xstrdup(host);
180 fwd->host_port = host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000181}
182
Damien Miller5428f641999-11-25 11:54:57 +1100183/*
184 * Adds a remote TCP/IP port forward to options. Never returns if there is
185 * an error.
186 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000187
Damien Miller95def091999-11-25 00:26:21 +1100188void
Damien Milleraae6c611999-12-06 11:47:28 +1100189add_remote_forward(Options *options, u_short port, const char *host,
190 u_short host_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000191{
Damien Miller95def091999-11-25 00:26:21 +1100192 Forward *fwd;
193 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
194 fatal("Too many remote forwards (max %d).",
195 SSH_MAX_FORWARDS_PER_DIRECTION);
196 fwd = &options->remote_forwards[options->num_remote_forwards++];
197 fwd->port = port;
198 fwd->host = xstrdup(host);
199 fwd->host_port = host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000200}
201
Damien Miller5428f641999-11-25 11:54:57 +1100202/*
203 * Returns the number of the token pointed to by cp of length len. Never
204 * returns if the token is not known.
205 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000206
Damien Miller95def091999-11-25 00:26:21 +1100207static OpCodes
208parse_token(const char *cp, const char *filename, int linenum)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000209{
Damien Miller95def091999-11-25 00:26:21 +1100210 unsigned int i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000211
Damien Miller95def091999-11-25 00:26:21 +1100212 for (i = 0; keywords[i].name; i++)
Damien Miller5428f641999-11-25 11:54:57 +1100213 if (strcasecmp(cp, keywords[i].name) == 0)
Damien Miller95def091999-11-25 00:26:21 +1100214 return keywords[i].opcode;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000215
Damien Miller95def091999-11-25 00:26:21 +1100216 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
217 filename, linenum, cp);
218 return oBadOption;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000219}
220
Damien Miller5428f641999-11-25 11:54:57 +1100221/*
222 * Processes a single option line as used in the configuration files. This
223 * only sets those values that have not already been set.
224 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000225
Damien Miller2ccf6611999-11-15 15:25:10 +1100226int
227process_config_line(Options *options, const char *host,
Damien Miller95def091999-11-25 00:26:21 +1100228 char *line, const char *filename, int linenum,
229 int *activep)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000230{
Damien Miller5428f641999-11-25 11:54:57 +1100231 char buf[256], *cp, *string, **charptr, *cp2;
Damien Milleraae6c611999-12-06 11:47:28 +1100232 int opcode, *intptr, value;
233 u_short fwd_port, fwd_host_port;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000234
Damien Miller95def091999-11-25 00:26:21 +1100235 /* Skip leading whitespace. */
236 cp = line + strspn(line, WHITESPACE);
237 if (!*cp || *cp == '\n' || *cp == '#')
238 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000239
Damien Miller5428f641999-11-25 11:54:57 +1100240 /* Get the keyword. (Each line is supposed to begin with a keyword). */
Damien Miller95def091999-11-25 00:26:21 +1100241 cp = strtok(cp, WHITESPACE);
Damien Miller95def091999-11-25 00:26:21 +1100242 opcode = parse_token(cp, filename, linenum);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000243
Damien Miller95def091999-11-25 00:26:21 +1100244 switch (opcode) {
245 case oBadOption:
Damien Miller5428f641999-11-25 11:54:57 +1100246 /* don't panic, but count bad options */
247 return -1;
Damien Miller95def091999-11-25 00:26:21 +1100248 /* NOTREACHED */
249 case oForwardAgent:
250 intptr = &options->forward_agent;
251parse_flag:
252 cp = strtok(NULL, WHITESPACE);
253 if (!cp)
254 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
255 value = 0; /* To avoid compiler warning... */
256 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
257 value = 1;
258 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
259 value = 0;
260 else
261 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
262 if (*activep && *intptr == -1)
263 *intptr = value;
264 break;
265
266 case oForwardX11:
267 intptr = &options->forward_x11;
268 goto parse_flag;
269
270 case oGatewayPorts:
271 intptr = &options->gateway_ports;
272 goto parse_flag;
273
274 case oUsePrivilegedPort:
275 intptr = &options->use_privileged_port;
276 goto parse_flag;
277
278 case oRhostsAuthentication:
279 intptr = &options->rhosts_authentication;
280 goto parse_flag;
281
282 case oPasswordAuthentication:
283 intptr = &options->password_authentication;
284 goto parse_flag;
285
286 case oRSAAuthentication:
287 intptr = &options->rsa_authentication;
288 goto parse_flag;
289
290 case oRhostsRSAAuthentication:
291 intptr = &options->rhosts_rsa_authentication;
292 goto parse_flag;
293
294 case oTISAuthentication:
295 /* fallthrough, there is no difference on the client side */
296 case oSkeyAuthentication:
297 intptr = &options->skey_authentication;
298 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000299
300#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100301 case oKerberosAuthentication:
302 intptr = &options->kerberos_authentication;
303 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000304#endif /* KRB4 */
305
306#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100307 case oKerberosTgtPassing:
308 intptr = &options->kerberos_tgt_passing;
309 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000310
Damien Miller95def091999-11-25 00:26:21 +1100311 case oAFSTokenPassing:
312 intptr = &options->afs_token_passing;
313 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000314#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000315
Damien Miller95def091999-11-25 00:26:21 +1100316 case oFallBackToRsh:
317 intptr = &options->fallback_to_rsh;
318 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000319
Damien Miller95def091999-11-25 00:26:21 +1100320 case oUseRsh:
321 intptr = &options->use_rsh;
322 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000323
Damien Miller95def091999-11-25 00:26:21 +1100324 case oBatchMode:
325 intptr = &options->batch_mode;
326 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000327
Damien Miller95def091999-11-25 00:26:21 +1100328 case oCheckHostIP:
329 intptr = &options->check_host_ip;
330 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000331
Damien Miller95def091999-11-25 00:26:21 +1100332 case oStrictHostKeyChecking:
333 intptr = &options->strict_host_key_checking;
334 cp = strtok(NULL, WHITESPACE);
335 if (!cp)
336 fatal("%.200s line %d: Missing yes/no argument.",
337 filename, linenum);
338 value = 0; /* To avoid compiler warning... */
339 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
340 value = 1;
341 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
342 value = 0;
343 else if (strcmp(cp, "ask") == 0)
344 value = 2;
345 else
346 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
347 if (*activep && *intptr == -1)
348 *intptr = value;
349 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000350
Damien Miller95def091999-11-25 00:26:21 +1100351 case oCompression:
352 intptr = &options->compression;
353 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000354
Damien Miller95def091999-11-25 00:26:21 +1100355 case oKeepAlives:
356 intptr = &options->keepalives;
357 goto parse_flag;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000358
Damien Miller95def091999-11-25 00:26:21 +1100359 case oNumberOfPasswordPrompts:
360 intptr = &options->number_of_password_prompts;
361 goto parse_int;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000362
Damien Miller95def091999-11-25 00:26:21 +1100363 case oCompressionLevel:
364 intptr = &options->compression_level;
365 goto parse_int;
366
367 case oIdentityFile:
368 cp = strtok(NULL, WHITESPACE);
369 if (!cp)
370 fatal("%.200s line %d: Missing argument.", filename, linenum);
371 if (*activep) {
372 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
373 fatal("%.200s line %d: Too many identity files specified (max %d).",
374 filename, linenum, SSH_MAX_IDENTITY_FILES);
375 options->identity_files[options->num_identity_files++] = xstrdup(cp);
376 }
377 break;
378
379 case oUser:
380 charptr = &options->user;
381parse_string:
382 cp = strtok(NULL, WHITESPACE);
383 if (!cp)
384 fatal("%.200s line %d: Missing argument.", filename, linenum);
385 if (*activep && *charptr == NULL)
386 *charptr = xstrdup(cp);
387 break;
388
389 case oGlobalKnownHostsFile:
390 charptr = &options->system_hostfile;
391 goto parse_string;
392
393 case oUserKnownHostsFile:
394 charptr = &options->user_hostfile;
395 goto parse_string;
396
397 case oHostName:
398 charptr = &options->hostname;
399 goto parse_string;
400
401 case oProxyCommand:
402 charptr = &options->proxy_command;
403 string = xstrdup("");
404 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
405 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
406 strcat(string, " ");
407 strcat(string, cp);
408 }
409 if (*activep && *charptr == NULL)
410 *charptr = string;
411 else
412 xfree(string);
413 return 0;
414
415 case oPort:
416 intptr = &options->port;
417parse_int:
418 cp = strtok(NULL, WHITESPACE);
419 if (!cp)
420 fatal("%.200s line %d: Missing argument.", filename, linenum);
421 if (cp[0] < '0' || cp[0] > '9')
422 fatal("%.200s line %d: Bad number.", filename, linenum);
Damien Miller5428f641999-11-25 11:54:57 +1100423
424 /* Octal, decimal, or hex format? */
425 value = strtol(cp, &cp2, 0);
426 if (cp == cp2)
427 fatal("%.200s line %d: Bad number.", filename, linenum);
Damien Miller95def091999-11-25 00:26:21 +1100428 if (*activep && *intptr == -1)
429 *intptr = value;
430 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000431
Damien Miller95def091999-11-25 00:26:21 +1100432 case oConnectionAttempts:
433 intptr = &options->connection_attempts;
434 goto parse_int;
Damien Miller5ce662a1999-11-11 17:57:39 +1100435
Damien Miller95def091999-11-25 00:26:21 +1100436 case oCipher:
437 intptr = &options->cipher;
438 cp = strtok(NULL, WHITESPACE);
439 value = cipher_number(cp);
440 if (value == -1)
441 fatal("%.200s line %d: Bad cipher '%s'.",
442 filename, linenum, cp ? cp : "<NONE>");
443 if (*activep && *intptr == -1)
444 *intptr = value;
445 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000446
Damien Miller95def091999-11-25 00:26:21 +1100447 case oLogLevel:
448 intptr = (int *) &options->log_level;
449 cp = strtok(NULL, WHITESPACE);
450 value = log_level_number(cp);
451 if (value == (LogLevel) - 1)
452 fatal("%.200s line %d: unsupported log level '%s'\n",
453 filename, linenum, cp ? cp : "<NONE>");
454 if (*activep && (LogLevel) * intptr == -1)
455 *intptr = (LogLevel) value;
456 break;
457
458 case oRemoteForward:
459 cp = strtok(NULL, WHITESPACE);
460 if (!cp)
461 fatal("%.200s line %d: Missing argument.", filename, linenum);
462 if (cp[0] < '0' || cp[0] > '9')
463 fatal("%.200s line %d: Badly formatted port number.",
464 filename, linenum);
465 fwd_port = atoi(cp);
466 cp = strtok(NULL, WHITESPACE);
467 if (!cp)
468 fatal("%.200s line %d: Missing second argument.",
469 filename, linenum);
Damien Milleraae6c611999-12-06 11:47:28 +1100470 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
Damien Miller95def091999-11-25 00:26:21 +1100471 fatal("%.200s line %d: Badly formatted host:port.",
472 filename, linenum);
473 if (*activep)
474 add_remote_forward(options, fwd_port, buf, fwd_host_port);
475 break;
476
477 case oLocalForward:
478 cp = strtok(NULL, WHITESPACE);
479 if (!cp)
480 fatal("%.200s line %d: Missing argument.", filename, linenum);
481 if (cp[0] < '0' || cp[0] > '9')
482 fatal("%.200s line %d: Badly formatted port number.",
483 filename, linenum);
484 fwd_port = atoi(cp);
485 cp = strtok(NULL, WHITESPACE);
486 if (!cp)
487 fatal("%.200s line %d: Missing second argument.",
488 filename, linenum);
Damien Milleraae6c611999-12-06 11:47:28 +1100489 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
Damien Miller95def091999-11-25 00:26:21 +1100490 fatal("%.200s line %d: Badly formatted host:port.",
491 filename, linenum);
492 if (*activep)
493 add_local_forward(options, fwd_port, buf, fwd_host_port);
494 break;
495
496 case oHost:
497 *activep = 0;
498 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
499 if (match_pattern(host, cp)) {
500 debug("Applying options for %.100s", cp);
501 *activep = 1;
502 break;
503 }
Damien Miller5428f641999-11-25 11:54:57 +1100504 /* Avoid garbage check below, as strtok already returned NULL. */
Damien Miller95def091999-11-25 00:26:21 +1100505 return 0;
506
507 case oEscapeChar:
508 intptr = &options->escape_char;
509 cp = strtok(NULL, WHITESPACE);
510 if (!cp)
511 fatal("%.200s line %d: Missing argument.", filename, linenum);
512 if (cp[0] == '^' && cp[2] == 0 &&
513 (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
514 value = (unsigned char) cp[1] & 31;
515 else if (strlen(cp) == 1)
516 value = (unsigned char) cp[0];
517 else if (strcmp(cp, "none") == 0)
518 value = -2;
519 else {
520 fatal("%.200s line %d: Bad escape character.",
521 filename, linenum);
522 /* NOTREACHED */
523 value = 0; /* Avoid compiler warning. */
524 }
525 if (*activep && *intptr == -1)
526 *intptr = value;
527 break;
528
529 default:
530 fatal("process_config_line: Unimplemented opcode %d", opcode);
531 }
532
533 /* Check that there is no garbage at end of line. */
534 if (strtok(NULL, WHITESPACE) != NULL)
535 fatal("%.200s line %d: garbage at end of line.",
536 filename, linenum);
537 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000538}
539
540
Damien Miller5428f641999-11-25 11:54:57 +1100541/*
542 * Reads the config file and modifies the options accordingly. Options
543 * should already be initialized before this call. This never returns if
544 * there is an error. If the file does not exist, this returns immediately.
545 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000546
Damien Miller95def091999-11-25 00:26:21 +1100547void
548read_config_file(const char *filename, const char *host, Options *options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000549{
Damien Miller95def091999-11-25 00:26:21 +1100550 FILE *f;
551 char line[1024];
552 int active, linenum;
553 int bad_options = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000554
Damien Miller95def091999-11-25 00:26:21 +1100555 /* Open the file. */
556 f = fopen(filename, "r");
557 if (!f)
558 return;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000559
Damien Miller95def091999-11-25 00:26:21 +1100560 debug("Reading configuration data %.200s", filename);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000561
Damien Miller5428f641999-11-25 11:54:57 +1100562 /*
563 * Mark that we are now processing the options. This flag is turned
564 * on/off by Host specifications.
565 */
Damien Miller95def091999-11-25 00:26:21 +1100566 active = 1;
567 linenum = 0;
568 while (fgets(line, sizeof(line), f)) {
569 /* Update line number counter. */
570 linenum++;
571 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
572 bad_options++;
573 }
574 fclose(f);
575 if (bad_options > 0)
576 fatal("%s: terminating, %d bad configuration options\n",
577 filename, bad_options);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000578}
579
Damien Miller5428f641999-11-25 11:54:57 +1100580/*
581 * Initializes options to special values that indicate that they have not yet
582 * been set. Read_config_file will only set options with this value. Options
583 * are processed in the following order: command line, user config file,
584 * system config file. Last, fill_default_options is called.
585 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000586
Damien Miller95def091999-11-25 00:26:21 +1100587void
588initialize_options(Options * options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000589{
Damien Miller95def091999-11-25 00:26:21 +1100590 memset(options, 'X', sizeof(*options));
591 options->forward_agent = -1;
592 options->forward_x11 = -1;
593 options->gateway_ports = -1;
594 options->use_privileged_port = -1;
595 options->rhosts_authentication = -1;
596 options->rsa_authentication = -1;
597 options->skey_authentication = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000598#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100599 options->kerberos_authentication = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000600#endif
601#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100602 options->kerberos_tgt_passing = -1;
603 options->afs_token_passing = -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000604#endif
Damien Miller95def091999-11-25 00:26:21 +1100605 options->password_authentication = -1;
606 options->rhosts_rsa_authentication = -1;
607 options->fallback_to_rsh = -1;
608 options->use_rsh = -1;
609 options->batch_mode = -1;
610 options->check_host_ip = -1;
611 options->strict_host_key_checking = -1;
612 options->compression = -1;
613 options->keepalives = -1;
614 options->compression_level = -1;
615 options->port = -1;
616 options->connection_attempts = -1;
617 options->number_of_password_prompts = -1;
618 options->cipher = -1;
619 options->num_identity_files = 0;
620 options->hostname = NULL;
621 options->proxy_command = NULL;
622 options->user = NULL;
623 options->escape_char = -1;
624 options->system_hostfile = NULL;
625 options->user_hostfile = NULL;
626 options->num_local_forwards = 0;
627 options->num_remote_forwards = 0;
628 options->log_level = (LogLevel) - 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000629}
630
Damien Miller5428f641999-11-25 11:54:57 +1100631/*
632 * Called after processing other sources of option data, this fills those
633 * options for which no value has been specified with their default values.
634 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000635
Damien Miller95def091999-11-25 00:26:21 +1100636void
637fill_default_options(Options * options)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000638{
Damien Miller95def091999-11-25 00:26:21 +1100639 if (options->forward_agent == -1)
640 options->forward_agent = 1;
641 if (options->forward_x11 == -1)
Damien Miller98c7ad62000-03-09 21:27:49 +1100642 options->forward_x11 = 0;
Damien Miller95def091999-11-25 00:26:21 +1100643 if (options->gateway_ports == -1)
644 options->gateway_ports = 0;
645 if (options->use_privileged_port == -1)
646 options->use_privileged_port = 1;
647 if (options->rhosts_authentication == -1)
648 options->rhosts_authentication = 1;
649 if (options->rsa_authentication == -1)
650 options->rsa_authentication = 1;
651 if (options->skey_authentication == -1)
652 options->skey_authentication = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000653#ifdef KRB4
Damien Miller95def091999-11-25 00:26:21 +1100654 if (options->kerberos_authentication == -1)
655 options->kerberos_authentication = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000656#endif /* KRB4 */
657#ifdef AFS
Damien Miller95def091999-11-25 00:26:21 +1100658 if (options->kerberos_tgt_passing == -1)
659 options->kerberos_tgt_passing = 1;
660 if (options->afs_token_passing == -1)
661 options->afs_token_passing = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000662#endif /* AFS */
Damien Miller95def091999-11-25 00:26:21 +1100663 if (options->password_authentication == -1)
664 options->password_authentication = 1;
665 if (options->rhosts_rsa_authentication == -1)
666 options->rhosts_rsa_authentication = 1;
667 if (options->fallback_to_rsh == -1)
668 options->fallback_to_rsh = 1;
669 if (options->use_rsh == -1)
670 options->use_rsh = 0;
671 if (options->batch_mode == -1)
672 options->batch_mode = 0;
673 if (options->check_host_ip == -1)
674 options->check_host_ip = 1;
675 if (options->strict_host_key_checking == -1)
676 options->strict_host_key_checking = 2; /* 2 is default */
677 if (options->compression == -1)
678 options->compression = 0;
679 if (options->keepalives == -1)
680 options->keepalives = 1;
681 if (options->compression_level == -1)
682 options->compression_level = 6;
683 if (options->port == -1)
684 options->port = 0; /* Filled in ssh_connect. */
685 if (options->connection_attempts == -1)
686 options->connection_attempts = 4;
687 if (options->number_of_password_prompts == -1)
688 options->number_of_password_prompts = 3;
689 /* Selected in ssh_login(). */
690 if (options->cipher == -1)
691 options->cipher = SSH_CIPHER_NOT_SET;
692 if (options->num_identity_files == 0) {
693 options->identity_files[0] =
694 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
695 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
696 options->num_identity_files = 1;
697 }
698 if (options->escape_char == -1)
699 options->escape_char = '~';
700 if (options->system_hostfile == NULL)
701 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
702 if (options->user_hostfile == NULL)
703 options->user_hostfile = SSH_USER_HOSTFILE;
704 if (options->log_level == (LogLevel) - 1)
705 options->log_level = SYSLOG_LEVEL_INFO;
706 /* options->proxy_command should not be set by default */
707 /* options->user will be set in the main program if appropriate */
708 /* options->hostname will be set in the main program if appropriate */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000709}