2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * Functions for reading the configuration files.
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose. Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
15 RCSID("$OpenBSD: readconf.c,v 1.68 2001/03/19 17:07:23 markus Exp $");
21 #include "pathnames.h"
29 /* Format of the configuration file:
31 # Configuration data is parsed as follows:
32 # 1. command line options
33 # 2. user-specific file
35 # Any configuration value is only changed the first time it is set.
36 # Thus, host-specific definitions should be at the beginning of the
37 # configuration file, and defaults at the end.
39 # Host-specific declarations. These may override anything above. A single
40 # host may match multiple declarations; these are processed in the order
41 # that they are given in.
47 HostName another.host.name.real.org
54 RemoteForward 9999 shadows.cs.hut.fi:9999
60 RhostsAuthentication no
61 PasswordAuthentication no
65 ProxyCommand ssh-proxy %h %p
72 PasswordAuthentication no
74 # Defaults for various options
78 RhostsAuthentication yes
79 PasswordAuthentication yes
81 RhostsRSAAuthentication yes
84 StrictHostKeyChecking yes
86 IdentityFile ~/.ssh/identity
96 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
97 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
98 oChallengeResponseAuthentication, oXAuthLocation,
100 oKerberosAuthentication,
103 oKerberosTgtPassing, oAFSTokenPassing,
105 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
106 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
107 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
108 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
109 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
110 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
111 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
112 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
113 oPreferredAuthentications
116 /* Textual representations of the tokens. */
122 { "forwardagent", oForwardAgent },
123 { "forwardx11", oForwardX11 },
124 { "xauthlocation", oXAuthLocation },
125 { "gatewayports", oGatewayPorts },
126 { "useprivilegedport", oUsePrivilegedPort },
127 { "rhostsauthentication", oRhostsAuthentication },
128 { "passwordauthentication", oPasswordAuthentication },
129 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
130 { "kbdinteractivedevices", oKbdInteractiveDevices },
131 { "rsaauthentication", oRSAAuthentication },
132 { "pubkeyauthentication", oPubkeyAuthentication },
133 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
134 { "challengeresponseauthentication", oChallengeResponseAuthentication },
135 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
136 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
138 { "kerberosauthentication", oKerberosAuthentication },
141 { "kerberostgtpassing", oKerberosTgtPassing },
142 { "afstokenpassing", oAFSTokenPassing },
144 { "fallbacktorsh", oFallBackToRsh },
145 { "usersh", oUseRsh },
146 { "identityfile", oIdentityFile },
147 { "identityfile2", oIdentityFile }, /* alias */
148 { "hostname", oHostName },
149 { "hostkeyalias", oHostKeyAlias },
150 { "proxycommand", oProxyCommand },
152 { "cipher", oCipher },
153 { "ciphers", oCiphers },
155 { "protocol", oProtocol },
156 { "remoteforward", oRemoteForward },
157 { "localforward", oLocalForward },
160 { "escapechar", oEscapeChar },
161 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
162 { "globalknownhostsfile", oGlobalKnownHostsFile },
163 { "userknownhostsfile", oUserKnownHostsFile },
164 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
165 { "userknownhostsfile2", oUserKnownHostsFile2 },
166 { "connectionattempts", oConnectionAttempts },
167 { "batchmode", oBatchMode },
168 { "checkhostip", oCheckHostIP },
169 { "stricthostkeychecking", oStrictHostKeyChecking },
170 { "compression", oCompression },
171 { "compressionlevel", oCompressionLevel },
172 { "keepalive", oKeepAlives },
173 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
174 { "loglevel", oLogLevel },
175 { "preferredauthentications", oPreferredAuthentications },
180 * Adds a local TCP/IP port forward to options. Never returns if there is an
185 add_local_forward(Options *options, u_short port, const char *host,
190 extern uid_t original_real_uid;
191 if (port < IPPORT_RESERVED && original_real_uid != 0)
192 fatal("Privileged ports can only be forwarded by root.");
194 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
195 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
196 fwd = &options->local_forwards[options->num_local_forwards++];
198 fwd->host = xstrdup(host);
199 fwd->host_port = host_port;
203 * Adds a remote TCP/IP port forward to options. Never returns if there is
208 add_remote_forward(Options *options, u_short port, const char *host,
212 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
213 fatal("Too many remote forwards (max %d).",
214 SSH_MAX_FORWARDS_PER_DIRECTION);
215 fwd = &options->remote_forwards[options->num_remote_forwards++];
217 fwd->host = xstrdup(host);
218 fwd->host_port = host_port;
222 * Returns the number of the token pointed to by cp of length len. Never
223 * returns if the token is not known.
227 parse_token(const char *cp, const char *filename, int linenum)
231 for (i = 0; keywords[i].name; i++)
232 if (strcasecmp(cp, keywords[i].name) == 0)
233 return keywords[i].opcode;
235 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
236 filename, linenum, cp);
241 * Processes a single option line as used in the configuration files. This
242 * only sets those values that have not already been set.
246 process_config_line(Options *options, const char *host,
247 char *line, const char *filename, int linenum,
250 char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
251 int opcode, *intptr, value;
252 u_short fwd_port, fwd_host_port;
255 /* Get the keyword. (Each line is supposed to begin with a keyword). */
256 keyword = strdelim(&s);
257 /* Ignore leading whitespace. */
258 if (*keyword == '\0')
259 keyword = strdelim(&s);
260 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
263 opcode = parse_token(keyword, filename, linenum);
267 /* don't panic, but count bad options */
271 intptr = &options->forward_agent;
274 if (!arg || *arg == '\0')
275 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
276 value = 0; /* To avoid compiler warning... */
277 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
279 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
282 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
283 if (*activep && *intptr == -1)
288 intptr = &options->forward_x11;
292 intptr = &options->gateway_ports;
295 case oUsePrivilegedPort:
296 intptr = &options->use_privileged_port;
299 case oRhostsAuthentication:
300 intptr = &options->rhosts_authentication;
303 case oPasswordAuthentication:
304 intptr = &options->password_authentication;
307 case oKbdInteractiveAuthentication:
308 intptr = &options->kbd_interactive_authentication;
311 case oKbdInteractiveDevices:
312 charptr = &options->kbd_interactive_devices;
315 case oPubkeyAuthentication:
316 intptr = &options->pubkey_authentication;
319 case oRSAAuthentication:
320 intptr = &options->rsa_authentication;
323 case oRhostsRSAAuthentication:
324 intptr = &options->rhosts_rsa_authentication;
327 case oChallengeResponseAuthentication:
328 intptr = &options->challenge_reponse_authentication;
332 case oKerberosAuthentication:
333 intptr = &options->kerberos_authentication;
338 case oKerberosTgtPassing:
339 intptr = &options->kerberos_tgt_passing;
342 case oAFSTokenPassing:
343 intptr = &options->afs_token_passing;
348 intptr = &options->fallback_to_rsh;
352 intptr = &options->use_rsh;
356 intptr = &options->batch_mode;
360 intptr = &options->check_host_ip;
363 case oStrictHostKeyChecking:
364 intptr = &options->strict_host_key_checking;
366 if (!arg || *arg == '\0')
367 fatal("%.200s line %d: Missing yes/no/ask argument.",
369 value = 0; /* To avoid compiler warning... */
370 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
372 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
374 else if (strcmp(arg, "ask") == 0)
377 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
378 if (*activep && *intptr == -1)
383 intptr = &options->compression;
387 intptr = &options->keepalives;
390 case oNumberOfPasswordPrompts:
391 intptr = &options->number_of_password_prompts;
394 case oCompressionLevel:
395 intptr = &options->compression_level;
400 if (!arg || *arg == '\0')
401 fatal("%.200s line %d: Missing argument.", filename, linenum);
403 intptr = &options->num_identity_files;
404 if (*intptr >= SSH_MAX_IDENTITY_FILES)
405 fatal("%.200s line %d: Too many identity files specified (max %d).",
406 filename, linenum, SSH_MAX_IDENTITY_FILES);
407 charptr = &options->identity_files[*intptr];
408 *charptr = xstrdup(arg);
409 *intptr = *intptr + 1;
414 charptr=&options->xauth_location;
418 charptr = &options->user;
421 if (!arg || *arg == '\0')
422 fatal("%.200s line %d: Missing argument.", filename, linenum);
423 if (*activep && *charptr == NULL)
424 *charptr = xstrdup(arg);
427 case oGlobalKnownHostsFile:
428 charptr = &options->system_hostfile;
431 case oUserKnownHostsFile:
432 charptr = &options->user_hostfile;
435 case oGlobalKnownHostsFile2:
436 charptr = &options->system_hostfile2;
439 case oUserKnownHostsFile2:
440 charptr = &options->user_hostfile2;
444 charptr = &options->hostname;
448 charptr = &options->host_key_alias;
451 case oPreferredAuthentications:
452 charptr = &options->preferred_authentications;
456 charptr = &options->proxy_command;
457 string = xstrdup("");
458 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
459 string = xrealloc(string, strlen(string) + strlen(arg) + 2);
463 if (*activep && *charptr == NULL)
470 intptr = &options->port;
473 if (!arg || *arg == '\0')
474 fatal("%.200s line %d: Missing argument.", filename, linenum);
475 if (arg[0] < '0' || arg[0] > '9')
476 fatal("%.200s line %d: Bad number.", filename, linenum);
478 /* Octal, decimal, or hex format? */
479 value = strtol(arg, &endofnumber, 0);
480 if (arg == endofnumber)
481 fatal("%.200s line %d: Bad number.", filename, linenum);
482 if (*activep && *intptr == -1)
486 case oConnectionAttempts:
487 intptr = &options->connection_attempts;
491 intptr = &options->cipher;
493 if (!arg || *arg == '\0')
494 fatal("%.200s line %d: Missing argument.", filename, linenum);
495 value = cipher_number(arg);
497 fatal("%.200s line %d: Bad cipher '%s'.",
498 filename, linenum, arg ? arg : "<NONE>");
499 if (*activep && *intptr == -1)
505 if (!arg || *arg == '\0')
506 fatal("%.200s line %d: Missing argument.", filename, linenum);
507 if (!ciphers_valid(arg))
508 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
509 filename, linenum, arg ? arg : "<NONE>");
510 if (*activep && options->ciphers == NULL)
511 options->ciphers = xstrdup(arg);
516 if (!arg || *arg == '\0')
517 fatal("%.200s line %d: Missing argument.", filename, linenum);
519 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
520 filename, linenum, arg ? arg : "<NONE>");
521 if (*activep && options->macs == NULL)
522 options->macs = xstrdup(arg);
526 intptr = &options->protocol;
528 if (!arg || *arg == '\0')
529 fatal("%.200s line %d: Missing argument.", filename, linenum);
530 value = proto_spec(arg);
531 if (value == SSH_PROTO_UNKNOWN)
532 fatal("%.200s line %d: Bad protocol spec '%s'.",
533 filename, linenum, arg ? arg : "<NONE>");
534 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
539 intptr = (int *) &options->log_level;
541 value = log_level_number(arg);
542 if (value == (LogLevel) - 1)
543 fatal("%.200s line %d: unsupported log level '%s'",
544 filename, linenum, arg ? arg : "<NONE>");
545 if (*activep && (LogLevel) * intptr == -1)
546 *intptr = (LogLevel) value;
551 if (!arg || *arg == '\0')
552 fatal("%.200s line %d: Missing argument.", filename, linenum);
553 if (arg[0] < '0' || arg[0] > '9')
554 fatal("%.200s line %d: Badly formatted port number.",
556 fwd_port = atoi(arg);
558 if (!arg || *arg == '\0')
559 fatal("%.200s line %d: Missing second argument.",
561 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
562 fatal("%.200s line %d: Badly formatted host:port.",
565 add_remote_forward(options, fwd_port, buf, fwd_host_port);
570 if (!arg || *arg == '\0')
571 fatal("%.200s line %d: Missing argument.", filename, linenum);
572 if (arg[0] < '0' || arg[0] > '9')
573 fatal("%.200s line %d: Badly formatted port number.",
575 fwd_port = atoi(arg);
577 if (!arg || *arg == '\0')
578 fatal("%.200s line %d: Missing second argument.",
580 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
581 fatal("%.200s line %d: Badly formatted host:port.",
584 add_local_forward(options, fwd_port, buf, fwd_host_port);
589 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
590 if (match_pattern(host, arg)) {
591 debug("Applying options for %.100s", arg);
595 /* Avoid garbage check below, as strdelim is done. */
599 intptr = &options->escape_char;
601 if (!arg || *arg == '\0')
602 fatal("%.200s line %d: Missing argument.", filename, linenum);
603 if (arg[0] == '^' && arg[2] == 0 &&
604 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
605 value = (u_char) arg[1] & 31;
606 else if (strlen(arg) == 1)
607 value = (u_char) arg[0];
608 else if (strcmp(arg, "none") == 0)
611 fatal("%.200s line %d: Bad escape character.",
614 value = 0; /* Avoid compiler warning. */
616 if (*activep && *intptr == -1)
621 fatal("process_config_line: Unimplemented opcode %d", opcode);
624 /* Check that there is no garbage at end of line. */
625 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
626 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
627 filename, linenum, arg);
634 * Reads the config file and modifies the options accordingly. Options
635 * should already be initialized before this call. This never returns if
636 * there is an error. If the file does not exist, this returns immediately.
640 read_config_file(const char *filename, const char *host, Options *options)
648 f = fopen(filename, "r");
652 debug("Reading configuration data %.200s", filename);
655 * Mark that we are now processing the options. This flag is turned
656 * on/off by Host specifications.
660 while (fgets(line, sizeof(line), f)) {
661 /* Update line number counter. */
663 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
668 fatal("%s: terminating, %d bad configuration options",
669 filename, bad_options);
673 * Initializes options to special values that indicate that they have not yet
674 * been set. Read_config_file will only set options with this value. Options
675 * are processed in the following order: command line, user config file,
676 * system config file. Last, fill_default_options is called.
680 initialize_options(Options * options)
682 memset(options, 'X', sizeof(*options));
683 options->forward_agent = -1;
684 options->forward_x11 = -1;
685 options->xauth_location = NULL;
686 options->gateway_ports = -1;
687 options->use_privileged_port = -1;
688 options->rhosts_authentication = -1;
689 options->rsa_authentication = -1;
690 options->pubkey_authentication = -1;
691 options->challenge_reponse_authentication = -1;
693 options->kerberos_authentication = -1;
696 options->kerberos_tgt_passing = -1;
697 options->afs_token_passing = -1;
699 options->password_authentication = -1;
700 options->kbd_interactive_authentication = -1;
701 options->kbd_interactive_devices = NULL;
702 options->rhosts_rsa_authentication = -1;
703 options->fallback_to_rsh = -1;
704 options->use_rsh = -1;
705 options->batch_mode = -1;
706 options->check_host_ip = -1;
707 options->strict_host_key_checking = -1;
708 options->compression = -1;
709 options->keepalives = -1;
710 options->compression_level = -1;
712 options->connection_attempts = -1;
713 options->number_of_password_prompts = -1;
714 options->cipher = -1;
715 options->ciphers = NULL;
716 options->macs = NULL;
717 options->protocol = SSH_PROTO_UNKNOWN;
718 options->num_identity_files = 0;
719 options->hostname = NULL;
720 options->host_key_alias = NULL;
721 options->proxy_command = NULL;
722 options->user = NULL;
723 options->escape_char = -1;
724 options->system_hostfile = NULL;
725 options->user_hostfile = NULL;
726 options->system_hostfile2 = NULL;
727 options->user_hostfile2 = NULL;
728 options->num_local_forwards = 0;
729 options->num_remote_forwards = 0;
730 options->log_level = (LogLevel) - 1;
731 options->preferred_authentications = NULL;
735 * Called after processing other sources of option data, this fills those
736 * options for which no value has been specified with their default values.
740 fill_default_options(Options * options)
744 if (options->forward_agent == -1)
745 options->forward_agent = 0;
746 if (options->forward_x11 == -1)
747 options->forward_x11 = 0;
749 if (options->xauth_location == NULL)
750 options->xauth_location = XAUTH_PATH;
751 #endif /* XAUTH_PATH */
752 if (options->gateway_ports == -1)
753 options->gateway_ports = 0;
754 if (options->use_privileged_port == -1)
755 options->use_privileged_port = 0;
756 if (options->rhosts_authentication == -1)
757 options->rhosts_authentication = 1;
758 if (options->rsa_authentication == -1)
759 options->rsa_authentication = 1;
760 if (options->pubkey_authentication == -1)
761 options->pubkey_authentication = 1;
762 if (options->challenge_reponse_authentication == -1)
763 options->challenge_reponse_authentication = 0;
765 if (options->kerberos_authentication == -1)
766 options->kerberos_authentication = 1;
769 if (options->kerberos_tgt_passing == -1)
770 options->kerberos_tgt_passing = 1;
771 if (options->afs_token_passing == -1)
772 options->afs_token_passing = 1;
774 if (options->password_authentication == -1)
775 options->password_authentication = 1;
776 if (options->kbd_interactive_authentication == -1)
777 options->kbd_interactive_authentication = 1;
778 if (options->rhosts_rsa_authentication == -1)
779 options->rhosts_rsa_authentication = 1;
780 if (options->fallback_to_rsh == -1)
781 options->fallback_to_rsh = 0;
782 if (options->use_rsh == -1)
783 options->use_rsh = 0;
784 if (options->batch_mode == -1)
785 options->batch_mode = 0;
786 if (options->check_host_ip == -1)
787 options->check_host_ip = 1;
788 if (options->strict_host_key_checking == -1)
789 options->strict_host_key_checking = 2; /* 2 is default */
790 if (options->compression == -1)
791 options->compression = 0;
792 if (options->keepalives == -1)
793 options->keepalives = 1;
794 if (options->compression_level == -1)
795 options->compression_level = 6;
796 if (options->port == -1)
797 options->port = 0; /* Filled in ssh_connect. */
798 if (options->connection_attempts == -1)
799 options->connection_attempts = 4;
800 if (options->number_of_password_prompts == -1)
801 options->number_of_password_prompts = 3;
802 /* Selected in ssh_login(). */
803 if (options->cipher == -1)
804 options->cipher = SSH_CIPHER_NOT_SET;
805 /* options->ciphers, default set in myproposals.h */
806 /* options->macs, default set in myproposals.h */
807 if (options->protocol == SSH_PROTO_UNKNOWN)
808 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
809 if (options->num_identity_files == 0) {
810 if (options->protocol & SSH_PROTO_1) {
811 len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
812 options->identity_files[options->num_identity_files] =
814 snprintf(options->identity_files[options->num_identity_files++],
815 len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
817 if (options->protocol & SSH_PROTO_2) {
818 len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
819 options->identity_files[options->num_identity_files] =
821 snprintf(options->identity_files[options->num_identity_files++],
822 len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
824 len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
825 options->identity_files[options->num_identity_files] =
827 snprintf(options->identity_files[options->num_identity_files++],
828 len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
831 if (options->escape_char == -1)
832 options->escape_char = '~';
833 if (options->system_hostfile == NULL)
834 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
835 if (options->user_hostfile == NULL)
836 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
837 if (options->system_hostfile2 == NULL)
838 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
839 if (options->user_hostfile2 == NULL)
840 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
841 if (options->log_level == (LogLevel) - 1)
842 options->log_level = SYSLOG_LEVEL_INFO;
843 /* options->proxy_command should not be set by default */
844 /* options->user will be set in the main program if appropriate */
845 /* options->hostname will be set in the main program if appropriate */
846 /* options->host_key_alias should not be set by default */
847 /* options->preferred_authentications will be set in ssh */