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.45 2000/08/02 17:27:04 provos 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 },
168 * Adds a local TCP/IP port forward to options. Never returns if there is an
173 add_local_forward(Options *options, u_short port, const char *host,
177 extern uid_t original_real_uid;
178 if (port < IPPORT_RESERVED && original_real_uid != 0)
179 fatal("Privileged ports can only be forwarded by root.\n");
180 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
181 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
182 fwd = &options->local_forwards[options->num_local_forwards++];
184 fwd->host = xstrdup(host);
185 fwd->host_port = host_port;
189 * Adds a remote TCP/IP port forward to options. Never returns if there is
194 add_remote_forward(Options *options, u_short port, const char *host,
198 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
199 fatal("Too many remote forwards (max %d).",
200 SSH_MAX_FORWARDS_PER_DIRECTION);
201 fwd = &options->remote_forwards[options->num_remote_forwards++];
203 fwd->host = xstrdup(host);
204 fwd->host_port = host_port;
208 * Returns the number of the token pointed to by cp of length len. Never
209 * returns if the token is not known.
213 parse_token(const char *cp, const char *filename, int linenum)
217 for (i = 0; keywords[i].name; i++)
218 if (strcasecmp(cp, keywords[i].name) == 0)
219 return keywords[i].opcode;
221 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
222 filename, linenum, cp);
227 * Processes a single option line as used in the configuration files. This
228 * only sets those values that have not already been set.
232 process_config_line(Options *options, const char *host,
233 char *line, const char *filename, int linenum,
236 char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
237 int opcode, *intptr, value;
238 u_short fwd_port, fwd_host_port;
241 /* Get the keyword. (Each line is supposed to begin with a keyword). */
242 keyword = strdelim(&s);
243 /* Ignore leading whitespace. */
244 if (*keyword == '\0')
245 keyword = strdelim(&s);
246 if (!*keyword || *keyword == '\n' || *keyword == '#')
249 opcode = parse_token(keyword, filename, linenum);
253 /* don't panic, but count bad options */
257 intptr = &options->forward_agent;
260 if (!arg || *arg == '\0')
261 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
262 value = 0; /* To avoid compiler warning... */
263 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
265 else if (strcmp(arg, "no") == 0 || strcmp(arg, "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 oDSAAuthentication:
294 intptr = &options->dsa_authentication;
297 case oRSAAuthentication:
298 intptr = &options->rsa_authentication;
301 case oRhostsRSAAuthentication:
302 intptr = &options->rhosts_rsa_authentication;
305 case oTISAuthentication:
306 /* fallthrough, there is no difference on the client side */
307 case oSkeyAuthentication:
308 intptr = &options->skey_authentication;
312 case oKerberosAuthentication:
313 intptr = &options->kerberos_authentication;
318 case oKerberosTgtPassing:
319 intptr = &options->kerberos_tgt_passing;
322 case oAFSTokenPassing:
323 intptr = &options->afs_token_passing;
328 intptr = &options->fallback_to_rsh;
332 intptr = &options->use_rsh;
336 intptr = &options->batch_mode;
340 intptr = &options->check_host_ip;
343 case oStrictHostKeyChecking:
344 intptr = &options->strict_host_key_checking;
346 if (!arg || *arg == '\0')
347 fatal("%.200s line %d: Missing yes/no argument.",
349 value = 0; /* To avoid compiler warning... */
350 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
352 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
354 else if (strcmp(arg, "ask") == 0)
357 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
358 if (*activep && *intptr == -1)
363 intptr = &options->compression;
367 intptr = &options->keepalives;
370 case oNumberOfPasswordPrompts:
371 intptr = &options->number_of_password_prompts;
374 case oCompressionLevel:
375 intptr = &options->compression_level;
381 if (!arg || *arg == '\0')
382 fatal("%.200s line %d: Missing argument.", filename, linenum);
384 intptr = (opcode == oIdentityFile) ?
385 &options->num_identity_files :
386 &options->num_identity_files2;
387 if (*intptr >= SSH_MAX_IDENTITY_FILES)
388 fatal("%.200s line %d: Too many identity files specified (max %d).",
389 filename, linenum, SSH_MAX_IDENTITY_FILES);
390 charptr = (opcode == oIdentityFile) ?
391 &options->identity_files[*intptr] :
392 &options->identity_files2[*intptr];
393 *charptr = xstrdup(arg);
394 *intptr = *intptr + 1;
399 charptr=&options->xauth_location;
403 charptr = &options->user;
406 if (!arg || *arg == '\0')
407 fatal("%.200s line %d: Missing argument.", filename, linenum);
408 if (*activep && *charptr == NULL)
409 *charptr = xstrdup(arg);
412 case oGlobalKnownHostsFile:
413 charptr = &options->system_hostfile;
416 case oUserKnownHostsFile:
417 charptr = &options->user_hostfile;
420 case oGlobalKnownHostsFile2:
421 charptr = &options->system_hostfile2;
424 case oUserKnownHostsFile2:
425 charptr = &options->user_hostfile2;
429 charptr = &options->hostname;
433 charptr = &options->proxy_command;
434 string = xstrdup("");
435 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
436 string = xrealloc(string, strlen(string) + strlen(arg) + 2);
440 if (*activep && *charptr == NULL)
447 intptr = &options->port;
450 if (!arg || *arg == '\0')
451 fatal("%.200s line %d: Missing argument.", filename, linenum);
452 if (arg[0] < '0' || arg[0] > '9')
453 fatal("%.200s line %d: Bad number.", filename, linenum);
455 /* Octal, decimal, or hex format? */
456 value = strtol(arg, &endofnumber, 0);
457 if (arg == endofnumber)
458 fatal("%.200s line %d: Bad number.", filename, linenum);
459 if (*activep && *intptr == -1)
463 case oConnectionAttempts:
464 intptr = &options->connection_attempts;
468 intptr = &options->cipher;
470 if (!arg || *arg == '\0')
471 fatal("%.200s line %d: Missing argument.", filename, linenum);
472 value = cipher_number(arg);
474 fatal("%.200s line %d: Bad cipher '%s'.",
475 filename, linenum, arg ? arg : "<NONE>");
476 if (*activep && *intptr == -1)
482 if (!arg || *arg == '\0')
483 fatal("%.200s line %d: Missing argument.", filename, linenum);
484 if (!ciphers_valid(arg))
485 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
486 filename, linenum, arg ? arg : "<NONE>");
487 if (*activep && options->ciphers == NULL)
488 options->ciphers = xstrdup(arg);
492 intptr = &options->protocol;
494 if (!arg || *arg == '\0')
495 fatal("%.200s line %d: Missing argument.", filename, linenum);
496 value = proto_spec(arg);
497 if (value == SSH_PROTO_UNKNOWN)
498 fatal("%.200s line %d: Bad protocol spec '%s'.",
499 filename, linenum, arg ? arg : "<NONE>");
500 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
505 intptr = (int *) &options->log_level;
507 value = log_level_number(arg);
508 if (value == (LogLevel) - 1)
509 fatal("%.200s line %d: unsupported log level '%s'\n",
510 filename, linenum, arg ? arg : "<NONE>");
511 if (*activep && (LogLevel) * intptr == -1)
512 *intptr = (LogLevel) value;
517 if (!arg || *arg == '\0')
518 fatal("%.200s line %d: Missing argument.", filename, linenum);
519 if (arg[0] < '0' || arg[0] > '9')
520 fatal("%.200s line %d: Badly formatted port number.",
522 fwd_port = atoi(arg);
524 if (!arg || *arg == '\0')
525 fatal("%.200s line %d: Missing second argument.",
527 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
528 fatal("%.200s line %d: Badly formatted host:port.",
531 add_remote_forward(options, fwd_port, buf, fwd_host_port);
536 if (!arg || *arg == '\0')
537 fatal("%.200s line %d: Missing argument.", filename, linenum);
538 if (arg[0] < '0' || arg[0] > '9')
539 fatal("%.200s line %d: Badly formatted port number.",
541 fwd_port = atoi(arg);
543 if (!arg || *arg == '\0')
544 fatal("%.200s line %d: Missing second argument.",
546 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
547 fatal("%.200s line %d: Badly formatted host:port.",
550 add_local_forward(options, fwd_port, buf, fwd_host_port);
555 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
556 if (match_pattern(host, arg)) {
557 debug("Applying options for %.100s", arg);
561 /* Avoid garbage check below, as strdelim is done. */
565 intptr = &options->escape_char;
567 if (!arg || *arg == '\0')
568 fatal("%.200s line %d: Missing argument.", filename, linenum);
569 if (arg[0] == '^' && arg[2] == 0 &&
570 (unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
571 value = (unsigned char) arg[1] & 31;
572 else if (strlen(arg) == 1)
573 value = (unsigned char) arg[0];
574 else if (strcmp(arg, "none") == 0)
577 fatal("%.200s line %d: Bad escape character.",
580 value = 0; /* Avoid compiler warning. */
582 if (*activep && *intptr == -1)
587 fatal("process_config_line: Unimplemented opcode %d", opcode);
590 /* Check that there is no garbage at end of line. */
591 if ((arg = strdelim(&s)) != NULL && *arg != '\0')
593 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
594 filename, linenum, arg);
601 * Reads the config file and modifies the options accordingly. Options
602 * should already be initialized before this call. This never returns if
603 * there is an error. If the file does not exist, this returns immediately.
607 read_config_file(const char *filename, const char *host, Options *options)
615 f = fopen(filename, "r");
619 debug("Reading configuration data %.200s", filename);
622 * Mark that we are now processing the options. This flag is turned
623 * on/off by Host specifications.
627 while (fgets(line, sizeof(line), f)) {
628 /* Update line number counter. */
630 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
635 fatal("%s: terminating, %d bad configuration options\n",
636 filename, bad_options);
640 * Initializes options to special values that indicate that they have not yet
641 * been set. Read_config_file will only set options with this value. Options
642 * are processed in the following order: command line, user config file,
643 * system config file. Last, fill_default_options is called.
647 initialize_options(Options * options)
649 memset(options, 'X', sizeof(*options));
650 options->forward_agent = -1;
651 options->forward_x11 = -1;
652 options->xauth_location = NULL;
653 options->gateway_ports = -1;
654 options->use_privileged_port = -1;
655 options->rhosts_authentication = -1;
656 options->rsa_authentication = -1;
657 options->dsa_authentication = -1;
658 options->skey_authentication = -1;
660 options->kerberos_authentication = -1;
663 options->kerberos_tgt_passing = -1;
664 options->afs_token_passing = -1;
666 options->password_authentication = -1;
667 options->rhosts_rsa_authentication = -1;
668 options->fallback_to_rsh = -1;
669 options->use_rsh = -1;
670 options->batch_mode = -1;
671 options->check_host_ip = -1;
672 options->strict_host_key_checking = -1;
673 options->compression = -1;
674 options->keepalives = -1;
675 options->compression_level = -1;
677 options->connection_attempts = -1;
678 options->number_of_password_prompts = -1;
679 options->cipher = -1;
680 options->ciphers = NULL;
681 options->protocol = SSH_PROTO_UNKNOWN;
682 options->num_identity_files = 0;
683 options->num_identity_files2 = 0;
684 options->hostname = NULL;
685 options->proxy_command = NULL;
686 options->user = NULL;
687 options->escape_char = -1;
688 options->system_hostfile = NULL;
689 options->user_hostfile = NULL;
690 options->system_hostfile2 = NULL;
691 options->user_hostfile2 = NULL;
692 options->num_local_forwards = 0;
693 options->num_remote_forwards = 0;
694 options->log_level = (LogLevel) - 1;
698 * Called after processing other sources of option data, this fills those
699 * options for which no value has been specified with their default values.
703 fill_default_options(Options * options)
705 if (options->forward_agent == -1)
706 options->forward_agent = 0;
707 if (options->forward_x11 == -1)
708 options->forward_x11 = 0;
710 if (options->xauth_location == NULL)
711 options->xauth_location = XAUTH_PATH;
712 #endif /* XAUTH_PATH */
713 if (options->gateway_ports == -1)
714 options->gateway_ports = 0;
715 if (options->use_privileged_port == -1)
716 options->use_privileged_port = 1;
717 if (options->rhosts_authentication == -1)
718 options->rhosts_authentication = 1;
719 if (options->rsa_authentication == -1)
720 options->rsa_authentication = 1;
721 if (options->dsa_authentication == -1)
722 options->dsa_authentication = 1;
723 if (options->skey_authentication == -1)
724 options->skey_authentication = 0;
726 if (options->kerberos_authentication == -1)
727 options->kerberos_authentication = 1;
730 if (options->kerberos_tgt_passing == -1)
731 options->kerberos_tgt_passing = 1;
732 if (options->afs_token_passing == -1)
733 options->afs_token_passing = 1;
735 if (options->password_authentication == -1)
736 options->password_authentication = 1;
737 if (options->rhosts_rsa_authentication == -1)
738 options->rhosts_rsa_authentication = 1;
739 if (options->fallback_to_rsh == -1)
740 options->fallback_to_rsh = 0;
741 if (options->use_rsh == -1)
742 options->use_rsh = 0;
743 if (options->batch_mode == -1)
744 options->batch_mode = 0;
745 if (options->check_host_ip == -1)
746 options->check_host_ip = 1;
747 if (options->strict_host_key_checking == -1)
748 options->strict_host_key_checking = 2; /* 2 is default */
749 if (options->compression == -1)
750 options->compression = 0;
751 if (options->keepalives == -1)
752 options->keepalives = 1;
753 if (options->compression_level == -1)
754 options->compression_level = 6;
755 if (options->port == -1)
756 options->port = 0; /* Filled in ssh_connect. */
757 if (options->connection_attempts == -1)
758 options->connection_attempts = 4;
759 if (options->number_of_password_prompts == -1)
760 options->number_of_password_prompts = 3;
761 /* Selected in ssh_login(). */
762 if (options->cipher == -1)
763 options->cipher = SSH_CIPHER_NOT_SET;
764 /* options->ciphers, default set in myproposals.h */
765 if (options->protocol == SSH_PROTO_UNKNOWN)
766 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
767 if (options->num_identity_files == 0) {
768 options->identity_files[0] =
769 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
770 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
771 options->num_identity_files = 1;
773 if (options->num_identity_files2 == 0) {
774 options->identity_files2[0] =
775 xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
776 sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
777 options->num_identity_files2 = 1;
779 if (options->escape_char == -1)
780 options->escape_char = '~';
781 if (options->system_hostfile == NULL)
782 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
783 if (options->user_hostfile == NULL)
784 options->user_hostfile = SSH_USER_HOSTFILE;
785 if (options->system_hostfile2 == NULL)
786 options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
787 if (options->user_hostfile2 == NULL)
788 options->user_hostfile2 = SSH_USER_HOSTFILE2;
789 if (options->log_level == (LogLevel) - 1)
790 options->log_level = SYSLOG_LEVEL_INFO;
791 /* options->proxy_command should not be set by default */
792 /* options->user will be set in the main program if appropriate */
793 /* options->hostname will be set in the main program if appropriate */