1*9f304aafSPeter Avalos /* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */ 218de8d7fSPeter Avalos /* 318de8d7fSPeter Avalos * Author: Tatu Ylonen <ylo@cs.hut.fi> 418de8d7fSPeter Avalos * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 518de8d7fSPeter Avalos * All rights reserved 618de8d7fSPeter Avalos * Functions for reading the configuration files. 718de8d7fSPeter Avalos * 818de8d7fSPeter Avalos * As far as I am concerned, the code I have written for this software 918de8d7fSPeter Avalos * can be used freely for any purpose. Any derived versions of this 1018de8d7fSPeter Avalos * software must be clearly marked as such, and if the derived work is 1118de8d7fSPeter Avalos * incompatible with the protocol description in the RFC file, it must be 1218de8d7fSPeter Avalos * called by a name other than "ssh" or "Secure Shell". 1318de8d7fSPeter Avalos */ 1418de8d7fSPeter Avalos 1518de8d7fSPeter Avalos #include "includes.h" 1618de8d7fSPeter Avalos 1718de8d7fSPeter Avalos #include <sys/types.h> 1818de8d7fSPeter Avalos #include <sys/stat.h> 1918de8d7fSPeter Avalos #include <sys/socket.h> 2018de8d7fSPeter Avalos 2118de8d7fSPeter Avalos #include <netinet/in.h> 22*9f304aafSPeter Avalos #include <netinet/in_systm.h> 23*9f304aafSPeter Avalos #include <netinet/ip.h> 2418de8d7fSPeter Avalos 2518de8d7fSPeter Avalos #include <ctype.h> 2618de8d7fSPeter Avalos #include <errno.h> 2718de8d7fSPeter Avalos #include <netdb.h> 2818de8d7fSPeter Avalos #include <signal.h> 2918de8d7fSPeter Avalos #include <stdarg.h> 3018de8d7fSPeter Avalos #include <stdio.h> 3118de8d7fSPeter Avalos #include <string.h> 3218de8d7fSPeter Avalos #include <unistd.h> 3318de8d7fSPeter Avalos 3418de8d7fSPeter Avalos #include "xmalloc.h" 3518de8d7fSPeter Avalos #include "ssh.h" 3618de8d7fSPeter Avalos #include "compat.h" 3718de8d7fSPeter Avalos #include "cipher.h" 3818de8d7fSPeter Avalos #include "pathnames.h" 3918de8d7fSPeter Avalos #include "log.h" 4018de8d7fSPeter Avalos #include "key.h" 4118de8d7fSPeter Avalos #include "readconf.h" 4218de8d7fSPeter Avalos #include "match.h" 4318de8d7fSPeter Avalos #include "misc.h" 4418de8d7fSPeter Avalos #include "buffer.h" 4518de8d7fSPeter Avalos #include "kex.h" 4618de8d7fSPeter Avalos #include "mac.h" 4718de8d7fSPeter Avalos 4818de8d7fSPeter Avalos /* Format of the configuration file: 4918de8d7fSPeter Avalos 5018de8d7fSPeter Avalos # Configuration data is parsed as follows: 5118de8d7fSPeter Avalos # 1. command line options 5218de8d7fSPeter Avalos # 2. user-specific file 5318de8d7fSPeter Avalos # 3. system-wide file 5418de8d7fSPeter Avalos # Any configuration value is only changed the first time it is set. 5518de8d7fSPeter Avalos # Thus, host-specific definitions should be at the beginning of the 5618de8d7fSPeter Avalos # configuration file, and defaults at the end. 5718de8d7fSPeter Avalos 5818de8d7fSPeter Avalos # Host-specific declarations. These may override anything above. A single 5918de8d7fSPeter Avalos # host may match multiple declarations; these are processed in the order 6018de8d7fSPeter Avalos # that they are given in. 6118de8d7fSPeter Avalos 6218de8d7fSPeter Avalos Host *.ngs.fi ngs.fi 6318de8d7fSPeter Avalos User foo 6418de8d7fSPeter Avalos 6518de8d7fSPeter Avalos Host fake.com 6618de8d7fSPeter Avalos HostName another.host.name.real.org 6718de8d7fSPeter Avalos User blaah 6818de8d7fSPeter Avalos Port 34289 6918de8d7fSPeter Avalos ForwardX11 no 7018de8d7fSPeter Avalos ForwardAgent no 7118de8d7fSPeter Avalos 7218de8d7fSPeter Avalos Host books.com 7318de8d7fSPeter Avalos RemoteForward 9999 shadows.cs.hut.fi:9999 7418de8d7fSPeter Avalos Cipher 3des 7518de8d7fSPeter Avalos 7618de8d7fSPeter Avalos Host fascist.blob.com 7718de8d7fSPeter Avalos Port 23123 7818de8d7fSPeter Avalos User tylonen 7918de8d7fSPeter Avalos PasswordAuthentication no 8018de8d7fSPeter Avalos 8118de8d7fSPeter Avalos Host puukko.hut.fi 8218de8d7fSPeter Avalos User t35124p 8318de8d7fSPeter Avalos ProxyCommand ssh-proxy %h %p 8418de8d7fSPeter Avalos 8518de8d7fSPeter Avalos Host *.fr 8618de8d7fSPeter Avalos PublicKeyAuthentication no 8718de8d7fSPeter Avalos 8818de8d7fSPeter Avalos Host *.su 8918de8d7fSPeter Avalos Cipher none 9018de8d7fSPeter Avalos PasswordAuthentication no 9118de8d7fSPeter Avalos 9218de8d7fSPeter Avalos Host vpn.fake.com 9318de8d7fSPeter Avalos Tunnel yes 9418de8d7fSPeter Avalos TunnelDevice 3 9518de8d7fSPeter Avalos 9618de8d7fSPeter Avalos # Defaults for various options 9718de8d7fSPeter Avalos Host * 9818de8d7fSPeter Avalos ForwardAgent no 9918de8d7fSPeter Avalos ForwardX11 no 10018de8d7fSPeter Avalos PasswordAuthentication yes 10118de8d7fSPeter Avalos RSAAuthentication yes 10218de8d7fSPeter Avalos RhostsRSAAuthentication yes 10318de8d7fSPeter Avalos StrictHostKeyChecking yes 10418de8d7fSPeter Avalos TcpKeepAlive no 10518de8d7fSPeter Avalos IdentityFile ~/.ssh/identity 10618de8d7fSPeter Avalos Port 22 10718de8d7fSPeter Avalos EscapeChar ~ 10818de8d7fSPeter Avalos 10918de8d7fSPeter Avalos */ 11018de8d7fSPeter Avalos 11118de8d7fSPeter Avalos /* Keyword tokens. */ 11218de8d7fSPeter Avalos 11318de8d7fSPeter Avalos typedef enum { 11418de8d7fSPeter Avalos oBadOption, 115856ea928SPeter Avalos oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 116856ea928SPeter Avalos oGatewayPorts, oExitOnForwardFailure, 11718de8d7fSPeter Avalos oPasswordAuthentication, oRSAAuthentication, 11818de8d7fSPeter Avalos oChallengeResponseAuthentication, oXAuthLocation, 11918de8d7fSPeter Avalos oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 12018de8d7fSPeter Avalos oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 12118de8d7fSPeter Avalos oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 12218de8d7fSPeter Avalos oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 12318de8d7fSPeter Avalos oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 12418de8d7fSPeter Avalos oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 12518de8d7fSPeter Avalos oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 12618de8d7fSPeter Avalos oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 12718de8d7fSPeter Avalos oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 128856ea928SPeter Avalos oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, 12918de8d7fSPeter Avalos oClearAllForwardings, oNoHostAuthenticationForLocalhost, 13018de8d7fSPeter Avalos oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 13118de8d7fSPeter Avalos oAddressFamily, oGssAuthentication, oGssDelegateCreds, 13218de8d7fSPeter Avalos oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 133856ea928SPeter Avalos oSendEnv, oControlPath, oControlMaster, oControlPersist, 134856ea928SPeter Avalos oHashKnownHosts, 13518de8d7fSPeter Avalos oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 13640c002afSPeter Avalos oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 137*9f304aafSPeter Avalos oKexAlgorithms, oIPQoS, 13818de8d7fSPeter Avalos oDeprecated, oUnsupported 13918de8d7fSPeter Avalos } OpCodes; 14018de8d7fSPeter Avalos 14118de8d7fSPeter Avalos /* Textual representations of the tokens. */ 14218de8d7fSPeter Avalos 14318de8d7fSPeter Avalos static struct { 14418de8d7fSPeter Avalos const char *name; 14518de8d7fSPeter Avalos OpCodes opcode; 14618de8d7fSPeter Avalos } keywords[] = { 14718de8d7fSPeter Avalos { "forwardagent", oForwardAgent }, 14818de8d7fSPeter Avalos { "forwardx11", oForwardX11 }, 14918de8d7fSPeter Avalos { "forwardx11trusted", oForwardX11Trusted }, 150856ea928SPeter Avalos { "forwardx11timeout", oForwardX11Timeout }, 15118de8d7fSPeter Avalos { "exitonforwardfailure", oExitOnForwardFailure }, 15218de8d7fSPeter Avalos { "xauthlocation", oXAuthLocation }, 15318de8d7fSPeter Avalos { "gatewayports", oGatewayPorts }, 15418de8d7fSPeter Avalos { "useprivilegedport", oUsePrivilegedPort }, 15518de8d7fSPeter Avalos { "rhostsauthentication", oDeprecated }, 15618de8d7fSPeter Avalos { "passwordauthentication", oPasswordAuthentication }, 15718de8d7fSPeter Avalos { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 15818de8d7fSPeter Avalos { "kbdinteractivedevices", oKbdInteractiveDevices }, 15918de8d7fSPeter Avalos { "rsaauthentication", oRSAAuthentication }, 16018de8d7fSPeter Avalos { "pubkeyauthentication", oPubkeyAuthentication }, 16118de8d7fSPeter Avalos { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 16218de8d7fSPeter Avalos { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 16318de8d7fSPeter Avalos { "hostbasedauthentication", oHostbasedAuthentication }, 16418de8d7fSPeter Avalos { "challengeresponseauthentication", oChallengeResponseAuthentication }, 16518de8d7fSPeter Avalos { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 16618de8d7fSPeter Avalos { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 16718de8d7fSPeter Avalos { "kerberosauthentication", oUnsupported }, 16818de8d7fSPeter Avalos { "kerberostgtpassing", oUnsupported }, 16918de8d7fSPeter Avalos { "afstokenpassing", oUnsupported }, 17018de8d7fSPeter Avalos #if defined(GSSAPI) 17118de8d7fSPeter Avalos { "gssapiauthentication", oGssAuthentication }, 17218de8d7fSPeter Avalos { "gssapidelegatecredentials", oGssDelegateCreds }, 17318de8d7fSPeter Avalos #else 17418de8d7fSPeter Avalos { "gssapiauthentication", oUnsupported }, 17518de8d7fSPeter Avalos { "gssapidelegatecredentials", oUnsupported }, 17618de8d7fSPeter Avalos #endif 17718de8d7fSPeter Avalos { "fallbacktorsh", oDeprecated }, 17818de8d7fSPeter Avalos { "usersh", oDeprecated }, 17918de8d7fSPeter Avalos { "identityfile", oIdentityFile }, 180cb5eb4f1SPeter Avalos { "identityfile2", oIdentityFile }, /* obsolete */ 18118de8d7fSPeter Avalos { "identitiesonly", oIdentitiesOnly }, 18218de8d7fSPeter Avalos { "hostname", oHostName }, 18318de8d7fSPeter Avalos { "hostkeyalias", oHostKeyAlias }, 18418de8d7fSPeter Avalos { "proxycommand", oProxyCommand }, 18518de8d7fSPeter Avalos { "port", oPort }, 18618de8d7fSPeter Avalos { "cipher", oCipher }, 18718de8d7fSPeter Avalos { "ciphers", oCiphers }, 18818de8d7fSPeter Avalos { "macs", oMacs }, 18918de8d7fSPeter Avalos { "protocol", oProtocol }, 19018de8d7fSPeter Avalos { "remoteforward", oRemoteForward }, 19118de8d7fSPeter Avalos { "localforward", oLocalForward }, 19218de8d7fSPeter Avalos { "user", oUser }, 19318de8d7fSPeter Avalos { "host", oHost }, 19418de8d7fSPeter Avalos { "escapechar", oEscapeChar }, 19518de8d7fSPeter Avalos { "globalknownhostsfile", oGlobalKnownHostsFile }, 196cb5eb4f1SPeter Avalos { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */ 197cb5eb4f1SPeter Avalos { "userknownhostsfile", oUserKnownHostsFile }, 19818de8d7fSPeter Avalos { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 19918de8d7fSPeter Avalos { "connectionattempts", oConnectionAttempts }, 20018de8d7fSPeter Avalos { "batchmode", oBatchMode }, 20118de8d7fSPeter Avalos { "checkhostip", oCheckHostIP }, 20218de8d7fSPeter Avalos { "stricthostkeychecking", oStrictHostKeyChecking }, 20318de8d7fSPeter Avalos { "compression", oCompression }, 20418de8d7fSPeter Avalos { "compressionlevel", oCompressionLevel }, 20518de8d7fSPeter Avalos { "tcpkeepalive", oTCPKeepAlive }, 20618de8d7fSPeter Avalos { "keepalive", oTCPKeepAlive }, /* obsolete */ 20718de8d7fSPeter Avalos { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 20818de8d7fSPeter Avalos { "loglevel", oLogLevel }, 20918de8d7fSPeter Avalos { "dynamicforward", oDynamicForward }, 21018de8d7fSPeter Avalos { "preferredauthentications", oPreferredAuthentications }, 21118de8d7fSPeter Avalos { "hostkeyalgorithms", oHostKeyAlgorithms }, 21218de8d7fSPeter Avalos { "bindaddress", oBindAddress }, 213856ea928SPeter Avalos #ifdef ENABLE_PKCS11 214856ea928SPeter Avalos { "smartcarddevice", oPKCS11Provider }, 215856ea928SPeter Avalos { "pkcs11provider", oPKCS11Provider }, 21618de8d7fSPeter Avalos #else 21718de8d7fSPeter Avalos { "smartcarddevice", oUnsupported }, 218856ea928SPeter Avalos { "pkcs11provider", oUnsupported }, 21918de8d7fSPeter Avalos #endif 22018de8d7fSPeter Avalos { "clearallforwardings", oClearAllForwardings }, 22118de8d7fSPeter Avalos { "enablesshkeysign", oEnableSSHKeysign }, 22218de8d7fSPeter Avalos { "verifyhostkeydns", oVerifyHostKeyDNS }, 22318de8d7fSPeter Avalos { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 22418de8d7fSPeter Avalos { "rekeylimit", oRekeyLimit }, 22518de8d7fSPeter Avalos { "connecttimeout", oConnectTimeout }, 22618de8d7fSPeter Avalos { "addressfamily", oAddressFamily }, 22718de8d7fSPeter Avalos { "serveraliveinterval", oServerAliveInterval }, 22818de8d7fSPeter Avalos { "serveralivecountmax", oServerAliveCountMax }, 22918de8d7fSPeter Avalos { "sendenv", oSendEnv }, 23018de8d7fSPeter Avalos { "controlpath", oControlPath }, 23118de8d7fSPeter Avalos { "controlmaster", oControlMaster }, 232856ea928SPeter Avalos { "controlpersist", oControlPersist }, 23318de8d7fSPeter Avalos { "hashknownhosts", oHashKnownHosts }, 23418de8d7fSPeter Avalos { "tunnel", oTunnel }, 23518de8d7fSPeter Avalos { "tunneldevice", oTunnelDevice }, 23618de8d7fSPeter Avalos { "localcommand", oLocalCommand }, 23718de8d7fSPeter Avalos { "permitlocalcommand", oPermitLocalCommand }, 23818de8d7fSPeter Avalos { "visualhostkey", oVisualHostKey }, 23940c002afSPeter Avalos { "useroaming", oUseRoaming }, 240cb5eb4f1SPeter Avalos #ifdef JPAKE 241cb5eb4f1SPeter Avalos { "zeroknowledgepasswordauthentication", 242cb5eb4f1SPeter Avalos oZeroKnowledgePasswordAuthentication }, 243cb5eb4f1SPeter Avalos #else 244cb5eb4f1SPeter Avalos { "zeroknowledgepasswordauthentication", oUnsupported }, 245cb5eb4f1SPeter Avalos #endif 246*9f304aafSPeter Avalos { "kexalgorithms", oKexAlgorithms }, 247*9f304aafSPeter Avalos { "ipqos", oIPQoS }, 248cb5eb4f1SPeter Avalos 24918de8d7fSPeter Avalos { NULL, oBadOption } 25018de8d7fSPeter Avalos }; 25118de8d7fSPeter Avalos 25218de8d7fSPeter Avalos /* 25318de8d7fSPeter Avalos * Adds a local TCP/IP port forward to options. Never returns if there is an 25418de8d7fSPeter Avalos * error. 25518de8d7fSPeter Avalos */ 25618de8d7fSPeter Avalos 25718de8d7fSPeter Avalos void 25818de8d7fSPeter Avalos add_local_forward(Options *options, const Forward *newfwd) 25918de8d7fSPeter Avalos { 26018de8d7fSPeter Avalos Forward *fwd; 26118de8d7fSPeter Avalos #ifndef NO_IPPORT_RESERVED_CONCEPT 26218de8d7fSPeter Avalos extern uid_t original_real_uid; 26318de8d7fSPeter Avalos if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 26418de8d7fSPeter Avalos fatal("Privileged ports can only be forwarded by root."); 26518de8d7fSPeter Avalos #endif 266856ea928SPeter Avalos options->local_forwards = xrealloc(options->local_forwards, 267856ea928SPeter Avalos options->num_local_forwards + 1, 268856ea928SPeter Avalos sizeof(*options->local_forwards)); 26918de8d7fSPeter Avalos fwd = &options->local_forwards[options->num_local_forwards++]; 27018de8d7fSPeter Avalos 271cb5eb4f1SPeter Avalos fwd->listen_host = newfwd->listen_host; 27218de8d7fSPeter Avalos fwd->listen_port = newfwd->listen_port; 273cb5eb4f1SPeter Avalos fwd->connect_host = newfwd->connect_host; 27418de8d7fSPeter Avalos fwd->connect_port = newfwd->connect_port; 27518de8d7fSPeter Avalos } 27618de8d7fSPeter Avalos 27718de8d7fSPeter Avalos /* 27818de8d7fSPeter Avalos * Adds a remote TCP/IP port forward to options. Never returns if there is 27918de8d7fSPeter Avalos * an error. 28018de8d7fSPeter Avalos */ 28118de8d7fSPeter Avalos 28218de8d7fSPeter Avalos void 28318de8d7fSPeter Avalos add_remote_forward(Options *options, const Forward *newfwd) 28418de8d7fSPeter Avalos { 28518de8d7fSPeter Avalos Forward *fwd; 286856ea928SPeter Avalos 287856ea928SPeter Avalos options->remote_forwards = xrealloc(options->remote_forwards, 288856ea928SPeter Avalos options->num_remote_forwards + 1, 289856ea928SPeter Avalos sizeof(*options->remote_forwards)); 29018de8d7fSPeter Avalos fwd = &options->remote_forwards[options->num_remote_forwards++]; 29118de8d7fSPeter Avalos 292cb5eb4f1SPeter Avalos fwd->listen_host = newfwd->listen_host; 29318de8d7fSPeter Avalos fwd->listen_port = newfwd->listen_port; 294cb5eb4f1SPeter Avalos fwd->connect_host = newfwd->connect_host; 29518de8d7fSPeter Avalos fwd->connect_port = newfwd->connect_port; 296856ea928SPeter Avalos fwd->allocated_port = 0; 29718de8d7fSPeter Avalos } 29818de8d7fSPeter Avalos 29918de8d7fSPeter Avalos static void 30018de8d7fSPeter Avalos clear_forwardings(Options *options) 30118de8d7fSPeter Avalos { 30218de8d7fSPeter Avalos int i; 30318de8d7fSPeter Avalos 30418de8d7fSPeter Avalos for (i = 0; i < options->num_local_forwards; i++) { 30518de8d7fSPeter Avalos if (options->local_forwards[i].listen_host != NULL) 30618de8d7fSPeter Avalos xfree(options->local_forwards[i].listen_host); 30718de8d7fSPeter Avalos xfree(options->local_forwards[i].connect_host); 30818de8d7fSPeter Avalos } 309856ea928SPeter Avalos if (options->num_local_forwards > 0) { 310856ea928SPeter Avalos xfree(options->local_forwards); 311856ea928SPeter Avalos options->local_forwards = NULL; 312856ea928SPeter Avalos } 31318de8d7fSPeter Avalos options->num_local_forwards = 0; 31418de8d7fSPeter Avalos for (i = 0; i < options->num_remote_forwards; i++) { 31518de8d7fSPeter Avalos if (options->remote_forwards[i].listen_host != NULL) 31618de8d7fSPeter Avalos xfree(options->remote_forwards[i].listen_host); 31718de8d7fSPeter Avalos xfree(options->remote_forwards[i].connect_host); 31818de8d7fSPeter Avalos } 319856ea928SPeter Avalos if (options->num_remote_forwards > 0) { 320856ea928SPeter Avalos xfree(options->remote_forwards); 321856ea928SPeter Avalos options->remote_forwards = NULL; 322856ea928SPeter Avalos } 32318de8d7fSPeter Avalos options->num_remote_forwards = 0; 32418de8d7fSPeter Avalos options->tun_open = SSH_TUNMODE_NO; 32518de8d7fSPeter Avalos } 32618de8d7fSPeter Avalos 32718de8d7fSPeter Avalos /* 32818de8d7fSPeter Avalos * Returns the number of the token pointed to by cp or oBadOption. 32918de8d7fSPeter Avalos */ 33018de8d7fSPeter Avalos 33118de8d7fSPeter Avalos static OpCodes 33218de8d7fSPeter Avalos parse_token(const char *cp, const char *filename, int linenum) 33318de8d7fSPeter Avalos { 33418de8d7fSPeter Avalos u_int i; 33518de8d7fSPeter Avalos 33618de8d7fSPeter Avalos for (i = 0; keywords[i].name; i++) 33718de8d7fSPeter Avalos if (strcasecmp(cp, keywords[i].name) == 0) 33818de8d7fSPeter Avalos return keywords[i].opcode; 33918de8d7fSPeter Avalos 34018de8d7fSPeter Avalos error("%s: line %d: Bad configuration option: %s", 34118de8d7fSPeter Avalos filename, linenum, cp); 34218de8d7fSPeter Avalos return oBadOption; 34318de8d7fSPeter Avalos } 34418de8d7fSPeter Avalos 34518de8d7fSPeter Avalos /* 34618de8d7fSPeter Avalos * Processes a single option line as used in the configuration files. This 34718de8d7fSPeter Avalos * only sets those values that have not already been set. 34818de8d7fSPeter Avalos */ 34918de8d7fSPeter Avalos #define WHITESPACE " \t\r\n" 35018de8d7fSPeter Avalos 35118de8d7fSPeter Avalos int 35218de8d7fSPeter Avalos process_config_line(Options *options, const char *host, 35318de8d7fSPeter Avalos char *line, const char *filename, int linenum, 35418de8d7fSPeter Avalos int *activep) 35518de8d7fSPeter Avalos { 35618de8d7fSPeter Avalos char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; 35718de8d7fSPeter Avalos int opcode, *intptr, value, value2, scale; 35818de8d7fSPeter Avalos LogLevel *log_level_ptr; 35918de8d7fSPeter Avalos long long orig, val64; 36018de8d7fSPeter Avalos size_t len; 36118de8d7fSPeter Avalos Forward fwd; 36218de8d7fSPeter Avalos 36318de8d7fSPeter Avalos /* Strip trailing whitespace */ 36418de8d7fSPeter Avalos for (len = strlen(line) - 1; len > 0; len--) { 36518de8d7fSPeter Avalos if (strchr(WHITESPACE, line[len]) == NULL) 36618de8d7fSPeter Avalos break; 36718de8d7fSPeter Avalos line[len] = '\0'; 36818de8d7fSPeter Avalos } 36918de8d7fSPeter Avalos 37018de8d7fSPeter Avalos s = line; 37118de8d7fSPeter Avalos /* Get the keyword. (Each line is supposed to begin with a keyword). */ 37218de8d7fSPeter Avalos if ((keyword = strdelim(&s)) == NULL) 37318de8d7fSPeter Avalos return 0; 37418de8d7fSPeter Avalos /* Ignore leading whitespace. */ 37518de8d7fSPeter Avalos if (*keyword == '\0') 37618de8d7fSPeter Avalos keyword = strdelim(&s); 37718de8d7fSPeter Avalos if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 37818de8d7fSPeter Avalos return 0; 37918de8d7fSPeter Avalos 38018de8d7fSPeter Avalos opcode = parse_token(keyword, filename, linenum); 38118de8d7fSPeter Avalos 38218de8d7fSPeter Avalos switch (opcode) { 38318de8d7fSPeter Avalos case oBadOption: 38418de8d7fSPeter Avalos /* don't panic, but count bad options */ 38518de8d7fSPeter Avalos return -1; 38618de8d7fSPeter Avalos /* NOTREACHED */ 38718de8d7fSPeter Avalos case oConnectTimeout: 38818de8d7fSPeter Avalos intptr = &options->connection_timeout; 38918de8d7fSPeter Avalos parse_time: 39018de8d7fSPeter Avalos arg = strdelim(&s); 39118de8d7fSPeter Avalos if (!arg || *arg == '\0') 39218de8d7fSPeter Avalos fatal("%s line %d: missing time value.", 39318de8d7fSPeter Avalos filename, linenum); 39418de8d7fSPeter Avalos if ((value = convtime(arg)) == -1) 39518de8d7fSPeter Avalos fatal("%s line %d: invalid time value.", 39618de8d7fSPeter Avalos filename, linenum); 39718de8d7fSPeter Avalos if (*activep && *intptr == -1) 39818de8d7fSPeter Avalos *intptr = value; 39918de8d7fSPeter Avalos break; 40018de8d7fSPeter Avalos 40118de8d7fSPeter Avalos case oForwardAgent: 40218de8d7fSPeter Avalos intptr = &options->forward_agent; 40318de8d7fSPeter Avalos parse_flag: 40418de8d7fSPeter Avalos arg = strdelim(&s); 40518de8d7fSPeter Avalos if (!arg || *arg == '\0') 40618de8d7fSPeter Avalos fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 40718de8d7fSPeter Avalos value = 0; /* To avoid compiler warning... */ 40818de8d7fSPeter Avalos if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 40918de8d7fSPeter Avalos value = 1; 41018de8d7fSPeter Avalos else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 41118de8d7fSPeter Avalos value = 0; 41218de8d7fSPeter Avalos else 41318de8d7fSPeter Avalos fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 41418de8d7fSPeter Avalos if (*activep && *intptr == -1) 41518de8d7fSPeter Avalos *intptr = value; 41618de8d7fSPeter Avalos break; 41718de8d7fSPeter Avalos 41818de8d7fSPeter Avalos case oForwardX11: 41918de8d7fSPeter Avalos intptr = &options->forward_x11; 42018de8d7fSPeter Avalos goto parse_flag; 42118de8d7fSPeter Avalos 42218de8d7fSPeter Avalos case oForwardX11Trusted: 42318de8d7fSPeter Avalos intptr = &options->forward_x11_trusted; 42418de8d7fSPeter Avalos goto parse_flag; 42518de8d7fSPeter Avalos 426856ea928SPeter Avalos case oForwardX11Timeout: 427856ea928SPeter Avalos intptr = &options->forward_x11_timeout; 428856ea928SPeter Avalos goto parse_time; 429856ea928SPeter Avalos 43018de8d7fSPeter Avalos case oGatewayPorts: 43118de8d7fSPeter Avalos intptr = &options->gateway_ports; 43218de8d7fSPeter Avalos goto parse_flag; 43318de8d7fSPeter Avalos 43418de8d7fSPeter Avalos case oExitOnForwardFailure: 43518de8d7fSPeter Avalos intptr = &options->exit_on_forward_failure; 43618de8d7fSPeter Avalos goto parse_flag; 43718de8d7fSPeter Avalos 43818de8d7fSPeter Avalos case oUsePrivilegedPort: 43918de8d7fSPeter Avalos intptr = &options->use_privileged_port; 44018de8d7fSPeter Avalos goto parse_flag; 44118de8d7fSPeter Avalos 44218de8d7fSPeter Avalos case oPasswordAuthentication: 44318de8d7fSPeter Avalos intptr = &options->password_authentication; 44418de8d7fSPeter Avalos goto parse_flag; 44518de8d7fSPeter Avalos 446cb5eb4f1SPeter Avalos case oZeroKnowledgePasswordAuthentication: 447cb5eb4f1SPeter Avalos intptr = &options->zero_knowledge_password_authentication; 448cb5eb4f1SPeter Avalos goto parse_flag; 449cb5eb4f1SPeter Avalos 45018de8d7fSPeter Avalos case oKbdInteractiveAuthentication: 45118de8d7fSPeter Avalos intptr = &options->kbd_interactive_authentication; 45218de8d7fSPeter Avalos goto parse_flag; 45318de8d7fSPeter Avalos 45418de8d7fSPeter Avalos case oKbdInteractiveDevices: 45518de8d7fSPeter Avalos charptr = &options->kbd_interactive_devices; 45618de8d7fSPeter Avalos goto parse_string; 45718de8d7fSPeter Avalos 45818de8d7fSPeter Avalos case oPubkeyAuthentication: 45918de8d7fSPeter Avalos intptr = &options->pubkey_authentication; 46018de8d7fSPeter Avalos goto parse_flag; 46118de8d7fSPeter Avalos 46218de8d7fSPeter Avalos case oRSAAuthentication: 46318de8d7fSPeter Avalos intptr = &options->rsa_authentication; 46418de8d7fSPeter Avalos goto parse_flag; 46518de8d7fSPeter Avalos 46618de8d7fSPeter Avalos case oRhostsRSAAuthentication: 46718de8d7fSPeter Avalos intptr = &options->rhosts_rsa_authentication; 46818de8d7fSPeter Avalos goto parse_flag; 46918de8d7fSPeter Avalos 47018de8d7fSPeter Avalos case oHostbasedAuthentication: 47118de8d7fSPeter Avalos intptr = &options->hostbased_authentication; 47218de8d7fSPeter Avalos goto parse_flag; 47318de8d7fSPeter Avalos 47418de8d7fSPeter Avalos case oChallengeResponseAuthentication: 47518de8d7fSPeter Avalos intptr = &options->challenge_response_authentication; 47618de8d7fSPeter Avalos goto parse_flag; 47718de8d7fSPeter Avalos 47818de8d7fSPeter Avalos case oGssAuthentication: 47918de8d7fSPeter Avalos intptr = &options->gss_authentication; 48018de8d7fSPeter Avalos goto parse_flag; 48118de8d7fSPeter Avalos 48218de8d7fSPeter Avalos case oGssDelegateCreds: 48318de8d7fSPeter Avalos intptr = &options->gss_deleg_creds; 48418de8d7fSPeter Avalos goto parse_flag; 48518de8d7fSPeter Avalos 48618de8d7fSPeter Avalos case oBatchMode: 48718de8d7fSPeter Avalos intptr = &options->batch_mode; 48818de8d7fSPeter Avalos goto parse_flag; 48918de8d7fSPeter Avalos 49018de8d7fSPeter Avalos case oCheckHostIP: 49118de8d7fSPeter Avalos intptr = &options->check_host_ip; 49218de8d7fSPeter Avalos goto parse_flag; 49318de8d7fSPeter Avalos 49418de8d7fSPeter Avalos case oVerifyHostKeyDNS: 49518de8d7fSPeter Avalos intptr = &options->verify_host_key_dns; 49618de8d7fSPeter Avalos goto parse_yesnoask; 49718de8d7fSPeter Avalos 49818de8d7fSPeter Avalos case oStrictHostKeyChecking: 49918de8d7fSPeter Avalos intptr = &options->strict_host_key_checking; 50018de8d7fSPeter Avalos parse_yesnoask: 50118de8d7fSPeter Avalos arg = strdelim(&s); 50218de8d7fSPeter Avalos if (!arg || *arg == '\0') 50318de8d7fSPeter Avalos fatal("%.200s line %d: Missing yes/no/ask argument.", 50418de8d7fSPeter Avalos filename, linenum); 50518de8d7fSPeter Avalos value = 0; /* To avoid compiler warning... */ 50618de8d7fSPeter Avalos if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 50718de8d7fSPeter Avalos value = 1; 50818de8d7fSPeter Avalos else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 50918de8d7fSPeter Avalos value = 0; 51018de8d7fSPeter Avalos else if (strcmp(arg, "ask") == 0) 51118de8d7fSPeter Avalos value = 2; 51218de8d7fSPeter Avalos else 51318de8d7fSPeter Avalos fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 51418de8d7fSPeter Avalos if (*activep && *intptr == -1) 51518de8d7fSPeter Avalos *intptr = value; 51618de8d7fSPeter Avalos break; 51718de8d7fSPeter Avalos 51818de8d7fSPeter Avalos case oCompression: 51918de8d7fSPeter Avalos intptr = &options->compression; 52018de8d7fSPeter Avalos goto parse_flag; 52118de8d7fSPeter Avalos 52218de8d7fSPeter Avalos case oTCPKeepAlive: 52318de8d7fSPeter Avalos intptr = &options->tcp_keep_alive; 52418de8d7fSPeter Avalos goto parse_flag; 52518de8d7fSPeter Avalos 52618de8d7fSPeter Avalos case oNoHostAuthenticationForLocalhost: 52718de8d7fSPeter Avalos intptr = &options->no_host_authentication_for_localhost; 52818de8d7fSPeter Avalos goto parse_flag; 52918de8d7fSPeter Avalos 53018de8d7fSPeter Avalos case oNumberOfPasswordPrompts: 53118de8d7fSPeter Avalos intptr = &options->number_of_password_prompts; 53218de8d7fSPeter Avalos goto parse_int; 53318de8d7fSPeter Avalos 53418de8d7fSPeter Avalos case oCompressionLevel: 53518de8d7fSPeter Avalos intptr = &options->compression_level; 53618de8d7fSPeter Avalos goto parse_int; 53718de8d7fSPeter Avalos 53818de8d7fSPeter Avalos case oRekeyLimit: 53918de8d7fSPeter Avalos arg = strdelim(&s); 54018de8d7fSPeter Avalos if (!arg || *arg == '\0') 54118de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 54218de8d7fSPeter Avalos if (arg[0] < '0' || arg[0] > '9') 54318de8d7fSPeter Avalos fatal("%.200s line %d: Bad number.", filename, linenum); 54418de8d7fSPeter Avalos orig = val64 = strtoll(arg, &endofnumber, 10); 54518de8d7fSPeter Avalos if (arg == endofnumber) 54618de8d7fSPeter Avalos fatal("%.200s line %d: Bad number.", filename, linenum); 54718de8d7fSPeter Avalos switch (toupper(*endofnumber)) { 54818de8d7fSPeter Avalos case '\0': 54918de8d7fSPeter Avalos scale = 1; 55018de8d7fSPeter Avalos break; 55118de8d7fSPeter Avalos case 'K': 55218de8d7fSPeter Avalos scale = 1<<10; 55318de8d7fSPeter Avalos break; 55418de8d7fSPeter Avalos case 'M': 55518de8d7fSPeter Avalos scale = 1<<20; 55618de8d7fSPeter Avalos break; 55718de8d7fSPeter Avalos case 'G': 55818de8d7fSPeter Avalos scale = 1<<30; 55918de8d7fSPeter Avalos break; 56018de8d7fSPeter Avalos default: 56118de8d7fSPeter Avalos fatal("%.200s line %d: Invalid RekeyLimit suffix", 56218de8d7fSPeter Avalos filename, linenum); 56318de8d7fSPeter Avalos } 56418de8d7fSPeter Avalos val64 *= scale; 56518de8d7fSPeter Avalos /* detect integer wrap and too-large limits */ 56618de8d7fSPeter Avalos if ((val64 / scale) != orig || val64 > UINT_MAX) 56718de8d7fSPeter Avalos fatal("%.200s line %d: RekeyLimit too large", 56818de8d7fSPeter Avalos filename, linenum); 56918de8d7fSPeter Avalos if (val64 < 16) 57018de8d7fSPeter Avalos fatal("%.200s line %d: RekeyLimit too small", 57118de8d7fSPeter Avalos filename, linenum); 57218de8d7fSPeter Avalos if (*activep && options->rekey_limit == -1) 57318de8d7fSPeter Avalos options->rekey_limit = (u_int32_t)val64; 57418de8d7fSPeter Avalos break; 57518de8d7fSPeter Avalos 57618de8d7fSPeter Avalos case oIdentityFile: 57718de8d7fSPeter Avalos arg = strdelim(&s); 57818de8d7fSPeter Avalos if (!arg || *arg == '\0') 57918de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 58018de8d7fSPeter Avalos if (*activep) { 58118de8d7fSPeter Avalos intptr = &options->num_identity_files; 58218de8d7fSPeter Avalos if (*intptr >= SSH_MAX_IDENTITY_FILES) 58318de8d7fSPeter Avalos fatal("%.200s line %d: Too many identity files specified (max %d).", 58418de8d7fSPeter Avalos filename, linenum, SSH_MAX_IDENTITY_FILES); 58518de8d7fSPeter Avalos charptr = &options->identity_files[*intptr]; 58618de8d7fSPeter Avalos *charptr = xstrdup(arg); 58718de8d7fSPeter Avalos *intptr = *intptr + 1; 58818de8d7fSPeter Avalos } 58918de8d7fSPeter Avalos break; 59018de8d7fSPeter Avalos 59118de8d7fSPeter Avalos case oXAuthLocation: 59218de8d7fSPeter Avalos charptr=&options->xauth_location; 59318de8d7fSPeter Avalos goto parse_string; 59418de8d7fSPeter Avalos 59518de8d7fSPeter Avalos case oUser: 59618de8d7fSPeter Avalos charptr = &options->user; 59718de8d7fSPeter Avalos parse_string: 59818de8d7fSPeter Avalos arg = strdelim(&s); 59918de8d7fSPeter Avalos if (!arg || *arg == '\0') 60018de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 60118de8d7fSPeter Avalos if (*activep && *charptr == NULL) 60218de8d7fSPeter Avalos *charptr = xstrdup(arg); 60318de8d7fSPeter Avalos break; 60418de8d7fSPeter Avalos 60518de8d7fSPeter Avalos case oGlobalKnownHostsFile: 60618de8d7fSPeter Avalos charptr = &options->system_hostfile; 60718de8d7fSPeter Avalos goto parse_string; 60818de8d7fSPeter Avalos 60918de8d7fSPeter Avalos case oUserKnownHostsFile: 61018de8d7fSPeter Avalos charptr = &options->user_hostfile; 61118de8d7fSPeter Avalos goto parse_string; 61218de8d7fSPeter Avalos 61318de8d7fSPeter Avalos case oGlobalKnownHostsFile2: 61418de8d7fSPeter Avalos charptr = &options->system_hostfile2; 61518de8d7fSPeter Avalos goto parse_string; 61618de8d7fSPeter Avalos 61718de8d7fSPeter Avalos case oUserKnownHostsFile2: 61818de8d7fSPeter Avalos charptr = &options->user_hostfile2; 61918de8d7fSPeter Avalos goto parse_string; 62018de8d7fSPeter Avalos 62118de8d7fSPeter Avalos case oHostName: 62218de8d7fSPeter Avalos charptr = &options->hostname; 62318de8d7fSPeter Avalos goto parse_string; 62418de8d7fSPeter Avalos 62518de8d7fSPeter Avalos case oHostKeyAlias: 62618de8d7fSPeter Avalos charptr = &options->host_key_alias; 62718de8d7fSPeter Avalos goto parse_string; 62818de8d7fSPeter Avalos 62918de8d7fSPeter Avalos case oPreferredAuthentications: 63018de8d7fSPeter Avalos charptr = &options->preferred_authentications; 63118de8d7fSPeter Avalos goto parse_string; 63218de8d7fSPeter Avalos 63318de8d7fSPeter Avalos case oBindAddress: 63418de8d7fSPeter Avalos charptr = &options->bind_address; 63518de8d7fSPeter Avalos goto parse_string; 63618de8d7fSPeter Avalos 637856ea928SPeter Avalos case oPKCS11Provider: 638856ea928SPeter Avalos charptr = &options->pkcs11_provider; 63918de8d7fSPeter Avalos goto parse_string; 64018de8d7fSPeter Avalos 64118de8d7fSPeter Avalos case oProxyCommand: 64218de8d7fSPeter Avalos charptr = &options->proxy_command; 64318de8d7fSPeter Avalos parse_command: 64418de8d7fSPeter Avalos if (s == NULL) 64518de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 64618de8d7fSPeter Avalos len = strspn(s, WHITESPACE "="); 64718de8d7fSPeter Avalos if (*activep && *charptr == NULL) 64818de8d7fSPeter Avalos *charptr = xstrdup(s + len); 64918de8d7fSPeter Avalos return 0; 65018de8d7fSPeter Avalos 65118de8d7fSPeter Avalos case oPort: 65218de8d7fSPeter Avalos intptr = &options->port; 65318de8d7fSPeter Avalos parse_int: 65418de8d7fSPeter Avalos arg = strdelim(&s); 65518de8d7fSPeter Avalos if (!arg || *arg == '\0') 65618de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 65718de8d7fSPeter Avalos if (arg[0] < '0' || arg[0] > '9') 65818de8d7fSPeter Avalos fatal("%.200s line %d: Bad number.", filename, linenum); 65918de8d7fSPeter Avalos 66018de8d7fSPeter Avalos /* Octal, decimal, or hex format? */ 66118de8d7fSPeter Avalos value = strtol(arg, &endofnumber, 0); 66218de8d7fSPeter Avalos if (arg == endofnumber) 66318de8d7fSPeter Avalos fatal("%.200s line %d: Bad number.", filename, linenum); 66418de8d7fSPeter Avalos if (*activep && *intptr == -1) 66518de8d7fSPeter Avalos *intptr = value; 66618de8d7fSPeter Avalos break; 66718de8d7fSPeter Avalos 66818de8d7fSPeter Avalos case oConnectionAttempts: 66918de8d7fSPeter Avalos intptr = &options->connection_attempts; 67018de8d7fSPeter Avalos goto parse_int; 67118de8d7fSPeter Avalos 67218de8d7fSPeter Avalos case oCipher: 67318de8d7fSPeter Avalos intptr = &options->cipher; 67418de8d7fSPeter Avalos arg = strdelim(&s); 67518de8d7fSPeter Avalos if (!arg || *arg == '\0') 67618de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 67718de8d7fSPeter Avalos value = cipher_number(arg); 67818de8d7fSPeter Avalos if (value == -1) 67918de8d7fSPeter Avalos fatal("%.200s line %d: Bad cipher '%s'.", 68018de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 68118de8d7fSPeter Avalos if (*activep && *intptr == -1) 68218de8d7fSPeter Avalos *intptr = value; 68318de8d7fSPeter Avalos break; 68418de8d7fSPeter Avalos 68518de8d7fSPeter Avalos case oCiphers: 68618de8d7fSPeter Avalos arg = strdelim(&s); 68718de8d7fSPeter Avalos if (!arg || *arg == '\0') 68818de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 68918de8d7fSPeter Avalos if (!ciphers_valid(arg)) 69018de8d7fSPeter Avalos fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 69118de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 69218de8d7fSPeter Avalos if (*activep && options->ciphers == NULL) 69318de8d7fSPeter Avalos options->ciphers = xstrdup(arg); 69418de8d7fSPeter Avalos break; 69518de8d7fSPeter Avalos 69618de8d7fSPeter Avalos case oMacs: 69718de8d7fSPeter Avalos arg = strdelim(&s); 69818de8d7fSPeter Avalos if (!arg || *arg == '\0') 69918de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 70018de8d7fSPeter Avalos if (!mac_valid(arg)) 70118de8d7fSPeter Avalos fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 70218de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 70318de8d7fSPeter Avalos if (*activep && options->macs == NULL) 70418de8d7fSPeter Avalos options->macs = xstrdup(arg); 70518de8d7fSPeter Avalos break; 70618de8d7fSPeter Avalos 707*9f304aafSPeter Avalos case oKexAlgorithms: 708*9f304aafSPeter Avalos arg = strdelim(&s); 709*9f304aafSPeter Avalos if (!arg || *arg == '\0') 710*9f304aafSPeter Avalos fatal("%.200s line %d: Missing argument.", 711*9f304aafSPeter Avalos filename, linenum); 712*9f304aafSPeter Avalos if (!kex_names_valid(arg)) 713*9f304aafSPeter Avalos fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 714*9f304aafSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 715*9f304aafSPeter Avalos if (*activep && options->kex_algorithms == NULL) 716*9f304aafSPeter Avalos options->kex_algorithms = xstrdup(arg); 717*9f304aafSPeter Avalos break; 718*9f304aafSPeter Avalos 71918de8d7fSPeter Avalos case oHostKeyAlgorithms: 72018de8d7fSPeter Avalos arg = strdelim(&s); 72118de8d7fSPeter Avalos if (!arg || *arg == '\0') 72218de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 72318de8d7fSPeter Avalos if (!key_names_valid2(arg)) 72418de8d7fSPeter Avalos fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 72518de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 72618de8d7fSPeter Avalos if (*activep && options->hostkeyalgorithms == NULL) 72718de8d7fSPeter Avalos options->hostkeyalgorithms = xstrdup(arg); 72818de8d7fSPeter Avalos break; 72918de8d7fSPeter Avalos 73018de8d7fSPeter Avalos case oProtocol: 73118de8d7fSPeter Avalos intptr = &options->protocol; 73218de8d7fSPeter Avalos arg = strdelim(&s); 73318de8d7fSPeter Avalos if (!arg || *arg == '\0') 73418de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 73518de8d7fSPeter Avalos value = proto_spec(arg); 73618de8d7fSPeter Avalos if (value == SSH_PROTO_UNKNOWN) 73718de8d7fSPeter Avalos fatal("%.200s line %d: Bad protocol spec '%s'.", 73818de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 73918de8d7fSPeter Avalos if (*activep && *intptr == SSH_PROTO_UNKNOWN) 74018de8d7fSPeter Avalos *intptr = value; 74118de8d7fSPeter Avalos break; 74218de8d7fSPeter Avalos 74318de8d7fSPeter Avalos case oLogLevel: 74418de8d7fSPeter Avalos log_level_ptr = &options->log_level; 74518de8d7fSPeter Avalos arg = strdelim(&s); 74618de8d7fSPeter Avalos value = log_level_number(arg); 74718de8d7fSPeter Avalos if (value == SYSLOG_LEVEL_NOT_SET) 74818de8d7fSPeter Avalos fatal("%.200s line %d: unsupported log level '%s'", 74918de8d7fSPeter Avalos filename, linenum, arg ? arg : "<NONE>"); 75018de8d7fSPeter Avalos if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 75118de8d7fSPeter Avalos *log_level_ptr = (LogLevel) value; 75218de8d7fSPeter Avalos break; 75318de8d7fSPeter Avalos 75418de8d7fSPeter Avalos case oLocalForward: 75518de8d7fSPeter Avalos case oRemoteForward: 756cb5eb4f1SPeter Avalos case oDynamicForward: 75718de8d7fSPeter Avalos arg = strdelim(&s); 75818de8d7fSPeter Avalos if (arg == NULL || *arg == '\0') 75918de8d7fSPeter Avalos fatal("%.200s line %d: Missing port argument.", 76018de8d7fSPeter Avalos filename, linenum); 761cb5eb4f1SPeter Avalos 762cb5eb4f1SPeter Avalos if (opcode == oLocalForward || 763cb5eb4f1SPeter Avalos opcode == oRemoteForward) { 76418de8d7fSPeter Avalos arg2 = strdelim(&s); 76518de8d7fSPeter Avalos if (arg2 == NULL || *arg2 == '\0') 76618de8d7fSPeter Avalos fatal("%.200s line %d: Missing target argument.", 76718de8d7fSPeter Avalos filename, linenum); 76818de8d7fSPeter Avalos 76918de8d7fSPeter Avalos /* construct a string for parse_forward */ 77018de8d7fSPeter Avalos snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 771cb5eb4f1SPeter Avalos } else if (opcode == oDynamicForward) { 772cb5eb4f1SPeter Avalos strlcpy(fwdarg, arg, sizeof(fwdarg)); 773cb5eb4f1SPeter Avalos } 77418de8d7fSPeter Avalos 775cb5eb4f1SPeter Avalos if (parse_forward(&fwd, fwdarg, 776cb5eb4f1SPeter Avalos opcode == oDynamicForward ? 1 : 0, 777cb5eb4f1SPeter Avalos opcode == oRemoteForward ? 1 : 0) == 0) 77818de8d7fSPeter Avalos fatal("%.200s line %d: Bad forwarding specification.", 77918de8d7fSPeter Avalos filename, linenum); 78018de8d7fSPeter Avalos 78118de8d7fSPeter Avalos if (*activep) { 782cb5eb4f1SPeter Avalos if (opcode == oLocalForward || 783cb5eb4f1SPeter Avalos opcode == oDynamicForward) 78418de8d7fSPeter Avalos add_local_forward(options, &fwd); 78518de8d7fSPeter Avalos else if (opcode == oRemoteForward) 78618de8d7fSPeter Avalos add_remote_forward(options, &fwd); 78718de8d7fSPeter Avalos } 78818de8d7fSPeter Avalos break; 78918de8d7fSPeter Avalos 79018de8d7fSPeter Avalos case oClearAllForwardings: 79118de8d7fSPeter Avalos intptr = &options->clear_forwardings; 79218de8d7fSPeter Avalos goto parse_flag; 79318de8d7fSPeter Avalos 79418de8d7fSPeter Avalos case oHost: 79518de8d7fSPeter Avalos *activep = 0; 79618de8d7fSPeter Avalos while ((arg = strdelim(&s)) != NULL && *arg != '\0') 79718de8d7fSPeter Avalos if (match_pattern(host, arg)) { 79818de8d7fSPeter Avalos debug("Applying options for %.100s", arg); 79918de8d7fSPeter Avalos *activep = 1; 80018de8d7fSPeter Avalos break; 80118de8d7fSPeter Avalos } 80218de8d7fSPeter Avalos /* Avoid garbage check below, as strdelim is done. */ 80318de8d7fSPeter Avalos return 0; 80418de8d7fSPeter Avalos 80518de8d7fSPeter Avalos case oEscapeChar: 80618de8d7fSPeter Avalos intptr = &options->escape_char; 80718de8d7fSPeter Avalos arg = strdelim(&s); 80818de8d7fSPeter Avalos if (!arg || *arg == '\0') 80918de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 81018de8d7fSPeter Avalos if (arg[0] == '^' && arg[2] == 0 && 81118de8d7fSPeter Avalos (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 81218de8d7fSPeter Avalos value = (u_char) arg[1] & 31; 81318de8d7fSPeter Avalos else if (strlen(arg) == 1) 81418de8d7fSPeter Avalos value = (u_char) arg[0]; 81518de8d7fSPeter Avalos else if (strcmp(arg, "none") == 0) 81618de8d7fSPeter Avalos value = SSH_ESCAPECHAR_NONE; 81718de8d7fSPeter Avalos else { 81818de8d7fSPeter Avalos fatal("%.200s line %d: Bad escape character.", 81918de8d7fSPeter Avalos filename, linenum); 82018de8d7fSPeter Avalos /* NOTREACHED */ 82118de8d7fSPeter Avalos value = 0; /* Avoid compiler warning. */ 82218de8d7fSPeter Avalos } 82318de8d7fSPeter Avalos if (*activep && *intptr == -1) 82418de8d7fSPeter Avalos *intptr = value; 82518de8d7fSPeter Avalos break; 82618de8d7fSPeter Avalos 82718de8d7fSPeter Avalos case oAddressFamily: 82818de8d7fSPeter Avalos arg = strdelim(&s); 82918de8d7fSPeter Avalos if (!arg || *arg == '\0') 83018de8d7fSPeter Avalos fatal("%s line %d: missing address family.", 83118de8d7fSPeter Avalos filename, linenum); 83218de8d7fSPeter Avalos intptr = &options->address_family; 83318de8d7fSPeter Avalos if (strcasecmp(arg, "inet") == 0) 83418de8d7fSPeter Avalos value = AF_INET; 83518de8d7fSPeter Avalos else if (strcasecmp(arg, "inet6") == 0) 83618de8d7fSPeter Avalos value = AF_INET6; 83718de8d7fSPeter Avalos else if (strcasecmp(arg, "any") == 0) 83818de8d7fSPeter Avalos value = AF_UNSPEC; 83918de8d7fSPeter Avalos else 84018de8d7fSPeter Avalos fatal("Unsupported AddressFamily \"%s\"", arg); 84118de8d7fSPeter Avalos if (*activep && *intptr == -1) 84218de8d7fSPeter Avalos *intptr = value; 84318de8d7fSPeter Avalos break; 84418de8d7fSPeter Avalos 84518de8d7fSPeter Avalos case oEnableSSHKeysign: 84618de8d7fSPeter Avalos intptr = &options->enable_ssh_keysign; 84718de8d7fSPeter Avalos goto parse_flag; 84818de8d7fSPeter Avalos 84918de8d7fSPeter Avalos case oIdentitiesOnly: 85018de8d7fSPeter Avalos intptr = &options->identities_only; 85118de8d7fSPeter Avalos goto parse_flag; 85218de8d7fSPeter Avalos 85318de8d7fSPeter Avalos case oServerAliveInterval: 85418de8d7fSPeter Avalos intptr = &options->server_alive_interval; 85518de8d7fSPeter Avalos goto parse_time; 85618de8d7fSPeter Avalos 85718de8d7fSPeter Avalos case oServerAliveCountMax: 85818de8d7fSPeter Avalos intptr = &options->server_alive_count_max; 85918de8d7fSPeter Avalos goto parse_int; 86018de8d7fSPeter Avalos 86118de8d7fSPeter Avalos case oSendEnv: 86218de8d7fSPeter Avalos while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 86318de8d7fSPeter Avalos if (strchr(arg, '=') != NULL) 86418de8d7fSPeter Avalos fatal("%s line %d: Invalid environment name.", 86518de8d7fSPeter Avalos filename, linenum); 86618de8d7fSPeter Avalos if (!*activep) 86718de8d7fSPeter Avalos continue; 86818de8d7fSPeter Avalos if (options->num_send_env >= MAX_SEND_ENV) 86918de8d7fSPeter Avalos fatal("%s line %d: too many send env.", 87018de8d7fSPeter Avalos filename, linenum); 87118de8d7fSPeter Avalos options->send_env[options->num_send_env++] = 87218de8d7fSPeter Avalos xstrdup(arg); 87318de8d7fSPeter Avalos } 87418de8d7fSPeter Avalos break; 87518de8d7fSPeter Avalos 87618de8d7fSPeter Avalos case oControlPath: 87718de8d7fSPeter Avalos charptr = &options->control_path; 87818de8d7fSPeter Avalos goto parse_string; 87918de8d7fSPeter Avalos 88018de8d7fSPeter Avalos case oControlMaster: 88118de8d7fSPeter Avalos intptr = &options->control_master; 88218de8d7fSPeter Avalos arg = strdelim(&s); 88318de8d7fSPeter Avalos if (!arg || *arg == '\0') 88418de8d7fSPeter Avalos fatal("%.200s line %d: Missing ControlMaster argument.", 88518de8d7fSPeter Avalos filename, linenum); 88618de8d7fSPeter Avalos value = 0; /* To avoid compiler warning... */ 88718de8d7fSPeter Avalos if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 88818de8d7fSPeter Avalos value = SSHCTL_MASTER_YES; 88918de8d7fSPeter Avalos else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 89018de8d7fSPeter Avalos value = SSHCTL_MASTER_NO; 89118de8d7fSPeter Avalos else if (strcmp(arg, "auto") == 0) 89218de8d7fSPeter Avalos value = SSHCTL_MASTER_AUTO; 89318de8d7fSPeter Avalos else if (strcmp(arg, "ask") == 0) 89418de8d7fSPeter Avalos value = SSHCTL_MASTER_ASK; 89518de8d7fSPeter Avalos else if (strcmp(arg, "autoask") == 0) 89618de8d7fSPeter Avalos value = SSHCTL_MASTER_AUTO_ASK; 89718de8d7fSPeter Avalos else 89818de8d7fSPeter Avalos fatal("%.200s line %d: Bad ControlMaster argument.", 89918de8d7fSPeter Avalos filename, linenum); 90018de8d7fSPeter Avalos if (*activep && *intptr == -1) 90118de8d7fSPeter Avalos *intptr = value; 90218de8d7fSPeter Avalos break; 90318de8d7fSPeter Avalos 904856ea928SPeter Avalos case oControlPersist: 905856ea928SPeter Avalos /* no/false/yes/true, or a time spec */ 906856ea928SPeter Avalos intptr = &options->control_persist; 907856ea928SPeter Avalos arg = strdelim(&s); 908856ea928SPeter Avalos if (!arg || *arg == '\0') 909856ea928SPeter Avalos fatal("%.200s line %d: Missing ControlPersist" 910856ea928SPeter Avalos " argument.", filename, linenum); 911856ea928SPeter Avalos value = 0; 912856ea928SPeter Avalos value2 = 0; /* timeout */ 913856ea928SPeter Avalos if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 914856ea928SPeter Avalos value = 0; 915856ea928SPeter Avalos else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 916856ea928SPeter Avalos value = 1; 917856ea928SPeter Avalos else if ((value2 = convtime(arg)) >= 0) 918856ea928SPeter Avalos value = 1; 919856ea928SPeter Avalos else 920856ea928SPeter Avalos fatal("%.200s line %d: Bad ControlPersist argument.", 921856ea928SPeter Avalos filename, linenum); 922856ea928SPeter Avalos if (*activep && *intptr == -1) { 923856ea928SPeter Avalos *intptr = value; 924856ea928SPeter Avalos options->control_persist_timeout = value2; 925856ea928SPeter Avalos } 926856ea928SPeter Avalos break; 927856ea928SPeter Avalos 92818de8d7fSPeter Avalos case oHashKnownHosts: 92918de8d7fSPeter Avalos intptr = &options->hash_known_hosts; 93018de8d7fSPeter Avalos goto parse_flag; 93118de8d7fSPeter Avalos 93218de8d7fSPeter Avalos case oTunnel: 93318de8d7fSPeter Avalos intptr = &options->tun_open; 93418de8d7fSPeter Avalos arg = strdelim(&s); 93518de8d7fSPeter Avalos if (!arg || *arg == '\0') 93618de8d7fSPeter Avalos fatal("%s line %d: Missing yes/point-to-point/" 93718de8d7fSPeter Avalos "ethernet/no argument.", filename, linenum); 93818de8d7fSPeter Avalos value = 0; /* silence compiler */ 93918de8d7fSPeter Avalos if (strcasecmp(arg, "ethernet") == 0) 94018de8d7fSPeter Avalos value = SSH_TUNMODE_ETHERNET; 94118de8d7fSPeter Avalos else if (strcasecmp(arg, "point-to-point") == 0) 94218de8d7fSPeter Avalos value = SSH_TUNMODE_POINTOPOINT; 94318de8d7fSPeter Avalos else if (strcasecmp(arg, "yes") == 0) 94418de8d7fSPeter Avalos value = SSH_TUNMODE_DEFAULT; 94518de8d7fSPeter Avalos else if (strcasecmp(arg, "no") == 0) 94618de8d7fSPeter Avalos value = SSH_TUNMODE_NO; 94718de8d7fSPeter Avalos else 94818de8d7fSPeter Avalos fatal("%s line %d: Bad yes/point-to-point/ethernet/" 94918de8d7fSPeter Avalos "no argument: %s", filename, linenum, arg); 95018de8d7fSPeter Avalos if (*activep) 95118de8d7fSPeter Avalos *intptr = value; 95218de8d7fSPeter Avalos break; 95318de8d7fSPeter Avalos 95418de8d7fSPeter Avalos case oTunnelDevice: 95518de8d7fSPeter Avalos arg = strdelim(&s); 95618de8d7fSPeter Avalos if (!arg || *arg == '\0') 95718de8d7fSPeter Avalos fatal("%.200s line %d: Missing argument.", filename, linenum); 95818de8d7fSPeter Avalos value = a2tun(arg, &value2); 95918de8d7fSPeter Avalos if (value == SSH_TUNID_ERR) 96018de8d7fSPeter Avalos fatal("%.200s line %d: Bad tun device.", filename, linenum); 96118de8d7fSPeter Avalos if (*activep) { 96218de8d7fSPeter Avalos options->tun_local = value; 96318de8d7fSPeter Avalos options->tun_remote = value2; 96418de8d7fSPeter Avalos } 96518de8d7fSPeter Avalos break; 96618de8d7fSPeter Avalos 96718de8d7fSPeter Avalos case oLocalCommand: 96818de8d7fSPeter Avalos charptr = &options->local_command; 96918de8d7fSPeter Avalos goto parse_command; 97018de8d7fSPeter Avalos 97118de8d7fSPeter Avalos case oPermitLocalCommand: 97218de8d7fSPeter Avalos intptr = &options->permit_local_command; 97318de8d7fSPeter Avalos goto parse_flag; 97418de8d7fSPeter Avalos 97518de8d7fSPeter Avalos case oVisualHostKey: 97618de8d7fSPeter Avalos intptr = &options->visual_host_key; 97718de8d7fSPeter Avalos goto parse_flag; 97818de8d7fSPeter Avalos 979*9f304aafSPeter Avalos case oIPQoS: 980*9f304aafSPeter Avalos arg = strdelim(&s); 981*9f304aafSPeter Avalos if ((value = parse_ipqos(arg)) == -1) 982*9f304aafSPeter Avalos fatal("%s line %d: Bad IPQoS value: %s", 983*9f304aafSPeter Avalos filename, linenum, arg); 984*9f304aafSPeter Avalos arg = strdelim(&s); 985*9f304aafSPeter Avalos if (arg == NULL) 986*9f304aafSPeter Avalos value2 = value; 987*9f304aafSPeter Avalos else if ((value2 = parse_ipqos(arg)) == -1) 988*9f304aafSPeter Avalos fatal("%s line %d: Bad IPQoS value: %s", 989*9f304aafSPeter Avalos filename, linenum, arg); 990*9f304aafSPeter Avalos if (*activep) { 991*9f304aafSPeter Avalos options->ip_qos_interactive = value; 992*9f304aafSPeter Avalos options->ip_qos_bulk = value2; 993*9f304aafSPeter Avalos } 994*9f304aafSPeter Avalos break; 995*9f304aafSPeter Avalos 99640c002afSPeter Avalos case oUseRoaming: 99740c002afSPeter Avalos intptr = &options->use_roaming; 99840c002afSPeter Avalos goto parse_flag; 99940c002afSPeter Avalos 100018de8d7fSPeter Avalos case oDeprecated: 100118de8d7fSPeter Avalos debug("%s line %d: Deprecated option \"%s\"", 100218de8d7fSPeter Avalos filename, linenum, keyword); 100318de8d7fSPeter Avalos return 0; 100418de8d7fSPeter Avalos 100518de8d7fSPeter Avalos case oUnsupported: 100618de8d7fSPeter Avalos error("%s line %d: Unsupported option \"%s\"", 100718de8d7fSPeter Avalos filename, linenum, keyword); 100818de8d7fSPeter Avalos return 0; 100918de8d7fSPeter Avalos 101018de8d7fSPeter Avalos default: 101118de8d7fSPeter Avalos fatal("process_config_line: Unimplemented opcode %d", opcode); 101218de8d7fSPeter Avalos } 101318de8d7fSPeter Avalos 101418de8d7fSPeter Avalos /* Check that there is no garbage at end of line. */ 101518de8d7fSPeter Avalos if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 101618de8d7fSPeter Avalos fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 101718de8d7fSPeter Avalos filename, linenum, arg); 101818de8d7fSPeter Avalos } 101918de8d7fSPeter Avalos return 0; 102018de8d7fSPeter Avalos } 102118de8d7fSPeter Avalos 102218de8d7fSPeter Avalos 102318de8d7fSPeter Avalos /* 102418de8d7fSPeter Avalos * Reads the config file and modifies the options accordingly. Options 102518de8d7fSPeter Avalos * should already be initialized before this call. This never returns if 102618de8d7fSPeter Avalos * there is an error. If the file does not exist, this returns 0. 102718de8d7fSPeter Avalos */ 102818de8d7fSPeter Avalos 102918de8d7fSPeter Avalos int 103018de8d7fSPeter Avalos read_config_file(const char *filename, const char *host, Options *options, 103118de8d7fSPeter Avalos int checkperm) 103218de8d7fSPeter Avalos { 103318de8d7fSPeter Avalos FILE *f; 103418de8d7fSPeter Avalos char line[1024]; 103518de8d7fSPeter Avalos int active, linenum; 103618de8d7fSPeter Avalos int bad_options = 0; 103718de8d7fSPeter Avalos 103818de8d7fSPeter Avalos if ((f = fopen(filename, "r")) == NULL) 103918de8d7fSPeter Avalos return 0; 104018de8d7fSPeter Avalos 104118de8d7fSPeter Avalos if (checkperm) { 104218de8d7fSPeter Avalos struct stat sb; 104318de8d7fSPeter Avalos 104418de8d7fSPeter Avalos if (fstat(fileno(f), &sb) == -1) 104518de8d7fSPeter Avalos fatal("fstat %s: %s", filename, strerror(errno)); 104618de8d7fSPeter Avalos if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 104718de8d7fSPeter Avalos (sb.st_mode & 022) != 0)) 104818de8d7fSPeter Avalos fatal("Bad owner or permissions on %s", filename); 104918de8d7fSPeter Avalos } 105018de8d7fSPeter Avalos 105118de8d7fSPeter Avalos debug("Reading configuration data %.200s", filename); 105218de8d7fSPeter Avalos 105318de8d7fSPeter Avalos /* 105418de8d7fSPeter Avalos * Mark that we are now processing the options. This flag is turned 105518de8d7fSPeter Avalos * on/off by Host specifications. 105618de8d7fSPeter Avalos */ 105718de8d7fSPeter Avalos active = 1; 105818de8d7fSPeter Avalos linenum = 0; 105918de8d7fSPeter Avalos while (fgets(line, sizeof(line), f)) { 106018de8d7fSPeter Avalos /* Update line number counter. */ 106118de8d7fSPeter Avalos linenum++; 106218de8d7fSPeter Avalos if (process_config_line(options, host, line, filename, linenum, &active) != 0) 106318de8d7fSPeter Avalos bad_options++; 106418de8d7fSPeter Avalos } 106518de8d7fSPeter Avalos fclose(f); 106618de8d7fSPeter Avalos if (bad_options > 0) 106718de8d7fSPeter Avalos fatal("%s: terminating, %d bad configuration options", 106818de8d7fSPeter Avalos filename, bad_options); 106918de8d7fSPeter Avalos return 1; 107018de8d7fSPeter Avalos } 107118de8d7fSPeter Avalos 107218de8d7fSPeter Avalos /* 107318de8d7fSPeter Avalos * Initializes options to special values that indicate that they have not yet 107418de8d7fSPeter Avalos * been set. Read_config_file will only set options with this value. Options 107518de8d7fSPeter Avalos * are processed in the following order: command line, user config file, 107618de8d7fSPeter Avalos * system config file. Last, fill_default_options is called. 107718de8d7fSPeter Avalos */ 107818de8d7fSPeter Avalos 107918de8d7fSPeter Avalos void 108018de8d7fSPeter Avalos initialize_options(Options * options) 108118de8d7fSPeter Avalos { 108218de8d7fSPeter Avalos memset(options, 'X', sizeof(*options)); 108318de8d7fSPeter Avalos options->forward_agent = -1; 108418de8d7fSPeter Avalos options->forward_x11 = -1; 108518de8d7fSPeter Avalos options->forward_x11_trusted = -1; 1086856ea928SPeter Avalos options->forward_x11_timeout = -1; 108718de8d7fSPeter Avalos options->exit_on_forward_failure = -1; 108818de8d7fSPeter Avalos options->xauth_location = NULL; 108918de8d7fSPeter Avalos options->gateway_ports = -1; 109018de8d7fSPeter Avalos options->use_privileged_port = -1; 109118de8d7fSPeter Avalos options->rsa_authentication = -1; 109218de8d7fSPeter Avalos options->pubkey_authentication = -1; 109318de8d7fSPeter Avalos options->challenge_response_authentication = -1; 109418de8d7fSPeter Avalos options->gss_authentication = -1; 109518de8d7fSPeter Avalos options->gss_deleg_creds = -1; 109618de8d7fSPeter Avalos options->password_authentication = -1; 109718de8d7fSPeter Avalos options->kbd_interactive_authentication = -1; 109818de8d7fSPeter Avalos options->kbd_interactive_devices = NULL; 109918de8d7fSPeter Avalos options->rhosts_rsa_authentication = -1; 110018de8d7fSPeter Avalos options->hostbased_authentication = -1; 110118de8d7fSPeter Avalos options->batch_mode = -1; 110218de8d7fSPeter Avalos options->check_host_ip = -1; 110318de8d7fSPeter Avalos options->strict_host_key_checking = -1; 110418de8d7fSPeter Avalos options->compression = -1; 110518de8d7fSPeter Avalos options->tcp_keep_alive = -1; 110618de8d7fSPeter Avalos options->compression_level = -1; 110718de8d7fSPeter Avalos options->port = -1; 110818de8d7fSPeter Avalos options->address_family = -1; 110918de8d7fSPeter Avalos options->connection_attempts = -1; 111018de8d7fSPeter Avalos options->connection_timeout = -1; 111118de8d7fSPeter Avalos options->number_of_password_prompts = -1; 111218de8d7fSPeter Avalos options->cipher = -1; 111318de8d7fSPeter Avalos options->ciphers = NULL; 111418de8d7fSPeter Avalos options->macs = NULL; 1115*9f304aafSPeter Avalos options->kex_algorithms = NULL; 111618de8d7fSPeter Avalos options->hostkeyalgorithms = NULL; 111718de8d7fSPeter Avalos options->protocol = SSH_PROTO_UNKNOWN; 111818de8d7fSPeter Avalos options->num_identity_files = 0; 111918de8d7fSPeter Avalos options->hostname = NULL; 112018de8d7fSPeter Avalos options->host_key_alias = NULL; 112118de8d7fSPeter Avalos options->proxy_command = NULL; 112218de8d7fSPeter Avalos options->user = NULL; 112318de8d7fSPeter Avalos options->escape_char = -1; 112418de8d7fSPeter Avalos options->system_hostfile = NULL; 112518de8d7fSPeter Avalos options->user_hostfile = NULL; 112618de8d7fSPeter Avalos options->system_hostfile2 = NULL; 112718de8d7fSPeter Avalos options->user_hostfile2 = NULL; 1128856ea928SPeter Avalos options->local_forwards = NULL; 112918de8d7fSPeter Avalos options->num_local_forwards = 0; 1130856ea928SPeter Avalos options->remote_forwards = NULL; 113118de8d7fSPeter Avalos options->num_remote_forwards = 0; 113218de8d7fSPeter Avalos options->clear_forwardings = -1; 113318de8d7fSPeter Avalos options->log_level = SYSLOG_LEVEL_NOT_SET; 113418de8d7fSPeter Avalos options->preferred_authentications = NULL; 113518de8d7fSPeter Avalos options->bind_address = NULL; 1136856ea928SPeter Avalos options->pkcs11_provider = NULL; 113718de8d7fSPeter Avalos options->enable_ssh_keysign = - 1; 113818de8d7fSPeter Avalos options->no_host_authentication_for_localhost = - 1; 113918de8d7fSPeter Avalos options->identities_only = - 1; 114018de8d7fSPeter Avalos options->rekey_limit = - 1; 114118de8d7fSPeter Avalos options->verify_host_key_dns = -1; 114218de8d7fSPeter Avalos options->server_alive_interval = -1; 114318de8d7fSPeter Avalos options->server_alive_count_max = -1; 114418de8d7fSPeter Avalos options->num_send_env = 0; 114518de8d7fSPeter Avalos options->control_path = NULL; 114618de8d7fSPeter Avalos options->control_master = -1; 1147856ea928SPeter Avalos options->control_persist = -1; 1148856ea928SPeter Avalos options->control_persist_timeout = 0; 114918de8d7fSPeter Avalos options->hash_known_hosts = -1; 115018de8d7fSPeter Avalos options->tun_open = -1; 115118de8d7fSPeter Avalos options->tun_local = -1; 115218de8d7fSPeter Avalos options->tun_remote = -1; 115318de8d7fSPeter Avalos options->local_command = NULL; 115418de8d7fSPeter Avalos options->permit_local_command = -1; 115540c002afSPeter Avalos options->use_roaming = -1; 115618de8d7fSPeter Avalos options->visual_host_key = -1; 1157cb5eb4f1SPeter Avalos options->zero_knowledge_password_authentication = -1; 1158*9f304aafSPeter Avalos options->ip_qos_interactive = -1; 1159*9f304aafSPeter Avalos options->ip_qos_bulk = -1; 116018de8d7fSPeter Avalos } 116118de8d7fSPeter Avalos 116218de8d7fSPeter Avalos /* 116318de8d7fSPeter Avalos * Called after processing other sources of option data, this fills those 116418de8d7fSPeter Avalos * options for which no value has been specified with their default values. 116518de8d7fSPeter Avalos */ 116618de8d7fSPeter Avalos 116718de8d7fSPeter Avalos void 116818de8d7fSPeter Avalos fill_default_options(Options * options) 116918de8d7fSPeter Avalos { 117018de8d7fSPeter Avalos int len; 117118de8d7fSPeter Avalos 117218de8d7fSPeter Avalos if (options->forward_agent == -1) 117318de8d7fSPeter Avalos options->forward_agent = 0; 117418de8d7fSPeter Avalos if (options->forward_x11 == -1) 117518de8d7fSPeter Avalos options->forward_x11 = 0; 117618de8d7fSPeter Avalos if (options->forward_x11_trusted == -1) 117718de8d7fSPeter Avalos options->forward_x11_trusted = 0; 1178856ea928SPeter Avalos if (options->forward_x11_timeout == -1) 1179856ea928SPeter Avalos options->forward_x11_timeout = 1200; 118018de8d7fSPeter Avalos if (options->exit_on_forward_failure == -1) 118118de8d7fSPeter Avalos options->exit_on_forward_failure = 0; 118218de8d7fSPeter Avalos if (options->xauth_location == NULL) 118318de8d7fSPeter Avalos options->xauth_location = _PATH_XAUTH; 118418de8d7fSPeter Avalos if (options->gateway_ports == -1) 118518de8d7fSPeter Avalos options->gateway_ports = 0; 118618de8d7fSPeter Avalos if (options->use_privileged_port == -1) 118718de8d7fSPeter Avalos options->use_privileged_port = 0; 118818de8d7fSPeter Avalos if (options->rsa_authentication == -1) 118918de8d7fSPeter Avalos options->rsa_authentication = 1; 119018de8d7fSPeter Avalos if (options->pubkey_authentication == -1) 119118de8d7fSPeter Avalos options->pubkey_authentication = 1; 119218de8d7fSPeter Avalos if (options->challenge_response_authentication == -1) 119318de8d7fSPeter Avalos options->challenge_response_authentication = 1; 119418de8d7fSPeter Avalos if (options->gss_authentication == -1) 119518de8d7fSPeter Avalos options->gss_authentication = 0; 119618de8d7fSPeter Avalos if (options->gss_deleg_creds == -1) 119718de8d7fSPeter Avalos options->gss_deleg_creds = 0; 119818de8d7fSPeter Avalos if (options->password_authentication == -1) 119918de8d7fSPeter Avalos options->password_authentication = 1; 120018de8d7fSPeter Avalos if (options->kbd_interactive_authentication == -1) 120118de8d7fSPeter Avalos options->kbd_interactive_authentication = 1; 120218de8d7fSPeter Avalos if (options->rhosts_rsa_authentication == -1) 120318de8d7fSPeter Avalos options->rhosts_rsa_authentication = 0; 120418de8d7fSPeter Avalos if (options->hostbased_authentication == -1) 120518de8d7fSPeter Avalos options->hostbased_authentication = 0; 120618de8d7fSPeter Avalos if (options->batch_mode == -1) 120718de8d7fSPeter Avalos options->batch_mode = 0; 120818de8d7fSPeter Avalos if (options->check_host_ip == -1) 120918de8d7fSPeter Avalos options->check_host_ip = 1; 121018de8d7fSPeter Avalos if (options->strict_host_key_checking == -1) 121118de8d7fSPeter Avalos options->strict_host_key_checking = 2; /* 2 is default */ 121218de8d7fSPeter Avalos if (options->compression == -1) 121318de8d7fSPeter Avalos options->compression = 0; 121418de8d7fSPeter Avalos if (options->tcp_keep_alive == -1) 121518de8d7fSPeter Avalos options->tcp_keep_alive = 1; 121618de8d7fSPeter Avalos if (options->compression_level == -1) 121718de8d7fSPeter Avalos options->compression_level = 6; 121818de8d7fSPeter Avalos if (options->port == -1) 121918de8d7fSPeter Avalos options->port = 0; /* Filled in ssh_connect. */ 122018de8d7fSPeter Avalos if (options->address_family == -1) 122118de8d7fSPeter Avalos options->address_family = AF_UNSPEC; 122218de8d7fSPeter Avalos if (options->connection_attempts == -1) 122318de8d7fSPeter Avalos options->connection_attempts = 1; 122418de8d7fSPeter Avalos if (options->number_of_password_prompts == -1) 122518de8d7fSPeter Avalos options->number_of_password_prompts = 3; 122618de8d7fSPeter Avalos /* Selected in ssh_login(). */ 122718de8d7fSPeter Avalos if (options->cipher == -1) 122818de8d7fSPeter Avalos options->cipher = SSH_CIPHER_NOT_SET; 122918de8d7fSPeter Avalos /* options->ciphers, default set in myproposals.h */ 123018de8d7fSPeter Avalos /* options->macs, default set in myproposals.h */ 1231*9f304aafSPeter Avalos /* options->kex_algorithms, default set in myproposals.h */ 123218de8d7fSPeter Avalos /* options->hostkeyalgorithms, default set in myproposals.h */ 123318de8d7fSPeter Avalos if (options->protocol == SSH_PROTO_UNKNOWN) 1234856ea928SPeter Avalos options->protocol = SSH_PROTO_2; 123518de8d7fSPeter Avalos if (options->num_identity_files == 0) { 123618de8d7fSPeter Avalos if (options->protocol & SSH_PROTO_1) { 123718de8d7fSPeter Avalos len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 123818de8d7fSPeter Avalos options->identity_files[options->num_identity_files] = 123918de8d7fSPeter Avalos xmalloc(len); 124018de8d7fSPeter Avalos snprintf(options->identity_files[options->num_identity_files++], 124118de8d7fSPeter Avalos len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 124218de8d7fSPeter Avalos } 124318de8d7fSPeter Avalos if (options->protocol & SSH_PROTO_2) { 124418de8d7fSPeter Avalos len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 124518de8d7fSPeter Avalos options->identity_files[options->num_identity_files] = 124618de8d7fSPeter Avalos xmalloc(len); 124718de8d7fSPeter Avalos snprintf(options->identity_files[options->num_identity_files++], 124818de8d7fSPeter Avalos len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 124918de8d7fSPeter Avalos 125018de8d7fSPeter Avalos len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 125118de8d7fSPeter Avalos options->identity_files[options->num_identity_files] = 125218de8d7fSPeter Avalos xmalloc(len); 125318de8d7fSPeter Avalos snprintf(options->identity_files[options->num_identity_files++], 125418de8d7fSPeter Avalos len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 1255*9f304aafSPeter Avalos #ifdef OPENSSL_HAS_ECC 1256*9f304aafSPeter Avalos len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1; 1257*9f304aafSPeter Avalos options->identity_files[options->num_identity_files] = 1258*9f304aafSPeter Avalos xmalloc(len); 1259*9f304aafSPeter Avalos snprintf(options->identity_files[options->num_identity_files++], 1260*9f304aafSPeter Avalos len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA); 1261*9f304aafSPeter Avalos #endif 126218de8d7fSPeter Avalos } 126318de8d7fSPeter Avalos } 126418de8d7fSPeter Avalos if (options->escape_char == -1) 126518de8d7fSPeter Avalos options->escape_char = '~'; 126618de8d7fSPeter Avalos if (options->system_hostfile == NULL) 126718de8d7fSPeter Avalos options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 126818de8d7fSPeter Avalos if (options->user_hostfile == NULL) 126918de8d7fSPeter Avalos options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 127018de8d7fSPeter Avalos if (options->system_hostfile2 == NULL) 127118de8d7fSPeter Avalos options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 127218de8d7fSPeter Avalos if (options->user_hostfile2 == NULL) 127318de8d7fSPeter Avalos options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 127418de8d7fSPeter Avalos if (options->log_level == SYSLOG_LEVEL_NOT_SET) 127518de8d7fSPeter Avalos options->log_level = SYSLOG_LEVEL_INFO; 127618de8d7fSPeter Avalos if (options->clear_forwardings == 1) 127718de8d7fSPeter Avalos clear_forwardings(options); 127818de8d7fSPeter Avalos if (options->no_host_authentication_for_localhost == - 1) 127918de8d7fSPeter Avalos options->no_host_authentication_for_localhost = 0; 128018de8d7fSPeter Avalos if (options->identities_only == -1) 128118de8d7fSPeter Avalos options->identities_only = 0; 128218de8d7fSPeter Avalos if (options->enable_ssh_keysign == -1) 128318de8d7fSPeter Avalos options->enable_ssh_keysign = 0; 128418de8d7fSPeter Avalos if (options->rekey_limit == -1) 128518de8d7fSPeter Avalos options->rekey_limit = 0; 128618de8d7fSPeter Avalos if (options->verify_host_key_dns == -1) 128718de8d7fSPeter Avalos options->verify_host_key_dns = 0; 128818de8d7fSPeter Avalos if (options->server_alive_interval == -1) 128918de8d7fSPeter Avalos options->server_alive_interval = 0; 129018de8d7fSPeter Avalos if (options->server_alive_count_max == -1) 129118de8d7fSPeter Avalos options->server_alive_count_max = 3; 129218de8d7fSPeter Avalos if (options->control_master == -1) 129318de8d7fSPeter Avalos options->control_master = 0; 1294856ea928SPeter Avalos if (options->control_persist == -1) { 1295856ea928SPeter Avalos options->control_persist = 0; 1296856ea928SPeter Avalos options->control_persist_timeout = 0; 1297856ea928SPeter Avalos } 129818de8d7fSPeter Avalos if (options->hash_known_hosts == -1) 129918de8d7fSPeter Avalos options->hash_known_hosts = 0; 130018de8d7fSPeter Avalos if (options->tun_open == -1) 130118de8d7fSPeter Avalos options->tun_open = SSH_TUNMODE_NO; 130218de8d7fSPeter Avalos if (options->tun_local == -1) 130318de8d7fSPeter Avalos options->tun_local = SSH_TUNID_ANY; 130418de8d7fSPeter Avalos if (options->tun_remote == -1) 130518de8d7fSPeter Avalos options->tun_remote = SSH_TUNID_ANY; 130618de8d7fSPeter Avalos if (options->permit_local_command == -1) 130718de8d7fSPeter Avalos options->permit_local_command = 0; 130840c002afSPeter Avalos if (options->use_roaming == -1) 130940c002afSPeter Avalos options->use_roaming = 1; 131018de8d7fSPeter Avalos if (options->visual_host_key == -1) 131118de8d7fSPeter Avalos options->visual_host_key = 0; 1312cb5eb4f1SPeter Avalos if (options->zero_knowledge_password_authentication == -1) 1313cb5eb4f1SPeter Avalos options->zero_knowledge_password_authentication = 0; 1314*9f304aafSPeter Avalos if (options->ip_qos_interactive == -1) 1315*9f304aafSPeter Avalos options->ip_qos_interactive = IPTOS_LOWDELAY; 1316*9f304aafSPeter Avalos if (options->ip_qos_bulk == -1) 1317*9f304aafSPeter Avalos options->ip_qos_bulk = IPTOS_THROUGHPUT; 131818de8d7fSPeter Avalos /* options->local_command should not be set by default */ 131918de8d7fSPeter Avalos /* options->proxy_command should not be set by default */ 132018de8d7fSPeter Avalos /* options->user will be set in the main program if appropriate */ 132118de8d7fSPeter Avalos /* options->hostname will be set in the main program if appropriate */ 132218de8d7fSPeter Avalos /* options->host_key_alias should not be set by default */ 132318de8d7fSPeter Avalos /* options->preferred_authentications will be set in ssh */ 132418de8d7fSPeter Avalos } 132518de8d7fSPeter Avalos 132618de8d7fSPeter Avalos /* 132718de8d7fSPeter Avalos * parse_forward 132818de8d7fSPeter Avalos * parses a string containing a port forwarding specification of the form: 1329cb5eb4f1SPeter Avalos * dynamicfwd == 0 133018de8d7fSPeter Avalos * [listenhost:]listenport:connecthost:connectport 1331cb5eb4f1SPeter Avalos * dynamicfwd == 1 1332cb5eb4f1SPeter Avalos * [listenhost:]listenport 133318de8d7fSPeter Avalos * returns number of arguments parsed or zero on error 133418de8d7fSPeter Avalos */ 133518de8d7fSPeter Avalos int 1336cb5eb4f1SPeter Avalos parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 133718de8d7fSPeter Avalos { 133818de8d7fSPeter Avalos int i; 133918de8d7fSPeter Avalos char *p, *cp, *fwdarg[4]; 134018de8d7fSPeter Avalos 134118de8d7fSPeter Avalos memset(fwd, '\0', sizeof(*fwd)); 134218de8d7fSPeter Avalos 134318de8d7fSPeter Avalos cp = p = xstrdup(fwdspec); 134418de8d7fSPeter Avalos 134518de8d7fSPeter Avalos /* skip leading spaces */ 134618de8d7fSPeter Avalos while (isspace(*cp)) 134718de8d7fSPeter Avalos cp++; 134818de8d7fSPeter Avalos 134918de8d7fSPeter Avalos for (i = 0; i < 4; ++i) 135018de8d7fSPeter Avalos if ((fwdarg[i] = hpdelim(&cp)) == NULL) 135118de8d7fSPeter Avalos break; 135218de8d7fSPeter Avalos 1353cb5eb4f1SPeter Avalos /* Check for trailing garbage */ 135418de8d7fSPeter Avalos if (cp != NULL) 135518de8d7fSPeter Avalos i = 0; /* failure */ 135618de8d7fSPeter Avalos 135718de8d7fSPeter Avalos switch (i) { 1358cb5eb4f1SPeter Avalos case 1: 1359cb5eb4f1SPeter Avalos fwd->listen_host = NULL; 1360cb5eb4f1SPeter Avalos fwd->listen_port = a2port(fwdarg[0]); 1361cb5eb4f1SPeter Avalos fwd->connect_host = xstrdup("socks"); 1362cb5eb4f1SPeter Avalos break; 1363cb5eb4f1SPeter Avalos 1364cb5eb4f1SPeter Avalos case 2: 1365cb5eb4f1SPeter Avalos fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1366cb5eb4f1SPeter Avalos fwd->listen_port = a2port(fwdarg[1]); 1367cb5eb4f1SPeter Avalos fwd->connect_host = xstrdup("socks"); 1368cb5eb4f1SPeter Avalos break; 1369cb5eb4f1SPeter Avalos 137018de8d7fSPeter Avalos case 3: 137118de8d7fSPeter Avalos fwd->listen_host = NULL; 137218de8d7fSPeter Avalos fwd->listen_port = a2port(fwdarg[0]); 137318de8d7fSPeter Avalos fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 137418de8d7fSPeter Avalos fwd->connect_port = a2port(fwdarg[2]); 137518de8d7fSPeter Avalos break; 137618de8d7fSPeter Avalos 137718de8d7fSPeter Avalos case 4: 137818de8d7fSPeter Avalos fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 137918de8d7fSPeter Avalos fwd->listen_port = a2port(fwdarg[1]); 138018de8d7fSPeter Avalos fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 138118de8d7fSPeter Avalos fwd->connect_port = a2port(fwdarg[3]); 138218de8d7fSPeter Avalos break; 138318de8d7fSPeter Avalos default: 138418de8d7fSPeter Avalos i = 0; /* failure */ 138518de8d7fSPeter Avalos } 138618de8d7fSPeter Avalos 138718de8d7fSPeter Avalos xfree(p); 138818de8d7fSPeter Avalos 1389cb5eb4f1SPeter Avalos if (dynamicfwd) { 1390cb5eb4f1SPeter Avalos if (!(i == 1 || i == 2)) 1391cb5eb4f1SPeter Avalos goto fail_free; 1392cb5eb4f1SPeter Avalos } else { 1393cb5eb4f1SPeter Avalos if (!(i == 3 || i == 4)) 1394cb5eb4f1SPeter Avalos goto fail_free; 1395cb5eb4f1SPeter Avalos if (fwd->connect_port <= 0) 1396cb5eb4f1SPeter Avalos goto fail_free; 1397cb5eb4f1SPeter Avalos } 1398cb5eb4f1SPeter Avalos 1399cb5eb4f1SPeter Avalos if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 140018de8d7fSPeter Avalos goto fail_free; 140118de8d7fSPeter Avalos 140218de8d7fSPeter Avalos if (fwd->connect_host != NULL && 140318de8d7fSPeter Avalos strlen(fwd->connect_host) >= NI_MAXHOST) 140418de8d7fSPeter Avalos goto fail_free; 1405cb5eb4f1SPeter Avalos if (fwd->listen_host != NULL && 1406cb5eb4f1SPeter Avalos strlen(fwd->listen_host) >= NI_MAXHOST) 1407cb5eb4f1SPeter Avalos goto fail_free; 1408cb5eb4f1SPeter Avalos 140918de8d7fSPeter Avalos 141018de8d7fSPeter Avalos return (i); 141118de8d7fSPeter Avalos 141218de8d7fSPeter Avalos fail_free: 1413cb5eb4f1SPeter Avalos if (fwd->connect_host != NULL) { 141418de8d7fSPeter Avalos xfree(fwd->connect_host); 1415cb5eb4f1SPeter Avalos fwd->connect_host = NULL; 1416cb5eb4f1SPeter Avalos } 1417cb5eb4f1SPeter Avalos if (fwd->listen_host != NULL) { 141818de8d7fSPeter Avalos xfree(fwd->listen_host); 1419cb5eb4f1SPeter Avalos fwd->listen_host = NULL; 1420cb5eb4f1SPeter Avalos } 142118de8d7fSPeter Avalos return (0); 142218de8d7fSPeter Avalos } 1423