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.
18 RCSID("$Id: readconf.c,v 1.23 2000/02/28 19:51:58 markus Exp $");
25 /* Format of the configuration file:
27 # Configuration data is parsed as follows:
28 # 1. command line options
29 # 2. user-specific file
31 # Any configuration value is only changed the first time it is set.
32 # Thus, host-specific definitions should be at the beginning of the
33 # configuration file, and defaults at the end.
35 # Host-specific declarations. These may override anything above. A single
36 # host may match multiple declarations; these are processed in the order
37 # that they are given in.
43 HostName another.host.name.real.org
50 RemoteForward 9999 shadows.cs.hut.fi:9999
56 RhostsAuthentication no
57 PasswordAuthentication no
61 ProxyCommand ssh-proxy %h %p
68 PasswordAuthentication no
70 # Defaults for various options
74 RhostsAuthentication yes
75 PasswordAuthentication yes
77 RhostsRSAAuthentication yes
80 StrictHostKeyChecking yes
82 IdentityFile ~/.ssh/identity
92 oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
93 oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
99 oKrb5Authentication, oKrb5TgtPassing,
102 oKrb4TgtPassing, oAFSTokenPassing,
104 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
105 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
106 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
107 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
108 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
109 oUsePrivilegedPort, oLogLevel
112 /* Textual representations of the tokens. */
118 { "forwardagent", oForwardAgent },
119 { "forwardx11", oForwardX11 },
120 { "gatewayports", oGatewayPorts },
121 { "useprivilegedport", oUsePrivilegedPort },
122 { "rhostsauthentication", oRhostsAuthentication },
123 { "passwordauthentication", oPasswordAuthentication },
124 { "rsaauthentication", oRSAAuthentication },
125 { "skeyauthentication", oSkeyAuthentication },
127 { "kerberos4authentication", oKrb4Authentication },
130 { "kerberos5authentication", oKrb5Authentication },
131 { "kerberos5tgtpassing", oKrb5TgtPassing },
134 { "kerberos4tgtpassing", oKrb4TgtPassing },
135 { "afstokenpassing", oAFSTokenPassing },
137 { "fallbacktorsh", oFallBackToRsh },
138 { "usersh", oUseRsh },
139 { "identityfile", oIdentityFile },
140 { "hostname", oHostName },
141 { "proxycommand", oProxyCommand },
143 { "cipher", oCipher },
144 { "remoteforward", oRemoteForward },
145 { "localforward", oLocalForward },
148 { "escapechar", oEscapeChar },
149 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
150 { "globalknownhostsfile", oGlobalKnownHostsFile },
151 { "userknownhostsfile", oUserKnownHostsFile },
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 oKrb4Authentication:
309 intptr = &options->krb4_authentication;
314 case oKrb5Authentication:
315 intptr = &options->krb5_authentication;
318 case oKrb5TgtPassing:
319 intptr = &options->krb5_tgt_passing;
324 case oKrb4TgtPassing:
325 intptr = &options->krb4_tgt_passing;
328 case oAFSTokenPassing:
329 intptr = &options->afs_token_passing;
334 intptr = &options->fallback_to_rsh;
338 intptr = &options->use_rsh;
342 intptr = &options->batch_mode;
346 intptr = &options->check_host_ip;
349 case oStrictHostKeyChecking:
350 intptr = &options->strict_host_key_checking;
351 cp = strtok(NULL, WHITESPACE);
353 fatal("%.200s line %d: Missing yes/no argument.",
355 value = 0; /* To avoid compiler warning... */
356 if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
358 else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
360 else if (strcmp(cp, "ask") == 0)
363 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
364 if (*activep && *intptr == -1)
369 intptr = &options->compression;
373 intptr = &options->keepalives;
376 case oNumberOfPasswordPrompts:
377 intptr = &options->number_of_password_prompts;
380 case oCompressionLevel:
381 intptr = &options->compression_level;
385 cp = strtok(NULL, WHITESPACE);
387 fatal("%.200s line %d: Missing argument.", filename, linenum);
389 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
390 fatal("%.200s line %d: Too many identity files specified (max %d).",
391 filename, linenum, SSH_MAX_IDENTITY_FILES);
392 options->identity_files[options->num_identity_files++] = xstrdup(cp);
397 charptr = &options->user;
399 cp = strtok(NULL, WHITESPACE);
401 fatal("%.200s line %d: Missing argument.", filename, linenum);
402 if (*activep && *charptr == NULL)
403 *charptr = xstrdup(cp);
406 case oGlobalKnownHostsFile:
407 charptr = &options->system_hostfile;
410 case oUserKnownHostsFile:
411 charptr = &options->user_hostfile;
415 charptr = &options->hostname;
419 charptr = &options->proxy_command;
420 string = xstrdup("");
421 while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
422 string = xrealloc(string, strlen(string) + strlen(cp) + 2);
426 if (*activep && *charptr == NULL)
433 intptr = &options->port;
435 cp = strtok(NULL, WHITESPACE);
437 fatal("%.200s line %d: Missing argument.", filename, linenum);
438 if (cp[0] < '0' || cp[0] > '9')
439 fatal("%.200s line %d: Bad number.", filename, linenum);
441 /* Octal, decimal, or hex format? */
442 value = strtol(cp, &cp2, 0);
444 fatal("%.200s line %d: Bad number.", filename, linenum);
445 if (*activep && *intptr == -1)
449 case oConnectionAttempts:
450 intptr = &options->connection_attempts;
454 intptr = &options->cipher;
455 cp = strtok(NULL, WHITESPACE);
456 value = cipher_number(cp);
458 fatal("%.200s line %d: Bad cipher '%s'.",
459 filename, linenum, cp ? cp : "<NONE>");
460 if (*activep && *intptr == -1)
465 intptr = (int *) &options->log_level;
466 cp = strtok(NULL, WHITESPACE);
467 value = log_level_number(cp);
468 if (value == (LogLevel) - 1)
469 fatal("%.200s line %d: unsupported log level '%s'\n",
470 filename, linenum, cp ? cp : "<NONE>");
471 if (*activep && (LogLevel) * intptr == -1)
472 *intptr = (LogLevel) value;
476 cp = strtok(NULL, WHITESPACE);
478 fatal("%.200s line %d: Missing argument.", filename, linenum);
479 if (cp[0] < '0' || cp[0] > '9')
480 fatal("%.200s line %d: Badly formatted port number.",
483 cp = strtok(NULL, WHITESPACE);
485 fatal("%.200s line %d: Missing second argument.",
487 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
488 fatal("%.200s line %d: Badly formatted host:port.",
491 add_remote_forward(options, fwd_port, buf, fwd_host_port);
495 cp = strtok(NULL, WHITESPACE);
497 fatal("%.200s line %d: Missing argument.", filename, linenum);
498 if (cp[0] < '0' || cp[0] > '9')
499 fatal("%.200s line %d: Badly formatted port number.",
502 cp = strtok(NULL, WHITESPACE);
504 fatal("%.200s line %d: Missing second argument.",
506 if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
507 fatal("%.200s line %d: Badly formatted host:port.",
510 add_local_forward(options, fwd_port, buf, fwd_host_port);
515 while ((cp = strtok(NULL, WHITESPACE)) != NULL)
516 if (match_pattern(host, cp)) {
517 debug("Applying options for %.100s", cp);
521 /* Avoid garbage check below, as strtok already returned NULL. */
525 intptr = &options->escape_char;
526 cp = strtok(NULL, WHITESPACE);
528 fatal("%.200s line %d: Missing argument.", filename, linenum);
529 if (cp[0] == '^' && cp[2] == 0 &&
530 (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
531 value = (unsigned char) cp[1] & 31;
532 else if (strlen(cp) == 1)
533 value = (unsigned char) cp[0];
534 else if (strcmp(cp, "none") == 0)
537 fatal("%.200s line %d: Bad escape character.",
540 value = 0; /* Avoid compiler warning. */
542 if (*activep && *intptr == -1)
547 fatal("process_config_line: Unimplemented opcode %d", opcode);
550 /* Check that there is no garbage at end of line. */
551 if (strtok(NULL, WHITESPACE) != NULL)
552 fatal("%.200s line %d: garbage at end of line.",
559 * Reads the config file and modifies the options accordingly. Options
560 * should already be initialized before this call. This never returns if
561 * there is an error. If the file does not exist, this returns immediately.
565 read_config_file(const char *filename, const char *host, Options *options)
573 f = fopen(filename, "r");
577 debug("Reading configuration data %.200s", filename);
580 * Mark that we are now processing the options. This flag is turned
581 * on/off by Host specifications.
585 while (fgets(line, sizeof(line), f)) {
586 /* Update line number counter. */
588 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
593 fatal("%s: terminating, %d bad configuration options\n",
594 filename, bad_options);
598 * Initializes options to special values that indicate that they have not yet
599 * been set. Read_config_file will only set options with this value. Options
600 * are processed in the following order: command line, user config file,
601 * system config file. Last, fill_default_options is called.
605 initialize_options(Options * options)
607 memset(options, 'X', sizeof(*options));
608 options->forward_agent = -1;
609 options->forward_x11 = -1;
610 options->gateway_ports = -1;
611 options->use_privileged_port = -1;
612 options->rhosts_authentication = -1;
613 options->rsa_authentication = -1;
614 options->skey_authentication = -1;
616 options->krb4_authentication = -1;
619 options->krb5_authentication = -1;
620 options->krb5_tgt_passing = -1;
623 options->krb4_tgt_passing = -1;
624 options->afs_token_passing = -1;
626 options->password_authentication = -1;
627 options->rhosts_rsa_authentication = -1;
628 options->fallback_to_rsh = -1;
629 options->use_rsh = -1;
630 options->batch_mode = -1;
631 options->check_host_ip = -1;
632 options->strict_host_key_checking = -1;
633 options->compression = -1;
634 options->keepalives = -1;
635 options->compression_level = -1;
637 options->connection_attempts = -1;
638 options->number_of_password_prompts = -1;
639 options->cipher = -1;
640 options->num_identity_files = 0;
641 options->hostname = NULL;
642 options->proxy_command = NULL;
643 options->user = NULL;
644 options->escape_char = -1;
645 options->system_hostfile = NULL;
646 options->user_hostfile = NULL;
647 options->num_local_forwards = 0;
648 options->num_remote_forwards = 0;
649 options->log_level = (LogLevel) - 1;
653 * Called after processing other sources of option data, this fills those
654 * options for which no value has been specified with their default values.
658 fill_default_options(Options * options)
660 if (options->forward_agent == -1)
661 options->forward_agent = 1;
662 if (options->forward_x11 == -1)
663 options->forward_x11 = 0;
664 if (options->gateway_ports == -1)
665 options->gateway_ports = 0;
666 if (options->use_privileged_port == -1)
667 options->use_privileged_port = 1;
668 if (options->rhosts_authentication == -1)
669 options->rhosts_authentication = 1;
670 if (options->rsa_authentication == -1)
671 options->rsa_authentication = 1;
672 if (options->skey_authentication == -1)
673 options->skey_authentication = 0;
675 if (options->krb4_authentication == -1)
676 options->krb4_authentication = 1;
679 if (options->krb5_authentication == -1)
680 options->krb5_authentication = 1;
681 if (options->krb5_tgt_passing == -1)
682 options->krb5_tgt_passing = 1;
685 if (options->krb4_tgt_passing == -1)
686 options->krb4_tgt_passing = 1;
687 if (options->afs_token_passing == -1)
688 options->afs_token_passing = 1;
690 if (options->password_authentication == -1)
691 options->password_authentication = 1;
692 if (options->rhosts_rsa_authentication == -1)
693 options->rhosts_rsa_authentication = 1;
694 if (options->fallback_to_rsh == -1)
695 options->fallback_to_rsh = 1;
696 if (options->use_rsh == -1)
697 options->use_rsh = 0;
698 if (options->batch_mode == -1)
699 options->batch_mode = 0;
700 if (options->check_host_ip == -1)
701 options->check_host_ip = 0;
702 if (options->strict_host_key_checking == -1)
703 options->strict_host_key_checking = 2; /* 2 is default */
704 if (options->compression == -1)
705 options->compression = 0;
706 if (options->keepalives == -1)
707 options->keepalives = 1;
708 if (options->compression_level == -1)
709 options->compression_level = 6;
710 if (options->port == -1)
711 options->port = 0; /* Filled in ssh_connect. */
712 if (options->connection_attempts == -1)
713 options->connection_attempts = 4;
714 if (options->number_of_password_prompts == -1)
715 options->number_of_password_prompts = 3;
716 /* Selected in ssh_login(). */
717 if (options->cipher == -1)
718 options->cipher = SSH_CIPHER_NOT_SET;
719 if (options->num_identity_files == 0) {
720 options->identity_files[0] =
721 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
722 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
723 options->num_identity_files = 1;
725 if (options->escape_char == -1)
726 options->escape_char = '~';
727 if (options->system_hostfile == NULL)
728 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
729 if (options->user_hostfile == NULL)
730 options->user_hostfile = SSH_USER_HOSTFILE;
731 if (options->log_level == (LogLevel) - 1)
732 options->log_level = SYSLOG_LEVEL_INFO;
733 /* options->proxy_command should not be set by default */
734 /* options->user will be set in the main program if appropriate */
735 /* options->hostname will be set in the main program if appropriate */