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.
17 RCSID("$OpenBSD: readconf.c,v 1.40 2000/07/10 16:27:05 ho Exp $");
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,
95 oSkeyAuthentication, oXAuthLocation,
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 { "xauthlocation", oXAuthLocation },
120 { "gatewayports", oGatewayPorts },
121 { "useprivilegedport", oUsePrivilegedPort },
122 { "rhostsauthentication", oRhostsAuthentication },
123 { "passwordauthentication", oPasswordAuthentication },
124 { "rsaauthentication", oRSAAuthentication },
125 { "dsaauthentication", oDSAAuthentication },
126 { "skeyauthentication", oSkeyAuthentication },
128 { "kerberosauthentication", oKerberosAuthentication },
131 { "kerberostgtpassing", oKerberosTgtPassing },
132 { "afstokenpassing", oAFSTokenPassing },
134 { "fallbacktorsh", oFallBackToRsh },
135 { "usersh", oUseRsh },
136 { "identityfile", oIdentityFile },
137 { "identityfile2", oIdentityFile2 },
138 { "hostname", oHostName },
139 { "proxycommand", oProxyCommand },
141 { "cipher", oCipher },
142 { "ciphers", oCiphers },
143 { "protocol", oProtocol },
144 { "remoteforward", oRemoteForward },
145 { "localforward", oLocalForward },
148 { "escapechar", oEscapeChar },
149 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
150 { "globalknownhostsfile", oGlobalKnownHostsFile },
151 { "userknownhostsfile", oUserKnownHostsFile },
152 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
153 { "userknownhostsfile2", oUserKnownHostsFile2 },
154 { "connectionattempts", oConnectionAttempts },
155 { "batchmode", oBatchMode },
156 { "checkhostip", oCheckHostIP },
157 { "stricthostkeychecking", oStrictHostKeyChecking },
158 { "compression", oCompression },
159 { "compressionlevel", oCompressionLevel },
160 { "keepalive", oKeepAlives },
161 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
162 { "tisauthentication", oTISAuthentication },
163 { "loglevel", oLogLevel },
167 /* Characters considered whitespace in strsep calls. */
168 #define WHITESPACE " \t\r\n="
172 * Adds a local TCP/IP port forward to options. Never returns if there is an
177 add_local_forward(Options *options, u_short port, const char *host,
181 extern uid_t original_real_uid;
182 if (port < IPPORT_RESERVED && original_real_uid != 0)
183 fatal("Privileged ports can only be forwarded by root.\n");
184 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
185 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
186 fwd = &options->local_forwards[options->num_local_forwards++];
188 fwd->host = xstrdup(host);
189 fwd->host_port = host_port;
193 * Adds a remote TCP/IP port forward to options. Never returns if there is
198 add_remote_forward(Options *options, u_short port, const char *host,
202 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
203 fatal("Too many remote forwards (max %d).",
204 SSH_MAX_FORWARDS_PER_DIRECTION);
205 fwd = &options->remote_forwards[options->num_remote_forwards++];
207 fwd->host = xstrdup(host);
208 fwd->host_port = host_port;
212 * Returns the number of the token pointed to by cp of length len. Never
213 * returns if the token is not known.
217 parse_token(const char *cp, const char *filename, int linenum)
221 for (i = 0; keywords[i].name; i++)
222 if (strcasecmp(cp, keywords[i].name) == 0)
223 return keywords[i].opcode;
225 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
226 filename, linenum, cp);
231 * Processes a single option line as used in the configuration files. This
232 * only sets those values that have not already been set.
236 process_config_line(Options *options, const char *host,
237 char *line, const char *filename, int linenum,
240 char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
241 int opcode, *intptr, value;
242 u_short fwd_port, fwd_host_port;
244 /* Skip leading whitespace. */
245 s = line + strspn(line, WHITESPACE);
246 if (!*s || *s == '\n' || *s == '#')
249 /* Get the keyword. (Each line is supposed to begin with a keyword). */
250 keyword = strsep(&s, WHITESPACE);
251 opcode = parse_token(keyword, filename, linenum);
255 /* don't panic, but count bad options */
259 intptr = &options->forward_agent;
261 arg = strsep(&s, WHITESPACE);
262 if (!arg || *arg == '\0')
263 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
264 value = 0; /* To avoid compiler warning... */
265 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
267 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
270 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
271 if (*activep && *intptr == -1)
276 intptr = &options->forward_x11;
280 intptr = &options->gateway_ports;
283 case oUsePrivilegedPort:
284 intptr = &options->use_privileged_port;
287 case oRhostsAuthentication:
288 intptr = &options->rhosts_authentication;
291 case oPasswordAuthentication:
292 intptr = &options->password_authentication;
295 case oDSAAuthentication:
296 intptr = &options->dsa_authentication;
299 case oRSAAuthentication:
300 intptr = &options->rsa_authentication;
303 case oRhostsRSAAuthentication:
304 intptr = &options->rhosts_rsa_authentication;
307 case oTISAuthentication:
308 /* fallthrough, there is no difference on the client side */
309 case oSkeyAuthentication:
310 intptr = &options->skey_authentication;
314 case oKerberosAuthentication:
315 intptr = &options->kerberos_authentication;
320 case oKerberosTgtPassing:
321 intptr = &options->kerberos_tgt_passing;
324 case oAFSTokenPassing:
325 intptr = &options->afs_token_passing;
330 intptr = &options->fallback_to_rsh;
334 intptr = &options->use_rsh;
338 intptr = &options->batch_mode;
342 intptr = &options->check_host_ip;
345 case oStrictHostKeyChecking:
346 intptr = &options->strict_host_key_checking;
347 arg = strsep(&s, WHITESPACE);
348 if (!arg || *arg == '\0')
349 fatal("%.200s line %d: Missing yes/no argument.",
351 value = 0; /* To avoid compiler warning... */
352 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
354 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
356 else if (strcmp(arg, "ask") == 0)
359 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
360 if (*activep && *intptr == -1)
365 intptr = &options->compression;
369 intptr = &options->keepalives;
372 case oNumberOfPasswordPrompts:
373 intptr = &options->number_of_password_prompts;
376 case oCompressionLevel:
377 intptr = &options->compression_level;
382 arg = strsep(&s, WHITESPACE);
383 if (!arg || *arg == '\0')
384 fatal("%.200s line %d: Missing argument.", filename, linenum);
386 intptr = (opcode == oIdentityFile) ?
387 &options->num_identity_files :
388 &options->num_identity_files2;
389 if (*intptr >= SSH_MAX_IDENTITY_FILES)
390 fatal("%.200s line %d: Too many identity files specified (max %d).",
391 filename, linenum, SSH_MAX_IDENTITY_FILES);
392 charptr = (opcode == oIdentityFile) ?
393 &options->identity_files[*intptr] :
394 &options->identity_files2[*intptr];
395 *charptr = xstrdup(arg);
396 *intptr = *intptr + 1;
401 charptr=&options->xauth_location;
405 charptr = &options->user;
407 arg = strsep(&s, WHITESPACE);
408 if (!arg || *arg == '\0')
409 fatal("%.200s line %d: Missing argument.", filename, linenum);
410 if (*activep && *charptr == NULL)
411 *charptr = xstrdup(arg);
414 case oGlobalKnownHostsFile:
415 charptr = &options->system_hostfile;
418 case oUserKnownHostsFile:
419 charptr = &options->user_hostfile;
422 case oGlobalKnownHostsFile2:
423 charptr = &options->system_hostfile2;
426 case oUserKnownHostsFile2:
427 charptr = &options->user_hostfile2;
431 charptr = &options->hostname;
435 charptr = &options->proxy_command;
436 string = xstrdup("");
437 while ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0') {
438 string = xrealloc(string, strlen(string) + strlen(arg) + 2);
442 if (*activep && *charptr == NULL)
449 intptr = &options->port;
451 arg = strsep(&s, WHITESPACE);
452 if (!arg || *arg == '\0')
453 fatal("%.200s line %d: Missing argument.", filename, linenum);
454 if (arg[0] < '0' || arg[0] > '9')
455 fatal("%.200s line %d: Bad number.", filename, linenum);
457 /* Octal, decimal, or hex format? */
458 value = strtol(arg, &endofnumber, 0);
459 if (arg == endofnumber)
460 fatal("%.200s line %d: Bad number.", filename, linenum);
461 if (*activep && *intptr == -1)
465 case oConnectionAttempts:
466 intptr = &options->connection_attempts;
470 intptr = &options->cipher;
471 arg = strsep(&s, WHITESPACE);
472 if (!arg || *arg == '\0')
473 fatal("%.200s line %d: Missing argument.", filename, linenum);
474 value = cipher_number(arg);
476 fatal("%.200s line %d: Bad cipher '%s'.",
477 filename, linenum, arg ? arg : "<NONE>");
478 if (*activep && *intptr == -1)
483 arg = strsep(&s, WHITESPACE);
484 if (!arg || *arg == '\0')
485 fatal("%.200s line %d: Missing argument.", filename, linenum);
486 if (!ciphers_valid(arg))
487 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
488 filename, linenum, arg ? arg : "<NONE>");
489 if (*activep && options->ciphers == NULL)
490 options->ciphers = xstrdup(arg);
494 intptr = &options->protocol;
495 arg = strsep(&s, WHITESPACE);
496 if (!arg || *arg == '\0')
497 fatal("%.200s line %d: Missing argument.", filename, linenum);
498 value = proto_spec(arg);
499 if (value == SSH_PROTO_UNKNOWN)
500 fatal("%.200s line %d: Bad protocol spec '%s'.",
501 filename, linenum, arg ? arg : "<NONE>");
502 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
507 intptr = (int *) &options->log_level;
508 arg = strsep(&s, WHITESPACE);
509 value = log_level_number(arg);
510 if (value == (LogLevel) - 1)
511 fatal("%.200s line %d: unsupported log level '%s'\n",
512 filename, linenum, arg ? arg : "<NONE>");
513 if (*activep && (LogLevel) * intptr == -1)
514 *intptr = (LogLevel) value;
518 arg = strsep(&s, WHITESPACE);
519 if (!arg || *arg == '\0')
520 fatal("%.200s line %d: Missing argument.", filename, linenum);
521 if (arg[0] < '0' || arg[0] > '9')
522 fatal("%.200s line %d: Badly formatted port number.",
524 fwd_port = atoi(arg);
525 arg = strsep(&s, WHITESPACE);
526 if (!arg || *arg == '\0')
527 fatal("%.200s line %d: Missing second argument.",
529 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
530 fatal("%.200s line %d: Badly formatted host:port.",
533 add_remote_forward(options, fwd_port, buf, fwd_host_port);
537 arg = strsep(&s, WHITESPACE);
538 if (!arg || *arg == '\0')
539 fatal("%.200s line %d: Missing argument.", filename, linenum);
540 if (arg[0] < '0' || arg[0] > '9')
541 fatal("%.200s line %d: Badly formatted port number.",
543 fwd_port = atoi(arg);
544 arg = strsep(&s, WHITESPACE);
545 if (!arg || *arg == '\0')
546 fatal("%.200s line %d: Missing second argument.",
548 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
549 fatal("%.200s line %d: Badly formatted host:port.",
552 add_local_forward(options, fwd_port, buf, fwd_host_port);
557 while ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0')
558 if (match_pattern(host, arg)) {
559 debug("Applying options for %.100s", arg);
563 /* Avoid garbage check below, as strsep is done. */
567 intptr = &options->escape_char;
568 arg = strsep(&s, WHITESPACE);
569 if (!arg || *arg == '\0')
570 fatal("%.200s line %d: Missing argument.", filename, linenum);
571 if (arg[0] == '^' && arg[2] == 0 &&
572 (unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
573 value = (unsigned char) arg[1] & 31;
574 else if (strlen(arg) == 1)
575 value = (unsigned char) arg[0];
576 else if (strcmp(arg, "none") == 0)
579 fatal("%.200s line %d: Bad escape character.",
582 value = 0; /* Avoid compiler warning. */
584 if (*activep && *intptr == -1)
589 fatal("process_config_line: Unimplemented opcode %d", opcode);
592 /* Check that there is no garbage at end of line. */
593 if ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0')
595 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
596 filename, linenum, arg);
603 * Reads the config file and modifies the options accordingly. Options
604 * should already be initialized before this call. This never returns if
605 * there is an error. If the file does not exist, this returns immediately.
609 read_config_file(const char *filename, const char *host, Options *options)
617 f = fopen(filename, "r");
621 debug("Reading configuration data %.200s", filename);
624 * Mark that we are now processing the options. This flag is turned
625 * on/off by Host specifications.
629 while (fgets(line, sizeof(line), f)) {
630 /* Update line number counter. */
632 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
637 fatal("%s: terminating, %d bad configuration options\n",
638 filename, bad_options);
642 * Initializes options to special values that indicate that they have not yet
643 * been set. Read_config_file will only set options with this value. Options
644 * are processed in the following order: command line, user config file,
645 * system config file. Last, fill_default_options is called.
649 initialize_options(Options * options)
651 memset(options, 'X', sizeof(*options));
652 options->forward_agent = -1;
653 options->forward_x11 = -1;
654 options->xauth_location = NULL;
655 options->gateway_ports = -1;
656 options->use_privileged_port = -1;
657 options->rhosts_authentication = -1;
658 options->rsa_authentication = -1;
659 options->dsa_authentication = -1;
660 options->skey_authentication = -1;
662 options->kerberos_authentication = -1;
665 options->kerberos_tgt_passing = -1;
666 options->afs_token_passing = -1;
668 options->password_authentication = -1;
669 options->rhosts_rsa_authentication = -1;
670 options->fallback_to_rsh = -1;
671 options->use_rsh = -1;
672 options->batch_mode = -1;
673 options->check_host_ip = -1;
674 options->strict_host_key_checking = -1;
675 options->compression = -1;
676 options->keepalives = -1;
677 options->compression_level = -1;
679 options->connection_attempts = -1;
680 options->number_of_password_prompts = -1;
681 options->cipher = -1;
682 options->ciphers = NULL;
683 options->protocol = SSH_PROTO_UNKNOWN;
684 options->num_identity_files = 0;
685 options->num_identity_files2 = 0;
686 options->hostname = NULL;
687 options->proxy_command = NULL;
688 options->user = NULL;
689 options->escape_char = -1;
690 options->system_hostfile = NULL;
691 options->user_hostfile = NULL;
692 options->system_hostfile2 = NULL;
693 options->user_hostfile2 = NULL;
694 options->num_local_forwards = 0;
695 options->num_remote_forwards = 0;
696 options->log_level = (LogLevel) - 1;
700 * Called after processing other sources of option data, this fills those
701 * options for which no value has been specified with their default values.
705 fill_default_options(Options * options)
707 if (options->forward_agent == -1)
708 options->forward_agent = 0;
709 if (options->forward_x11 == -1)
710 options->forward_x11 = 0;
712 if (options->xauth_location == NULL)
713 options->xauth_location = XAUTH_PATH;
714 #endif /* XAUTH_PATH */
715 if (options->gateway_ports == -1)
716 options->gateway_ports = 0;
717 if (options->use_privileged_port == -1)
718 options->use_privileged_port = 1;
719 if (options->rhosts_authentication == -1)
720 options->rhosts_authentication = 1;
721 if (options->rsa_authentication == -1)
722 options->rsa_authentication = 1;
723 if (options->dsa_authentication == -1)
724 options->dsa_authentication = 1;
725 if (options->skey_authentication == -1)
726 options->skey_authentication = 0;
728 if (options->kerberos_authentication == -1)
729 options->kerberos_authentication = 1;
732 if (options->kerberos_tgt_passing == -1)
733 options->kerberos_tgt_passing = 1;
734 if (options->afs_token_passing == -1)
735 options->afs_token_passing = 1;
737 if (options->password_authentication == -1)
738 options->password_authentication = 1;
739 if (options->rhosts_rsa_authentication == -1)
740 options->rhosts_rsa_authentication = 1;
741 if (options->fallback_to_rsh == -1)
742 options->fallback_to_rsh = 1;
743 if (options->use_rsh == -1)
744 options->use_rsh = 0;
745 if (options->batch_mode == -1)
746 options->batch_mode = 0;
747 if (options->check_host_ip == -1)
748 options->check_host_ip = 1;
749 if (options->strict_host_key_checking == -1)
750 options->strict_host_key_checking = 2; /* 2 is default */
751 if (options->compression == -1)
752 options->compression = 0;
753 if (options->keepalives == -1)
754 options->keepalives = 1;
755 if (options->compression_level == -1)
756 options->compression_level = 6;
757 if (options->port == -1)
758 options->port = 0; /* Filled in ssh_connect. */
759 if (options->connection_attempts == -1)
760 options->connection_attempts = 4;
761 if (options->number_of_password_prompts == -1)
762 options->number_of_password_prompts = 3;
763 /* Selected in ssh_login(). */
764 if (options->cipher == -1)
765 options->cipher = SSH_CIPHER_NOT_SET;
766 /* options->ciphers, default set in myproposals.h */
767 if (options->protocol == SSH_PROTO_UNKNOWN)
768 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
769 if (options->num_identity_files == 0) {
770 options->identity_files[0] =
771 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
772 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
773 options->num_identity_files = 1;
775 if (options->num_identity_files2 == 0) {
776 options->identity_files2[0] =
777 xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
778 sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
779 options->num_identity_files2 = 1;
781 if (options->escape_char == -1)
782 options->escape_char = '~';
783 if (options->system_hostfile == NULL)
784 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
785 if (options->user_hostfile == NULL)
786 options->user_hostfile = SSH_USER_HOSTFILE;
787 if (options->system_hostfile2 == NULL)
788 options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
789 if (options->user_hostfile2 == NULL)
790 options->user_hostfile2 = SSH_USER_HOSTFILE2;
791 if (options->log_level == (LogLevel) - 1)
792 options->log_level = SYSLOG_LEVEL_INFO;
793 /* options->proxy_command should not be set by default */
794 /* options->user will be set in the main program if appropriate */
795 /* options->hostname will be set in the main program if appropriate */