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, oDSAAuthentication
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 { "dsaauthentication", oDSAAuthentication },
125 { "skeyauthentication", oSkeyAuthentication },
127 { "kerberosauthentication", oKerberosAuthentication },
130 { "kerberostgtpassing", oKerberosTgtPassing },
131 { "afstokenpassing", oAFSTokenPassing },
133 { "fallbacktorsh", oFallBackToRsh },
134 { "usersh", oUseRsh },
135 { "identityfile", oIdentityFile },
136 { "identityfile2", oIdentityFile2 },
137 { "hostname", oHostName },
138 { "proxycommand", oProxyCommand },
140 { "cipher", oCipher },
141 { "ciphers", oCiphers },
142 { "protocol", oProtocol },
143 { "remoteforward", oRemoteForward },
144 { "localforward", oLocalForward },
147 { "escapechar", oEscapeChar },
148 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
149 { "globalknownhostsfile", oGlobalKnownHostsFile },
150 { "userknownhostsfile", oUserKnownHostsFile },
151 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
152 { "userknownhostsfile2", oUserKnownHostsFile2 },
153 { "connectionattempts", oConnectionAttempts },
154 { "batchmode", oBatchMode },
155 { "checkhostip", oCheckHostIP },
156 { "stricthostkeychecking", oStrictHostKeyChecking },
157 { "compression", oCompression },
158 { "compressionlevel", oCompressionLevel },
159 { "keepalive", oKeepAlives },
160 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
161 { "tisauthentication", oTISAuthentication },
162 { "loglevel", oLogLevel },
166 /* Characters considered whitespace in strtok calls. */
167 #define WHITESPACE " \t\r\n"
171 * Adds a local TCP/IP port forward to options. Never returns if there is an
176 add_local_forward(Options *options, u_short port, const char *host,
180 extern uid_t original_real_uid;
181 if (port < IPPORT_RESERVED && original_real_uid != 0)
182 fatal("Privileged ports can only be forwarded by root.\n");
183 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
184 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
185 fwd = &options->local_forwards[options->num_local_forwards++];
187 fwd->host = xstrdup(host);
188 fwd->host_port = host_port;
192 * Adds a remote TCP/IP port forward to options. Never returns if there is
197 add_remote_forward(Options *options, u_short port, const char *host,
201 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
202 fatal("Too many remote forwards (max %d).",
203 SSH_MAX_FORWARDS_PER_DIRECTION);
204 fwd = &options->remote_forwards[options->num_remote_forwards++];
206 fwd->host = xstrdup(host);
207 fwd->host_port = host_port;
211 * Returns the number of the token pointed to by cp of length len. Never
212 * returns if the token is not known.
216 parse_token(const char *cp, const char *filename, int linenum)
220 for (i = 0; keywords[i].name; i++)
221 if (strcasecmp(cp, keywords[i].name) == 0)
222 return keywords[i].opcode;
224 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
225 filename, linenum, cp);
230 * Processes a single option line as used in the configuration files. This
231 * only sets those values that have not already been set.
235 process_config_line(Options *options, const char *host,
236 char *line, const char *filename, int linenum,
239 char buf[256], *cp, *string, **charptr, *cp2;
240 int opcode, *intptr, value;
241 u_short fwd_port, fwd_host_port;
243 /* Skip leading whitespace. */
244 cp = line + strspn(line, WHITESPACE);
245 if (!*cp || *cp == '\n' || *cp == '#')
248 /* Get the keyword. (Each line is supposed to begin with a keyword). */
249 cp = strtok(cp, WHITESPACE);
250 opcode = parse_token(cp, filename, linenum);
254 /* don't panic, but count bad options */
258 intptr = &options->forward_agent;
260 cp = strtok(NULL, WHITESPACE);
262 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
263 value = 0; /* To avoid compiler warning... */
264 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
266 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
269 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
270 if (*activep && *intptr == -1)
275 intptr = &options->forward_x11;
279 intptr = &options->gateway_ports;
282 case oUsePrivilegedPort:
283 intptr = &options->use_privileged_port;
286 case oRhostsAuthentication:
287 intptr = &options->rhosts_authentication;
290 case oPasswordAuthentication:
291 intptr = &options->password_authentication;
294 case oDSAAuthentication:
295 intptr = &options->dsa_authentication;
298 case oRSAAuthentication:
299 intptr = &options->rsa_authentication;
302 case oRhostsRSAAuthentication:
303 intptr = &options->rhosts_rsa_authentication;
306 case oTISAuthentication:
307 /* fallthrough, there is no difference on the client side */
308 case oSkeyAuthentication:
309 intptr = &options->skey_authentication;
313 case oKerberosAuthentication:
314 intptr = &options->kerberos_authentication;
319 case oKerberosTgtPassing:
320 intptr = &options->kerberos_tgt_passing;
323 case oAFSTokenPassing:
324 intptr = &options->afs_token_passing;
329 intptr = &options->fallback_to_rsh;
333 intptr = &options->use_rsh;
337 intptr = &options->batch_mode;
341 intptr = &options->check_host_ip;
344 case oStrictHostKeyChecking:
345 intptr = &options->strict_host_key_checking;
346 cp = strtok(NULL, WHITESPACE);
348 fatal("%.200s line %d: Missing yes/no argument.",
350 value = 0; /* To avoid compiler warning... */
351 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
353 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
355 else if (strcmp(cp, "ask") == 0)
358 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
359 if (*activep && *intptr == -1)
364 intptr = &options->compression;
368 intptr = &options->keepalives;
371 case oNumberOfPasswordPrompts:
372 intptr = &options->number_of_password_prompts;
375 case oCompressionLevel:
376 intptr = &options->compression_level;
381 cp = strtok(NULL, WHITESPACE);
383 fatal("%.200s line %d: Missing argument.", filename, linenum);
385 intptr = (opcode == oIdentityFile) ?
386 &options->num_identity_files :
387 &options->num_identity_files2;
388 if (*intptr >= SSH_MAX_IDENTITY_FILES)
389 fatal("%.200s line %d: Too many identity files specified (max %d).",
390 filename, linenum, SSH_MAX_IDENTITY_FILES);
391 charptr = (opcode == oIdentityFile) ?
392 &options->identity_files[*intptr] :
393 &options->identity_files2[*intptr];
394 *charptr = xstrdup(cp);
395 *intptr = *intptr + 1;
400 charptr = &options->user;
402 cp = strtok(NULL, WHITESPACE);
404 fatal("%.200s line %d: Missing argument.", filename, linenum);
405 if (*activep && *charptr == NULL)
406 *charptr = xstrdup(cp);
409 case oGlobalKnownHostsFile:
410 charptr = &options->system_hostfile;
413 case oUserKnownHostsFile:
414 charptr = &options->user_hostfile;
417 case oGlobalKnownHostsFile2:
418 charptr = &options->system_hostfile2;
421 case oUserKnownHostsFile2:
422 charptr = &options->user_hostfile2;
426 charptr = &options->hostname;
430 charptr = &options->proxy_command;
431 string = xstrdup("");
432 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
433 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
437 if (*activep && *charptr == NULL)
444 intptr = &options->port;
446 cp = strtok(NULL, WHITESPACE);
448 fatal("%.200s line %d: Missing argument.", filename, linenum);
449 if (cp[0] < '0' || cp[0] > '9')
450 fatal("%.200s line %d: Bad number.", filename, linenum);
452 /* Octal, decimal, or hex format? */
453 value = strtol(cp, &cp2, 0);
455 fatal("%.200s line %d: Bad number.", filename, linenum);
456 if (*activep && *intptr == -1)
460 case oConnectionAttempts:
461 intptr = &options->connection_attempts;
465 intptr = &options->cipher;
466 cp = strtok(NULL, WHITESPACE);
468 fatal("%.200s line %d: Missing argument.", filename, linenum);
469 value = cipher_number(cp);
471 fatal("%.200s line %d: Bad cipher '%s'.",
472 filename, linenum, cp ? cp : "<NONE>");
473 if (*activep && *intptr == -1)
478 cp = strtok(NULL, WHITESPACE);
480 fatal("%.200s line %d: Missing argument.", filename, linenum);
481 if (!ciphers_valid(cp))
482 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
483 filename, linenum, cp ? cp : "<NONE>");
484 if (*activep && options->ciphers == NULL)
485 options->ciphers = xstrdup(cp);
489 intptr = &options->protocol;
490 cp = strtok(NULL, WHITESPACE);
492 fatal("%.200s line %d: Missing argument.", filename, linenum);
493 value = proto_spec(cp);
494 if (value == SSH_PROTO_UNKNOWN)
495 fatal("%.200s line %d: Bad protocol spec '%s'.",
496 filename, linenum, cp ? cp : "<NONE>");
497 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
502 intptr = (int *) &options->log_level;
503 cp = strtok(NULL, WHITESPACE);
504 value = log_level_number(cp);
505 if (value == (LogLevel) - 1)
506 fatal("%.200s line %d: unsupported log level '%s'\n",
507 filename, linenum, cp ? cp : "<NONE>");
508 if (*activep && (LogLevel) * intptr == -1)
509 *intptr = (LogLevel) value;
513 cp = strtok(NULL, WHITESPACE);
515 fatal("%.200s line %d: Missing argument.", filename, linenum);
516 if (cp[0] < '0' || cp[0] > '9')
517 fatal("%.200s line %d: Badly formatted port number.",
520 cp = strtok(NULL, WHITESPACE);
522 fatal("%.200s line %d: Missing second argument.",
524 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
525 fatal("%.200s line %d: Badly formatted host:port.",
528 add_remote_forward(options, fwd_port, buf, fwd_host_port);
532 cp = strtok(NULL, WHITESPACE);
534 fatal("%.200s line %d: Missing argument.", filename, linenum);
535 if (cp[0] < '0' || cp[0] > '9')
536 fatal("%.200s line %d: Badly formatted port number.",
539 cp = strtok(NULL, WHITESPACE);
541 fatal("%.200s line %d: Missing second argument.",
543 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
544 fatal("%.200s line %d: Badly formatted host:port.",
547 add_local_forward(options, fwd_port, buf, fwd_host_port);
552 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
553 if (match_pattern(host, cp)) {
554 debug("Applying options for %.100s", cp);
558 /* Avoid garbage check below, as strtok already returned NULL. */
562 intptr = &options->escape_char;
563 cp = strtok(NULL, WHITESPACE);
565 fatal("%.200s line %d: Missing argument.", filename, linenum);
566 if (cp[0] == '^' && cp[2] == 0 &&
567 (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
568 value = (unsigned char) cp[1] & 31;
569 else if (strlen(cp) == 1)
570 value = (unsigned char) cp[0];
571 else if (strcmp(cp, "none") == 0)
574 fatal("%.200s line %d: Bad escape character.",
577 value = 0; /* Avoid compiler warning. */
579 if (*activep && *intptr == -1)
584 fatal("process_config_line: Unimplemented opcode %d", opcode);
587 /* Check that there is no garbage at end of line. */
588 if (strtok(NULL, WHITESPACE) != NULL)
589 fatal("%.200s line %d: garbage at end of line.",
596 * Reads the config file and modifies the options accordingly. Options
597 * should already be initialized before this call. This never returns if
598 * there is an error. If the file does not exist, this returns immediately.
602 read_config_file(const char *filename, const char *host, Options *options)
610 f = fopen(filename, "r");
614 debug("Reading configuration data %.200s", filename);
617 * Mark that we are now processing the options. This flag is turned
618 * on/off by Host specifications.
622 while (fgets(line, sizeof(line), f)) {
623 /* Update line number counter. */
625 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
630 fatal("%s: terminating, %d bad configuration options\n",
631 filename, bad_options);
635 * Initializes options to special values that indicate that they have not yet
636 * been set. Read_config_file will only set options with this value. Options
637 * are processed in the following order: command line, user config file,
638 * system config file. Last, fill_default_options is called.
642 initialize_options(Options * options)
644 memset(options, 'X', sizeof(*options));
645 options->forward_agent = -1;
646 options->forward_x11 = -1;
647 options->gateway_ports = -1;
648 options->use_privileged_port = -1;
649 options->rhosts_authentication = -1;
650 options->rsa_authentication = -1;
651 options->dsa_authentication = -1;
652 options->skey_authentication = -1;
654 options->kerberos_authentication = -1;
657 options->kerberos_tgt_passing = -1;
658 options->afs_token_passing = -1;
660 options->password_authentication = -1;
661 options->rhosts_rsa_authentication = -1;
662 options->fallback_to_rsh = -1;
663 options->use_rsh = -1;
664 options->batch_mode = -1;
665 options->check_host_ip = -1;
666 options->strict_host_key_checking = -1;
667 options->compression = -1;
668 options->keepalives = -1;
669 options->compression_level = -1;
671 options->connection_attempts = -1;
672 options->number_of_password_prompts = -1;
673 options->cipher = -1;
674 options->ciphers = NULL;
675 options->protocol = SSH_PROTO_UNKNOWN;
676 options->num_identity_files = 0;
677 options->num_identity_files2 = 0;
678 options->hostname = NULL;
679 options->proxy_command = NULL;
680 options->user = NULL;
681 options->escape_char = -1;
682 options->system_hostfile = NULL;
683 options->user_hostfile = NULL;
684 options->system_hostfile2 = NULL;
685 options->user_hostfile2 = NULL;
686 options->num_local_forwards = 0;
687 options->num_remote_forwards = 0;
688 options->log_level = (LogLevel) - 1;
692 * Called after processing other sources of option data, this fills those
693 * options for which no value has been specified with their default values.
697 fill_default_options(Options * options)
699 if (options->forward_agent == -1)
700 options->forward_agent = 0;
701 if (options->forward_x11 == -1)
702 options->forward_x11 = 0;
703 if (options->gateway_ports == -1)
704 options->gateway_ports = 0;
705 if (options->use_privileged_port == -1)
706 options->use_privileged_port = 1;
707 if (options->rhosts_authentication == -1)
708 options->rhosts_authentication = 1;
709 if (options->rsa_authentication == -1)
710 options->rsa_authentication = 1;
711 if (options->dsa_authentication == -1)
712 options->dsa_authentication = 1;
713 if (options->skey_authentication == -1)
714 options->skey_authentication = 0;
716 if (options->kerberos_authentication == -1)
717 options->kerberos_authentication = 1;
720 if (options->kerberos_tgt_passing == -1)
721 options->kerberos_tgt_passing = 1;
722 if (options->afs_token_passing == -1)
723 options->afs_token_passing = 1;
725 if (options->password_authentication == -1)
726 options->password_authentication = 1;
727 if (options->rhosts_rsa_authentication == -1)
728 options->rhosts_rsa_authentication = 1;
729 if (options->fallback_to_rsh == -1)
730 options->fallback_to_rsh = 1;
731 if (options->use_rsh == -1)
732 options->use_rsh = 0;
733 if (options->batch_mode == -1)
734 options->batch_mode = 0;
735 if (options->check_host_ip == -1)
736 options->check_host_ip = 1;
737 if (options->strict_host_key_checking == -1)
738 options->strict_host_key_checking = 2; /* 2 is default */
739 if (options->compression == -1)
740 options->compression = 0;
741 if (options->keepalives == -1)
742 options->keepalives = 1;
743 if (options->compression_level == -1)
744 options->compression_level = 6;
745 if (options->port == -1)
746 options->port = 0; /* Filled in ssh_connect. */
747 if (options->connection_attempts == -1)
748 options->connection_attempts = 4;
749 if (options->number_of_password_prompts == -1)
750 options->number_of_password_prompts = 3;
751 /* Selected in ssh_login(). */
752 if (options->cipher == -1)
753 options->cipher = SSH_CIPHER_NOT_SET;
754 /* options->ciphers, default set in myproposals.h */
755 if (options->protocol == SSH_PROTO_UNKNOWN)
756 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
757 if (options->num_identity_files == 0) {
758 options->identity_files[0] =
759 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
760 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
761 options->num_identity_files = 1;
763 if (options->num_identity_files2 == 0) {
764 options->identity_files2[0] =
765 xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
766 sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
767 options->num_identity_files2 = 1;
769 if (options->escape_char == -1)
770 options->escape_char = '~';
771 if (options->system_hostfile == NULL)
772 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
773 if (options->user_hostfile == NULL)
774 options->user_hostfile = SSH_USER_HOSTFILE;
775 if (options->system_hostfile2 == NULL)
776 options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
777 if (options->user_hostfile2 == NULL)
778 options->user_hostfile2 = SSH_USER_HOSTFILE2;
779 if (options->log_level == (LogLevel) - 1)
780 options->log_level = SYSLOG_LEVEL_INFO;
781 /* options->proxy_command should not be set by default */
782 /* options->user will be set in the main program if appropriate */
783 /* options->hostname will be set in the main program if appropriate */