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.
26 /* Format of the configuration file:
28 # Configuration data is parsed as follows:
29 # 1. command line options
30 # 2. user-specific file
32 # Any configuration value is only changed the first time it is set.
33 # Thus, host-specific definitions should be at the beginning of the
34 # configuration file, and defaults at the end.
36 # Host-specific declarations. These may override anything above. A single
37 # host may match multiple declarations; these are processed in the order
38 # that they are given in.
44 HostName another.host.name.real.org
51 RemoteForward 9999 shadows.cs.hut.fi:9999
57 RhostsAuthentication no
58 PasswordAuthentication no
62 ProxyCommand ssh-proxy %h %p
69 PasswordAuthentication no
71 # Defaults for various options
75 RhostsAuthentication yes
76 PasswordAuthentication yes
78 RhostsRSAAuthentication yes
81 StrictHostKeyChecking yes
83 IdentityFile ~/.ssh/identity
93 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
94 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
97 oKerberosAuthentication,
100 oKerberosTgtPassing, oAFSTokenPassing,
102 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
103 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
104 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
105 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
106 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
107 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
108 oGlobalKnownHostsFile2, oUserKnownHostsFile2
111 /* Textual representations of the tokens. */
117 { "forwardagent", oForwardAgent },
118 { "forwardx11", oForwardX11 },
119 { "gatewayports", oGatewayPorts },
120 { "useprivilegedport", oUsePrivilegedPort },
121 { "rhostsauthentication", oRhostsAuthentication },
122 { "passwordauthentication", oPasswordAuthentication },
123 { "rsaauthentication", oRSAAuthentication },
124 { "skeyauthentication", oSkeyAuthentication },
126 { "kerberosauthentication", oKerberosAuthentication },
129 { "kerberostgtpassing", oKerberosTgtPassing },
130 { "afstokenpassing", oAFSTokenPassing },
132 { "fallbacktorsh", oFallBackToRsh },
133 { "usersh", oUseRsh },
134 { "identityfile", oIdentityFile },
135 { "identityfile2", oIdentityFile2 },
136 { "hostname", oHostName },
137 { "proxycommand", oProxyCommand },
139 { "cipher", oCipher },
140 { "ciphers", oCiphers },
141 { "protocol", oProtocol },
142 { "remoteforward", oRemoteForward },
143 { "localforward", oLocalForward },
146 { "escapechar", oEscapeChar },
147 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
148 { "globalknownhostsfile", oGlobalKnownHostsFile },
149 { "userknownhostsfile", oUserKnownHostsFile },
150 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
151 { "userknownhostsfile2", oUserKnownHostsFile2 },
152 { "connectionattempts", oConnectionAttempts },
153 { "batchmode", oBatchMode },
154 { "checkhostip", oCheckHostIP },
155 { "stricthostkeychecking", oStrictHostKeyChecking },
156 { "compression", oCompression },
157 { "compressionlevel", oCompressionLevel },
158 { "keepalive", oKeepAlives },
159 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
160 { "tisauthentication", oTISAuthentication },
161 { "loglevel", oLogLevel },
165 /* Characters considered whitespace in strtok calls. */
166 #define WHITESPACE " \t\r\n"
170 * Adds a local TCP/IP port forward to options. Never returns if there is an
175 add_local_forward(Options *options, u_short port, const char *host,
179 extern uid_t original_real_uid;
180 if (port < IPPORT_RESERVED && original_real_uid != 0)
181 fatal("Privileged ports can only be forwarded by root.\n");
182 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
183 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
184 fwd = &options->local_forwards[options->num_local_forwards++];
186 fwd->host = xstrdup(host);
187 fwd->host_port = host_port;
191 * Adds a remote TCP/IP port forward to options. Never returns if there is
196 add_remote_forward(Options *options, u_short port, const char *host,
200 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
201 fatal("Too many remote forwards (max %d).",
202 SSH_MAX_FORWARDS_PER_DIRECTION);
203 fwd = &options->remote_forwards[options->num_remote_forwards++];
205 fwd->host = xstrdup(host);
206 fwd->host_port = host_port;
210 * Returns the number of the token pointed to by cp of length len. Never
211 * returns if the token is not known.
215 parse_token(const char *cp, const char *filename, int linenum)
219 for (i = 0; keywords[i].name; i++)
220 if (strcasecmp(cp, keywords[i].name) == 0)
221 return keywords[i].opcode;
223 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
224 filename, linenum, cp);
229 * Processes a single option line as used in the configuration files. This
230 * only sets those values that have not already been set.
234 process_config_line(Options *options, const char *host,
235 char *line, const char *filename, int linenum,
238 char buf[256], *cp, *string, **charptr, *cp2;
239 int opcode, *intptr, value;
240 u_short fwd_port, fwd_host_port;
242 /* Skip leading whitespace. */
243 cp = line + strspn(line, WHITESPACE);
244 if (!*cp || *cp == '\n' || *cp == '#')
247 /* Get the keyword. (Each line is supposed to begin with a keyword). */
248 cp = strtok(cp, WHITESPACE);
249 opcode = parse_token(cp, filename, linenum);
253 /* don't panic, but count bad options */
257 intptr = &options->forward_agent;
259 cp = strtok(NULL, WHITESPACE);
261 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
262 value = 0; /* To avoid compiler warning... */
263 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
265 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
268 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
269 if (*activep && *intptr == -1)
274 intptr = &options->forward_x11;
278 intptr = &options->gateway_ports;
281 case oUsePrivilegedPort:
282 intptr = &options->use_privileged_port;
285 case oRhostsAuthentication:
286 intptr = &options->rhosts_authentication;
289 case oPasswordAuthentication:
290 intptr = &options->password_authentication;
293 case oRSAAuthentication:
294 intptr = &options->rsa_authentication;
297 case oRhostsRSAAuthentication:
298 intptr = &options->rhosts_rsa_authentication;
301 case oTISAuthentication:
302 /* fallthrough, there is no difference on the client side */
303 case oSkeyAuthentication:
304 intptr = &options->skey_authentication;
308 case oKerberosAuthentication:
309 intptr = &options->kerberos_authentication;
314 case oKerberosTgtPassing:
315 intptr = &options->kerberos_tgt_passing;
318 case oAFSTokenPassing:
319 intptr = &options->afs_token_passing;
324 intptr = &options->fallback_to_rsh;
328 intptr = &options->use_rsh;
332 intptr = &options->batch_mode;
336 intptr = &options->check_host_ip;
339 case oStrictHostKeyChecking:
340 intptr = &options->strict_host_key_checking;
341 cp = strtok(NULL, WHITESPACE);
343 fatal("%.200s line %d: Missing yes/no argument.",
345 value = 0; /* To avoid compiler warning... */
346 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
348 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
350 else if (strcmp(cp, "ask") == 0)
353 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
354 if (*activep && *intptr == -1)
359 intptr = &options->compression;
363 intptr = &options->keepalives;
366 case oNumberOfPasswordPrompts:
367 intptr = &options->number_of_password_prompts;
370 case oCompressionLevel:
371 intptr = &options->compression_level;
376 cp = strtok(NULL, WHITESPACE);
378 fatal("%.200s line %d: Missing argument.", filename, linenum);
380 intptr = (opcode == oIdentityFile) ?
381 &options->num_identity_files :
382 &options->num_identity_files2;
383 if (*intptr >= SSH_MAX_IDENTITY_FILES)
384 fatal("%.200s line %d: Too many identity files specified (max %d).",
385 filename, linenum, SSH_MAX_IDENTITY_FILES);
386 charptr = (opcode == oIdentityFile) ?
387 &options->identity_files[*intptr] :
388 &options->identity_files2[*intptr];
389 *charptr = xstrdup(cp);
390 *intptr = *intptr + 1;
395 charptr = &options->user;
397 cp = strtok(NULL, WHITESPACE);
399 fatal("%.200s line %d: Missing argument.", filename, linenum);
400 if (*activep && *charptr == NULL)
401 *charptr = xstrdup(cp);
404 case oGlobalKnownHostsFile:
405 charptr = &options->system_hostfile;
408 case oUserKnownHostsFile:
409 charptr = &options->user_hostfile;
412 case oGlobalKnownHostsFile2:
413 charptr = &options->system_hostfile2;
416 case oUserKnownHostsFile2:
417 charptr = &options->user_hostfile2;
421 charptr = &options->hostname;
425 charptr = &options->proxy_command;
426 string = xstrdup("");
427 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
428 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
432 if (*activep && *charptr == NULL)
439 intptr = &options->port;
441 cp = strtok(NULL, WHITESPACE);
443 fatal("%.200s line %d: Missing argument.", filename, linenum);
444 if (cp[0] < '0' || cp[0] > '9')
445 fatal("%.200s line %d: Bad number.", filename, linenum);
447 /* Octal, decimal, or hex format? */
448 value = strtol(cp, &cp2, 0);
450 fatal("%.200s line %d: Bad number.", filename, linenum);
451 if (*activep && *intptr == -1)
455 case oConnectionAttempts:
456 intptr = &options->connection_attempts;
460 intptr = &options->cipher;
461 cp = strtok(NULL, WHITESPACE);
462 value = cipher_number(cp);
464 fatal("%.200s line %d: Bad cipher '%s'.",
465 filename, linenum, cp ? cp : "<NONE>");
466 if (*activep && *intptr == -1)
471 cp = strtok(NULL, WHITESPACE);
472 if (!ciphers_valid(cp))
473 fatal("%.200s line %d: Bad cipher spec '%s'.",
474 filename, linenum, cp ? cp : "<NONE>");
475 if (*activep && options->ciphers == NULL)
476 options->ciphers = xstrdup(cp);
480 intptr = &options->protocol;
481 cp = strtok(NULL, WHITESPACE);
482 value = proto_spec(cp);
483 if (value == SSH_PROTO_UNKNOWN)
484 fatal("%.200s line %d: Bad protocol spec '%s'.",
485 filename, linenum, cp ? cp : "<NONE>");
486 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
491 intptr = (int *) &options->log_level;
492 cp = strtok(NULL, WHITESPACE);
493 value = log_level_number(cp);
494 if (value == (LogLevel) - 1)
495 fatal("%.200s line %d: unsupported log level '%s'\n",
496 filename, linenum, cp ? cp : "<NONE>");
497 if (*activep && (LogLevel) * intptr == -1)
498 *intptr = (LogLevel) value;
502 cp = strtok(NULL, WHITESPACE);
504 fatal("%.200s line %d: Missing argument.", filename, linenum);
505 if (cp[0] < '0' || cp[0] > '9')
506 fatal("%.200s line %d: Badly formatted port number.",
509 cp = strtok(NULL, WHITESPACE);
511 fatal("%.200s line %d: Missing second argument.",
513 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
514 fatal("%.200s line %d: Badly formatted host:port.",
517 add_remote_forward(options, fwd_port, buf, fwd_host_port);
521 cp = strtok(NULL, WHITESPACE);
523 fatal("%.200s line %d: Missing argument.", filename, linenum);
524 if (cp[0] < '0' || cp[0] > '9')
525 fatal("%.200s line %d: Badly formatted port number.",
528 cp = strtok(NULL, WHITESPACE);
530 fatal("%.200s line %d: Missing second argument.",
532 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
533 fatal("%.200s line %d: Badly formatted host:port.",
536 add_local_forward(options, fwd_port, buf, fwd_host_port);
541 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
542 if (match_pattern(host, cp)) {
543 debug("Applying options for %.100s", cp);
547 /* Avoid garbage check below, as strtok already returned NULL. */
551 intptr = &options->escape_char;
552 cp = strtok(NULL, WHITESPACE);
554 fatal("%.200s line %d: Missing argument.", filename, linenum);
555 if (cp[0] == '^' && cp[2] == 0 &&
556 (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
557 value = (unsigned char) cp[1] & 31;
558 else if (strlen(cp) == 1)
559 value = (unsigned char) cp[0];
560 else if (strcmp(cp, "none") == 0)
563 fatal("%.200s line %d: Bad escape character.",
566 value = 0; /* Avoid compiler warning. */
568 if (*activep && *intptr == -1)
573 fatal("process_config_line: Unimplemented opcode %d", opcode);
576 /* Check that there is no garbage at end of line. */
577 if (strtok(NULL, WHITESPACE) != NULL)
578 fatal("%.200s line %d: garbage at end of line.",
585 * Reads the config file and modifies the options accordingly. Options
586 * should already be initialized before this call. This never returns if
587 * there is an error. If the file does not exist, this returns immediately.
591 read_config_file(const char *filename, const char *host, Options *options)
599 f = fopen(filename, "r");
603 debug("Reading configuration data %.200s", filename);
606 * Mark that we are now processing the options. This flag is turned
607 * on/off by Host specifications.
611 while (fgets(line, sizeof(line), f)) {
612 /* Update line number counter. */
614 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
619 fatal("%s: terminating, %d bad configuration options\n",
620 filename, bad_options);
624 * Initializes options to special values that indicate that they have not yet
625 * been set. Read_config_file will only set options with this value. Options
626 * are processed in the following order: command line, user config file,
627 * system config file. Last, fill_default_options is called.
631 initialize_options(Options * options)
633 memset(options, 'X', sizeof(*options));
634 options->forward_agent = -1;
635 options->forward_x11 = -1;
636 options->gateway_ports = -1;
637 options->use_privileged_port = -1;
638 options->rhosts_authentication = -1;
639 options->rsa_authentication = -1;
640 options->skey_authentication = -1;
642 options->kerberos_authentication = -1;
645 options->kerberos_tgt_passing = -1;
646 options->afs_token_passing = -1;
648 options->password_authentication = -1;
649 options->rhosts_rsa_authentication = -1;
650 options->fallback_to_rsh = -1;
651 options->use_rsh = -1;
652 options->batch_mode = -1;
653 options->check_host_ip = -1;
654 options->strict_host_key_checking = -1;
655 options->compression = -1;
656 options->keepalives = -1;
657 options->compression_level = -1;
659 options->connection_attempts = -1;
660 options->number_of_password_prompts = -1;
661 options->cipher = -1;
662 options->ciphers = NULL;
663 options->protocol = SSH_PROTO_UNKNOWN;
664 options->num_identity_files = 0;
665 options->num_identity_files2 = 0;
666 options->hostname = NULL;
667 options->proxy_command = NULL;
668 options->user = NULL;
669 options->escape_char = -1;
670 options->system_hostfile = NULL;
671 options->user_hostfile = NULL;
672 options->system_hostfile2 = NULL;
673 options->user_hostfile2 = NULL;
674 options->num_local_forwards = 0;
675 options->num_remote_forwards = 0;
676 options->log_level = (LogLevel) - 1;
680 * Called after processing other sources of option data, this fills those
681 * options for which no value has been specified with their default values.
685 fill_default_options(Options * options)
687 if (options->forward_agent == -1)
688 options->forward_agent = 1;
689 if (options->forward_x11 == -1)
690 options->forward_x11 = 0;
691 if (options->gateway_ports == -1)
692 options->gateway_ports = 0;
693 if (options->use_privileged_port == -1)
694 options->use_privileged_port = 1;
695 if (options->rhosts_authentication == -1)
696 options->rhosts_authentication = 1;
697 if (options->rsa_authentication == -1)
698 options->rsa_authentication = 1;
699 if (options->skey_authentication == -1)
700 options->skey_authentication = 0;
702 if (options->kerberos_authentication == -1)
703 options->kerberos_authentication = 1;
706 if (options->kerberos_tgt_passing == -1)
707 options->kerberos_tgt_passing = 1;
708 if (options->afs_token_passing == -1)
709 options->afs_token_passing = 1;
711 if (options->password_authentication == -1)
712 options->password_authentication = 1;
713 if (options->rhosts_rsa_authentication == -1)
714 options->rhosts_rsa_authentication = 1;
715 if (options->fallback_to_rsh == -1)
716 options->fallback_to_rsh = 1;
717 if (options->use_rsh == -1)
718 options->use_rsh = 0;
719 if (options->batch_mode == -1)
720 options->batch_mode = 0;
721 if (options->check_host_ip == -1)
722 options->check_host_ip = 1;
723 if (options->strict_host_key_checking == -1)
724 options->strict_host_key_checking = 2; /* 2 is default */
725 if (options->compression == -1)
726 options->compression = 0;
727 if (options->keepalives == -1)
728 options->keepalives = 1;
729 if (options->compression_level == -1)
730 options->compression_level = 6;
731 if (options->port == -1)
732 options->port = 0; /* Filled in ssh_connect. */
733 if (options->connection_attempts == -1)
734 options->connection_attempts = 4;
735 if (options->number_of_password_prompts == -1)
736 options->number_of_password_prompts = 3;
737 /* Selected in ssh_login(). */
738 if (options->cipher == -1)
739 options->cipher = SSH_CIPHER_NOT_SET;
740 if (options->protocol == SSH_PROTO_UNKNOWN)
741 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
742 if (options->num_identity_files == 0) {
743 options->identity_files[0] =
744 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
745 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
746 options->num_identity_files = 1;
749 if (options->num_identity_files2 == 0) {
750 options->identity_files2[0] =
751 xmalloc(2 + strlen(SSH2_CLIENT_IDENTITY) + 1);
752 sprintf(options->identity_files2[0], "~/%.100s", SSH2_CLIENT_IDENTITY);
753 options->num_identity_files2 = 1;
756 if (options->escape_char == -1)
757 options->escape_char = '~';
758 if (options->system_hostfile == NULL)
759 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
760 if (options->user_hostfile == NULL)
761 options->user_hostfile = SSH_USER_HOSTFILE;
762 if (options->system_hostfile2 == NULL)
763 options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
764 if (options->user_hostfile2 == NULL)
765 options->user_hostfile2 = SSH_USER_HOSTFILE2;
766 if (options->log_level == (LogLevel) - 1)
767 options->log_level = SYSLOG_LEVEL_INFO;
768 /* options->proxy_command should not be set by default */
769 /* options->user will be set in the main program if appropriate */
770 /* options->hostname will be set in the main program if appropriate */