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
92 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
93 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
95 oKerberosAuthentication,
98 oKerberosTgtPassing, oAFSTokenPassing,
100 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
108 /* Textual representations of the tokens. */
116 { "forwardagent", oForwardAgent },
117 { "forwardx11", oForwardX11 },
118 { "gatewayports", oGatewayPorts },
119 { "useprivilegedport", oUsePrivilegedPort },
120 { "rhostsauthentication", oRhostsAuthentication },
121 { "passwordauthentication", oPasswordAuthentication },
122 { "rsaauthentication", oRSAAuthentication },
124 { "kerberosauthentication", oKerberosAuthentication },
127 { "kerberostgtpassing", oKerberosTgtPassing },
128 { "afstokenpassing", oAFSTokenPassing },
130 { "fallbacktorsh", oFallBackToRsh },
131 { "usersh", oUseRsh },
132 { "identityfile", oIdentityFile },
133 { "hostname", oHostName },
134 { "proxycommand", oProxyCommand },
136 { "cipher", oCipher },
137 { "remoteforward", oRemoteForward },
138 { "localforward", oLocalForward },
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 },
158 /* Characters considered whitespace in strtok calls. */
159 #define WHITESPACE " \t\r\n"
162 /* Adds a local TCP/IP port forward to options. Never returns if there
165 void add_local_forward(Options *options, int port, const char *host,
169 extern uid_t original_real_uid;
170 if ((port & 0xffff) != port)
171 fatal("Requested forwarding of nonexistent port %d.", port);
172 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++];
178 fwd->host = xstrdup(host);
179 fwd->host_port = host_port;
182 /* Adds a remote TCP/IP port forward to options. Never returns if there
185 void add_remote_forward(Options *options, int port, const char *host,
189 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
190 fatal("Too many remote forwards (max %d).",
191 SSH_MAX_FORWARDS_PER_DIRECTION);
192 fwd = &options->remote_forwards[options->num_remote_forwards++];
194 fwd->host = xstrdup(host);
195 fwd->host_port = host_port;
198 /* Returns the number of the token pointed to by cp of length len.
199 Never returns if the token is not known. */
201 static OpCodes parse_token(const char *cp, const char *filename, int linenum)
205 for (i = 0; keywords[i].name; i++)
206 if (strcmp(cp, keywords[i].name) == 0)
207 return keywords[i].opcode;
209 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
210 filename, linenum, cp);
214 /* Processes a single option line as used in the configuration files.
215 This only sets those values that have not already been set. */
218 process_config_line(Options *options, const char *host,
219 char *line, const char *filename, int linenum,
222 char buf[256], *cp, *string, **charptr;
223 int opcode, *intptr, value, fwd_port, fwd_host_port;
225 /* Skip leading whitespace. */
226 cp = line + strspn(line, WHITESPACE);
227 if (!*cp || *cp == '\n' || *cp == '#')
230 /* Get the keyword. (Each line is supposed to begin with a keyword). */
231 cp = strtok(cp, WHITESPACE);
235 if ('A' <= *t && *t <= 'Z')
236 *t = *t - 'A' + 'a'; /* tolower */
239 opcode = parse_token(cp, filename, linenum);
244 return -1; /* don't panic, but count bad options */
247 intptr = &options->forward_agent;
249 cp = strtok(NULL, WHITESPACE);
251 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
252 value = 0; /* To avoid compiler warning... */
253 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
255 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
258 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
259 if (*activep && *intptr == -1)
264 intptr = &options->forward_x11;
268 intptr = &options->gateway_ports;
271 case oUsePrivilegedPort:
272 intptr = &options->use_privileged_port;
275 case oRhostsAuthentication:
276 intptr = &options->rhosts_authentication;
279 case oPasswordAuthentication:
280 intptr = &options->password_authentication;
283 case oRSAAuthentication:
284 intptr = &options->rsa_authentication;
287 case oRhostsRSAAuthentication:
288 intptr = &options->rhosts_rsa_authentication;
292 case oKerberosAuthentication:
293 intptr = &options->kerberos_authentication;
298 case oKerberosTgtPassing:
299 intptr = &options->kerberos_tgt_passing;
302 case oAFSTokenPassing:
303 intptr = &options->afs_token_passing;
308 intptr = &options->fallback_to_rsh;
312 intptr = &options->use_rsh;
316 intptr = &options->batch_mode;
320 intptr = &options->check_host_ip;
323 case oStrictHostKeyChecking:
324 intptr = &options->strict_host_key_checking;
325 cp = strtok(NULL, WHITESPACE);
327 fatal("%.200s line %d: Missing yes/no argument.",
329 value = 0; /* To avoid compiler warning... */
330 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
332 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
334 else if (strcmp(cp, "ask") == 0)
337 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
338 if (*activep && *intptr == -1)
343 intptr = &options->compression;
347 intptr = &options->keepalives;
350 case oNumberOfPasswordPrompts:
351 intptr = &options->number_of_password_prompts;
354 case oTISAuthentication:
355 cp = strtok(NULL, WHITESPACE);
356 if (cp != 0 && (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0))
358 "%.99s line %d: Warning, TIS is not supported.\n",
363 case oCompressionLevel:
364 intptr = &options->compression_level;
368 cp = strtok(NULL, WHITESPACE);
370 fatal("%.200s line %d: Missing argument.", filename, linenum);
373 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
374 fatal("%.200s line %d: Too many identity files specified (max %d).",
375 filename, linenum, SSH_MAX_IDENTITY_FILES);
376 options->identity_files[options->num_identity_files++] = xstrdup(cp);
381 charptr = &options->user;
383 cp = strtok(NULL, WHITESPACE);
385 fatal("%.200s line %d: Missing argument.", filename, linenum);
386 if (*activep && *charptr == NULL)
387 *charptr = xstrdup(cp);
390 case oGlobalKnownHostsFile:
391 charptr = &options->system_hostfile;
394 case oUserKnownHostsFile:
395 charptr = &options->user_hostfile;
399 charptr = &options->hostname;
403 charptr = &options->proxy_command;
404 string = xstrdup("");
405 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
407 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
411 if (*activep && *charptr == NULL)
418 intptr = &options->port;
420 cp = strtok(NULL, WHITESPACE);
422 fatal("%.200s line %d: Missing argument.", filename, linenum);
423 if (cp[0] < '0' || cp[0] > '9')
424 fatal("%.200s line %d: Bad number.", filename, linenum);
430 value = strtol(cp, &ptr, 0); /* Octal, decimal, or hex format? */
432 fatal("%.200s line %d: Bad number.", filename, linenum);
435 if (*activep && *intptr == -1)
439 case oConnectionAttempts:
440 intptr = &options->connection_attempts;
444 intptr = &options->cipher;
445 cp = strtok(NULL, WHITESPACE);
446 value = cipher_number(cp);
448 fatal("%.200s line %d: Bad cipher '%s'.",
449 filename, linenum, cp ? cp : "<NONE>");
450 if (*activep && *intptr == -1)
455 intptr = (int *)&options->log_level;
456 cp = strtok(NULL, WHITESPACE);
457 value = log_level_number(cp);
458 if (value == (LogLevel)-1)
459 fatal("%.200s line %d: unsupported log level '%s'\n",
460 filename, linenum, cp ? cp : "<NONE>");
461 if (*activep && (LogLevel)*intptr == -1)
462 *intptr = (LogLevel)value;
466 cp = strtok(NULL, WHITESPACE);
468 fatal("%.200s line %d: Missing argument.", filename, linenum);
469 if (cp[0] < '0' || cp[0] > '9')
470 fatal("%.200s line %d: Badly formatted port number.",
473 cp = strtok(NULL, WHITESPACE);
475 fatal("%.200s line %d: Missing second argument.",
477 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
478 fatal("%.200s line %d: Badly formatted host:port.",
481 add_remote_forward(options, fwd_port, buf, fwd_host_port);
485 cp = strtok(NULL, WHITESPACE);
487 fatal("%.200s line %d: Missing argument.", filename, linenum);
488 if (cp[0] < '0' || cp[0] > '9')
489 fatal("%.200s line %d: Badly formatted port number.",
492 cp = strtok(NULL, WHITESPACE);
494 fatal("%.200s line %d: Missing second argument.",
496 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
497 fatal("%.200s line %d: Badly formatted host:port.",
500 add_local_forward(options, fwd_port, buf, fwd_host_port);
505 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
506 if (match_pattern(host, cp))
508 debug("Applying options for %.100s", cp);
512 /* Avoid garbage check below, as strtok already returned NULL. */
516 intptr = &options->escape_char;
517 cp = strtok(NULL, WHITESPACE);
519 fatal("%.200s line %d: Missing argument.", filename, linenum);
520 if (cp[0] == '^' && cp[2] == 0 &&
521 (unsigned char)cp[1] >= 64 && (unsigned char)cp[1] < 128)
522 value = (unsigned char)cp[1] & 31;
525 value = (unsigned char)cp[0];
527 if (strcmp(cp, "none") == 0)
531 fatal("%.200s line %d: Bad escape character.",
534 value = 0; /* Avoid compiler warning. */
536 if (*activep && *intptr == -1)
541 fatal("process_config_line: Unimplemented opcode %d", opcode);
544 /* Check that there is no garbage at end of line. */
545 if (strtok(NULL, WHITESPACE) != NULL)
546 fatal("%.200s line %d: garbage at end of line.",
552 /* Reads the config file and modifies the options accordingly. Options should
553 already be initialized before this call. This never returns if there
554 is an error. If the file does not exist, this returns immediately. */
556 void read_config_file(const char *filename, const char *host, Options *options)
564 f = fopen(filename, "r");
568 debug("Reading configuration data %.200s", filename);
570 /* Mark that we are now processing the options. This flag is turned on/off
571 by Host specifications. */
574 while (fgets(line, sizeof(line), f))
576 /* Update line number counter. */
578 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
583 fatal("%s: terminating, %d bad configuration options\n",
584 filename, bad_options);
587 /* Initializes options to special values that indicate that they have not
588 yet been set. Read_config_file will only set options with this value.
589 Options are processed in the following order: command line, user config
590 file, system config file. Last, fill_default_options is called. */
592 void initialize_options(Options *options)
594 memset(options, 'X', sizeof(*options));
595 options->forward_agent = -1;
596 options->forward_x11 = -1;
597 options->gateway_ports = -1;
598 options->use_privileged_port = -1;
599 options->rhosts_authentication = -1;
600 options->rsa_authentication = -1;
602 options->kerberos_authentication = -1;
605 options->kerberos_tgt_passing = -1;
606 options->afs_token_passing = -1;
608 options->password_authentication = -1;
609 options->rhosts_rsa_authentication = -1;
610 options->fallback_to_rsh = -1;
611 options->use_rsh = -1;
612 options->batch_mode = -1;
613 options->check_host_ip = -1;
614 options->strict_host_key_checking = -1;
615 options->compression = -1;
616 options->keepalives = -1;
617 options->compression_level = -1;
619 options->connection_attempts = -1;
620 options->number_of_password_prompts = -1;
621 options->cipher = -1;
622 options->num_identity_files = 0;
623 options->hostname = NULL;
624 options->proxy_command = NULL;
625 options->user = NULL;
626 options->escape_char = -1;
627 options->system_hostfile = NULL;
628 options->user_hostfile = NULL;
629 options->num_local_forwards = 0;
630 options->num_remote_forwards = 0;
631 options->log_level = (LogLevel)-1;
634 /* Called after processing other sources of option data, this fills those
635 options for which no value has been specified with their default values. */
637 void fill_default_options(Options *options)
639 if (options->forward_agent == -1)
640 options->forward_agent = 1;
641 if (options->forward_x11 == -1)
642 options->forward_x11 = 1;
643 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;
652 if (options->kerberos_authentication == -1)
653 options->kerberos_authentication = 1;
656 if (options->kerberos_tgt_passing == -1)
657 options->kerberos_tgt_passing = 1;
658 if (options->afs_token_passing == -1)
659 options->afs_token_passing = 1;
661 if (options->password_authentication == -1)
662 options->password_authentication = 1;
663 if (options->rhosts_rsa_authentication == -1)
664 options->rhosts_rsa_authentication = 1;
665 if (options->fallback_to_rsh == -1)
666 options->fallback_to_rsh = 1;
667 if (options->use_rsh == -1)
668 options->use_rsh = 0;
669 if (options->batch_mode == -1)
670 options->batch_mode = 0;
671 if (options->check_host_ip == -1)
672 options->check_host_ip = 1;
673 if (options->strict_host_key_checking == -1)
674 options->strict_host_key_checking = 2; /* 2 is default */
675 if (options->compression == -1)
676 options->compression = 0;
677 if (options->keepalives == -1)
678 options->keepalives = 1;
679 if (options->compression_level == -1)
680 options->compression_level = 6;
681 if (options->port == -1)
682 options->port = 0; /* Filled in ssh_connect. */
683 if (options->connection_attempts == -1)
684 options->connection_attempts = 4;
685 if (options->number_of_password_prompts == -1)
686 options->number_of_password_prompts = 3;
687 if (options->cipher == -1)
688 options->cipher = SSH_CIPHER_NOT_SET; /* Selected in ssh_login(). */
689 if (options->num_identity_files == 0)
691 options->identity_files[0] =
692 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
693 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
694 options->num_identity_files = 1;
696 if (options->escape_char == -1)
697 options->escape_char = '~';
698 if (options->system_hostfile == NULL)
699 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
700 if (options->user_hostfile == NULL)
701 options->user_hostfile = SSH_USER_HOSTFILE;
702 if (options->log_level == (LogLevel)-1)
703 options->log_level = SYSLOG_LEVEL_INFO;
704 /* options->proxy_command should not be set by default */
705 /* options->user will be set in the main program if appropriate */
706 /* options->hostname will be set in the main program if appropriate */