5 Author: Tatu Ylonen <ylo@cs.hut.fi>
7 Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
10 Created: Sat Apr 22 00:03:10 1995 ylo
12 Functions for reading the configuration files.
24 /* Format of the configuration file:
26 # Configuration data is parsed as follows:
27 # 1. command line options
28 # 2. user-specific 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.
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.
42 HostName another.host.name.real.org
49 RemoteForward 9999 shadows.cs.hut.fi:9999
55 RhostsAuthentication no
56 PasswordAuthentication no
60 ProxyCommand ssh-proxy %h %p
67 PasswordAuthentication no
69 # Defaults for various options
73 RhostsAuthentication yes
74 PasswordAuthentication yes
76 RhostsRSAAuthentication yes
79 StrictHostKeyChecking yes
81 IdentityFile ~/.ssh/identity
91 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
92 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
94 oKerberosAuthentication,
97 oKerberosTgtPassing, oAFSTokenPassing,
99 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
100 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
101 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
102 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
103 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
107 /* Textual representations of the tokens. */
115 { "forwardagent", oForwardAgent },
116 { "forwardx11", oForwardX11 },
117 { "gatewayports", oGatewayPorts },
118 { "useprivilegedport", oUsePrivilegedPort },
119 { "rhostsauthentication", oRhostsAuthentication },
120 { "passwordauthentication", oPasswordAuthentication },
121 { "rsaauthentication", oRSAAuthentication },
123 { "kerberosauthentication", oKerberosAuthentication },
126 { "kerberostgtpassing", oKerberosTgtPassing },
127 { "afstokenpassing", oAFSTokenPassing },
129 { "fallbacktorsh", oFallBackToRsh },
130 { "usersh", oUseRsh },
131 { "identityfile", oIdentityFile },
132 { "hostname", oHostName },
133 { "proxycommand", oProxyCommand },
135 { "cipher", oCipher },
136 { "remoteforward", oRemoteForward },
137 { "localforward", oLocalForward },
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 },
156 /* Characters considered whitespace in strtok calls. */
157 #define WHITESPACE " \t\r\n"
160 /* Adds a local TCP/IP port forward to options. Never returns if there
163 void add_local_forward(Options *options, int port, const char *host,
167 extern uid_t original_real_uid;
168 if ((port & 0xffff) != port)
169 fatal("Requested forwarding of nonexistent port %d.", port);
170 if (port < IPPORT_RESERVED && original_real_uid != 0)
171 fatal("Privileged ports can only be forwarded by root.\n");
172 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
173 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
174 fwd = &options->local_forwards[options->num_local_forwards++];
176 fwd->host = xstrdup(host);
177 fwd->host_port = host_port;
180 /* Adds a remote TCP/IP port forward to options. Never returns if there
183 void add_remote_forward(Options *options, int port, const char *host,
187 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
188 fatal("Too many remote forwards (max %d).",
189 SSH_MAX_FORWARDS_PER_DIRECTION);
190 fwd = &options->remote_forwards[options->num_remote_forwards++];
192 fwd->host = xstrdup(host);
193 fwd->host_port = host_port;
196 /* Returns the number of the token pointed to by cp of length len.
197 Never returns if the token is not known. */
199 static OpCodes parse_token(const char *cp, const char *filename, int linenum)
203 for (i = 0; keywords[i].name; i++)
204 if (strcmp(cp, keywords[i].name) == 0)
205 return keywords[i].opcode;
207 fatal("%.200s line %d: Bad configuration option.",
213 /* Processes a single option line as used in the configuration files.
214 This only sets those values that have not already been set. */
216 void process_config_line(Options *options, const char *host,
217 char *line, const char *filename, int linenum,
220 char buf[256], *cp, *string, **charptr;
221 int opcode, *intptr, value, fwd_port, fwd_host_port;
223 /* Skip leading whitespace. */
224 cp = line + strspn(line, WHITESPACE);
225 if (!*cp || *cp == '\n' || *cp == '#')
228 /* Get the keyword. (Each line is supposed to begin with a keyword). */
229 cp = strtok(cp, WHITESPACE);
233 if ('A' <= *t && *t <= 'Z')
234 *t = *t - 'A' + 'a'; /* tolower */
237 opcode = parse_token(cp, filename, linenum);
243 intptr = &options->forward_agent;
245 cp = strtok(NULL, WHITESPACE);
247 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
248 value = 0; /* To avoid compiler warning... */
249 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
251 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
254 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
255 if (*activep && *intptr == -1)
260 intptr = &options->forward_x11;
264 intptr = &options->gateway_ports;
267 case oUsePrivilegedPort:
268 intptr = &options->use_privileged_port;
271 case oRhostsAuthentication:
272 intptr = &options->rhosts_authentication;
275 case oPasswordAuthentication:
276 intptr = &options->password_authentication;
279 case oRSAAuthentication:
280 intptr = &options->rsa_authentication;
283 case oRhostsRSAAuthentication:
284 intptr = &options->rhosts_rsa_authentication;
288 case oKerberosAuthentication:
289 intptr = &options->kerberos_authentication;
294 case oKerberosTgtPassing:
295 intptr = &options->kerberos_tgt_passing;
298 case oAFSTokenPassing:
299 intptr = &options->afs_token_passing;
304 intptr = &options->fallback_to_rsh;
308 intptr = &options->use_rsh;
312 intptr = &options->batch_mode;
316 intptr = &options->check_host_ip;
319 case oStrictHostKeyChecking:
320 intptr = &options->strict_host_key_checking;
321 cp = strtok(NULL, WHITESPACE);
323 fatal("%.200s line %d: Missing yes/no argument.",
325 value = 0; /* To avoid compiler warning... */
326 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
328 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
330 else if (strcmp(cp, "ask") == 0)
333 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
334 if (*activep && *intptr == -1)
339 intptr = &options->compression;
343 intptr = &options->keepalives;
346 case oNumberOfPasswordPrompts:
347 intptr = &options->number_of_password_prompts;
350 case oTISAuthentication:
351 cp = strtok(NULL, WHITESPACE);
352 if (cp != 0 && (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0))
354 "%.99s line %d: Warning, TIS is not supported.\n",
359 case oCompressionLevel:
360 intptr = &options->compression_level;
364 cp = strtok(NULL, WHITESPACE);
366 fatal("%.200s line %d: Missing argument.", filename, linenum);
369 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
370 fatal("%.200s line %d: Too many identity files specified (max %d).",
371 filename, linenum, SSH_MAX_IDENTITY_FILES);
372 options->identity_files[options->num_identity_files++] = xstrdup(cp);
377 charptr = &options->user;
379 cp = strtok(NULL, WHITESPACE);
381 fatal("%.200s line %d: Missing argument.", filename, linenum);
382 if (*activep && *charptr == NULL)
383 *charptr = xstrdup(cp);
386 case oGlobalKnownHostsFile:
387 charptr = &options->system_hostfile;
390 case oUserKnownHostsFile:
391 charptr = &options->user_hostfile;
395 charptr = &options->hostname;
399 charptr = &options->proxy_command;
400 string = xstrdup("");
401 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
403 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
407 if (*activep && *charptr == NULL)
414 intptr = &options->port;
416 cp = strtok(NULL, WHITESPACE);
418 fatal("%.200s line %d: Missing argument.", filename, linenum);
419 if (cp[0] < '0' || cp[0] > '9')
420 fatal("%.200s line %d: Bad number.", filename, linenum);
426 value = strtol(cp, &ptr, 0); /* Octal, decimal, or hex format? */
428 fatal("%.200s line %d: Bad number.", filename, linenum);
431 if (*activep && *intptr == -1)
435 case oConnectionAttempts:
436 intptr = &options->connection_attempts;
440 intptr = &options->cipher;
441 cp = strtok(NULL, WHITESPACE);
442 value = cipher_number(cp);
444 fatal("%.200s line %d: Bad cipher.", filename, linenum);
445 if (*activep && *intptr == -1)
450 cp = strtok(NULL, WHITESPACE);
452 fatal("%.200s line %d: Missing argument.", filename, linenum);
453 if (cp[0] < '0' || cp[0] > '9')
454 fatal("%.200s line %d: Badly formatted port number.",
457 cp = strtok(NULL, WHITESPACE);
459 fatal("%.200s line %d: Missing second argument.",
461 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
462 fatal("%.200s line %d: Badly formatted host:port.",
465 add_remote_forward(options, fwd_port, buf, fwd_host_port);
469 cp = strtok(NULL, WHITESPACE);
471 fatal("%.200s line %d: Missing argument.", filename, linenum);
472 if (cp[0] < '0' || cp[0] > '9')
473 fatal("%.200s line %d: Badly formatted port number.",
476 cp = strtok(NULL, WHITESPACE);
478 fatal("%.200s line %d: Missing second argument.",
480 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
481 fatal("%.200s line %d: Badly formatted host:port.",
484 add_local_forward(options, fwd_port, buf, fwd_host_port);
489 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
490 if (match_pattern(host, cp))
492 debug("Applying options for %.100s", cp);
496 /* Avoid garbage check below, as strtok already returned NULL. */
500 intptr = &options->escape_char;
501 cp = strtok(NULL, WHITESPACE);
503 fatal("%.200s line %d: Missing argument.", filename, linenum);
504 if (cp[0] == '^' && cp[2] == 0 &&
505 (unsigned char)cp[1] >= 64 && (unsigned char)cp[1] < 128)
506 value = (unsigned char)cp[1] & 31;
509 value = (unsigned char)cp[0];
511 if (strcmp(cp, "none") == 0)
515 fatal("%.200s line %d: Bad escape character.",
518 value = 0; /* Avoid compiler warning. */
520 if (*activep && *intptr == -1)
525 fatal("parse_config_file: Unimplemented opcode %d", opcode);
528 /* Check that there is no garbage at end of line. */
529 if (strtok(NULL, WHITESPACE) != NULL)
530 fatal("%.200s line %d: garbage at end of line.",
535 /* Reads the config file and modifies the options accordingly. Options should
536 already be initialized before this call. This never returns if there
537 is an error. If the file does not exist, this returns immediately. */
539 void read_config_file(const char *filename, const char *host, Options *options)
546 f = fopen(filename, "r");
550 debug("Reading configuration data %.200s", filename);
552 /* Mark that we are now processing the options. This flag is turned on/off
553 by Host specifications. */
556 while (fgets(line, sizeof(line), f))
558 /* Update line number counter. */
561 process_config_line(options, host, line, filename, linenum, &active);
566 /* Initializes options to special values that indicate that they have not
567 yet been set. Read_config_file will only set options with this value.
568 Options are processed in the following order: command line, user config
569 file, system config file. Last, fill_default_options is called. */
571 void initialize_options(Options *options)
573 memset(options, 'X', sizeof(*options));
574 options->forward_agent = -1;
575 options->forward_x11 = -1;
576 options->gateway_ports = -1;
577 options->use_privileged_port = -1;
578 options->rhosts_authentication = -1;
579 options->rsa_authentication = -1;
581 options->kerberos_authentication = -1;
584 options->kerberos_tgt_passing = -1;
585 options->afs_token_passing = -1;
587 options->password_authentication = -1;
588 options->rhosts_rsa_authentication = -1;
589 options->fallback_to_rsh = -1;
590 options->use_rsh = -1;
591 options->batch_mode = -1;
592 options->check_host_ip = -1;
593 options->strict_host_key_checking = -1;
594 options->compression = -1;
595 options->keepalives = -1;
596 options->compression_level = -1;
598 options->connection_attempts = -1;
599 options->number_of_password_prompts = -1;
600 options->cipher = -1;
601 options->num_identity_files = 0;
602 options->hostname = NULL;
603 options->proxy_command = NULL;
604 options->user = NULL;
605 options->escape_char = -1;
606 options->system_hostfile = NULL;
607 options->user_hostfile = NULL;
608 options->num_local_forwards = 0;
609 options->num_remote_forwards = 0;
612 /* Called after processing other sources of option data, this fills those
613 options for which no value has been specified with their default values. */
615 void fill_default_options(Options *options)
617 if (options->forward_agent == -1)
618 options->forward_agent = 1;
619 if (options->forward_x11 == -1)
620 options->forward_x11 = 1;
621 if (options->gateway_ports == -1)
622 options->gateway_ports = 0;
623 if (options->use_privileged_port == -1)
624 options->use_privileged_port = 1;
625 if (options->rhosts_authentication == -1)
626 options->rhosts_authentication = 1;
627 if (options->rsa_authentication == -1)
628 options->rsa_authentication = 1;
630 if (options->kerberos_authentication == -1)
631 options->kerberos_authentication = 1;
634 if (options->kerberos_tgt_passing == -1)
635 options->kerberos_tgt_passing = 1;
636 if (options->afs_token_passing == -1)
637 options->afs_token_passing = 1;
639 if (options->password_authentication == -1)
640 options->password_authentication = 1;
641 if (options->rhosts_rsa_authentication == -1)
642 options->rhosts_rsa_authentication = 1;
643 if (options->fallback_to_rsh == -1)
644 options->fallback_to_rsh = 1;
645 if (options->use_rsh == -1)
646 options->use_rsh = 0;
647 if (options->batch_mode == -1)
648 options->batch_mode = 0;
649 if (options->check_host_ip == -1)
650 options->check_host_ip = 1;
651 if (options->strict_host_key_checking == -1)
652 options->strict_host_key_checking = 2; /* 2 is default */
653 if (options->compression == -1)
654 options->compression = 0;
655 if (options->keepalives == -1)
656 options->keepalives = 1;
657 if (options->compression_level == -1)
658 options->compression_level = 6;
659 if (options->port == -1)
660 options->port = 0; /* Filled in ssh_connect. */
661 if (options->connection_attempts == -1)
662 options->connection_attempts = 4;
663 if (options->number_of_password_prompts == -1)
664 options->number_of_password_prompts = 3;
665 if (options->cipher == -1)
666 options->cipher = SSH_CIPHER_NOT_SET; /* Selected in ssh_login(). */
667 if (options->num_identity_files == 0)
669 options->identity_files[0] =
670 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
671 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
672 options->num_identity_files = 1;
674 if (options->escape_char == -1)
675 options->escape_char = '~';
676 if (options->system_hostfile == NULL)
677 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
678 if (options->user_hostfile == NULL)
679 options->user_hostfile = SSH_USER_HOSTFILE;
680 /* options->proxy_command should not be set by default */
681 /* options->user will be set in the main program if appropriate */
682 /* options->hostname will be set in the main program if appropriate */