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,
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. */
114 { "forwardagent", oForwardAgent },
115 { "forwardx11", oForwardX11 },
116 { "gatewayports", oGatewayPorts },
117 { "useprivilegedport", oUsePrivilegedPort },
118 { "rhostsauthentication", oRhostsAuthentication },
119 { "passwordauthentication", oPasswordAuthentication },
120 { "rsaauthentication", oRSAAuthentication },
121 { "skeyauthentication", oSkeyAuthentication },
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 },
153 { "loglevel", oLogLevel },
157 /* Characters considered whitespace in strtok calls. */
158 #define WHITESPACE " \t\r\n"
162 * Adds a local TCP/IP port forward to options. Never returns if there is an
167 add_local_forward(Options *options, u_short port, const char *host,
171 extern uid_t original_real_uid;
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;
183 * Adds a remote TCP/IP port forward to options. Never returns if there is
188 add_remote_forward(Options *options, u_short port, const char *host,
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++];
197 fwd->host = xstrdup(host);
198 fwd->host_port = host_port;
202 * Returns the number of the token pointed to by cp of length len. Never
203 * returns if the token is not known.
207 parse_token(const char *cp, const char *filename, int linenum)
211 for (i = 0; keywords[i].name; i++)
212 if (strcasecmp(cp, keywords[i].name) == 0)
213 return keywords[i].opcode;
215 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
216 filename, linenum, cp);
221 * Processes a single option line as used in the configuration files. This
222 * only sets those values that have not already been set.
226 process_config_line(Options *options, const char *host,
227 char *line, const char *filename, int linenum,
230 char buf[256], *cp, *string, **charptr, *cp2;
231 int opcode, *intptr, value;
232 u_short fwd_port, fwd_host_port;
234 /* Skip leading whitespace. */
235 cp = line + strspn(line, WHITESPACE);
236 if (!*cp || *cp == '\n' || *cp == '#')
239 /* Get the keyword. (Each line is supposed to begin with a keyword). */
240 cp = strtok(cp, WHITESPACE);
241 opcode = parse_token(cp, filename, linenum);
245 /* don't panic, but count bad options */
249 intptr = &options->forward_agent;
251 cp = strtok(NULL, WHITESPACE);
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)
257 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
260 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
261 if (*activep && *intptr == -1)
266 intptr = &options->forward_x11;
270 intptr = &options->gateway_ports;
273 case oUsePrivilegedPort:
274 intptr = &options->use_privileged_port;
277 case oRhostsAuthentication:
278 intptr = &options->rhosts_authentication;
281 case oPasswordAuthentication:
282 intptr = &options->password_authentication;
285 case oRSAAuthentication:
286 intptr = &options->rsa_authentication;
289 case oRhostsRSAAuthentication:
290 intptr = &options->rhosts_rsa_authentication;
293 case oTISAuthentication:
294 /* fallthrough, there is no difference on the client side */
295 case oSkeyAuthentication:
296 intptr = &options->skey_authentication;
300 case oKerberosAuthentication:
301 intptr = &options->kerberos_authentication;
306 case oKerberosTgtPassing:
307 intptr = &options->kerberos_tgt_passing;
310 case oAFSTokenPassing:
311 intptr = &options->afs_token_passing;
316 intptr = &options->fallback_to_rsh;
320 intptr = &options->use_rsh;
324 intptr = &options->batch_mode;
328 intptr = &options->check_host_ip;
331 case oStrictHostKeyChecking:
332 intptr = &options->strict_host_key_checking;
333 cp = strtok(NULL, WHITESPACE);
335 fatal("%.200s line %d: Missing yes/no argument.",
337 value = 0; /* To avoid compiler warning... */
338 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
340 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
342 else if (strcmp(cp, "ask") == 0)
345 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
346 if (*activep && *intptr == -1)
351 intptr = &options->compression;
355 intptr = &options->keepalives;
358 case oNumberOfPasswordPrompts:
359 intptr = &options->number_of_password_prompts;
362 case oCompressionLevel:
363 intptr = &options->compression_level;
367 cp = strtok(NULL, WHITESPACE);
369 fatal("%.200s line %d: Missing argument.", filename, linenum);
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);
379 charptr = &options->user;
381 cp = strtok(NULL, WHITESPACE);
383 fatal("%.200s line %d: Missing argument.", filename, linenum);
384 if (*activep && *charptr == NULL)
385 *charptr = xstrdup(cp);
388 case oGlobalKnownHostsFile:
389 charptr = &options->system_hostfile;
392 case oUserKnownHostsFile:
393 charptr = &options->user_hostfile;
397 charptr = &options->hostname;
401 charptr = &options->proxy_command;
402 string = xstrdup("");
403 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
404 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
408 if (*activep && *charptr == NULL)
415 intptr = &options->port;
417 cp = strtok(NULL, WHITESPACE);
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);
423 /* Octal, decimal, or hex format? */
424 value = strtol(cp, &cp2, 0);
426 fatal("%.200s line %d: Bad number.", filename, linenum);
427 if (*activep && *intptr == -1)
431 case oConnectionAttempts:
432 intptr = &options->connection_attempts;
436 intptr = &options->cipher;
437 cp = strtok(NULL, WHITESPACE);
438 value = cipher_number(cp);
440 fatal("%.200s line %d: Bad cipher '%s'.",
441 filename, linenum, cp ? cp : "<NONE>");
442 if (*activep && *intptr == -1)
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;
458 cp = strtok(NULL, WHITESPACE);
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.",
465 cp = strtok(NULL, WHITESPACE);
467 fatal("%.200s line %d: Missing second argument.",
469 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
470 fatal("%.200s line %d: Badly formatted host:port.",
473 add_remote_forward(options, fwd_port, buf, fwd_host_port);
477 cp = strtok(NULL, WHITESPACE);
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.",
484 cp = strtok(NULL, WHITESPACE);
486 fatal("%.200s line %d: Missing second argument.",
488 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
489 fatal("%.200s line %d: Badly formatted host:port.",
492 add_local_forward(options, fwd_port, buf, fwd_host_port);
497 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
498 if (match_pattern(host, cp)) {
499 debug("Applying options for %.100s", cp);
503 /* Avoid garbage check below, as strtok already returned NULL. */
507 intptr = &options->escape_char;
508 cp = strtok(NULL, WHITESPACE);
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)
519 fatal("%.200s line %d: Bad escape character.",
522 value = 0; /* Avoid compiler warning. */
524 if (*activep && *intptr == -1)
529 fatal("process_config_line: Unimplemented opcode %d", opcode);
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.",
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.
547 read_config_file(const char *filename, const char *host, Options *options)
555 f = fopen(filename, "r");
559 debug("Reading configuration data %.200s", filename);
562 * Mark that we are now processing the options. This flag is turned
563 * on/off by Host specifications.
567 while (fgets(line, sizeof(line), f)) {
568 /* Update line number counter. */
570 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
575 fatal("%s: terminating, %d bad configuration options\n",
576 filename, bad_options);
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.
587 initialize_options(Options * options)
589 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;
598 options->kerberos_authentication = -1;
601 options->kerberos_tgt_passing = -1;
602 options->afs_token_passing = -1;
604 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;
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;
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.
636 fill_default_options(Options * options)
638 if (options->forward_agent == -1)
639 options->forward_agent = 1;
640 if (options->forward_x11 == -1)
641 options->forward_x11 = 0;
642 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;
653 if (options->kerberos_authentication == -1)
654 options->kerberos_authentication = 1;
657 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;
662 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;
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 */