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, int port, const char *host,
171 extern uid_t original_real_uid;
172 if ((port & 0xffff) != port)
173 fatal("Requested forwarding of nonexistent port %d.", port);
174 if (port < IPPORT_RESERVED && original_real_uid != 0)
175 fatal("Privileged ports can only be forwarded by root.\n");
176 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
177 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
178 fwd = &options->local_forwards[options->num_local_forwards++];
180 fwd->host = xstrdup(host);
181 fwd->host_port = host_port;
185 * Adds a remote TCP/IP port forward to options. Never returns if there is
190 add_remote_forward(Options *options, int port, const char *host,
194 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
195 fatal("Too many remote forwards (max %d).",
196 SSH_MAX_FORWARDS_PER_DIRECTION);
197 fwd = &options->remote_forwards[options->num_remote_forwards++];
199 fwd->host = xstrdup(host);
200 fwd->host_port = host_port;
204 * Returns the number of the token pointed to by cp of length len. Never
205 * returns if the token is not known.
209 parse_token(const char *cp, const char *filename, int linenum)
213 for (i = 0; keywords[i].name; i++)
214 if (strcasecmp(cp, keywords[i].name) == 0)
215 return keywords[i].opcode;
217 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
218 filename, linenum, cp);
223 * Processes a single option line as used in the configuration files. This
224 * only sets those values that have not already been set.
228 process_config_line(Options *options, const char *host,
229 char *line, const char *filename, int linenum,
232 char buf[256], *cp, *string, **charptr, *cp2;
233 int opcode, *intptr, value, fwd_port, fwd_host_port;
235 /* Skip leading whitespace. */
236 cp = line + strspn(line, WHITESPACE);
237 if (!*cp || *cp == '\n' || *cp == '#')
240 /* Get the keyword. (Each line is supposed to begin with a keyword). */
241 cp = strtok(cp, WHITESPACE);
242 opcode = parse_token(cp, filename, linenum);
246 /* don't panic, but count bad options */
250 intptr = &options->forward_agent;
252 cp = strtok(NULL, WHITESPACE);
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)
258 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
261 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
262 if (*activep && *intptr == -1)
267 intptr = &options->forward_x11;
271 intptr = &options->gateway_ports;
274 case oUsePrivilegedPort:
275 intptr = &options->use_privileged_port;
278 case oRhostsAuthentication:
279 intptr = &options->rhosts_authentication;
282 case oPasswordAuthentication:
283 intptr = &options->password_authentication;
286 case oRSAAuthentication:
287 intptr = &options->rsa_authentication;
290 case oRhostsRSAAuthentication:
291 intptr = &options->rhosts_rsa_authentication;
294 case oTISAuthentication:
295 /* fallthrough, there is no difference on the client side */
296 case oSkeyAuthentication:
297 intptr = &options->skey_authentication;
301 case oKerberosAuthentication:
302 intptr = &options->kerberos_authentication;
307 case oKerberosTgtPassing:
308 intptr = &options->kerberos_tgt_passing;
311 case oAFSTokenPassing:
312 intptr = &options->afs_token_passing;
317 intptr = &options->fallback_to_rsh;
321 intptr = &options->use_rsh;
325 intptr = &options->batch_mode;
329 intptr = &options->check_host_ip;
332 case oStrictHostKeyChecking:
333 intptr = &options->strict_host_key_checking;
334 cp = strtok(NULL, WHITESPACE);
336 fatal("%.200s line %d: Missing yes/no argument.",
338 value = 0; /* To avoid compiler warning... */
339 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
341 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
343 else if (strcmp(cp, "ask") == 0)
346 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
347 if (*activep && *intptr == -1)
352 intptr = &options->compression;
356 intptr = &options->keepalives;
359 case oNumberOfPasswordPrompts:
360 intptr = &options->number_of_password_prompts;
363 case oCompressionLevel:
364 intptr = &options->compression_level;
368 cp = strtok(NULL, WHITESPACE);
370 fatal("%.200s line %d: Missing argument.", filename, linenum);
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);
380 charptr = &options->user;
382 cp = strtok(NULL, WHITESPACE);
384 fatal("%.200s line %d: Missing argument.", filename, linenum);
385 if (*activep && *charptr == NULL)
386 *charptr = xstrdup(cp);
389 case oGlobalKnownHostsFile:
390 charptr = &options->system_hostfile;
393 case oUserKnownHostsFile:
394 charptr = &options->user_hostfile;
398 charptr = &options->hostname;
402 charptr = &options->proxy_command;
403 string = xstrdup("");
404 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
405 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
409 if (*activep && *charptr == NULL)
416 intptr = &options->port;
418 cp = strtok(NULL, WHITESPACE);
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);
424 /* Octal, decimal, or hex format? */
425 value = strtol(cp, &cp2, 0);
427 fatal("%.200s line %d: Bad number.", filename, linenum);
428 if (*activep && *intptr == -1)
432 case oConnectionAttempts:
433 intptr = &options->connection_attempts;
437 intptr = &options->cipher;
438 cp = strtok(NULL, WHITESPACE);
439 value = cipher_number(cp);
441 fatal("%.200s line %d: Bad cipher '%s'.",
442 filename, linenum, cp ? cp : "<NONE>");
443 if (*activep && *intptr == -1)
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;
459 cp = strtok(NULL, WHITESPACE);
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.",
466 cp = strtok(NULL, WHITESPACE);
468 fatal("%.200s line %d: Missing second argument.",
470 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
471 fatal("%.200s line %d: Badly formatted host:port.",
474 add_remote_forward(options, fwd_port, buf, fwd_host_port);
478 cp = strtok(NULL, WHITESPACE);
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.",
485 cp = strtok(NULL, WHITESPACE);
487 fatal("%.200s line %d: Missing second argument.",
489 if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
490 fatal("%.200s line %d: Badly formatted host:port.",
493 add_local_forward(options, fwd_port, buf, fwd_host_port);
498 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
499 if (match_pattern(host, cp)) {
500 debug("Applying options for %.100s", cp);
504 /* Avoid garbage check below, as strtok already returned NULL. */
508 intptr = &options->escape_char;
509 cp = strtok(NULL, WHITESPACE);
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)
520 fatal("%.200s line %d: Bad escape character.",
523 value = 0; /* Avoid compiler warning. */
525 if (*activep && *intptr == -1)
530 fatal("process_config_line: Unimplemented opcode %d", opcode);
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.",
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.
548 read_config_file(const char *filename, const char *host, Options *options)
556 f = fopen(filename, "r");
560 debug("Reading configuration data %.200s", filename);
563 * Mark that we are now processing the options. This flag is turned
564 * on/off by Host specifications.
568 while (fgets(line, sizeof(line), f)) {
569 /* Update line number counter. */
571 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
576 fatal("%s: terminating, %d bad configuration options\n",
577 filename, bad_options);
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.
588 initialize_options(Options * options)
590 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;
599 options->kerberos_authentication = -1;
602 options->kerberos_tgt_passing = -1;
603 options->afs_token_passing = -1;
605 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;
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;
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.
637 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;
651 if (options->skey_authentication == -1)
652 options->skey_authentication = 0;
654 if (options->kerberos_authentication == -1)
655 options->kerberos_authentication = 1;
658 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;
663 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;
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 */