1*acc1a9efSDag-Erling Smørgrav /* $OpenBSD: readconf.c,v 1.250 2016/02/08 23:40:12 djm Exp $ */ 2511b41d2SMark Murray /* 3511b41d2SMark Murray * Author: Tatu Ylonen <ylo@cs.hut.fi> 4511b41d2SMark Murray * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5511b41d2SMark Murray * All rights reserved 6511b41d2SMark Murray * Functions for reading the configuration files. 7511b41d2SMark Murray * 8c2d3a559SKris Kennaway * As far as I am concerned, the code I have written for this software 9c2d3a559SKris Kennaway * can be used freely for any purpose. Any derived versions of this 10c2d3a559SKris Kennaway * software must be clearly marked as such, and if the derived work is 11c2d3a559SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 12c2d3a559SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 13511b41d2SMark Murray */ 14511b41d2SMark Murray 15511b41d2SMark Murray #include "includes.h" 16333ee039SDag-Erling Smørgrav __RCSID("$FreeBSD$"); 17511b41d2SMark Murray 18333ee039SDag-Erling Smørgrav #include <sys/types.h> 19333ee039SDag-Erling Smørgrav #include <sys/stat.h> 20333ee039SDag-Erling Smørgrav #include <sys/socket.h> 2103f6c5cdSDag-Erling Smørgrav #include <sys/sysctl.h> 22f7167e0eSDag-Erling Smørgrav #include <sys/wait.h> 23a0ee8cc6SDag-Erling Smørgrav #include <sys/un.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> 28b83788ffSDag-Erling Smørgrav #include <arpa/inet.h> 29333ee039SDag-Erling Smørgrav 30333ee039SDag-Erling Smørgrav #include <ctype.h> 31333ee039SDag-Erling Smørgrav #include <errno.h> 32f7167e0eSDag-Erling Smørgrav #include <fcntl.h> 33bc5531deSDag-Erling Smørgrav #include <limits.h> 34333ee039SDag-Erling Smørgrav #include <netdb.h> 35f7167e0eSDag-Erling Smørgrav #ifdef HAVE_PATHS_H 36f7167e0eSDag-Erling Smørgrav # include <paths.h> 37f7167e0eSDag-Erling Smørgrav #endif 38f7167e0eSDag-Erling Smørgrav #include <pwd.h> 39333ee039SDag-Erling Smørgrav #include <signal.h> 40333ee039SDag-Erling Smørgrav #include <stdarg.h> 41333ee039SDag-Erling Smørgrav #include <stdio.h> 42333ee039SDag-Erling Smørgrav #include <string.h> 43333ee039SDag-Erling Smørgrav #include <unistd.h> 44e4a9863fSDag-Erling Smørgrav #ifdef HAVE_UTIL_H 45e4a9863fSDag-Erling Smørgrav #include <util.h> 46e4a9863fSDag-Erling Smørgrav #endif 47bc5531deSDag-Erling Smørgrav #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 48bc5531deSDag-Erling Smørgrav # include <vis.h> 49bc5531deSDag-Erling Smørgrav #endif 50333ee039SDag-Erling Smørgrav 51511b41d2SMark Murray #include "xmalloc.h" 52333ee039SDag-Erling Smørgrav #include "ssh.h" 53e8aafc91SKris Kennaway #include "compat.h" 54ca3176e7SBrian Feldman #include "cipher.h" 55ca3176e7SBrian Feldman #include "pathnames.h" 56ca3176e7SBrian Feldman #include "log.h" 57bc5531deSDag-Erling Smørgrav #include "sshkey.h" 58a0ee8cc6SDag-Erling Smørgrav #include "misc.h" 59ca3176e7SBrian Feldman #include "readconf.h" 60ca3176e7SBrian Feldman #include "match.h" 61ca3176e7SBrian Feldman #include "kex.h" 62ca3176e7SBrian Feldman #include "mac.h" 63f7167e0eSDag-Erling Smørgrav #include "uidswap.h" 64bc5531deSDag-Erling Smørgrav #include "myproposal.h" 65bc5531deSDag-Erling Smørgrav #include "digest.h" 66cce7d346SDag-Erling Smørgrav #include "version.h" 67511b41d2SMark Murray 68511b41d2SMark Murray /* Format of the configuration file: 69511b41d2SMark Murray 70511b41d2SMark Murray # Configuration data is parsed as follows: 71511b41d2SMark Murray # 1. command line options 72511b41d2SMark Murray # 2. user-specific file 73511b41d2SMark Murray # 3. system-wide file 74511b41d2SMark Murray # Any configuration value is only changed the first time it is set. 75511b41d2SMark Murray # Thus, host-specific definitions should be at the beginning of the 76511b41d2SMark Murray # configuration file, and defaults at the end. 77511b41d2SMark Murray 78511b41d2SMark Murray # Host-specific declarations. These may override anything above. A single 79511b41d2SMark Murray # host may match multiple declarations; these are processed in the order 80511b41d2SMark Murray # that they are given in. 81511b41d2SMark Murray 82511b41d2SMark Murray Host *.ngs.fi ngs.fi 8380628bacSDag-Erling Smørgrav User foo 84511b41d2SMark Murray 85511b41d2SMark Murray Host fake.com 86511b41d2SMark Murray HostName another.host.name.real.org 87511b41d2SMark Murray User blaah 88511b41d2SMark Murray Port 34289 89511b41d2SMark Murray ForwardX11 no 90511b41d2SMark Murray ForwardAgent no 91511b41d2SMark Murray 92511b41d2SMark Murray Host books.com 93511b41d2SMark Murray RemoteForward 9999 shadows.cs.hut.fi:9999 94511b41d2SMark Murray Cipher 3des 95511b41d2SMark Murray 96511b41d2SMark Murray Host fascist.blob.com 97511b41d2SMark Murray Port 23123 98511b41d2SMark Murray User tylonen 99511b41d2SMark Murray PasswordAuthentication no 100511b41d2SMark Murray 101511b41d2SMark Murray Host puukko.hut.fi 102511b41d2SMark Murray User t35124p 103511b41d2SMark Murray ProxyCommand ssh-proxy %h %p 104511b41d2SMark Murray 105511b41d2SMark Murray Host *.fr 10680628bacSDag-Erling Smørgrav PublicKeyAuthentication no 107511b41d2SMark Murray 108511b41d2SMark Murray Host *.su 109511b41d2SMark Murray Cipher none 110511b41d2SMark Murray PasswordAuthentication no 111511b41d2SMark Murray 112b74df5b2SDag-Erling Smørgrav Host vpn.fake.com 113b74df5b2SDag-Erling Smørgrav Tunnel yes 114b74df5b2SDag-Erling Smørgrav TunnelDevice 3 115b74df5b2SDag-Erling Smørgrav 116511b41d2SMark Murray # Defaults for various options 117511b41d2SMark Murray Host * 118511b41d2SMark Murray ForwardAgent no 119ca3176e7SBrian Feldman ForwardX11 no 120511b41d2SMark Murray PasswordAuthentication yes 121511b41d2SMark Murray RSAAuthentication yes 122511b41d2SMark Murray RhostsRSAAuthentication yes 123511b41d2SMark Murray StrictHostKeyChecking yes 1241ec0d754SDag-Erling Smørgrav TcpKeepAlive no 125511b41d2SMark Murray IdentityFile ~/.ssh/identity 126511b41d2SMark Murray Port 22 127511b41d2SMark Murray EscapeChar ~ 128511b41d2SMark Murray 129511b41d2SMark Murray */ 130511b41d2SMark Murray 131511b41d2SMark Murray /* Keyword tokens. */ 132511b41d2SMark Murray 133511b41d2SMark Murray typedef enum { 134511b41d2SMark Murray oBadOption, 135eccfee6eSDag-Erling Smørgrav oVersionAddendum, 136f7167e0eSDag-Erling Smørgrav oHost, oMatch, 137e2f6069cSDag-Erling Smørgrav oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 138e2f6069cSDag-Erling Smørgrav oGatewayPorts, oExitOnForwardFailure, 13980628bacSDag-Erling Smørgrav oPasswordAuthentication, oRSAAuthentication, 140ca3176e7SBrian Feldman oChallengeResponseAuthentication, oXAuthLocation, 141511b41d2SMark Murray oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 142*acc1a9efSDag-Erling Smørgrav oCertificateFile, oAddKeysToAgent, 143f7167e0eSDag-Erling Smørgrav oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 144511b41d2SMark Murray oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 145511b41d2SMark Murray oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 1461ec0d754SDag-Erling Smørgrav oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 147ca3176e7SBrian Feldman oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 148bc5531deSDag-Erling Smørgrav oPubkeyAuthentication, 149ca3176e7SBrian Feldman oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 150ca3176e7SBrian Feldman oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 151b15c8340SDag-Erling Smørgrav oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, 1529e2cbe04SDag-Erling Smørgrav oClearAllForwardings, oNoHostAuthenticationForLocalhost, 153cf2b5f3bSDag-Erling Smørgrav oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 154cf2b5f3bSDag-Erling Smørgrav oAddressFamily, oGssAuthentication, oGssDelegateCreds, 1555962c0e9SDag-Erling Smørgrav oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 156e2f6069cSDag-Erling Smørgrav oSendEnv, oControlPath, oControlMaster, oControlPersist, 157e2f6069cSDag-Erling Smørgrav oHashKnownHosts, 158b74df5b2SDag-Erling Smørgrav oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 159*acc1a9efSDag-Erling Smørgrav oVisualHostKey, 160f7167e0eSDag-Erling Smørgrav oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 161f7167e0eSDag-Erling Smørgrav oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 162f7167e0eSDag-Erling Smørgrav oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 163bc5531deSDag-Erling Smørgrav oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 164bc5531deSDag-Erling Smørgrav oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, 165eccfee6eSDag-Erling Smørgrav oPubkeyAcceptedKeyTypes, 16660c59fadSDag-Erling Smørgrav oIgnoredUnknownOption, oDeprecated, oUnsupported 167511b41d2SMark Murray } OpCodes; 168511b41d2SMark Murray 169511b41d2SMark Murray /* Textual representations of the tokens. */ 170511b41d2SMark Murray 171511b41d2SMark Murray static struct { 172511b41d2SMark Murray const char *name; 173511b41d2SMark Murray OpCodes opcode; 174511b41d2SMark Murray } keywords[] = { 175511b41d2SMark Murray { "forwardagent", oForwardAgent }, 176511b41d2SMark Murray { "forwardx11", oForwardX11 }, 1771ec0d754SDag-Erling Smørgrav { "forwardx11trusted", oForwardX11Trusted }, 178e2f6069cSDag-Erling Smørgrav { "forwardx11timeout", oForwardX11Timeout }, 179333ee039SDag-Erling Smørgrav { "exitonforwardfailure", oExitOnForwardFailure }, 180c2d3a559SKris Kennaway { "xauthlocation", oXAuthLocation }, 181511b41d2SMark Murray { "gatewayports", oGatewayPorts }, 182511b41d2SMark Murray { "useprivilegedport", oUsePrivilegedPort }, 183cf2b5f3bSDag-Erling Smørgrav { "rhostsauthentication", oDeprecated }, 184511b41d2SMark Murray { "passwordauthentication", oPasswordAuthentication }, 18509958426SBrian Feldman { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 18609958426SBrian Feldman { "kbdinteractivedevices", oKbdInteractiveDevices }, 187511b41d2SMark Murray { "rsaauthentication", oRSAAuthentication }, 188ca3176e7SBrian Feldman { "pubkeyauthentication", oPubkeyAuthentication }, 189ca3176e7SBrian Feldman { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 190ca3176e7SBrian Feldman { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 191ca3176e7SBrian Feldman { "hostbasedauthentication", oHostbasedAuthentication }, 192ca3176e7SBrian Feldman { "challengeresponseauthentication", oChallengeResponseAuthentication }, 193ca3176e7SBrian Feldman { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 194ca3176e7SBrian Feldman { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 195cf2b5f3bSDag-Erling Smørgrav { "kerberosauthentication", oUnsupported }, 196cf2b5f3bSDag-Erling Smørgrav { "kerberostgtpassing", oUnsupported }, 197cf2b5f3bSDag-Erling Smørgrav { "afstokenpassing", oUnsupported }, 198cf2b5f3bSDag-Erling Smørgrav #if defined(GSSAPI) 199cf2b5f3bSDag-Erling Smørgrav { "gssapiauthentication", oGssAuthentication }, 200cf2b5f3bSDag-Erling Smørgrav { "gssapidelegatecredentials", oGssDelegateCreds }, 201cf2b5f3bSDag-Erling Smørgrav #else 202cf2b5f3bSDag-Erling Smørgrav { "gssapiauthentication", oUnsupported }, 203cf2b5f3bSDag-Erling Smørgrav { "gssapidelegatecredentials", oUnsupported }, 204511b41d2SMark Murray #endif 20580628bacSDag-Erling Smørgrav { "fallbacktorsh", oDeprecated }, 20680628bacSDag-Erling Smørgrav { "usersh", oDeprecated }, 207511b41d2SMark Murray { "identityfile", oIdentityFile }, 208cce7d346SDag-Erling Smørgrav { "identityfile2", oIdentityFile }, /* obsolete */ 2095962c0e9SDag-Erling Smørgrav { "identitiesonly", oIdentitiesOnly }, 210*acc1a9efSDag-Erling Smørgrav { "certificatefile", oCertificateFile }, 211*acc1a9efSDag-Erling Smørgrav { "addkeystoagent", oAddKeysToAgent }, 212511b41d2SMark Murray { "hostname", oHostName }, 213ca3176e7SBrian Feldman { "hostkeyalias", oHostKeyAlias }, 214511b41d2SMark Murray { "proxycommand", oProxyCommand }, 215511b41d2SMark Murray { "port", oPort }, 216511b41d2SMark Murray { "cipher", oCipher }, 217e8aafc91SKris Kennaway { "ciphers", oCiphers }, 218ca3176e7SBrian Feldman { "macs", oMacs }, 219e8aafc91SKris Kennaway { "protocol", oProtocol }, 220511b41d2SMark Murray { "remoteforward", oRemoteForward }, 221511b41d2SMark Murray { "localforward", oLocalForward }, 222511b41d2SMark Murray { "user", oUser }, 223511b41d2SMark Murray { "host", oHost }, 224f7167e0eSDag-Erling Smørgrav { "match", oMatch }, 225511b41d2SMark Murray { "escapechar", oEscapeChar }, 226511b41d2SMark Murray { "globalknownhostsfile", oGlobalKnownHostsFile }, 227e146993eSDag-Erling Smørgrav { "globalknownhostsfile2", oDeprecated }, 228cce7d346SDag-Erling Smørgrav { "userknownhostsfile", oUserKnownHostsFile }, 229e146993eSDag-Erling Smørgrav { "userknownhostsfile2", oDeprecated }, 230511b41d2SMark Murray { "connectionattempts", oConnectionAttempts }, 231511b41d2SMark Murray { "batchmode", oBatchMode }, 232511b41d2SMark Murray { "checkhostip", oCheckHostIP }, 233511b41d2SMark Murray { "stricthostkeychecking", oStrictHostKeyChecking }, 234511b41d2SMark Murray { "compression", oCompression }, 235511b41d2SMark Murray { "compressionlevel", oCompressionLevel }, 2361ec0d754SDag-Erling Smørgrav { "tcpkeepalive", oTCPKeepAlive }, 2371ec0d754SDag-Erling Smørgrav { "keepalive", oTCPKeepAlive }, /* obsolete */ 238511b41d2SMark Murray { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 239511b41d2SMark Murray { "loglevel", oLogLevel }, 240ca3176e7SBrian Feldman { "dynamicforward", oDynamicForward }, 241ca3176e7SBrian Feldman { "preferredauthentications", oPreferredAuthentications }, 242ca3176e7SBrian Feldman { "hostkeyalgorithms", oHostKeyAlgorithms }, 243af12a3e7SDag-Erling Smørgrav { "bindaddress", oBindAddress }, 244b15c8340SDag-Erling Smørgrav #ifdef ENABLE_PKCS11 245b15c8340SDag-Erling Smørgrav { "smartcarddevice", oPKCS11Provider }, 246b15c8340SDag-Erling Smørgrav { "pkcs11provider", oPKCS11Provider }, 247cf2b5f3bSDag-Erling Smørgrav #else 248cf2b5f3bSDag-Erling Smørgrav { "smartcarddevice", oUnsupported }, 249b15c8340SDag-Erling Smørgrav { "pkcs11provider", oUnsupported }, 250cf2b5f3bSDag-Erling Smørgrav #endif 251af12a3e7SDag-Erling Smørgrav { "clearallforwardings", oClearAllForwardings }, 252e73e9afaSDag-Erling Smørgrav { "enablesshkeysign", oEnableSSHKeysign }, 253cf2b5f3bSDag-Erling Smørgrav { "verifyhostkeydns", oVerifyHostKeyDNS }, 254af12a3e7SDag-Erling Smørgrav { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 255cf2b5f3bSDag-Erling Smørgrav { "rekeylimit", oRekeyLimit }, 256cf2b5f3bSDag-Erling Smørgrav { "connecttimeout", oConnectTimeout }, 257cf2b5f3bSDag-Erling Smørgrav { "addressfamily", oAddressFamily }, 2581ec0d754SDag-Erling Smørgrav { "serveraliveinterval", oServerAliveInterval }, 2591ec0d754SDag-Erling Smørgrav { "serveralivecountmax", oServerAliveCountMax }, 26021e764dfSDag-Erling Smørgrav { "sendenv", oSendEnv }, 26121e764dfSDag-Erling Smørgrav { "controlpath", oControlPath }, 26221e764dfSDag-Erling Smørgrav { "controlmaster", oControlMaster }, 263e2f6069cSDag-Erling Smørgrav { "controlpersist", oControlPersist }, 264aa49c926SDag-Erling Smørgrav { "hashknownhosts", oHashKnownHosts }, 265b74df5b2SDag-Erling Smørgrav { "tunnel", oTunnel }, 266b74df5b2SDag-Erling Smørgrav { "tunneldevice", oTunnelDevice }, 267b74df5b2SDag-Erling Smørgrav { "localcommand", oLocalCommand }, 268b74df5b2SDag-Erling Smørgrav { "permitlocalcommand", oPermitLocalCommand }, 269d4af9e69SDag-Erling Smørgrav { "visualhostkey", oVisualHostKey }, 270*acc1a9efSDag-Erling Smørgrav { "useroaming", oDeprecated }, 2714a421b63SDag-Erling Smørgrav { "kexalgorithms", oKexAlgorithms }, 2724a421b63SDag-Erling Smørgrav { "ipqos", oIPQoS }, 273e146993eSDag-Erling Smørgrav { "requesttty", oRequestTTY }, 274f7167e0eSDag-Erling Smørgrav { "proxyusefdpass", oProxyUseFdpass }, 275f7167e0eSDag-Erling Smørgrav { "canonicaldomains", oCanonicalDomains }, 276f7167e0eSDag-Erling Smørgrav { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 277f7167e0eSDag-Erling Smørgrav { "canonicalizehostname", oCanonicalizeHostname }, 278f7167e0eSDag-Erling Smørgrav { "canonicalizemaxdots", oCanonicalizeMaxDots }, 279f7167e0eSDag-Erling Smørgrav { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 280a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindmask", oStreamLocalBindMask }, 281a0ee8cc6SDag-Erling Smørgrav { "streamlocalbindunlink", oStreamLocalBindUnlink }, 282bc5531deSDag-Erling Smørgrav { "revokedhostkeys", oRevokedHostKeys }, 283bc5531deSDag-Erling Smørgrav { "fingerprinthash", oFingerprintHash }, 284bc5531deSDag-Erling Smørgrav { "updatehostkeys", oUpdateHostkeys }, 285bc5531deSDag-Erling Smørgrav { "hostbasedkeytypes", oHostbasedKeyTypes }, 286eccfee6eSDag-Erling Smørgrav { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, 287e4a9863fSDag-Erling Smørgrav { "ignoreunknown", oIgnoreUnknown }, 2889860d96eSDag-Erling Smørgrav { "hpndisabled", oDeprecated }, 2899860d96eSDag-Erling Smørgrav { "hpnbuffersize", oDeprecated }, 2909860d96eSDag-Erling Smørgrav { "tcprcvbufpoll", oDeprecated }, 2919860d96eSDag-Erling Smørgrav { "tcprcvbuf", oDeprecated }, 29263620802SDag-Erling Smørgrav { "noneenabled", oUnsupported }, 29363620802SDag-Erling Smørgrav { "noneswitch", oUnsupported }, 294975616f0SDag-Erling Smørgrav { "versionaddendum", oVersionAddendum }, 29535762f59SEd Schouten 296af12a3e7SDag-Erling Smørgrav { NULL, oBadOption } 297511b41d2SMark Murray }; 298511b41d2SMark Murray 299511b41d2SMark Murray /* 300511b41d2SMark Murray * Adds a local TCP/IP port forward to options. Never returns if there is an 301511b41d2SMark Murray * error. 302511b41d2SMark Murray */ 303511b41d2SMark Murray 304511b41d2SMark Murray void 305a0ee8cc6SDag-Erling Smørgrav add_local_forward(Options *options, const struct Forward *newfwd) 306511b41d2SMark Murray { 307a0ee8cc6SDag-Erling Smørgrav struct Forward *fwd; 308f388f5efSDag-Erling Smørgrav #ifndef NO_IPPORT_RESERVED_CONCEPT 309511b41d2SMark Murray extern uid_t original_real_uid; 31003f6c5cdSDag-Erling Smørgrav int ipport_reserved; 31103f6c5cdSDag-Erling Smørgrav #ifdef __FreeBSD__ 31203f6c5cdSDag-Erling Smørgrav size_t len_ipport_reserved = sizeof(ipport_reserved); 31303f6c5cdSDag-Erling Smørgrav 31403f6c5cdSDag-Erling Smørgrav if (sysctlbyname("net.inet.ip.portrange.reservedhigh", 31503f6c5cdSDag-Erling Smørgrav &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0) 31603f6c5cdSDag-Erling Smørgrav ipport_reserved = IPPORT_RESERVED; 31703f6c5cdSDag-Erling Smørgrav else 31803f6c5cdSDag-Erling Smørgrav ipport_reserved++; 31903f6c5cdSDag-Erling Smørgrav #else 32003f6c5cdSDag-Erling Smørgrav ipport_reserved = IPPORT_RESERVED; 32103f6c5cdSDag-Erling Smørgrav #endif 32203f6c5cdSDag-Erling Smørgrav if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) 323a0ee8cc6SDag-Erling Smørgrav if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 && 324a0ee8cc6SDag-Erling Smørgrav newfwd->listen_path == NULL) 325ca3176e7SBrian Feldman fatal("Privileged ports can only be forwarded by root."); 326989dd127SDag-Erling Smørgrav #endif 327557f75e5SDag-Erling Smørgrav options->local_forwards = xreallocarray(options->local_forwards, 328e2f6069cSDag-Erling Smørgrav options->num_local_forwards + 1, 329e2f6069cSDag-Erling Smørgrav sizeof(*options->local_forwards)); 330511b41d2SMark Murray fwd = &options->local_forwards[options->num_local_forwards++]; 331aa49c926SDag-Erling Smørgrav 332cce7d346SDag-Erling Smørgrav fwd->listen_host = newfwd->listen_host; 333aa49c926SDag-Erling Smørgrav fwd->listen_port = newfwd->listen_port; 334a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = newfwd->listen_path; 335cce7d346SDag-Erling Smørgrav fwd->connect_host = newfwd->connect_host; 336aa49c926SDag-Erling Smørgrav fwd->connect_port = newfwd->connect_port; 337a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = newfwd->connect_path; 338511b41d2SMark Murray } 339511b41d2SMark Murray 340511b41d2SMark Murray /* 341511b41d2SMark Murray * Adds a remote TCP/IP port forward to options. Never returns if there is 342511b41d2SMark Murray * an error. 343511b41d2SMark Murray */ 344511b41d2SMark Murray 345511b41d2SMark Murray void 346a0ee8cc6SDag-Erling Smørgrav add_remote_forward(Options *options, const struct Forward *newfwd) 347511b41d2SMark Murray { 348a0ee8cc6SDag-Erling Smørgrav struct Forward *fwd; 349e2f6069cSDag-Erling Smørgrav 350557f75e5SDag-Erling Smørgrav options->remote_forwards = xreallocarray(options->remote_forwards, 351e2f6069cSDag-Erling Smørgrav options->num_remote_forwards + 1, 352e2f6069cSDag-Erling Smørgrav sizeof(*options->remote_forwards)); 353511b41d2SMark Murray fwd = &options->remote_forwards[options->num_remote_forwards++]; 354aa49c926SDag-Erling Smørgrav 355cce7d346SDag-Erling Smørgrav fwd->listen_host = newfwd->listen_host; 356aa49c926SDag-Erling Smørgrav fwd->listen_port = newfwd->listen_port; 357a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = newfwd->listen_path; 358cce7d346SDag-Erling Smørgrav fwd->connect_host = newfwd->connect_host; 359aa49c926SDag-Erling Smørgrav fwd->connect_port = newfwd->connect_port; 360a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = newfwd->connect_path; 361462c32cbSDag-Erling Smørgrav fwd->handle = newfwd->handle; 362e2f6069cSDag-Erling Smørgrav fwd->allocated_port = 0; 363511b41d2SMark Murray } 364511b41d2SMark Murray 365af12a3e7SDag-Erling Smørgrav static void 366af12a3e7SDag-Erling Smørgrav clear_forwardings(Options *options) 367af12a3e7SDag-Erling Smørgrav { 368af12a3e7SDag-Erling Smørgrav int i; 369af12a3e7SDag-Erling Smørgrav 370aa49c926SDag-Erling Smørgrav for (i = 0; i < options->num_local_forwards; i++) { 371e4a9863fSDag-Erling Smørgrav free(options->local_forwards[i].listen_host); 372a0ee8cc6SDag-Erling Smørgrav free(options->local_forwards[i].listen_path); 373e4a9863fSDag-Erling Smørgrav free(options->local_forwards[i].connect_host); 374a0ee8cc6SDag-Erling Smørgrav free(options->local_forwards[i].connect_path); 375aa49c926SDag-Erling Smørgrav } 376e2f6069cSDag-Erling Smørgrav if (options->num_local_forwards > 0) { 377e4a9863fSDag-Erling Smørgrav free(options->local_forwards); 378e2f6069cSDag-Erling Smørgrav options->local_forwards = NULL; 379e2f6069cSDag-Erling Smørgrav } 380af12a3e7SDag-Erling Smørgrav options->num_local_forwards = 0; 381aa49c926SDag-Erling Smørgrav for (i = 0; i < options->num_remote_forwards; i++) { 382e4a9863fSDag-Erling Smørgrav free(options->remote_forwards[i].listen_host); 383a0ee8cc6SDag-Erling Smørgrav free(options->remote_forwards[i].listen_path); 384e4a9863fSDag-Erling Smørgrav free(options->remote_forwards[i].connect_host); 385a0ee8cc6SDag-Erling Smørgrav free(options->remote_forwards[i].connect_path); 386aa49c926SDag-Erling Smørgrav } 387e2f6069cSDag-Erling Smørgrav if (options->num_remote_forwards > 0) { 388e4a9863fSDag-Erling Smørgrav free(options->remote_forwards); 389e2f6069cSDag-Erling Smørgrav options->remote_forwards = NULL; 390e2f6069cSDag-Erling Smørgrav } 391af12a3e7SDag-Erling Smørgrav options->num_remote_forwards = 0; 392b74df5b2SDag-Erling Smørgrav options->tun_open = SSH_TUNMODE_NO; 393af12a3e7SDag-Erling Smørgrav } 394af12a3e7SDag-Erling Smørgrav 395fa67e83cSDag-Erling Smørgrav void 396*acc1a9efSDag-Erling Smørgrav add_certificate_file(Options *options, const char *path, int userprovided) 397*acc1a9efSDag-Erling Smørgrav { 398*acc1a9efSDag-Erling Smørgrav int i; 399*acc1a9efSDag-Erling Smørgrav 400*acc1a9efSDag-Erling Smørgrav if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 401*acc1a9efSDag-Erling Smørgrav fatal("Too many certificate files specified (max %d)", 402*acc1a9efSDag-Erling Smørgrav SSH_MAX_CERTIFICATE_FILES); 403*acc1a9efSDag-Erling Smørgrav 404*acc1a9efSDag-Erling Smørgrav /* Avoid registering duplicates */ 405*acc1a9efSDag-Erling Smørgrav for (i = 0; i < options->num_certificate_files; i++) { 406*acc1a9efSDag-Erling Smørgrav if (options->certificate_file_userprovided[i] == userprovided && 407*acc1a9efSDag-Erling Smørgrav strcmp(options->certificate_files[i], path) == 0) { 408*acc1a9efSDag-Erling Smørgrav debug2("%s: ignoring duplicate key %s", __func__, path); 409*acc1a9efSDag-Erling Smørgrav return; 410*acc1a9efSDag-Erling Smørgrav } 411*acc1a9efSDag-Erling Smørgrav } 412*acc1a9efSDag-Erling Smørgrav 413*acc1a9efSDag-Erling Smørgrav options->certificate_file_userprovided[options->num_certificate_files] = 414*acc1a9efSDag-Erling Smørgrav userprovided; 415*acc1a9efSDag-Erling Smørgrav options->certificate_files[options->num_certificate_files++] = 416*acc1a9efSDag-Erling Smørgrav xstrdup(path); 417*acc1a9efSDag-Erling Smørgrav } 418*acc1a9efSDag-Erling Smørgrav 419*acc1a9efSDag-Erling Smørgrav void 420fa67e83cSDag-Erling Smørgrav add_identity_file(Options *options, const char *dir, const char *filename, 421fa67e83cSDag-Erling Smørgrav int userprovided) 422fa67e83cSDag-Erling Smørgrav { 423fa67e83cSDag-Erling Smørgrav char *path; 424a0ee8cc6SDag-Erling Smørgrav int i; 425fa67e83cSDag-Erling Smørgrav 426fa67e83cSDag-Erling Smørgrav if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 427fa67e83cSDag-Erling Smørgrav fatal("Too many identity files specified (max %d)", 428fa67e83cSDag-Erling Smørgrav SSH_MAX_IDENTITY_FILES); 429fa67e83cSDag-Erling Smørgrav 430fa67e83cSDag-Erling Smørgrav if (dir == NULL) /* no dir, filename is absolute */ 431fa67e83cSDag-Erling Smørgrav path = xstrdup(filename); 432fa67e83cSDag-Erling Smørgrav else 433fa67e83cSDag-Erling Smørgrav (void)xasprintf(&path, "%.100s%.100s", dir, filename); 434fa67e83cSDag-Erling Smørgrav 435a0ee8cc6SDag-Erling Smørgrav /* Avoid registering duplicates */ 436a0ee8cc6SDag-Erling Smørgrav for (i = 0; i < options->num_identity_files; i++) { 437a0ee8cc6SDag-Erling Smørgrav if (options->identity_file_userprovided[i] == userprovided && 438a0ee8cc6SDag-Erling Smørgrav strcmp(options->identity_files[i], path) == 0) { 439a0ee8cc6SDag-Erling Smørgrav debug2("%s: ignoring duplicate key %s", __func__, path); 440a0ee8cc6SDag-Erling Smørgrav free(path); 441a0ee8cc6SDag-Erling Smørgrav return; 442a0ee8cc6SDag-Erling Smørgrav } 443a0ee8cc6SDag-Erling Smørgrav } 444a0ee8cc6SDag-Erling Smørgrav 445fa67e83cSDag-Erling Smørgrav options->identity_file_userprovided[options->num_identity_files] = 446fa67e83cSDag-Erling Smørgrav userprovided; 447fa67e83cSDag-Erling Smørgrav options->identity_files[options->num_identity_files++] = path; 448fa67e83cSDag-Erling Smørgrav } 449fa67e83cSDag-Erling Smørgrav 450f7167e0eSDag-Erling Smørgrav int 451f7167e0eSDag-Erling Smørgrav default_ssh_port(void) 452f7167e0eSDag-Erling Smørgrav { 453f7167e0eSDag-Erling Smørgrav static int port; 454f7167e0eSDag-Erling Smørgrav struct servent *sp; 455f7167e0eSDag-Erling Smørgrav 456f7167e0eSDag-Erling Smørgrav if (port == 0) { 457f7167e0eSDag-Erling Smørgrav sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 458f7167e0eSDag-Erling Smørgrav port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 459f7167e0eSDag-Erling Smørgrav } 460f7167e0eSDag-Erling Smørgrav return port; 461f7167e0eSDag-Erling Smørgrav } 462f7167e0eSDag-Erling Smørgrav 463f7167e0eSDag-Erling Smørgrav /* 464f7167e0eSDag-Erling Smørgrav * Execute a command in a shell. 465f7167e0eSDag-Erling Smørgrav * Return its exit status or -1 on abnormal exit. 466f7167e0eSDag-Erling Smørgrav */ 467f7167e0eSDag-Erling Smørgrav static int 468f7167e0eSDag-Erling Smørgrav execute_in_shell(const char *cmd) 469f7167e0eSDag-Erling Smørgrav { 470*acc1a9efSDag-Erling Smørgrav char *shell; 471f7167e0eSDag-Erling Smørgrav pid_t pid; 472f7167e0eSDag-Erling Smørgrav int devnull, status; 473f7167e0eSDag-Erling Smørgrav extern uid_t original_real_uid; 474f7167e0eSDag-Erling Smørgrav 475f7167e0eSDag-Erling Smørgrav if ((shell = getenv("SHELL")) == NULL) 476f7167e0eSDag-Erling Smørgrav shell = _PATH_BSHELL; 477f7167e0eSDag-Erling Smørgrav 478f7167e0eSDag-Erling Smørgrav /* Need this to redirect subprocess stdin/out */ 479f7167e0eSDag-Erling Smørgrav if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) 480f7167e0eSDag-Erling Smørgrav fatal("open(/dev/null): %s", strerror(errno)); 481f7167e0eSDag-Erling Smørgrav 482f7167e0eSDag-Erling Smørgrav debug("Executing command: '%.500s'", cmd); 483f7167e0eSDag-Erling Smørgrav 484f7167e0eSDag-Erling Smørgrav /* Fork and execute the command. */ 485f7167e0eSDag-Erling Smørgrav if ((pid = fork()) == 0) { 486f7167e0eSDag-Erling Smørgrav char *argv[4]; 487f7167e0eSDag-Erling Smørgrav 488f7167e0eSDag-Erling Smørgrav /* Child. Permanently give up superuser privileges. */ 489f7167e0eSDag-Erling Smørgrav permanently_drop_suid(original_real_uid); 490f7167e0eSDag-Erling Smørgrav 491f7167e0eSDag-Erling Smørgrav /* Redirect child stdin and stdout. Leave stderr */ 492f7167e0eSDag-Erling Smørgrav if (dup2(devnull, STDIN_FILENO) == -1) 493f7167e0eSDag-Erling Smørgrav fatal("dup2: %s", strerror(errno)); 494f7167e0eSDag-Erling Smørgrav if (dup2(devnull, STDOUT_FILENO) == -1) 495f7167e0eSDag-Erling Smørgrav fatal("dup2: %s", strerror(errno)); 496f7167e0eSDag-Erling Smørgrav if (devnull > STDERR_FILENO) 497f7167e0eSDag-Erling Smørgrav close(devnull); 498f7167e0eSDag-Erling Smørgrav closefrom(STDERR_FILENO + 1); 499f7167e0eSDag-Erling Smørgrav 500f7167e0eSDag-Erling Smørgrav argv[0] = shell; 501f7167e0eSDag-Erling Smørgrav argv[1] = "-c"; 502*acc1a9efSDag-Erling Smørgrav argv[2] = xstrdup(cmd); 503f7167e0eSDag-Erling Smørgrav argv[3] = NULL; 504f7167e0eSDag-Erling Smørgrav 505f7167e0eSDag-Erling Smørgrav execv(argv[0], argv); 506f7167e0eSDag-Erling Smørgrav error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 507f7167e0eSDag-Erling Smørgrav /* Die with signal to make this error apparent to parent. */ 508f7167e0eSDag-Erling Smørgrav signal(SIGTERM, SIG_DFL); 509f7167e0eSDag-Erling Smørgrav kill(getpid(), SIGTERM); 510f7167e0eSDag-Erling Smørgrav _exit(1); 511f7167e0eSDag-Erling Smørgrav } 512f7167e0eSDag-Erling Smørgrav /* Parent. */ 513f7167e0eSDag-Erling Smørgrav if (pid < 0) 514f7167e0eSDag-Erling Smørgrav fatal("%s: fork: %.100s", __func__, strerror(errno)); 515f7167e0eSDag-Erling Smørgrav 516f7167e0eSDag-Erling Smørgrav close(devnull); 517f7167e0eSDag-Erling Smørgrav 518f7167e0eSDag-Erling Smørgrav while (waitpid(pid, &status, 0) == -1) { 519f7167e0eSDag-Erling Smørgrav if (errno != EINTR && errno != EAGAIN) 520f7167e0eSDag-Erling Smørgrav fatal("%s: waitpid: %s", __func__, strerror(errno)); 521f7167e0eSDag-Erling Smørgrav } 522f7167e0eSDag-Erling Smørgrav if (!WIFEXITED(status)) { 523f7167e0eSDag-Erling Smørgrav error("command '%.100s' exited abnormally", cmd); 524f7167e0eSDag-Erling Smørgrav return -1; 525f7167e0eSDag-Erling Smørgrav } 526f7167e0eSDag-Erling Smørgrav debug3("command returned status %d", WEXITSTATUS(status)); 527f7167e0eSDag-Erling Smørgrav return WEXITSTATUS(status); 528f7167e0eSDag-Erling Smørgrav } 529f7167e0eSDag-Erling Smørgrav 530f7167e0eSDag-Erling Smørgrav /* 531f7167e0eSDag-Erling Smørgrav * Parse and execute a Match directive. 532f7167e0eSDag-Erling Smørgrav */ 533f7167e0eSDag-Erling Smørgrav static int 534f7167e0eSDag-Erling Smørgrav match_cfg_line(Options *options, char **condition, struct passwd *pw, 535bc5531deSDag-Erling Smørgrav const char *host_arg, const char *original_host, int post_canon, 536bc5531deSDag-Erling Smørgrav const char *filename, int linenum) 537f7167e0eSDag-Erling Smørgrav { 538bc5531deSDag-Erling Smørgrav char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 539f7167e0eSDag-Erling Smørgrav const char *ruser; 540bc5531deSDag-Erling Smørgrav int r, port, this_result, result = 1, attributes = 0, negate; 541f7167e0eSDag-Erling Smørgrav char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 542f7167e0eSDag-Erling Smørgrav 543f7167e0eSDag-Erling Smørgrav /* 544f7167e0eSDag-Erling Smørgrav * Configuration is likely to be incomplete at this point so we 545f7167e0eSDag-Erling Smørgrav * must be prepared to use default values. 546f7167e0eSDag-Erling Smørgrav */ 547f7167e0eSDag-Erling Smørgrav port = options->port <= 0 ? default_ssh_port() : options->port; 548f7167e0eSDag-Erling Smørgrav ruser = options->user == NULL ? pw->pw_name : options->user; 549*acc1a9efSDag-Erling Smørgrav if (post_canon) { 550*acc1a9efSDag-Erling Smørgrav host = xstrdup(options->hostname); 551*acc1a9efSDag-Erling Smørgrav } else if (options->hostname != NULL) { 552f7167e0eSDag-Erling Smørgrav /* NB. Please keep in sync with ssh.c:main() */ 553f7167e0eSDag-Erling Smørgrav host = percent_expand(options->hostname, 554f7167e0eSDag-Erling Smørgrav "h", host_arg, (char *)NULL); 555*acc1a9efSDag-Erling Smørgrav } else { 556f7167e0eSDag-Erling Smørgrav host = xstrdup(host_arg); 557*acc1a9efSDag-Erling Smørgrav } 558f7167e0eSDag-Erling Smørgrav 559bc5531deSDag-Erling Smørgrav debug2("checking match for '%s' host %s originally %s", 560bc5531deSDag-Erling Smørgrav cp, host, original_host); 561bc5531deSDag-Erling Smørgrav while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 562bc5531deSDag-Erling Smørgrav criteria = NULL; 563bc5531deSDag-Erling Smørgrav this_result = 1; 564bc5531deSDag-Erling Smørgrav if ((negate = attrib[0] == '!')) 565bc5531deSDag-Erling Smørgrav attrib++; 566bc5531deSDag-Erling Smørgrav /* criteria "all" and "canonical" have no argument */ 567f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "all") == 0) { 568bc5531deSDag-Erling Smørgrav if (attributes > 1 || 569f7167e0eSDag-Erling Smørgrav ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 570bc5531deSDag-Erling Smørgrav error("%.200s line %d: '%s' cannot be combined " 571bc5531deSDag-Erling Smørgrav "with other Match attributes", 572bc5531deSDag-Erling Smørgrav filename, linenum, oattrib); 573f7167e0eSDag-Erling Smørgrav result = -1; 574f7167e0eSDag-Erling Smørgrav goto out; 575f7167e0eSDag-Erling Smørgrav } 576bc5531deSDag-Erling Smørgrav if (result) 577bc5531deSDag-Erling Smørgrav result = negate ? 0 : 1; 578f7167e0eSDag-Erling Smørgrav goto out; 579f7167e0eSDag-Erling Smørgrav } 580bc5531deSDag-Erling Smørgrav attributes++; 581bc5531deSDag-Erling Smørgrav if (strcasecmp(attrib, "canonical") == 0) { 582bc5531deSDag-Erling Smørgrav r = !!post_canon; /* force bitmask member to boolean */ 583bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 584bc5531deSDag-Erling Smørgrav this_result = result = 0; 585bc5531deSDag-Erling Smørgrav debug3("%.200s line %d: %smatched '%s'", 586bc5531deSDag-Erling Smørgrav filename, linenum, 587bc5531deSDag-Erling Smørgrav this_result ? "" : "not ", oattrib); 588bc5531deSDag-Erling Smørgrav continue; 589bc5531deSDag-Erling Smørgrav } 590bc5531deSDag-Erling Smørgrav /* All other criteria require an argument */ 591f7167e0eSDag-Erling Smørgrav if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 592f7167e0eSDag-Erling Smørgrav error("Missing Match criteria for %s", attrib); 593f7167e0eSDag-Erling Smørgrav result = -1; 594f7167e0eSDag-Erling Smørgrav goto out; 595f7167e0eSDag-Erling Smørgrav } 596f7167e0eSDag-Erling Smørgrav if (strcasecmp(attrib, "host") == 0) { 597bc5531deSDag-Erling Smørgrav criteria = xstrdup(host); 598557f75e5SDag-Erling Smørgrav r = match_hostname(host, arg) == 1; 599bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 600bc5531deSDag-Erling Smørgrav this_result = result = 0; 601f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "originalhost") == 0) { 602bc5531deSDag-Erling Smørgrav criteria = xstrdup(original_host); 603557f75e5SDag-Erling Smørgrav r = match_hostname(original_host, arg) == 1; 604bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 605bc5531deSDag-Erling Smørgrav this_result = result = 0; 606f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "user") == 0) { 607bc5531deSDag-Erling Smørgrav criteria = xstrdup(ruser); 608557f75e5SDag-Erling Smørgrav r = match_pattern_list(ruser, arg, 0) == 1; 609bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 610bc5531deSDag-Erling Smørgrav this_result = result = 0; 611f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "localuser") == 0) { 612bc5531deSDag-Erling Smørgrav criteria = xstrdup(pw->pw_name); 613557f75e5SDag-Erling Smørgrav r = match_pattern_list(pw->pw_name, arg, 0) == 1; 614bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 615bc5531deSDag-Erling Smørgrav this_result = result = 0; 616f7167e0eSDag-Erling Smørgrav } else if (strcasecmp(attrib, "exec") == 0) { 617f7167e0eSDag-Erling Smørgrav if (gethostname(thishost, sizeof(thishost)) == -1) 618f7167e0eSDag-Erling Smørgrav fatal("gethostname: %s", strerror(errno)); 619f7167e0eSDag-Erling Smørgrav strlcpy(shorthost, thishost, sizeof(shorthost)); 620f7167e0eSDag-Erling Smørgrav shorthost[strcspn(thishost, ".")] = '\0'; 621f7167e0eSDag-Erling Smørgrav snprintf(portstr, sizeof(portstr), "%d", port); 622f7167e0eSDag-Erling Smørgrav 623f7167e0eSDag-Erling Smørgrav cmd = percent_expand(arg, 624f7167e0eSDag-Erling Smørgrav "L", shorthost, 625f7167e0eSDag-Erling Smørgrav "d", pw->pw_dir, 626f7167e0eSDag-Erling Smørgrav "h", host, 627f7167e0eSDag-Erling Smørgrav "l", thishost, 628bc5531deSDag-Erling Smørgrav "n", original_host, 629f7167e0eSDag-Erling Smørgrav "p", portstr, 630f7167e0eSDag-Erling Smørgrav "r", ruser, 631f7167e0eSDag-Erling Smørgrav "u", pw->pw_name, 632f7167e0eSDag-Erling Smørgrav (char *)NULL); 633b83788ffSDag-Erling Smørgrav if (result != 1) { 634b83788ffSDag-Erling Smørgrav /* skip execution if prior predicate failed */ 635bc5531deSDag-Erling Smørgrav debug3("%.200s line %d: skipped exec " 636bc5531deSDag-Erling Smørgrav "\"%.100s\"", filename, linenum, cmd); 637bc5531deSDag-Erling Smørgrav free(cmd); 638bc5531deSDag-Erling Smørgrav continue; 639bc5531deSDag-Erling Smørgrav } 640f7167e0eSDag-Erling Smørgrav r = execute_in_shell(cmd); 641f7167e0eSDag-Erling Smørgrav if (r == -1) { 642b83788ffSDag-Erling Smørgrav fatal("%.200s line %d: match exec " 643b83788ffSDag-Erling Smørgrav "'%.100s' error", filename, 644b83788ffSDag-Erling Smørgrav linenum, cmd); 645b83788ffSDag-Erling Smørgrav } 646bc5531deSDag-Erling Smørgrav criteria = xstrdup(cmd); 647f7167e0eSDag-Erling Smørgrav free(cmd); 648bc5531deSDag-Erling Smørgrav /* Force exit status to boolean */ 649bc5531deSDag-Erling Smørgrav r = r == 0; 650bc5531deSDag-Erling Smørgrav if (r == (negate ? 1 : 0)) 651bc5531deSDag-Erling Smørgrav this_result = result = 0; 652f7167e0eSDag-Erling Smørgrav } else { 653f7167e0eSDag-Erling Smørgrav error("Unsupported Match attribute %s", attrib); 654f7167e0eSDag-Erling Smørgrav result = -1; 655f7167e0eSDag-Erling Smørgrav goto out; 656f7167e0eSDag-Erling Smørgrav } 657bc5531deSDag-Erling Smørgrav debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", 658bc5531deSDag-Erling Smørgrav filename, linenum, this_result ? "": "not ", 659bc5531deSDag-Erling Smørgrav oattrib, criteria); 660bc5531deSDag-Erling Smørgrav free(criteria); 661f7167e0eSDag-Erling Smørgrav } 662f7167e0eSDag-Erling Smørgrav if (attributes == 0) { 663f7167e0eSDag-Erling Smørgrav error("One or more attributes required for Match"); 664f7167e0eSDag-Erling Smørgrav result = -1; 665f7167e0eSDag-Erling Smørgrav goto out; 666f7167e0eSDag-Erling Smørgrav } 667f7167e0eSDag-Erling Smørgrav out: 668bc5531deSDag-Erling Smørgrav if (result != -1) 669bc5531deSDag-Erling Smørgrav debug2("match %sfound", result ? "" : "not "); 670bc5531deSDag-Erling Smørgrav *condition = cp; 671f7167e0eSDag-Erling Smørgrav free(host); 672f7167e0eSDag-Erling Smørgrav return result; 673f7167e0eSDag-Erling Smørgrav } 674f7167e0eSDag-Erling Smørgrav 675f7167e0eSDag-Erling Smørgrav /* Check and prepare a domain name: removes trailing '.' and lowercases */ 676f7167e0eSDag-Erling Smørgrav static void 677f7167e0eSDag-Erling Smørgrav valid_domain(char *name, const char *filename, int linenum) 678f7167e0eSDag-Erling Smørgrav { 679f7167e0eSDag-Erling Smørgrav size_t i, l = strlen(name); 680f7167e0eSDag-Erling Smørgrav u_char c, last = '\0'; 681f7167e0eSDag-Erling Smørgrav 682f7167e0eSDag-Erling Smørgrav if (l == 0) 683f7167e0eSDag-Erling Smørgrav fatal("%s line %d: empty hostname suffix", filename, linenum); 684f7167e0eSDag-Erling Smørgrav if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) 685f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" " 686f7167e0eSDag-Erling Smørgrav "starts with invalid character", filename, linenum, name); 687f7167e0eSDag-Erling Smørgrav for (i = 0; i < l; i++) { 688f7167e0eSDag-Erling Smørgrav c = tolower((u_char)name[i]); 689f7167e0eSDag-Erling Smørgrav name[i] = (char)c; 690f7167e0eSDag-Erling Smørgrav if (last == '.' && c == '.') 691f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" contains " 692f7167e0eSDag-Erling Smørgrav "consecutive separators", filename, linenum, name); 693f7167e0eSDag-Erling Smørgrav if (c != '.' && c != '-' && !isalnum(c) && 694f7167e0eSDag-Erling Smørgrav c != '_') /* technically invalid, but common */ 695f7167e0eSDag-Erling Smørgrav fatal("%s line %d: hostname suffix \"%.100s\" contains " 696f7167e0eSDag-Erling Smørgrav "invalid characters", filename, linenum, name); 697f7167e0eSDag-Erling Smørgrav last = c; 698f7167e0eSDag-Erling Smørgrav } 699f7167e0eSDag-Erling Smørgrav if (name[l - 1] == '.') 700f7167e0eSDag-Erling Smørgrav name[l - 1] = '\0'; 701f7167e0eSDag-Erling Smørgrav } 702f7167e0eSDag-Erling Smørgrav 703511b41d2SMark Murray /* 704ca3176e7SBrian Feldman * Returns the number of the token pointed to by cp or oBadOption. 705511b41d2SMark Murray */ 706511b41d2SMark Murray static OpCodes 707e4a9863fSDag-Erling Smørgrav parse_token(const char *cp, const char *filename, int linenum, 708e4a9863fSDag-Erling Smørgrav const char *ignored_unknown) 709511b41d2SMark Murray { 710e4a9863fSDag-Erling Smørgrav int i; 711511b41d2SMark Murray 712511b41d2SMark Murray for (i = 0; keywords[i].name; i++) 713e4a9863fSDag-Erling Smørgrav if (strcmp(cp, keywords[i].name) == 0) 714511b41d2SMark Murray return keywords[i].opcode; 715557f75e5SDag-Erling Smørgrav if (ignored_unknown != NULL && 716557f75e5SDag-Erling Smørgrav match_pattern_list(cp, ignored_unknown, 1) == 1) 717e4a9863fSDag-Erling Smørgrav return oIgnoredUnknownOption; 718ca3176e7SBrian Feldman error("%s: line %d: Bad configuration option: %s", 719511b41d2SMark Murray filename, linenum, cp); 720511b41d2SMark Murray return oBadOption; 721511b41d2SMark Murray } 722511b41d2SMark Murray 723f7167e0eSDag-Erling Smørgrav /* Multistate option parsing */ 724f7167e0eSDag-Erling Smørgrav struct multistate { 725f7167e0eSDag-Erling Smørgrav char *key; 726f7167e0eSDag-Erling Smørgrav int value; 727f7167e0eSDag-Erling Smørgrav }; 728f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_flag[] = { 729f7167e0eSDag-Erling Smørgrav { "true", 1 }, 730f7167e0eSDag-Erling Smørgrav { "false", 0 }, 731f7167e0eSDag-Erling Smørgrav { "yes", 1 }, 732f7167e0eSDag-Erling Smørgrav { "no", 0 }, 733f7167e0eSDag-Erling Smørgrav { NULL, -1 } 734f7167e0eSDag-Erling Smørgrav }; 735f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_yesnoask[] = { 736f7167e0eSDag-Erling Smørgrav { "true", 1 }, 737f7167e0eSDag-Erling Smørgrav { "false", 0 }, 738f7167e0eSDag-Erling Smørgrav { "yes", 1 }, 739f7167e0eSDag-Erling Smørgrav { "no", 0 }, 740f7167e0eSDag-Erling Smørgrav { "ask", 2 }, 741f7167e0eSDag-Erling Smørgrav { NULL, -1 } 742f7167e0eSDag-Erling Smørgrav }; 743*acc1a9efSDag-Erling Smørgrav static const struct multistate multistate_yesnoaskconfirm[] = { 744*acc1a9efSDag-Erling Smørgrav { "true", 1 }, 745*acc1a9efSDag-Erling Smørgrav { "false", 0 }, 746*acc1a9efSDag-Erling Smørgrav { "yes", 1 }, 747*acc1a9efSDag-Erling Smørgrav { "no", 0 }, 748*acc1a9efSDag-Erling Smørgrav { "ask", 2 }, 749*acc1a9efSDag-Erling Smørgrav { "confirm", 3 }, 750*acc1a9efSDag-Erling Smørgrav { NULL, -1 } 751*acc1a9efSDag-Erling Smørgrav }; 752f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_addressfamily[] = { 753f7167e0eSDag-Erling Smørgrav { "inet", AF_INET }, 754f7167e0eSDag-Erling Smørgrav { "inet6", AF_INET6 }, 755f7167e0eSDag-Erling Smørgrav { "any", AF_UNSPEC }, 756f7167e0eSDag-Erling Smørgrav { NULL, -1 } 757f7167e0eSDag-Erling Smørgrav }; 758f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_controlmaster[] = { 759f7167e0eSDag-Erling Smørgrav { "true", SSHCTL_MASTER_YES }, 760f7167e0eSDag-Erling Smørgrav { "yes", SSHCTL_MASTER_YES }, 761f7167e0eSDag-Erling Smørgrav { "false", SSHCTL_MASTER_NO }, 762f7167e0eSDag-Erling Smørgrav { "no", SSHCTL_MASTER_NO }, 763f7167e0eSDag-Erling Smørgrav { "auto", SSHCTL_MASTER_AUTO }, 764f7167e0eSDag-Erling Smørgrav { "ask", SSHCTL_MASTER_ASK }, 765f7167e0eSDag-Erling Smørgrav { "autoask", SSHCTL_MASTER_AUTO_ASK }, 766f7167e0eSDag-Erling Smørgrav { NULL, -1 } 767f7167e0eSDag-Erling Smørgrav }; 768f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_tunnel[] = { 769f7167e0eSDag-Erling Smørgrav { "ethernet", SSH_TUNMODE_ETHERNET }, 770f7167e0eSDag-Erling Smørgrav { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 771f7167e0eSDag-Erling Smørgrav { "true", SSH_TUNMODE_DEFAULT }, 772f7167e0eSDag-Erling Smørgrav { "yes", SSH_TUNMODE_DEFAULT }, 773f7167e0eSDag-Erling Smørgrav { "false", SSH_TUNMODE_NO }, 774f7167e0eSDag-Erling Smørgrav { "no", SSH_TUNMODE_NO }, 775f7167e0eSDag-Erling Smørgrav { NULL, -1 } 776f7167e0eSDag-Erling Smørgrav }; 777f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_requesttty[] = { 778f7167e0eSDag-Erling Smørgrav { "true", REQUEST_TTY_YES }, 779f7167e0eSDag-Erling Smørgrav { "yes", REQUEST_TTY_YES }, 780f7167e0eSDag-Erling Smørgrav { "false", REQUEST_TTY_NO }, 781f7167e0eSDag-Erling Smørgrav { "no", REQUEST_TTY_NO }, 782f7167e0eSDag-Erling Smørgrav { "force", REQUEST_TTY_FORCE }, 783f7167e0eSDag-Erling Smørgrav { "auto", REQUEST_TTY_AUTO }, 784f7167e0eSDag-Erling Smørgrav { NULL, -1 } 785f7167e0eSDag-Erling Smørgrav }; 786f7167e0eSDag-Erling Smørgrav static const struct multistate multistate_canonicalizehostname[] = { 787f7167e0eSDag-Erling Smørgrav { "true", SSH_CANONICALISE_YES }, 788f7167e0eSDag-Erling Smørgrav { "false", SSH_CANONICALISE_NO }, 789f7167e0eSDag-Erling Smørgrav { "yes", SSH_CANONICALISE_YES }, 790f7167e0eSDag-Erling Smørgrav { "no", SSH_CANONICALISE_NO }, 791f7167e0eSDag-Erling Smørgrav { "always", SSH_CANONICALISE_ALWAYS }, 792f7167e0eSDag-Erling Smørgrav { NULL, -1 } 793f7167e0eSDag-Erling Smørgrav }; 794f7167e0eSDag-Erling Smørgrav 795511b41d2SMark Murray /* 796511b41d2SMark Murray * Processes a single option line as used in the configuration files. This 797511b41d2SMark Murray * only sets those values that have not already been set. 798511b41d2SMark Murray */ 799e73e9afaSDag-Erling Smørgrav #define WHITESPACE " \t\r\n" 800511b41d2SMark Murray int 801f7167e0eSDag-Erling Smørgrav process_config_line(Options *options, struct passwd *pw, const char *host, 802bc5531deSDag-Erling Smørgrav const char *original_host, char *line, const char *filename, 803bc5531deSDag-Erling Smørgrav int linenum, int *activep, int flags) 804511b41d2SMark Murray { 805e146993eSDag-Erling Smørgrav char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; 806e146993eSDag-Erling Smørgrav char **cpptr, fwdarg[256]; 807e4a9863fSDag-Erling Smørgrav u_int i, *uintptr, max_entries = 0; 808f7167e0eSDag-Erling Smørgrav int negated, opcode, *intptr, value, value2, cmdline = 0; 809d4af9e69SDag-Erling Smørgrav LogLevel *log_level_ptr; 810e4a9863fSDag-Erling Smørgrav long long val64; 811e73e9afaSDag-Erling Smørgrav size_t len; 812a0ee8cc6SDag-Erling Smørgrav struct Forward fwd; 813f7167e0eSDag-Erling Smørgrav const struct multistate *multistate_ptr; 814f7167e0eSDag-Erling Smørgrav struct allowed_cname *cname; 815f7167e0eSDag-Erling Smørgrav 816f7167e0eSDag-Erling Smørgrav if (activep == NULL) { /* We are processing a command line directive */ 817f7167e0eSDag-Erling Smørgrav cmdline = 1; 818f7167e0eSDag-Erling Smørgrav activep = &cmdline; 819f7167e0eSDag-Erling Smørgrav } 820511b41d2SMark Murray 821cf2b5f3bSDag-Erling Smørgrav /* Strip trailing whitespace */ 822557f75e5SDag-Erling Smørgrav if ((len = strlen(line)) == 0) 823557f75e5SDag-Erling Smørgrav return 0; 824557f75e5SDag-Erling Smørgrav for (len--; len > 0; len--) { 825cf2b5f3bSDag-Erling Smørgrav if (strchr(WHITESPACE, line[len]) == NULL) 826cf2b5f3bSDag-Erling Smørgrav break; 827cf2b5f3bSDag-Erling Smørgrav line[len] = '\0'; 828cf2b5f3bSDag-Erling Smørgrav } 829cf2b5f3bSDag-Erling Smørgrav 830c2d3a559SKris Kennaway s = line; 831c2d3a559SKris Kennaway /* Get the keyword. (Each line is supposed to begin with a keyword). */ 832333ee039SDag-Erling Smørgrav if ((keyword = strdelim(&s)) == NULL) 833333ee039SDag-Erling Smørgrav return 0; 834c2d3a559SKris Kennaway /* Ignore leading whitespace. */ 835c2d3a559SKris Kennaway if (*keyword == '\0') 836c2d3a559SKris Kennaway keyword = strdelim(&s); 837ca3176e7SBrian Feldman if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 838511b41d2SMark Murray return 0; 839e4a9863fSDag-Erling Smørgrav /* Match lowercase keyword */ 840f7167e0eSDag-Erling Smørgrav lowercase(keyword); 841511b41d2SMark Murray 842e4a9863fSDag-Erling Smørgrav opcode = parse_token(keyword, filename, linenum, 843e4a9863fSDag-Erling Smørgrav options->ignored_unknown); 844511b41d2SMark Murray 845511b41d2SMark Murray switch (opcode) { 846511b41d2SMark Murray case oBadOption: 847511b41d2SMark Murray /* don't panic, but count bad options */ 848511b41d2SMark Murray return -1; 849511b41d2SMark Murray /* NOTREACHED */ 850e4a9863fSDag-Erling Smørgrav case oIgnoredUnknownOption: 851e4a9863fSDag-Erling Smørgrav debug("%s line %d: Ignored unknown option \"%s\"", 852e4a9863fSDag-Erling Smørgrav filename, linenum, keyword); 853e4a9863fSDag-Erling Smørgrav return 0; 854cf2b5f3bSDag-Erling Smørgrav case oConnectTimeout: 855cf2b5f3bSDag-Erling Smørgrav intptr = &options->connection_timeout; 8561ec0d754SDag-Erling Smørgrav parse_time: 857cf2b5f3bSDag-Erling Smørgrav arg = strdelim(&s); 858cf2b5f3bSDag-Erling Smørgrav if (!arg || *arg == '\0') 859cf2b5f3bSDag-Erling Smørgrav fatal("%s line %d: missing time value.", 860cf2b5f3bSDag-Erling Smørgrav filename, linenum); 861bc5531deSDag-Erling Smørgrav if (strcmp(arg, "none") == 0) 862bc5531deSDag-Erling Smørgrav value = -1; 863bc5531deSDag-Erling Smørgrav else if ((value = convtime(arg)) == -1) 864cf2b5f3bSDag-Erling Smørgrav fatal("%s line %d: invalid time value.", 865cf2b5f3bSDag-Erling Smørgrav filename, linenum); 866d4af9e69SDag-Erling Smørgrav if (*activep && *intptr == -1) 867cf2b5f3bSDag-Erling Smørgrav *intptr = value; 868cf2b5f3bSDag-Erling Smørgrav break; 869cf2b5f3bSDag-Erling Smørgrav 870511b41d2SMark Murray case oForwardAgent: 871511b41d2SMark Murray intptr = &options->forward_agent; 872511b41d2SMark Murray parse_flag: 873f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_flag; 874f7167e0eSDag-Erling Smørgrav parse_multistate: 875c2d3a559SKris Kennaway arg = strdelim(&s); 876c2d3a559SKris Kennaway if (!arg || *arg == '\0') 877f7167e0eSDag-Erling Smørgrav fatal("%s line %d: missing argument.", 878f7167e0eSDag-Erling Smørgrav filename, linenum); 879f7167e0eSDag-Erling Smørgrav value = -1; 880f7167e0eSDag-Erling Smørgrav for (i = 0; multistate_ptr[i].key != NULL; i++) { 881f7167e0eSDag-Erling Smørgrav if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 882f7167e0eSDag-Erling Smørgrav value = multistate_ptr[i].value; 883f7167e0eSDag-Erling Smørgrav break; 884f7167e0eSDag-Erling Smørgrav } 885f7167e0eSDag-Erling Smørgrav } 886f7167e0eSDag-Erling Smørgrav if (value == -1) 887f7167e0eSDag-Erling Smørgrav fatal("%s line %d: unsupported option \"%s\".", 888f7167e0eSDag-Erling Smørgrav filename, linenum, arg); 889511b41d2SMark Murray if (*activep && *intptr == -1) 890511b41d2SMark Murray *intptr = value; 891511b41d2SMark Murray break; 892511b41d2SMark Murray 893511b41d2SMark Murray case oForwardX11: 894511b41d2SMark Murray intptr = &options->forward_x11; 895511b41d2SMark Murray goto parse_flag; 896511b41d2SMark Murray 8971ec0d754SDag-Erling Smørgrav case oForwardX11Trusted: 8981ec0d754SDag-Erling Smørgrav intptr = &options->forward_x11_trusted; 8991ec0d754SDag-Erling Smørgrav goto parse_flag; 9001ec0d754SDag-Erling Smørgrav 901e2f6069cSDag-Erling Smørgrav case oForwardX11Timeout: 902e2f6069cSDag-Erling Smørgrav intptr = &options->forward_x11_timeout; 903e2f6069cSDag-Erling Smørgrav goto parse_time; 904e2f6069cSDag-Erling Smørgrav 905511b41d2SMark Murray case oGatewayPorts: 906a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.gateway_ports; 907511b41d2SMark Murray goto parse_flag; 908511b41d2SMark Murray 909333ee039SDag-Erling Smørgrav case oExitOnForwardFailure: 910333ee039SDag-Erling Smørgrav intptr = &options->exit_on_forward_failure; 911333ee039SDag-Erling Smørgrav goto parse_flag; 912333ee039SDag-Erling Smørgrav 913511b41d2SMark Murray case oUsePrivilegedPort: 914511b41d2SMark Murray intptr = &options->use_privileged_port; 915511b41d2SMark Murray goto parse_flag; 916511b41d2SMark Murray 917511b41d2SMark Murray case oPasswordAuthentication: 918511b41d2SMark Murray intptr = &options->password_authentication; 919511b41d2SMark Murray goto parse_flag; 920511b41d2SMark Murray 92109958426SBrian Feldman case oKbdInteractiveAuthentication: 92209958426SBrian Feldman intptr = &options->kbd_interactive_authentication; 92309958426SBrian Feldman goto parse_flag; 92409958426SBrian Feldman 92509958426SBrian Feldman case oKbdInteractiveDevices: 92609958426SBrian Feldman charptr = &options->kbd_interactive_devices; 92709958426SBrian Feldman goto parse_string; 92809958426SBrian Feldman 929ca3176e7SBrian Feldman case oPubkeyAuthentication: 930ca3176e7SBrian Feldman intptr = &options->pubkey_authentication; 931e8aafc91SKris Kennaway goto parse_flag; 932e8aafc91SKris Kennaway 933511b41d2SMark Murray case oRSAAuthentication: 934511b41d2SMark Murray intptr = &options->rsa_authentication; 935511b41d2SMark Murray goto parse_flag; 936511b41d2SMark Murray 937511b41d2SMark Murray case oRhostsRSAAuthentication: 938511b41d2SMark Murray intptr = &options->rhosts_rsa_authentication; 939511b41d2SMark Murray goto parse_flag; 940511b41d2SMark Murray 941ca3176e7SBrian Feldman case oHostbasedAuthentication: 942ca3176e7SBrian Feldman intptr = &options->hostbased_authentication; 943511b41d2SMark Murray goto parse_flag; 944511b41d2SMark Murray 945af12a3e7SDag-Erling Smørgrav case oChallengeResponseAuthentication: 946af12a3e7SDag-Erling Smørgrav intptr = &options->challenge_response_authentication; 947af12a3e7SDag-Erling Smørgrav goto parse_flag; 948cf2b5f3bSDag-Erling Smørgrav 949cf2b5f3bSDag-Erling Smørgrav case oGssAuthentication: 950cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_authentication; 951511b41d2SMark Murray goto parse_flag; 952cf2b5f3bSDag-Erling Smørgrav 953cf2b5f3bSDag-Erling Smørgrav case oGssDelegateCreds: 954cf2b5f3bSDag-Erling Smørgrav intptr = &options->gss_deleg_creds; 955ca3176e7SBrian Feldman goto parse_flag; 956cf2b5f3bSDag-Erling Smørgrav 957511b41d2SMark Murray case oBatchMode: 958511b41d2SMark Murray intptr = &options->batch_mode; 959511b41d2SMark Murray goto parse_flag; 960511b41d2SMark Murray 961511b41d2SMark Murray case oCheckHostIP: 962511b41d2SMark Murray intptr = &options->check_host_ip; 963511b41d2SMark Murray goto parse_flag; 964511b41d2SMark Murray 965cf2b5f3bSDag-Erling Smørgrav case oVerifyHostKeyDNS: 966cf2b5f3bSDag-Erling Smørgrav intptr = &options->verify_host_key_dns; 967f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_yesnoask; 968f7167e0eSDag-Erling Smørgrav goto parse_multistate; 969cf2b5f3bSDag-Erling Smørgrav 970511b41d2SMark Murray case oStrictHostKeyChecking: 971511b41d2SMark Murray intptr = &options->strict_host_key_checking; 972f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_yesnoask; 973f7167e0eSDag-Erling Smørgrav goto parse_multistate; 974511b41d2SMark Murray 975511b41d2SMark Murray case oCompression: 976511b41d2SMark Murray intptr = &options->compression; 977511b41d2SMark Murray goto parse_flag; 978511b41d2SMark Murray 9791ec0d754SDag-Erling Smørgrav case oTCPKeepAlive: 9801ec0d754SDag-Erling Smørgrav intptr = &options->tcp_keep_alive; 981511b41d2SMark Murray goto parse_flag; 982511b41d2SMark Murray 983af12a3e7SDag-Erling Smørgrav case oNoHostAuthenticationForLocalhost: 984af12a3e7SDag-Erling Smørgrav intptr = &options->no_host_authentication_for_localhost; 985af12a3e7SDag-Erling Smørgrav goto parse_flag; 986af12a3e7SDag-Erling Smørgrav 987511b41d2SMark Murray case oNumberOfPasswordPrompts: 988511b41d2SMark Murray intptr = &options->number_of_password_prompts; 989511b41d2SMark Murray goto parse_int; 990511b41d2SMark Murray 991511b41d2SMark Murray case oCompressionLevel: 992511b41d2SMark Murray intptr = &options->compression_level; 993511b41d2SMark Murray goto parse_int; 994511b41d2SMark Murray 995cf2b5f3bSDag-Erling Smørgrav case oRekeyLimit: 996cf2b5f3bSDag-Erling Smørgrav arg = strdelim(&s); 997cf2b5f3bSDag-Erling Smørgrav if (!arg || *arg == '\0') 998e4a9863fSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, 999e4a9863fSDag-Erling Smørgrav linenum); 1000e4a9863fSDag-Erling Smørgrav if (strcmp(arg, "default") == 0) { 1001e4a9863fSDag-Erling Smørgrav val64 = 0; 1002e4a9863fSDag-Erling Smørgrav } else { 1003e4a9863fSDag-Erling Smørgrav if (scan_scaled(arg, &val64) == -1) 1004e4a9863fSDag-Erling Smørgrav fatal("%.200s line %d: Bad number '%s': %s", 1005e4a9863fSDag-Erling Smørgrav filename, linenum, arg, strerror(errno)); 1006e4a9863fSDag-Erling Smørgrav if (val64 != 0 && val64 < 16) 1007333ee039SDag-Erling Smørgrav fatal("%.200s line %d: RekeyLimit too small", 1008333ee039SDag-Erling Smørgrav filename, linenum); 1009e4a9863fSDag-Erling Smørgrav } 1010d4af9e69SDag-Erling Smørgrav if (*activep && options->rekey_limit == -1) 1011*acc1a9efSDag-Erling Smørgrav options->rekey_limit = val64; 1012e4a9863fSDag-Erling Smørgrav if (s != NULL) { /* optional rekey interval present */ 1013e4a9863fSDag-Erling Smørgrav if (strcmp(s, "none") == 0) { 1014e4a9863fSDag-Erling Smørgrav (void)strdelim(&s); /* discard */ 1015e4a9863fSDag-Erling Smørgrav break; 1016e4a9863fSDag-Erling Smørgrav } 1017e4a9863fSDag-Erling Smørgrav intptr = &options->rekey_interval; 1018e4a9863fSDag-Erling Smørgrav goto parse_time; 1019e4a9863fSDag-Erling Smørgrav } 1020cf2b5f3bSDag-Erling Smørgrav break; 1021cf2b5f3bSDag-Erling Smørgrav 1022511b41d2SMark Murray case oIdentityFile: 1023c2d3a559SKris Kennaway arg = strdelim(&s); 1024c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1025511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 1026511b41d2SMark Murray if (*activep) { 1027ca3176e7SBrian Feldman intptr = &options->num_identity_files; 1028e8aafc91SKris Kennaway if (*intptr >= SSH_MAX_IDENTITY_FILES) 1029511b41d2SMark Murray fatal("%.200s line %d: Too many identity files specified (max %d).", 1030511b41d2SMark Murray filename, linenum, SSH_MAX_IDENTITY_FILES); 1031bc5531deSDag-Erling Smørgrav add_identity_file(options, NULL, 1032bc5531deSDag-Erling Smørgrav arg, flags & SSHCONF_USERCONF); 1033511b41d2SMark Murray } 1034511b41d2SMark Murray break; 1035511b41d2SMark Murray 1036*acc1a9efSDag-Erling Smørgrav case oCertificateFile: 1037*acc1a9efSDag-Erling Smørgrav arg = strdelim(&s); 1038*acc1a9efSDag-Erling Smørgrav if (!arg || *arg == '\0') 1039*acc1a9efSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 1040*acc1a9efSDag-Erling Smørgrav filename, linenum); 1041*acc1a9efSDag-Erling Smørgrav if (*activep) { 1042*acc1a9efSDag-Erling Smørgrav intptr = &options->num_certificate_files; 1043*acc1a9efSDag-Erling Smørgrav if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1044*acc1a9efSDag-Erling Smørgrav fatal("%.200s line %d: Too many certificate " 1045*acc1a9efSDag-Erling Smørgrav "files specified (max %d).", 1046*acc1a9efSDag-Erling Smørgrav filename, linenum, 1047*acc1a9efSDag-Erling Smørgrav SSH_MAX_CERTIFICATE_FILES); 1048*acc1a9efSDag-Erling Smørgrav } 1049*acc1a9efSDag-Erling Smørgrav add_certificate_file(options, arg, 1050*acc1a9efSDag-Erling Smørgrav flags & SSHCONF_USERCONF); 1051*acc1a9efSDag-Erling Smørgrav } 1052*acc1a9efSDag-Erling Smørgrav break; 1053*acc1a9efSDag-Erling Smørgrav 1054c2d3a559SKris Kennaway case oXAuthLocation: 1055c2d3a559SKris Kennaway charptr=&options->xauth_location; 1056c2d3a559SKris Kennaway goto parse_string; 1057c2d3a559SKris Kennaway 1058511b41d2SMark Murray case oUser: 1059511b41d2SMark Murray charptr = &options->user; 1060511b41d2SMark Murray parse_string: 1061c2d3a559SKris Kennaway arg = strdelim(&s); 1062c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1063e146993eSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 1064e146993eSDag-Erling Smørgrav filename, linenum); 1065511b41d2SMark Murray if (*activep && *charptr == NULL) 1066c2d3a559SKris Kennaway *charptr = xstrdup(arg); 1067511b41d2SMark Murray break; 1068511b41d2SMark Murray 1069511b41d2SMark Murray case oGlobalKnownHostsFile: 1070e146993eSDag-Erling Smørgrav cpptr = (char **)&options->system_hostfiles; 1071e146993eSDag-Erling Smørgrav uintptr = &options->num_system_hostfiles; 1072e146993eSDag-Erling Smørgrav max_entries = SSH_MAX_HOSTS_FILES; 1073e146993eSDag-Erling Smørgrav parse_char_array: 1074e146993eSDag-Erling Smørgrav if (*activep && *uintptr == 0) { 1075e146993eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1076e146993eSDag-Erling Smørgrav if ((*uintptr) >= max_entries) 1077e146993eSDag-Erling Smørgrav fatal("%s line %d: " 1078e146993eSDag-Erling Smørgrav "too many authorized keys files.", 1079e146993eSDag-Erling Smørgrav filename, linenum); 1080e146993eSDag-Erling Smørgrav cpptr[(*uintptr)++] = xstrdup(arg); 1081e146993eSDag-Erling Smørgrav } 1082e146993eSDag-Erling Smørgrav } 1083e146993eSDag-Erling Smørgrav return 0; 1084511b41d2SMark Murray 1085511b41d2SMark Murray case oUserKnownHostsFile: 1086e146993eSDag-Erling Smørgrav cpptr = (char **)&options->user_hostfiles; 1087e146993eSDag-Erling Smørgrav uintptr = &options->num_user_hostfiles; 1088e146993eSDag-Erling Smørgrav max_entries = SSH_MAX_HOSTS_FILES; 1089e146993eSDag-Erling Smørgrav goto parse_char_array; 1090e8aafc91SKris Kennaway 1091511b41d2SMark Murray case oHostName: 1092511b41d2SMark Murray charptr = &options->hostname; 1093511b41d2SMark Murray goto parse_string; 1094511b41d2SMark Murray 1095ca3176e7SBrian Feldman case oHostKeyAlias: 1096ca3176e7SBrian Feldman charptr = &options->host_key_alias; 1097ca3176e7SBrian Feldman goto parse_string; 1098ca3176e7SBrian Feldman 1099ca3176e7SBrian Feldman case oPreferredAuthentications: 1100ca3176e7SBrian Feldman charptr = &options->preferred_authentications; 1101ca3176e7SBrian Feldman goto parse_string; 1102ca3176e7SBrian Feldman 1103af12a3e7SDag-Erling Smørgrav case oBindAddress: 1104af12a3e7SDag-Erling Smørgrav charptr = &options->bind_address; 1105af12a3e7SDag-Erling Smørgrav goto parse_string; 1106af12a3e7SDag-Erling Smørgrav 1107b15c8340SDag-Erling Smørgrav case oPKCS11Provider: 1108b15c8340SDag-Erling Smørgrav charptr = &options->pkcs11_provider; 1109af12a3e7SDag-Erling Smørgrav goto parse_string; 1110af12a3e7SDag-Erling Smørgrav 1111511b41d2SMark Murray case oProxyCommand: 1112b74df5b2SDag-Erling Smørgrav charptr = &options->proxy_command; 1113b74df5b2SDag-Erling Smørgrav parse_command: 1114cf2b5f3bSDag-Erling Smørgrav if (s == NULL) 1115cf2b5f3bSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, linenum); 1116e73e9afaSDag-Erling Smørgrav len = strspn(s, WHITESPACE "="); 1117511b41d2SMark Murray if (*activep && *charptr == NULL) 1118e73e9afaSDag-Erling Smørgrav *charptr = xstrdup(s + len); 1119511b41d2SMark Murray return 0; 1120511b41d2SMark Murray 1121511b41d2SMark Murray case oPort: 1122511b41d2SMark Murray intptr = &options->port; 1123511b41d2SMark Murray parse_int: 1124c2d3a559SKris Kennaway arg = strdelim(&s); 1125c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1126511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 1127c2d3a559SKris Kennaway if (arg[0] < '0' || arg[0] > '9') 1128511b41d2SMark Murray fatal("%.200s line %d: Bad number.", filename, linenum); 1129511b41d2SMark Murray 1130511b41d2SMark Murray /* Octal, decimal, or hex format? */ 1131c2d3a559SKris Kennaway value = strtol(arg, &endofnumber, 0); 1132c2d3a559SKris Kennaway if (arg == endofnumber) 1133511b41d2SMark Murray fatal("%.200s line %d: Bad number.", filename, linenum); 1134511b41d2SMark Murray if (*activep && *intptr == -1) 1135511b41d2SMark Murray *intptr = value; 1136511b41d2SMark Murray break; 1137511b41d2SMark Murray 1138511b41d2SMark Murray case oConnectionAttempts: 1139511b41d2SMark Murray intptr = &options->connection_attempts; 1140511b41d2SMark Murray goto parse_int; 1141511b41d2SMark Murray 1142511b41d2SMark Murray case oCipher: 1143511b41d2SMark Murray intptr = &options->cipher; 1144c2d3a559SKris Kennaway arg = strdelim(&s); 1145c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1146db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1147c2d3a559SKris Kennaway value = cipher_number(arg); 1148511b41d2SMark Murray if (value == -1) 1149511b41d2SMark Murray fatal("%.200s line %d: Bad cipher '%s'.", 1150c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1151511b41d2SMark Murray if (*activep && *intptr == -1) 1152511b41d2SMark Murray *intptr = value; 1153511b41d2SMark Murray break; 1154511b41d2SMark Murray 1155e8aafc91SKris Kennaway case oCiphers: 1156c2d3a559SKris Kennaway arg = strdelim(&s); 1157c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1158db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1159eccfee6eSDag-Erling Smørgrav if (!ciphers_valid(*arg == '+' ? arg + 1 : arg)) 1160e8aafc91SKris Kennaway fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 1161c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1162e8aafc91SKris Kennaway if (*activep && options->ciphers == NULL) 1163c2d3a559SKris Kennaway options->ciphers = xstrdup(arg); 1164e8aafc91SKris Kennaway break; 1165e8aafc91SKris Kennaway 1166ca3176e7SBrian Feldman case oMacs: 1167ca3176e7SBrian Feldman arg = strdelim(&s); 1168ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1169ca3176e7SBrian Feldman fatal("%.200s line %d: Missing argument.", filename, linenum); 1170eccfee6eSDag-Erling Smørgrav if (!mac_valid(*arg == '+' ? arg + 1 : arg)) 1171ca3176e7SBrian Feldman fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 1172ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1173ca3176e7SBrian Feldman if (*activep && options->macs == NULL) 1174ca3176e7SBrian Feldman options->macs = xstrdup(arg); 1175ca3176e7SBrian Feldman break; 1176ca3176e7SBrian Feldman 11774a421b63SDag-Erling Smørgrav case oKexAlgorithms: 11784a421b63SDag-Erling Smørgrav arg = strdelim(&s); 11794a421b63SDag-Erling Smørgrav if (!arg || *arg == '\0') 11804a421b63SDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 11814a421b63SDag-Erling Smørgrav filename, linenum); 1182eccfee6eSDag-Erling Smørgrav if (!kex_names_valid(*arg == '+' ? arg + 1 : arg)) 11834a421b63SDag-Erling Smørgrav fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 11844a421b63SDag-Erling Smørgrav filename, linenum, arg ? arg : "<NONE>"); 11854a421b63SDag-Erling Smørgrav if (*activep && options->kex_algorithms == NULL) 11864a421b63SDag-Erling Smørgrav options->kex_algorithms = xstrdup(arg); 11874a421b63SDag-Erling Smørgrav break; 11884a421b63SDag-Erling Smørgrav 1189ca3176e7SBrian Feldman case oHostKeyAlgorithms: 1190eccfee6eSDag-Erling Smørgrav charptr = &options->hostkeyalgorithms; 1191eccfee6eSDag-Erling Smørgrav parse_keytypes: 1192ca3176e7SBrian Feldman arg = strdelim(&s); 1193ca3176e7SBrian Feldman if (!arg || *arg == '\0') 1194eccfee6eSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 1195eccfee6eSDag-Erling Smørgrav filename, linenum); 1196eccfee6eSDag-Erling Smørgrav if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) 1197eccfee6eSDag-Erling Smørgrav fatal("%s line %d: Bad key types '%s'.", 1198ca3176e7SBrian Feldman filename, linenum, arg ? arg : "<NONE>"); 1199eccfee6eSDag-Erling Smørgrav if (*activep && *charptr == NULL) 1200eccfee6eSDag-Erling Smørgrav *charptr = xstrdup(arg); 1201ca3176e7SBrian Feldman break; 1202ca3176e7SBrian Feldman 1203e8aafc91SKris Kennaway case oProtocol: 1204e8aafc91SKris Kennaway intptr = &options->protocol; 1205c2d3a559SKris Kennaway arg = strdelim(&s); 1206c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1207db1cb46cSKris Kennaway fatal("%.200s line %d: Missing argument.", filename, linenum); 1208c2d3a559SKris Kennaway value = proto_spec(arg); 1209e8aafc91SKris Kennaway if (value == SSH_PROTO_UNKNOWN) 1210e8aafc91SKris Kennaway fatal("%.200s line %d: Bad protocol spec '%s'.", 1211c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1212e8aafc91SKris Kennaway if (*activep && *intptr == SSH_PROTO_UNKNOWN) 1213e8aafc91SKris Kennaway *intptr = value; 1214e8aafc91SKris Kennaway break; 1215e8aafc91SKris Kennaway 1216511b41d2SMark Murray case oLogLevel: 1217d4af9e69SDag-Erling Smørgrav log_level_ptr = &options->log_level; 1218c2d3a559SKris Kennaway arg = strdelim(&s); 1219c2d3a559SKris Kennaway value = log_level_number(arg); 1220af12a3e7SDag-Erling Smørgrav if (value == SYSLOG_LEVEL_NOT_SET) 1221ca3176e7SBrian Feldman fatal("%.200s line %d: unsupported log level '%s'", 1222c2d3a559SKris Kennaway filename, linenum, arg ? arg : "<NONE>"); 1223d4af9e69SDag-Erling Smørgrav if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1224d4af9e69SDag-Erling Smørgrav *log_level_ptr = (LogLevel) value; 1225511b41d2SMark Murray break; 1226511b41d2SMark Murray 1227af12a3e7SDag-Erling Smørgrav case oLocalForward: 1228511b41d2SMark Murray case oRemoteForward: 1229cce7d346SDag-Erling Smørgrav case oDynamicForward: 1230c2d3a559SKris Kennaway arg = strdelim(&s); 1231aa49c926SDag-Erling Smørgrav if (arg == NULL || *arg == '\0') 1232af12a3e7SDag-Erling Smørgrav fatal("%.200s line %d: Missing port argument.", 1233af12a3e7SDag-Erling Smørgrav filename, linenum); 1234cce7d346SDag-Erling Smørgrav 1235cce7d346SDag-Erling Smørgrav if (opcode == oLocalForward || 1236cce7d346SDag-Erling Smørgrav opcode == oRemoteForward) { 1237aa49c926SDag-Erling Smørgrav arg2 = strdelim(&s); 1238aa49c926SDag-Erling Smørgrav if (arg2 == NULL || *arg2 == '\0') 1239aa49c926SDag-Erling Smørgrav fatal("%.200s line %d: Missing target argument.", 1240511b41d2SMark Murray filename, linenum); 1241aa49c926SDag-Erling Smørgrav 1242aa49c926SDag-Erling Smørgrav /* construct a string for parse_forward */ 1243aa49c926SDag-Erling Smørgrav snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 1244cce7d346SDag-Erling Smørgrav } else if (opcode == oDynamicForward) { 1245cce7d346SDag-Erling Smørgrav strlcpy(fwdarg, arg, sizeof(fwdarg)); 1246cce7d346SDag-Erling Smørgrav } 1247aa49c926SDag-Erling Smørgrav 1248cce7d346SDag-Erling Smørgrav if (parse_forward(&fwd, fwdarg, 1249cce7d346SDag-Erling Smørgrav opcode == oDynamicForward ? 1 : 0, 1250cce7d346SDag-Erling Smørgrav opcode == oRemoteForward ? 1 : 0) == 0) 1251af12a3e7SDag-Erling Smørgrav fatal("%.200s line %d: Bad forwarding specification.", 1252511b41d2SMark Murray filename, linenum); 1253aa49c926SDag-Erling Smørgrav 1254af12a3e7SDag-Erling Smørgrav if (*activep) { 1255cce7d346SDag-Erling Smørgrav if (opcode == oLocalForward || 1256cce7d346SDag-Erling Smørgrav opcode == oDynamicForward) 1257aa49c926SDag-Erling Smørgrav add_local_forward(options, &fwd); 1258af12a3e7SDag-Erling Smørgrav else if (opcode == oRemoteForward) 1259aa49c926SDag-Erling Smørgrav add_remote_forward(options, &fwd); 1260af12a3e7SDag-Erling Smørgrav } 1261511b41d2SMark Murray break; 1262511b41d2SMark Murray 1263af12a3e7SDag-Erling Smørgrav case oClearAllForwardings: 1264af12a3e7SDag-Erling Smørgrav intptr = &options->clear_forwardings; 1265af12a3e7SDag-Erling Smørgrav goto parse_flag; 1266af12a3e7SDag-Erling Smørgrav 1267511b41d2SMark Murray case oHost: 1268f7167e0eSDag-Erling Smørgrav if (cmdline) 1269f7167e0eSDag-Erling Smørgrav fatal("Host directive not supported as a command-line " 1270f7167e0eSDag-Erling Smørgrav "option"); 1271511b41d2SMark Murray *activep = 0; 1272e146993eSDag-Erling Smørgrav arg2 = NULL; 1273e146993eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1274e146993eSDag-Erling Smørgrav negated = *arg == '!'; 1275e146993eSDag-Erling Smørgrav if (negated) 1276e146993eSDag-Erling Smørgrav arg++; 1277c2d3a559SKris Kennaway if (match_pattern(host, arg)) { 1278e146993eSDag-Erling Smørgrav if (negated) { 1279e146993eSDag-Erling Smørgrav debug("%.200s line %d: Skipping Host " 1280e146993eSDag-Erling Smørgrav "block because of negated match " 1281e146993eSDag-Erling Smørgrav "for %.100s", filename, linenum, 1282e146993eSDag-Erling Smørgrav arg); 1283e146993eSDag-Erling Smørgrav *activep = 0; 1284511b41d2SMark Murray break; 1285511b41d2SMark Murray } 1286e146993eSDag-Erling Smørgrav if (!*activep) 1287e146993eSDag-Erling Smørgrav arg2 = arg; /* logged below */ 1288e146993eSDag-Erling Smørgrav *activep = 1; 1289e146993eSDag-Erling Smørgrav } 1290e146993eSDag-Erling Smørgrav } 1291e146993eSDag-Erling Smørgrav if (*activep) 1292e146993eSDag-Erling Smørgrav debug("%.200s line %d: Applying options for %.100s", 1293e146993eSDag-Erling Smørgrav filename, linenum, arg2); 1294c2d3a559SKris Kennaway /* Avoid garbage check below, as strdelim is done. */ 1295511b41d2SMark Murray return 0; 1296511b41d2SMark Murray 1297f7167e0eSDag-Erling Smørgrav case oMatch: 1298f7167e0eSDag-Erling Smørgrav if (cmdline) 1299f7167e0eSDag-Erling Smørgrav fatal("Host directive not supported as a command-line " 1300f7167e0eSDag-Erling Smørgrav "option"); 1301bc5531deSDag-Erling Smørgrav value = match_cfg_line(options, &s, pw, host, original_host, 1302bc5531deSDag-Erling Smørgrav flags & SSHCONF_POSTCANON, filename, linenum); 1303f7167e0eSDag-Erling Smørgrav if (value < 0) 1304f7167e0eSDag-Erling Smørgrav fatal("%.200s line %d: Bad Match condition", filename, 1305f7167e0eSDag-Erling Smørgrav linenum); 1306f7167e0eSDag-Erling Smørgrav *activep = value; 1307f7167e0eSDag-Erling Smørgrav break; 1308f7167e0eSDag-Erling Smørgrav 1309511b41d2SMark Murray case oEscapeChar: 1310511b41d2SMark Murray intptr = &options->escape_char; 1311c2d3a559SKris Kennaway arg = strdelim(&s); 1312c2d3a559SKris Kennaway if (!arg || *arg == '\0') 1313511b41d2SMark Murray fatal("%.200s line %d: Missing argument.", filename, linenum); 1314557f75e5SDag-Erling Smørgrav if (strcmp(arg, "none") == 0) 1315557f75e5SDag-Erling Smørgrav value = SSH_ESCAPECHAR_NONE; 1316557f75e5SDag-Erling Smørgrav else if (arg[1] == '\0') 1317557f75e5SDag-Erling Smørgrav value = (u_char) arg[0]; 1318557f75e5SDag-Erling Smørgrav else if (arg[0] == '^' && arg[2] == 0 && 1319ca3176e7SBrian Feldman (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 1320ca3176e7SBrian Feldman value = (u_char) arg[1] & 31; 1321511b41d2SMark Murray else { 1322511b41d2SMark Murray fatal("%.200s line %d: Bad escape character.", 1323511b41d2SMark Murray filename, linenum); 1324511b41d2SMark Murray /* NOTREACHED */ 1325511b41d2SMark Murray value = 0; /* Avoid compiler warning. */ 1326511b41d2SMark Murray } 1327511b41d2SMark Murray if (*activep && *intptr == -1) 1328511b41d2SMark Murray *intptr = value; 1329511b41d2SMark Murray break; 1330511b41d2SMark Murray 1331cf2b5f3bSDag-Erling Smørgrav case oAddressFamily: 1332cf2b5f3bSDag-Erling Smørgrav intptr = &options->address_family; 1333f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_addressfamily; 1334f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1335cf2b5f3bSDag-Erling Smørgrav 1336e73e9afaSDag-Erling Smørgrav case oEnableSSHKeysign: 1337e73e9afaSDag-Erling Smørgrav intptr = &options->enable_ssh_keysign; 1338e73e9afaSDag-Erling Smørgrav goto parse_flag; 1339e73e9afaSDag-Erling Smørgrav 13405962c0e9SDag-Erling Smørgrav case oIdentitiesOnly: 13415962c0e9SDag-Erling Smørgrav intptr = &options->identities_only; 13425962c0e9SDag-Erling Smørgrav goto parse_flag; 13435962c0e9SDag-Erling Smørgrav 13441ec0d754SDag-Erling Smørgrav case oServerAliveInterval: 13451ec0d754SDag-Erling Smørgrav intptr = &options->server_alive_interval; 13461ec0d754SDag-Erling Smørgrav goto parse_time; 13471ec0d754SDag-Erling Smørgrav 13481ec0d754SDag-Erling Smørgrav case oServerAliveCountMax: 13491ec0d754SDag-Erling Smørgrav intptr = &options->server_alive_count_max; 13501ec0d754SDag-Erling Smørgrav goto parse_int; 13511ec0d754SDag-Erling Smørgrav 135221e764dfSDag-Erling Smørgrav case oSendEnv: 135321e764dfSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 135421e764dfSDag-Erling Smørgrav if (strchr(arg, '=') != NULL) 135521e764dfSDag-Erling Smørgrav fatal("%s line %d: Invalid environment name.", 135621e764dfSDag-Erling Smørgrav filename, linenum); 1357aa49c926SDag-Erling Smørgrav if (!*activep) 1358aa49c926SDag-Erling Smørgrav continue; 135921e764dfSDag-Erling Smørgrav if (options->num_send_env >= MAX_SEND_ENV) 136021e764dfSDag-Erling Smørgrav fatal("%s line %d: too many send env.", 136121e764dfSDag-Erling Smørgrav filename, linenum); 136221e764dfSDag-Erling Smørgrav options->send_env[options->num_send_env++] = 136321e764dfSDag-Erling Smørgrav xstrdup(arg); 136421e764dfSDag-Erling Smørgrav } 136521e764dfSDag-Erling Smørgrav break; 136621e764dfSDag-Erling Smørgrav 136721e764dfSDag-Erling Smørgrav case oControlPath: 136821e764dfSDag-Erling Smørgrav charptr = &options->control_path; 136921e764dfSDag-Erling Smørgrav goto parse_string; 137021e764dfSDag-Erling Smørgrav 137121e764dfSDag-Erling Smørgrav case oControlMaster: 137221e764dfSDag-Erling Smørgrav intptr = &options->control_master; 1373f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_controlmaster; 1374f7167e0eSDag-Erling Smørgrav goto parse_multistate; 137521e764dfSDag-Erling Smørgrav 1376e2f6069cSDag-Erling Smørgrav case oControlPersist: 1377e2f6069cSDag-Erling Smørgrav /* no/false/yes/true, or a time spec */ 1378e2f6069cSDag-Erling Smørgrav intptr = &options->control_persist; 1379e2f6069cSDag-Erling Smørgrav arg = strdelim(&s); 1380e2f6069cSDag-Erling Smørgrav if (!arg || *arg == '\0') 1381e2f6069cSDag-Erling Smørgrav fatal("%.200s line %d: Missing ControlPersist" 1382e2f6069cSDag-Erling Smørgrav " argument.", filename, linenum); 1383e2f6069cSDag-Erling Smørgrav value = 0; 1384e2f6069cSDag-Erling Smørgrav value2 = 0; /* timeout */ 1385e2f6069cSDag-Erling Smørgrav if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1386e2f6069cSDag-Erling Smørgrav value = 0; 1387e2f6069cSDag-Erling Smørgrav else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1388e2f6069cSDag-Erling Smørgrav value = 1; 1389e2f6069cSDag-Erling Smørgrav else if ((value2 = convtime(arg)) >= 0) 1390e2f6069cSDag-Erling Smørgrav value = 1; 1391e2f6069cSDag-Erling Smørgrav else 1392e2f6069cSDag-Erling Smørgrav fatal("%.200s line %d: Bad ControlPersist argument.", 1393e2f6069cSDag-Erling Smørgrav filename, linenum); 1394e2f6069cSDag-Erling Smørgrav if (*activep && *intptr == -1) { 1395e2f6069cSDag-Erling Smørgrav *intptr = value; 1396e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = value2; 1397e2f6069cSDag-Erling Smørgrav } 1398e2f6069cSDag-Erling Smørgrav break; 1399e2f6069cSDag-Erling Smørgrav 1400aa49c926SDag-Erling Smørgrav case oHashKnownHosts: 1401aa49c926SDag-Erling Smørgrav intptr = &options->hash_known_hosts; 1402aa49c926SDag-Erling Smørgrav goto parse_flag; 1403aa49c926SDag-Erling Smørgrav 1404b74df5b2SDag-Erling Smørgrav case oTunnel: 1405b74df5b2SDag-Erling Smørgrav intptr = &options->tun_open; 1406f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_tunnel; 1407f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1408b74df5b2SDag-Erling Smørgrav 1409b74df5b2SDag-Erling Smørgrav case oTunnelDevice: 1410b74df5b2SDag-Erling Smørgrav arg = strdelim(&s); 1411b74df5b2SDag-Erling Smørgrav if (!arg || *arg == '\0') 1412b74df5b2SDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, linenum); 1413b74df5b2SDag-Erling Smørgrav value = a2tun(arg, &value2); 1414b74df5b2SDag-Erling Smørgrav if (value == SSH_TUNID_ERR) 1415b74df5b2SDag-Erling Smørgrav fatal("%.200s line %d: Bad tun device.", filename, linenum); 1416b74df5b2SDag-Erling Smørgrav if (*activep) { 1417b74df5b2SDag-Erling Smørgrav options->tun_local = value; 1418b74df5b2SDag-Erling Smørgrav options->tun_remote = value2; 1419b74df5b2SDag-Erling Smørgrav } 1420b74df5b2SDag-Erling Smørgrav break; 1421b74df5b2SDag-Erling Smørgrav 1422b74df5b2SDag-Erling Smørgrav case oLocalCommand: 1423b74df5b2SDag-Erling Smørgrav charptr = &options->local_command; 1424b74df5b2SDag-Erling Smørgrav goto parse_command; 1425b74df5b2SDag-Erling Smørgrav 1426b74df5b2SDag-Erling Smørgrav case oPermitLocalCommand: 1427b74df5b2SDag-Erling Smørgrav intptr = &options->permit_local_command; 1428b74df5b2SDag-Erling Smørgrav goto parse_flag; 1429b74df5b2SDag-Erling Smørgrav 1430d4af9e69SDag-Erling Smørgrav case oVisualHostKey: 1431d4af9e69SDag-Erling Smørgrav intptr = &options->visual_host_key; 1432d4af9e69SDag-Erling Smørgrav goto parse_flag; 1433d4af9e69SDag-Erling Smørgrav 14344a421b63SDag-Erling Smørgrav case oIPQoS: 14354a421b63SDag-Erling Smørgrav arg = strdelim(&s); 14364a421b63SDag-Erling Smørgrav if ((value = parse_ipqos(arg)) == -1) 14374a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad IPQoS value: %s", 14384a421b63SDag-Erling Smørgrav filename, linenum, arg); 14394a421b63SDag-Erling Smørgrav arg = strdelim(&s); 14404a421b63SDag-Erling Smørgrav if (arg == NULL) 14414a421b63SDag-Erling Smørgrav value2 = value; 14424a421b63SDag-Erling Smørgrav else if ((value2 = parse_ipqos(arg)) == -1) 14434a421b63SDag-Erling Smørgrav fatal("%s line %d: Bad IPQoS value: %s", 14444a421b63SDag-Erling Smørgrav filename, linenum, arg); 14454a421b63SDag-Erling Smørgrav if (*activep) { 14464a421b63SDag-Erling Smørgrav options->ip_qos_interactive = value; 14474a421b63SDag-Erling Smørgrav options->ip_qos_bulk = value2; 14484a421b63SDag-Erling Smørgrav } 14494a421b63SDag-Erling Smørgrav break; 14504a421b63SDag-Erling Smørgrav 1451e146993eSDag-Erling Smørgrav case oRequestTTY: 1452e146993eSDag-Erling Smørgrav intptr = &options->request_tty; 1453f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_requesttty; 1454f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1455975616f0SDag-Erling Smørgrav 1456e146993eSDag-Erling Smørgrav case oVersionAddendum: 1457462c32cbSDag-Erling Smørgrav if (s == NULL) 1458462c32cbSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", filename, 1459462c32cbSDag-Erling Smørgrav linenum); 1460462c32cbSDag-Erling Smørgrav len = strspn(s, WHITESPACE); 1461462c32cbSDag-Erling Smørgrav if (*activep && options->version_addendum == NULL) { 1462462c32cbSDag-Erling Smørgrav if (strcasecmp(s + len, "none") == 0) 1463462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(""); 1464462c32cbSDag-Erling Smørgrav else if (strchr(s + len, '\r') != NULL) 1465462c32cbSDag-Erling Smørgrav fatal("%.200s line %d: Invalid argument", 1466462c32cbSDag-Erling Smørgrav filename, linenum); 1467462c32cbSDag-Erling Smørgrav else 1468462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(s + len); 1469462c32cbSDag-Erling Smørgrav } 1470462c32cbSDag-Erling Smørgrav return 0; 1471e146993eSDag-Erling Smørgrav 1472e4a9863fSDag-Erling Smørgrav case oIgnoreUnknown: 1473e4a9863fSDag-Erling Smørgrav charptr = &options->ignored_unknown; 1474e4a9863fSDag-Erling Smørgrav goto parse_string; 1475e4a9863fSDag-Erling Smørgrav 1476f7167e0eSDag-Erling Smørgrav case oProxyUseFdpass: 1477f7167e0eSDag-Erling Smørgrav intptr = &options->proxy_use_fdpass; 1478f7167e0eSDag-Erling Smørgrav goto parse_flag; 1479f7167e0eSDag-Erling Smørgrav 1480f7167e0eSDag-Erling Smørgrav case oCanonicalDomains: 1481f7167e0eSDag-Erling Smørgrav value = options->num_canonical_domains != 0; 1482f7167e0eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1483f7167e0eSDag-Erling Smørgrav valid_domain(arg, filename, linenum); 1484f7167e0eSDag-Erling Smørgrav if (!*activep || value) 1485f7167e0eSDag-Erling Smørgrav continue; 1486f7167e0eSDag-Erling Smørgrav if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1487f7167e0eSDag-Erling Smørgrav fatal("%s line %d: too many hostname suffixes.", 1488f7167e0eSDag-Erling Smørgrav filename, linenum); 1489f7167e0eSDag-Erling Smørgrav options->canonical_domains[ 1490f7167e0eSDag-Erling Smørgrav options->num_canonical_domains++] = xstrdup(arg); 1491f7167e0eSDag-Erling Smørgrav } 1492f7167e0eSDag-Erling Smørgrav break; 1493f7167e0eSDag-Erling Smørgrav 1494f7167e0eSDag-Erling Smørgrav case oCanonicalizePermittedCNAMEs: 1495f7167e0eSDag-Erling Smørgrav value = options->num_permitted_cnames != 0; 1496f7167e0eSDag-Erling Smørgrav while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1497f7167e0eSDag-Erling Smørgrav /* Either '*' for everything or 'list:list' */ 1498f7167e0eSDag-Erling Smørgrav if (strcmp(arg, "*") == 0) 1499f7167e0eSDag-Erling Smørgrav arg2 = arg; 1500f7167e0eSDag-Erling Smørgrav else { 1501f7167e0eSDag-Erling Smørgrav lowercase(arg); 1502f7167e0eSDag-Erling Smørgrav if ((arg2 = strchr(arg, ':')) == NULL || 1503f7167e0eSDag-Erling Smørgrav arg2[1] == '\0') { 1504f7167e0eSDag-Erling Smørgrav fatal("%s line %d: " 1505f7167e0eSDag-Erling Smørgrav "Invalid permitted CNAME \"%s\"", 1506f7167e0eSDag-Erling Smørgrav filename, linenum, arg); 1507f7167e0eSDag-Erling Smørgrav } 1508f7167e0eSDag-Erling Smørgrav *arg2 = '\0'; 1509f7167e0eSDag-Erling Smørgrav arg2++; 1510f7167e0eSDag-Erling Smørgrav } 1511f7167e0eSDag-Erling Smørgrav if (!*activep || value) 1512f7167e0eSDag-Erling Smørgrav continue; 1513f7167e0eSDag-Erling Smørgrav if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1514f7167e0eSDag-Erling Smørgrav fatal("%s line %d: too many permitted CNAMEs.", 1515f7167e0eSDag-Erling Smørgrav filename, linenum); 1516f7167e0eSDag-Erling Smørgrav cname = options->permitted_cnames + 1517f7167e0eSDag-Erling Smørgrav options->num_permitted_cnames++; 1518f7167e0eSDag-Erling Smørgrav cname->source_list = xstrdup(arg); 1519f7167e0eSDag-Erling Smørgrav cname->target_list = xstrdup(arg2); 1520f7167e0eSDag-Erling Smørgrav } 1521f7167e0eSDag-Erling Smørgrav break; 1522f7167e0eSDag-Erling Smørgrav 1523f7167e0eSDag-Erling Smørgrav case oCanonicalizeHostname: 1524f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_hostname; 1525f7167e0eSDag-Erling Smørgrav multistate_ptr = multistate_canonicalizehostname; 1526f7167e0eSDag-Erling Smørgrav goto parse_multistate; 1527f7167e0eSDag-Erling Smørgrav 1528f7167e0eSDag-Erling Smørgrav case oCanonicalizeMaxDots: 1529f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_max_dots; 1530f7167e0eSDag-Erling Smørgrav goto parse_int; 1531f7167e0eSDag-Erling Smørgrav 1532f7167e0eSDag-Erling Smørgrav case oCanonicalizeFallbackLocal: 1533f7167e0eSDag-Erling Smørgrav intptr = &options->canonicalize_fallback_local; 1534f7167e0eSDag-Erling Smørgrav goto parse_flag; 1535f7167e0eSDag-Erling Smørgrav 1536a0ee8cc6SDag-Erling Smørgrav case oStreamLocalBindMask: 1537a0ee8cc6SDag-Erling Smørgrav arg = strdelim(&s); 1538a0ee8cc6SDag-Erling Smørgrav if (!arg || *arg == '\0') 1539a0ee8cc6SDag-Erling Smørgrav fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); 1540a0ee8cc6SDag-Erling Smørgrav /* Parse mode in octal format */ 1541a0ee8cc6SDag-Erling Smørgrav value = strtol(arg, &endofnumber, 8); 1542a0ee8cc6SDag-Erling Smørgrav if (arg == endofnumber || value < 0 || value > 0777) 1543a0ee8cc6SDag-Erling Smørgrav fatal("%.200s line %d: Bad mask.", filename, linenum); 1544a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1545a0ee8cc6SDag-Erling Smørgrav break; 1546a0ee8cc6SDag-Erling Smørgrav 1547a0ee8cc6SDag-Erling Smørgrav case oStreamLocalBindUnlink: 1548a0ee8cc6SDag-Erling Smørgrav intptr = &options->fwd_opts.streamlocal_bind_unlink; 1549a0ee8cc6SDag-Erling Smørgrav goto parse_flag; 1550a0ee8cc6SDag-Erling Smørgrav 1551bc5531deSDag-Erling Smørgrav case oRevokedHostKeys: 1552bc5531deSDag-Erling Smørgrav charptr = &options->revoked_host_keys; 1553bc5531deSDag-Erling Smørgrav goto parse_string; 1554bc5531deSDag-Erling Smørgrav 1555bc5531deSDag-Erling Smørgrav case oFingerprintHash: 1556bc5531deSDag-Erling Smørgrav intptr = &options->fingerprint_hash; 1557bc5531deSDag-Erling Smørgrav arg = strdelim(&s); 1558bc5531deSDag-Erling Smørgrav if (!arg || *arg == '\0') 1559bc5531deSDag-Erling Smørgrav fatal("%.200s line %d: Missing argument.", 1560bc5531deSDag-Erling Smørgrav filename, linenum); 1561bc5531deSDag-Erling Smørgrav if ((value = ssh_digest_alg_by_name(arg)) == -1) 1562bc5531deSDag-Erling Smørgrav fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1563bc5531deSDag-Erling Smørgrav filename, linenum, arg); 1564bc5531deSDag-Erling Smørgrav if (*activep && *intptr == -1) 1565bc5531deSDag-Erling Smørgrav *intptr = value; 1566bc5531deSDag-Erling Smørgrav break; 1567bc5531deSDag-Erling Smørgrav 1568bc5531deSDag-Erling Smørgrav case oUpdateHostkeys: 1569bc5531deSDag-Erling Smørgrav intptr = &options->update_hostkeys; 1570bc5531deSDag-Erling Smørgrav multistate_ptr = multistate_yesnoask; 1571bc5531deSDag-Erling Smørgrav goto parse_multistate; 1572bc5531deSDag-Erling Smørgrav 1573bc5531deSDag-Erling Smørgrav case oHostbasedKeyTypes: 1574bc5531deSDag-Erling Smørgrav charptr = &options->hostbased_key_types; 1575eccfee6eSDag-Erling Smørgrav goto parse_keytypes; 1576eccfee6eSDag-Erling Smørgrav 1577eccfee6eSDag-Erling Smørgrav case oPubkeyAcceptedKeyTypes: 1578eccfee6eSDag-Erling Smørgrav charptr = &options->pubkey_key_types; 1579eccfee6eSDag-Erling Smørgrav goto parse_keytypes; 1580bc5531deSDag-Erling Smørgrav 1581*acc1a9efSDag-Erling Smørgrav case oAddKeysToAgent: 1582*acc1a9efSDag-Erling Smørgrav intptr = &options->add_keys_to_agent; 1583*acc1a9efSDag-Erling Smørgrav multistate_ptr = multistate_yesnoaskconfirm; 1584*acc1a9efSDag-Erling Smørgrav goto parse_multistate; 1585*acc1a9efSDag-Erling Smørgrav 158680628bacSDag-Erling Smørgrav case oDeprecated: 158780628bacSDag-Erling Smørgrav debug("%s line %d: Deprecated option \"%s\"", 158880628bacSDag-Erling Smørgrav filename, linenum, keyword); 158980628bacSDag-Erling Smørgrav return 0; 159080628bacSDag-Erling Smørgrav 1591cf2b5f3bSDag-Erling Smørgrav case oUnsupported: 1592cf2b5f3bSDag-Erling Smørgrav error("%s line %d: Unsupported option \"%s\"", 1593cf2b5f3bSDag-Erling Smørgrav filename, linenum, keyword); 1594cf2b5f3bSDag-Erling Smørgrav return 0; 1595cf2b5f3bSDag-Erling Smørgrav 1596511b41d2SMark Murray default: 1597bc5531deSDag-Erling Smørgrav fatal("%s: Unimplemented opcode %d", __func__, opcode); 1598511b41d2SMark Murray } 1599511b41d2SMark Murray 1600511b41d2SMark Murray /* Check that there is no garbage at end of line. */ 1601ca3176e7SBrian Feldman if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1602c2d3a559SKris Kennaway fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1603c2d3a559SKris Kennaway filename, linenum, arg); 1604c2d3a559SKris Kennaway } 1605511b41d2SMark Murray return 0; 1606511b41d2SMark Murray } 1607511b41d2SMark Murray 1608511b41d2SMark Murray 1609511b41d2SMark Murray /* 1610511b41d2SMark Murray * Reads the config file and modifies the options accordingly. Options 1611511b41d2SMark Murray * should already be initialized before this call. This never returns if 1612af12a3e7SDag-Erling Smørgrav * there is an error. If the file does not exist, this returns 0. 1613511b41d2SMark Murray */ 1614511b41d2SMark Murray 1615af12a3e7SDag-Erling Smørgrav int 1616f7167e0eSDag-Erling Smørgrav read_config_file(const char *filename, struct passwd *pw, const char *host, 1617bc5531deSDag-Erling Smørgrav const char *original_host, Options *options, int flags) 1618511b41d2SMark Murray { 1619511b41d2SMark Murray FILE *f; 1620511b41d2SMark Murray char line[1024]; 1621511b41d2SMark Murray int active, linenum; 1622511b41d2SMark Murray int bad_options = 0; 1623511b41d2SMark Murray 162421e764dfSDag-Erling Smørgrav if ((f = fopen(filename, "r")) == NULL) 1625af12a3e7SDag-Erling Smørgrav return 0; 1626511b41d2SMark Murray 162773370613SDag-Erling Smørgrav if (flags & SSHCONF_CHECKPERM) { 162821e764dfSDag-Erling Smørgrav struct stat sb; 162921e764dfSDag-Erling Smørgrav 163021e764dfSDag-Erling Smørgrav if (fstat(fileno(f), &sb) == -1) 163121e764dfSDag-Erling Smørgrav fatal("fstat %s: %s", filename, strerror(errno)); 163221e764dfSDag-Erling Smørgrav if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 163321e764dfSDag-Erling Smørgrav (sb.st_mode & 022) != 0)) 163421e764dfSDag-Erling Smørgrav fatal("Bad owner or permissions on %s", filename); 163521e764dfSDag-Erling Smørgrav } 163621e764dfSDag-Erling Smørgrav 1637511b41d2SMark Murray debug("Reading configuration data %.200s", filename); 1638511b41d2SMark Murray 1639511b41d2SMark Murray /* 1640511b41d2SMark Murray * Mark that we are now processing the options. This flag is turned 1641511b41d2SMark Murray * on/off by Host specifications. 1642511b41d2SMark Murray */ 1643511b41d2SMark Murray active = 1; 1644511b41d2SMark Murray linenum = 0; 1645511b41d2SMark Murray while (fgets(line, sizeof(line), f)) { 1646511b41d2SMark Murray /* Update line number counter. */ 1647511b41d2SMark Murray linenum++; 1648bc5531deSDag-Erling Smørgrav if (process_config_line(options, pw, host, original_host, 1649bc5531deSDag-Erling Smørgrav line, filename, linenum, &active, flags) != 0) 1650511b41d2SMark Murray bad_options++; 1651511b41d2SMark Murray } 1652511b41d2SMark Murray fclose(f); 1653511b41d2SMark Murray if (bad_options > 0) 1654ca3176e7SBrian Feldman fatal("%s: terminating, %d bad configuration options", 1655511b41d2SMark Murray filename, bad_options); 1656af12a3e7SDag-Erling Smørgrav return 1; 1657511b41d2SMark Murray } 1658511b41d2SMark Murray 1659b83788ffSDag-Erling Smørgrav /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1660b83788ffSDag-Erling Smørgrav int 1661b83788ffSDag-Erling Smørgrav option_clear_or_none(const char *o) 1662b83788ffSDag-Erling Smørgrav { 1663b83788ffSDag-Erling Smørgrav return o == NULL || strcasecmp(o, "none") == 0; 1664b83788ffSDag-Erling Smørgrav } 1665b83788ffSDag-Erling Smørgrav 1666511b41d2SMark Murray /* 1667511b41d2SMark Murray * Initializes options to special values that indicate that they have not yet 1668511b41d2SMark Murray * been set. Read_config_file will only set options with this value. Options 1669511b41d2SMark Murray * are processed in the following order: command line, user config file, 1670511b41d2SMark Murray * system config file. Last, fill_default_options is called. 1671511b41d2SMark Murray */ 1672511b41d2SMark Murray 1673511b41d2SMark Murray void 1674511b41d2SMark Murray initialize_options(Options * options) 1675511b41d2SMark Murray { 1676511b41d2SMark Murray memset(options, 'X', sizeof(*options)); 1677eccfee6eSDag-Erling Smørgrav options->version_addendum = NULL; 1678511b41d2SMark Murray options->forward_agent = -1; 1679511b41d2SMark Murray options->forward_x11 = -1; 16801ec0d754SDag-Erling Smørgrav options->forward_x11_trusted = -1; 1681e2f6069cSDag-Erling Smørgrav options->forward_x11_timeout = -1; 1682333ee039SDag-Erling Smørgrav options->exit_on_forward_failure = -1; 1683c2d3a559SKris Kennaway options->xauth_location = NULL; 1684a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = -1; 1685a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1686a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = -1; 1687511b41d2SMark Murray options->use_privileged_port = -1; 1688511b41d2SMark Murray options->rsa_authentication = -1; 1689ca3176e7SBrian Feldman options->pubkey_authentication = -1; 1690af12a3e7SDag-Erling Smørgrav options->challenge_response_authentication = -1; 1691cf2b5f3bSDag-Erling Smørgrav options->gss_authentication = -1; 1692cf2b5f3bSDag-Erling Smørgrav options->gss_deleg_creds = -1; 1693511b41d2SMark Murray options->password_authentication = -1; 169409958426SBrian Feldman options->kbd_interactive_authentication = -1; 169509958426SBrian Feldman options->kbd_interactive_devices = NULL; 1696511b41d2SMark Murray options->rhosts_rsa_authentication = -1; 1697ca3176e7SBrian Feldman options->hostbased_authentication = -1; 1698511b41d2SMark Murray options->batch_mode = -1; 1699511b41d2SMark Murray options->check_host_ip = -1; 1700511b41d2SMark Murray options->strict_host_key_checking = -1; 1701511b41d2SMark Murray options->compression = -1; 17021ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = -1; 1703511b41d2SMark Murray options->compression_level = -1; 1704511b41d2SMark Murray options->port = -1; 1705cf2b5f3bSDag-Erling Smørgrav options->address_family = -1; 1706511b41d2SMark Murray options->connection_attempts = -1; 1707cf2b5f3bSDag-Erling Smørgrav options->connection_timeout = -1; 1708511b41d2SMark Murray options->number_of_password_prompts = -1; 1709511b41d2SMark Murray options->cipher = -1; 1710e8aafc91SKris Kennaway options->ciphers = NULL; 1711ca3176e7SBrian Feldman options->macs = NULL; 17124a421b63SDag-Erling Smørgrav options->kex_algorithms = NULL; 1713ca3176e7SBrian Feldman options->hostkeyalgorithms = NULL; 1714e8aafc91SKris Kennaway options->protocol = SSH_PROTO_UNKNOWN; 1715511b41d2SMark Murray options->num_identity_files = 0; 1716*acc1a9efSDag-Erling Smørgrav options->num_certificate_files = 0; 1717511b41d2SMark Murray options->hostname = NULL; 1718ca3176e7SBrian Feldman options->host_key_alias = NULL; 1719511b41d2SMark Murray options->proxy_command = NULL; 1720511b41d2SMark Murray options->user = NULL; 1721511b41d2SMark Murray options->escape_char = -1; 1722e146993eSDag-Erling Smørgrav options->num_system_hostfiles = 0; 1723e146993eSDag-Erling Smørgrav options->num_user_hostfiles = 0; 1724e2f6069cSDag-Erling Smørgrav options->local_forwards = NULL; 1725511b41d2SMark Murray options->num_local_forwards = 0; 1726e2f6069cSDag-Erling Smørgrav options->remote_forwards = NULL; 1727511b41d2SMark Murray options->num_remote_forwards = 0; 1728af12a3e7SDag-Erling Smørgrav options->clear_forwardings = -1; 1729af12a3e7SDag-Erling Smørgrav options->log_level = SYSLOG_LEVEL_NOT_SET; 1730ca3176e7SBrian Feldman options->preferred_authentications = NULL; 1731af12a3e7SDag-Erling Smørgrav options->bind_address = NULL; 1732b15c8340SDag-Erling Smørgrav options->pkcs11_provider = NULL; 1733e73e9afaSDag-Erling Smørgrav options->enable_ssh_keysign = - 1; 1734af12a3e7SDag-Erling Smørgrav options->no_host_authentication_for_localhost = - 1; 17355962c0e9SDag-Erling Smørgrav options->identities_only = - 1; 1736cf2b5f3bSDag-Erling Smørgrav options->rekey_limit = - 1; 1737e4a9863fSDag-Erling Smørgrav options->rekey_interval = -1; 1738cf2b5f3bSDag-Erling Smørgrav options->verify_host_key_dns = -1; 17391ec0d754SDag-Erling Smørgrav options->server_alive_interval = -1; 17401ec0d754SDag-Erling Smørgrav options->server_alive_count_max = -1; 174121e764dfSDag-Erling Smørgrav options->num_send_env = 0; 174221e764dfSDag-Erling Smørgrav options->control_path = NULL; 174321e764dfSDag-Erling Smørgrav options->control_master = -1; 1744e2f6069cSDag-Erling Smørgrav options->control_persist = -1; 1745e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = 0; 1746aa49c926SDag-Erling Smørgrav options->hash_known_hosts = -1; 1747b74df5b2SDag-Erling Smørgrav options->tun_open = -1; 1748b74df5b2SDag-Erling Smørgrav options->tun_local = -1; 1749b74df5b2SDag-Erling Smørgrav options->tun_remote = -1; 1750b74df5b2SDag-Erling Smørgrav options->local_command = NULL; 1751b74df5b2SDag-Erling Smørgrav options->permit_local_command = -1; 1752*acc1a9efSDag-Erling Smørgrav options->add_keys_to_agent = -1; 1753d4af9e69SDag-Erling Smørgrav options->visual_host_key = -1; 17544a421b63SDag-Erling Smørgrav options->ip_qos_interactive = -1; 17554a421b63SDag-Erling Smørgrav options->ip_qos_bulk = -1; 1756e146993eSDag-Erling Smørgrav options->request_tty = -1; 1757f7167e0eSDag-Erling Smørgrav options->proxy_use_fdpass = -1; 1758e4a9863fSDag-Erling Smørgrav options->ignored_unknown = NULL; 1759f7167e0eSDag-Erling Smørgrav options->num_canonical_domains = 0; 1760f7167e0eSDag-Erling Smørgrav options->num_permitted_cnames = 0; 1761f7167e0eSDag-Erling Smørgrav options->canonicalize_max_dots = -1; 1762f7167e0eSDag-Erling Smørgrav options->canonicalize_fallback_local = -1; 1763f7167e0eSDag-Erling Smørgrav options->canonicalize_hostname = -1; 1764bc5531deSDag-Erling Smørgrav options->revoked_host_keys = NULL; 1765bc5531deSDag-Erling Smørgrav options->fingerprint_hash = -1; 1766bc5531deSDag-Erling Smørgrav options->update_hostkeys = -1; 1767bc5531deSDag-Erling Smørgrav options->hostbased_key_types = NULL; 1768eccfee6eSDag-Erling Smørgrav options->pubkey_key_types = NULL; 1769511b41d2SMark Murray } 1770511b41d2SMark Murray 1771511b41d2SMark Murray /* 1772b83788ffSDag-Erling Smørgrav * A petite version of fill_default_options() that just fills the options 1773b83788ffSDag-Erling Smørgrav * needed for hostname canonicalization to proceed. 1774b83788ffSDag-Erling Smørgrav */ 1775b83788ffSDag-Erling Smørgrav void 1776b83788ffSDag-Erling Smørgrav fill_default_options_for_canonicalization(Options *options) 1777b83788ffSDag-Erling Smørgrav { 1778b83788ffSDag-Erling Smørgrav if (options->canonicalize_max_dots == -1) 1779b83788ffSDag-Erling Smørgrav options->canonicalize_max_dots = 1; 1780b83788ffSDag-Erling Smørgrav if (options->canonicalize_fallback_local == -1) 1781b83788ffSDag-Erling Smørgrav options->canonicalize_fallback_local = 1; 1782b83788ffSDag-Erling Smørgrav if (options->canonicalize_hostname == -1) 1783b83788ffSDag-Erling Smørgrav options->canonicalize_hostname = SSH_CANONICALISE_NO; 1784b83788ffSDag-Erling Smørgrav } 1785b83788ffSDag-Erling Smørgrav 1786b83788ffSDag-Erling Smørgrav /* 1787511b41d2SMark Murray * Called after processing other sources of option data, this fills those 1788511b41d2SMark Murray * options for which no value has been specified with their default values. 1789511b41d2SMark Murray */ 1790511b41d2SMark Murray void 1791511b41d2SMark Murray fill_default_options(Options * options) 1792511b41d2SMark Murray { 1793511b41d2SMark Murray if (options->forward_agent == -1) 1794db1cb46cSKris Kennaway options->forward_agent = 0; 1795511b41d2SMark Murray if (options->forward_x11 == -1) 17965dc73ebeSBrian Feldman options->forward_x11 = 0; 17971ec0d754SDag-Erling Smørgrav if (options->forward_x11_trusted == -1) 17981ec0d754SDag-Erling Smørgrav options->forward_x11_trusted = 0; 1799e2f6069cSDag-Erling Smørgrav if (options->forward_x11_timeout == -1) 1800e2f6069cSDag-Erling Smørgrav options->forward_x11_timeout = 1200; 1801333ee039SDag-Erling Smørgrav if (options->exit_on_forward_failure == -1) 1802333ee039SDag-Erling Smørgrav options->exit_on_forward_failure = 0; 1803c2d3a559SKris Kennaway if (options->xauth_location == NULL) 1804af12a3e7SDag-Erling Smørgrav options->xauth_location = _PATH_XAUTH; 1805a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.gateway_ports == -1) 1806a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.gateway_ports = 0; 1807a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 1808a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_mask = 0177; 1809a0ee8cc6SDag-Erling Smørgrav if (options->fwd_opts.streamlocal_bind_unlink == -1) 1810a0ee8cc6SDag-Erling Smørgrav options->fwd_opts.streamlocal_bind_unlink = 0; 1811511b41d2SMark Murray if (options->use_privileged_port == -1) 1812ca3176e7SBrian Feldman options->use_privileged_port = 0; 1813511b41d2SMark Murray if (options->rsa_authentication == -1) 1814511b41d2SMark Murray options->rsa_authentication = 1; 1815ca3176e7SBrian Feldman if (options->pubkey_authentication == -1) 1816ca3176e7SBrian Feldman options->pubkey_authentication = 1; 1817af12a3e7SDag-Erling Smørgrav if (options->challenge_response_authentication == -1) 1818af12a3e7SDag-Erling Smørgrav options->challenge_response_authentication = 1; 1819cf2b5f3bSDag-Erling Smørgrav if (options->gss_authentication == -1) 18201ec0d754SDag-Erling Smørgrav options->gss_authentication = 0; 1821cf2b5f3bSDag-Erling Smørgrav if (options->gss_deleg_creds == -1) 1822cf2b5f3bSDag-Erling Smørgrav options->gss_deleg_creds = 0; 1823511b41d2SMark Murray if (options->password_authentication == -1) 1824511b41d2SMark Murray options->password_authentication = 1; 182509958426SBrian Feldman if (options->kbd_interactive_authentication == -1) 1826ca3176e7SBrian Feldman options->kbd_interactive_authentication = 1; 1827511b41d2SMark Murray if (options->rhosts_rsa_authentication == -1) 182880628bacSDag-Erling Smørgrav options->rhosts_rsa_authentication = 0; 1829ca3176e7SBrian Feldman if (options->hostbased_authentication == -1) 1830ca3176e7SBrian Feldman options->hostbased_authentication = 0; 1831511b41d2SMark Murray if (options->batch_mode == -1) 1832511b41d2SMark Murray options->batch_mode = 0; 1833511b41d2SMark Murray if (options->check_host_ip == -1) 1834975616f0SDag-Erling Smørgrav options->check_host_ip = 0; 1835511b41d2SMark Murray if (options->strict_host_key_checking == -1) 1836511b41d2SMark Murray options->strict_host_key_checking = 2; /* 2 is default */ 1837511b41d2SMark Murray if (options->compression == -1) 1838511b41d2SMark Murray options->compression = 0; 18391ec0d754SDag-Erling Smørgrav if (options->tcp_keep_alive == -1) 18401ec0d754SDag-Erling Smørgrav options->tcp_keep_alive = 1; 1841511b41d2SMark Murray if (options->compression_level == -1) 1842511b41d2SMark Murray options->compression_level = 6; 1843511b41d2SMark Murray if (options->port == -1) 1844511b41d2SMark Murray options->port = 0; /* Filled in ssh_connect. */ 1845cf2b5f3bSDag-Erling Smørgrav if (options->address_family == -1) 1846cf2b5f3bSDag-Erling Smørgrav options->address_family = AF_UNSPEC; 1847511b41d2SMark Murray if (options->connection_attempts == -1) 1848af12a3e7SDag-Erling Smørgrav options->connection_attempts = 1; 1849511b41d2SMark Murray if (options->number_of_password_prompts == -1) 1850511b41d2SMark Murray options->number_of_password_prompts = 3; 1851511b41d2SMark Murray /* Selected in ssh_login(). */ 1852511b41d2SMark Murray if (options->cipher == -1) 1853511b41d2SMark Murray options->cipher = SSH_CIPHER_NOT_SET; 1854ca3176e7SBrian Feldman /* options->hostkeyalgorithms, default set in myproposals.h */ 1855e8aafc91SKris Kennaway if (options->protocol == SSH_PROTO_UNKNOWN) 1856b15c8340SDag-Erling Smørgrav options->protocol = SSH_PROTO_2; 1857*acc1a9efSDag-Erling Smørgrav if (options->add_keys_to_agent == -1) 1858*acc1a9efSDag-Erling Smørgrav options->add_keys_to_agent = 0; 1859511b41d2SMark Murray if (options->num_identity_files == 0) { 1860ca3176e7SBrian Feldman if (options->protocol & SSH_PROTO_1) { 186173370613SDag-Erling Smørgrav add_identity_file(options, "~/", 186273370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_IDENTITY, 0); 1863511b41d2SMark Murray } 1864ca3176e7SBrian Feldman if (options->protocol & SSH_PROTO_2) { 186573370613SDag-Erling Smørgrav add_identity_file(options, "~/", 186673370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_RSA, 0); 186773370613SDag-Erling Smørgrav add_identity_file(options, "~/", 186873370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_DSA, 0); 18694a421b63SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 187073370613SDag-Erling Smørgrav add_identity_file(options, "~/", 187173370613SDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_ECDSA, 0); 18724a421b63SDag-Erling Smørgrav #endif 1873f7167e0eSDag-Erling Smørgrav add_identity_file(options, "~/", 1874f7167e0eSDag-Erling Smørgrav _PATH_SSH_CLIENT_ID_ED25519, 0); 1875ca3176e7SBrian Feldman } 1876e8aafc91SKris Kennaway } 1877511b41d2SMark Murray if (options->escape_char == -1) 1878511b41d2SMark Murray options->escape_char = '~'; 1879e146993eSDag-Erling Smørgrav if (options->num_system_hostfiles == 0) { 1880e146993eSDag-Erling Smørgrav options->system_hostfiles[options->num_system_hostfiles++] = 1881e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1882e146993eSDag-Erling Smørgrav options->system_hostfiles[options->num_system_hostfiles++] = 1883e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1884e146993eSDag-Erling Smørgrav } 1885e146993eSDag-Erling Smørgrav if (options->num_user_hostfiles == 0) { 1886e146993eSDag-Erling Smørgrav options->user_hostfiles[options->num_user_hostfiles++] = 1887e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_USER_HOSTFILE); 1888e146993eSDag-Erling Smørgrav options->user_hostfiles[options->num_user_hostfiles++] = 1889e146993eSDag-Erling Smørgrav xstrdup(_PATH_SSH_USER_HOSTFILE2); 1890e146993eSDag-Erling Smørgrav } 1891af12a3e7SDag-Erling Smørgrav if (options->log_level == SYSLOG_LEVEL_NOT_SET) 1892511b41d2SMark Murray options->log_level = SYSLOG_LEVEL_INFO; 1893af12a3e7SDag-Erling Smørgrav if (options->clear_forwardings == 1) 1894af12a3e7SDag-Erling Smørgrav clear_forwardings(options); 1895af12a3e7SDag-Erling Smørgrav if (options->no_host_authentication_for_localhost == - 1) 1896af12a3e7SDag-Erling Smørgrav options->no_host_authentication_for_localhost = 0; 18975962c0e9SDag-Erling Smørgrav if (options->identities_only == -1) 18985962c0e9SDag-Erling Smørgrav options->identities_only = 0; 1899e73e9afaSDag-Erling Smørgrav if (options->enable_ssh_keysign == -1) 1900e73e9afaSDag-Erling Smørgrav options->enable_ssh_keysign = 0; 1901cf2b5f3bSDag-Erling Smørgrav if (options->rekey_limit == -1) 1902cf2b5f3bSDag-Erling Smørgrav options->rekey_limit = 0; 1903e4a9863fSDag-Erling Smørgrav if (options->rekey_interval == -1) 1904e4a9863fSDag-Erling Smørgrav options->rekey_interval = 0; 190583c6a524SDag-Erling Smørgrav #if HAVE_LDNS 190683c6a524SDag-Erling Smørgrav if (options->verify_host_key_dns == -1) 190783c6a524SDag-Erling Smørgrav /* automatically trust a verified SSHFP record */ 190883c6a524SDag-Erling Smørgrav options->verify_host_key_dns = 1; 190983c6a524SDag-Erling Smørgrav #else 1910cf2b5f3bSDag-Erling Smørgrav if (options->verify_host_key_dns == -1) 1911cf2b5f3bSDag-Erling Smørgrav options->verify_host_key_dns = 0; 191283c6a524SDag-Erling Smørgrav #endif 19131ec0d754SDag-Erling Smørgrav if (options->server_alive_interval == -1) 19141ec0d754SDag-Erling Smørgrav options->server_alive_interval = 0; 19151ec0d754SDag-Erling Smørgrav if (options->server_alive_count_max == -1) 19161ec0d754SDag-Erling Smørgrav options->server_alive_count_max = 3; 191721e764dfSDag-Erling Smørgrav if (options->control_master == -1) 191821e764dfSDag-Erling Smørgrav options->control_master = 0; 1919e2f6069cSDag-Erling Smørgrav if (options->control_persist == -1) { 1920e2f6069cSDag-Erling Smørgrav options->control_persist = 0; 1921e2f6069cSDag-Erling Smørgrav options->control_persist_timeout = 0; 1922e2f6069cSDag-Erling Smørgrav } 1923aa49c926SDag-Erling Smørgrav if (options->hash_known_hosts == -1) 1924aa49c926SDag-Erling Smørgrav options->hash_known_hosts = 0; 1925b74df5b2SDag-Erling Smørgrav if (options->tun_open == -1) 1926b74df5b2SDag-Erling Smørgrav options->tun_open = SSH_TUNMODE_NO; 1927b74df5b2SDag-Erling Smørgrav if (options->tun_local == -1) 1928b74df5b2SDag-Erling Smørgrav options->tun_local = SSH_TUNID_ANY; 1929b74df5b2SDag-Erling Smørgrav if (options->tun_remote == -1) 1930b74df5b2SDag-Erling Smørgrav options->tun_remote = SSH_TUNID_ANY; 1931b74df5b2SDag-Erling Smørgrav if (options->permit_local_command == -1) 1932b74df5b2SDag-Erling Smørgrav options->permit_local_command = 0; 1933d4af9e69SDag-Erling Smørgrav if (options->visual_host_key == -1) 1934d4af9e69SDag-Erling Smørgrav options->visual_host_key = 0; 19354a421b63SDag-Erling Smørgrav if (options->ip_qos_interactive == -1) 19364a421b63SDag-Erling Smørgrav options->ip_qos_interactive = IPTOS_LOWDELAY; 19374a421b63SDag-Erling Smørgrav if (options->ip_qos_bulk == -1) 19384a421b63SDag-Erling Smørgrav options->ip_qos_bulk = IPTOS_THROUGHPUT; 1939e146993eSDag-Erling Smørgrav if (options->request_tty == -1) 1940e146993eSDag-Erling Smørgrav options->request_tty = REQUEST_TTY_AUTO; 1941f7167e0eSDag-Erling Smørgrav if (options->proxy_use_fdpass == -1) 1942f7167e0eSDag-Erling Smørgrav options->proxy_use_fdpass = 0; 1943f7167e0eSDag-Erling Smørgrav if (options->canonicalize_max_dots == -1) 1944f7167e0eSDag-Erling Smørgrav options->canonicalize_max_dots = 1; 1945f7167e0eSDag-Erling Smørgrav if (options->canonicalize_fallback_local == -1) 1946f7167e0eSDag-Erling Smørgrav options->canonicalize_fallback_local = 1; 1947f7167e0eSDag-Erling Smørgrav if (options->canonicalize_hostname == -1) 1948f7167e0eSDag-Erling Smørgrav options->canonicalize_hostname = SSH_CANONICALISE_NO; 1949bc5531deSDag-Erling Smørgrav if (options->fingerprint_hash == -1) 1950bc5531deSDag-Erling Smørgrav options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 1951bc5531deSDag-Erling Smørgrav if (options->update_hostkeys == -1) 1952bc5531deSDag-Erling Smørgrav options->update_hostkeys = 0; 1953eccfee6eSDag-Erling Smørgrav if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || 1954eccfee6eSDag-Erling Smørgrav kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || 1955eccfee6eSDag-Erling Smørgrav kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || 1956eccfee6eSDag-Erling Smørgrav kex_assemble_names(KEX_DEFAULT_PK_ALG, 1957eccfee6eSDag-Erling Smørgrav &options->hostbased_key_types) != 0 || 1958eccfee6eSDag-Erling Smørgrav kex_assemble_names(KEX_DEFAULT_PK_ALG, 1959eccfee6eSDag-Erling Smørgrav &options->pubkey_key_types) != 0) 1960eccfee6eSDag-Erling Smørgrav fatal("%s: kex_assemble_names failed", __func__); 1961bc5531deSDag-Erling Smørgrav 1962f7167e0eSDag-Erling Smørgrav #define CLEAR_ON_NONE(v) \ 1963f7167e0eSDag-Erling Smørgrav do { \ 1964b83788ffSDag-Erling Smørgrav if (option_clear_or_none(v)) { \ 1965f7167e0eSDag-Erling Smørgrav free(v); \ 1966f7167e0eSDag-Erling Smørgrav v = NULL; \ 1967f7167e0eSDag-Erling Smørgrav } \ 1968f7167e0eSDag-Erling Smørgrav } while(0) 1969f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->local_command); 1970f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->proxy_command); 1971f7167e0eSDag-Erling Smørgrav CLEAR_ON_NONE(options->control_path); 1972bc5531deSDag-Erling Smørgrav CLEAR_ON_NONE(options->revoked_host_keys); 1973511b41d2SMark Murray /* options->user will be set in the main program if appropriate */ 1974511b41d2SMark Murray /* options->hostname will be set in the main program if appropriate */ 1975ca3176e7SBrian Feldman /* options->host_key_alias should not be set by default */ 1976ca3176e7SBrian Feldman /* options->preferred_authentications will be set in ssh */ 1977462c32cbSDag-Erling Smørgrav if (options->version_addendum == NULL) 1978462c32cbSDag-Erling Smørgrav options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 1979511b41d2SMark Murray } 1980aa49c926SDag-Erling Smørgrav 1981a0ee8cc6SDag-Erling Smørgrav struct fwdarg { 1982a0ee8cc6SDag-Erling Smørgrav char *arg; 1983a0ee8cc6SDag-Erling Smørgrav int ispath; 1984a0ee8cc6SDag-Erling Smørgrav }; 1985a0ee8cc6SDag-Erling Smørgrav 1986a0ee8cc6SDag-Erling Smørgrav /* 1987a0ee8cc6SDag-Erling Smørgrav * parse_fwd_field 1988a0ee8cc6SDag-Erling Smørgrav * parses the next field in a port forwarding specification. 1989a0ee8cc6SDag-Erling Smørgrav * sets fwd to the parsed field and advances p past the colon 1990a0ee8cc6SDag-Erling Smørgrav * or sets it to NULL at end of string. 1991a0ee8cc6SDag-Erling Smørgrav * returns 0 on success, else non-zero. 1992a0ee8cc6SDag-Erling Smørgrav */ 1993a0ee8cc6SDag-Erling Smørgrav static int 1994a0ee8cc6SDag-Erling Smørgrav parse_fwd_field(char **p, struct fwdarg *fwd) 1995a0ee8cc6SDag-Erling Smørgrav { 1996a0ee8cc6SDag-Erling Smørgrav char *ep, *cp = *p; 1997a0ee8cc6SDag-Erling Smørgrav int ispath = 0; 1998a0ee8cc6SDag-Erling Smørgrav 1999a0ee8cc6SDag-Erling Smørgrav if (*cp == '\0') { 2000a0ee8cc6SDag-Erling Smørgrav *p = NULL; 2001a0ee8cc6SDag-Erling Smørgrav return -1; /* end of string */ 2002a0ee8cc6SDag-Erling Smørgrav } 2003a0ee8cc6SDag-Erling Smørgrav 2004a0ee8cc6SDag-Erling Smørgrav /* 2005a0ee8cc6SDag-Erling Smørgrav * A field escaped with square brackets is used literally. 2006a0ee8cc6SDag-Erling Smørgrav * XXX - allow ']' to be escaped via backslash? 2007a0ee8cc6SDag-Erling Smørgrav */ 2008a0ee8cc6SDag-Erling Smørgrav if (*cp == '[') { 2009a0ee8cc6SDag-Erling Smørgrav /* find matching ']' */ 2010a0ee8cc6SDag-Erling Smørgrav for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2011a0ee8cc6SDag-Erling Smørgrav if (*ep == '/') 2012a0ee8cc6SDag-Erling Smørgrav ispath = 1; 2013a0ee8cc6SDag-Erling Smørgrav } 2014a0ee8cc6SDag-Erling Smørgrav /* no matching ']' or not at end of field. */ 2015a0ee8cc6SDag-Erling Smørgrav if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2016a0ee8cc6SDag-Erling Smørgrav return -1; 2017a0ee8cc6SDag-Erling Smørgrav /* NUL terminate the field and advance p past the colon */ 2018a0ee8cc6SDag-Erling Smørgrav *ep++ = '\0'; 2019a0ee8cc6SDag-Erling Smørgrav if (*ep != '\0') 2020a0ee8cc6SDag-Erling Smørgrav *ep++ = '\0'; 2021a0ee8cc6SDag-Erling Smørgrav fwd->arg = cp + 1; 2022a0ee8cc6SDag-Erling Smørgrav fwd->ispath = ispath; 2023a0ee8cc6SDag-Erling Smørgrav *p = ep; 2024a0ee8cc6SDag-Erling Smørgrav return 0; 2025a0ee8cc6SDag-Erling Smørgrav } 2026a0ee8cc6SDag-Erling Smørgrav 2027a0ee8cc6SDag-Erling Smørgrav for (cp = *p; *cp != '\0'; cp++) { 2028a0ee8cc6SDag-Erling Smørgrav switch (*cp) { 2029a0ee8cc6SDag-Erling Smørgrav case '\\': 2030a0ee8cc6SDag-Erling Smørgrav memmove(cp, cp + 1, strlen(cp + 1) + 1); 2031557f75e5SDag-Erling Smørgrav if (*cp == '\0') 2032557f75e5SDag-Erling Smørgrav return -1; 2033a0ee8cc6SDag-Erling Smørgrav break; 2034a0ee8cc6SDag-Erling Smørgrav case '/': 2035a0ee8cc6SDag-Erling Smørgrav ispath = 1; 2036a0ee8cc6SDag-Erling Smørgrav break; 2037a0ee8cc6SDag-Erling Smørgrav case ':': 2038a0ee8cc6SDag-Erling Smørgrav *cp++ = '\0'; 2039a0ee8cc6SDag-Erling Smørgrav goto done; 2040a0ee8cc6SDag-Erling Smørgrav } 2041a0ee8cc6SDag-Erling Smørgrav } 2042a0ee8cc6SDag-Erling Smørgrav done: 2043a0ee8cc6SDag-Erling Smørgrav fwd->arg = *p; 2044a0ee8cc6SDag-Erling Smørgrav fwd->ispath = ispath; 2045a0ee8cc6SDag-Erling Smørgrav *p = cp; 2046a0ee8cc6SDag-Erling Smørgrav return 0; 2047a0ee8cc6SDag-Erling Smørgrav } 2048a0ee8cc6SDag-Erling Smørgrav 2049aa49c926SDag-Erling Smørgrav /* 2050aa49c926SDag-Erling Smørgrav * parse_forward 2051aa49c926SDag-Erling Smørgrav * parses a string containing a port forwarding specification of the form: 2052cce7d346SDag-Erling Smørgrav * dynamicfwd == 0 2053a0ee8cc6SDag-Erling Smørgrav * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2054a0ee8cc6SDag-Erling Smørgrav * listenpath:connectpath 2055cce7d346SDag-Erling Smørgrav * dynamicfwd == 1 2056cce7d346SDag-Erling Smørgrav * [listenhost:]listenport 2057aa49c926SDag-Erling Smørgrav * returns number of arguments parsed or zero on error 2058aa49c926SDag-Erling Smørgrav */ 2059aa49c926SDag-Erling Smørgrav int 2060a0ee8cc6SDag-Erling Smørgrav parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2061aa49c926SDag-Erling Smørgrav { 2062a0ee8cc6SDag-Erling Smørgrav struct fwdarg fwdargs[4]; 2063a0ee8cc6SDag-Erling Smørgrav char *p, *cp; 2064aa49c926SDag-Erling Smørgrav int i; 2065aa49c926SDag-Erling Smørgrav 2066a0ee8cc6SDag-Erling Smørgrav memset(fwd, 0, sizeof(*fwd)); 2067a0ee8cc6SDag-Erling Smørgrav memset(fwdargs, 0, sizeof(fwdargs)); 2068aa49c926SDag-Erling Smørgrav 2069aa49c926SDag-Erling Smørgrav cp = p = xstrdup(fwdspec); 2070aa49c926SDag-Erling Smørgrav 2071aa49c926SDag-Erling Smørgrav /* skip leading spaces */ 2072f7167e0eSDag-Erling Smørgrav while (isspace((u_char)*cp)) 2073aa49c926SDag-Erling Smørgrav cp++; 2074aa49c926SDag-Erling Smørgrav 2075a0ee8cc6SDag-Erling Smørgrav for (i = 0; i < 4; ++i) { 2076a0ee8cc6SDag-Erling Smørgrav if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2077aa49c926SDag-Erling Smørgrav break; 2078a0ee8cc6SDag-Erling Smørgrav } 2079aa49c926SDag-Erling Smørgrav 2080cce7d346SDag-Erling Smørgrav /* Check for trailing garbage */ 2081a0ee8cc6SDag-Erling Smørgrav if (cp != NULL && *cp != '\0') { 2082aa49c926SDag-Erling Smørgrav i = 0; /* failure */ 2083a0ee8cc6SDag-Erling Smørgrav } 2084aa49c926SDag-Erling Smørgrav 2085aa49c926SDag-Erling Smørgrav switch (i) { 2086cce7d346SDag-Erling Smørgrav case 1: 2087a0ee8cc6SDag-Erling Smørgrav if (fwdargs[0].ispath) { 2088a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = xstrdup(fwdargs[0].arg); 2089a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = PORT_STREAMLOCAL; 2090a0ee8cc6SDag-Erling Smørgrav } else { 2091cce7d346SDag-Erling Smørgrav fwd->listen_host = NULL; 2092a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[0].arg); 2093a0ee8cc6SDag-Erling Smørgrav } 2094cce7d346SDag-Erling Smørgrav fwd->connect_host = xstrdup("socks"); 2095cce7d346SDag-Erling Smørgrav break; 2096cce7d346SDag-Erling Smørgrav 2097cce7d346SDag-Erling Smørgrav case 2: 2098a0ee8cc6SDag-Erling Smørgrav if (fwdargs[0].ispath && fwdargs[1].ispath) { 2099a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = xstrdup(fwdargs[0].arg); 2100a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = PORT_STREAMLOCAL; 2101a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = xstrdup(fwdargs[1].arg); 2102a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = PORT_STREAMLOCAL; 2103a0ee8cc6SDag-Erling Smørgrav } else if (fwdargs[1].ispath) { 2104a0ee8cc6SDag-Erling Smørgrav fwd->listen_host = NULL; 2105a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[0].arg); 2106a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = xstrdup(fwdargs[1].arg); 2107a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = PORT_STREAMLOCAL; 2108a0ee8cc6SDag-Erling Smørgrav } else { 2109a0ee8cc6SDag-Erling Smørgrav fwd->listen_host = xstrdup(fwdargs[0].arg); 2110a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[1].arg); 2111cce7d346SDag-Erling Smørgrav fwd->connect_host = xstrdup("socks"); 2112a0ee8cc6SDag-Erling Smørgrav } 2113cce7d346SDag-Erling Smørgrav break; 2114cce7d346SDag-Erling Smørgrav 2115aa49c926SDag-Erling Smørgrav case 3: 2116a0ee8cc6SDag-Erling Smørgrav if (fwdargs[0].ispath) { 2117a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = xstrdup(fwdargs[0].arg); 2118a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = PORT_STREAMLOCAL; 2119a0ee8cc6SDag-Erling Smørgrav fwd->connect_host = xstrdup(fwdargs[1].arg); 2120a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = a2port(fwdargs[2].arg); 2121a0ee8cc6SDag-Erling Smørgrav } else if (fwdargs[2].ispath) { 2122a0ee8cc6SDag-Erling Smørgrav fwd->listen_host = xstrdup(fwdargs[0].arg); 2123a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[1].arg); 2124a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = xstrdup(fwdargs[2].arg); 2125a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = PORT_STREAMLOCAL; 2126a0ee8cc6SDag-Erling Smørgrav } else { 2127aa49c926SDag-Erling Smørgrav fwd->listen_host = NULL; 2128a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[0].arg); 2129a0ee8cc6SDag-Erling Smørgrav fwd->connect_host = xstrdup(fwdargs[1].arg); 2130a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = a2port(fwdargs[2].arg); 2131a0ee8cc6SDag-Erling Smørgrav } 2132aa49c926SDag-Erling Smørgrav break; 2133aa49c926SDag-Erling Smørgrav 2134aa49c926SDag-Erling Smørgrav case 4: 2135a0ee8cc6SDag-Erling Smørgrav fwd->listen_host = xstrdup(fwdargs[0].arg); 2136a0ee8cc6SDag-Erling Smørgrav fwd->listen_port = a2port(fwdargs[1].arg); 2137a0ee8cc6SDag-Erling Smørgrav fwd->connect_host = xstrdup(fwdargs[2].arg); 2138a0ee8cc6SDag-Erling Smørgrav fwd->connect_port = a2port(fwdargs[3].arg); 2139aa49c926SDag-Erling Smørgrav break; 2140aa49c926SDag-Erling Smørgrav default: 2141aa49c926SDag-Erling Smørgrav i = 0; /* failure */ 2142aa49c926SDag-Erling Smørgrav } 2143aa49c926SDag-Erling Smørgrav 2144e4a9863fSDag-Erling Smørgrav free(p); 2145aa49c926SDag-Erling Smørgrav 2146cce7d346SDag-Erling Smørgrav if (dynamicfwd) { 2147cce7d346SDag-Erling Smørgrav if (!(i == 1 || i == 2)) 2148cce7d346SDag-Erling Smørgrav goto fail_free; 2149cce7d346SDag-Erling Smørgrav } else { 2150a0ee8cc6SDag-Erling Smørgrav if (!(i == 3 || i == 4)) { 2151a0ee8cc6SDag-Erling Smørgrav if (fwd->connect_path == NULL && 2152a0ee8cc6SDag-Erling Smørgrav fwd->listen_path == NULL) 2153cce7d346SDag-Erling Smørgrav goto fail_free; 2154a0ee8cc6SDag-Erling Smørgrav } 2155a0ee8cc6SDag-Erling Smørgrav if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2156cce7d346SDag-Erling Smørgrav goto fail_free; 2157cce7d346SDag-Erling Smørgrav } 2158cce7d346SDag-Erling Smørgrav 2159a0ee8cc6SDag-Erling Smørgrav if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2160a0ee8cc6SDag-Erling Smørgrav (!remotefwd && fwd->listen_port == 0)) 2161aa49c926SDag-Erling Smørgrav goto fail_free; 2162aa49c926SDag-Erling Smørgrav if (fwd->connect_host != NULL && 2163aa49c926SDag-Erling Smørgrav strlen(fwd->connect_host) >= NI_MAXHOST) 2164aa49c926SDag-Erling Smørgrav goto fail_free; 2165a0ee8cc6SDag-Erling Smørgrav /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2166a0ee8cc6SDag-Erling Smørgrav if (fwd->connect_path != NULL && 2167a0ee8cc6SDag-Erling Smørgrav strlen(fwd->connect_path) >= PATH_MAX_SUN) 2168a0ee8cc6SDag-Erling Smørgrav goto fail_free; 2169cce7d346SDag-Erling Smørgrav if (fwd->listen_host != NULL && 2170cce7d346SDag-Erling Smørgrav strlen(fwd->listen_host) >= NI_MAXHOST) 2171cce7d346SDag-Erling Smørgrav goto fail_free; 2172a0ee8cc6SDag-Erling Smørgrav if (fwd->listen_path != NULL && 2173a0ee8cc6SDag-Erling Smørgrav strlen(fwd->listen_path) >= PATH_MAX_SUN) 2174a0ee8cc6SDag-Erling Smørgrav goto fail_free; 2175aa49c926SDag-Erling Smørgrav 2176aa49c926SDag-Erling Smørgrav return (i); 2177aa49c926SDag-Erling Smørgrav 2178aa49c926SDag-Erling Smørgrav fail_free: 2179e4a9863fSDag-Erling Smørgrav free(fwd->connect_host); 2180cce7d346SDag-Erling Smørgrav fwd->connect_host = NULL; 2181a0ee8cc6SDag-Erling Smørgrav free(fwd->connect_path); 2182a0ee8cc6SDag-Erling Smørgrav fwd->connect_path = NULL; 2183e4a9863fSDag-Erling Smørgrav free(fwd->listen_host); 2184cce7d346SDag-Erling Smørgrav fwd->listen_host = NULL; 2185a0ee8cc6SDag-Erling Smørgrav free(fwd->listen_path); 2186a0ee8cc6SDag-Erling Smørgrav fwd->listen_path = NULL; 2187aa49c926SDag-Erling Smørgrav return (0); 2188aa49c926SDag-Erling Smørgrav } 2189bc5531deSDag-Erling Smørgrav 2190bc5531deSDag-Erling Smørgrav /* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2191bc5531deSDag-Erling Smørgrav static const char * 2192bc5531deSDag-Erling Smørgrav fmt_multistate_int(int val, const struct multistate *m) 2193bc5531deSDag-Erling Smørgrav { 2194bc5531deSDag-Erling Smørgrav u_int i; 2195bc5531deSDag-Erling Smørgrav 2196bc5531deSDag-Erling Smørgrav for (i = 0; m[i].key != NULL; i++) { 2197bc5531deSDag-Erling Smørgrav if (m[i].value == val) 2198bc5531deSDag-Erling Smørgrav return m[i].key; 2199bc5531deSDag-Erling Smørgrav } 2200bc5531deSDag-Erling Smørgrav return "UNKNOWN"; 2201bc5531deSDag-Erling Smørgrav } 2202bc5531deSDag-Erling Smørgrav 2203bc5531deSDag-Erling Smørgrav static const char * 2204bc5531deSDag-Erling Smørgrav fmt_intarg(OpCodes code, int val) 2205bc5531deSDag-Erling Smørgrav { 2206bc5531deSDag-Erling Smørgrav if (val == -1) 2207bc5531deSDag-Erling Smørgrav return "unset"; 2208bc5531deSDag-Erling Smørgrav switch (code) { 2209bc5531deSDag-Erling Smørgrav case oAddressFamily: 2210bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_addressfamily); 2211bc5531deSDag-Erling Smørgrav case oVerifyHostKeyDNS: 2212bc5531deSDag-Erling Smørgrav case oStrictHostKeyChecking: 2213bc5531deSDag-Erling Smørgrav case oUpdateHostkeys: 2214bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_yesnoask); 2215bc5531deSDag-Erling Smørgrav case oControlMaster: 2216bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_controlmaster); 2217bc5531deSDag-Erling Smørgrav case oTunnel: 2218bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_tunnel); 2219bc5531deSDag-Erling Smørgrav case oRequestTTY: 2220bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_requesttty); 2221bc5531deSDag-Erling Smørgrav case oCanonicalizeHostname: 2222bc5531deSDag-Erling Smørgrav return fmt_multistate_int(val, multistate_canonicalizehostname); 2223bc5531deSDag-Erling Smørgrav case oFingerprintHash: 2224bc5531deSDag-Erling Smørgrav return ssh_digest_alg_name(val); 2225bc5531deSDag-Erling Smørgrav case oProtocol: 2226bc5531deSDag-Erling Smørgrav switch (val) { 2227bc5531deSDag-Erling Smørgrav case SSH_PROTO_1: 2228bc5531deSDag-Erling Smørgrav return "1"; 2229bc5531deSDag-Erling Smørgrav case SSH_PROTO_2: 2230bc5531deSDag-Erling Smørgrav return "2"; 2231bc5531deSDag-Erling Smørgrav case (SSH_PROTO_1|SSH_PROTO_2): 2232bc5531deSDag-Erling Smørgrav return "2,1"; 2233bc5531deSDag-Erling Smørgrav default: 2234bc5531deSDag-Erling Smørgrav return "UNKNOWN"; 2235bc5531deSDag-Erling Smørgrav } 2236bc5531deSDag-Erling Smørgrav default: 2237bc5531deSDag-Erling Smørgrav switch (val) { 2238bc5531deSDag-Erling Smørgrav case 0: 2239bc5531deSDag-Erling Smørgrav return "no"; 2240bc5531deSDag-Erling Smørgrav case 1: 2241bc5531deSDag-Erling Smørgrav return "yes"; 2242bc5531deSDag-Erling Smørgrav default: 2243bc5531deSDag-Erling Smørgrav return "UNKNOWN"; 2244bc5531deSDag-Erling Smørgrav } 2245bc5531deSDag-Erling Smørgrav } 2246bc5531deSDag-Erling Smørgrav } 2247bc5531deSDag-Erling Smørgrav 2248bc5531deSDag-Erling Smørgrav static const char * 2249bc5531deSDag-Erling Smørgrav lookup_opcode_name(OpCodes code) 2250bc5531deSDag-Erling Smørgrav { 2251bc5531deSDag-Erling Smørgrav u_int i; 2252bc5531deSDag-Erling Smørgrav 2253bc5531deSDag-Erling Smørgrav for (i = 0; keywords[i].name != NULL; i++) 2254bc5531deSDag-Erling Smørgrav if (keywords[i].opcode == code) 2255bc5531deSDag-Erling Smørgrav return(keywords[i].name); 2256bc5531deSDag-Erling Smørgrav return "UNKNOWN"; 2257bc5531deSDag-Erling Smørgrav } 2258bc5531deSDag-Erling Smørgrav 2259bc5531deSDag-Erling Smørgrav static void 2260bc5531deSDag-Erling Smørgrav dump_cfg_int(OpCodes code, int val) 2261bc5531deSDag-Erling Smørgrav { 2262bc5531deSDag-Erling Smørgrav printf("%s %d\n", lookup_opcode_name(code), val); 2263bc5531deSDag-Erling Smørgrav } 2264bc5531deSDag-Erling Smørgrav 2265bc5531deSDag-Erling Smørgrav static void 2266bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(OpCodes code, int val) 2267bc5531deSDag-Erling Smørgrav { 2268bc5531deSDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2269bc5531deSDag-Erling Smørgrav } 2270bc5531deSDag-Erling Smørgrav 2271bc5531deSDag-Erling Smørgrav static void 2272bc5531deSDag-Erling Smørgrav dump_cfg_string(OpCodes code, const char *val) 2273bc5531deSDag-Erling Smørgrav { 2274bc5531deSDag-Erling Smørgrav if (val == NULL) 2275bc5531deSDag-Erling Smørgrav return; 2276bc5531deSDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), val); 2277bc5531deSDag-Erling Smørgrav } 2278bc5531deSDag-Erling Smørgrav 2279bc5531deSDag-Erling Smørgrav static void 2280bc5531deSDag-Erling Smørgrav dump_cfg_strarray(OpCodes code, u_int count, char **vals) 2281bc5531deSDag-Erling Smørgrav { 2282bc5531deSDag-Erling Smørgrav u_int i; 2283bc5531deSDag-Erling Smørgrav 2284bc5531deSDag-Erling Smørgrav for (i = 0; i < count; i++) 2285bc5531deSDag-Erling Smørgrav printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2286bc5531deSDag-Erling Smørgrav } 2287bc5531deSDag-Erling Smørgrav 2288bc5531deSDag-Erling Smørgrav static void 2289bc5531deSDag-Erling Smørgrav dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2290bc5531deSDag-Erling Smørgrav { 2291bc5531deSDag-Erling Smørgrav u_int i; 2292bc5531deSDag-Erling Smørgrav 2293bc5531deSDag-Erling Smørgrav printf("%s", lookup_opcode_name(code)); 2294bc5531deSDag-Erling Smørgrav for (i = 0; i < count; i++) 2295bc5531deSDag-Erling Smørgrav printf(" %s", vals[i]); 2296bc5531deSDag-Erling Smørgrav printf("\n"); 2297bc5531deSDag-Erling Smørgrav } 2298bc5531deSDag-Erling Smørgrav 2299bc5531deSDag-Erling Smørgrav static void 2300bc5531deSDag-Erling Smørgrav dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2301bc5531deSDag-Erling Smørgrav { 2302bc5531deSDag-Erling Smørgrav const struct Forward *fwd; 2303bc5531deSDag-Erling Smørgrav u_int i; 2304bc5531deSDag-Erling Smørgrav 2305bc5531deSDag-Erling Smørgrav /* oDynamicForward */ 2306bc5531deSDag-Erling Smørgrav for (i = 0; i < count; i++) { 2307bc5531deSDag-Erling Smørgrav fwd = &fwds[i]; 2308bc5531deSDag-Erling Smørgrav if (code == oDynamicForward && 2309bc5531deSDag-Erling Smørgrav strcmp(fwd->connect_host, "socks") != 0) 2310bc5531deSDag-Erling Smørgrav continue; 2311bc5531deSDag-Erling Smørgrav if (code == oLocalForward && 2312bc5531deSDag-Erling Smørgrav strcmp(fwd->connect_host, "socks") == 0) 2313bc5531deSDag-Erling Smørgrav continue; 2314bc5531deSDag-Erling Smørgrav printf("%s", lookup_opcode_name(code)); 2315bc5531deSDag-Erling Smørgrav if (fwd->listen_port == PORT_STREAMLOCAL) 2316bc5531deSDag-Erling Smørgrav printf(" %s", fwd->listen_path); 2317bc5531deSDag-Erling Smørgrav else if (fwd->listen_host == NULL) 2318bc5531deSDag-Erling Smørgrav printf(" %d", fwd->listen_port); 2319bc5531deSDag-Erling Smørgrav else { 2320bc5531deSDag-Erling Smørgrav printf(" [%s]:%d", 2321bc5531deSDag-Erling Smørgrav fwd->listen_host, fwd->listen_port); 2322bc5531deSDag-Erling Smørgrav } 2323bc5531deSDag-Erling Smørgrav if (code != oDynamicForward) { 2324bc5531deSDag-Erling Smørgrav if (fwd->connect_port == PORT_STREAMLOCAL) 2325bc5531deSDag-Erling Smørgrav printf(" %s", fwd->connect_path); 2326bc5531deSDag-Erling Smørgrav else if (fwd->connect_host == NULL) 2327bc5531deSDag-Erling Smørgrav printf(" %d", fwd->connect_port); 2328bc5531deSDag-Erling Smørgrav else { 2329bc5531deSDag-Erling Smørgrav printf(" [%s]:%d", 2330bc5531deSDag-Erling Smørgrav fwd->connect_host, fwd->connect_port); 2331bc5531deSDag-Erling Smørgrav } 2332bc5531deSDag-Erling Smørgrav } 2333bc5531deSDag-Erling Smørgrav printf("\n"); 2334bc5531deSDag-Erling Smørgrav } 2335bc5531deSDag-Erling Smørgrav } 2336bc5531deSDag-Erling Smørgrav 2337bc5531deSDag-Erling Smørgrav void 2338bc5531deSDag-Erling Smørgrav dump_client_config(Options *o, const char *host) 2339bc5531deSDag-Erling Smørgrav { 2340bc5531deSDag-Erling Smørgrav int i; 2341bc5531deSDag-Erling Smørgrav char vbuf[5]; 2342bc5531deSDag-Erling Smørgrav 2343*acc1a9efSDag-Erling Smørgrav /* This is normally prepared in ssh_kex2 */ 2344*acc1a9efSDag-Erling Smørgrav if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) 2345*acc1a9efSDag-Erling Smørgrav fatal("%s: kex_assemble_names failed", __func__); 2346*acc1a9efSDag-Erling Smørgrav 2347bc5531deSDag-Erling Smørgrav /* Most interesting options first: user, host, port */ 2348bc5531deSDag-Erling Smørgrav dump_cfg_string(oUser, o->user); 2349bc5531deSDag-Erling Smørgrav dump_cfg_string(oHostName, host); 2350bc5531deSDag-Erling Smørgrav dump_cfg_int(oPort, o->port); 2351bc5531deSDag-Erling Smørgrav 2352bc5531deSDag-Erling Smørgrav /* Flag options */ 2353bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oAddressFamily, o->address_family); 2354bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oBatchMode, o->batch_mode); 2355bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2356bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2357bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2358bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2359bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oCompression, o->compression); 2360bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oControlMaster, o->control_master); 2361bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2362bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2363bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2364bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2365bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oForwardX11, o->forward_x11); 2366bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2367bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2368bc5531deSDag-Erling Smørgrav #ifdef GSSAPI 2369bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2370bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2371bc5531deSDag-Erling Smørgrav #endif /* GSSAPI */ 2372bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2373bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2374bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2375bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2376bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2377bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2378bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2379bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oProtocol, o->protocol); 2380bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2381bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2382bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oRequestTTY, o->request_tty); 2383bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication); 2384bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication); 2385bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2386bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2387bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2388bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oTunnel, o->tun_open); 2389bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); 2390bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2391bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2392bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2393bc5531deSDag-Erling Smørgrav 2394bc5531deSDag-Erling Smørgrav /* Integer options */ 2395bc5531deSDag-Erling Smørgrav dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2396bc5531deSDag-Erling Smørgrav dump_cfg_int(oCompressionLevel, o->compression_level); 2397bc5531deSDag-Erling Smørgrav dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2398bc5531deSDag-Erling Smørgrav dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2399bc5531deSDag-Erling Smørgrav dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2400bc5531deSDag-Erling Smørgrav dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2401bc5531deSDag-Erling Smørgrav dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2402bc5531deSDag-Erling Smørgrav 2403bc5531deSDag-Erling Smørgrav /* String options */ 2404bc5531deSDag-Erling Smørgrav dump_cfg_string(oBindAddress, o->bind_address); 2405bc5531deSDag-Erling Smørgrav dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); 2406bc5531deSDag-Erling Smørgrav dump_cfg_string(oControlPath, o->control_path); 2407*acc1a9efSDag-Erling Smørgrav dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2408bc5531deSDag-Erling Smørgrav dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2409bc5531deSDag-Erling Smørgrav dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2410bc5531deSDag-Erling Smørgrav dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2411bc5531deSDag-Erling Smørgrav dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); 2412bc5531deSDag-Erling Smørgrav dump_cfg_string(oLocalCommand, o->local_command); 2413bc5531deSDag-Erling Smørgrav dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2414bc5531deSDag-Erling Smørgrav dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); 2415bc5531deSDag-Erling Smørgrav dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2416bc5531deSDag-Erling Smørgrav dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2417bc5531deSDag-Erling Smørgrav dump_cfg_string(oProxyCommand, o->proxy_command); 2418*acc1a9efSDag-Erling Smørgrav dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2419bc5531deSDag-Erling Smørgrav dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2420bc5531deSDag-Erling Smørgrav dump_cfg_string(oXAuthLocation, o->xauth_location); 2421bc5531deSDag-Erling Smørgrav 2422bc5531deSDag-Erling Smørgrav /* Forwards */ 2423bc5531deSDag-Erling Smørgrav dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2424bc5531deSDag-Erling Smørgrav dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2425bc5531deSDag-Erling Smørgrav dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2426bc5531deSDag-Erling Smørgrav 2427bc5531deSDag-Erling Smørgrav /* String array options */ 2428bc5531deSDag-Erling Smørgrav dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2429bc5531deSDag-Erling Smørgrav dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2430bc5531deSDag-Erling Smørgrav dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2431bc5531deSDag-Erling Smørgrav dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2432bc5531deSDag-Erling Smørgrav dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2433bc5531deSDag-Erling Smørgrav 2434bc5531deSDag-Erling Smørgrav /* Special cases */ 2435bc5531deSDag-Erling Smørgrav 2436bc5531deSDag-Erling Smørgrav /* oConnectTimeout */ 2437bc5531deSDag-Erling Smørgrav if (o->connection_timeout == -1) 2438bc5531deSDag-Erling Smørgrav printf("connecttimeout none\n"); 2439bc5531deSDag-Erling Smørgrav else 2440bc5531deSDag-Erling Smørgrav dump_cfg_int(oConnectTimeout, o->connection_timeout); 2441bc5531deSDag-Erling Smørgrav 2442bc5531deSDag-Erling Smørgrav /* oTunnelDevice */ 2443bc5531deSDag-Erling Smørgrav printf("tunneldevice"); 2444bc5531deSDag-Erling Smørgrav if (o->tun_local == SSH_TUNID_ANY) 2445bc5531deSDag-Erling Smørgrav printf(" any"); 2446bc5531deSDag-Erling Smørgrav else 2447bc5531deSDag-Erling Smørgrav printf(" %d", o->tun_local); 2448bc5531deSDag-Erling Smørgrav if (o->tun_remote == SSH_TUNID_ANY) 2449bc5531deSDag-Erling Smørgrav printf(":any"); 2450bc5531deSDag-Erling Smørgrav else 2451bc5531deSDag-Erling Smørgrav printf(":%d", o->tun_remote); 2452bc5531deSDag-Erling Smørgrav printf("\n"); 2453bc5531deSDag-Erling Smørgrav 2454bc5531deSDag-Erling Smørgrav /* oCanonicalizePermittedCNAMEs */ 2455bc5531deSDag-Erling Smørgrav if ( o->num_permitted_cnames > 0) { 2456bc5531deSDag-Erling Smørgrav printf("canonicalizePermittedcnames"); 2457bc5531deSDag-Erling Smørgrav for (i = 0; i < o->num_permitted_cnames; i++) { 2458bc5531deSDag-Erling Smørgrav printf(" %s:%s", o->permitted_cnames[i].source_list, 2459bc5531deSDag-Erling Smørgrav o->permitted_cnames[i].target_list); 2460bc5531deSDag-Erling Smørgrav } 2461bc5531deSDag-Erling Smørgrav printf("\n"); 2462bc5531deSDag-Erling Smørgrav } 2463bc5531deSDag-Erling Smørgrav 2464bc5531deSDag-Erling Smørgrav /* oCipher */ 2465bc5531deSDag-Erling Smørgrav if (o->cipher != SSH_CIPHER_NOT_SET) 2466bc5531deSDag-Erling Smørgrav printf("Cipher %s\n", cipher_name(o->cipher)); 2467bc5531deSDag-Erling Smørgrav 2468bc5531deSDag-Erling Smørgrav /* oControlPersist */ 2469bc5531deSDag-Erling Smørgrav if (o->control_persist == 0 || o->control_persist_timeout == 0) 2470bc5531deSDag-Erling Smørgrav dump_cfg_fmtint(oControlPersist, o->control_persist); 2471bc5531deSDag-Erling Smørgrav else 2472bc5531deSDag-Erling Smørgrav dump_cfg_int(oControlPersist, o->control_persist_timeout); 2473bc5531deSDag-Erling Smørgrav 2474bc5531deSDag-Erling Smørgrav /* oEscapeChar */ 2475bc5531deSDag-Erling Smørgrav if (o->escape_char == SSH_ESCAPECHAR_NONE) 2476bc5531deSDag-Erling Smørgrav printf("escapechar none\n"); 2477bc5531deSDag-Erling Smørgrav else { 2478bc5531deSDag-Erling Smørgrav vis(vbuf, o->escape_char, VIS_WHITE, 0); 2479bc5531deSDag-Erling Smørgrav printf("escapechar %s\n", vbuf); 2480bc5531deSDag-Erling Smørgrav } 2481bc5531deSDag-Erling Smørgrav 2482bc5531deSDag-Erling Smørgrav /* oIPQoS */ 2483bc5531deSDag-Erling Smørgrav printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2484bc5531deSDag-Erling Smørgrav printf("%s\n", iptos2str(o->ip_qos_bulk)); 2485bc5531deSDag-Erling Smørgrav 2486bc5531deSDag-Erling Smørgrav /* oRekeyLimit */ 2487*acc1a9efSDag-Erling Smørgrav printf("rekeylimit %llu %d\n", 2488*acc1a9efSDag-Erling Smørgrav (unsigned long long)o->rekey_limit, o->rekey_interval); 2489bc5531deSDag-Erling Smørgrav 2490bc5531deSDag-Erling Smørgrav /* oStreamLocalBindMask */ 2491bc5531deSDag-Erling Smørgrav printf("streamlocalbindmask 0%o\n", 2492bc5531deSDag-Erling Smørgrav o->fwd_opts.streamlocal_bind_mask); 2493bc5531deSDag-Erling Smørgrav } 2494