readconf.c revision 57430
162587Sitojun/* 295023Ssuz * 362587Sitojun * readconf.c 453541Sshin * 553541Sshin * Author: Tatu Ylonen <ylo@cs.hut.fi> 653541Sshin * 753541Sshin * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 853541Sshin * All rights reserved 953541Sshin * 1053541Sshin * Created: Sat Apr 22 00:03:10 1995 ylo 1153541Sshin * 1253541Sshin * Functions for reading the configuration files. 1353541Sshin * 1453541Sshin */ 1553541Sshin 1653541Sshin#include "includes.h" 1753541SshinRCSID("$Id: readconf.c,v 1.22 1999/12/01 13:59:15 markus Exp $"); 1853541Sshin 1953541Sshin#include "ssh.h" 2053541Sshin#include "cipher.h" 2153541Sshin#include "readconf.h" 2253541Sshin#include "xmalloc.h" 2353541Sshin 2453541Sshin/* Format of the configuration file: 2553541Sshin 2653541Sshin # Configuration data is parsed as follows: 2753541Sshin # 1. command line options 2853541Sshin # 2. user-specific file 2953541Sshin # 3. system-wide file 3053541Sshin # Any configuration value is only changed the first time it is set. 3153541Sshin # Thus, host-specific definitions should be at the beginning of the 3253541Sshin # configuration file, and defaults at the end. 3353541Sshin 3453541Sshin # Host-specific declarations. These may override anything above. A single 3553541Sshin # host may match multiple declarations; these are processed in the order 3653541Sshin # that they are given in. 3753541Sshin 3853541Sshin Host *.ngs.fi ngs.fi 3953541Sshin FallBackToRsh no 4053541Sshin 4153541Sshin Host fake.com 4253541Sshin HostName another.host.name.real.org 4353541Sshin User blaah 4453541Sshin Port 34289 4553541Sshin ForwardX11 no 4653541Sshin ForwardAgent no 4753541Sshin 4853541Sshin Host books.com 4953541Sshin RemoteForward 9999 shadows.cs.hut.fi:9999 5053541Sshin Cipher 3des 5153541Sshin 5253541Sshin Host fascist.blob.com 5353541Sshin Port 23123 5453541Sshin User tylonen 5553541Sshin RhostsAuthentication no 5653541Sshin PasswordAuthentication no 5753541Sshin 5853541Sshin Host puukko.hut.fi 5953541Sshin User t35124p 6053541Sshin ProxyCommand ssh-proxy %h %p 6153541Sshin 6253541Sshin Host *.fr 6353541Sshin UseRsh yes 6453541Sshin 6553541Sshin Host *.su 6653541Sshin Cipher none 6753541Sshin PasswordAuthentication no 6862587Sitojun 6962587Sitojun # Defaults for various options 7062587Sitojun Host * 7153541Sshin ForwardAgent no 7253541Sshin ForwardX11 yes 7353541Sshin RhostsAuthentication yes 7453541Sshin PasswordAuthentication yes 7553541Sshin RSAAuthentication yes 7653541Sshin RhostsRSAAuthentication yes 7753541Sshin FallBackToRsh no 7853541Sshin UseRsh no 7953541Sshin StrictHostKeyChecking yes 8053541Sshin KeepAlives no 8153541Sshin IdentityFile ~/.ssh/identity 8253541Sshin Port 22 8353541Sshin EscapeChar ~ 8453541Sshin 8553541Sshin*/ 8653541Sshin 8753541Sshin/* Keyword tokens. */ 8853541Sshin 8953541Sshintypedef enum { 9053541Sshin oBadOption, 9178064Sume oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication, 9278064Sume oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh, 9378064Sume oSkeyAuthentication, 9453541Sshin#ifdef KRB4 9562587Sitojun oKerberosAuthentication, 9653541Sshin#endif /* KRB4 */ 9795023Ssuz#ifdef AFS 9853541Sshin oKerberosTgtPassing, oAFSTokenPassing, 9962587Sitojun#endif 10053541Sshin oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 10162587Sitojun oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 10278064Sume oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 10362587Sitojun oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 10453541Sshin oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, 10553541Sshin oUsePrivilegedPort, oLogLevel 10653541Sshin} OpCodes; 10753541Sshin 10853541Sshin/* Textual representations of the tokens. */ 10953541Sshin 11053541Sshinstatic struct { 11162587Sitojun const char *name; 11262587Sitojun OpCodes opcode; 11362587Sitojun} keywords[] = { 11453541Sshin { "forwardagent", oForwardAgent }, 11562587Sitojun { "forwardx11", oForwardX11 }, 11653541Sshin { "gatewayports", oGatewayPorts }, 11762587Sitojun { "useprivilegedport", oUsePrivilegedPort }, 11853541Sshin { "rhostsauthentication", oRhostsAuthentication }, 11953541Sshin { "passwordauthentication", oPasswordAuthentication }, 12062587Sitojun { "rsaauthentication", oRSAAuthentication }, 12162587Sitojun { "skeyauthentication", oSkeyAuthentication }, 12262587Sitojun#ifdef KRB4 12362587Sitojun { "kerberosauthentication", oKerberosAuthentication }, 12462587Sitojun#endif /* KRB4 */ 12553541Sshin#ifdef AFS 12678064Sume { "kerberostgtpassing", oKerberosTgtPassing }, 12778064Sume { "afstokenpassing", oAFSTokenPassing }, 12878064Sume#endif 12962587Sitojun { "fallbacktorsh", oFallBackToRsh }, 13083366Sjulian { "usersh", oUseRsh }, 13178064Sume { "identityfile", oIdentityFile }, 132120891Sume { "hostname", oHostName }, 13378064Sume { "proxycommand", oProxyCommand }, 13453541Sshin { "port", oPort }, 13562587Sitojun { "cipher", oCipher }, 13683934Sbrooks { "remoteforward", oRemoteForward }, 13783934Sbrooks { "localforward", oLocalForward }, 13853541Sshin { "user", oUser }, 13953541Sshin { "host", oHost }, 14053541Sshin { "escapechar", oEscapeChar }, 14153541Sshin { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 14253541Sshin { "globalknownhostsfile", oGlobalKnownHostsFile }, 14353541Sshin { "userknownhostsfile", oUserKnownHostsFile }, 14453541Sshin { "connectionattempts", oConnectionAttempts }, 14553541Sshin { "batchmode", oBatchMode }, 14678064Sume { "checkhostip", oCheckHostIP }, 14778064Sume { "stricthostkeychecking", oStrictHostKeyChecking }, 148120891Sume { "compression", oCompression }, 14953541Sshin { "compressionlevel", oCompressionLevel }, 15078064Sume { "keepalive", oKeepAlives }, 15178064Sume { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 15253541Sshin { "tisauthentication", oTISAuthentication }, 15378064Sume { "loglevel", oLogLevel }, 15462587Sitojun { NULL, 0 } 15578064Sume}; 15678064Sume 15778064Sume/* Characters considered whitespace in strtok calls. */ 15878064Sume#define WHITESPACE " \t\r\n" 15978064Sume 16078064Sume 16162587Sitojun/* 16278064Sume * Adds a local TCP/IP port forward to options. Never returns if there is an 163120891Sume * error. 16478064Sume */ 165120891Sume 16678064Sumevoid 16778064Sumeadd_local_forward(Options *options, u_short port, const char *host, 16878064Sume u_short host_port) 16978064Sume{ 17078064Sume Forward *fwd; 17178064Sume extern uid_t original_real_uid; 17253541Sshin if (port < IPPORT_RESERVED && original_real_uid != 0) 173120727Ssam fatal("Privileged ports can only be forwarded by root.\n"); 174120727Ssam if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 175120727Ssam fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 176120727Ssam fwd = &options->local_forwards[options->num_local_forwards++]; 177120727Ssam fwd->port = port; 178120727Ssam fwd->host = xstrdup(host); 179120727Ssam fwd->host_port = host_port; 180120727Ssam} 181120727Ssam 182120727Ssam/* 183120727Ssam * Adds a remote TCP/IP port forward to options. Never returns if there is 184120727Ssam * an error. 185120727Ssam */ 18678064Sume 187120727Ssamvoid 188120727Ssamadd_remote_forward(Options *options, u_short port, const char *host, 189120727Ssam u_short host_port) 190120727Ssam{ 191120727Ssam Forward *fwd; 192120727Ssam if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 193120727Ssam fatal("Too many remote forwards (max %d).", 194120727Ssam SSH_MAX_FORWARDS_PER_DIRECTION); 19578064Sume fwd = &options->remote_forwards[options->num_remote_forwards++]; 19678064Sume fwd->port = port; 197120727Ssam fwd->host = xstrdup(host); 19878064Sume fwd->host_port = host_port; 19978064Sume} 200122334Ssam 201120727Ssam/* 20278064Sume * Returns the number of the token pointed to by cp of length len. Never 20378064Sume * returns if the token is not known. 20453541Sshin */ 20553541Sshin 20653541Sshinstatic OpCodes 20778064Sumeparse_token(const char *cp, const char *filename, int linenum) 20878064Sume{ 20978064Sume unsigned int i; 21078064Sume 21178064Sume for (i = 0; keywords[i].name; i++) 21253541Sshin if (strcasecmp(cp, keywords[i].name) == 0) 21353541Sshin return keywords[i].opcode; 21453541Sshin 21553541Sshin fprintf(stderr, "%s: line %d: Bad configuration option: %s\n", 21678064Sume filename, linenum, cp); 217121716Ssam return oBadOption; 21853541Sshin} 21978064Sume 22078064Sume/* 221121716Ssam * Processes a single option line as used in the configuration files. This 222121716Ssam * only sets those values that have not already been set. 22378064Sume */ 224120727Ssam 225121716Ssamint 226121716Ssamprocess_config_line(Options *options, const char *host, 22753541Sshin char *line, const char *filename, int linenum, 22853541Sshin int *activep) 22953541Sshin{ 23053541Sshin char buf[256], *cp, *string, **charptr, *cp2; 23153541Sshin int opcode, *intptr, value; 23253541Sshin u_short fwd_port, fwd_host_port; 23353541Sshin 23453541Sshin /* Skip leading whitespace. */ 23553541Sshin cp = line + strspn(line, WHITESPACE); 23662587Sitojun if (!*cp || *cp == '\n' || *cp == '#') 23778064Sume return 0; 23862587Sitojun 23953541Sshin /* Get the keyword. (Each line is supposed to begin with a keyword). */ 24062587Sitojun cp = strtok(cp, WHITESPACE); 24178064Sume opcode = parse_token(cp, filename, linenum); 24262587Sitojun 24378064Sume switch (opcode) { 24478064Sume case oBadOption: 24578064Sume /* don't panic, but count bad options */ 24678064Sume return -1; 24762587Sitojun /* NOTREACHED */ 24862587Sitojun case oForwardAgent: 24978064Sume intptr = &options->forward_agent; 25078064Sumeparse_flag: 25195023Ssuz cp = strtok(NULL, WHITESPACE); 25278064Sume if (!cp) 25378064Sume fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 25478064Sume value = 0; /* To avoid compiler warning... */ 25578064Sume if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0) 25678064Sume value = 1; 25778064Sume else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0) 25878064Sume value = 0; 25978064Sume else 26078064Sume fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 26153541Sshin if (*activep && *intptr == -1) 26278064Sume *intptr = value; 26378064Sume break; 26478064Sume 26578064Sume case oForwardX11: 26678064Sume intptr = &options->forward_x11; 26795023Ssuz goto parse_flag; 26878064Sume 269120891Sume case oGatewayPorts: 27078064Sume intptr = &options->gateway_ports; 27178064Sume goto parse_flag; 27278064Sume 27378064Sume case oUsePrivilegedPort: 274120727Ssam intptr = &options->use_privileged_port; 275120727Ssam goto parse_flag; 276120727Ssam 277120727Ssam case oRhostsAuthentication: 278120727Ssam intptr = &options->rhosts_authentication; 279120727Ssam goto parse_flag; 280120727Ssam 28178064Sume case oPasswordAuthentication: 28253541Sshin intptr = &options->password_authentication; 28353541Sshin goto parse_flag; 28453541Sshin 28553541Sshin case oRSAAuthentication: 28678064Sume intptr = &options->rsa_authentication; 28753541Sshin goto parse_flag; 28878064Sume 28953541Sshin case oRhostsRSAAuthentication: 29078064Sume intptr = &options->rhosts_rsa_authentication; 29178064Sume goto parse_flag; 29253541Sshin 293120891Sume case oTISAuthentication: 294120891Sume /* fallthrough, there is no difference on the client side */ 29578064Sume case oSkeyAuthentication: 29678064Sume intptr = &options->skey_authentication; 29778064Sume goto parse_flag; 29853541Sshin 29953541Sshin#ifdef KRB4 30053541Sshin case oKerberosAuthentication: 30178064Sume intptr = &options->kerberos_authentication; 30253541Sshin goto parse_flag; 30378064Sume#endif /* KRB4 */ 30453541Sshin 30553541Sshin#ifdef AFS 30653541Sshin case oKerberosTgtPassing: 30778064Sume intptr = &options->kerberos_tgt_passing; 30878064Sume goto parse_flag; 30978064Sume 31078064Sume case oAFSTokenPassing: 31178064Sume intptr = &options->afs_token_passing; 31278064Sume goto parse_flag; 31378064Sume#endif 314120856Sume 31578064Sume case oFallBackToRsh: 31678064Sume intptr = &options->fallback_to_rsh; 317120856Sume goto parse_flag; 31878064Sume 319120891Sume case oUseRsh: 32053541Sshin intptr = &options->use_rsh; 32153541Sshin goto parse_flag; 32253541Sshin 32353541Sshin case oBatchMode: 32462587Sitojun intptr = &options->batch_mode; 32553541Sshin goto parse_flag; 32653541Sshin 32783366Sjulian case oCheckHostIP: 32853541Sshin intptr = &options->check_host_ip; 32953541Sshin goto parse_flag; 33053541Sshin 33153541Sshin case oStrictHostKeyChecking: 33283366Sjulian intptr = &options->strict_host_key_checking; 33353541Sshin cp = strtok(NULL, WHITESPACE); 33453541Sshin if (!cp) 33578064Sume fatal("%.200s line %d: Missing yes/no argument.", 33653541Sshin filename, linenum); 33753541Sshin value = 0; /* To avoid compiler warning... */ 33853541Sshin if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0) 33953541Sshin value = 1; 34093593Sjhb else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0) 34153541Sshin value = 0; 34253541Sshin else if (strcmp(cp, "ask") == 0) 34362587Sitojun value = 2; 34462587Sitojun else 34562587Sitojun fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 34662587Sitojun if (*activep && *intptr == -1) 34762587Sitojun *intptr = value; 34853541Sshin break; 349121742Sume 350121742Sume case oCompression: 351121742Sume intptr = &options->compression; 352121742Sume goto parse_flag; 353121742Sume 354121742Sume case oKeepAlives: 355121742Sume intptr = &options->keepalives; 356121742Sume goto parse_flag; 35762587Sitojun 358120856Sume case oNumberOfPasswordPrompts: 35953541Sshin intptr = &options->number_of_password_prompts; 36053541Sshin goto parse_int; 36153541Sshin 36253541Sshin case oCompressionLevel: 36353541Sshin intptr = &options->compression_level; 36462587Sitojun goto parse_int; 36562587Sitojun 36653541Sshin case oIdentityFile: 367120856Sume cp = strtok(NULL, WHITESPACE); 368120891Sume if (!cp) 36978064Sume fatal("%.200s line %d: Missing argument.", filename, linenum); 37053541Sshin if (*activep) { 37153541Sshin if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 37253541Sshin fatal("%.200s line %d: Too many identity files specified (max %d).", 37353541Sshin filename, linenum, SSH_MAX_IDENTITY_FILES); 37462587Sitojun options->identity_files[options->num_identity_files++] = xstrdup(cp); 375120856Sume } 37653541Sshin break; 37753541Sshin 37853541Sshin case oUser: 37953541Sshin charptr = &options->user; 38053541Sshinparse_string: 38153541Sshin cp = strtok(NULL, WHITESPACE); 38253541Sshin if (!cp) 38353541Sshin fatal("%.200s line %d: Missing argument.", filename, linenum); 38453541Sshin if (*activep && *charptr == NULL) 38578064Sume *charptr = xstrdup(cp); 38678064Sume break; 38778064Sume 388120856Sume case oGlobalKnownHostsFile: 38953541Sshin charptr = &options->system_hostfile; 39053541Sshin goto parse_string; 39195023Ssuz 39262587Sitojun case oUserKnownHostsFile: 39362587Sitojun charptr = &options->user_hostfile; 394120856Sume goto parse_string; 395121161Sume 396121161Sume case oHostName: 39762587Sitojun charptr = &options->hostname; 398121161Sume goto parse_string; 399121161Sume 40062587Sitojun case oProxyCommand: 401121161Sume charptr = &options->proxy_command; 402121161Sume string = xstrdup(""); 40362587Sitojun while ((cp = strtok(NULL, WHITESPACE)) != NULL) { 40462587Sitojun string = xrealloc(string, strlen(string) + strlen(cp) + 2); 40553541Sshin strcat(string, " "); 40653541Sshin strcat(string, cp); 40753541Sshin } 40853541Sshin if (*activep && *charptr == NULL) 409120856Sume *charptr = string; 410120891Sume else 41153541Sshin xfree(string); 41283366Sjulian return 0; 41353541Sshin 41453541Sshin case oPort: 41553541Sshin intptr = &options->port; 41653541Sshinparse_int: 41753541Sshin cp = strtok(NULL, WHITESPACE); 41862587Sitojun if (!cp) 41953541Sshin fatal("%.200s line %d: Missing argument.", filename, linenum); 42053541Sshin if (cp[0] < '0' || cp[0] > '9') 42153541Sshin fatal("%.200s line %d: Bad number.", filename, linenum); 42253541Sshin 42353541Sshin /* Octal, decimal, or hex format? */ 42478064Sume value = strtol(cp, &cp2, 0); 42553541Sshin if (cp == cp2) 426120891Sume fatal("%.200s line %d: Bad number.", filename, linenum); 42762587Sitojun if (*activep && *intptr == -1) 428120891Sume *intptr = value; 429120856Sume break; 43062587Sitojun 43153541Sshin case oConnectionAttempts: 43253541Sshin intptr = &options->connection_attempts; 43353541Sshin goto parse_int; 434120856Sume 43553541Sshin case oCipher: 43653541Sshin intptr = &options->cipher; 43753541Sshin cp = strtok(NULL, WHITESPACE); 43862587Sitojun value = cipher_number(cp); 43953541Sshin if (value == -1) 44053541Sshin fatal("%.200s line %d: Bad cipher '%s'.", 44153541Sshin filename, linenum, cp ? cp : "<NONE>"); 44278064Sume if (*activep && *intptr == -1) 44378064Sume *intptr = value; 44478064Sume break; 44578064Sume 44678064Sume case oLogLevel: 44778064Sume intptr = (int *) &options->log_level; 44878064Sume cp = strtok(NULL, WHITESPACE); 44978064Sume value = log_level_number(cp); 45078064Sume if (value == (LogLevel) - 1) 451120856Sume fatal("%.200s line %d: unsupported log level '%s'\n", 45253541Sshin filename, linenum, cp ? cp : "<NONE>"); 45353541Sshin if (*activep && (LogLevel) * intptr == -1) 45462587Sitojun *intptr = (LogLevel) value; 45578064Sume break; 45662587Sitojun 45762587Sitojun case oRemoteForward: 45862587Sitojun cp = strtok(NULL, WHITESPACE); 45978064Sume if (!cp) 46062587Sitojun fatal("%.200s line %d: Missing argument.", filename, linenum); 46162587Sitojun if (cp[0] < '0' || cp[0] > '9') 462120856Sume fatal("%.200s line %d: Badly formatted port number.", 46353541Sshin filename, linenum); 46453541Sshin fwd_port = atoi(cp); 46562587Sitojun cp = strtok(NULL, WHITESPACE); 46678064Sume if (!cp) 46778064Sume fatal("%.200s line %d: Missing second argument.", 46862587Sitojun filename, linenum); 46978064Sume if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2) 47078064Sume fatal("%.200s line %d: Badly formatted host:port.", 471120856Sume filename, linenum); 47253541Sshin if (*activep) 473120856Sume add_remote_forward(options, fwd_port, buf, fwd_host_port); 47453541Sshin break; 47553541Sshin 47653541Sshin case oLocalForward: 47753541Sshin cp = strtok(NULL, WHITESPACE); 47853541Sshin if (!cp) 479120891Sume fatal("%.200s line %d: Missing argument.", filename, linenum); 48053541Sshin if (cp[0] < '0' || cp[0] > '9') 48153541Sshin fatal("%.200s line %d: Badly formatted port number.", 48253541Sshin filename, linenum); 48353541Sshin fwd_port = atoi(cp); 48453541Sshin cp = strtok(NULL, WHITESPACE); 48562587Sitojun if (!cp) 486120856Sume fatal("%.200s line %d: Missing second argument.", 48753541Sshin filename, linenum); 48853541Sshin if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2) 48953541Sshin fatal("%.200s line %d: Badly formatted host:port.", 49053541Sshin filename, linenum); 49153541Sshin if (*activep) 49253541Sshin add_local_forward(options, fwd_port, buf, fwd_host_port); 493120856Sume break; 49462587Sitojun 495120856Sume case oHost: 49653541Sshin *activep = 0; 49753541Sshin while ((cp = strtok(NULL, WHITESPACE)) != NULL) 49853541Sshin if (match_pattern(host, cp)) { 49953541Sshin debug("Applying options for %.100s", cp); 50053541Sshin *activep = 1; 50153541Sshin break; 50253541Sshin } 50353541Sshin /* Avoid garbage check below, as strtok already returned NULL. */ 50453541Sshin return 0; 50553541Sshin 50653541Sshin case oEscapeChar: 50753541Sshin intptr = &options->escape_char; 50853541Sshin cp = strtok(NULL, WHITESPACE); 50953541Sshin if (!cp) 51053541Sshin fatal("%.200s line %d: Missing argument.", filename, linenum); 51153541Sshin if (cp[0] == '^' && cp[2] == 0 && 51253541Sshin (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128) 51353541Sshin value = (unsigned char) cp[1] & 31; 51453541Sshin else if (strlen(cp) == 1) 51553541Sshin value = (unsigned char) cp[0]; 51653541Sshin else if (strcmp(cp, "none") == 0) 51753541Sshin value = -2; 518120856Sume else { 51962587Sitojun fatal("%.200s line %d: Bad escape character.", 52062587Sitojun filename, linenum); 52162587Sitojun /* NOTREACHED */ 52262587Sitojun value = 0; /* Avoid compiler warning. */ 52353541Sshin } 52453541Sshin if (*activep && *intptr == -1) 52553541Sshin *intptr = value; 52653541Sshin break; 52753541Sshin 52853541Sshin default: 52953541Sshin fatal("process_config_line: Unimplemented opcode %d", opcode); 53053541Sshin } 53153541Sshin 53253541Sshin /* Check that there is no garbage at end of line. */ 53353541Sshin if (strtok(NULL, WHITESPACE) != NULL) 53453541Sshin fatal("%.200s line %d: garbage at end of line.", 535121167Sume filename, linenum); 536121167Sume return 0; 537121161Sume} 538121161Sume 539121161Sume 540121161Sume/* 54153541Sshin * Reads the config file and modifies the options accordingly. Options 54253541Sshin * should already be initialized before this call. This never returns if 54353541Sshin * there is an error. If the file does not exist, this returns immediately. 54453541Sshin */ 54553541Sshin 546121161Sumevoid 547121161Sumeread_config_file(const char *filename, const char *host, Options *options) 548121161Sume{ 549121161Sume FILE *f; 55053541Sshin char line[1024]; 55153541Sshin int active, linenum; 55253541Sshin int bad_options = 0; 55353541Sshin 55453541Sshin /* Open the file. */ 55553541Sshin f = fopen(filename, "r"); 55653541Sshin if (!f) 55753541Sshin return; 55853541Sshin 55953541Sshin debug("Reading configuration data %.200s", filename); 56053541Sshin 56153541Sshin /* 56253541Sshin * Mark that we are now processing the options. This flag is turned 56353541Sshin * on/off by Host specifications. 56453541Sshin */ 56553541Sshin active = 1; 56653541Sshin linenum = 0; 56753541Sshin while (fgets(line, sizeof(line), f)) { 56853541Sshin /* Update line number counter. */ 56953541Sshin linenum++; 57053541Sshin if (process_config_line(options, host, line, filename, linenum, &active) != 0) 57178064Sume bad_options++; 57278064Sume } 57378064Sume fclose(f); 57478064Sume if (bad_options > 0) 57578064Sume fatal("%s: terminating, %d bad configuration options\n", 57662587Sitojun filename, bad_options); 57778064Sume} 57878064Sume 57962587Sitojun/* 58078064Sume * Initializes options to special values that indicate that they have not yet 581120856Sume * been set. Read_config_file will only set options with this value. Options 58253541Sshin * are processed in the following order: command line, user config file, 58378064Sume * system config file. Last, fill_default_options is called. 58478064Sume */ 58578064Sume 58678064Sumevoid 58778064Sumeinitialize_options(Options * options) 58878064Sume{ 58978064Sume memset(options, 'X', sizeof(*options)); 59078064Sume options->forward_agent = -1; 59178064Sume options->forward_x11 = -1; 59278064Sume options->gateway_ports = -1; 59378064Sume options->use_privileged_port = -1; 59478064Sume options->rhosts_authentication = -1; 59578064Sume options->rsa_authentication = -1; 59678064Sume options->skey_authentication = -1; 597120891Sume#ifdef KRB4 598120891Sume options->kerberos_authentication = -1; 59978064Sume#endif 600120891Sume#ifdef AFS 60178064Sume options->kerberos_tgt_passing = -1; 60278064Sume options->afs_token_passing = -1; 60378064Sume#endif 60478064Sume options->password_authentication = -1; 60578064Sume options->rhosts_rsa_authentication = -1; 606120891Sume options->fallback_to_rsh = -1; 60778064Sume options->use_rsh = -1; 60878064Sume options->batch_mode = -1; 60995023Ssuz options->check_host_ip = -1; 61095023Ssuz options->strict_host_key_checking = -1; 61195023Ssuz options->compression = -1; 61295023Ssuz options->keepalives = -1; 61395023Ssuz options->compression_level = -1; 61478064Sume options->port = -1; 61578064Sume options->connection_attempts = -1; 61678064Sume options->number_of_password_prompts = -1; 617120891Sume options->cipher = -1; 61878064Sume options->num_identity_files = 0; 61978064Sume options->hostname = NULL; 62078064Sume options->proxy_command = NULL; 621120891Sume options->user = NULL; 62278064Sume options->escape_char = -1; 62378064Sume options->system_hostfile = NULL; 62478064Sume options->user_hostfile = NULL; 62578064Sume options->num_local_forwards = 0; 62678064Sume options->num_remote_forwards = 0; 62778064Sume options->log_level = (LogLevel) - 1; 628120856Sume} 62978064Sume 630120891Sume/* 63178064Sume * Called after processing other sources of option data, this fills those 632120856Sume * options for which no value has been specified with their default values. 63378064Sume */ 63478064Sume 63578064Sumevoid 63678064Sumefill_default_options(Options * options) 63778064Sume{ 63878064Sume if (options->forward_agent == -1) 63978064Sume options->forward_agent = 1; 64078064Sume if (options->forward_x11 == -1) 64178064Sume options->forward_x11 = 1; 64278064Sume if (options->gateway_ports == -1) 64378064Sume options->gateway_ports = 0; 64478064Sume if (options->use_privileged_port == -1) 64578064Sume options->use_privileged_port = 1; 64678064Sume if (options->rhosts_authentication == -1) 64778064Sume options->rhosts_authentication = 1; 64878064Sume if (options->rsa_authentication == -1) 64978064Sume options->rsa_authentication = 1; 65078064Sume if (options->skey_authentication == -1) 65178064Sume options->skey_authentication = 0; 65278064Sume#ifdef KRB4 65378064Sume if (options->kerberos_authentication == -1) 65478064Sume options->kerberos_authentication = 1; 65578064Sume#endif /* KRB4 */ 65678064Sume#ifdef AFS 65778064Sume if (options->kerberos_tgt_passing == -1) 658122059Sume options->kerberos_tgt_passing = 1; 65978064Sume if (options->afs_token_passing == -1) 66062587Sitojun options->afs_token_passing = 1; 66162587Sitojun#endif /* AFS */ 66278064Sume if (options->password_authentication == -1) 66378064Sume options->password_authentication = 1; 66478064Sume if (options->rhosts_rsa_authentication == -1) 66578064Sume options->rhosts_rsa_authentication = 1; 66678064Sume if (options->fallback_to_rsh == -1) 66778064Sume options->fallback_to_rsh = 1; 66878064Sume if (options->use_rsh == -1) 66962587Sitojun options->use_rsh = 0; 67078064Sume if (options->batch_mode == -1) 67178064Sume options->batch_mode = 0; 67262587Sitojun if (options->check_host_ip == -1) 67378064Sume options->check_host_ip = 1; 67478064Sume if (options->strict_host_key_checking == -1) 67578064Sume options->strict_host_key_checking = 2; /* 2 is default */ 67678064Sume if (options->compression == -1) 67778064Sume options->compression = 0; 67878064Sume if (options->keepalives == -1) 67978064Sume options->keepalives = 1; 68078064Sume if (options->compression_level == -1) 681120891Sume options->compression_level = 6; 68278064Sume if (options->port == -1) 68378064Sume options->port = 0; /* Filled in ssh_connect. */ 68478064Sume if (options->connection_attempts == -1) 68578064Sume options->connection_attempts = 4; 68678064Sume if (options->number_of_password_prompts == -1) 68778064Sume options->number_of_password_prompts = 3; 68878064Sume /* Selected in ssh_login(). */ 68978064Sume if (options->cipher == -1) 69078064Sume options->cipher = SSH_CIPHER_NOT_SET; 69178064Sume if (options->num_identity_files == 0) { 69278064Sume options->identity_files[0] = 69378064Sume xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1); 69478064Sume sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY); 69578064Sume options->num_identity_files = 1; 69678064Sume } 69778064Sume if (options->escape_char == -1) 69878064Sume options->escape_char = '~'; 69978064Sume if (options->system_hostfile == NULL) 70078064Sume options->system_hostfile = SSH_SYSTEM_HOSTFILE; 70178064Sume if (options->user_hostfile == NULL) 70278064Sume options->user_hostfile = SSH_USER_HOSTFILE; 70378064Sume if (options->log_level == (LogLevel) - 1) 70478064Sume options->log_level = SYSLOG_LEVEL_INFO; 70578064Sume /* options->proxy_command should not be set by default */ 70678064Sume /* options->user will be set in the main program if appropriate */ 70778064Sume /* options->hostname will be set in the main program if appropriate */ 70878064Sume} 70978064Sume