readconf.c revision 149753
157429Smarkm/* 257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 457429Smarkm * All rights reserved 557429Smarkm * Functions for reading the configuration files. 660576Skris * 765674Skris * As far as I am concerned, the code I have written for this software 865674Skris * can be used freely for any purpose. Any derived versions of this 965674Skris * software must be clearly marked as such, and if the derived work is 1065674Skris * incompatible with the protocol description in the RFC file, it must be 1165674Skris * called by a name other than "ssh" or "Secure Shell". 1257429Smarkm */ 1357429Smarkm 1457429Smarkm#include "includes.h" 15149753SdesRCSID("$OpenBSD: readconf.c,v 1.143 2005/07/30 02:03:47 djm Exp $"); 16128460SdesRCSID("$FreeBSD: head/crypto/openssh/readconf.c 149753 2005-09-03 07:04:25Z des $"); 1757429Smarkm 1857429Smarkm#include "ssh.h" 1976262Sgreen#include "xmalloc.h" 2076262Sgreen#include "compat.h" 2176262Sgreen#include "cipher.h" 2276262Sgreen#include "pathnames.h" 2376262Sgreen#include "log.h" 2457429Smarkm#include "readconf.h" 2560576Skris#include "match.h" 2676262Sgreen#include "misc.h" 2776262Sgreen#include "kex.h" 2876262Sgreen#include "mac.h" 2957429Smarkm 3057429Smarkm/* Format of the configuration file: 3157429Smarkm 3257429Smarkm # Configuration data is parsed as follows: 3357429Smarkm # 1. command line options 3457429Smarkm # 2. user-specific file 3557429Smarkm # 3. system-wide file 3657429Smarkm # Any configuration value is only changed the first time it is set. 3757429Smarkm # Thus, host-specific definitions should be at the beginning of the 3857429Smarkm # configuration file, and defaults at the end. 3957429Smarkm 4057429Smarkm # Host-specific declarations. These may override anything above. A single 4157429Smarkm # host may match multiple declarations; these are processed in the order 4257429Smarkm # that they are given in. 4357429Smarkm 4457429Smarkm Host *.ngs.fi ngs.fi 4598684Sdes User foo 4657429Smarkm 4757429Smarkm Host fake.com 4857429Smarkm HostName another.host.name.real.org 4957429Smarkm User blaah 5057429Smarkm Port 34289 5157429Smarkm ForwardX11 no 5257429Smarkm ForwardAgent no 5357429Smarkm 5457429Smarkm Host books.com 5557429Smarkm RemoteForward 9999 shadows.cs.hut.fi:9999 5657429Smarkm Cipher 3des 5757429Smarkm 5857429Smarkm Host fascist.blob.com 5957429Smarkm Port 23123 6057429Smarkm User tylonen 6157429Smarkm PasswordAuthentication no 6257429Smarkm 6357429Smarkm Host puukko.hut.fi 6457429Smarkm User t35124p 6557429Smarkm ProxyCommand ssh-proxy %h %p 6657429Smarkm 6757429Smarkm Host *.fr 6898684Sdes PublicKeyAuthentication no 6957429Smarkm 7057429Smarkm Host *.su 7157429Smarkm Cipher none 7257429Smarkm PasswordAuthentication no 7357429Smarkm 7457429Smarkm # Defaults for various options 7557429Smarkm Host * 7657429Smarkm ForwardAgent no 7776262Sgreen ForwardX11 no 7857429Smarkm PasswordAuthentication yes 7957429Smarkm RSAAuthentication yes 8057429Smarkm RhostsRSAAuthentication yes 8157429Smarkm StrictHostKeyChecking yes 82126277Sdes TcpKeepAlive no 8357429Smarkm IdentityFile ~/.ssh/identity 8457429Smarkm Port 22 8557429Smarkm EscapeChar ~ 8657429Smarkm 8757429Smarkm*/ 8857429Smarkm 8957429Smarkm/* Keyword tokens. */ 9057429Smarkm 9157429Smarkmtypedef enum { 9257429Smarkm oBadOption, 93126277Sdes oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, 9498684Sdes oPasswordAuthentication, oRSAAuthentication, 9576262Sgreen oChallengeResponseAuthentication, oXAuthLocation, 9657429Smarkm oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 9757429Smarkm oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 9857429Smarkm oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 9957429Smarkm oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 100126277Sdes oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 10176262Sgreen oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 10276262Sgreen oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 10376262Sgreen oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 10476262Sgreen oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 10592559Sdes oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 10693698Sdes oClearAllForwardings, oNoHostAuthenticationForLocalhost, 107124211Sdes oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 108124211Sdes oAddressFamily, oGssAuthentication, oGssDelegateCreds, 109128461Sdes oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 110147005Sdes oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, 11199048Sdes oVersionAddendum, 112124211Sdes oDeprecated, oUnsupported 11357429Smarkm} OpCodes; 11457429Smarkm 11557429Smarkm/* Textual representations of the tokens. */ 11657429Smarkm 11757429Smarkmstatic struct { 11857429Smarkm const char *name; 11957429Smarkm OpCodes opcode; 12057429Smarkm} keywords[] = { 12157429Smarkm { "forwardagent", oForwardAgent }, 12257429Smarkm { "forwardx11", oForwardX11 }, 123126277Sdes { "forwardx11trusted", oForwardX11Trusted }, 12465674Skris { "xauthlocation", oXAuthLocation }, 12557429Smarkm { "gatewayports", oGatewayPorts }, 12657429Smarkm { "useprivilegedport", oUsePrivilegedPort }, 127124211Sdes { "rhostsauthentication", oDeprecated }, 12857429Smarkm { "passwordauthentication", oPasswordAuthentication }, 12969591Sgreen { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 13069591Sgreen { "kbdinteractivedevices", oKbdInteractiveDevices }, 13157429Smarkm { "rsaauthentication", oRSAAuthentication }, 13276262Sgreen { "pubkeyauthentication", oPubkeyAuthentication }, 13376262Sgreen { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 13476262Sgreen { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 13576262Sgreen { "hostbasedauthentication", oHostbasedAuthentication }, 13676262Sgreen { "challengeresponseauthentication", oChallengeResponseAuthentication }, 13776262Sgreen { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 13876262Sgreen { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 139124211Sdes { "kerberosauthentication", oUnsupported }, 140124211Sdes { "kerberostgtpassing", oUnsupported }, 141124211Sdes { "afstokenpassing", oUnsupported }, 142124211Sdes#if defined(GSSAPI) 143124211Sdes { "gssapiauthentication", oGssAuthentication }, 144124211Sdes { "gssapidelegatecredentials", oGssDelegateCreds }, 145124211Sdes#else 146124211Sdes { "gssapiauthentication", oUnsupported }, 147124211Sdes { "gssapidelegatecredentials", oUnsupported }, 14892559Sdes#endif 14998684Sdes { "fallbacktorsh", oDeprecated }, 15098684Sdes { "usersh", oDeprecated }, 15157429Smarkm { "identityfile", oIdentityFile }, 15276262Sgreen { "identityfile2", oIdentityFile }, /* alias */ 153128460Sdes { "identitiesonly", oIdentitiesOnly }, 15457429Smarkm { "hostname", oHostName }, 15576262Sgreen { "hostkeyalias", oHostKeyAlias }, 15657429Smarkm { "proxycommand", oProxyCommand }, 15757429Smarkm { "port", oPort }, 15857429Smarkm { "cipher", oCipher }, 15960576Skris { "ciphers", oCiphers }, 16076262Sgreen { "macs", oMacs }, 16160576Skris { "protocol", oProtocol }, 16257429Smarkm { "remoteforward", oRemoteForward }, 16357429Smarkm { "localforward", oLocalForward }, 16457429Smarkm { "user", oUser }, 16557429Smarkm { "host", oHost }, 16657429Smarkm { "escapechar", oEscapeChar }, 16757429Smarkm { "globalknownhostsfile", oGlobalKnownHostsFile }, 16892559Sdes { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ 16960576Skris { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, 17092559Sdes { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 17157429Smarkm { "connectionattempts", oConnectionAttempts }, 17257429Smarkm { "batchmode", oBatchMode }, 17357429Smarkm { "checkhostip", oCheckHostIP }, 17457429Smarkm { "stricthostkeychecking", oStrictHostKeyChecking }, 17557429Smarkm { "compression", oCompression }, 17657429Smarkm { "compressionlevel", oCompressionLevel }, 177126277Sdes { "tcpkeepalive", oTCPKeepAlive }, 178126277Sdes { "keepalive", oTCPKeepAlive }, /* obsolete */ 17957429Smarkm { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 18057429Smarkm { "loglevel", oLogLevel }, 18176262Sgreen { "dynamicforward", oDynamicForward }, 18276262Sgreen { "preferredauthentications", oPreferredAuthentications }, 18376262Sgreen { "hostkeyalgorithms", oHostKeyAlgorithms }, 18492559Sdes { "bindaddress", oBindAddress }, 185124211Sdes#ifdef SMARTCARD 18692559Sdes { "smartcarddevice", oSmartcardDevice }, 187124211Sdes#else 188124211Sdes { "smartcarddevice", oUnsupported }, 189124211Sdes#endif 19092559Sdes { "clearallforwardings", oClearAllForwardings }, 191113911Sdes { "enablesshkeysign", oEnableSSHKeysign }, 192124211Sdes { "verifyhostkeydns", oVerifyHostKeyDNS }, 19392559Sdes { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 194124211Sdes { "rekeylimit", oRekeyLimit }, 195124211Sdes { "connecttimeout", oConnectTimeout }, 196124211Sdes { "addressfamily", oAddressFamily }, 197126277Sdes { "serveraliveinterval", oServerAliveInterval }, 198126277Sdes { "serveralivecountmax", oServerAliveCountMax }, 199137019Sdes { "sendenv", oSendEnv }, 200137019Sdes { "controlpath", oControlPath }, 201137019Sdes { "controlmaster", oControlMaster }, 202147005Sdes { "hashknownhosts", oHashKnownHosts }, 20399048Sdes { "versionaddendum", oVersionAddendum }, 20492559Sdes { NULL, oBadOption } 20557429Smarkm}; 20657429Smarkm 20757429Smarkm/* 20857429Smarkm * Adds a local TCP/IP port forward to options. Never returns if there is an 20957429Smarkm * error. 21057429Smarkm */ 21157429Smarkm 21260576Skrisvoid 213147005Sdesadd_local_forward(Options *options, const Forward *newfwd) 21457429Smarkm{ 21557429Smarkm Forward *fwd; 216106130Sdes#ifndef NO_IPPORT_RESERVED_CONCEPT 21757429Smarkm extern uid_t original_real_uid; 218147005Sdes if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 21976262Sgreen fatal("Privileged ports can only be forwarded by root."); 22098941Sdes#endif 22157429Smarkm if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 22257429Smarkm fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 22357429Smarkm fwd = &options->local_forwards[options->num_local_forwards++]; 224147005Sdes 225147005Sdes fwd->listen_host = (newfwd->listen_host == NULL) ? 226147005Sdes NULL : xstrdup(newfwd->listen_host); 227147005Sdes fwd->listen_port = newfwd->listen_port; 228147005Sdes fwd->connect_host = xstrdup(newfwd->connect_host); 229147005Sdes fwd->connect_port = newfwd->connect_port; 23057429Smarkm} 23157429Smarkm 23257429Smarkm/* 23357429Smarkm * Adds a remote TCP/IP port forward to options. Never returns if there is 23457429Smarkm * an error. 23557429Smarkm */ 23657429Smarkm 23760576Skrisvoid 238147005Sdesadd_remote_forward(Options *options, const Forward *newfwd) 23957429Smarkm{ 24057429Smarkm Forward *fwd; 24157429Smarkm if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 24257429Smarkm fatal("Too many remote forwards (max %d).", 24392559Sdes SSH_MAX_FORWARDS_PER_DIRECTION); 24457429Smarkm fwd = &options->remote_forwards[options->num_remote_forwards++]; 245147005Sdes 246147005Sdes fwd->listen_host = (newfwd->listen_host == NULL) ? 247147005Sdes NULL : xstrdup(newfwd->listen_host); 248147005Sdes fwd->listen_port = newfwd->listen_port; 249147005Sdes fwd->connect_host = xstrdup(newfwd->connect_host); 250147005Sdes fwd->connect_port = newfwd->connect_port; 25157429Smarkm} 25257429Smarkm 25392559Sdesstatic void 25492559Sdesclear_forwardings(Options *options) 25592559Sdes{ 25692559Sdes int i; 25792559Sdes 258147005Sdes for (i = 0; i < options->num_local_forwards; i++) { 259147005Sdes if (options->local_forwards[i].listen_host != NULL) 260147005Sdes xfree(options->local_forwards[i].listen_host); 261147005Sdes xfree(options->local_forwards[i].connect_host); 262147005Sdes } 26392559Sdes options->num_local_forwards = 0; 264147005Sdes for (i = 0; i < options->num_remote_forwards; i++) { 265147005Sdes if (options->remote_forwards[i].listen_host != NULL) 266147005Sdes xfree(options->remote_forwards[i].listen_host); 267147005Sdes xfree(options->remote_forwards[i].connect_host); 268147005Sdes } 26992559Sdes options->num_remote_forwards = 0; 27092559Sdes} 27192559Sdes 27257429Smarkm/* 27376262Sgreen * Returns the number of the token pointed to by cp or oBadOption. 27457429Smarkm */ 27557429Smarkm 27660576Skrisstatic OpCodes 27757429Smarkmparse_token(const char *cp, const char *filename, int linenum) 27857429Smarkm{ 27976262Sgreen u_int i; 28057429Smarkm 28157429Smarkm for (i = 0; keywords[i].name; i++) 28257429Smarkm if (strcasecmp(cp, keywords[i].name) == 0) 28357429Smarkm return keywords[i].opcode; 28457429Smarkm 28576262Sgreen error("%s: line %d: Bad configuration option: %s", 28676262Sgreen filename, linenum, cp); 28757429Smarkm return oBadOption; 28857429Smarkm} 28957429Smarkm 29057429Smarkm/* 29157429Smarkm * Processes a single option line as used in the configuration files. This 29257429Smarkm * only sets those values that have not already been set. 29357429Smarkm */ 294113911Sdes#define WHITESPACE " \t\r\n" 29557429Smarkm 29657429Smarkmint 29757429Smarkmprocess_config_line(Options *options, const char *host, 29857429Smarkm char *line, const char *filename, int linenum, 29957429Smarkm int *activep) 30057429Smarkm{ 301147005Sdes char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; 30257429Smarkm int opcode, *intptr, value; 303113911Sdes size_t len; 304147005Sdes Forward fwd; 30557429Smarkm 306124211Sdes /* Strip trailing whitespace */ 307147005Sdes for (len = strlen(line) - 1; len > 0; len--) { 308124211Sdes if (strchr(WHITESPACE, line[len]) == NULL) 309124211Sdes break; 310124211Sdes line[len] = '\0'; 311124211Sdes } 312124211Sdes 31365674Skris s = line; 31465674Skris /* Get the keyword. (Each line is supposed to begin with a keyword). */ 31565674Skris keyword = strdelim(&s); 31665674Skris /* Ignore leading whitespace. */ 31765674Skris if (*keyword == '\0') 31865674Skris keyword = strdelim(&s); 31976262Sgreen if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 32057429Smarkm return 0; 32157429Smarkm 32265674Skris opcode = parse_token(keyword, filename, linenum); 32357429Smarkm 32457429Smarkm switch (opcode) { 32557429Smarkm case oBadOption: 32657429Smarkm /* don't panic, but count bad options */ 32757429Smarkm return -1; 32857429Smarkm /* NOTREACHED */ 329124211Sdes case oConnectTimeout: 330124211Sdes intptr = &options->connection_timeout; 331126277Sdesparse_time: 332124211Sdes arg = strdelim(&s); 333124211Sdes if (!arg || *arg == '\0') 334124211Sdes fatal("%s line %d: missing time value.", 335124211Sdes filename, linenum); 336124211Sdes if ((value = convtime(arg)) == -1) 337124211Sdes fatal("%s line %d: invalid time value.", 338124211Sdes filename, linenum); 339124211Sdes if (*intptr == -1) 340124211Sdes *intptr = value; 341124211Sdes break; 342124211Sdes 34357429Smarkm case oForwardAgent: 34457429Smarkm intptr = &options->forward_agent; 34557429Smarkmparse_flag: 34665674Skris arg = strdelim(&s); 34765674Skris if (!arg || *arg == '\0') 34857429Smarkm fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 34957429Smarkm value = 0; /* To avoid compiler warning... */ 35065674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 35157429Smarkm value = 1; 35265674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 35357429Smarkm value = 0; 35457429Smarkm else 35557429Smarkm fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 35657429Smarkm if (*activep && *intptr == -1) 35757429Smarkm *intptr = value; 35857429Smarkm break; 35957429Smarkm 36057429Smarkm case oForwardX11: 36157429Smarkm intptr = &options->forward_x11; 36257429Smarkm goto parse_flag; 36357429Smarkm 364126277Sdes case oForwardX11Trusted: 365126277Sdes intptr = &options->forward_x11_trusted; 366126277Sdes goto parse_flag; 367126277Sdes 36857429Smarkm case oGatewayPorts: 36957429Smarkm intptr = &options->gateway_ports; 37057429Smarkm goto parse_flag; 37157429Smarkm 37257429Smarkm case oUsePrivilegedPort: 37357429Smarkm intptr = &options->use_privileged_port; 37457429Smarkm goto parse_flag; 37557429Smarkm 37657429Smarkm case oPasswordAuthentication: 37757429Smarkm intptr = &options->password_authentication; 37857429Smarkm goto parse_flag; 37957429Smarkm 38069591Sgreen case oKbdInteractiveAuthentication: 38169591Sgreen intptr = &options->kbd_interactive_authentication; 38269591Sgreen goto parse_flag; 38369591Sgreen 38469591Sgreen case oKbdInteractiveDevices: 38569591Sgreen charptr = &options->kbd_interactive_devices; 38669591Sgreen goto parse_string; 38769591Sgreen 38876262Sgreen case oPubkeyAuthentication: 38976262Sgreen intptr = &options->pubkey_authentication; 39060576Skris goto parse_flag; 39160576Skris 39257429Smarkm case oRSAAuthentication: 39357429Smarkm intptr = &options->rsa_authentication; 39457429Smarkm goto parse_flag; 39557429Smarkm 39657429Smarkm case oRhostsRSAAuthentication: 39757429Smarkm intptr = &options->rhosts_rsa_authentication; 39857429Smarkm goto parse_flag; 39957429Smarkm 40076262Sgreen case oHostbasedAuthentication: 40176262Sgreen intptr = &options->hostbased_authentication; 40257429Smarkm goto parse_flag; 40357429Smarkm 40492559Sdes case oChallengeResponseAuthentication: 40592559Sdes intptr = &options->challenge_response_authentication; 40692559Sdes goto parse_flag; 407124211Sdes 408124211Sdes case oGssAuthentication: 409124211Sdes intptr = &options->gss_authentication; 41057429Smarkm goto parse_flag; 411124211Sdes 412124211Sdes case oGssDelegateCreds: 413124211Sdes intptr = &options->gss_deleg_creds; 41476262Sgreen goto parse_flag; 415124211Sdes 41657429Smarkm case oBatchMode: 41757429Smarkm intptr = &options->batch_mode; 41857429Smarkm goto parse_flag; 41957429Smarkm 42057429Smarkm case oCheckHostIP: 42157429Smarkm intptr = &options->check_host_ip; 42257429Smarkm goto parse_flag; 42357429Smarkm 424124211Sdes case oVerifyHostKeyDNS: 425124211Sdes intptr = &options->verify_host_key_dns; 426126277Sdes goto parse_yesnoask; 427124211Sdes 42857429Smarkm case oStrictHostKeyChecking: 42957429Smarkm intptr = &options->strict_host_key_checking; 430126277Sdesparse_yesnoask: 43165674Skris arg = strdelim(&s); 43265674Skris if (!arg || *arg == '\0') 43376262Sgreen fatal("%.200s line %d: Missing yes/no/ask argument.", 43492559Sdes filename, linenum); 43557429Smarkm value = 0; /* To avoid compiler warning... */ 43665674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 43757429Smarkm value = 1; 43865674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 43957429Smarkm value = 0; 44065674Skris else if (strcmp(arg, "ask") == 0) 44157429Smarkm value = 2; 44257429Smarkm else 44357429Smarkm fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 44457429Smarkm if (*activep && *intptr == -1) 44557429Smarkm *intptr = value; 44657429Smarkm break; 44757429Smarkm 44857429Smarkm case oCompression: 44957429Smarkm intptr = &options->compression; 45057429Smarkm goto parse_flag; 45157429Smarkm 452126277Sdes case oTCPKeepAlive: 453126277Sdes intptr = &options->tcp_keep_alive; 45457429Smarkm goto parse_flag; 45557429Smarkm 45692559Sdes case oNoHostAuthenticationForLocalhost: 45792559Sdes intptr = &options->no_host_authentication_for_localhost; 45892559Sdes goto parse_flag; 45992559Sdes 46057429Smarkm case oNumberOfPasswordPrompts: 46157429Smarkm intptr = &options->number_of_password_prompts; 46257429Smarkm goto parse_int; 46357429Smarkm 46457429Smarkm case oCompressionLevel: 46557429Smarkm intptr = &options->compression_level; 46657429Smarkm goto parse_int; 46757429Smarkm 468124211Sdes case oRekeyLimit: 469124211Sdes intptr = &options->rekey_limit; 470124211Sdes arg = strdelim(&s); 471124211Sdes if (!arg || *arg == '\0') 472124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 473124211Sdes if (arg[0] < '0' || arg[0] > '9') 474124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 475124211Sdes value = strtol(arg, &endofnumber, 10); 476124211Sdes if (arg == endofnumber) 477124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 478124211Sdes switch (toupper(*endofnumber)) { 479124211Sdes case 'K': 480124211Sdes value *= 1<<10; 481124211Sdes break; 482124211Sdes case 'M': 483124211Sdes value *= 1<<20; 484124211Sdes break; 485124211Sdes case 'G': 486124211Sdes value *= 1<<30; 487124211Sdes break; 488124211Sdes } 489124211Sdes if (*activep && *intptr == -1) 490124211Sdes *intptr = value; 491124211Sdes break; 492124211Sdes 49357429Smarkm case oIdentityFile: 49465674Skris arg = strdelim(&s); 49565674Skris if (!arg || *arg == '\0') 49657429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 49757429Smarkm if (*activep) { 49876262Sgreen intptr = &options->num_identity_files; 49960576Skris if (*intptr >= SSH_MAX_IDENTITY_FILES) 50057429Smarkm fatal("%.200s line %d: Too many identity files specified (max %d).", 50192559Sdes filename, linenum, SSH_MAX_IDENTITY_FILES); 50276262Sgreen charptr = &options->identity_files[*intptr]; 50365674Skris *charptr = xstrdup(arg); 50460576Skris *intptr = *intptr + 1; 50557429Smarkm } 50657429Smarkm break; 50757429Smarkm 50865674Skris case oXAuthLocation: 50965674Skris charptr=&options->xauth_location; 51065674Skris goto parse_string; 51165674Skris 51257429Smarkm case oUser: 51357429Smarkm charptr = &options->user; 51457429Smarkmparse_string: 51565674Skris arg = strdelim(&s); 51665674Skris if (!arg || *arg == '\0') 51757429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 51857429Smarkm if (*activep && *charptr == NULL) 51965674Skris *charptr = xstrdup(arg); 52057429Smarkm break; 52157429Smarkm 52257429Smarkm case oGlobalKnownHostsFile: 52357429Smarkm charptr = &options->system_hostfile; 52457429Smarkm goto parse_string; 52557429Smarkm 52657429Smarkm case oUserKnownHostsFile: 52757429Smarkm charptr = &options->user_hostfile; 52857429Smarkm goto parse_string; 52957429Smarkm 53060576Skris case oGlobalKnownHostsFile2: 53160576Skris charptr = &options->system_hostfile2; 53260576Skris goto parse_string; 53360576Skris 53460576Skris case oUserKnownHostsFile2: 53560576Skris charptr = &options->user_hostfile2; 53660576Skris goto parse_string; 53760576Skris 53857429Smarkm case oHostName: 53957429Smarkm charptr = &options->hostname; 54057429Smarkm goto parse_string; 54157429Smarkm 54276262Sgreen case oHostKeyAlias: 54376262Sgreen charptr = &options->host_key_alias; 54476262Sgreen goto parse_string; 54576262Sgreen 54676262Sgreen case oPreferredAuthentications: 54776262Sgreen charptr = &options->preferred_authentications; 54876262Sgreen goto parse_string; 54976262Sgreen 55092559Sdes case oBindAddress: 55192559Sdes charptr = &options->bind_address; 55292559Sdes goto parse_string; 55392559Sdes 55492559Sdes case oSmartcardDevice: 55592559Sdes charptr = &options->smartcard_device; 55692559Sdes goto parse_string; 55792559Sdes 55857429Smarkm case oProxyCommand: 559124211Sdes if (s == NULL) 560124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 56157429Smarkm charptr = &options->proxy_command; 562113911Sdes len = strspn(s, WHITESPACE "="); 56357429Smarkm if (*activep && *charptr == NULL) 564113911Sdes *charptr = xstrdup(s + len); 56557429Smarkm return 0; 56657429Smarkm 56757429Smarkm case oPort: 56857429Smarkm intptr = &options->port; 56957429Smarkmparse_int: 57065674Skris arg = strdelim(&s); 57165674Skris if (!arg || *arg == '\0') 57257429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 57365674Skris if (arg[0] < '0' || arg[0] > '9') 57457429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 57557429Smarkm 57657429Smarkm /* Octal, decimal, or hex format? */ 57765674Skris value = strtol(arg, &endofnumber, 0); 57865674Skris if (arg == endofnumber) 57957429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 58057429Smarkm if (*activep && *intptr == -1) 58157429Smarkm *intptr = value; 58257429Smarkm break; 58357429Smarkm 58457429Smarkm case oConnectionAttempts: 58557429Smarkm intptr = &options->connection_attempts; 58657429Smarkm goto parse_int; 58757429Smarkm 58857429Smarkm case oCipher: 58957429Smarkm intptr = &options->cipher; 59065674Skris arg = strdelim(&s); 59165674Skris if (!arg || *arg == '\0') 59261203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 59365674Skris value = cipher_number(arg); 59457429Smarkm if (value == -1) 59557429Smarkm fatal("%.200s line %d: Bad cipher '%s'.", 59692559Sdes filename, linenum, arg ? arg : "<NONE>"); 59757429Smarkm if (*activep && *intptr == -1) 59857429Smarkm *intptr = value; 59957429Smarkm break; 60057429Smarkm 60160576Skris case oCiphers: 60265674Skris arg = strdelim(&s); 60365674Skris if (!arg || *arg == '\0') 60461203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 60565674Skris if (!ciphers_valid(arg)) 60660576Skris fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 60792559Sdes filename, linenum, arg ? arg : "<NONE>"); 60860576Skris if (*activep && options->ciphers == NULL) 60965674Skris options->ciphers = xstrdup(arg); 61060576Skris break; 61160576Skris 61276262Sgreen case oMacs: 61376262Sgreen arg = strdelim(&s); 61476262Sgreen if (!arg || *arg == '\0') 61576262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 61676262Sgreen if (!mac_valid(arg)) 61776262Sgreen fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 61892559Sdes filename, linenum, arg ? arg : "<NONE>"); 61976262Sgreen if (*activep && options->macs == NULL) 62076262Sgreen options->macs = xstrdup(arg); 62176262Sgreen break; 62276262Sgreen 62376262Sgreen case oHostKeyAlgorithms: 62476262Sgreen arg = strdelim(&s); 62576262Sgreen if (!arg || *arg == '\0') 62676262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 62776262Sgreen if (!key_names_valid2(arg)) 62876262Sgreen fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 62992559Sdes filename, linenum, arg ? arg : "<NONE>"); 63076262Sgreen if (*activep && options->hostkeyalgorithms == NULL) 63176262Sgreen options->hostkeyalgorithms = xstrdup(arg); 63276262Sgreen break; 63376262Sgreen 63460576Skris case oProtocol: 63560576Skris intptr = &options->protocol; 63665674Skris arg = strdelim(&s); 63765674Skris if (!arg || *arg == '\0') 63861203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 63965674Skris value = proto_spec(arg); 64060576Skris if (value == SSH_PROTO_UNKNOWN) 64160576Skris fatal("%.200s line %d: Bad protocol spec '%s'.", 64292559Sdes filename, linenum, arg ? arg : "<NONE>"); 64360576Skris if (*activep && *intptr == SSH_PROTO_UNKNOWN) 64460576Skris *intptr = value; 64560576Skris break; 64660576Skris 64757429Smarkm case oLogLevel: 64857429Smarkm intptr = (int *) &options->log_level; 64965674Skris arg = strdelim(&s); 65065674Skris value = log_level_number(arg); 65192559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 65276262Sgreen fatal("%.200s line %d: unsupported log level '%s'", 65392559Sdes filename, linenum, arg ? arg : "<NONE>"); 65492559Sdes if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) 65557429Smarkm *intptr = (LogLevel) value; 65657429Smarkm break; 65757429Smarkm 65892559Sdes case oLocalForward: 65957429Smarkm case oRemoteForward: 66065674Skris arg = strdelim(&s); 661147005Sdes if (arg == NULL || *arg == '\0') 66292559Sdes fatal("%.200s line %d: Missing port argument.", 66392559Sdes filename, linenum); 664147005Sdes arg2 = strdelim(&s); 665147005Sdes if (arg2 == NULL || *arg2 == '\0') 666147005Sdes fatal("%.200s line %d: Missing target argument.", 66792559Sdes filename, linenum); 668147005Sdes 669147005Sdes /* construct a string for parse_forward */ 670147005Sdes snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 671147005Sdes 672147005Sdes if (parse_forward(&fwd, fwdarg) == 0) 67392559Sdes fatal("%.200s line %d: Bad forwarding specification.", 67492559Sdes filename, linenum); 675147005Sdes 67692559Sdes if (*activep) { 67792559Sdes if (opcode == oLocalForward) 678147005Sdes add_local_forward(options, &fwd); 67992559Sdes else if (opcode == oRemoteForward) 680147005Sdes add_remote_forward(options, &fwd); 68192559Sdes } 68257429Smarkm break; 68357429Smarkm 68476262Sgreen case oDynamicForward: 68576262Sgreen arg = strdelim(&s); 68676262Sgreen if (!arg || *arg == '\0') 68776262Sgreen fatal("%.200s line %d: Missing port argument.", 68876262Sgreen filename, linenum); 689147005Sdes memset(&fwd, '\0', sizeof(fwd)); 690147005Sdes fwd.connect_host = "socks"; 691147005Sdes fwd.listen_host = hpdelim(&arg); 692147005Sdes if (fwd.listen_host == NULL || 693147005Sdes strlen(fwd.listen_host) >= NI_MAXHOST) 694147005Sdes fatal("%.200s line %d: Bad forwarding specification.", 695147005Sdes filename, linenum); 696147005Sdes if (arg) { 697147005Sdes fwd.listen_port = a2port(arg); 698147005Sdes fwd.listen_host = cleanhostname(fwd.listen_host); 699147005Sdes } else { 700147005Sdes fwd.listen_port = a2port(fwd.listen_host); 701149753Sdes fwd.listen_host = NULL; 702147005Sdes } 703147005Sdes if (fwd.listen_port == 0) 70476262Sgreen fatal("%.200s line %d: Badly formatted port number.", 70576262Sgreen filename, linenum); 70692559Sdes if (*activep) 707147005Sdes add_local_forward(options, &fwd); 70876262Sgreen break; 70976262Sgreen 71092559Sdes case oClearAllForwardings: 71192559Sdes intptr = &options->clear_forwardings; 71292559Sdes goto parse_flag; 71392559Sdes 71457429Smarkm case oHost: 71557429Smarkm *activep = 0; 71665674Skris while ((arg = strdelim(&s)) != NULL && *arg != '\0') 71765674Skris if (match_pattern(host, arg)) { 71865674Skris debug("Applying options for %.100s", arg); 71957429Smarkm *activep = 1; 72057429Smarkm break; 72157429Smarkm } 72265674Skris /* Avoid garbage check below, as strdelim is done. */ 72357429Smarkm return 0; 72457429Smarkm 72557429Smarkm case oEscapeChar: 72657429Smarkm intptr = &options->escape_char; 72765674Skris arg = strdelim(&s); 72865674Skris if (!arg || *arg == '\0') 72957429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 73065674Skris if (arg[0] == '^' && arg[2] == 0 && 73176262Sgreen (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 73276262Sgreen value = (u_char) arg[1] & 31; 73365674Skris else if (strlen(arg) == 1) 73476262Sgreen value = (u_char) arg[0]; 73565674Skris else if (strcmp(arg, "none") == 0) 73692559Sdes value = SSH_ESCAPECHAR_NONE; 73757429Smarkm else { 73857429Smarkm fatal("%.200s line %d: Bad escape character.", 73992559Sdes filename, linenum); 74057429Smarkm /* NOTREACHED */ 74157429Smarkm value = 0; /* Avoid compiler warning. */ 74257429Smarkm } 74357429Smarkm if (*activep && *intptr == -1) 74457429Smarkm *intptr = value; 74557429Smarkm break; 74657429Smarkm 747124211Sdes case oAddressFamily: 748124211Sdes arg = strdelim(&s); 749149753Sdes if (!arg || *arg == '\0') 750149753Sdes fatal("%s line %d: missing address family.", 751149753Sdes filename, linenum); 752124211Sdes intptr = &options->address_family; 753124211Sdes if (strcasecmp(arg, "inet") == 0) 754124211Sdes value = AF_INET; 755124211Sdes else if (strcasecmp(arg, "inet6") == 0) 756124211Sdes value = AF_INET6; 757124211Sdes else if (strcasecmp(arg, "any") == 0) 758124211Sdes value = AF_UNSPEC; 759124211Sdes else 760124211Sdes fatal("Unsupported AddressFamily \"%s\"", arg); 761124211Sdes if (*activep && *intptr == -1) 762124211Sdes *intptr = value; 763124211Sdes break; 764124211Sdes 765113911Sdes case oEnableSSHKeysign: 766113911Sdes intptr = &options->enable_ssh_keysign; 767113911Sdes goto parse_flag; 768113911Sdes 769128460Sdes case oIdentitiesOnly: 770128460Sdes intptr = &options->identities_only; 771128460Sdes goto parse_flag; 772128460Sdes 773126277Sdes case oServerAliveInterval: 774126277Sdes intptr = &options->server_alive_interval; 775126277Sdes goto parse_time; 776126277Sdes 777126277Sdes case oServerAliveCountMax: 778126277Sdes intptr = &options->server_alive_count_max; 779126277Sdes goto parse_int; 780126277Sdes 781137019Sdes case oSendEnv: 782137019Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 783137019Sdes if (strchr(arg, '=') != NULL) 784137019Sdes fatal("%s line %d: Invalid environment name.", 785137019Sdes filename, linenum); 786147005Sdes if (!*activep) 787147005Sdes continue; 788137019Sdes if (options->num_send_env >= MAX_SEND_ENV) 789137019Sdes fatal("%s line %d: too many send env.", 790137019Sdes filename, linenum); 791137019Sdes options->send_env[options->num_send_env++] = 792137019Sdes xstrdup(arg); 793137019Sdes } 794137019Sdes break; 795137019Sdes 796137019Sdes case oControlPath: 797137019Sdes charptr = &options->control_path; 798137019Sdes goto parse_string; 799137019Sdes 800137019Sdes case oControlMaster: 801137019Sdes intptr = &options->control_master; 802149753Sdes arg = strdelim(&s); 803149753Sdes if (!arg || *arg == '\0') 804149753Sdes fatal("%.200s line %d: Missing ControlMaster argument.", 805149753Sdes filename, linenum); 806149753Sdes value = 0; /* To avoid compiler warning... */ 807149753Sdes if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 808149753Sdes value = SSHCTL_MASTER_YES; 809149753Sdes else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 810149753Sdes value = SSHCTL_MASTER_NO; 811149753Sdes else if (strcmp(arg, "auto") == 0) 812149753Sdes value = SSHCTL_MASTER_AUTO; 813149753Sdes else if (strcmp(arg, "ask") == 0) 814149753Sdes value = SSHCTL_MASTER_ASK; 815149753Sdes else if (strcmp(arg, "autoask") == 0) 816149753Sdes value = SSHCTL_MASTER_AUTO_ASK; 817149753Sdes else 818149753Sdes fatal("%.200s line %d: Bad ControlMaster argument.", 819149753Sdes filename, linenum); 820149753Sdes if (*activep && *intptr == -1) 821149753Sdes *intptr = value; 822149753Sdes break; 823137019Sdes 824147005Sdes case oHashKnownHosts: 825147005Sdes intptr = &options->hash_known_hosts; 826147005Sdes goto parse_flag; 827147005Sdes 82899048Sdes case oVersionAddendum: 82999048Sdes ssh_version_set_addendum(strtok(s, "\n")); 83099048Sdes do { 83199048Sdes arg = strdelim(&s); 83299048Sdes } while (arg != NULL && *arg != '\0'); 83399048Sdes break; 83499048Sdes 83598684Sdes case oDeprecated: 83698684Sdes debug("%s line %d: Deprecated option \"%s\"", 83798684Sdes filename, linenum, keyword); 83898684Sdes return 0; 83998684Sdes 840124211Sdes case oUnsupported: 841124211Sdes error("%s line %d: Unsupported option \"%s\"", 842124211Sdes filename, linenum, keyword); 843124211Sdes return 0; 844124211Sdes 84557429Smarkm default: 84657429Smarkm fatal("process_config_line: Unimplemented opcode %d", opcode); 84757429Smarkm } 84857429Smarkm 84957429Smarkm /* Check that there is no garbage at end of line. */ 85076262Sgreen if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 85165674Skris fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 852149753Sdes filename, linenum, arg); 85365674Skris } 85457429Smarkm return 0; 85557429Smarkm} 85657429Smarkm 85757429Smarkm 85857429Smarkm/* 85957429Smarkm * Reads the config file and modifies the options accordingly. Options 86057429Smarkm * should already be initialized before this call. This never returns if 86192559Sdes * there is an error. If the file does not exist, this returns 0. 86257429Smarkm */ 86357429Smarkm 86492559Sdesint 865137019Sdesread_config_file(const char *filename, const char *host, Options *options, 866137019Sdes int checkperm) 86757429Smarkm{ 86857429Smarkm FILE *f; 86957429Smarkm char line[1024]; 87057429Smarkm int active, linenum; 87157429Smarkm int bad_options = 0; 87257429Smarkm 87357429Smarkm /* Open the file. */ 874137019Sdes if ((f = fopen(filename, "r")) == NULL) 87592559Sdes return 0; 87657429Smarkm 877137019Sdes if (checkperm) { 878137019Sdes struct stat sb; 879137019Sdes 880137019Sdes if (fstat(fileno(f), &sb) == -1) 881137019Sdes fatal("fstat %s: %s", filename, strerror(errno)); 882137019Sdes if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 883137019Sdes (sb.st_mode & 022) != 0)) 884137019Sdes fatal("Bad owner or permissions on %s", filename); 885137019Sdes } 886137019Sdes 88757429Smarkm debug("Reading configuration data %.200s", filename); 88857429Smarkm 88957429Smarkm /* 89057429Smarkm * Mark that we are now processing the options. This flag is turned 89157429Smarkm * on/off by Host specifications. 89257429Smarkm */ 89357429Smarkm active = 1; 89457429Smarkm linenum = 0; 89557429Smarkm while (fgets(line, sizeof(line), f)) { 89657429Smarkm /* Update line number counter. */ 89757429Smarkm linenum++; 89857429Smarkm if (process_config_line(options, host, line, filename, linenum, &active) != 0) 89957429Smarkm bad_options++; 90057429Smarkm } 90157429Smarkm fclose(f); 90257429Smarkm if (bad_options > 0) 90376262Sgreen fatal("%s: terminating, %d bad configuration options", 90492559Sdes filename, bad_options); 90592559Sdes return 1; 90657429Smarkm} 90757429Smarkm 90857429Smarkm/* 90957429Smarkm * Initializes options to special values that indicate that they have not yet 91057429Smarkm * been set. Read_config_file will only set options with this value. Options 91157429Smarkm * are processed in the following order: command line, user config file, 91257429Smarkm * system config file. Last, fill_default_options is called. 91357429Smarkm */ 91457429Smarkm 91560576Skrisvoid 91657429Smarkminitialize_options(Options * options) 91757429Smarkm{ 91857429Smarkm memset(options, 'X', sizeof(*options)); 91957429Smarkm options->forward_agent = -1; 92057429Smarkm options->forward_x11 = -1; 921126277Sdes options->forward_x11_trusted = -1; 92265674Skris options->xauth_location = NULL; 92357429Smarkm options->gateway_ports = -1; 92457429Smarkm options->use_privileged_port = -1; 92557429Smarkm options->rsa_authentication = -1; 92676262Sgreen options->pubkey_authentication = -1; 92792559Sdes options->challenge_response_authentication = -1; 928124211Sdes options->gss_authentication = -1; 929124211Sdes options->gss_deleg_creds = -1; 93057429Smarkm options->password_authentication = -1; 93169591Sgreen options->kbd_interactive_authentication = -1; 93269591Sgreen options->kbd_interactive_devices = NULL; 93357429Smarkm options->rhosts_rsa_authentication = -1; 93476262Sgreen options->hostbased_authentication = -1; 93557429Smarkm options->batch_mode = -1; 93657429Smarkm options->check_host_ip = -1; 93757429Smarkm options->strict_host_key_checking = -1; 93857429Smarkm options->compression = -1; 939126277Sdes options->tcp_keep_alive = -1; 94057429Smarkm options->compression_level = -1; 94157429Smarkm options->port = -1; 942124211Sdes options->address_family = -1; 94357429Smarkm options->connection_attempts = -1; 944124211Sdes options->connection_timeout = -1; 94557429Smarkm options->number_of_password_prompts = -1; 94657429Smarkm options->cipher = -1; 94760576Skris options->ciphers = NULL; 94876262Sgreen options->macs = NULL; 94976262Sgreen options->hostkeyalgorithms = NULL; 95060576Skris options->protocol = SSH_PROTO_UNKNOWN; 95157429Smarkm options->num_identity_files = 0; 95257429Smarkm options->hostname = NULL; 95376262Sgreen options->host_key_alias = NULL; 95457429Smarkm options->proxy_command = NULL; 95557429Smarkm options->user = NULL; 95657429Smarkm options->escape_char = -1; 95757429Smarkm options->system_hostfile = NULL; 95857429Smarkm options->user_hostfile = NULL; 95960576Skris options->system_hostfile2 = NULL; 96060576Skris options->user_hostfile2 = NULL; 96157429Smarkm options->num_local_forwards = 0; 96257429Smarkm options->num_remote_forwards = 0; 96392559Sdes options->clear_forwardings = -1; 96492559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 96576262Sgreen options->preferred_authentications = NULL; 96692559Sdes options->bind_address = NULL; 96792559Sdes options->smartcard_device = NULL; 968113911Sdes options->enable_ssh_keysign = - 1; 96992559Sdes options->no_host_authentication_for_localhost = - 1; 970128460Sdes options->identities_only = - 1; 971124211Sdes options->rekey_limit = - 1; 972124211Sdes options->verify_host_key_dns = -1; 973126277Sdes options->server_alive_interval = -1; 974126277Sdes options->server_alive_count_max = -1; 975137019Sdes options->num_send_env = 0; 976137019Sdes options->control_path = NULL; 977137019Sdes options->control_master = -1; 978147005Sdes options->hash_known_hosts = -1; 97957429Smarkm} 98057429Smarkm 98157429Smarkm/* 98257429Smarkm * Called after processing other sources of option data, this fills those 98357429Smarkm * options for which no value has been specified with their default values. 98457429Smarkm */ 98557429Smarkm 98660576Skrisvoid 98757429Smarkmfill_default_options(Options * options) 98857429Smarkm{ 98976262Sgreen int len; 99076262Sgreen 99157429Smarkm if (options->forward_agent == -1) 99261203Skris options->forward_agent = 0; 99357429Smarkm if (options->forward_x11 == -1) 99457708Sgreen options->forward_x11 = 0; 995126277Sdes if (options->forward_x11_trusted == -1) 996126277Sdes options->forward_x11_trusted = 0; 99765674Skris if (options->xauth_location == NULL) 99892559Sdes options->xauth_location = _PATH_XAUTH; 99957429Smarkm if (options->gateway_ports == -1) 100057429Smarkm options->gateway_ports = 0; 100157429Smarkm if (options->use_privileged_port == -1) 100276262Sgreen options->use_privileged_port = 0; 100357429Smarkm if (options->rsa_authentication == -1) 100457429Smarkm options->rsa_authentication = 1; 100576262Sgreen if (options->pubkey_authentication == -1) 100676262Sgreen options->pubkey_authentication = 1; 100792559Sdes if (options->challenge_response_authentication == -1) 100892559Sdes options->challenge_response_authentication = 1; 1009124211Sdes if (options->gss_authentication == -1) 1010126277Sdes options->gss_authentication = 0; 1011124211Sdes if (options->gss_deleg_creds == -1) 1012124211Sdes options->gss_deleg_creds = 0; 101357429Smarkm if (options->password_authentication == -1) 101457429Smarkm options->password_authentication = 1; 101569591Sgreen if (options->kbd_interactive_authentication == -1) 101676262Sgreen options->kbd_interactive_authentication = 1; 101757429Smarkm if (options->rhosts_rsa_authentication == -1) 101898684Sdes options->rhosts_rsa_authentication = 0; 101976262Sgreen if (options->hostbased_authentication == -1) 102076262Sgreen options->hostbased_authentication = 0; 102157429Smarkm if (options->batch_mode == -1) 102257429Smarkm options->batch_mode = 0; 102357429Smarkm if (options->check_host_ip == -1) 102499048Sdes options->check_host_ip = 0; 102557429Smarkm if (options->strict_host_key_checking == -1) 102657429Smarkm options->strict_host_key_checking = 2; /* 2 is default */ 102757429Smarkm if (options->compression == -1) 102857429Smarkm options->compression = 0; 1029126277Sdes if (options->tcp_keep_alive == -1) 1030126277Sdes options->tcp_keep_alive = 1; 103157429Smarkm if (options->compression_level == -1) 103257429Smarkm options->compression_level = 6; 103357429Smarkm if (options->port == -1) 103457429Smarkm options->port = 0; /* Filled in ssh_connect. */ 1035124211Sdes if (options->address_family == -1) 1036124211Sdes options->address_family = AF_UNSPEC; 103757429Smarkm if (options->connection_attempts == -1) 103892559Sdes options->connection_attempts = 1; 103957429Smarkm if (options->number_of_password_prompts == -1) 104057429Smarkm options->number_of_password_prompts = 3; 104157429Smarkm /* Selected in ssh_login(). */ 104257429Smarkm if (options->cipher == -1) 104357429Smarkm options->cipher = SSH_CIPHER_NOT_SET; 104460576Skris /* options->ciphers, default set in myproposals.h */ 104576262Sgreen /* options->macs, default set in myproposals.h */ 104676262Sgreen /* options->hostkeyalgorithms, default set in myproposals.h */ 104760576Skris if (options->protocol == SSH_PROTO_UNKNOWN) 104876262Sgreen options->protocol = SSH_PROTO_1|SSH_PROTO_2; 104957429Smarkm if (options->num_identity_files == 0) { 105076262Sgreen if (options->protocol & SSH_PROTO_1) { 105176262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 105276262Sgreen options->identity_files[options->num_identity_files] = 105376262Sgreen xmalloc(len); 105476262Sgreen snprintf(options->identity_files[options->num_identity_files++], 105576262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 105676262Sgreen } 105776262Sgreen if (options->protocol & SSH_PROTO_2) { 105876262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 105976262Sgreen options->identity_files[options->num_identity_files] = 106076262Sgreen xmalloc(len); 106176262Sgreen snprintf(options->identity_files[options->num_identity_files++], 106276262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 106376262Sgreen 106476262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 106576262Sgreen options->identity_files[options->num_identity_files] = 106676262Sgreen xmalloc(len); 106776262Sgreen snprintf(options->identity_files[options->num_identity_files++], 106876262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 106976262Sgreen } 107057429Smarkm } 107157429Smarkm if (options->escape_char == -1) 107257429Smarkm options->escape_char = '~'; 107357429Smarkm if (options->system_hostfile == NULL) 107476262Sgreen options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 107557429Smarkm if (options->user_hostfile == NULL) 107676262Sgreen options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 107760576Skris if (options->system_hostfile2 == NULL) 107876262Sgreen options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 107960576Skris if (options->user_hostfile2 == NULL) 108076262Sgreen options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 108192559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 108257429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 108392559Sdes if (options->clear_forwardings == 1) 108492559Sdes clear_forwardings(options); 108592559Sdes if (options->no_host_authentication_for_localhost == - 1) 108692559Sdes options->no_host_authentication_for_localhost = 0; 1087128460Sdes if (options->identities_only == -1) 1088128460Sdes options->identities_only = 0; 1089113911Sdes if (options->enable_ssh_keysign == -1) 1090113911Sdes options->enable_ssh_keysign = 0; 1091124211Sdes if (options->rekey_limit == -1) 1092124211Sdes options->rekey_limit = 0; 1093124211Sdes if (options->verify_host_key_dns == -1) 1094124211Sdes options->verify_host_key_dns = 0; 1095126277Sdes if (options->server_alive_interval == -1) 1096126277Sdes options->server_alive_interval = 0; 1097126277Sdes if (options->server_alive_count_max == -1) 1098126277Sdes options->server_alive_count_max = 3; 1099137019Sdes if (options->control_master == -1) 1100137019Sdes options->control_master = 0; 1101147005Sdes if (options->hash_known_hosts == -1) 1102147005Sdes options->hash_known_hosts = 0; 110357429Smarkm /* options->proxy_command should not be set by default */ 110457429Smarkm /* options->user will be set in the main program if appropriate */ 110557429Smarkm /* options->hostname will be set in the main program if appropriate */ 110676262Sgreen /* options->host_key_alias should not be set by default */ 110776262Sgreen /* options->preferred_authentications will be set in ssh */ 110857429Smarkm} 1109147005Sdes 1110147005Sdes/* 1111147005Sdes * parse_forward 1112147005Sdes * parses a string containing a port forwarding specification of the form: 1113147005Sdes * [listenhost:]listenport:connecthost:connectport 1114147005Sdes * returns number of arguments parsed or zero on error 1115147005Sdes */ 1116147005Sdesint 1117147005Sdesparse_forward(Forward *fwd, const char *fwdspec) 1118147005Sdes{ 1119147005Sdes int i; 1120147005Sdes char *p, *cp, *fwdarg[4]; 1121147005Sdes 1122147005Sdes memset(fwd, '\0', sizeof(*fwd)); 1123147005Sdes 1124147005Sdes cp = p = xstrdup(fwdspec); 1125147005Sdes 1126147005Sdes /* skip leading spaces */ 1127147005Sdes while (*cp && isspace(*cp)) 1128147005Sdes cp++; 1129147005Sdes 1130147005Sdes for (i = 0; i < 4; ++i) 1131147005Sdes if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1132147005Sdes break; 1133147005Sdes 1134147005Sdes /* Check for trailing garbage in 4-arg case*/ 1135147005Sdes if (cp != NULL) 1136147005Sdes i = 0; /* failure */ 1137147005Sdes 1138147005Sdes switch (i) { 1139147005Sdes case 3: 1140147005Sdes fwd->listen_host = NULL; 1141147005Sdes fwd->listen_port = a2port(fwdarg[0]); 1142147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1143147005Sdes fwd->connect_port = a2port(fwdarg[2]); 1144147005Sdes break; 1145147005Sdes 1146147005Sdes case 4: 1147147005Sdes fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1148147005Sdes fwd->listen_port = a2port(fwdarg[1]); 1149147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1150147005Sdes fwd->connect_port = a2port(fwdarg[3]); 1151147005Sdes break; 1152147005Sdes default: 1153147005Sdes i = 0; /* failure */ 1154147005Sdes } 1155147005Sdes 1156147005Sdes xfree(p); 1157147005Sdes 1158147005Sdes if (fwd->listen_port == 0 && fwd->connect_port == 0) 1159147005Sdes goto fail_free; 1160147005Sdes 1161147005Sdes if (fwd->connect_host != NULL && 1162147005Sdes strlen(fwd->connect_host) >= NI_MAXHOST) 1163147005Sdes goto fail_free; 1164147005Sdes 1165147005Sdes return (i); 1166147005Sdes 1167147005Sdes fail_free: 1168147005Sdes if (fwd->connect_host != NULL) 1169147005Sdes xfree(fwd->connect_host); 1170147005Sdes if (fwd->listen_host != NULL) 1171147005Sdes xfree(fwd->listen_host); 1172147005Sdes return (0); 1173147005Sdes} 1174