1*f7167e0eSDag-Erling Smørgrav /* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */ 289986192SBrooks Davis /* $FreeBSD$ */ 3511b41d2SMark Murray /* 4511b41d2SMark Murray * Author: Tatu Ylonen <ylo@cs.hut.fi> 5511b41d2SMark Murray * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 6511b41d2SMark Murray * All rights reserved 7511b41d2SMark Murray * Functions for reading the configuration files. 8511b41d2SMark Murray * 9c2d3a559SKris Kennaway * As far as I am concerned, the code I have written for this software 10c2d3a559SKris Kennaway * can be used freely for any purpose. Any derived versions of this 11c2d3a559SKris Kennaway * software must be clearly marked as such, and if the derived work is 12c2d3a559SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 13c2d3a559SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 14511b41d2SMark Murray */ 15511b41d2SMark Murray 16511b41d2SMark Murray #include "includes.h" 17333ee039SDag-Erling Smørgrav __RCSID("$FreeBSD$"); 18511b41d2SMark Murray 19333ee039SDag-Erling Smørgrav #include <sys/types.h> 20333ee039SDag-Erling Smørgrav #include <sys/stat.h> 21333ee039SDag-Erling Smørgrav #include <sys/socket.h> 2203f6c5cdSDag-Erling Smørgrav #include <sys/sysctl.h> 23*f7167e0eSDag-Erling Smørgrav #include <sys/wait.h> 24333ee039SDag-Erling Smørgrav 25333ee039SDag-Erling Smørgrav #include <netinet/in.h> 264a421b63SDag-Erling Smørgrav #include <netinet/in_systm.h> 274a421b63SDag-Erling Smørgrav #include <netinet/ip.h> 28333ee039SDag-Erling Smørgrav 29333ee039SDag-Erling Smørgrav #include <ctype.h> 30333ee039SDag-Erling Smørgrav #include <errno.h> 31*f7167e0eSDag-Erling Smørgrav #include <fcntl.h> 32333ee039SDag-Erling Smørgrav #include <netdb.h> 33*f7167e0eSDag-Erling Smørgrav #ifdef HAVE_PATHS_H 34*f7167e0eSDag-Erling Smørgrav # include <paths.h> 35*f7167e0eSDag-Erling Smørgrav #endif 36*f7167e0eSDag-Erling Smørgrav #include <pwd.h> 37333ee039SDag-Erling Smørgrav #include <signal.h> 38333ee039SDag-Erling Smørgrav #include <stdarg.h> 39333ee039SDag-Erling Smørgrav #include <stdio.h> 40333ee039SDag-Erling Smørgrav #include <string.h> 41333ee039SDag-Erling Smørgrav #include <unistd.h> 42e4a9863fSDag-Erling Smørgrav #ifdef HAVE_UTIL_H 43e4a9863fSDag-Erling Smørgrav #include <util.h> 44e4a9863fSDag-Erling Smørgrav #endif 45333ee039SDag-Erling Smørgrav 46511b41d2SMark Murray #include "xmalloc.h" 47333ee039SDag-Erling Smørgrav #include "ssh.h" 48e8aafc91SKris Kennaway #include "compat.h" 49ca3176e7SBrian Feldman #include "cipher.h" 50ca3176e7SBrian Feldman #include "pathnames.h" 51ca3176e7SBrian Feldman #include "log.h" 52333ee039SDag-Erling Smørgrav #include "key.h" 53ca3176e7SBrian Feldman #include "readconf.h" 54ca3176e7SBrian Feldman #include "match.h" 55ca3176e7SBrian Feldman #include "misc.h" 56333ee039SDag-Erling Smørgrav #include "buffer.h" 57ca3176e7SBrian Feldman #include "kex.h" 58ca3176e7SBrian Feldman #include "mac.h" 59*f7167e0eSDag-Erling Smørgrav #include "uidswap.h" 60cce7d346SDag-Erling Smørgrav #include "version.h" 61511b41d2SMark Murray 62511b41d2SMark Murray /* Format of the configuration file: 63511b41d2SMark Murray 64511b41d2SMark Murray # Configuration data is parsed as follows: 65511b41d2SMark Murray # 1. command line options 66511b41d2SMark Murray # 2. user-specific file 67511b41d2SMark Murray # 3. system-wide file 68511b41d2SMark Murray # Any configuration value is only changed the first time it is set. 69511b41d2SMark Murray # Thus, host-specific definitions should be at the beginning of the 70511b41d2SMark Murray # configuration file, and defaults at the end. 71511b41d2SMark Murray 72511b41d2SMark Murray # Host-specific declarations. These may override anything above. A single 73511b41d2SMark Murray # host may match multiple declarations; these are processed in the order 74511b41d2SMark Murray # that they are given in. 75511b41d2SMark Murray 76511b41d2SMark Murray Host *.ngs.fi ngs.fi 7780628bacSDag-Erling Smørgrav User foo 78511b41d2SMark Murray 79511b41d2SMark Murray Host fake.com 80511b41d2SMark Murray HostName another.host.name.real.org 81511b41d2SMark Murray User blaah 82511b41d2SMark Murray Port 34289 83511b41d2SMark Murray ForwardX11 no 84511b41d2SMark Murray ForwardAgent no 85511b41d2SMark Murray 86511b41d2SMark Murray Host books.com 87511b41d2SMark Murray RemoteForward 9999 shadows.cs.hut.fi:9999 88511b41d2SMark Murray Cipher 3des 89511b41d2SMark Murray 90511b41d2SMark Murray Host fascist.blob.com 91511b41d2SMark Murray Port 23123 92511b41d2SMark Murray User tylonen 93511b41d2SMark Murray PasswordAuthentication no 94511b41d2SMark Murray 95511b41d2SMark Murray Host puukko.hut.fi 96511b41d2SMark Murray User t35124p 97511b41d2SMark Murray ProxyCommand ssh-proxy %h %p 98511b41d2SMark Murray 99511b41d2SMark Murray Host *.fr 10080628bacSDag-Erling Smørgrav PublicKeyAuthentication no 101511b41d2SMark Murray 102511b41d2SMark Murray Host *.su 103511b41d2SMark Murray Cipher none 104511b41d2SMark Murray PasswordAuthentication no 105511b41d2SMark Murray 106b74df5b2SDag-Erling Smørgrav Host vpn.fake.com 107b74df5b2SDag-Erling Smørgrav Tunnel yes 108b74df5b2SDag-Erling Smørgrav TunnelDevice 3 109b74df5b2SDag-Erling Smørgrav 110511b41d2SMark Murray # Defaults for various options 111511b41d2SMark Murray Host * 112511b41d2SMark Murray ForwardAgent no 113ca3176e7SBrian Feldman ForwardX11 no 114511b41d2SMark Murray PasswordAuthentication yes 115511b41d2SMark Murray RSAAuthentication yes 116511b41d2SMark Murray RhostsRSAAuthentication yes 117511b41d2SMark Murray StrictHostKeyChecking yes 1181ec0d754SDag-Erling Smørgrav TcpKeepAlive no 119511b41d2SMark Murray IdentityFile ~/.ssh/identity 120511b41d2SMark Murray Port 22 121511b41d2SMark Murray EscapeChar ~ 122511b41d2SMark Murray 123511b41d2SMark Murray */ 124511b41d2SMark Murray 125511b41d2SMark Murray /* Keyword tokens. */ 126511b41d2SMark Murray 127511b41d2SMark Murray typedef enum { 128511b41d2SMark Murray oBadOption, 129*f7167e0eSDag-Erling Smørgrav oHost, oMatch, 130e2f6069cSDag-Erling Smørgrav oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 131e2f6069cSDag-Erling Smørgrav oGatewayPorts, oExitOnForwardFailure, 13280628bacSDag-Erling Smørgrav oPasswordAuthentication, oRSAAuthentication, 133ca3176e7SBrian Feldman oChallengeResponseAuthentication, oXAuthLocation, 134511b41d2SMark Murray oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 135*f7167e0eSDag-Erling Smørgrav oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 136511b41d2SMark Murray oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 137511b41d2SMark Murray oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 1381ec0d754SDag-Erling Smørgrav oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 139ca3176e7SBrian Feldman oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 140ca3176e7SBrian Feldman oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 141ca3176e7SBrian Feldman oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 142ca3176e7SBrian Feldman oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 143b15c8340SDag-Erling Smørgrav oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, 1449e2cbe04SDag-Erling Smørgrav oClearAllForwardings, oNoHostAuthenticationForLocalhost, 145cf2b5f3bSDag-Erling Smørgrav oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 146cf2b5f3bSDag-Erling Smørgrav oAddressFamily, oGssAuthentication, oGssDelegateCreds, 1475962c0e9SDag-Erling Smørgrav oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 148e2f6069cSDag-Erling Smørgrav oSendEnv, oControlPath, oControlMaster, oControlPersist, 149e2f6069cSDag-Erling Smørgrav oHashKnownHosts, 150b74df5b2SDag-Erling Smørgrav oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 1517aee6ffeSDag-Erling Smørgrav oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 152*f7167e0eSDag-Erling Smørgrav oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 153*f7167e0eSDag-Erling Smørgrav oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 154*f7167e0eSDag-Erling Smørgrav oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 155e4a9863fSDag-Erling Smørgrav oIgnoredUnknownOption, 15689986192SBrooks Davis oHPNDisabled, oHPNBufferSize, oTcpRcvBufPoll, oTcpRcvBuf, 15789986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED 15889986192SBrooks Davis oNoneEnabled, oNoneSwitch, 15989986192SBrooks Davis #endif 160e4a9863fSDag-Erling Smørgrav oVersionAddendum, oDeprecated, oUnsupported 161511b41d2SMark Murray } OpCodes; 162511b41d2SMark Murray 163511b41d2SMark Murray /* Textual representations of the tokens. */ 164511b41d2SMark Murray 165511b41d2SMark Murray static struct { 166511b41d2SMark Murray const char *name; 167511b41d2SMark Murray OpCodes opcode; 168511b41d2SMark Murray } keywords[] = { 169511b41d2SMark Murray { "forwardagent", oForwardAgent }, 170511b41d2SMark Murray { "forwardx11", oForwardX11 }, 1711ec0d754SDag-Erling Smørgrav { "forwardx11trusted", oForwardX11Trusted }, 172e2f6069cSDag-Erling Smørgrav { "forwardx11timeout", oForwardX11Timeout }, 173333ee039SDag-Erling Smørgrav { "exitonforwardfailure", oExitOnForwardFailure }, 174c2d3a559SKris Kennaway { "xauthlocation", oXAuthLocation }, 175511b41d2SMark Murray { "gatewayports", oGatewayPorts }, 176511b41d2SMark Murray { "useprivilegedport", oUsePrivilegedPort }, 177cf2b5f3bSDag-Erling Smørgrav { "rhostsauthentication", oDeprecated }, 178511b41d2SMark Murray { "passwordauthentication", oPasswordAuthentication }, 17909958426SBrian Feldman { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 18009958426SBrian Feldman { "kbdinteractivedevices", oKbdInteractiveDevices }, 181511b41d2SMark Murray { "rsaauthentication", oRSAAuthentication }, 182ca3176e7SBrian Feldman { "pubkeyauthentication", oPubkeyAuthentication }, 183ca3176e7SBrian Feldman { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 184ca3176e7SBrian Feldman { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 185ca3176e7SBrian Feldman { "hostbasedauthentication", oHostbasedAuthentication }, 186ca3176e7SBrian Feldman { "challengeresponseauthentication", oChallengeResponseAuthentication }, 187ca3176e7SBrian Feldman { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 188ca3176e7SBrian Feldman { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 189cf2b5f3bSDag-Erling Smørgrav { "kerberosauthentication", oUnsupported }, 190cf2b5f3bSDag-Erling Smørgrav { "kerberostgtpassing", oUnsupported }, 191cf2b5f3bSDag-Erling Smørgrav { "afstokenpassing", oUnsupported }, 192cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI) 193cf2b5f3bSDag-Erling Smørgrav { "gssapiauthentication", oGssAuthentication }, 194cf2b5f3bSDag-Erling Smørgrav { "gssapidelegatecredentials", oGssDelegateCreds }, 195cf2b5f3bSDag-Erling Smørgrav #else 196cf2b5f3bSDag-Erling Smørgrav { "gssapiauthentication", oUnsupported }, 197cf2b5f3bSDag-Erling Smørgrav { "gssapidelegatecredentials", oUnsupported }, 198511b41d2SMark Murray #endif 19980628bacSDag-Erling Smørgrav { "fallbacktorsh", oDeprecated }, 20080628bacSDag-Erling Smørgrav { "usersh", oDeprecated }, 201511b41d2SMark Murray { "identityfile", oIdentityFile }, 202cce7d346SDag-Erling Smørgrav { "identityfile2", oIdentityFile }, /* obsolete */ 2035962c0e9SDag-Erling Smørgrav { "identitiesonly", oIdentitiesOnly }, 204511b41d2SMark Murray { "hostname", oHostName }, 205ca3176e7SBrian Feldman { "hostkeyalias", oHostKeyAlias }, 206511b41d2SMark Murray { "proxycommand", oProxyCommand }, 207511b41d2SMark Murray { "port", oPort }, 208511b41d2SMark Murray { "cipher", oCipher }, 209e8aafc91SKris Kennaway { "ciphers", oCiphers }, 210ca3176e7SBrian Feldman { "macs", oMacs }, 211e8aafc91SKris Kennaway { "protocol", oProtocol }, 212511b41d2SMark Murray { "remoteforward", oRemoteForward }, 213511b41d2SMark Murray { "localforward", oLocalForward }, 214511b41d2SMark Murray { "user", oUser }, 215511b41d2SMark Murray { "host", oHost }, 216*f7167e0eSDag-Erling Smørgrav { "match", oMatch }, 217511b41d2SMark Murray { "escapechar", oEscapeChar }, 218511b41d2SMark Murray { "globalknownhostsfile", oGlobalKnownHostsFile }, 219e146993eSDag-Erling Smørgrav { "globalknownhostsfile2", oDeprecated }, 220cce7d346SDag-Erling Smørgrav { "userknownhostsfile", oUserKnownHostsFile }, 221e146993eSDag-Erling Smørgrav { "userknownhostsfile2", oDeprecated }, 222511b41d2SMark Murray { "connectionattempts", oConnectionAttempts }, 223511b41d2SMark Murray { "batchmode", oBatchMode }, 224511b41d2SMark Murray { "checkhostip", oCheckHostIP }, 225511b41d2SMark Murray { "stricthostkeychecking", oStrictHostKeyChecking }, 226511b41d2SMark Murray { "compression", oCompression }, 227511b41d2SMark Murray { "compressionlevel", oCompressionLevel }, 2281ec0d754SDag-Erling Smørgrav { "tcpkeepalive", oTCPKeepAlive }, 2291ec0d754SDag-Erling Smørgrav { "keepalive", oTCPKeepAlive }, /* obsolete */ 230511b41d2SMark Murray { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 231511b41d2SMark Murray { "loglevel", oLogLevel }, 232ca3176e7SBrian Feldman { "dynamicforward", oDynamicForward }, 233ca3176e7SBrian Feldman { "preferredauthentications", oPreferredAuthentications }, 234ca3176e7SBrian Feldman { "hostkeyalgorithms", oHostKeyAlgorithms }, 235af12a3e7SDag-Erling Smørgrav { "bindaddress", oBindAddress }, 236b15c8340SDag-Erling Smørgrav #ifdef ENABLE_PKCS11 237b15c8340SDag-Erling Smørgrav { "smartcarddevice", oPKCS11Provider }, 238b15c8340SDag-Erling Smørgrav { "pkcs11provider", oPKCS11Provider }, 239cf2b5f3bSDag-Erling Smørgrav #else 240cf2b5f3bSDag-Erling Smørgrav { "smartcarddevice", oUnsupported }, 241b15c8340SDag-Erling Smørgrav { "pkcs11provider", oUnsupported }, 242cf2b5f3bSDag-Erling Smørgrav #endif 243af12a3e7SDag-Erling Smørgrav { "clearallforwardings", oClearAllForwardings }, 244e73e9afaSDag-Erling Smørgrav { "enablesshkeysign", oEnableSSHKeysign }, 245cf2b5f3bSDag-Erling Smørgrav { "verifyhostkeydns", oVerifyHostKeyDNS }, 246af12a3e7SDag-Erling Smørgrav { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 247cf2b5f3bSDag-Erling Smørgrav { "rekeylimit", oRekeyLimit }, 248cf2b5f3bSDag-Erling Smørgrav { "connecttimeout", oConnectTimeout }, 249cf2b5f3bSDag-Erling Smørgrav { "addressfamily", oAddressFamily }, 2501ec0d754SDag-Erling Smørgrav { "serveraliveinterval", oServerAliveInterval }, 2511ec0d754SDag-Erling Smørgrav { "serveralivecountmax", oServerAliveCountMax }, 25221e764dfSDag-Erling Smørgrav { "sendenv", oSendEnv }, 25321e764dfSDag-Erling Smørgrav { "controlpath", oControlPath }, 25421e764dfSDag-Erling Smørgrav { "controlmaster", oControlMaster }, 255e2f6069cSDag-Erling Smørgrav { "controlpersist", oControlPersist }, 256aa49c926SDag-Erling Smørgrav { "hashknownhosts", oHashKnownHosts }, 257b74df5b2SDag-Erling Smørgrav { "tunnel", oTunnel }, 258b74df5b2SDag-Erling Smørgrav { "tunneldevice", oTunnelDevice }, 259b74df5b2SDag-Erling Smørgrav { "localcommand", oLocalCommand }, 260b74df5b2SDag-Erling Smørgrav { "permitlocalcommand", oPermitLocalCommand }, 261d4af9e69SDag-Erling Smørgrav { "visualhostkey", oVisualHostKey }, 2627aee6ffeSDag-Erling Smørgrav { "useroaming", oUseRoaming }, 263cce7d346SDag-Erling Smørgrav #ifdef JPAKE 264cce7d346SDag-Erling Smørgrav { "zeroknowledgepasswordauthentication", 265cce7d346SDag-Erling Smørgrav oZeroKnowledgePasswordAuthentication }, 266cce7d346SDag-Erling Smørgrav #else 267cce7d346SDag-Erling Smørgrav { "zeroknowledgepasswordauthentication", oUnsupported }, 268cce7d346SDag-Erling Smørgrav #endif 2694a421b63SDag-Erling Smørgrav { "kexalgorithms", oKexAlgorithms }, 2704a421b63SDag-Erling Smørgrav { "ipqos", oIPQoS }, 271e146993eSDag-Erling Smørgrav { "requesttty", oRequestTTY }, 272*f7167e0eSDag-Erling Smørgrav { "proxyusefdpass", oProxyUseFdpass }, 273*f7167e0eSDag-Erling Smørgrav { "canonicaldomains", oCanonicalDomains }, 274*f7167e0eSDag-Erling Smørgrav { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 275*f7167e0eSDag-Erling Smørgrav { "canonicalizehostname", oCanonicalizeHostname }, 276*f7167e0eSDag-Erling Smørgrav { "canonicalizemaxdots", oCanonicalizeMaxDots }, 277*f7167e0eSDag-Erling Smørgrav { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 278e4a9863fSDag-Erling Smørgrav { "ignoreunknown", oIgnoreUnknown }, 27989986192SBrooks Davis { "hpndisabled", oHPNDisabled }, 28089986192SBrooks Davis { "hpnbuffersize", oHPNBufferSize }, 28189986192SBrooks Davis { "tcprcvbufpoll", oTcpRcvBufPoll }, 28289986192SBrooks Davis { "tcprcvbuf", oTcpRcvBuf }, 28389986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED 28489986192SBrooks Davis { "noneenabled", oNoneEnabled }, 28589986192SBrooks Davis { "noneswitch", oNoneSwitch }, 28689986192SBrooks Davis #endif 287975616f0SDag-Erling Smørgrav { "versionaddendum", oVersionAddendum }, 28835762f59SEd Schouten 289af12a3e7SDag-Erling Smørgrav { NULL, oBadOption } 290511b41d2SMark Murray }; 291511b41d2SMark Murray 292511b41d2SMark Murray /* 293511b41d2SMark Murray * Adds a local TCP/IP port forward to options. Never returns if there is an 294511b41d2SMark Murray * error. 295511b41d2SMark Murray */ 296511b41d2SMark Murray 297511b41d2SMark Murray void 298aa49c926SDag-Erling Smørgrav add_local_forward(Options *options, const Forward *newfwd) 299511b41d2SMark Murray { 300511b41d2SMark Murray Forward *fwd; 301f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT 302511b41d2SMark Murray extern uid_t original_real_uid; 30303f6c5cdSDag-Erling Smørgrav int ipport_reserved; 30403f6c5cdSDag-Erling Smørgrav #ifdef __FreeBSD__ 30503f6c5cdSDag-Erling Smørgrav size_t len_ipport_reserved = sizeof(ipport_reserved); 30603f6c5cdSDag-Erling Smørgrav 30703f6c5cdSDag-Erling Smørgrav if (sysctlbyname("net.inet.ip.portrange.reservedhigh", 30803f6c5cdSDag-Erling Smørgrav &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0) 30903f6c5cdSDag-Erling Smørgrav ipport_reserved = IPPORT_RESERVED; 31003f6c5cdSDag-Erling Smørgrav else 31103f6c5cdSDag-Erling Smørgrav ipport_reserved++; 31203f6c5cdSDag-Erling Smørgrav #else 31303f6c5cdSDag-Erling Smørgrav ipport_reserved = IPPORT_RESERVED; 31403f6c5cdSDag-Erling Smørgrav #endif 31503f6c5cdSDag-Erling Smørgrav if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) 316ca3176e7SBrian Feldman fatal("Privileged ports can only be forwarded by root."); 317989dd127SDag-Erling Smørgrav #endif 318e2f6069cSDag-Erling Smørgrav options->local_forwards = xrealloc(options->local_forwards, 319e2f6069cSDag-Erling Smørgrav options->num_local_forwards + 1, 320e2f6069cSDag-Erling Smørgrav sizeof(*options->local_forwards)); 321511b41d2SMark Murray fwd = &options->local_forwards[options->num_local_forwards++]; 322aa49c926SDag-Erling Smørgrav 323cce7d346SDag-Erling Smørgrav fwd->listen_host = newfwd->listen_host; 324aa49c926SDag-Erling Smørgrav fwd->listen_port = newfwd->listen_port; 325cce7d346SDag-Erling Smørgrav fwd->connect_host = newfwd->connect_host; 326aa49c926SDag-Erling Smørgrav fwd->connect_port = newfwd->connect_port; 327511b41d2SMark Murray } 328511b41d2SMark Murray 329511b41d2SMark Murray /* 330511b41d2SMark Murray * Adds a remote TCP/IP port forward to options. Never returns if there is 331511b41d2SMark Murray * an error. 332511b41d2SMark Murray */ 333511b41d2SMark Murray 334511b41d2SMark Murray void 335aa49c926SDag-Erling Smørgrav add_remote_forward(Options *options, const Forward *newfwd) 336511b41d2SMark Murray { 337511b41d2SMark Murray Forward *fwd; 338e2f6069cSDag-Erling Smørgrav 339e2f6069cSDag-Erling Smørgrav options->remote_forwards = xrealloc(options->remote_forwards, 340e2f6069cSDag-Erling Smørgrav options->num_remote_forwards + 1, 341e2f6069cSDag-Erling Smørgrav sizeof(*options->remote_forwards)); 342511b41d2SMark Murray fwd = &options->remote_forwards[options->num_remote_forwards++]; 343aa49c926SDag-Erling Smørgrav 344cce7d346SDag-Erling Smørgrav fwd->listen_host = newfwd->listen_host; 345aa49c926SDag-Erling Smørgrav fwd->listen_port = newfwd->listen_port; 346cce7d346SDag-Erling Smørgrav fwd->connect_host = newfwd->connect_host; 347aa49c926SDag-Erling Smørgrav fwd->connect_port = newfwd->connect_port; 348462c32cbSDag-Erling Smørgrav fwd->handle = newfwd->handle; 349e2f6069cSDag-Erling Smørgrav fwd->allocated_port = 0; 350511b41d2SMark Murray } 351511b41d2SMark Murray 352af12a3e7SDag-Erling Smørgrav static void 353af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options) 354af12a3e7SDag-Erling Smørgrav { 355af12a3e7SDag-Erling Smørgrav int i; 356af12a3e7SDag-Erling Smørgrav 357aa49c926SDag-Erling Smørgrav for (i = 0; i < options->num_local_forwards; i++) { 358e4a9863fSDag-Erling Smørgrav free(options->local_forwards[i].listen_host); 359e4a9863fSDag-Erling Smørgrav free(options->local_forwards[i].connect_host); 360aa49c926SDag-Erling Smørgrav } 361e2f6069cSDag-Erling Smørgrav if (options->num_local_forwards > 0) { 362e4a9863fSDag-Erling Smørgrav free(options->local_forwards); 363e2f6069cSDag-Erling Smørgrav options->local_forwards = NULL; 364e2f6069cSDag-Erling Smørgrav } 365af12a3e7SDag-Erling Smørgrav options->num_local_forwards = 0; 366aa49c926SDag-Erling Smørgrav for (i = 0; i < options->num_remote_forwards; i++) { 367e4a9863fSDag-Erling Smørgrav free(options->remote_forwards[i].listen_host); 368e4a9863fSDag-Erling Smørgrav free(options->remote_forwards[i].connect_host); 369aa49c926SDag-Erling Smørgrav } 370e2f6069cSDag-Erling Smørgrav if (options->num_remote_forwards > 0) { 371e4a9863fSDag-Erling Smørgrav free(options->remote_forwards); 372e2f6069cSDag-Erling Smørgrav options->remote_forwards = NULL; 373e2f6069cSDag-Erling Smørgrav } 374af12a3e7SDag-Erling Smørgrav options->num_remote_forwards = 0; 375b74df5b2SDag-Erling Smørgrav options->tun_open = SSH_TUNMODE_NO; 376af12a3e7SDag-Erling Smørgrav } 377af12a3e7SDag-Erling Smørgrav 378fa67e83cSDag-Erling Smørgrav void 379fa67e83cSDag-Erling Smørgrav add_identity_file(Options *options, const char *dir, const char *filename, 380fa67e83cSDag-Erling Smørgrav int userprovided) 381fa67e83cSDag-Erling Smørgrav { 382fa67e83cSDag-Erling Smørgrav char *path; 383fa67e83cSDag-Erling Smørgrav 384fa67e83cSDag-Erling Smørgrav if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 385fa67e83cSDag-Erling Smørgrav fatal("Too many identity files specified (max %d)", 386fa67e83cSDag-Erling Smørgrav SSH_MAX_IDENTITY_FILES); 387fa67e83cSDag-Erling Smørgrav 388fa67e83cSDag-Erling Smørgrav if (dir == NULL) /* no dir, filename is absolute */ 389fa67e83cSDag-Erling Smørgrav path = xstrdup(filename); 390fa67e83cSDag-Erling Smørgrav else 391fa67e83cSDag-Erling Smørgrav (void)xasprintf(&path, "%.100s%.100s", dir, filename); 392fa67e83cSDag-Erling Smørgrav 393fa67e83cSDag-Erling Smørgrav options->identity_file_userprovided[options->num_identity_files] = 394fa67e83cSDag-Erling Smørgrav userprovided; 395fa67e83cSDag-Erling Smørgrav options->identity_files[options->num_identity_files++] = path; 396fa67e83cSDag-Erling Smørgrav } 397fa67e83cSDag-Erling Smørgrav 398*f7167e0eSDag-Erling Smørgrav int 399*f7167e0eSDag-Erling Smørgrav default_ssh_port(void) 400*f7167e0eSDag-Erling Smørgrav { 401*f7167e0eSDag-Erling Smørgrav static int port; 402*f7167e0eSDag-Erling Smørgrav struct servent *sp; 403*f7167e0eSDag-Erling Smørgrav 404*f7167e0eSDag-Erling Smørgrav if (port == 0) { 405*f7167e0eSDag-Erling Smørgrav sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 406*f7167e0eSDag-Erling Smørgrav port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 407*f7167e0eSDag-Erling Smørgrav } 408*f7167e0eSDag-Erling Smørgrav return port; 409*f7167e0eSDag-Erling Smørgrav } 410*f7167e0eSDag-Erling Smørgrav 411*f7167e0eSDag-Erling Smørgrav /* 412*f7167e0eSDag-Erling Smørgrav * Execute a command in a shell. 413*f7167e0eSDag-Erling Smørgrav * Return its exit status or -1 on abnormal exit. 414*f7167e0eSDag-Erling Smørgrav */ 415*f7167e0eSDag-Erling Smørgrav static int 416*f7167e0eSDag-Erling Smørgrav execute_in_shell(const char *cmd) 417*f7167e0eSDag-Erling Smørgrav { 418*f7167e0eSDag-Erling Smørgrav char *shell, *command_string; 419*f7167e0eSDag-Erling Smørgrav pid_t pid; 420*f7167e0eSDag-Erling Smørgrav int devnull, status; 421*f7167e0eSDag-Erling Smørgrav extern uid_t original_real_uid; 422*f7167e0eSDag-Erling Smørgrav 423*f7167e0eSDag-Erling Smørgrav if ((shell = getenv("SHELL")) == NULL) 424*f7167e0eSDag-Erling Smørgrav shell = _PATH_BSHELL; 425*f7167e0eSDag-Erling Smørgrav 426*f7167e0eSDag-Erling Smørgrav /* 427*f7167e0eSDag-Erling Smørgrav * Use "exec" to avoid "sh -c" processes on some platforms 428*f7167e0eSDag-Erling Smørgrav * (e.g. Solaris) 429*f7167e0eSDag-Erling Smørgrav */ 430*f7167e0eSDag-Erling Smørgrav xasprintf(&command_string, "exec %s", cmd); 431*f7167e0eSDag-Erling Smørgrav 432*f7167e0eSDag-Erling Smørgrav /* Need this to redirect subprocess stdin/out */ 433*f7167e0eSDag-Erling Smørgrav if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) 434*f7167e0eSDag-Erling Smørgrav fatal("open(/dev/null): %s", strerror(errno)); 435*f7167e0eSDag-Erling Smørgrav 436*f7167e0eSDag-Erling Smørgrav debug("Executing command: '%.500s'", cmd); 437*f7167e0eSDag-Erling Smørgrav 438*f7167e0eSDag-Erling Smørgrav /* Fork and execute the command. */ 439*f7167e0eSDag-Erling Smørgrav if ((pid = fork()) == 0) { 440*f7167e0eSDag-Erling Smørgrav char *argv[4]; 441*f7167e0eSDag-Erling Smørgrav 442*f7167e0eSDag-Erling Smørgrav /* Child. Permanently give up superuser privileges. */ 443*f7167e0eSDag-Erling Smørgrav permanently_drop_suid(original_real_uid); 444*f7167e0eSDag-Erling Smørgrav 445*f7167e0eSDag-Erling Smørgrav /* Redirect child stdin and stdout. Leave stderr */ 446*f7167e0eSDag-Erling Smørgrav if (dup2(devnull, STDIN_FILENO) == -1) 447*f7167e0eSDag-Erling Smørgrav fatal("dup2: %s", strerror(errno)); 448*f7167e0eSDag-Erling Smørgrav if (dup2(devnull, STDOUT_FILENO) == -1) 449*f7167e0eSDag-Erling Smørgrav fatal("dup2: %s", strerror(errno)); 450*f7167e0eSDag-Erling Smørgrav if (devnull > STDERR_FILENO) 451*f7167e0eSDag-Erling Smørgrav close(devnull); 452*f7167e0eSDag-Erling Smørgrav closefrom(STDERR_FILENO + 1); 453*f7167e0eSDag-Erling Smørgrav 454*f7167e0eSDag-Erling Smørgrav argv[0] = shell; 455*f7167e0eSDag-Erling Smørgrav argv[1] = "-c"; 456*f7167e0eSDag-Erling Smørgrav argv[2] = command_string; 457*f7167e0eSDag-Erling Smørgrav argv[3] = NULL; 458*f7167e0eSDag-Erling Smørgrav 459*f7167e0eSDag-Erling Smørgrav execv(argv[0], argv); 460*f7167e0eSDag-Erling Smørgrav error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 461*f7167e0eSDag-Erling Smørgrav /* Die with signal to make this error apparent to parent. */ 462*f7167e0eSDag-Erling Smørgrav signal(SIGTERM, SIG_DFL); 463*f7167e0eSDag-Erling Smørgrav kill(getpid(), SIGTERM); 464*f7167e0eSDag-Erling Smørgrav _exit(1); 465*f7167e0eSDag-Erling Smørgrav } 466*f7167e0eSDag-Erling Smørgrav /* Parent. */ 467*f7167e0eSDag-Erling Smørgrav if (pid < 0) 468*f7167e0eSDag-Erling Smørgrav fatal("%s: fork: %.100s", __func__, strerror(errno)); 469*f7167e0eSDag-Erling Smørgrav 470*f7167e0eSDag-Erling Smørgrav close(devnull); 471*f7167e0eSDag-Erling Smørgrav free(command_string); 472*f7167e0eSDag-Erling Smørgrav 473*f7167e0eSDag-Erling Smørgrav while (waitpid(pid, &status, 0) == -1) { 474*f7167e0eSDag-Erling Smørgrav if (errno != EINTR && errno != EAGAIN) 475*f7167e0eSDag-Erling Smørgrav fatal("%s: waitpid: %s", __func__, strerror(errno)); 476*f7167e0eSDag-Erling Smørgrav } 477*f7167e0eSDag-Erling Smørgrav if (!WIFEXITED(status)) { 478*f7167e0eSDag-Erling Smørgrav error("command '%.100s' exited abnormally", cmd); 479*f7167e0eSDag-Erling Smørgrav return -1; 480*f7167e0eSDag-Erling Smørgrav } 481*f7167e0eSDag-Erling Smørgrav debug3("command returned status %d", WEXITSTATUS(status)); 482*f7167e0eSDag-Erling Smørgrav return WEXITSTATUS(status); 483*f7167e0eSDag-Erling Smørgrav } 484*f7167e0eSDag-Erling Smørgrav 485*f7167e0eSDag-Erling Smørgrav /* 486*f7167e0eSDag-Erling Smørgrav * Parse and execute a Match directive. 487*f7167e0eSDag-Erling Smørgrav */ 488*f7167e0eSDag-Erling Smørgrav static int 489*f7167e0eSDag-Erling Smørgrav match_cfg_line(Options *options, char **condition, struct passwd *pw, 490*f7167e0eSDag-Erling Smørgrav const char *host_arg, const char *filename, int linenum) 491*f7167e0eSDag-Erling Smørgrav { 492*f7167e0eSDag-Erling Smørgrav char *arg, *attrib, *cmd, *cp = *condition, *host; 493*f7167e0eSDag-Erling Smørgrav const char *ruser; 494*f7167e0eSDag-Erling Smørgrav int r, port, result = 1, attributes = 0; 495*f7167e0eSDag-Erling Smørgrav size_t len; 496*f7167e0eSDag-Erling Smørgrav char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 497*f7167e0eSDag-Erling Smørgrav 498*f7167e0eSDag-Erling Smørgrav /* 499*f7167e0eSDag-Erling Smørgrav * Configuration is likely to be incomplete at this point so we 500*f7167e0eSDag-Erling Smørgrav * must be prepared to use default values. 501*f7167e0eSDag-Erling Smørgrav */ 502*f7167e0eSDag-Erling Smørgrav port = options->port <= 0 ? default_ssh_port() : options->port; 503*f7167e0eSDag-Erling Smørgrav ruser = options->user == NULL ? pw->pw_name : options->user; 504*f7167e0eSDag-Erling Smørgrav if (options->hostname != NULL) { 505*f7167e0eSDag-Erling Smørgrav /* NB. Please keep in sync with ssh.c:main() */ 506*f7167e0eSDag-Erling Smørgrav host = percent_expand(options->hostname, 507*f7167e0eSDag-Erling Smørgrav "h", host_arg, (char *)NULL); 508*f7167e0eSDag-Erling Smørgrav } else 509*f7167e0eSDag-Erling Smørgrav host = xstrdup(host_arg); 510*f7167e0eSDag-Erling Smørgrav 511*f7167e0eSDag-Erling Smørgrav debug3("checking match for '%s' host %s", cp, host); 512*f7167e0eSDag-Erling Smørgrav while ((attrib = strdelim(&cp)) && *attrib != '\0') { 513*f7167e0eSDag-Erling Smørgrav attributes++; 514*f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "all") == 0) { 515*f7167e0eSDag-Erling Smørgrav if (attributes != 1 || 516*f7167e0eSDag-Erling Smørgrav ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 517*f7167e0eSDag-Erling Smørgrav error("'all' cannot be combined with other " 518*f7167e0eSDag-Erling Smørgrav "Match attributes"); 519*f7167e0eSDag-Erling Smørgrav result = -1; 520*f7167e0eSDag-Erling Smørgrav goto out; 521*f7167e0eSDag-Erling Smørgrav } 522*f7167e0eSDag-Erling Smørgrav *condition = cp; 523*f7167e0eSDag-Erling Smørgrav result = 1; 524*f7167e0eSDag-Erling Smørgrav goto out; 525*f7167e0eSDag-Erling Smørgrav } 526*f7167e0eSDag-Erling Smørgrav if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 527*f7167e0eSDag-Erling Smørgrav error("Missing Match criteria for %s", attrib); 528*f7167e0eSDag-Erling Smørgrav result = -1; 529*f7167e0eSDag-Erling Smørgrav goto out; 530*f7167e0eSDag-Erling Smørgrav } 531*f7167e0eSDag-Erling Smørgrav len = strlen(arg); 532*f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "host") == 0) { 533*f7167e0eSDag-Erling Smørgrav if (match_hostname(host, arg, len) != 1) 534*f7167e0eSDag-Erling Smørgrav result = 0; 535*f7167e0eSDag-Erling Smørgrav else 536*f7167e0eSDag-Erling Smørgrav debug("%.200s line %d: matched 'Host %.100s' ", 537*f7167e0eSDag-Erling Smørgrav filename, linenum, host); 538*f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "originalhost") == 0) { 539*f7167e0eSDag-Erling Smørgrav if (match_hostname(host_arg, arg, len) != 1) 540*f7167e0eSDag-Erling Smørgrav result = 0; 541*f7167e0eSDag-Erling Smørgrav else 542*f7167e0eSDag-Erling Smørgrav debug("%.200s line %d: matched " 543*f7167e0eSDag-Erling Smørgrav "'OriginalHost %.100s' ", 544*f7167e0eSDag-Erling Smørgrav filename, linenum, host_arg); 545*f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "user") == 0) { 546*f7167e0eSDag-Erling Smørgrav if (match_pattern_list(ruser, arg, len, 0) != 1) 547*f7167e0eSDag-Erling Smørgrav result = 0; 548*f7167e0eSDag-Erling Smørgrav else 549*f7167e0eSDag-Erling Smørgrav debug("%.200s line %d: matched 'User %.100s' ", 550*f7167e0eSDag-Erling Smørgrav filename, linenum, ruser); 551*f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localuser") == 0) { 552*f7167e0eSDag-Erling Smørgrav if (match_pattern_list(pw->pw_name, arg, len, 0) != 1) 553*f7167e0eSDag-Erling Smørgrav result = 0; 554*f7167e0eSDag-Erling Smørgrav else 555*f7167e0eSDag-Erling Smørgrav debug("%.200s line %d: matched " 556*f7167e0eSDag-Erling Smørgrav "'LocalUser %.100s' ", 557*f7167e0eSDag-Erling Smørgrav filename, linenum, pw->pw_name); 558*f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "exec") == 0) { 559*f7167e0eSDag-Erling Smørgrav if (gethostname(thishost, sizeof(thishost)) == -1) 560*f7167e0eSDag-Erling Smørgrav fatal("gethostname: %s", strerror(errno)); 561*f7167e0eSDag-Erling Smørgrav strlcpy(shorthost, thishost, sizeof(shorthost)); 562*f7167e0eSDag-Erling Smørgrav shorthost[strcspn(thishost, ".")] = '\0'; 563*f7167e0eSDag-Erling Smørgrav snprintf(portstr, sizeof(portstr), "%d", port); 564*f7167e0eSDag-Erling Smørgrav 565*f7167e0eSDag-Erling Smørgrav cmd = percent_expand(arg, 566*f7167e0eSDag-Erling Smørgrav "L", shorthost, 567*f7167e0eSDag-Erling Smørgrav "d", pw->pw_dir, 568*f7167e0eSDag-Erling Smørgrav "h", host, 569*f7167e0eSDag-Erling Smørgrav "l", thishost, 570*f7167e0eSDag-Erling Smørgrav "n", host_arg, 571*f7167e0eSDag-Erling Smørgrav "p", portstr, 572*f7167e0eSDag-Erling Smørgrav "r", ruser, 573*f7167e0eSDag-Erling Smørgrav "u", pw->pw_name, 574*f7167e0eSDag-Erling Smørgrav (char *)NULL); 575*f7167e0eSDag-Erling Smørgrav r = execute_in_shell(cmd); 576*f7167e0eSDag-Erling Smørgrav if (r == -1) { 577*f7167e0eSDag-Erling Smørgrav fatal("%.200s line %d: match exec '%.100s' " 578*f7167e0eSDag-Erling Smørgrav "error", filename, linenum, cmd); 579*f7167e0eSDag-Erling Smørgrav } else if (r == 0) { 580*f7167e0eSDag-Erling Smørgrav debug("%.200s line %d: matched " 581*f7167e0eSDag-Erling Smørgrav "'exec \"%.100s\"' ", 582*f7167e0eSDag-Erling Smørgrav filename, linenum, cmd); 583*f7167e0eSDag-Erling Smørgrav } else 584*f7167e0eSDag-Erling Smørgrav result = 0; 585*f7167e0eSDag-Erling Smørgrav free(cmd); 586*f7167e0eSDag-Erling Smørgrav } else { 587*f7167e0eSDag-Erling Smørgrav error("Unsupported Match attribute %s", attrib); 588*f7167e0eSDag-Erling Smørgrav result = -1; 589*f7167e0eSDag-Erling Smørgrav goto out; 590*f7167e0eSDag-Erling Smørgrav } 591*f7167e0eSDag-Erling Smørgrav } 592*f7167e0eSDag-Erling Smørgrav if (attributes == 0) { 593*f7167e0eSDag-Erling Smørgrav error("One or more attributes required for Match"); 594*f7167e0eSDag-Erling Smørgrav result = -1; 595*f7167e0eSDag-Erling Smørgrav goto out; 596*f7167e0eSDag-Erling Smørgrav } 597*f7167e0eSDag-Erling Smørgrav debug3("match %sfound", result ? "" : "not "); 598*f7167e0eSDag-Erling Smørgrav *condition = cp; 599*f7167e0eSDag-Erling Smørgrav out: 600*f7167e0eSDag-Erling Smørgrav free(host); 601*f7167e0eSDag-Erling Smørgrav return result; 602*f7167e0eSDag-Erling Smørgrav } 603*f7167e0eSDag-Erling Smørgrav 604*f7167e0eSDag-Erling Smørgrav /* Check and prepare a domain name: removes trailing '.' and lowercases */ 605*f7167e0eSDag-Erling Smørgrav static void 606*f7167e0eSDag-Erling Smørgrav valid_domain(char *name, const char *filename, int linenum) 607*f7167e0eSDag-Erling Smørgrav { 608*f7167e0eSDag-Erling Smørgrav size_t i, l = strlen(name); 609*f7167e0eSDag-Erling Smørgrav u_char c, last = '\0'; 610*f7167e0eSDag-Erling Smørgrav 611*f7167e0eSDag-Erling Smørgrav if (l == 0) 612*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: empty hostname suffix", filename, linenum); 613*f7167e0eSDag-Erling Smørgrav if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) 614*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" " 615*f7167e0eSDag-Erling Smørgrav "starts with invalid character", filename, linenum, name); 616*f7167e0eSDag-Erling Smørgrav for (i = 0; i < l; i++) { 617*f7167e0eSDag-Erling Smørgrav c = tolower((u_char)name[i]); 618*f7167e0eSDag-Erling Smørgrav name[i] = (char)c; 619*f7167e0eSDag-Erling Smørgrav if (last == '.' && c == '.') 620*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" contains " 621*f7167e0eSDag-Erling Smørgrav "consecutive separators", filename, linenum, name); 622*f7167e0eSDag-Erling Smørgrav if (c != '.' && c != '-' && !isalnum(c) && 623*f7167e0eSDag-Erling Smørgrav c != '_') /* technically invalid, but common */ 624*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" contains " 625*f7167e0eSDag-Erling Smørgrav "invalid characters", filename, linenum, name); 626*f7167e0eSDag-Erling Smørgrav last = c; 627*f7167e0eSDag-Erling Smørgrav } 628*f7167e0eSDag-Erling Smørgrav if (name[l - 1] == '.') 629*f7167e0eSDag-Erling Smørgrav name[l - 1] = '\0'; 630*f7167e0eSDag-Erling Smørgrav } 631*f7167e0eSDag-Erling Smørgrav 632511b41d2SMark Murray /* 633ca3176e7SBrian Feldman * Returns the number of the token pointed to by cp or oBadOption. 634511b41d2SMark Murray */ 635511b41d2SMark Murray static OpCodes 636e4a9863fSDag-Erling Smørgrav parse_token(const char *cp, const char *filename, int linenum, 637e4a9863fSDag-Erling Smørgrav const char *ignored_unknown) 638511b41d2SMark Murray { 639e4a9863fSDag-Erling Smørgrav int i; 640511b41d2SMark Murray 641511b41d2SMark Murray for (i = 0; keywords[i].name; i++) 642e4a9863fSDag-Erling Smørgrav if (strcmp(cp, keywords[i].name) == 0) 643511b41d2SMark Murray return keywords[i].opcode; 644e4a9863fSDag-Erling Smørgrav if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown, 645e4a9863fSDag-Erling Smørgrav strlen(ignored_unknown), 1) == 1) 646e4a9863fSDag-Erling Smørgrav return oIgnoredUnknownOption; 647ca3176e7SBrian Feldman error("%s: line %d: Bad configuration option: %s", 648511b41d2SMark Murray filename, linenum, cp); 649511b41d2SMark Murray return oBadOption; 650511b41d2SMark Murray } 651511b41d2SMark Murray 652*f7167e0eSDag-Erling Smørgrav /* Multistate option parsing */ 653*f7167e0eSDag-Erling Smørgrav struct multistate { 654*f7167e0eSDag-Erling Smørgrav char *key; 655*f7167e0eSDag-Erling Smørgrav int value; 656*f7167e0eSDag-Erling Smørgrav }; 657*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_flag[] = { 658*f7167e0eSDag-Erling Smørgrav { "true", 1 }, 659*f7167e0eSDag-Erling Smørgrav { "false", 0 }, 660*f7167e0eSDag-Erling Smørgrav { "yes", 1 }, 661*f7167e0eSDag-Erling Smørgrav { "no", 0 }, 662*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 663*f7167e0eSDag-Erling Smørgrav }; 664*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_yesnoask[] = { 665*f7167e0eSDag-Erling Smørgrav { "true", 1 }, 666*f7167e0eSDag-Erling Smørgrav { "false", 0 }, 667*f7167e0eSDag-Erling Smørgrav { "yes", 1 }, 668*f7167e0eSDag-Erling Smørgrav { "no", 0 }, 669*f7167e0eSDag-Erling Smørgrav { "ask", 2 }, 670*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 671*f7167e0eSDag-Erling Smørgrav }; 672*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_addressfamily[] = { 673*f7167e0eSDag-Erling Smørgrav { "inet", AF_INET }, 674*f7167e0eSDag-Erling Smørgrav { "inet6", AF_INET6 }, 675*f7167e0eSDag-Erling Smørgrav { "any", AF_UNSPEC }, 676*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 677*f7167e0eSDag-Erling Smørgrav }; 678*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_controlmaster[] = { 679*f7167e0eSDag-Erling Smørgrav { "true", SSHCTL_MASTER_YES }, 680*f7167e0eSDag-Erling Smørgrav { "yes", SSHCTL_MASTER_YES }, 681*f7167e0eSDag-Erling Smørgrav { "false", SSHCTL_MASTER_NO }, 682*f7167e0eSDag-Erling Smørgrav { "no", SSHCTL_MASTER_NO }, 683*f7167e0eSDag-Erling Smørgrav { "auto", SSHCTL_MASTER_AUTO }, 684*f7167e0eSDag-Erling Smørgrav { "ask", SSHCTL_MASTER_ASK }, 685*f7167e0eSDag-Erling Smørgrav { "autoask", SSHCTL_MASTER_AUTO_ASK }, 686*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 687*f7167e0eSDag-Erling Smørgrav }; 688*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_tunnel[] = { 689*f7167e0eSDag-Erling Smørgrav { "ethernet", SSH_TUNMODE_ETHERNET }, 690*f7167e0eSDag-Erling Smørgrav { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 691*f7167e0eSDag-Erling Smørgrav { "true", SSH_TUNMODE_DEFAULT }, 692*f7167e0eSDag-Erling Smørgrav { "yes", SSH_TUNMODE_DEFAULT }, 693*f7167e0eSDag-Erling Smørgrav { "false", SSH_TUNMODE_NO }, 694*f7167e0eSDag-Erling Smørgrav { "no", SSH_TUNMODE_NO }, 695*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 696*f7167e0eSDag-Erling Smørgrav }; 697*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_requesttty[] = { 698*f7167e0eSDag-Erling Smørgrav { "true", REQUEST_TTY_YES }, 699*f7167e0eSDag-Erling Smørgrav { "yes", REQUEST_TTY_YES }, 700*f7167e0eSDag-Erling Smørgrav { "false", REQUEST_TTY_NO }, 701*f7167e0eSDag-Erling Smørgrav { "no", REQUEST_TTY_NO }, 702*f7167e0eSDag-Erling Smørgrav { "force", REQUEST_TTY_FORCE }, 703*f7167e0eSDag-Erling Smørgrav { "auto", REQUEST_TTY_AUTO }, 704*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 705*f7167e0eSDag-Erling Smørgrav }; 706*f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_canonicalizehostname[] = { 707*f7167e0eSDag-Erling Smørgrav { "true", SSH_CANONICALISE_YES }, 708*f7167e0eSDag-Erling Smørgrav { "false", SSH_CANONICALISE_NO }, 709*f7167e0eSDag-Erling Smørgrav { "yes", SSH_CANONICALISE_YES }, 710*f7167e0eSDag-Erling Smørgrav { "no", SSH_CANONICALISE_NO }, 711*f7167e0eSDag-Erling Smørgrav { "always", SSH_CANONICALISE_ALWAYS }, 712*f7167e0eSDag-Erling Smørgrav { NULL, -1 } 713*f7167e0eSDag-Erling Smørgrav }; 714*f7167e0eSDag-Erling Smørgrav 715511b41d2SMark Murray /* 716511b41d2SMark Murray * Processes a single option line as used in the configuration files. This 717511b41d2SMark Murray * only sets those values that have not already been set. 718511b41d2SMark Murray */ 719e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n" 720511b41d2SMark Murray int 721*f7167e0eSDag-Erling Smørgrav process_config_line(Options *options, struct passwd *pw, const char *host, 722*f7167e0eSDag-Erling Smørgrav char *line, const char *filename, int linenum, int *activep, int userconfig) 723511b41d2SMark Murray { 724e146993eSDag-Erling Smørgrav char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; 725e146993eSDag-Erling Smørgrav char **cpptr, fwdarg[256]; 726e4a9863fSDag-Erling Smørgrav u_int i, *uintptr, max_entries = 0; 727*f7167e0eSDag-Erling Smørgrav int negated, opcode, *intptr, value, value2, cmdline = 0; 728d4af9e69SDag-Erling Smørgrav LogLevel *log_level_ptr; 729e4a9863fSDag-Erling Smørgrav long long val64; 730e73e9afaSDag-Erling Smørgrav size_t len; 731aa49c926SDag-Erling Smørgrav Forward fwd; 732*f7167e0eSDag-Erling Smørgrav const struct multistate *multistate_ptr; 733*f7167e0eSDag-Erling Smørgrav struct allowed_cname *cname; 734*f7167e0eSDag-Erling Smørgrav 735*f7167e0eSDag-Erling Smørgrav if (activep == NULL) { /* We are processing a command line directive */ 736*f7167e0eSDag-Erling Smørgrav cmdline = 1; 737*f7167e0eSDag-Erling Smørgrav activep = &cmdline; 738*f7167e0eSDag-Erling Smørgrav } 739511b41d2SMark Murray 740cf2b5f3bSDag-Erling Smørgrav /* Strip trailing whitespace */ 741cf2b5f3bSDag-Erling Smørgrav for (len = strlen(line) - 1; len > 0; len--) { 742cf2b5f3bSDag-Erling Smørgrav if (strchr(WHITESPACE, line[len]) == NULL) 743cf2b5f3bSDag-Erling Smørgrav break; 744cf2b5f3bSDag-Erling Smørgrav line[len] = '\0'; 745cf2b5f3bSDag-Erling Smørgrav } 746cf2b5f3bSDag-Erling Smørgrav 747c2d3a559SKris Kennaway s = line; 748c2d3a559SKris Kennaway /* Get the keyword. (Each line is supposed to begin with a keyword). */ 749333ee039SDag-Erling Smørgrav if ((keyword = strdelim(&s)) == NULL) 750333ee039SDag-Erling Smørgrav return 0; 751c2d3a559SKris Kennaway /* Ignore leading whitespace. */ 752c2d3a559SKris Kennaway if (*keyword == '\0') 753c2d3a559SKris Kennaway keyword = strdelim(&s); 754ca3176e7SBrian Feldman if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 755511b41d2SMark Murray return 0; 756e4a9863fSDag-Erling Smørgrav /* Match lowercase keyword */ 757*f7167e0eSDag-Erling Smørgrav lowercase(keyword); 758511b41d2SMark Murray 759e4a9863fSDag-Erling Smørgrav opcode = parse_token(keyword, filename, linenum, 760e4a9863fSDag-Erling Smørgrav options->ignored_unknown); 761511b41d2SMark Murray 762511b41d2SMark Murray switch (opcode) { 763511b41d2SMark Murray case oBadOption: 764511b41d2SMark Murray /* don't panic, but count bad options */ 765511b41d2SMark Murray return -1; 766511b41d2SMark Murray /* NOTREACHED */ 767e4a9863fSDag-Erling Smørgrav case oIgnoredUnknownOption: 768e4a9863fSDag-Erling Smørgrav debug("%s line %d: Ignored unknown option \"%s\"", 769e4a9863fSDag-Erling Smørgrav filename, linenum, keyword); 770e4a9863fSDag-Erling Smørgrav return 0; 771cf2b5f3bSDag-Erling Smørgrav case oConnectTimeout: 772cf2b5f3bSDag-Erling Smørgrav intptr = &options->connection_timeout; 7731ec0d754SDag-Erling Smørgrav parse_time: 774cf2b5f3bSDag-Erling Smørgrav arg = strdelim(&s); 775cf2b5f3bSDag-Erling Smørgrav if (!arg || *arg == '\0') 776cf2b5f3bSDag-Erling Smørgrav fatal("%s line %d: missing time value.", 777cf2b5f3bSDag-Erling Smørgrav filename, linenum); 778cf2b5f3bSDag-Erling Smørgrav if ((value = convtime(arg)) == -1) 779cf2b5f3bSDag-Erling Smørgrav fatal("%s line %d: invalid time value.", 780cf2b5f3bSDag-Erling Smørgrav filename, linenum); 781d4af9e69SDag-Erling Smørgrav if (*activep && *intptr == -1) 782cf2b5f3bSDag-Erling Smørgrav *intptr = value; 783cf2b5f3bSDag-Erling Smørgrav break; 784cf2b5f3bSDag-Erling Smørgrav 785511b41d2SMark Murray case oForwardAgent: 786511b41d2SMark Murray intptr = &options->forward_agent; 787511b41d2SMark Murray parse_flag: 788*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_flag; 789*f7167e0eSDag-Erling Smørgrav parse_multistate: 790c2d3a559SKris Kennaway arg = strdelim(&s); 791c2d3a559SKris Kennaway if (!arg || *arg == '\0') 792*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: missing argument.", 793*f7167e0eSDag-Erling Smørgrav filename, linenum); 794*f7167e0eSDag-Erling Smørgrav value = -1; 795*f7167e0eSDag-Erling Smørgrav for (i = 0; multistate_ptr[i].key != NULL; i++) { 796*f7167e0eSDag-Erling Smørgrav if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 797*f7167e0eSDag-Erling Smørgrav value = multistate_ptr[i].value; 798*f7167e0eSDag-Erling Smørgrav break; 799*f7167e0eSDag-Erling Smørgrav } 800*f7167e0eSDag-Erling Smørgrav } 801*f7167e0eSDag-Erling Smørgrav if (value == -1) 802*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: unsupported option \"%s\".", 803*f7167e0eSDag-Erling Smørgrav filename, linenum, arg); 804511b41d2SMark Murray if (*activep && *intptr == -1) 805511b41d2SMark Murray *intptr = value; 806511b41d2SMark Murray break; 807511b41d2SMark Murray 808511b41d2SMark Murray case oForwardX11: 809511b41d2SMark Murray intptr = &options->forward_x11; 810511b41d2SMark Murray goto parse_flag; 811511b41d2SMark Murray 8121ec0d754SDag-Erling Smørgrav case oForwardX11Trusted: 8131ec0d754SDag-Erling Smørgrav intptr = &options->forward_x11_trusted; 8141ec0d754SDag-Erling Smørgrav goto parse_flag; 8151ec0d754SDag-Erling Smørgrav 816e2f6069cSDag-Erling Smørgrav case oForwardX11Timeout: 817e2f6069cSDag-Erling Smørgrav intptr = &options->forward_x11_timeout; 818e2f6069cSDag-Erling Smørgrav goto parse_time; 819e2f6069cSDag-Erling Smørgrav 820511b41d2SMark Murray case oGatewayPorts: 821511b41d2SMark Murray intptr = &options->gateway_ports; 822511b41d2SMark Murray goto parse_flag; 823511b41d2SMark Murray 824333ee039SDag-Erling Smørgrav case oExitOnForwardFailure: 825333ee039SDag-Erling Smørgrav intptr = &options->exit_on_forward_failure; 826333ee039SDag-Erling Smørgrav goto parse_flag; 827333ee039SDag-Erling Smørgrav 828511b41d2SMark Murray case oUsePrivilegedPort: 829511b41d2SMark Murray intptr = &options->use_privileged_port; 830511b41d2SMark Murray goto parse_flag; 831511b41d2SMark Murray 832511b41d2SMark Murray case oPasswordAuthentication: 833511b41d2SMark Murray intptr = &options->password_authentication; 834511b41d2SMark Murray goto parse_flag; 835511b41d2SMark Murray 836cce7d346SDag-Erling Smørgrav case oZeroKnowledgePasswordAuthentication: 837cce7d346SDag-Erling Smørgrav intptr = &options->zero_knowledge_password_authentication; 838cce7d346SDag-Erling Smørgrav goto parse_flag; 839cce7d346SDag-Erling Smørgrav 84009958426SBrian Feldman case oKbdInteractiveAuthentication: 84109958426SBrian Feldman intptr = &options->kbd_interactive_authentication; 84209958426SBrian Feldman goto parse_flag; 84309958426SBrian Feldman 84409958426SBrian Feldman case oKbdInteractiveDevices: 84509958426SBrian Feldman charptr = &options->kbd_interactive_devices; 84609958426SBrian Feldman goto parse_string; 84709958426SBrian Feldman 848ca3176e7SBrian Feldman case oPubkeyAuthentication: 849ca3176e7SBrian Feldman intptr = &options->pubkey_authentication; 850e8aafc91SKris Kennaway goto parse_flag; 851e8aafc91SKris Kennaway 852511b41d2SMark Murray case oRSAAuthentication: 853511b41d2SMark Murray intptr = &options->rsa_authentication; 854511b41d2SMark Murray goto parse_flag; 855511b41d2SMark Murray 856511b41d2SMark Murray case oRhostsRSAAuthentication: 857511b41d2SMark Murray intptr = &options->rhosts_rsa_authentication; 858511b41d2SMark Murray goto parse_flag; 859511b41d2SMark Murray 860ca3176e7SBrian Feldman case oHostbasedAuthentication: 861ca3176e7SBrian Feldman intptr = &options->hostbased_authentication; 862511b41d2SMark Murray goto parse_flag; 863511b41d2SMark Murray 864af12a3e7SDag-Erling Smørgrav case oChallengeResponseAuthentication: 865af12a3e7SDag-Erling Smørgrav intptr = &options->challenge_response_authentication; 866af12a3e7SDag-Erling Smørgrav goto parse_flag; 867cf2b5f3bSDag-Erling Smørgrav 868cf2b5f3bSDag-Erling Smørgrav case oGssAuthentication: 869cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_authentication; 870511b41d2SMark Murray goto parse_flag; 871cf2b5f3bSDag-Erling Smørgrav 872cf2b5f3bSDag-Erling Smørgrav case oGssDelegateCreds: 873cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_deleg_creds; 874ca3176e7SBrian Feldman goto parse_flag; 875cf2b5f3bSDag-Erling Smørgrav 876511b41d2SMark Murray case oBatchMode: 877511b41d2SMark Murray intptr = &options->batch_mode; 878511b41d2SMark Murray goto parse_flag; 879511b41d2SMark Murray 880511b41d2SMark Murray case oCheckHostIP: 881511b41d2SMark Murray intptr = &options->check_host_ip; 882511b41d2SMark Murray goto parse_flag; 883511b41d2SMark Murray 884cf2b5f3bSDag-Erling Smørgrav case oVerifyHostKeyDNS: 885cf2b5f3bSDag-Erling Smørgrav intptr = &options->verify_host_key_dns; 886*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_yesnoask; 887*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 888cf2b5f3bSDag-Erling Smørgrav 889511b41d2SMark Murray case oStrictHostKeyChecking: 890511b41d2SMark Murray intptr = &options->strict_host_key_checking; 891*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_yesnoask; 892*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 893511b41d2SMark Murray 894511b41d2SMark Murray case oCompression: 895511b41d2SMark Murray intptr = &options->compression; 896511b41d2SMark Murray goto parse_flag; 897511b41d2SMark Murray 8981ec0d754SDag-Erling Smørgrav case oTCPKeepAlive: 8991ec0d754SDag-Erling Smørgrav intptr = &options->tcp_keep_alive; 900511b41d2SMark Murray goto parse_flag; 901511b41d2SMark Murray 902af12a3e7SDag-Erling Smørgrav case oNoHostAuthenticationForLocalhost: 903af12a3e7SDag-Erling Smørgrav intptr = &options->no_host_authentication_for_localhost; 904af12a3e7SDag-Erling Smørgrav goto parse_flag; 905af12a3e7SDag-Erling Smørgrav 906511b41d2SMark Murray case oNumberOfPasswordPrompts: 907511b41d2SMark Murray intptr = &options->number_of_password_prompts; 908511b41d2SMark Murray goto parse_int; 909511b41d2SMark Murray 910511b41d2SMark Murray case oCompressionLevel: 911511b41d2SMark Murray intptr = &options->compression_level; 912511b41d2SMark Murray goto parse_int; 913511b41d2SMark Murray 914cf2b5f3bSDag-Erling Smørgrav case oRekeyLimit: 915cf2b5f3bSDag-Erling Smørgrav arg = strdelim(&s); 916cf2b5f3bSDag-Erling Smørgrav if (!arg || *arg == '\0') 917e4a9863fSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, 918e4a9863fSDag-Erling Smørgrav linenum); 919e4a9863fSDag-Erling Smørgrav if (strcmp(arg, "default") == 0) { 920e4a9863fSDag-Erling Smørgrav val64 = 0; 921e4a9863fSDag-Erling Smørgrav } else { 922e4a9863fSDag-Erling Smørgrav if (scan_scaled(arg, &val64) == -1) 923e4a9863fSDag-Erling Smørgrav fatal("%.200s line %d: Bad number '%s': %s", 924e4a9863fSDag-Erling Smørgrav filename, linenum, arg, strerror(errno)); 925e4a9863fSDag-Erling Smørgrav /* check for too-large or too-small limits */ 926e4a9863fSDag-Erling Smørgrav if (val64 > UINT_MAX) 927333ee039SDag-Erling Smørgrav fatal("%.200s line %d: RekeyLimit too large", 928333ee039SDag-Erling Smørgrav filename, linenum); 929e4a9863fSDag-Erling Smørgrav if (val64 != 0 && val64 < 16) 930333ee039SDag-Erling Smørgrav fatal("%.200s line %d: RekeyLimit too small", 931333ee039SDag-Erling Smørgrav filename, linenum); 932e4a9863fSDag-Erling Smørgrav } 933d4af9e69SDag-Erling Smørgrav if (*activep && options->rekey_limit == -1) 934d4af9e69SDag-Erling Smørgrav options->rekey_limit = (u_int32_t)val64; 935e4a9863fSDag-Erling Smørgrav if (s != NULL) { /* optional rekey interval present */ 936e4a9863fSDag-Erling Smørgrav if (strcmp(s, "none") == 0) { 937e4a9863fSDag-Erling Smørgrav (void)strdelim(&s); /* discard */ 938e4a9863fSDag-Erling Smørgrav break; 939e4a9863fSDag-Erling Smørgrav } 940e4a9863fSDag-Erling Smørgrav intptr = &options->rekey_interval; 941e4a9863fSDag-Erling Smørgrav goto parse_time; 942e4a9863fSDag-Erling Smørgrav } 943cf2b5f3bSDag-Erling Smørgrav break; 944cf2b5f3bSDag-Erling Smørgrav 945511b41d2SMark Murray case oIdentityFile: 946c2d3a559SKris Kennaway arg = strdelim(&s); 947c2d3a559SKris Kennaway if (!arg || *arg == '\0') 948511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 949511b41d2SMark Murray if (*activep) { 950ca3176e7SBrian Feldman intptr = &options->num_identity_files; 951e8aafc91SKris Kennaway if (*intptr >= SSH_MAX_IDENTITY_FILES) 952511b41d2SMark Murray fatal("%.200s line %d: Too many identity files specified (max %d).", 953511b41d2SMark Murray filename, linenum, SSH_MAX_IDENTITY_FILES); 95473370613SDag-Erling Smørgrav add_identity_file(options, NULL, arg, userconfig); 955511b41d2SMark Murray } 956511b41d2SMark Murray break; 957511b41d2SMark Murray 958c2d3a559SKris Kennaway case oXAuthLocation: 959c2d3a559SKris Kennaway charptr=&options->xauth_location; 960c2d3a559SKris Kennaway goto parse_string; 961c2d3a559SKris Kennaway 962511b41d2SMark Murray case oUser: 963511b41d2SMark Murray charptr = &options->user; 964511b41d2SMark Murray parse_string: 965c2d3a559SKris Kennaway arg = strdelim(&s); 966c2d3a559SKris Kennaway if (!arg || *arg == '\0') 967e146993eSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 968e146993eSDag-Erling Smørgrav filename, linenum); 969511b41d2SMark Murray if (*activep && *charptr == NULL) 970c2d3a559SKris Kennaway *charptr = xstrdup(arg); 971511b41d2SMark Murray break; 972511b41d2SMark Murray 973511b41d2SMark Murray case oGlobalKnownHostsFile: 974e146993eSDag-Erling Smørgrav cpptr = (char **)&options->system_hostfiles; 975e146993eSDag-Erling Smørgrav uintptr = &options->num_system_hostfiles; 976e146993eSDag-Erling Smørgrav max_entries = SSH_MAX_HOSTS_FILES; 977e146993eSDag-Erling Smørgrav parse_char_array: 978e146993eSDag-Erling Smørgrav if (*activep && *uintptr == 0) { 979e146993eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 980e146993eSDag-Erling Smørgrav if ((*uintptr) >= max_entries) 981e146993eSDag-Erling Smørgrav fatal("%s line %d: " 982e146993eSDag-Erling Smørgrav "too many authorized keys files.", 983e146993eSDag-Erling Smørgrav filename, linenum); 984e146993eSDag-Erling Smørgrav cpptr[(*uintptr)++] = xstrdup(arg); 985e146993eSDag-Erling Smørgrav } 986e146993eSDag-Erling Smørgrav } 987e146993eSDag-Erling Smørgrav return 0; 988511b41d2SMark Murray 989511b41d2SMark Murray case oUserKnownHostsFile: 990e146993eSDag-Erling Smørgrav cpptr = (char **)&options->user_hostfiles; 991e146993eSDag-Erling Smørgrav uintptr = &options->num_user_hostfiles; 992e146993eSDag-Erling Smørgrav max_entries = SSH_MAX_HOSTS_FILES; 993e146993eSDag-Erling Smørgrav goto parse_char_array; 994e8aafc91SKris Kennaway 995511b41d2SMark Murray case oHostName: 996511b41d2SMark Murray charptr = &options->hostname; 997511b41d2SMark Murray goto parse_string; 998511b41d2SMark Murray 999ca3176e7SBrian Feldman case oHostKeyAlias: 1000ca3176e7SBrian Feldman charptr = &options->host_key_alias; 1001ca3176e7SBrian Feldman goto parse_string; 1002ca3176e7SBrian Feldman 1003ca3176e7SBrian Feldman case oPreferredAuthentications: 1004ca3176e7SBrian Feldman charptr = &options->preferred_authentications; 1005ca3176e7SBrian Feldman goto parse_string; 1006ca3176e7SBrian Feldman 1007af12a3e7SDag-Erling Smørgrav case oBindAddress: 1008af12a3e7SDag-Erling Smørgrav charptr = &options->bind_address; 1009af12a3e7SDag-Erling Smørgrav goto parse_string; 1010af12a3e7SDag-Erling Smørgrav 1011b15c8340SDag-Erling Smørgrav case oPKCS11Provider: 1012b15c8340SDag-Erling Smørgrav charptr = &options->pkcs11_provider; 1013af12a3e7SDag-Erling Smørgrav goto parse_string; 1014af12a3e7SDag-Erling Smørgrav 1015511b41d2SMark Murray case oProxyCommand: 1016b74df5b2SDag-Erling Smørgrav charptr = &options->proxy_command; 1017b74df5b2SDag-Erling Smørgrav parse_command: 1018cf2b5f3bSDag-Erling Smørgrav if (s == NULL) 1019cf2b5f3bSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, linenum); 1020e73e9afaSDag-Erling Smørgrav len = strspn(s, WHITESPACE "="); 1021511b41d2SMark Murray if (*activep && *charptr == NULL) 1022e73e9afaSDag-Erling Smørgrav *charptr = xstrdup(s + len); 1023511b41d2SMark Murray return 0; 1024511b41d2SMark Murray 1025511b41d2SMark Murray case oPort: 1026511b41d2SMark Murray intptr = &options->port; 1027511b41d2SMark Murray parse_int: 1028c2d3a559SKris Kennaway arg = strdelim(&s); 1029c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1030511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 1031c2d3a559SKris Kennaway if (arg[0] < '0' || arg[0] > '9') 1032511b41d2SMark Murray fatal("%.200s line %d: Bad number.", filename, linenum); 1033511b41d2SMark Murray 1034511b41d2SMark Murray /* Octal, decimal, or hex format? */ 1035c2d3a559SKris Kennaway value = strtol(arg, &endofnumber, 0); 1036c2d3a559SKris Kennaway if (arg == endofnumber) 1037511b41d2SMark Murray fatal("%.200s line %d: Bad number.", filename, linenum); 1038511b41d2SMark Murray if (*activep && *intptr == -1) 1039511b41d2SMark Murray *intptr = value; 1040511b41d2SMark Murray break; 1041511b41d2SMark Murray 1042511b41d2SMark Murray case oConnectionAttempts: 1043511b41d2SMark Murray intptr = &options->connection_attempts; 1044511b41d2SMark Murray goto parse_int; 1045511b41d2SMark Murray 1046511b41d2SMark Murray case oCipher: 1047511b41d2SMark Murray intptr = &options->cipher; 1048c2d3a559SKris Kennaway arg = strdelim(&s); 1049c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1050db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1051c2d3a559SKris Kennaway value = cipher_number(arg); 1052511b41d2SMark Murray if (value == -1) 1053511b41d2SMark Murray fatal("%.200s line %d: Bad cipher '%s'.", 1054c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1055511b41d2SMark Murray if (*activep && *intptr == -1) 1056511b41d2SMark Murray *intptr = value; 1057511b41d2SMark Murray break; 1058511b41d2SMark Murray 1059e8aafc91SKris Kennaway case oCiphers: 1060c2d3a559SKris Kennaway arg = strdelim(&s); 1061c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1062db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1063c2d3a559SKris Kennaway if (!ciphers_valid(arg)) 1064e8aafc91SKris Kennaway fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1065c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1066e8aafc91SKris Kennaway if (*activep && options->ciphers == NULL) 1067c2d3a559SKris Kennaway options->ciphers = xstrdup(arg); 1068e8aafc91SKris Kennaway break; 1069e8aafc91SKris Kennaway 1070ca3176e7SBrian Feldman case oMacs: 1071ca3176e7SBrian Feldman arg = strdelim(&s); 1072ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1073ca3176e7SBrian Feldman fatal("%.200s line %d: Missing argument.", filename, linenum); 1074ca3176e7SBrian Feldman if (!mac_valid(arg)) 1075ca3176e7SBrian Feldman fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 1076ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1077ca3176e7SBrian Feldman if (*activep && options->macs == NULL) 1078ca3176e7SBrian Feldman options->macs = xstrdup(arg); 1079ca3176e7SBrian Feldman break; 1080ca3176e7SBrian Feldman 10814a421b63SDag-Erling Smørgrav case oKexAlgorithms: 10824a421b63SDag-Erling Smørgrav arg = strdelim(&s); 10834a421b63SDag-Erling Smørgrav if (!arg || *arg == '\0') 10844a421b63SDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 10854a421b63SDag-Erling Smørgrav filename, linenum); 10864a421b63SDag-Erling Smørgrav if (!kex_names_valid(arg)) 10874a421b63SDag-Erling Smørgrav fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 10884a421b63SDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 10894a421b63SDag-Erling Smørgrav if (*activep && options->kex_algorithms == NULL) 10904a421b63SDag-Erling Smørgrav options->kex_algorithms = xstrdup(arg); 10914a421b63SDag-Erling Smørgrav break; 10924a421b63SDag-Erling Smørgrav 1093ca3176e7SBrian Feldman case oHostKeyAlgorithms: 1094ca3176e7SBrian Feldman arg = strdelim(&s); 1095ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1096ca3176e7SBrian Feldman fatal("%.200s line %d: Missing argument.", filename, linenum); 1097ca3176e7SBrian Feldman if (!key_names_valid2(arg)) 1098ca3176e7SBrian Feldman fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 1099ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1100ca3176e7SBrian Feldman if (*activep && options->hostkeyalgorithms == NULL) 1101ca3176e7SBrian Feldman options->hostkeyalgorithms = xstrdup(arg); 1102ca3176e7SBrian Feldman break; 1103ca3176e7SBrian Feldman 1104e8aafc91SKris Kennaway case oProtocol: 1105e8aafc91SKris Kennaway intptr = &options->protocol; 1106c2d3a559SKris Kennaway arg = strdelim(&s); 1107c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1108db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1109c2d3a559SKris Kennaway value = proto_spec(arg); 1110e8aafc91SKris Kennaway if (value == SSH_PROTO_UNKNOWN) 1111e8aafc91SKris Kennaway fatal("%.200s line %d: Bad protocol spec '%s'.", 1112c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1113e8aafc91SKris Kennaway if (*activep && *intptr == SSH_PROTO_UNKNOWN) 1114e8aafc91SKris Kennaway *intptr = value; 1115e8aafc91SKris Kennaway break; 1116e8aafc91SKris Kennaway 1117511b41d2SMark Murray case oLogLevel: 1118d4af9e69SDag-Erling Smørgrav log_level_ptr = &options->log_level; 1119c2d3a559SKris Kennaway arg = strdelim(&s); 1120c2d3a559SKris Kennaway value = log_level_number(arg); 1121af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_LEVEL_NOT_SET) 1122ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log level '%s'", 1123c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1124d4af9e69SDag-Erling Smørgrav if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1125d4af9e69SDag-Erling Smørgrav *log_level_ptr = (LogLevel) value; 1126511b41d2SMark Murray break; 1127511b41d2SMark Murray 1128af12a3e7SDag-Erling Smørgrav case oLocalForward: 1129511b41d2SMark Murray case oRemoteForward: 1130cce7d346SDag-Erling Smørgrav case oDynamicForward: 1131c2d3a559SKris Kennaway arg = strdelim(&s); 1132aa49c926SDag-Erling Smørgrav if (arg == NULL || *arg == '\0') 1133af12a3e7SDag-Erling Smørgrav fatal("%.200s line %d: Missing port argument.", 1134af12a3e7SDag-Erling Smørgrav filename, linenum); 1135cce7d346SDag-Erling Smørgrav 1136cce7d346SDag-Erling Smørgrav if (opcode == oLocalForward || 1137cce7d346SDag-Erling Smørgrav opcode == oRemoteForward) { 1138aa49c926SDag-Erling Smørgrav arg2 = strdelim(&s); 1139aa49c926SDag-Erling Smørgrav if (arg2 == NULL || *arg2 == '\0') 1140aa49c926SDag-Erling Smørgrav fatal("%.200s line %d: Missing target argument.", 1141511b41d2SMark Murray filename, linenum); 1142aa49c926SDag-Erling Smørgrav 1143aa49c926SDag-Erling Smørgrav /* construct a string for parse_forward */ 1144aa49c926SDag-Erling Smørgrav snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 1145cce7d346SDag-Erling Smørgrav } else if (opcode == oDynamicForward) { 1146cce7d346SDag-Erling Smørgrav strlcpy(fwdarg, arg, sizeof(fwdarg)); 1147cce7d346SDag-Erling Smørgrav } 1148aa49c926SDag-Erling Smørgrav 1149cce7d346SDag-Erling Smørgrav if (parse_forward(&fwd, fwdarg, 1150cce7d346SDag-Erling Smørgrav opcode == oDynamicForward ? 1 : 0, 1151cce7d346SDag-Erling Smørgrav opcode == oRemoteForward ? 1 : 0) == 0) 1152af12a3e7SDag-Erling Smørgrav fatal("%.200s line %d: Bad forwarding specification.", 1153511b41d2SMark Murray filename, linenum); 1154aa49c926SDag-Erling Smørgrav 1155af12a3e7SDag-Erling Smørgrav if (*activep) { 1156cce7d346SDag-Erling Smørgrav if (opcode == oLocalForward || 1157cce7d346SDag-Erling Smørgrav opcode == oDynamicForward) 1158aa49c926SDag-Erling Smørgrav add_local_forward(options, &fwd); 1159af12a3e7SDag-Erling Smørgrav else if (opcode == oRemoteForward) 1160aa49c926SDag-Erling Smørgrav add_remote_forward(options, &fwd); 1161af12a3e7SDag-Erling Smørgrav } 1162511b41d2SMark Murray break; 1163511b41d2SMark Murray 1164af12a3e7SDag-Erling Smørgrav case oClearAllForwardings: 1165af12a3e7SDag-Erling Smørgrav intptr = &options->clear_forwardings; 1166af12a3e7SDag-Erling Smørgrav goto parse_flag; 1167af12a3e7SDag-Erling Smørgrav 1168511b41d2SMark Murray case oHost: 1169*f7167e0eSDag-Erling Smørgrav if (cmdline) 1170*f7167e0eSDag-Erling Smørgrav fatal("Host directive not supported as a command-line " 1171*f7167e0eSDag-Erling Smørgrav "option"); 1172511b41d2SMark Murray *activep = 0; 1173e146993eSDag-Erling Smørgrav arg2 = NULL; 1174e146993eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1175e146993eSDag-Erling Smørgrav negated = *arg == '!'; 1176e146993eSDag-Erling Smørgrav if (negated) 1177e146993eSDag-Erling Smørgrav arg++; 1178c2d3a559SKris Kennaway if (match_pattern(host, arg)) { 1179e146993eSDag-Erling Smørgrav if (negated) { 1180e146993eSDag-Erling Smørgrav debug("%.200s line %d: Skipping Host " 1181e146993eSDag-Erling Smørgrav "block because of negated match " 1182e146993eSDag-Erling Smørgrav "for %.100s", filename, linenum, 1183e146993eSDag-Erling Smørgrav arg); 1184e146993eSDag-Erling Smørgrav *activep = 0; 1185511b41d2SMark Murray break; 1186511b41d2SMark Murray } 1187e146993eSDag-Erling Smørgrav if (!*activep) 1188e146993eSDag-Erling Smørgrav arg2 = arg; /* logged below */ 1189e146993eSDag-Erling Smørgrav *activep = 1; 1190e146993eSDag-Erling Smørgrav } 1191e146993eSDag-Erling Smørgrav } 1192e146993eSDag-Erling Smørgrav if (*activep) 1193e146993eSDag-Erling Smørgrav debug("%.200s line %d: Applying options for %.100s", 1194e146993eSDag-Erling Smørgrav filename, linenum, arg2); 1195c2d3a559SKris Kennaway /* Avoid garbage check below, as strdelim is done. */ 1196511b41d2SMark Murray return 0; 1197511b41d2SMark Murray 1198*f7167e0eSDag-Erling Smørgrav case oMatch: 1199*f7167e0eSDag-Erling Smørgrav if (cmdline) 1200*f7167e0eSDag-Erling Smørgrav fatal("Host directive not supported as a command-line " 1201*f7167e0eSDag-Erling Smørgrav "option"); 1202*f7167e0eSDag-Erling Smørgrav value = match_cfg_line(options, &s, pw, host, 1203*f7167e0eSDag-Erling Smørgrav filename, linenum); 1204*f7167e0eSDag-Erling Smørgrav if (value < 0) 1205*f7167e0eSDag-Erling Smørgrav fatal("%.200s line %d: Bad Match condition", filename, 1206*f7167e0eSDag-Erling Smørgrav linenum); 1207*f7167e0eSDag-Erling Smørgrav *activep = value; 1208*f7167e0eSDag-Erling Smørgrav break; 1209*f7167e0eSDag-Erling Smørgrav 1210511b41d2SMark Murray case oEscapeChar: 1211511b41d2SMark Murray intptr = &options->escape_char; 1212c2d3a559SKris Kennaway arg = strdelim(&s); 1213c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1214511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 1215c2d3a559SKris Kennaway if (arg[0] == '^' && arg[2] == 0 && 1216ca3176e7SBrian Feldman (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1217ca3176e7SBrian Feldman value = (u_char) arg[1] & 31; 1218c2d3a559SKris Kennaway else if (strlen(arg) == 1) 1219ca3176e7SBrian Feldman value = (u_char) arg[0]; 1220c2d3a559SKris Kennaway else if (strcmp(arg, "none") == 0) 1221af12a3e7SDag-Erling Smørgrav value = SSH_ESCAPECHAR_NONE; 1222511b41d2SMark Murray else { 1223511b41d2SMark Murray fatal("%.200s line %d: Bad escape character.", 1224511b41d2SMark Murray filename, linenum); 1225511b41d2SMark Murray /* NOTREACHED */ 1226511b41d2SMark Murray value = 0; /* Avoid compiler warning. */ 1227511b41d2SMark Murray } 1228511b41d2SMark Murray if (*activep && *intptr == -1) 1229511b41d2SMark Murray *intptr = value; 1230511b41d2SMark Murray break; 1231511b41d2SMark Murray 1232cf2b5f3bSDag-Erling Smørgrav case oAddressFamily: 1233cf2b5f3bSDag-Erling Smørgrav intptr = &options->address_family; 1234*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_addressfamily; 1235*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1236cf2b5f3bSDag-Erling Smørgrav 1237e73e9afaSDag-Erling Smørgrav case oEnableSSHKeysign: 1238e73e9afaSDag-Erling Smørgrav intptr = &options->enable_ssh_keysign; 1239e73e9afaSDag-Erling Smørgrav goto parse_flag; 1240e73e9afaSDag-Erling Smørgrav 12415962c0e9SDag-Erling Smørgrav case oIdentitiesOnly: 12425962c0e9SDag-Erling Smørgrav intptr = &options->identities_only; 12435962c0e9SDag-Erling Smørgrav goto parse_flag; 12445962c0e9SDag-Erling Smørgrav 12451ec0d754SDag-Erling Smørgrav case oServerAliveInterval: 12461ec0d754SDag-Erling Smørgrav intptr = &options->server_alive_interval; 12471ec0d754SDag-Erling Smørgrav goto parse_time; 12481ec0d754SDag-Erling Smørgrav 12491ec0d754SDag-Erling Smørgrav case oServerAliveCountMax: 12501ec0d754SDag-Erling Smørgrav intptr = &options->server_alive_count_max; 12511ec0d754SDag-Erling Smørgrav goto parse_int; 12521ec0d754SDag-Erling Smørgrav 125321e764dfSDag-Erling Smørgrav case oSendEnv: 125421e764dfSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 125521e764dfSDag-Erling Smørgrav if (strchr(arg, '=') != NULL) 125621e764dfSDag-Erling Smørgrav fatal("%s line %d: Invalid environment name.", 125721e764dfSDag-Erling Smørgrav filename, linenum); 1258aa49c926SDag-Erling Smørgrav if (!*activep) 1259aa49c926SDag-Erling Smørgrav continue; 126021e764dfSDag-Erling Smørgrav if (options->num_send_env >= MAX_SEND_ENV) 126121e764dfSDag-Erling Smørgrav fatal("%s line %d: too many send env.", 126221e764dfSDag-Erling Smørgrav filename, linenum); 126321e764dfSDag-Erling Smørgrav options->send_env[options->num_send_env++] = 126421e764dfSDag-Erling Smørgrav xstrdup(arg); 126521e764dfSDag-Erling Smørgrav } 126621e764dfSDag-Erling Smørgrav break; 126721e764dfSDag-Erling Smørgrav 126821e764dfSDag-Erling Smørgrav case oControlPath: 126921e764dfSDag-Erling Smørgrav charptr = &options->control_path; 127021e764dfSDag-Erling Smørgrav goto parse_string; 127121e764dfSDag-Erling Smørgrav 127221e764dfSDag-Erling Smørgrav case oControlMaster: 127321e764dfSDag-Erling Smørgrav intptr = &options->control_master; 1274*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_controlmaster; 1275*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 127621e764dfSDag-Erling Smørgrav 1277e2f6069cSDag-Erling Smørgrav case oControlPersist: 1278e2f6069cSDag-Erling Smørgrav /* no/false/yes/true, or a time spec */ 1279e2f6069cSDag-Erling Smørgrav intptr = &options->control_persist; 1280e2f6069cSDag-Erling Smørgrav arg = strdelim(&s); 1281e2f6069cSDag-Erling Smørgrav if (!arg || *arg == '\0') 1282e2f6069cSDag-Erling Smørgrav fatal("%.200s line %d: Missing ControlPersist" 1283e2f6069cSDag-Erling Smørgrav " argument.", filename, linenum); 1284e2f6069cSDag-Erling Smørgrav value = 0; 1285e2f6069cSDag-Erling Smørgrav value2 = 0; /* timeout */ 1286e2f6069cSDag-Erling Smørgrav if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1287e2f6069cSDag-Erling Smørgrav value = 0; 1288e2f6069cSDag-Erling Smørgrav else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1289e2f6069cSDag-Erling Smørgrav value = 1; 1290e2f6069cSDag-Erling Smørgrav else if ((value2 = convtime(arg)) >= 0) 1291e2f6069cSDag-Erling Smørgrav value = 1; 1292e2f6069cSDag-Erling Smørgrav else 1293e2f6069cSDag-Erling Smørgrav fatal("%.200s line %d: Bad ControlPersist argument.", 1294e2f6069cSDag-Erling Smørgrav filename, linenum); 1295e2f6069cSDag-Erling Smørgrav if (*activep && *intptr == -1) { 1296e2f6069cSDag-Erling Smørgrav *intptr = value; 1297e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = value2; 1298e2f6069cSDag-Erling Smørgrav } 1299e2f6069cSDag-Erling Smørgrav break; 1300e2f6069cSDag-Erling Smørgrav 1301aa49c926SDag-Erling Smørgrav case oHashKnownHosts: 1302aa49c926SDag-Erling Smørgrav intptr = &options->hash_known_hosts; 1303aa49c926SDag-Erling Smørgrav goto parse_flag; 1304aa49c926SDag-Erling Smørgrav 1305b74df5b2SDag-Erling Smørgrav case oTunnel: 1306b74df5b2SDag-Erling Smørgrav intptr = &options->tun_open; 1307*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_tunnel; 1308*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1309b74df5b2SDag-Erling Smørgrav 1310b74df5b2SDag-Erling Smørgrav case oTunnelDevice: 1311b74df5b2SDag-Erling Smørgrav arg = strdelim(&s); 1312b74df5b2SDag-Erling Smørgrav if (!arg || *arg == '\0') 1313b74df5b2SDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, linenum); 1314b74df5b2SDag-Erling Smørgrav value = a2tun(arg, &value2); 1315b74df5b2SDag-Erling Smørgrav if (value == SSH_TUNID_ERR) 1316b74df5b2SDag-Erling Smørgrav fatal("%.200s line %d: Bad tun device.", filename, linenum); 1317b74df5b2SDag-Erling Smørgrav if (*activep) { 1318b74df5b2SDag-Erling Smørgrav options->tun_local = value; 1319b74df5b2SDag-Erling Smørgrav options->tun_remote = value2; 1320b74df5b2SDag-Erling Smørgrav } 1321b74df5b2SDag-Erling Smørgrav break; 1322b74df5b2SDag-Erling Smørgrav 1323b74df5b2SDag-Erling Smørgrav case oLocalCommand: 1324b74df5b2SDag-Erling Smørgrav charptr = &options->local_command; 1325b74df5b2SDag-Erling Smørgrav goto parse_command; 1326b74df5b2SDag-Erling Smørgrav 1327b74df5b2SDag-Erling Smørgrav case oPermitLocalCommand: 1328b74df5b2SDag-Erling Smørgrav intptr = &options->permit_local_command; 1329b74df5b2SDag-Erling Smørgrav goto parse_flag; 1330b74df5b2SDag-Erling Smørgrav 1331d4af9e69SDag-Erling Smørgrav case oVisualHostKey: 1332d4af9e69SDag-Erling Smørgrav intptr = &options->visual_host_key; 1333d4af9e69SDag-Erling Smørgrav goto parse_flag; 1334d4af9e69SDag-Erling Smørgrav 13354a421b63SDag-Erling Smørgrav case oIPQoS: 13364a421b63SDag-Erling Smørgrav arg = strdelim(&s); 13374a421b63SDag-Erling Smørgrav if ((value = parse_ipqos(arg)) == -1) 13384a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad IPQoS value: %s", 13394a421b63SDag-Erling Smørgrav filename, linenum, arg); 13404a421b63SDag-Erling Smørgrav arg = strdelim(&s); 13414a421b63SDag-Erling Smørgrav if (arg == NULL) 13424a421b63SDag-Erling Smørgrav value2 = value; 13434a421b63SDag-Erling Smørgrav else if ((value2 = parse_ipqos(arg)) == -1) 13444a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad IPQoS value: %s", 13454a421b63SDag-Erling Smørgrav filename, linenum, arg); 13464a421b63SDag-Erling Smørgrav if (*activep) { 13474a421b63SDag-Erling Smørgrav options->ip_qos_interactive = value; 13484a421b63SDag-Erling Smørgrav options->ip_qos_bulk = value2; 13494a421b63SDag-Erling Smørgrav } 13504a421b63SDag-Erling Smørgrav break; 13514a421b63SDag-Erling Smørgrav 13527aee6ffeSDag-Erling Smørgrav case oUseRoaming: 13537aee6ffeSDag-Erling Smørgrav intptr = &options->use_roaming; 13547aee6ffeSDag-Erling Smørgrav goto parse_flag; 13557aee6ffeSDag-Erling Smørgrav 1356e146993eSDag-Erling Smørgrav case oRequestTTY: 1357e146993eSDag-Erling Smørgrav intptr = &options->request_tty; 1358*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_requesttty; 1359*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1360975616f0SDag-Erling Smørgrav 136189986192SBrooks Davis case oHPNDisabled: 136289986192SBrooks Davis intptr = &options->hpn_disabled; 136389986192SBrooks Davis goto parse_flag; 136489986192SBrooks Davis 136589986192SBrooks Davis case oHPNBufferSize: 136689986192SBrooks Davis intptr = &options->hpn_buffer_size; 136789986192SBrooks Davis goto parse_int; 136889986192SBrooks Davis 136989986192SBrooks Davis case oTcpRcvBufPoll: 137089986192SBrooks Davis intptr = &options->tcp_rcv_buf_poll; 137189986192SBrooks Davis goto parse_flag; 137289986192SBrooks Davis 137389986192SBrooks Davis case oTcpRcvBuf: 137489986192SBrooks Davis intptr = &options->tcp_rcv_buf; 137589986192SBrooks Davis goto parse_int; 137689986192SBrooks Davis 137789986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED 137889986192SBrooks Davis case oNoneEnabled: 137989986192SBrooks Davis intptr = &options->none_enabled; 138089986192SBrooks Davis goto parse_flag; 138189986192SBrooks Davis 138289986192SBrooks Davis /* 138389986192SBrooks Davis * We check to see if the command comes from the command line or not. 138489986192SBrooks Davis * If it does then enable it otherwise fail. NONE must never be a 138589986192SBrooks Davis * default configuration. 138689986192SBrooks Davis */ 138789986192SBrooks Davis case oNoneSwitch: 138889986192SBrooks Davis if (strcmp(filename,"command-line") == 0) { 138989986192SBrooks Davis intptr = &options->none_switch; 139089986192SBrooks Davis goto parse_flag; 139189986192SBrooks Davis } else { 139289986192SBrooks Davis debug("NoneSwitch directive found in %.200s.", 139389986192SBrooks Davis filename); 139489986192SBrooks Davis error("NoneSwitch is found in %.200s.\n" 139589986192SBrooks Davis "You may only use this configuration option " 139689986192SBrooks Davis "from the command line", filename); 139789986192SBrooks Davis error("Continuing..."); 139889986192SBrooks Davis return 0; 139989986192SBrooks Davis } 140089986192SBrooks Davis #endif 140189986192SBrooks Davis 1402e146993eSDag-Erling Smørgrav case oVersionAddendum: 1403462c32cbSDag-Erling Smørgrav if (s == NULL) 1404462c32cbSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, 1405462c32cbSDag-Erling Smørgrav linenum); 1406462c32cbSDag-Erling Smørgrav len = strspn(s, WHITESPACE); 1407462c32cbSDag-Erling Smørgrav if (*activep && options->version_addendum == NULL) { 1408462c32cbSDag-Erling Smørgrav if (strcasecmp(s + len, "none") == 0) 1409462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(""); 1410462c32cbSDag-Erling Smørgrav else if (strchr(s + len, '\r') != NULL) 1411462c32cbSDag-Erling Smørgrav fatal("%.200s line %d: Invalid argument", 1412462c32cbSDag-Erling Smørgrav filename, linenum); 1413462c32cbSDag-Erling Smørgrav else 1414462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(s + len); 1415462c32cbSDag-Erling Smørgrav } 1416462c32cbSDag-Erling Smørgrav return 0; 1417e146993eSDag-Erling Smørgrav 1418e4a9863fSDag-Erling Smørgrav case oIgnoreUnknown: 1419e4a9863fSDag-Erling Smørgrav charptr = &options->ignored_unknown; 1420e4a9863fSDag-Erling Smørgrav goto parse_string; 1421e4a9863fSDag-Erling Smørgrav 1422*f7167e0eSDag-Erling Smørgrav case oProxyUseFdpass: 1423*f7167e0eSDag-Erling Smørgrav intptr = &options->proxy_use_fdpass; 1424*f7167e0eSDag-Erling Smørgrav goto parse_flag; 1425*f7167e0eSDag-Erling Smørgrav 1426*f7167e0eSDag-Erling Smørgrav case oCanonicalDomains: 1427*f7167e0eSDag-Erling Smørgrav value = options->num_canonical_domains != 0; 1428*f7167e0eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1429*f7167e0eSDag-Erling Smørgrav valid_domain(arg, filename, linenum); 1430*f7167e0eSDag-Erling Smørgrav if (!*activep || value) 1431*f7167e0eSDag-Erling Smørgrav continue; 1432*f7167e0eSDag-Erling Smørgrav if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1433*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: too many hostname suffixes.", 1434*f7167e0eSDag-Erling Smørgrav filename, linenum); 1435*f7167e0eSDag-Erling Smørgrav options->canonical_domains[ 1436*f7167e0eSDag-Erling Smørgrav options->num_canonical_domains++] = xstrdup(arg); 1437*f7167e0eSDag-Erling Smørgrav } 1438*f7167e0eSDag-Erling Smørgrav break; 1439*f7167e0eSDag-Erling Smørgrav 1440*f7167e0eSDag-Erling Smørgrav case oCanonicalizePermittedCNAMEs: 1441*f7167e0eSDag-Erling Smørgrav value = options->num_permitted_cnames != 0; 1442*f7167e0eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1443*f7167e0eSDag-Erling Smørgrav /* Either '*' for everything or 'list:list' */ 1444*f7167e0eSDag-Erling Smørgrav if (strcmp(arg, "*") == 0) 1445*f7167e0eSDag-Erling Smørgrav arg2 = arg; 1446*f7167e0eSDag-Erling Smørgrav else { 1447*f7167e0eSDag-Erling Smørgrav lowercase(arg); 1448*f7167e0eSDag-Erling Smørgrav if ((arg2 = strchr(arg, ':')) == NULL || 1449*f7167e0eSDag-Erling Smørgrav arg2[1] == '\0') { 1450*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: " 1451*f7167e0eSDag-Erling Smørgrav "Invalid permitted CNAME \"%s\"", 1452*f7167e0eSDag-Erling Smørgrav filename, linenum, arg); 1453*f7167e0eSDag-Erling Smørgrav } 1454*f7167e0eSDag-Erling Smørgrav *arg2 = '\0'; 1455*f7167e0eSDag-Erling Smørgrav arg2++; 1456*f7167e0eSDag-Erling Smørgrav } 1457*f7167e0eSDag-Erling Smørgrav if (!*activep || value) 1458*f7167e0eSDag-Erling Smørgrav continue; 1459*f7167e0eSDag-Erling Smørgrav if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1460*f7167e0eSDag-Erling Smørgrav fatal("%s line %d: too many permitted CNAMEs.", 1461*f7167e0eSDag-Erling Smørgrav filename, linenum); 1462*f7167e0eSDag-Erling Smørgrav cname = options->permitted_cnames + 1463*f7167e0eSDag-Erling Smørgrav options->num_permitted_cnames++; 1464*f7167e0eSDag-Erling Smørgrav cname->source_list = xstrdup(arg); 1465*f7167e0eSDag-Erling Smørgrav cname->target_list = xstrdup(arg2); 1466*f7167e0eSDag-Erling Smørgrav } 1467*f7167e0eSDag-Erling Smørgrav break; 1468*f7167e0eSDag-Erling Smørgrav 1469*f7167e0eSDag-Erling Smørgrav case oCanonicalizeHostname: 1470*f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_hostname; 1471*f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_canonicalizehostname; 1472*f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1473*f7167e0eSDag-Erling Smørgrav 1474*f7167e0eSDag-Erling Smørgrav case oCanonicalizeMaxDots: 1475*f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_max_dots; 1476*f7167e0eSDag-Erling Smørgrav goto parse_int; 1477*f7167e0eSDag-Erling Smørgrav 1478*f7167e0eSDag-Erling Smørgrav case oCanonicalizeFallbackLocal: 1479*f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_fallback_local; 1480*f7167e0eSDag-Erling Smørgrav goto parse_flag; 1481*f7167e0eSDag-Erling Smørgrav 148280628bacSDag-Erling Smørgrav case oDeprecated: 148380628bacSDag-Erling Smørgrav debug("%s line %d: Deprecated option \"%s\"", 148480628bacSDag-Erling Smørgrav filename, linenum, keyword); 148580628bacSDag-Erling Smørgrav return 0; 148680628bacSDag-Erling Smørgrav 1487cf2b5f3bSDag-Erling Smørgrav case oUnsupported: 1488cf2b5f3bSDag-Erling Smørgrav error("%s line %d: Unsupported option \"%s\"", 1489cf2b5f3bSDag-Erling Smørgrav filename, linenum, keyword); 1490cf2b5f3bSDag-Erling Smørgrav return 0; 1491cf2b5f3bSDag-Erling Smørgrav 1492511b41d2SMark Murray default: 1493511b41d2SMark Murray fatal("process_config_line: Unimplemented opcode %d", opcode); 1494511b41d2SMark Murray } 1495511b41d2SMark Murray 1496511b41d2SMark Murray /* Check that there is no garbage at end of line. */ 1497ca3176e7SBrian Feldman if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1498c2d3a559SKris Kennaway fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1499c2d3a559SKris Kennaway filename, linenum, arg); 1500c2d3a559SKris Kennaway } 1501511b41d2SMark Murray return 0; 1502511b41d2SMark Murray } 1503511b41d2SMark Murray 1504511b41d2SMark Murray 1505511b41d2SMark Murray /* 1506511b41d2SMark Murray * Reads the config file and modifies the options accordingly. Options 1507511b41d2SMark Murray * should already be initialized before this call. This never returns if 1508af12a3e7SDag-Erling Smørgrav * there is an error. If the file does not exist, this returns 0. 1509511b41d2SMark Murray */ 1510511b41d2SMark Murray 1511af12a3e7SDag-Erling Smørgrav int 1512*f7167e0eSDag-Erling Smørgrav read_config_file(const char *filename, struct passwd *pw, const char *host, 1513*f7167e0eSDag-Erling Smørgrav Options *options, int flags) 1514511b41d2SMark Murray { 1515511b41d2SMark Murray FILE *f; 1516511b41d2SMark Murray char line[1024]; 1517511b41d2SMark Murray int active, linenum; 1518511b41d2SMark Murray int bad_options = 0; 1519511b41d2SMark Murray 152021e764dfSDag-Erling Smørgrav if ((f = fopen(filename, "r")) == NULL) 1521af12a3e7SDag-Erling Smørgrav return 0; 1522511b41d2SMark Murray 152373370613SDag-Erling Smørgrav if (flags & SSHCONF_CHECKPERM) { 152421e764dfSDag-Erling Smørgrav struct stat sb; 152521e764dfSDag-Erling Smørgrav 152621e764dfSDag-Erling Smørgrav if (fstat(fileno(f), &sb) == -1) 152721e764dfSDag-Erling Smørgrav fatal("fstat %s: %s", filename, strerror(errno)); 152821e764dfSDag-Erling Smørgrav if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 152921e764dfSDag-Erling Smørgrav (sb.st_mode & 022) != 0)) 153021e764dfSDag-Erling Smørgrav fatal("Bad owner or permissions on %s", filename); 153121e764dfSDag-Erling Smørgrav } 153221e764dfSDag-Erling Smørgrav 1533511b41d2SMark Murray debug("Reading configuration data %.200s", filename); 1534511b41d2SMark Murray 1535511b41d2SMark Murray /* 1536511b41d2SMark Murray * Mark that we are now processing the options. This flag is turned 1537511b41d2SMark Murray * on/off by Host specifications. 1538511b41d2SMark Murray */ 1539511b41d2SMark Murray active = 1; 1540511b41d2SMark Murray linenum = 0; 1541511b41d2SMark Murray while (fgets(line, sizeof(line), f)) { 1542511b41d2SMark Murray /* Update line number counter. */ 1543511b41d2SMark Murray linenum++; 1544*f7167e0eSDag-Erling Smørgrav if (process_config_line(options, pw, host, line, filename, 1545*f7167e0eSDag-Erling Smørgrav linenum, &active, flags & SSHCONF_USERCONF) != 0) 1546511b41d2SMark Murray bad_options++; 1547511b41d2SMark Murray } 1548511b41d2SMark Murray fclose(f); 1549511b41d2SMark Murray if (bad_options > 0) 1550ca3176e7SBrian Feldman fatal("%s: terminating, %d bad configuration options", 1551511b41d2SMark Murray filename, bad_options); 1552af12a3e7SDag-Erling Smørgrav return 1; 1553511b41d2SMark Murray } 1554511b41d2SMark Murray 1555511b41d2SMark Murray /* 1556511b41d2SMark Murray * Initializes options to special values that indicate that they have not yet 1557511b41d2SMark Murray * been set. Read_config_file will only set options with this value. Options 1558511b41d2SMark Murray * are processed in the following order: command line, user config file, 1559511b41d2SMark Murray * system config file. Last, fill_default_options is called. 1560511b41d2SMark Murray */ 1561511b41d2SMark Murray 1562511b41d2SMark Murray void 1563511b41d2SMark Murray initialize_options(Options * options) 1564511b41d2SMark Murray { 1565511b41d2SMark Murray memset(options, 'X', sizeof(*options)); 1566511b41d2SMark Murray options->forward_agent = -1; 1567511b41d2SMark Murray options->forward_x11 = -1; 15681ec0d754SDag-Erling Smørgrav options->forward_x11_trusted = -1; 1569e2f6069cSDag-Erling Smørgrav options->forward_x11_timeout = -1; 1570333ee039SDag-Erling Smørgrav options->exit_on_forward_failure = -1; 1571c2d3a559SKris Kennaway options->xauth_location = NULL; 1572511b41d2SMark Murray options->gateway_ports = -1; 1573511b41d2SMark Murray options->use_privileged_port = -1; 1574511b41d2SMark Murray options->rsa_authentication = -1; 1575ca3176e7SBrian Feldman options->pubkey_authentication = -1; 1576af12a3e7SDag-Erling Smørgrav options->challenge_response_authentication = -1; 1577cf2b5f3bSDag-Erling Smørgrav options->gss_authentication = -1; 1578cf2b5f3bSDag-Erling Smørgrav options->gss_deleg_creds = -1; 1579511b41d2SMark Murray options->password_authentication = -1; 158009958426SBrian Feldman options->kbd_interactive_authentication = -1; 158109958426SBrian Feldman options->kbd_interactive_devices = NULL; 1582511b41d2SMark Murray options->rhosts_rsa_authentication = -1; 1583ca3176e7SBrian Feldman options->hostbased_authentication = -1; 1584511b41d2SMark Murray options->batch_mode = -1; 1585511b41d2SMark Murray options->check_host_ip = -1; 1586511b41d2SMark Murray options->strict_host_key_checking = -1; 1587511b41d2SMark Murray options->compression = -1; 15881ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = -1; 1589511b41d2SMark Murray options->compression_level = -1; 1590511b41d2SMark Murray options->port = -1; 1591cf2b5f3bSDag-Erling Smørgrav options->address_family = -1; 1592511b41d2SMark Murray options->connection_attempts = -1; 1593cf2b5f3bSDag-Erling Smørgrav options->connection_timeout = -1; 1594511b41d2SMark Murray options->number_of_password_prompts = -1; 1595511b41d2SMark Murray options->cipher = -1; 1596e8aafc91SKris Kennaway options->ciphers = NULL; 1597ca3176e7SBrian Feldman options->macs = NULL; 15984a421b63SDag-Erling Smørgrav options->kex_algorithms = NULL; 1599ca3176e7SBrian Feldman options->hostkeyalgorithms = NULL; 1600e8aafc91SKris Kennaway options->protocol = SSH_PROTO_UNKNOWN; 1601511b41d2SMark Murray options->num_identity_files = 0; 1602511b41d2SMark Murray options->hostname = NULL; 1603ca3176e7SBrian Feldman options->host_key_alias = NULL; 1604511b41d2SMark Murray options->proxy_command = NULL; 1605511b41d2SMark Murray options->user = NULL; 1606511b41d2SMark Murray options->escape_char = -1; 1607e146993eSDag-Erling Smørgrav options->num_system_hostfiles = 0; 1608e146993eSDag-Erling Smørgrav options->num_user_hostfiles = 0; 1609e2f6069cSDag-Erling Smørgrav options->local_forwards = NULL; 1610511b41d2SMark Murray options->num_local_forwards = 0; 1611e2f6069cSDag-Erling Smørgrav options->remote_forwards = NULL; 1612511b41d2SMark Murray options->num_remote_forwards = 0; 1613af12a3e7SDag-Erling Smørgrav options->clear_forwardings = -1; 1614af12a3e7SDag-Erling Smørgrav options->log_level = SYSLOG_LEVEL_NOT_SET; 1615ca3176e7SBrian Feldman options->preferred_authentications = NULL; 1616af12a3e7SDag-Erling Smørgrav options->bind_address = NULL; 1617b15c8340SDag-Erling Smørgrav options->pkcs11_provider = NULL; 1618e73e9afaSDag-Erling Smørgrav options->enable_ssh_keysign = - 1; 1619af12a3e7SDag-Erling Smørgrav options->no_host_authentication_for_localhost = - 1; 16205962c0e9SDag-Erling Smørgrav options->identities_only = - 1; 1621cf2b5f3bSDag-Erling Smørgrav options->rekey_limit = - 1; 1622e4a9863fSDag-Erling Smørgrav options->rekey_interval = -1; 1623cf2b5f3bSDag-Erling Smørgrav options->verify_host_key_dns = -1; 16241ec0d754SDag-Erling Smørgrav options->server_alive_interval = -1; 16251ec0d754SDag-Erling Smørgrav options->server_alive_count_max = -1; 162621e764dfSDag-Erling Smørgrav options->num_send_env = 0; 162721e764dfSDag-Erling Smørgrav options->control_path = NULL; 162821e764dfSDag-Erling Smørgrav options->control_master = -1; 1629e2f6069cSDag-Erling Smørgrav options->control_persist = -1; 1630e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = 0; 1631aa49c926SDag-Erling Smørgrav options->hash_known_hosts = -1; 1632b74df5b2SDag-Erling Smørgrav options->tun_open = -1; 1633b74df5b2SDag-Erling Smørgrav options->tun_local = -1; 1634b74df5b2SDag-Erling Smørgrav options->tun_remote = -1; 1635b74df5b2SDag-Erling Smørgrav options->local_command = NULL; 1636b74df5b2SDag-Erling Smørgrav options->permit_local_command = -1; 16377aee6ffeSDag-Erling Smørgrav options->use_roaming = -1; 1638d4af9e69SDag-Erling Smørgrav options->visual_host_key = -1; 1639cce7d346SDag-Erling Smørgrav options->zero_knowledge_password_authentication = -1; 16404a421b63SDag-Erling Smørgrav options->ip_qos_interactive = -1; 16414a421b63SDag-Erling Smørgrav options->ip_qos_bulk = -1; 1642e146993eSDag-Erling Smørgrav options->request_tty = -1; 1643*f7167e0eSDag-Erling Smørgrav options->proxy_use_fdpass = -1; 1644e4a9863fSDag-Erling Smørgrav options->ignored_unknown = NULL; 1645*f7167e0eSDag-Erling Smørgrav options->num_canonical_domains = 0; 1646*f7167e0eSDag-Erling Smørgrav options->num_permitted_cnames = 0; 1647*f7167e0eSDag-Erling Smørgrav options->canonicalize_max_dots = -1; 1648*f7167e0eSDag-Erling Smørgrav options->canonicalize_fallback_local = -1; 1649*f7167e0eSDag-Erling Smørgrav options->canonicalize_hostname = -1; 1650*f7167e0eSDag-Erling Smørgrav options->version_addendum = NULL; 165189986192SBrooks Davis options->hpn_disabled = -1; 165289986192SBrooks Davis options->hpn_buffer_size = -1; 165389986192SBrooks Davis options->tcp_rcv_buf_poll = -1; 165489986192SBrooks Davis options->tcp_rcv_buf = -1; 165589986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED 165689986192SBrooks Davis options->none_enabled = -1; 165789986192SBrooks Davis options->none_switch = -1; 165889986192SBrooks Davis #endif 1659511b41d2SMark Murray } 1660511b41d2SMark Murray 1661511b41d2SMark Murray /* 1662511b41d2SMark Murray * Called after processing other sources of option data, this fills those 1663511b41d2SMark Murray * options for which no value has been specified with their default values. 1664511b41d2SMark Murray */ 1665511b41d2SMark Murray 1666511b41d2SMark Murray void 1667511b41d2SMark Murray fill_default_options(Options * options) 1668511b41d2SMark Murray { 1669511b41d2SMark Murray if (options->forward_agent == -1) 1670db1cb46cSKris Kennaway options->forward_agent = 0; 1671511b41d2SMark Murray if (options->forward_x11 == -1) 16725dc73ebeSBrian Feldman options->forward_x11 = 0; 16731ec0d754SDag-Erling Smørgrav if (options->forward_x11_trusted == -1) 16741ec0d754SDag-Erling Smørgrav options->forward_x11_trusted = 0; 1675e2f6069cSDag-Erling Smørgrav if (options->forward_x11_timeout == -1) 1676e2f6069cSDag-Erling Smørgrav options->forward_x11_timeout = 1200; 1677333ee039SDag-Erling Smørgrav if (options->exit_on_forward_failure == -1) 1678333ee039SDag-Erling Smørgrav options->exit_on_forward_failure = 0; 1679c2d3a559SKris Kennaway if (options->xauth_location == NULL) 1680af12a3e7SDag-Erling Smørgrav options->xauth_location = _PATH_XAUTH; 1681511b41d2SMark Murray if (options->gateway_ports == -1) 1682511b41d2SMark Murray options->gateway_ports = 0; 1683511b41d2SMark Murray if (options->use_privileged_port == -1) 1684ca3176e7SBrian Feldman options->use_privileged_port = 0; 1685511b41d2SMark Murray if (options->rsa_authentication == -1) 1686511b41d2SMark Murray options->rsa_authentication = 1; 1687ca3176e7SBrian Feldman if (options->pubkey_authentication == -1) 1688ca3176e7SBrian Feldman options->pubkey_authentication = 1; 1689af12a3e7SDag-Erling Smørgrav if (options->challenge_response_authentication == -1) 1690af12a3e7SDag-Erling Smørgrav options->challenge_response_authentication = 1; 1691cf2b5f3bSDag-Erling Smørgrav if (options->gss_authentication == -1) 16921ec0d754SDag-Erling Smørgrav options->gss_authentication = 0; 1693cf2b5f3bSDag-Erling Smørgrav if (options->gss_deleg_creds == -1) 1694cf2b5f3bSDag-Erling Smørgrav options->gss_deleg_creds = 0; 1695511b41d2SMark Murray if (options->password_authentication == -1) 1696511b41d2SMark Murray options->password_authentication = 1; 169709958426SBrian Feldman if (options->kbd_interactive_authentication == -1) 1698ca3176e7SBrian Feldman options->kbd_interactive_authentication = 1; 1699511b41d2SMark Murray if (options->rhosts_rsa_authentication == -1) 170080628bacSDag-Erling Smørgrav options->rhosts_rsa_authentication = 0; 1701ca3176e7SBrian Feldman if (options->hostbased_authentication == -1) 1702ca3176e7SBrian Feldman options->hostbased_authentication = 0; 1703511b41d2SMark Murray if (options->batch_mode == -1) 1704511b41d2SMark Murray options->batch_mode = 0; 1705511b41d2SMark Murray if (options->check_host_ip == -1) 1706975616f0SDag-Erling Smørgrav options->check_host_ip = 0; 1707511b41d2SMark Murray if (options->strict_host_key_checking == -1) 1708511b41d2SMark Murray options->strict_host_key_checking = 2; /* 2 is default */ 1709511b41d2SMark Murray if (options->compression == -1) 1710511b41d2SMark Murray options->compression = 0; 17111ec0d754SDag-Erling Smørgrav if (options->tcp_keep_alive == -1) 17121ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = 1; 1713511b41d2SMark Murray if (options->compression_level == -1) 1714511b41d2SMark Murray options->compression_level = 6; 1715511b41d2SMark Murray if (options->port == -1) 1716511b41d2SMark Murray options->port = 0; /* Filled in ssh_connect. */ 1717cf2b5f3bSDag-Erling Smørgrav if (options->address_family == -1) 1718cf2b5f3bSDag-Erling Smørgrav options->address_family = AF_UNSPEC; 1719511b41d2SMark Murray if (options->connection_attempts == -1) 1720af12a3e7SDag-Erling Smørgrav options->connection_attempts = 1; 1721511b41d2SMark Murray if (options->number_of_password_prompts == -1) 1722511b41d2SMark Murray options->number_of_password_prompts = 3; 1723511b41d2SMark Murray /* Selected in ssh_login(). */ 1724511b41d2SMark Murray if (options->cipher == -1) 1725511b41d2SMark Murray options->cipher = SSH_CIPHER_NOT_SET; 1726e8aafc91SKris Kennaway /* options->ciphers, default set in myproposals.h */ 1727ca3176e7SBrian Feldman /* options->macs, default set in myproposals.h */ 17284a421b63SDag-Erling Smørgrav /* options->kex_algorithms, default set in myproposals.h */ 1729ca3176e7SBrian Feldman /* options->hostkeyalgorithms, default set in myproposals.h */ 1730e8aafc91SKris Kennaway if (options->protocol == SSH_PROTO_UNKNOWN) 1731b15c8340SDag-Erling Smørgrav options->protocol = SSH_PROTO_2; 1732511b41d2SMark Murray if (options->num_identity_files == 0) { 1733ca3176e7SBrian Feldman if (options->protocol & SSH_PROTO_1) { 173473370613SDag-Erling Smørgrav add_identity_file(options, "~/", 173573370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_IDENTITY, 0); 1736511b41d2SMark Murray } 1737ca3176e7SBrian Feldman if (options->protocol & SSH_PROTO_2) { 173873370613SDag-Erling Smørgrav add_identity_file(options, "~/", 173973370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_RSA, 0); 174073370613SDag-Erling Smørgrav add_identity_file(options, "~/", 174173370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_DSA, 0); 17424a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 174373370613SDag-Erling Smørgrav add_identity_file(options, "~/", 174473370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_ECDSA, 0); 17454a421b63SDag-Erling Smørgrav #endif 1746*f7167e0eSDag-Erling Smørgrav add_identity_file(options, "~/", 1747*f7167e0eSDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_ED25519, 0); 1748ca3176e7SBrian Feldman } 1749e8aafc91SKris Kennaway } 1750511b41d2SMark Murray if (options->escape_char == -1) 1751511b41d2SMark Murray options->escape_char = '~'; 1752e146993eSDag-Erling Smørgrav if (options->num_system_hostfiles == 0) { 1753e146993eSDag-Erling Smørgrav options->system_hostfiles[options->num_system_hostfiles++] = 1754e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1755e146993eSDag-Erling Smørgrav options->system_hostfiles[options->num_system_hostfiles++] = 1756e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1757e146993eSDag-Erling Smørgrav } 1758e146993eSDag-Erling Smørgrav if (options->num_user_hostfiles == 0) { 1759e146993eSDag-Erling Smørgrav options->user_hostfiles[options->num_user_hostfiles++] = 1760e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_USER_HOSTFILE); 1761e146993eSDag-Erling Smørgrav options->user_hostfiles[options->num_user_hostfiles++] = 1762e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_USER_HOSTFILE2); 1763e146993eSDag-Erling Smørgrav } 1764af12a3e7SDag-Erling Smørgrav if (options->log_level == SYSLOG_LEVEL_NOT_SET) 1765511b41d2SMark Murray options->log_level = SYSLOG_LEVEL_INFO; 1766af12a3e7SDag-Erling Smørgrav if (options->clear_forwardings == 1) 1767af12a3e7SDag-Erling Smørgrav clear_forwardings(options); 1768af12a3e7SDag-Erling Smørgrav if (options->no_host_authentication_for_localhost == - 1) 1769af12a3e7SDag-Erling Smørgrav options->no_host_authentication_for_localhost = 0; 17705962c0e9SDag-Erling Smørgrav if (options->identities_only == -1) 17715962c0e9SDag-Erling Smørgrav options->identities_only = 0; 1772e73e9afaSDag-Erling Smørgrav if (options->enable_ssh_keysign == -1) 1773e73e9afaSDag-Erling Smørgrav options->enable_ssh_keysign = 0; 1774cf2b5f3bSDag-Erling Smørgrav if (options->rekey_limit == -1) 1775cf2b5f3bSDag-Erling Smørgrav options->rekey_limit = 0; 1776e4a9863fSDag-Erling Smørgrav if (options->rekey_interval == -1) 1777e4a9863fSDag-Erling Smørgrav options->rekey_interval = 0; 177883c6a524SDag-Erling Smørgrav #if HAVE_LDNS 177983c6a524SDag-Erling Smørgrav if (options->verify_host_key_dns == -1) 178083c6a524SDag-Erling Smørgrav /* automatically trust a verified SSHFP record */ 178183c6a524SDag-Erling Smørgrav options->verify_host_key_dns = 1; 178283c6a524SDag-Erling Smørgrav #else 1783cf2b5f3bSDag-Erling Smørgrav if (options->verify_host_key_dns == -1) 1784cf2b5f3bSDag-Erling Smørgrav options->verify_host_key_dns = 0; 178583c6a524SDag-Erling Smørgrav #endif 17861ec0d754SDag-Erling Smørgrav if (options->server_alive_interval == -1) 17871ec0d754SDag-Erling Smørgrav options->server_alive_interval = 0; 17881ec0d754SDag-Erling Smørgrav if (options->server_alive_count_max == -1) 17891ec0d754SDag-Erling Smørgrav options->server_alive_count_max = 3; 179021e764dfSDag-Erling Smørgrav if (options->control_master == -1) 179121e764dfSDag-Erling Smørgrav options->control_master = 0; 1792e2f6069cSDag-Erling Smørgrav if (options->control_persist == -1) { 1793e2f6069cSDag-Erling Smørgrav options->control_persist = 0; 1794e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = 0; 1795e2f6069cSDag-Erling Smørgrav } 1796aa49c926SDag-Erling Smørgrav if (options->hash_known_hosts == -1) 1797aa49c926SDag-Erling Smørgrav options->hash_known_hosts = 0; 1798b74df5b2SDag-Erling Smørgrav if (options->tun_open == -1) 1799b74df5b2SDag-Erling Smørgrav options->tun_open = SSH_TUNMODE_NO; 1800b74df5b2SDag-Erling Smørgrav if (options->tun_local == -1) 1801b74df5b2SDag-Erling Smørgrav options->tun_local = SSH_TUNID_ANY; 1802b74df5b2SDag-Erling Smørgrav if (options->tun_remote == -1) 1803b74df5b2SDag-Erling Smørgrav options->tun_remote = SSH_TUNID_ANY; 1804b74df5b2SDag-Erling Smørgrav if (options->permit_local_command == -1) 1805b74df5b2SDag-Erling Smørgrav options->permit_local_command = 0; 18067aee6ffeSDag-Erling Smørgrav if (options->use_roaming == -1) 18077aee6ffeSDag-Erling Smørgrav options->use_roaming = 1; 1808d4af9e69SDag-Erling Smørgrav if (options->visual_host_key == -1) 1809d4af9e69SDag-Erling Smørgrav options->visual_host_key = 0; 1810cce7d346SDag-Erling Smørgrav if (options->zero_knowledge_password_authentication == -1) 1811cce7d346SDag-Erling Smørgrav options->zero_knowledge_password_authentication = 0; 18124a421b63SDag-Erling Smørgrav if (options->ip_qos_interactive == -1) 18134a421b63SDag-Erling Smørgrav options->ip_qos_interactive = IPTOS_LOWDELAY; 18144a421b63SDag-Erling Smørgrav if (options->ip_qos_bulk == -1) 18154a421b63SDag-Erling Smørgrav options->ip_qos_bulk = IPTOS_THROUGHPUT; 1816e146993eSDag-Erling Smørgrav if (options->request_tty == -1) 1817e146993eSDag-Erling Smørgrav options->request_tty = REQUEST_TTY_AUTO; 1818*f7167e0eSDag-Erling Smørgrav if (options->proxy_use_fdpass == -1) 1819*f7167e0eSDag-Erling Smørgrav options->proxy_use_fdpass = 0; 1820*f7167e0eSDag-Erling Smørgrav if (options->canonicalize_max_dots == -1) 1821*f7167e0eSDag-Erling Smørgrav options->canonicalize_max_dots = 1; 1822*f7167e0eSDag-Erling Smørgrav if (options->canonicalize_fallback_local == -1) 1823*f7167e0eSDag-Erling Smørgrav options->canonicalize_fallback_local = 1; 1824*f7167e0eSDag-Erling Smørgrav if (options->canonicalize_hostname == -1) 1825*f7167e0eSDag-Erling Smørgrav options->canonicalize_hostname = SSH_CANONICALISE_NO; 1826*f7167e0eSDag-Erling Smørgrav #define CLEAR_ON_NONE(v) \ 1827*f7167e0eSDag-Erling Smørgrav do { \ 1828*f7167e0eSDag-Erling Smørgrav if (v != NULL && strcasecmp(v, "none") == 0) { \ 1829*f7167e0eSDag-Erling Smørgrav free(v); \ 1830*f7167e0eSDag-Erling Smørgrav v = NULL; \ 1831*f7167e0eSDag-Erling Smørgrav } \ 1832*f7167e0eSDag-Erling Smørgrav } while(0) 1833*f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->local_command); 1834*f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->proxy_command); 1835*f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->control_path); 1836511b41d2SMark Murray /* options->user will be set in the main program if appropriate */ 1837511b41d2SMark Murray /* options->hostname will be set in the main program if appropriate */ 1838ca3176e7SBrian Feldman /* options->host_key_alias should not be set by default */ 1839ca3176e7SBrian Feldman /* options->preferred_authentications will be set in ssh */ 1840462c32cbSDag-Erling Smørgrav if (options->version_addendum == NULL) 1841462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 184289986192SBrooks Davis if (options->hpn_disabled == -1) 184389986192SBrooks Davis options->hpn_disabled = 0; 184489986192SBrooks Davis if (options->hpn_buffer_size > -1) 184589986192SBrooks Davis { 184689986192SBrooks Davis u_int maxlen; 184789986192SBrooks Davis 184889986192SBrooks Davis /* If a user tries to set the size to 0 set it to 1KB. */ 184989986192SBrooks Davis if (options->hpn_buffer_size == 0) 185089986192SBrooks Davis options->hpn_buffer_size = 1024; 185189986192SBrooks Davis /* Limit the buffer to BUFFER_MAX_LEN. */ 185289986192SBrooks Davis maxlen = buffer_get_max_len(); 185389986192SBrooks Davis if (options->hpn_buffer_size > (maxlen / 1024)) { 185489986192SBrooks Davis debug("User requested buffer larger than %ub: %ub. " 185589986192SBrooks Davis "Request reverted to %ub", maxlen, 185689986192SBrooks Davis options->hpn_buffer_size * 1024, maxlen); 185789986192SBrooks Davis options->hpn_buffer_size = maxlen; 185889986192SBrooks Davis } 185989986192SBrooks Davis debug("hpn_buffer_size set to %d", options->hpn_buffer_size); 186089986192SBrooks Davis } 186189986192SBrooks Davis if (options->tcp_rcv_buf == 0) 186289986192SBrooks Davis options->tcp_rcv_buf = 1; 186389986192SBrooks Davis if (options->tcp_rcv_buf > -1) 186489986192SBrooks Davis options->tcp_rcv_buf *= 1024; 186589986192SBrooks Davis if (options->tcp_rcv_buf_poll == -1) 186689986192SBrooks Davis options->tcp_rcv_buf_poll = 1; 186789986192SBrooks Davis #ifdef NONE_CIPHER_ENABLED 186889986192SBrooks Davis /* options->none_enabled must not be set by default */ 186989986192SBrooks Davis if (options->none_switch == -1) 187089986192SBrooks Davis options->none_switch = 0; 187189986192SBrooks Davis #endif 1872511b41d2SMark Murray } 1873aa49c926SDag-Erling Smørgrav 1874aa49c926SDag-Erling Smørgrav /* 1875aa49c926SDag-Erling Smørgrav * parse_forward 1876aa49c926SDag-Erling Smørgrav * parses a string containing a port forwarding specification of the form: 1877cce7d346SDag-Erling Smørgrav * dynamicfwd == 0 1878aa49c926SDag-Erling Smørgrav * [listenhost:]listenport:connecthost:connectport 1879cce7d346SDag-Erling Smørgrav * dynamicfwd == 1 1880cce7d346SDag-Erling Smørgrav * [listenhost:]listenport 1881aa49c926SDag-Erling Smørgrav * returns number of arguments parsed or zero on error 1882aa49c926SDag-Erling Smørgrav */ 1883aa49c926SDag-Erling Smørgrav int 1884cce7d346SDag-Erling Smørgrav parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 1885aa49c926SDag-Erling Smørgrav { 1886aa49c926SDag-Erling Smørgrav int i; 1887aa49c926SDag-Erling Smørgrav char *p, *cp, *fwdarg[4]; 1888aa49c926SDag-Erling Smørgrav 1889aa49c926SDag-Erling Smørgrav memset(fwd, '\0', sizeof(*fwd)); 1890aa49c926SDag-Erling Smørgrav 1891aa49c926SDag-Erling Smørgrav cp = p = xstrdup(fwdspec); 1892aa49c926SDag-Erling Smørgrav 1893aa49c926SDag-Erling Smørgrav /* skip leading spaces */ 1894*f7167e0eSDag-Erling Smørgrav while (isspace((u_char)*cp)) 1895aa49c926SDag-Erling Smørgrav cp++; 1896aa49c926SDag-Erling Smørgrav 1897aa49c926SDag-Erling Smørgrav for (i = 0; i < 4; ++i) 1898aa49c926SDag-Erling Smørgrav if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1899aa49c926SDag-Erling Smørgrav break; 1900aa49c926SDag-Erling Smørgrav 1901cce7d346SDag-Erling Smørgrav /* Check for trailing garbage */ 1902aa49c926SDag-Erling Smørgrav if (cp != NULL) 1903aa49c926SDag-Erling Smørgrav i = 0; /* failure */ 1904aa49c926SDag-Erling Smørgrav 1905aa49c926SDag-Erling Smørgrav switch (i) { 1906cce7d346SDag-Erling Smørgrav case 1: 1907cce7d346SDag-Erling Smørgrav fwd->listen_host = NULL; 1908cce7d346SDag-Erling Smørgrav fwd->listen_port = a2port(fwdarg[0]); 1909cce7d346SDag-Erling Smørgrav fwd->connect_host = xstrdup("socks"); 1910cce7d346SDag-Erling Smørgrav break; 1911cce7d346SDag-Erling Smørgrav 1912cce7d346SDag-Erling Smørgrav case 2: 1913cce7d346SDag-Erling Smørgrav fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1914cce7d346SDag-Erling Smørgrav fwd->listen_port = a2port(fwdarg[1]); 1915cce7d346SDag-Erling Smørgrav fwd->connect_host = xstrdup("socks"); 1916cce7d346SDag-Erling Smørgrav break; 1917cce7d346SDag-Erling Smørgrav 1918aa49c926SDag-Erling Smørgrav case 3: 1919aa49c926SDag-Erling Smørgrav fwd->listen_host = NULL; 1920aa49c926SDag-Erling Smørgrav fwd->listen_port = a2port(fwdarg[0]); 1921aa49c926SDag-Erling Smørgrav fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1922aa49c926SDag-Erling Smørgrav fwd->connect_port = a2port(fwdarg[2]); 1923aa49c926SDag-Erling Smørgrav break; 1924aa49c926SDag-Erling Smørgrav 1925aa49c926SDag-Erling Smørgrav case 4: 1926aa49c926SDag-Erling Smørgrav fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1927aa49c926SDag-Erling Smørgrav fwd->listen_port = a2port(fwdarg[1]); 1928aa49c926SDag-Erling Smørgrav fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1929aa49c926SDag-Erling Smørgrav fwd->connect_port = a2port(fwdarg[3]); 1930aa49c926SDag-Erling Smørgrav break; 1931aa49c926SDag-Erling Smørgrav default: 1932aa49c926SDag-Erling Smørgrav i = 0; /* failure */ 1933aa49c926SDag-Erling Smørgrav } 1934aa49c926SDag-Erling Smørgrav 1935e4a9863fSDag-Erling Smørgrav free(p); 1936aa49c926SDag-Erling Smørgrav 1937cce7d346SDag-Erling Smørgrav if (dynamicfwd) { 1938cce7d346SDag-Erling Smørgrav if (!(i == 1 || i == 2)) 1939cce7d346SDag-Erling Smørgrav goto fail_free; 1940cce7d346SDag-Erling Smørgrav } else { 1941cce7d346SDag-Erling Smørgrav if (!(i == 3 || i == 4)) 1942cce7d346SDag-Erling Smørgrav goto fail_free; 1943cce7d346SDag-Erling Smørgrav if (fwd->connect_port <= 0) 1944cce7d346SDag-Erling Smørgrav goto fail_free; 1945cce7d346SDag-Erling Smørgrav } 1946cce7d346SDag-Erling Smørgrav 1947cce7d346SDag-Erling Smørgrav if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 1948aa49c926SDag-Erling Smørgrav goto fail_free; 1949aa49c926SDag-Erling Smørgrav 1950aa49c926SDag-Erling Smørgrav if (fwd->connect_host != NULL && 1951aa49c926SDag-Erling Smørgrav strlen(fwd->connect_host) >= NI_MAXHOST) 1952aa49c926SDag-Erling Smørgrav goto fail_free; 1953cce7d346SDag-Erling Smørgrav if (fwd->listen_host != NULL && 1954cce7d346SDag-Erling Smørgrav strlen(fwd->listen_host) >= NI_MAXHOST) 1955cce7d346SDag-Erling Smørgrav goto fail_free; 1956cce7d346SDag-Erling Smørgrav 1957aa49c926SDag-Erling Smørgrav 1958aa49c926SDag-Erling Smørgrav return (i); 1959aa49c926SDag-Erling Smørgrav 1960aa49c926SDag-Erling Smørgrav fail_free: 1961e4a9863fSDag-Erling Smørgrav free(fwd->connect_host); 1962cce7d346SDag-Erling Smørgrav fwd->connect_host = NULL; 1963e4a9863fSDag-Erling Smørgrav free(fwd->listen_host); 1964cce7d346SDag-Erling Smørgrav fwd->listen_host = NULL; 1965aa49c926SDag-Erling Smørgrav return (0); 1966aa49c926SDag-Erling Smørgrav } 1967