Home | History | Annotate | Line # | Download | only in dist
      1  1.48  christos /*	$NetBSD: readconf.c,v 1.51 2026/04/08 18:58:41 christos Exp $	*/
      2  1.51  christos /* $OpenBSD: readconf.c,v 1.411 2026/03/30 07:18:24 djm Exp $ */
      3  1.42  christos 
      4   1.1  christos /*
      5   1.1  christos  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      6   1.1  christos  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      7   1.1  christos  *                    All rights reserved
      8   1.1  christos  * Functions for reading the configuration files.
      9   1.1  christos  *
     10   1.1  christos  * As far as I am concerned, the code I have written for this software
     11   1.1  christos  * can be used freely for any purpose.  Any derived versions of this
     12   1.1  christos  * software must be clearly marked as such, and if the derived work is
     13   1.1  christos  * incompatible with the protocol description in the RFC file, it must be
     14   1.1  christos  * called by a name other than "ssh" or "Secure Shell".
     15   1.1  christos  */
     16   1.1  christos 
     17   1.2  christos #include "includes.h"
     18  1.48  christos __RCSID("$NetBSD: readconf.c,v 1.51 2026/04/08 18:58:41 christos Exp $");
     19   1.1  christos #include <sys/types.h>
     20   1.1  christos #include <sys/stat.h>
     21   1.1  christos #include <sys/socket.h>
     22  1.12  christos #include <sys/wait.h>
     23  1.12  christos #include <sys/un.h>
     24   1.1  christos 
     25  1.42  christos #include <net/if.h>
     26   1.1  christos #include <netinet/in.h>
     27   1.5  christos #include <netinet/ip.h>
     28   1.1  christos 
     29   1.1  christos #include <ctype.h>
     30   1.1  christos #include <errno.h>
     31  1.19  christos #include <glob.h>
     32  1.42  christos #include <ifaddrs.h>
     33  1.51  christos #include <limits.h>
     34   1.1  christos #include <netdb.h>
     35  1.12  christos #include <paths.h>
     36  1.12  christos #include <pwd.h>
     37   1.1  christos #include <signal.h>
     38   1.1  christos #include <stdio.h>
     39   1.1  christos #include <string.h>
     40  1.29  christos #include <stdarg.h>
     41   1.1  christos #include <unistd.h>
     42  1.11  christos #include <util.h>
     43  1.13  christos #include <vis.h>
     44   1.1  christos 
     45   1.1  christos #include "xmalloc.h"
     46   1.1  christos #include "ssh.h"
     47   1.1  christos #include "cipher.h"
     48   1.1  christos #include "pathnames.h"
     49   1.1  christos #include "log.h"
     50  1.13  christos #include "sshkey.h"
     51  1.12  christos #include "misc.h"
     52   1.1  christos #include "readconf.h"
     53   1.1  christos #include "match.h"
     54   1.1  christos #include "kex.h"
     55   1.1  christos #include "mac.h"
     56  1.13  christos #include "myproposal.h"
     57  1.13  christos #include "digest.h"
     58  1.49  christos #include "version.h"
     59  1.51  christos #include "sshbuf.h"
     60  1.51  christos #include "fmt_scaled.h"
     61   1.1  christos 
     62   1.1  christos /* Format of the configuration file:
     63   1.1  christos 
     64   1.1  christos    # Configuration data is parsed as follows:
     65   1.1  christos    #  1. command line options
     66   1.1  christos    #  2. user-specific file
     67   1.1  christos    #  3. system-wide file
     68   1.1  christos    # Any configuration value is only changed the first time it is set.
     69   1.1  christos    # Thus, host-specific definitions should be at the beginning of the
     70   1.1  christos    # configuration file, and defaults at the end.
     71   1.1  christos 
     72   1.1  christos    # Host-specific declarations.  These may override anything above.  A single
     73   1.1  christos    # host may match multiple declarations; these are processed in the order
     74   1.1  christos    # that they are given in.
     75   1.1  christos 
     76   1.1  christos    Host *.ngs.fi ngs.fi
     77   1.1  christos      User foo
     78   1.1  christos 
     79   1.1  christos    Host fake.com
     80  1.28  christos      Hostname another.host.name.real.org
     81   1.1  christos      User blaah
     82   1.1  christos      Port 34289
     83   1.1  christos      ForwardX11 no
     84   1.1  christos      ForwardAgent no
     85   1.1  christos 
     86   1.1  christos    Host books.com
     87   1.1  christos      RemoteForward 9999 shadows.cs.hut.fi:9999
     88  1.21  christos      Ciphers 3des-cbc
     89   1.1  christos 
     90   1.1  christos    Host fascist.blob.com
     91   1.1  christos      Port 23123
     92   1.1  christos      User tylonen
     93   1.1  christos      PasswordAuthentication no
     94   1.1  christos 
     95   1.1  christos    Host puukko.hut.fi
     96   1.1  christos      User t35124p
     97   1.1  christos      ProxyCommand ssh-proxy %h %p
     98   1.1  christos 
     99   1.1  christos    Host *.fr
    100   1.1  christos      PublicKeyAuthentication no
    101   1.1  christos 
    102   1.1  christos    Host *.su
    103  1.21  christos      Ciphers aes128-ctr
    104   1.1  christos      PasswordAuthentication no
    105   1.1  christos 
    106   1.1  christos    Host vpn.fake.com
    107   1.1  christos      Tunnel yes
    108   1.1  christos      TunnelDevice 3
    109   1.1  christos 
    110   1.1  christos    # Defaults for various options
    111   1.1  christos    Host *
    112   1.1  christos      ForwardAgent no
    113   1.1  christos      ForwardX11 no
    114   1.1  christos      PasswordAuthentication yes
    115   1.1  christos      StrictHostKeyChecking yes
    116   1.1  christos      TcpKeepAlive no
    117   1.1  christos      IdentityFile ~/.ssh/identity
    118   1.1  christos      Port 22
    119   1.1  christos      EscapeChar ~
    120   1.1  christos 
    121   1.1  christos */
    122   1.1  christos 
    123  1.19  christos static int read_config_file_depth(const char *filename, struct passwd *pw,
    124  1.49  christos     const char *host, const char *original_host, const char *remote_command,
    125  1.49  christos     Options *options, int flags, int *activep, int *want_final_pass, int depth);
    126  1.19  christos static int process_config_line_depth(Options *options, struct passwd *pw,
    127  1.49  christos     const char *host, const char *original_host, const char *remote_command,
    128  1.49  christos     char *line, const char *filename, int linenum, int *activep, int flags,
    129  1.27  christos     int *want_final_pass, int depth);
    130  1.19  christos 
    131   1.1  christos /* Keyword tokens. */
    132   1.1  christos 
    133   1.1  christos typedef enum {
    134   1.1  christos 	oBadOption,
    135  1.42  christos 	oHost, oMatch, oInclude, oTag,
    136   1.4      adam 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
    137   1.4      adam 	oGatewayPorts, oExitOnForwardFailure,
    138  1.29  christos 	oPasswordAuthentication,
    139  1.35  christos 	oXAuthLocation,
    140   1.2  christos #if defined(KRB4) || defined(KRB5)
    141   1.2  christos 	oKerberosAuthentication,
    142   1.2  christos #endif
    143   1.2  christos #if defined(AFS) || defined(KRB5)
    144   1.2  christos 	oKerberosTgtPassing,
    145   1.2  christos #endif
    146   1.2  christos #ifdef AFS
    147   1.2  christos 	oAFSTokenPassing,
    148   1.2  christos #endif
    149  1.29  christos 	oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
    150  1.33  christos 	oPermitRemoteOpen,
    151  1.19  christos 	oCertificateFile, oAddKeysToAgent, oIdentityAgent,
    152  1.29  christos 	oUser, oEscapeChar, oProxyCommand,
    153   1.1  christos 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
    154   1.1  christos 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
    155  1.29  christos 	oTCPKeepAlive, oNumberOfPasswordPrompts,
    156  1.33  christos 	oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
    157  1.13  christos 	oPubkeyAuthentication,
    158   1.1  christos 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
    159   1.1  christos 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
    160  1.23  christos 	oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
    161  1.43        ws 	oIPv6PreferTemporary,
    162   1.1  christos 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    163   1.1  christos 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    164   1.1  christos 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
    165   1.1  christos 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    166  1.25  christos 	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
    167   1.4      adam 	oHashKnownHosts,
    168  1.22  christos 	oTunnel, oTunnelDevice,
    169  1.22  christos 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
    170  1.17  christos 	oVisualHostKey,
    171  1.35  christos 	oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
    172  1.35  christos 	oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
    173  1.12  christos 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
    174  1.12  christos 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
    175  1.13  christos 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
    176  1.33  christos 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
    177  1.33  christos 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
    178  1.40  christos 	oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
    179  1.44  christos 	oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
    180  1.50  christos 	oVersionAddendum, oRefuseConnection, oWarnWeakCrypto,
    181   1.2  christos 	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
    182   1.2  christos 	oHPNBufferSize,
    183   1.7       tls 	oSendVersionFirst,
    184  1.22  christos 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
    185   1.1  christos } OpCodes;
    186   1.1  christos 
    187   1.1  christos /* Textual representations of the tokens. */
    188   1.1  christos 
    189   1.1  christos static struct {
    190   1.1  christos 	const char *name;
    191   1.1  christos 	OpCodes opcode;
    192   1.1  christos } keywords[] = {
    193  1.21  christos 	/* Deprecated options */
    194  1.22  christos 	{ "protocol", oIgnore }, /* NB. silently ignored */
    195  1.22  christos 	{ "cipher", oDeprecated },
    196  1.21  christos 	{ "fallbacktorsh", oDeprecated },
    197  1.21  christos 	{ "globalknownhostsfile2", oDeprecated },
    198  1.21  christos 	{ "rhostsauthentication", oDeprecated },
    199  1.21  christos 	{ "userknownhostsfile2", oDeprecated },
    200  1.21  christos 	{ "useroaming", oDeprecated },
    201  1.21  christos 	{ "usersh", oDeprecated },
    202  1.25  christos 	{ "useprivilegedport", oDeprecated },
    203  1.21  christos 
    204  1.21  christos 	/* Unsupported options */
    205  1.30       kim #ifdef AFS
    206  1.30       kim 	{ "afstokenpassing", oAFSTokenPassing },
    207  1.30       kim #else
    208  1.21  christos 	{ "afstokenpassing", oUnsupported },
    209  1.30       kim #endif
    210  1.30       kim #if defined(KRB4) || defined(KRB5)
    211  1.30       kim 	{ "kerberosauthentication", oKerberosAuthentication },
    212  1.30       kim #else
    213  1.21  christos 	{ "kerberosauthentication", oUnsupported },
    214  1.30       kim #endif
    215  1.30       kim #if defined(AFS) || defined(KRB5)
    216  1.30       kim 	{ "kerberostgtpassing", oKerberosTgtPassing },
    217  1.30       kim 	{ "kerberos5tgtpassing", oKerberosTgtPassing },		/* alias */
    218  1.30       kim 	{ "kerberos4tgtpassing", oKerberosTgtPassing },		/* alias */
    219  1.30       kim #else
    220  1.21  christos 	{ "kerberostgtpassing", oUnsupported },
    221  1.30       kim 	{ "kerberos5tgtpassing", oUnsupported },
    222  1.30       kim 	{ "kerberos4tgtpassing", oUnsupported },
    223  1.30       kim #endif
    224  1.29  christos 	{ "rsaauthentication", oUnsupported },
    225  1.29  christos 	{ "rhostsrsaauthentication", oUnsupported },
    226  1.29  christos 	{ "compressionlevel", oUnsupported },
    227  1.21  christos 
    228  1.21  christos 	/* Sometimes-unsupported options */
    229  1.21  christos #if defined(GSSAPI)
    230  1.21  christos 	{ "gssapiauthentication", oGssAuthentication },
    231  1.21  christos 	{ "gssapidelegatecredentials", oGssDelegateCreds },
    232  1.21  christos # else
    233  1.21  christos 	{ "gssapiauthentication", oUnsupported },
    234  1.21  christos 	{ "gssapidelegatecredentials", oUnsupported },
    235  1.21  christos #endif
    236  1.21  christos #ifdef ENABLE_PKCS11
    237  1.27  christos 	{ "pkcs11provider", oPKCS11Provider },
    238  1.21  christos 	{ "smartcarddevice", oPKCS11Provider },
    239  1.21  christos # else
    240  1.21  christos 	{ "smartcarddevice", oUnsupported },
    241  1.21  christos 	{ "pkcs11provider", oUnsupported },
    242  1.21  christos #endif
    243  1.21  christos 
    244   1.1  christos 	{ "forwardagent", oForwardAgent },
    245   1.1  christos 	{ "forwardx11", oForwardX11 },
    246   1.1  christos 	{ "forwardx11trusted", oForwardX11Trusted },
    247   1.4      adam 	{ "forwardx11timeout", oForwardX11Timeout },
    248   1.1  christos 	{ "exitonforwardfailure", oExitOnForwardFailure },
    249   1.1  christos 	{ "xauthlocation", oXAuthLocation },
    250   1.1  christos 	{ "gatewayports", oGatewayPorts },
    251   1.1  christos 	{ "passwordauthentication", oPasswordAuthentication },
    252   1.1  christos 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
    253   1.1  christos 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
    254  1.36       kim 	{ "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
    255  1.36       kim 	{ "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
    256  1.36       kim 	{ "tisauthentication", oKbdInteractiveAuthentication },  /* alias */
    257   1.1  christos 	{ "pubkeyauthentication", oPubkeyAuthentication },
    258   1.1  christos 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
    259   1.1  christos 	{ "hostbasedauthentication", oHostbasedAuthentication },
    260   1.1  christos #if defined(GSSAPI)
    261   1.1  christos 	{ "gssapiauthentication", oGssAuthentication },
    262   1.1  christos 	{ "gssapidelegatecredentials", oGssDelegateCreds },
    263   1.1  christos #else
    264   1.1  christos 	{ "gssapiauthentication", oUnsupported },
    265   1.1  christos 	{ "gssapidelegatecredentials", oUnsupported },
    266   1.1  christos #endif
    267   1.1  christos 	{ "identityfile", oIdentityFile },
    268   1.1  christos 	{ "identityfile2", oIdentityFile },			/* obsolete */
    269   1.1  christos 	{ "identitiesonly", oIdentitiesOnly },
    270  1.18  christos 	{ "certificatefile", oCertificateFile },
    271  1.18  christos 	{ "addkeystoagent", oAddKeysToAgent },
    272  1.19  christos 	{ "identityagent", oIdentityAgent },
    273  1.28  christos 	{ "hostname", oHostname },
    274   1.1  christos 	{ "hostkeyalias", oHostKeyAlias },
    275   1.1  christos 	{ "proxycommand", oProxyCommand },
    276   1.1  christos 	{ "port", oPort },
    277   1.1  christos 	{ "ciphers", oCiphers },
    278   1.1  christos 	{ "macs", oMacs },
    279   1.1  christos 	{ "remoteforward", oRemoteForward },
    280   1.1  christos 	{ "localforward", oLocalForward },
    281  1.33  christos 	{ "permitremoteopen", oPermitRemoteOpen },
    282   1.1  christos 	{ "user", oUser },
    283   1.1  christos 	{ "host", oHost },
    284  1.12  christos 	{ "match", oMatch },
    285  1.42  christos 	{ "tag", oTag },
    286   1.1  christos 	{ "escapechar", oEscapeChar },
    287   1.1  christos 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
    288   1.1  christos 	{ "userknownhostsfile", oUserKnownHostsFile },
    289   1.1  christos 	{ "connectionattempts", oConnectionAttempts },
    290   1.1  christos 	{ "batchmode", oBatchMode },
    291   1.1  christos 	{ "checkhostip", oCheckHostIP },
    292   1.1  christos 	{ "stricthostkeychecking", oStrictHostKeyChecking },
    293   1.1  christos 	{ "compression", oCompression },
    294   1.1  christos 	{ "tcpkeepalive", oTCPKeepAlive },
    295   1.1  christos 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
    296   1.1  christos 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
    297  1.22  christos 	{ "syslogfacility", oLogFacility },
    298   1.1  christos 	{ "loglevel", oLogLevel },
    299  1.33  christos 	{ "logverbose", oLogVerbose },
    300   1.1  christos 	{ "dynamicforward", oDynamicForward },
    301   1.1  christos 	{ "preferredauthentications", oPreferredAuthentications },
    302   1.1  christos 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
    303  1.27  christos 	{ "casignaturealgorithms", oCASignatureAlgorithms },
    304   1.1  christos 	{ "bindaddress", oBindAddress },
    305  1.23  christos 	{ "bindinterface", oBindInterface },
    306  1.43        ws 	{ "ipv6prefertemporary", oIPv6PreferTemporary },
    307   1.1  christos 	{ "clearallforwardings", oClearAllForwardings },
    308   1.1  christos 	{ "enablesshkeysign", oEnableSSHKeysign },
    309   1.1  christos 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
    310   1.1  christos 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
    311   1.1  christos 	{ "rekeylimit", oRekeyLimit },
    312   1.1  christos 	{ "connecttimeout", oConnectTimeout },
    313   1.1  christos 	{ "addressfamily", oAddressFamily },
    314   1.1  christos 	{ "serveraliveinterval", oServerAliveInterval },
    315   1.1  christos 	{ "serveralivecountmax", oServerAliveCountMax },
    316   1.1  christos 	{ "sendenv", oSendEnv },
    317  1.25  christos 	{ "setenv", oSetEnv },
    318   1.1  christos 	{ "controlpath", oControlPath },
    319   1.1  christos 	{ "controlmaster", oControlMaster },
    320   1.4      adam 	{ "controlpersist", oControlPersist },
    321   1.1  christos 	{ "hashknownhosts", oHashKnownHosts },
    322  1.19  christos 	{ "include", oInclude },
    323   1.1  christos 	{ "tunnel", oTunnel },
    324   1.1  christos 	{ "tunneldevice", oTunnelDevice },
    325   1.1  christos 	{ "localcommand", oLocalCommand },
    326   1.1  christos 	{ "permitlocalcommand", oPermitLocalCommand },
    327  1.22  christos 	{ "remotecommand", oRemoteCommand },
    328   1.1  christos 	{ "visualhostkey", oVisualHostKey },
    329   1.5  christos 	{ "kexalgorithms", oKexAlgorithms },
    330   1.5  christos 	{ "ipqos", oIPQoS },
    331   1.6  christos 	{ "requesttty", oRequestTTY },
    332  1.35  christos 	{ "sessiontype", oSessionType },
    333  1.35  christos 	{ "stdinnull", oStdinNull },
    334  1.35  christos 	{ "forkafterauthentication", oForkAfterAuthentication },
    335  1.12  christos 	{ "proxyusefdpass", oProxyUseFdpass },
    336  1.12  christos 	{ "canonicaldomains", oCanonicalDomains },
    337  1.12  christos 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
    338  1.12  christos 	{ "canonicalizehostname", oCanonicalizeHostname },
    339  1.12  christos 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
    340  1.12  christos 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
    341  1.12  christos 	{ "streamlocalbindmask", oStreamLocalBindMask },
    342  1.12  christos 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
    343  1.13  christos 	{ "revokedhostkeys", oRevokedHostKeys },
    344  1.13  christos 	{ "fingerprinthash", oFingerprintHash },
    345  1.13  christos 	{ "updatehostkeys", oUpdateHostkeys },
    346  1.35  christos 	{ "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
    347  1.33  christos 	{ "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
    348  1.33  christos 	{ "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
    349  1.33  christos 	{ "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
    350  1.19  christos 	{ "proxyjump", oProxyJump },
    351   1.2  christos 	{ "noneenabled", oNoneEnabled },
    352   1.2  christos 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
    353   1.2  christos 	{ "tcprcvbuf", oTcpRcvBuf },
    354   1.2  christos 	{ "noneswitch", oNoneSwitch },
    355   1.2  christos 	{ "hpndisabled", oHPNDisabled },
    356   1.2  christos 	{ "hpnbuffersize", oHPNBufferSize },
    357   1.7       tls 	{ "sendversionfirst", oSendVersionFirst },
    358  1.12  christos 	{ "ignoreunknown", oIgnoreUnknown },
    359  1.29  christos 	{ "proxyjump", oProxyJump },
    360  1.29  christos 	{ "securitykeyprovider", oSecurityKeyProvider },
    361  1.33  christos 	{ "knownhostscommand", oKnownHostsCommand },
    362  1.40  christos 	{ "requiredrsasize", oRequiredRSASize },
    363  1.41  christos 	{ "enableescapecommandline", oEnableEscapeCommandline },
    364  1.42  christos 	{ "obscurekeystroketiming", oObscureKeystrokeTiming },
    365  1.44  christos 	{ "channeltimeout", oChannelTimeout },
    366  1.49  christos 	{ "versionaddendum", oVersionAddendum },
    367  1.50  christos 	{ "refuseconnection", oRefuseConnection },
    368  1.50  christos 	{ "warnweakcrypto", oWarnWeakCrypto },
    369  1.19  christos 
    370   1.1  christos 	{ NULL, oBadOption }
    371   1.1  christos };
    372   1.1  christos 
    373  1.33  christos static const char *lookup_opcode_name(OpCodes code);
    374  1.29  christos 
    375  1.29  christos const char *
    376  1.29  christos kex_default_pk_alg(void)
    377  1.29  christos {
    378  1.33  christos 	static char *pkalgs;
    379  1.33  christos 
    380  1.33  christos 	if (pkalgs == NULL) {
    381  1.33  christos 		char *all_key;
    382  1.33  christos 
    383  1.33  christos 		all_key = sshkey_alg_list(0, 0, 1, ',');
    384  1.33  christos 		pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
    385  1.33  christos 		free(all_key);
    386  1.33  christos 	}
    387  1.33  christos 	return pkalgs;
    388  1.29  christos }
    389  1.29  christos 
    390  1.31  christos char *
    391  1.31  christos ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
    392  1.44  christos     const char *user, const char *jumphost)
    393  1.31  christos {
    394  1.31  christos 	struct ssh_digest_ctx *md;
    395  1.31  christos 	u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
    396  1.31  christos 
    397  1.31  christos 	if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
    398  1.31  christos 	    ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
    399  1.31  christos 	    ssh_digest_update(md, host, strlen(host)) < 0 ||
    400  1.31  christos 	    ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
    401  1.31  christos 	    ssh_digest_update(md, user, strlen(user)) < 0 ||
    402  1.44  christos 	    ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 ||
    403  1.31  christos 	    ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
    404  1.33  christos 		fatal_f("mux digest failed");
    405  1.31  christos 	ssh_digest_free(md);
    406  1.31  christos 	return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
    407  1.31  christos }
    408  1.31  christos 
    409   1.1  christos /*
    410   1.1  christos  * Adds a local TCP/IP port forward to options.  Never returns if there is an
    411   1.1  christos  * error.
    412   1.1  christos  */
    413   1.1  christos 
    414   1.1  christos void
    415  1.12  christos add_local_forward(Options *options, const struct Forward *newfwd)
    416   1.1  christos {
    417  1.12  christos 	struct Forward *fwd;
    418  1.19  christos 	int i;
    419   1.4      adam 
    420  1.19  christos 	/* Don't add duplicates */
    421  1.19  christos 	for (i = 0; i < options->num_local_forwards; i++) {
    422  1.19  christos 		if (forward_equals(newfwd, options->local_forwards + i))
    423  1.19  christos 			return;
    424  1.19  christos 	}
    425  1.14  christos 	options->local_forwards = xreallocarray(options->local_forwards,
    426   1.4      adam 	    options->num_local_forwards + 1,
    427   1.4      adam 	    sizeof(*options->local_forwards));
    428   1.1  christos 	fwd = &options->local_forwards[options->num_local_forwards++];
    429   1.1  christos 
    430   1.1  christos 	fwd->listen_host = newfwd->listen_host;
    431   1.1  christos 	fwd->listen_port = newfwd->listen_port;
    432  1.12  christos 	fwd->listen_path = newfwd->listen_path;
    433   1.1  christos 	fwd->connect_host = newfwd->connect_host;
    434   1.1  christos 	fwd->connect_port = newfwd->connect_port;
    435  1.12  christos 	fwd->connect_path = newfwd->connect_path;
    436   1.1  christos }
    437   1.1  christos 
    438   1.1  christos /*
    439   1.1  christos  * Adds a remote TCP/IP port forward to options.  Never returns if there is
    440   1.1  christos  * an error.
    441   1.1  christos  */
    442   1.1  christos 
    443   1.1  christos void
    444  1.12  christos add_remote_forward(Options *options, const struct Forward *newfwd)
    445   1.1  christos {
    446  1.12  christos 	struct Forward *fwd;
    447  1.19  christos 	int i;
    448   1.4      adam 
    449  1.19  christos 	/* Don't add duplicates */
    450  1.19  christos 	for (i = 0; i < options->num_remote_forwards; i++) {
    451  1.19  christos 		if (forward_equals(newfwd, options->remote_forwards + i))
    452  1.19  christos 			return;
    453  1.19  christos 	}
    454  1.14  christos 	options->remote_forwards = xreallocarray(options->remote_forwards,
    455   1.4      adam 	    options->num_remote_forwards + 1,
    456   1.4      adam 	    sizeof(*options->remote_forwards));
    457   1.1  christos 	fwd = &options->remote_forwards[options->num_remote_forwards++];
    458   1.1  christos 
    459   1.1  christos 	fwd->listen_host = newfwd->listen_host;
    460   1.1  christos 	fwd->listen_port = newfwd->listen_port;
    461  1.12  christos 	fwd->listen_path = newfwd->listen_path;
    462   1.1  christos 	fwd->connect_host = newfwd->connect_host;
    463   1.1  christos 	fwd->connect_port = newfwd->connect_port;
    464  1.12  christos 	fwd->connect_path = newfwd->connect_path;
    465   1.8  christos 	fwd->handle = newfwd->handle;
    466   1.4      adam 	fwd->allocated_port = 0;
    467   1.1  christos }
    468   1.1  christos 
    469   1.1  christos static void
    470   1.1  christos clear_forwardings(Options *options)
    471   1.1  christos {
    472   1.1  christos 	int i;
    473   1.1  christos 
    474   1.1  christos 	for (i = 0; i < options->num_local_forwards; i++) {
    475  1.11  christos 		free(options->local_forwards[i].listen_host);
    476  1.12  christos 		free(options->local_forwards[i].listen_path);
    477  1.11  christos 		free(options->local_forwards[i].connect_host);
    478  1.12  christos 		free(options->local_forwards[i].connect_path);
    479   1.1  christos 	}
    480   1.4      adam 	if (options->num_local_forwards > 0) {
    481  1.11  christos 		free(options->local_forwards);
    482   1.4      adam 		options->local_forwards = NULL;
    483   1.4      adam 	}
    484   1.1  christos 	options->num_local_forwards = 0;
    485   1.1  christos 	for (i = 0; i < options->num_remote_forwards; i++) {
    486  1.11  christos 		free(options->remote_forwards[i].listen_host);
    487  1.12  christos 		free(options->remote_forwards[i].listen_path);
    488  1.11  christos 		free(options->remote_forwards[i].connect_host);
    489  1.12  christos 		free(options->remote_forwards[i].connect_path);
    490   1.1  christos 	}
    491   1.4      adam 	if (options->num_remote_forwards > 0) {
    492  1.11  christos 		free(options->remote_forwards);
    493   1.4      adam 		options->remote_forwards = NULL;
    494   1.4      adam 	}
    495   1.1  christos 	options->num_remote_forwards = 0;
    496   1.1  christos 	options->tun_open = SSH_TUNMODE_NO;
    497   1.1  christos }
    498   1.1  christos 
    499   1.9   mlelstv void
    500  1.18  christos add_certificate_file(Options *options, const char *path, int userprovided)
    501  1.18  christos {
    502  1.18  christos 	int i;
    503  1.18  christos 
    504  1.18  christos 	if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
    505  1.18  christos 		fatal("Too many certificate files specified (max %d)",
    506  1.18  christos 		    SSH_MAX_CERTIFICATE_FILES);
    507  1.18  christos 
    508  1.18  christos 	/* Avoid registering duplicates */
    509  1.18  christos 	for (i = 0; i < options->num_certificate_files; i++) {
    510  1.18  christos 		if (options->certificate_file_userprovided[i] == userprovided &&
    511  1.18  christos 		    strcmp(options->certificate_files[i], path) == 0) {
    512  1.33  christos 			debug2_f("ignoring duplicate key %s", path);
    513  1.18  christos 			return;
    514  1.18  christos 		}
    515  1.18  christos 	}
    516  1.18  christos 
    517  1.18  christos 	options->certificate_file_userprovided[options->num_certificate_files] =
    518  1.18  christos 	    userprovided;
    519  1.18  christos 	options->certificate_files[options->num_certificate_files++] =
    520  1.18  christos 	    xstrdup(path);
    521  1.18  christos }
    522  1.18  christos 
    523  1.18  christos void
    524   1.9   mlelstv add_identity_file(Options *options, const char *dir, const char *filename,
    525   1.9   mlelstv     int userprovided)
    526   1.9   mlelstv {
    527   1.9   mlelstv 	char *path;
    528  1.12  christos 	int i;
    529   1.9   mlelstv 
    530   1.9   mlelstv 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
    531   1.9   mlelstv 		fatal("Too many identity files specified (max %d)",
    532   1.9   mlelstv 		    SSH_MAX_IDENTITY_FILES);
    533   1.9   mlelstv 
    534   1.9   mlelstv 	if (dir == NULL) /* no dir, filename is absolute */
    535   1.9   mlelstv 		path = xstrdup(filename);
    536  1.22  christos 	else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
    537  1.22  christos 		fatal("Identity file path %s too long", path);
    538   1.9   mlelstv 
    539  1.12  christos 	/* Avoid registering duplicates */
    540  1.12  christos 	for (i = 0; i < options->num_identity_files; i++) {
    541  1.12  christos 		if (options->identity_file_userprovided[i] == userprovided &&
    542  1.12  christos 		    strcmp(options->identity_files[i], path) == 0) {
    543  1.33  christos 			debug2_f("ignoring duplicate key %s", path);
    544  1.12  christos 			free(path);
    545  1.12  christos 			return;
    546  1.12  christos 		}
    547  1.12  christos 	}
    548  1.12  christos 
    549   1.9   mlelstv 	options->identity_file_userprovided[options->num_identity_files] =
    550   1.9   mlelstv 	    userprovided;
    551   1.9   mlelstv 	options->identity_files[options->num_identity_files++] = path;
    552   1.9   mlelstv }
    553   1.9   mlelstv 
    554  1.12  christos int
    555  1.12  christos default_ssh_port(void)
    556  1.12  christos {
    557  1.12  christos 	static int port;
    558  1.12  christos 	struct servent *sp;
    559  1.12  christos 
    560  1.12  christos 	if (port == 0) {
    561  1.12  christos 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
    562  1.12  christos 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
    563  1.12  christos 	}
    564  1.12  christos 	return port;
    565  1.12  christos }
    566  1.12  christos 
    567  1.12  christos /*
    568  1.12  christos  * Execute a command in a shell.
    569  1.12  christos  * Return its exit status or -1 on abnormal exit.
    570  1.12  christos  */
    571  1.12  christos static int
    572  1.12  christos execute_in_shell(const char *cmd)
    573  1.12  christos {
    574  1.12  christos 	const char *shell;
    575  1.12  christos 	pid_t pid;
    576  1.33  christos 	int status;
    577  1.12  christos 
    578  1.12  christos 	if ((shell = getenv("SHELL")) == NULL)
    579  1.12  christos 		shell = _PATH_BSHELL;
    580  1.12  christos 
    581  1.28  christos 	if (access(shell, X_OK) == -1) {
    582  1.28  christos 		fatal("Shell \"%s\" is not executable: %s",
    583  1.28  christos 		    shell, strerror(errno));
    584  1.28  christos 	}
    585  1.28  christos 
    586  1.12  christos 	debug("Executing command: '%.500s'", cmd);
    587  1.12  christos 
    588  1.12  christos 	/* Fork and execute the command. */
    589  1.12  christos 	if ((pid = fork()) == 0) {
    590  1.12  christos 		char *argv[4];
    591  1.12  christos 
    592  1.33  christos 		if (stdfd_devnull(1, 1, 0) == -1)
    593  1.33  christos 			fatal_f("stdfd_devnull failed");
    594  1.33  christos 		closefrom(STDERR_FILENO + 1);
    595  1.12  christos 
    596  1.12  christos 		argv[0] = __UNCONST(shell);
    597  1.12  christos 		argv[1] = __UNCONST("-c");
    598  1.18  christos 		argv[2] = xstrdup(cmd);
    599  1.12  christos 		argv[3] = NULL;
    600  1.12  christos 
    601  1.12  christos 		execv(argv[0], argv);
    602  1.12  christos 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
    603  1.12  christos 		/* Die with signal to make this error apparent to parent. */
    604  1.29  christos 		ssh_signal(SIGTERM, SIG_DFL);
    605  1.12  christos 		kill(getpid(), SIGTERM);
    606  1.12  christos 		_exit(1);
    607  1.12  christos 	}
    608  1.12  christos 	/* Parent. */
    609  1.28  christos 	if (pid == -1)
    610  1.33  christos 		fatal_f("fork: %.100s", strerror(errno));
    611  1.12  christos 
    612  1.12  christos 	while (waitpid(pid, &status, 0) == -1) {
    613  1.12  christos 		if (errno != EINTR && errno != EAGAIN)
    614  1.33  christos 			fatal_f("waitpid: %s", strerror(errno));
    615  1.12  christos 	}
    616  1.12  christos 	if (!WIFEXITED(status)) {
    617  1.12  christos 		error("command '%.100s' exited abnormally", cmd);
    618  1.12  christos 		return -1;
    619  1.13  christos 	}
    620  1.12  christos 	debug3("command returned status %d", WEXITSTATUS(status));
    621  1.12  christos 	return WEXITSTATUS(status);
    622  1.12  christos }
    623  1.12  christos 
    624  1.12  christos /*
    625  1.42  christos  * Check whether a local network interface address appears in CIDR pattern-
    626  1.42  christos  * list 'addrlist'. Returns 1 if matched or 0 otherwise.
    627  1.42  christos  */
    628  1.42  christos static int
    629  1.42  christos check_match_ifaddrs(const char *addrlist)
    630  1.42  christos {
    631  1.42  christos 	struct ifaddrs *ifa, *ifaddrs = NULL;
    632  1.42  christos 	int r, found = 0;
    633  1.42  christos 	char addr[NI_MAXHOST];
    634  1.42  christos 	socklen_t salen;
    635  1.42  christos 
    636  1.42  christos 	if (getifaddrs(&ifaddrs) != 0) {
    637  1.42  christos 		error("match localnetwork: getifaddrs failed: %s",
    638  1.42  christos 		    strerror(errno));
    639  1.42  christos 		return 0;
    640  1.42  christos 	}
    641  1.42  christos 	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
    642  1.42  christos 		if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
    643  1.42  christos 		    (ifa->ifa_flags & IFF_UP) == 0)
    644  1.42  christos 			continue;
    645  1.42  christos 		switch (ifa->ifa_addr->sa_family) {
    646  1.42  christos 		case AF_INET:
    647  1.42  christos 			salen = sizeof(struct sockaddr_in);
    648  1.42  christos 			break;
    649  1.42  christos 		case AF_INET6:
    650  1.42  christos 			salen = sizeof(struct sockaddr_in6);
    651  1.42  christos 			break;
    652  1.42  christos 		case AF_LINK:
    653  1.42  christos 			/* ignore */
    654  1.42  christos 			continue;
    655  1.42  christos 		default:
    656  1.42  christos 			debug2_f("interface %s: unsupported address family %d",
    657  1.42  christos 			    ifa->ifa_name, ifa->ifa_addr->sa_family);
    658  1.42  christos 			continue;
    659  1.42  christos 		}
    660  1.42  christos 		if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
    661  1.42  christos 		    NULL, 0, NI_NUMERICHOST)) != 0) {
    662  1.42  christos 			debug2_f("interface %s getnameinfo failed: %s",
    663  1.42  christos 			    ifa->ifa_name, gai_strerror(r));
    664  1.42  christos 			continue;
    665  1.42  christos 		}
    666  1.42  christos 		debug3_f("interface %s addr %s", ifa->ifa_name, addr);
    667  1.42  christos 		if (addr_match_cidr_list(addr, addrlist) == 1) {
    668  1.42  christos 			debug3_f("matched interface %s: address %s in %s",
    669  1.42  christos 			    ifa->ifa_name, addr, addrlist);
    670  1.42  christos 			found = 1;
    671  1.42  christos 			break;
    672  1.42  christos 		}
    673  1.42  christos 	}
    674  1.42  christos 	freeifaddrs(ifaddrs);
    675  1.42  christos 	return found;
    676  1.42  christos }
    677  1.42  christos 
    678  1.42  christos /*
    679  1.47  christos  * Expand a "match exec" command or an Include path, caller must free returned
    680  1.47  christos  * value.
    681  1.47  christos  */
    682  1.47  christos static char *
    683  1.47  christos expand_match_exec_or_include_path(const char *path, Options *options,
    684  1.47  christos     struct passwd *pw, const char *host_arg, const char *original_host,
    685  1.47  christos     int final_pass, int is_include_path)
    686  1.47  christos {
    687  1.47  christos 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
    688  1.47  christos 	char uidstr[32], *conn_hash_hex, *keyalias, *ruser;
    689  1.47  christos 	const char *jmphost;
    690  1.47  christos 	char *host, *ret;
    691  1.47  christos 	int port;
    692  1.47  christos 
    693  1.47  christos 	port = options->port <= 0 ? default_ssh_port() : options->port;
    694  1.47  christos 	ruser = options->user == NULL ? pw->pw_name : options->user;
    695  1.47  christos 	if (final_pass) {
    696  1.47  christos 		host = xstrdup(options->hostname);
    697  1.47  christos 	} else if (options->hostname != NULL) {
    698  1.47  christos 		/* NB. Please keep in sync with ssh.c:main() */
    699  1.47  christos 		host = percent_expand(options->hostname,
    700  1.47  christos 		    "h", host_arg, (char *)NULL);
    701  1.47  christos 	} else {
    702  1.47  christos 		host = xstrdup(host_arg);
    703  1.47  christos 	}
    704  1.47  christos 	if (gethostname(thishost, sizeof(thishost)) == -1)
    705  1.47  christos 		fatal("gethostname: %s", strerror(errno));
    706  1.47  christos 	jmphost = option_clear_or_none(options->jump_host) ?
    707  1.47  christos 	    "" : options->jump_host;
    708  1.47  christos 	strlcpy(shorthost, thishost, sizeof(shorthost));
    709  1.47  christos 	shorthost[strcspn(thishost, ".")] = '\0';
    710  1.47  christos 	snprintf(portstr, sizeof(portstr), "%d", port);
    711  1.47  christos 	snprintf(uidstr, sizeof(uidstr), "%llu",
    712  1.47  christos 	    (unsigned long long)pw->pw_uid);
    713  1.47  christos 	conn_hash_hex = ssh_connection_hash(thishost, host,
    714  1.47  christos 	    portstr, ruser, jmphost);
    715  1.47  christos 	keyalias = options->host_key_alias ?  options->host_key_alias : host;
    716  1.47  christos 
    717  1.47  christos 	ret = (is_include_path ? percent_dollar_expand : percent_expand)(path,
    718  1.47  christos 	    "C", conn_hash_hex,
    719  1.47  christos 	    "L", shorthost,
    720  1.47  christos 	    "d", pw->pw_dir,
    721  1.47  christos 	    "h", host,
    722  1.47  christos 	    "k", keyalias,
    723  1.47  christos 	    "l", thishost,
    724  1.47  christos 	    "n", original_host,
    725  1.47  christos 	    "p", portstr,
    726  1.47  christos 	    "r", ruser,
    727  1.47  christos 	    "u", pw->pw_name,
    728  1.47  christos 	    "i", uidstr,
    729  1.47  christos 	    "j", jmphost,
    730  1.47  christos 	    (char *)NULL);
    731  1.47  christos 	free(host);
    732  1.47  christos 	free(conn_hash_hex);
    733  1.47  christos 	return ret;
    734  1.47  christos }
    735  1.47  christos 
    736  1.47  christos /*
    737  1.12  christos  * Parse and execute a Match directive.
    738  1.12  christos  */
    739  1.12  christos static int
    740  1.47  christos match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
    741  1.47  christos     struct passwd *pw, const char *host_arg, const char *original_host,
    742  1.49  christos     const char *remote_command, int final_pass, int *want_final_pass,
    743  1.49  christos     const char *filename, int linenum)
    744  1.12  christos {
    745  1.48  christos 	char *arg, *oattrib = NULL, *attrib = NULL, *cmd, *host, *criteria;
    746  1.12  christos 	const char *ruser;
    747  1.47  christos 	int r, this_result, result = 1, attributes = 0, negate;
    748  1.12  christos 
    749  1.12  christos 	/*
    750  1.12  christos 	 * Configuration is likely to be incomplete at this point so we
    751  1.12  christos 	 * must be prepared to use default values.
    752  1.12  christos 	 */
    753  1.12  christos 	ruser = options->user == NULL ? pw->pw_name : options->user;
    754  1.27  christos 	if (final_pass) {
    755  1.18  christos 		host = xstrdup(options->hostname);
    756  1.18  christos 	} else if (options->hostname != NULL) {
    757  1.12  christos 		/* NB. Please keep in sync with ssh.c:main() */
    758  1.12  christos 		host = percent_expand(options->hostname,
    759  1.12  christos 		    "h", host_arg, (char *)NULL);
    760  1.18  christos 	} else {
    761  1.12  christos 		host = xstrdup(host_arg);
    762  1.18  christos 	}
    763  1.12  christos 
    764  1.13  christos 	debug2("checking match for '%s' host %s originally %s",
    765  1.47  christos 	    full_line, host, original_host);
    766  1.48  christos 	while ((attrib = argv_next(acp, avp)) != NULL) {
    767  1.35  christos 		/* Terminate on comment */
    768  1.35  christos 		if (*attrib == '#') {
    769  1.47  christos 			argv_consume(acp);
    770  1.35  christos 			break;
    771  1.35  christos 		}
    772  1.51  christos 		attrib = oattrib = xstrdup(attrib);
    773  1.35  christos 		arg = criteria = NULL;
    774  1.13  christos 		this_result = 1;
    775  1.41  christos 		if ((negate = (attrib[0] == '!')))
    776  1.13  christos 			attrib++;
    777  1.35  christos 		/* Criterion "all" has no argument and must appear alone */
    778  1.12  christos 		if (strcasecmp(attrib, "all") == 0) {
    779  1.47  christos 			if (attributes > 1 ||
    780  1.47  christos 			    ((arg = argv_next(acp, avp)) != NULL &&
    781  1.35  christos 			    *arg != '\0' && *arg != '#')) {
    782  1.13  christos 				error("%.200s line %d: '%s' cannot be combined "
    783  1.13  christos 				    "with other Match attributes",
    784  1.13  christos 				    filename, linenum, oattrib);
    785  1.12  christos 				result = -1;
    786  1.12  christos 				goto out;
    787  1.12  christos 			}
    788  1.35  christos 			if (arg != NULL && *arg == '#')
    789  1.47  christos 				argv_consume(acp); /* consume remaining args */
    790  1.13  christos 			if (result)
    791  1.13  christos 				result = negate ? 0 : 1;
    792  1.12  christos 			goto out;
    793  1.12  christos 		}
    794  1.13  christos 		attributes++;
    795  1.35  christos 		/* criteria "final" and "canonical" have no argument */
    796  1.27  christos 		if (strcasecmp(attrib, "canonical") == 0 ||
    797  1.27  christos 		    strcasecmp(attrib, "final") == 0) {
    798  1.27  christos 			/*
    799  1.50  christos 			 * If the config requests "Match final" without
    800  1.50  christos 			 * negation then remember this so we can perform a
    801  1.50  christos 			 * second pass later.
    802  1.27  christos 			 */
    803  1.27  christos 			if (strcasecmp(attrib, "final") == 0 &&
    804  1.27  christos 			    want_final_pass != NULL)
    805  1.50  christos 				*want_final_pass |= !negate;
    806  1.27  christos 			r = !!final_pass;  /* force bitmask member to boolean */
    807  1.13  christos 			if (r == (negate ? 1 : 0))
    808  1.13  christos 				this_result = result = 0;
    809  1.13  christos 			debug3("%.200s line %d: %smatched '%s'",
    810  1.13  christos 			    filename, linenum,
    811  1.13  christos 			    this_result ? "" : "not ", oattrib);
    812  1.51  christos 			goto next;
    813  1.13  christos 		}
    814  1.48  christos 
    815  1.48  christos 		/* Keep this list in sync with below */
    816  1.48  christos 		if (strprefix(attrib, "host=", 1)  != NULL ||
    817  1.48  christos 		    strprefix(attrib, "originalhost=", 1) != NULL ||
    818  1.48  christos 		    strprefix(attrib, "user=", 1) != NULL ||
    819  1.48  christos 		    strprefix(attrib, "localuser=", 1) != NULL ||
    820  1.48  christos 		    strprefix(attrib, "localnetwork=", 1) != NULL ||
    821  1.49  christos 		    strprefix(attrib, "version=", 1) != NULL ||
    822  1.48  christos 		    strprefix(attrib, "tagged=", 1) != NULL ||
    823  1.49  christos 		    strprefix(attrib, "command=", 1) != NULL ||
    824  1.48  christos 		    strprefix(attrib, "exec=", 1) != NULL) {
    825  1.48  christos 			arg = strchr(attrib, '=');
    826  1.48  christos 			*(arg++) = '\0';
    827  1.49  christos 		} else if ((arg = argv_next(acp, avp)) == NULL) {
    828  1.49  christos 			error("%.200s line %d: missing argument for Match '%s'",
    829  1.49  christos 			    filename, linenum, oattrib);
    830  1.49  christos 			result = -1;
    831  1.49  christos 			goto out;
    832  1.48  christos 		}
    833  1.48  christos 
    834  1.49  christos 		/*
    835  1.49  christos 		 * All other criteria require an argument, though it may
    836  1.49  christos 		 * be the empty string for the "tagged" and "command"
    837  1.49  christos 		 * options.
    838  1.49  christos 		 */
    839  1.49  christos 		if (*arg == '\0' &&
    840  1.49  christos 		    strcasecmp(attrib, "tagged") != 0 &&
    841  1.49  christos 		    strcasecmp(attrib, "command") != 0)
    842  1.49  christos 			arg = NULL;
    843  1.49  christos 		if (arg == NULL || *arg == '#') {
    844  1.12  christos 			error("Missing Match criteria for %s", attrib);
    845  1.12  christos 			result = -1;
    846  1.12  christos 			goto out;
    847  1.12  christos 		}
    848  1.12  christos 		if (strcasecmp(attrib, "host") == 0) {
    849  1.13  christos 			criteria = xstrdup(host);
    850  1.14  christos 			r = match_hostname(host, arg) == 1;
    851  1.13  christos 			if (r == (negate ? 1 : 0))
    852  1.13  christos 				this_result = result = 0;
    853  1.12  christos 		} else if (strcasecmp(attrib, "originalhost") == 0) {
    854  1.13  christos 			criteria = xstrdup(original_host);
    855  1.14  christos 			r = match_hostname(original_host, arg) == 1;
    856  1.13  christos 			if (r == (negate ? 1 : 0))
    857  1.13  christos 				this_result = result = 0;
    858  1.12  christos 		} else if (strcasecmp(attrib, "user") == 0) {
    859  1.13  christos 			criteria = xstrdup(ruser);
    860  1.14  christos 			r = match_pattern_list(ruser, arg, 0) == 1;
    861  1.13  christos 			if (r == (negate ? 1 : 0))
    862  1.13  christos 				this_result = result = 0;
    863  1.12  christos 		} else if (strcasecmp(attrib, "localuser") == 0) {
    864  1.13  christos 			criteria = xstrdup(pw->pw_name);
    865  1.14  christos 			r = match_pattern_list(pw->pw_name, arg, 0) == 1;
    866  1.13  christos 			if (r == (negate ? 1 : 0))
    867  1.13  christos 				this_result = result = 0;
    868  1.42  christos 		} else if (strcasecmp(attrib, "localnetwork") == 0) {
    869  1.42  christos 			if (addr_match_cidr_list(NULL, arg) == -1) {
    870  1.42  christos 				/* Error already printed */
    871  1.42  christos 				result = -1;
    872  1.42  christos 				goto out;
    873  1.42  christos 			}
    874  1.42  christos 			r = check_match_ifaddrs(arg) == 1;
    875  1.42  christos 			if (r == (negate ? 1 : 0))
    876  1.42  christos 				this_result = result = 0;
    877  1.49  christos 		} else if (strcasecmp(attrib, "version") == 0) {
    878  1.49  christos 			criteria = xstrdup(SSH_RELEASE);
    879  1.49  christos 			r = match_pattern_list(SSH_RELEASE, arg, 0) == 1;
    880  1.49  christos 			if (r == (negate ? 1 : 0))
    881  1.49  christos 				this_result = result = 0;
    882  1.42  christos 		} else if (strcasecmp(attrib, "tagged") == 0) {
    883  1.42  christos 			criteria = xstrdup(options->tag == NULL ? "" :
    884  1.42  christos 			    options->tag);
    885  1.49  christos 			/* Special case: empty criteria matches empty arg */
    886  1.49  christos 			r = (*criteria == '\0') ? *arg == '\0' :
    887  1.49  christos 			    match_pattern_list(criteria, arg, 0) == 1;
    888  1.49  christos 			if (r == (negate ? 1 : 0))
    889  1.49  christos 				this_result = result = 0;
    890  1.49  christos 		} else if (strcasecmp(attrib, "command") == 0) {
    891  1.49  christos 			criteria = xstrdup(remote_command == NULL ?
    892  1.49  christos 			    "" : remote_command);
    893  1.49  christos 			/* Special case: empty criteria matches empty arg */
    894  1.49  christos 			r = (*criteria == '\0') ? *arg == '\0' :
    895  1.49  christos 			    match_pattern_list(criteria, arg, 0) == 1;
    896  1.49  christos 			if (r == (negate ? 1 : 0))
    897  1.49  christos 				this_result = result = 0;
    898  1.49  christos 		} else if (strcasecmp(attrib, "sessiontype") == 0) {
    899  1.49  christos 			if (options->session_type == SESSION_TYPE_SUBSYSTEM)
    900  1.49  christos 				criteria = xstrdup("subsystem");
    901  1.49  christos 			else if (options->session_type == SESSION_TYPE_NONE)
    902  1.49  christos 				criteria = xstrdup("none");
    903  1.49  christos 			else if (remote_command != NULL &&
    904  1.49  christos 			    *remote_command != '\0')
    905  1.49  christos 				criteria = xstrdup("exec");
    906  1.49  christos 			else
    907  1.49  christos 				criteria = xstrdup("shell");
    908  1.42  christos 			r = match_pattern_list(criteria, arg, 0) == 1;
    909  1.42  christos 			if (r == (negate ? 1 : 0))
    910  1.42  christos 				this_result = result = 0;
    911  1.12  christos 		} else if (strcasecmp(attrib, "exec") == 0) {
    912  1.47  christos 			if ((cmd = expand_match_exec_or_include_path(arg,
    913  1.47  christos 			    options, pw, host_arg, original_host,
    914  1.47  christos 			    final_pass, 0)) == NULL) {
    915  1.47  christos 				fatal("%.200s line %d: failed to expand match "
    916  1.47  christos 				    "exec '%.100s'", filename, linenum, arg);
    917  1.47  christos 			}
    918  1.12  christos 			if (result != 1) {
    919  1.12  christos 				/* skip execution if prior predicate failed */
    920  1.13  christos 				debug3("%.200s line %d: skipped exec "
    921  1.13  christos 				    "\"%.100s\"", filename, linenum, cmd);
    922  1.13  christos 				free(cmd);
    923  1.51  christos 				goto next;
    924  1.13  christos 			}
    925  1.13  christos 			r = execute_in_shell(cmd);
    926  1.13  christos 			if (r == -1) {
    927  1.13  christos 				fatal("%.200s line %d: match exec "
    928  1.13  christos 				    "'%.100s' error", filename,
    929  1.13  christos 				    linenum, cmd);
    930  1.12  christos 			}
    931  1.13  christos 			criteria = xstrdup(cmd);
    932  1.12  christos 			free(cmd);
    933  1.13  christos 			/* Force exit status to boolean */
    934  1.13  christos 			r = r == 0;
    935  1.13  christos 			if (r == (negate ? 1 : 0))
    936  1.13  christos 				this_result = result = 0;
    937  1.12  christos 		} else {
    938  1.12  christos 			error("Unsupported Match attribute %s", attrib);
    939  1.12  christos 			result = -1;
    940  1.12  christos 			goto out;
    941  1.12  christos 		}
    942  1.42  christos 		debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
    943  1.42  christos 		    filename, linenum, this_result ? "": "not ", oattrib,
    944  1.42  christos 		    criteria == NULL ? "" : " \"",
    945  1.42  christos 		    criteria == NULL ? "" : criteria,
    946  1.42  christos 		    criteria == NULL ? "" : "\"");
    947  1.51  christos  next:
    948  1.13  christos 		free(criteria);
    949  1.48  christos 		free(oattrib);
    950  1.48  christos 		oattrib = attrib = NULL;
    951  1.12  christos 	}
    952  1.12  christos 	if (attributes == 0) {
    953  1.12  christos 		error("One or more attributes required for Match");
    954  1.12  christos 		result = -1;
    955  1.12  christos 		goto out;
    956  1.12  christos 	}
    957  1.13  christos  out:
    958  1.13  christos 	if (result != -1)
    959  1.13  christos 		debug2("match %sfound", result ? "" : "not ");
    960  1.48  christos 	free(oattrib);
    961  1.12  christos 	free(host);
    962  1.12  christos 	return result;
    963  1.12  christos }
    964  1.12  christos 
    965  1.25  christos /* Remove environment variable by pattern */
    966  1.25  christos static void
    967  1.25  christos rm_env(Options *options, const char *arg, const char *filename, int linenum)
    968  1.25  christos {
    969  1.40  christos 	u_int i, j, onum_send_env = options->num_send_env;
    970  1.25  christos 
    971  1.25  christos 	/* Remove an environment variable */
    972  1.25  christos 	for (i = 0; i < options->num_send_env; ) {
    973  1.40  christos 		if (!match_pattern(options->send_env[i], arg + 1)) {
    974  1.25  christos 			i++;
    975  1.25  christos 			continue;
    976  1.25  christos 		}
    977  1.25  christos 		debug3("%s line %d: removing environment %s",
    978  1.40  christos 		    filename, linenum, options->send_env[i]);
    979  1.25  christos 		free(options->send_env[i]);
    980  1.25  christos 		options->send_env[i] = NULL;
    981  1.25  christos 		for (j = i; j < options->num_send_env - 1; j++) {
    982  1.25  christos 			options->send_env[j] = options->send_env[j + 1];
    983  1.25  christos 			options->send_env[j + 1] = NULL;
    984  1.25  christos 		}
    985  1.25  christos 		options->num_send_env--;
    986  1.25  christos 		/* NB. don't increment i */
    987  1.25  christos 	}
    988  1.32  christos 	if (onum_send_env != options->num_send_env) {
    989  1.32  christos 		options->send_env = xrecallocarray(options->send_env,
    990  1.32  christos 		    onum_send_env, options->num_send_env,
    991  1.32  christos 		    sizeof(*options->send_env));
    992  1.32  christos 	}
    993  1.25  christos }
    994  1.25  christos 
    995   1.1  christos /*
    996   1.1  christos  * Returns the number of the token pointed to by cp or oBadOption.
    997   1.1  christos  */
    998   1.1  christos static OpCodes
    999  1.11  christos parse_token(const char *cp, const char *filename, int linenum,
   1000  1.11  christos     const char *ignored_unknown)
   1001   1.1  christos {
   1002  1.11  christos 	int i;
   1003   1.1  christos 
   1004   1.1  christos 	for (i = 0; keywords[i].name; i++)
   1005  1.11  christos 		if (strcmp(cp, keywords[i].name) == 0)
   1006   1.1  christos 			return keywords[i].opcode;
   1007  1.14  christos 	if (ignored_unknown != NULL &&
   1008  1.14  christos 	    match_pattern_list(cp, ignored_unknown, 1) == 1)
   1009  1.11  christos 		return oIgnoredUnknownOption;
   1010   1.1  christos 	error("%s: line %d: Bad configuration option: %s",
   1011   1.1  christos 	    filename, linenum, cp);
   1012   1.1  christos 	return oBadOption;
   1013   1.1  christos }
   1014   1.1  christos 
   1015  1.45  christos static void
   1016  1.45  christos free_canon_cnames(struct allowed_cname *cnames, u_int n)
   1017  1.45  christos {
   1018  1.45  christos 	u_int i;
   1019  1.45  christos 
   1020  1.45  christos 	if (cnames == NULL || n == 0)
   1021  1.45  christos 		return;
   1022  1.45  christos 	for (i = 0; i < n; i++) {
   1023  1.45  christos 		free(cnames[i].source_list);
   1024  1.45  christos 		free(cnames[i].target_list);
   1025  1.45  christos 	}
   1026  1.45  christos 	free(cnames);
   1027  1.45  christos }
   1028  1.45  christos 
   1029  1.12  christos /* Multistate option parsing */
   1030  1.12  christos struct multistate {
   1031  1.12  christos 	const char *key;
   1032  1.12  christos 	int value;
   1033  1.12  christos };
   1034  1.12  christos static const struct multistate multistate_flag[] = {
   1035  1.12  christos 	{ "true",			1 },
   1036  1.12  christos 	{ "false",			0 },
   1037  1.12  christos 	{ "yes",			1 },
   1038  1.12  christos 	{ "no",				0 },
   1039  1.12  christos 	{ NULL, -1 }
   1040  1.12  christos };
   1041  1.12  christos static const struct multistate multistate_yesnoask[] = {
   1042  1.12  christos 	{ "true",			1 },
   1043  1.12  christos 	{ "false",			0 },
   1044  1.12  christos 	{ "yes",			1 },
   1045  1.12  christos 	{ "no",				0 },
   1046  1.12  christos 	{ "ask",			2 },
   1047  1.12  christos 	{ NULL, -1 }
   1048  1.12  christos };
   1049  1.22  christos static const struct multistate multistate_strict_hostkey[] = {
   1050  1.22  christos 	{ "true",			SSH_STRICT_HOSTKEY_YES },
   1051  1.22  christos 	{ "false",			SSH_STRICT_HOSTKEY_OFF },
   1052  1.22  christos 	{ "yes",			SSH_STRICT_HOSTKEY_YES },
   1053  1.22  christos 	{ "no",				SSH_STRICT_HOSTKEY_OFF },
   1054  1.22  christos 	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
   1055  1.22  christos 	{ "off",			SSH_STRICT_HOSTKEY_OFF },
   1056  1.22  christos 	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
   1057  1.22  christos 	{ NULL, -1 }
   1058  1.22  christos };
   1059  1.18  christos static const struct multistate multistate_yesnoaskconfirm[] = {
   1060  1.18  christos 	{ "true",			1 },
   1061  1.18  christos 	{ "false",			0 },
   1062  1.18  christos 	{ "yes",			1 },
   1063  1.18  christos 	{ "no",				0 },
   1064  1.18  christos 	{ "ask",			2 },
   1065  1.18  christos 	{ "confirm",			3 },
   1066  1.18  christos 	{ NULL, -1 }
   1067  1.18  christos };
   1068  1.12  christos static const struct multistate multistate_addressfamily[] = {
   1069  1.12  christos 	{ "inet",			AF_INET },
   1070  1.12  christos 	{ "inet6",			AF_INET6 },
   1071  1.12  christos 	{ "any",			AF_UNSPEC },
   1072  1.12  christos 	{ NULL, -1 }
   1073  1.12  christos };
   1074  1.12  christos static const struct multistate multistate_controlmaster[] = {
   1075  1.12  christos 	{ "true",			SSHCTL_MASTER_YES },
   1076  1.12  christos 	{ "yes",			SSHCTL_MASTER_YES },
   1077  1.12  christos 	{ "false",			SSHCTL_MASTER_NO },
   1078  1.12  christos 	{ "no",				SSHCTL_MASTER_NO },
   1079  1.12  christos 	{ "auto",			SSHCTL_MASTER_AUTO },
   1080  1.12  christos 	{ "ask",			SSHCTL_MASTER_ASK },
   1081  1.12  christos 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
   1082  1.12  christos 	{ NULL, -1 }
   1083  1.12  christos };
   1084  1.12  christos static const struct multistate multistate_tunnel[] = {
   1085  1.12  christos 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
   1086  1.12  christos 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
   1087  1.12  christos 	{ "true",			SSH_TUNMODE_DEFAULT },
   1088  1.12  christos 	{ "yes",			SSH_TUNMODE_DEFAULT },
   1089  1.12  christos 	{ "false",			SSH_TUNMODE_NO },
   1090  1.12  christos 	{ "no",				SSH_TUNMODE_NO },
   1091  1.12  christos 	{ NULL, -1 }
   1092  1.12  christos };
   1093  1.12  christos static const struct multistate multistate_requesttty[] = {
   1094  1.12  christos 	{ "true",			REQUEST_TTY_YES },
   1095  1.12  christos 	{ "yes",			REQUEST_TTY_YES },
   1096  1.12  christos 	{ "false",			REQUEST_TTY_NO },
   1097  1.12  christos 	{ "no",				REQUEST_TTY_NO },
   1098  1.12  christos 	{ "force",			REQUEST_TTY_FORCE },
   1099  1.12  christos 	{ "auto",			REQUEST_TTY_AUTO },
   1100  1.12  christos 	{ NULL, -1 }
   1101  1.12  christos };
   1102  1.35  christos static const struct multistate multistate_sessiontype[] = {
   1103  1.35  christos 	{ "none",			SESSION_TYPE_NONE },
   1104  1.35  christos 	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
   1105  1.35  christos 	{ "default",			SESSION_TYPE_DEFAULT },
   1106  1.35  christos 	{ NULL, -1 }
   1107  1.35  christos };
   1108  1.12  christos static const struct multistate multistate_canonicalizehostname[] = {
   1109  1.12  christos 	{ "true",			SSH_CANONICALISE_YES },
   1110  1.12  christos 	{ "false",			SSH_CANONICALISE_NO },
   1111  1.12  christos 	{ "yes",			SSH_CANONICALISE_YES },
   1112  1.12  christos 	{ "no",				SSH_CANONICALISE_NO },
   1113  1.12  christos 	{ "always",			SSH_CANONICALISE_ALWAYS },
   1114  1.12  christos 	{ NULL, -1 }
   1115  1.12  christos };
   1116  1.38  christos static const struct multistate multistate_pubkey_auth[] = {
   1117  1.38  christos 	{ "true",			SSH_PUBKEY_AUTH_ALL },
   1118  1.38  christos 	{ "false",			SSH_PUBKEY_AUTH_NO },
   1119  1.38  christos 	{ "yes",			SSH_PUBKEY_AUTH_ALL },
   1120  1.38  christos 	{ "no",				SSH_PUBKEY_AUTH_NO },
   1121  1.38  christos 	{ "unbound",			SSH_PUBKEY_AUTH_UNBOUND },
   1122  1.38  christos 	{ "host-bound",			SSH_PUBKEY_AUTH_HBOUND },
   1123  1.38  christos 	{ NULL, -1 }
   1124  1.38  christos };
   1125  1.29  christos static const struct multistate multistate_compression[] = {
   1126  1.29  christos #ifdef WITH_ZLIB
   1127  1.47  christos 	{ "yes",			COMP_DELAYED },
   1128  1.29  christos #endif
   1129  1.29  christos 	{ "no",				COMP_NONE },
   1130  1.29  christos 	{ NULL, -1 }
   1131  1.29  christos };
   1132  1.50  christos /* XXX this will need to be replaced with a bitmask if we add more flags */
   1133  1.50  christos static const struct multistate multistate_warnweakcrypto[] = {
   1134  1.50  christos 	{ "true",			1 },
   1135  1.50  christos 	{ "false",			0 },
   1136  1.50  christos 	{ "yes",			1 },
   1137  1.50  christos 	{ "no",				0 },
   1138  1.50  christos 	{ "no-pq-kex",			0 },
   1139  1.50  christos 	{ NULL, -1 }
   1140  1.50  christos };
   1141  1.12  christos 
   1142  1.32  christos static int
   1143  1.32  christos parse_multistate_value(const char *arg, const char *filename, int linenum,
   1144  1.32  christos     const struct multistate *multistate_ptr)
   1145  1.32  christos {
   1146  1.32  christos 	int i;
   1147  1.32  christos 
   1148  1.33  christos 	if (!arg || *arg == '\0') {
   1149  1.33  christos 		error("%s line %d: missing argument.", filename, linenum);
   1150  1.33  christos 		return -1;
   1151  1.33  christos 	}
   1152  1.32  christos 	for (i = 0; multistate_ptr[i].key != NULL; i++) {
   1153  1.32  christos 		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
   1154  1.32  christos 			return multistate_ptr[i].value;
   1155  1.32  christos 	}
   1156  1.32  christos 	return -1;
   1157  1.32  christos }
   1158  1.32  christos 
   1159   1.1  christos /*
   1160   1.1  christos  * Processes a single option line as used in the configuration files. This
   1161   1.1  christos  * only sets those values that have not already been set.
   1162   1.1  christos  */
   1163   1.1  christos int
   1164  1.12  christos process_config_line(Options *options, struct passwd *pw, const char *host,
   1165  1.49  christos     const char *original_host, const char *remote_command, char *line,
   1166  1.49  christos     const char *filename, int linenum, int *activep, int flags)
   1167   1.1  christos {
   1168  1.19  christos 	return process_config_line_depth(options, pw, host, original_host,
   1169  1.49  christos 	    remote_command, line, filename, linenum, activep, flags, NULL, 0);
   1170  1.19  christos }
   1171  1.19  christos 
   1172  1.19  christos #define WHITESPACE " \t\r\n"
   1173  1.19  christos static int
   1174  1.19  christos process_config_line_depth(Options *options, struct passwd *pw, const char *host,
   1175  1.49  christos     const char *original_host, const char *remote_command, char *line,
   1176  1.49  christos     const char *filename, int linenum, int *activep, int flags,
   1177  1.49  christos     int *want_final_pass, int depth)
   1178  1.19  christos {
   1179  1.38  christos 	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
   1180  1.33  christos 	char **cpptr, ***cppptr, fwdarg[256];
   1181  1.45  christos 	u_int i, *uintptr, max_entries = 0;
   1182  1.19  christos 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
   1183  1.45  christos 	int remotefwd, dynamicfwd, ca_only = 0, found = 0;
   1184   1.1  christos 	LogLevel *log_level_ptr;
   1185  1.22  christos 	SyslogFacility *log_facility_ptr;
   1186  1.11  christos 	long long val64;
   1187   1.1  christos 	size_t len;
   1188  1.12  christos 	struct Forward fwd;
   1189  1.12  christos 	const struct multistate *multistate_ptr;
   1190  1.19  christos 	glob_t gl;
   1191  1.23  christos 	const char *errstr;
   1192  1.35  christos 	char **oav = NULL, **av;
   1193  1.35  christos 	int oac = 0, ac;
   1194  1.35  christos 	int ret = -1;
   1195  1.45  christos 	struct allowed_cname *cnames = NULL;
   1196  1.45  christos 	u_int ncnames = 0;
   1197  1.45  christos 	char **strs = NULL; /* string array arguments; freed implicitly */
   1198  1.45  christos 	u_int nstrs = 0;
   1199  1.12  christos 
   1200  1.12  christos 	if (activep == NULL) { /* We are processing a command line directive */
   1201  1.12  christos 		cmdline = 1;
   1202  1.12  christos 		activep = &cmdline;
   1203  1.12  christos 	}
   1204   1.1  christos 
   1205  1.21  christos 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
   1206  1.14  christos 	if ((len = strlen(line)) == 0)
   1207  1.14  christos 		return 0;
   1208  1.14  christos 	for (len--; len > 0; len--) {
   1209  1.21  christos 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
   1210   1.1  christos 			break;
   1211   1.1  christos 		line[len] = '\0';
   1212   1.1  christos 	}
   1213   1.1  christos 
   1214  1.35  christos 	str = line;
   1215   1.1  christos 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
   1216  1.35  christos 	if ((keyword = strdelim(&str)) == NULL)
   1217   1.1  christos 		return 0;
   1218   1.1  christos 	/* Ignore leading whitespace. */
   1219   1.1  christos 	if (*keyword == '\0')
   1220  1.35  christos 		keyword = strdelim(&str);
   1221   1.1  christos 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
   1222   1.1  christos 		return 0;
   1223  1.11  christos 	/* Match lowercase keyword */
   1224  1.12  christos 	lowercase(keyword);
   1225   1.1  christos 
   1226  1.35  christos 	/* Prepare to parse remainder of line */
   1227  1.35  christos 	if (str != NULL)
   1228  1.35  christos 		str += strspn(str, WHITESPACE);
   1229  1.35  christos 	if (str == NULL || *str == '\0') {
   1230  1.35  christos 		error("%s line %d: no argument after keyword \"%s\"",
   1231  1.35  christos 		    filename, linenum, keyword);
   1232  1.35  christos 		return -1;
   1233  1.35  christos 	}
   1234  1.11  christos 	opcode = parse_token(keyword, filename, linenum,
   1235  1.11  christos 	    options->ignored_unknown);
   1236  1.35  christos 	if (argv_split(str, &oac, &oav, 1) != 0) {
   1237  1.35  christos 		error("%s line %d: invalid quotes", filename, linenum);
   1238  1.35  christos 		return -1;
   1239  1.35  christos 	}
   1240  1.35  christos 	ac = oac;
   1241  1.35  christos 	av = oav;
   1242   1.1  christos 
   1243   1.1  christos 	switch (opcode) {
   1244   1.1  christos 	case oBadOption:
   1245   1.1  christos 		/* don't panic, but count bad options */
   1246  1.35  christos 		goto out;
   1247  1.22  christos 	case oIgnore:
   1248  1.35  christos 		argv_consume(&ac);
   1249  1.35  christos 		break;
   1250  1.11  christos 	case oIgnoredUnknownOption:
   1251  1.11  christos 		debug("%s line %d: Ignored unknown option \"%s\"",
   1252  1.11  christos 		    filename, linenum, keyword);
   1253  1.35  christos 		argv_consume(&ac);
   1254  1.35  christos 		break;
   1255   1.1  christos 	case oConnectTimeout:
   1256   1.1  christos 		intptr = &options->connection_timeout;
   1257   1.1  christos parse_time:
   1258  1.35  christos 		arg = argv_next(&ac, &av);
   1259  1.33  christos 		if (!arg || *arg == '\0') {
   1260  1.33  christos 			error("%s line %d: missing time value.",
   1261   1.1  christos 			    filename, linenum);
   1262  1.35  christos 			goto out;
   1263  1.33  christos 		}
   1264  1.13  christos 		if (strcmp(arg, "none") == 0)
   1265  1.13  christos 			value = -1;
   1266  1.33  christos 		else if ((value = convtime(arg)) == -1) {
   1267  1.33  christos 			error("%s line %d: invalid time value.",
   1268   1.1  christos 			    filename, linenum);
   1269  1.35  christos 			goto out;
   1270  1.33  christos 		}
   1271   1.1  christos 		if (*activep && *intptr == -1)
   1272   1.1  christos 			*intptr = value;
   1273   1.1  christos 		break;
   1274   1.1  christos 
   1275   1.1  christos 	case oForwardAgent:
   1276   1.1  christos 		intptr = &options->forward_agent;
   1277  1.29  christos 
   1278  1.35  christos 		arg = argv_next(&ac, &av);
   1279  1.33  christos 		if (!arg || *arg == '\0') {
   1280  1.33  christos 			error("%s line %d: missing argument.",
   1281  1.29  christos 			    filename, linenum);
   1282  1.35  christos 			goto out;
   1283  1.33  christos 		}
   1284  1.29  christos 
   1285  1.29  christos 		value = -1;
   1286  1.29  christos 		multistate_ptr = multistate_flag;
   1287  1.29  christos 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
   1288  1.29  christos 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
   1289  1.29  christos 				value = multistate_ptr[i].value;
   1290  1.29  christos 				break;
   1291  1.29  christos 			}
   1292  1.29  christos 		}
   1293  1.29  christos 		if (value != -1) {
   1294  1.29  christos 			if (*activep && *intptr == -1)
   1295  1.29  christos 				*intptr = value;
   1296  1.29  christos 			break;
   1297  1.29  christos 		}
   1298  1.29  christos 		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
   1299  1.29  christos 		if (*activep && *intptr == -1)
   1300  1.29  christos 			*intptr = 1;
   1301  1.29  christos 
   1302  1.29  christos 		charptr = &options->forward_agent_sock_path;
   1303  1.29  christos 		goto parse_agent_path;
   1304  1.29  christos 
   1305  1.29  christos 	case oForwardX11:
   1306  1.29  christos 		intptr = &options->forward_x11;
   1307  1.12  christos  parse_flag:
   1308  1.12  christos 		multistate_ptr = multistate_flag;
   1309  1.12  christos  parse_multistate:
   1310  1.35  christos 		arg = argv_next(&ac, &av);
   1311  1.32  christos 		if ((value = parse_multistate_value(arg, filename, linenum,
   1312  1.34  christos 		    multistate_ptr)) == -1) {
   1313  1.33  christos 			error("%s line %d: unsupported option \"%s\".",
   1314  1.12  christos 			    filename, linenum, arg);
   1315  1.35  christos 			goto out;
   1316  1.32  christos 		}
   1317   1.1  christos 		if (*activep && *intptr == -1)
   1318   1.1  christos 			*intptr = value;
   1319   1.1  christos 		break;
   1320   1.1  christos 
   1321   1.1  christos 	case oForwardX11Trusted:
   1322   1.1  christos 		intptr = &options->forward_x11_trusted;
   1323   1.1  christos 		goto parse_flag;
   1324  1.13  christos 
   1325   1.4      adam 	case oForwardX11Timeout:
   1326   1.4      adam 		intptr = &options->forward_x11_timeout;
   1327   1.4      adam 		goto parse_time;
   1328   1.1  christos 
   1329   1.1  christos 	case oGatewayPorts:
   1330  1.12  christos 		intptr = &options->fwd_opts.gateway_ports;
   1331   1.1  christos 		goto parse_flag;
   1332   1.1  christos 
   1333   1.1  christos 	case oExitOnForwardFailure:
   1334   1.1  christos 		intptr = &options->exit_on_forward_failure;
   1335   1.1  christos 		goto parse_flag;
   1336   1.1  christos 
   1337   1.1  christos 	case oPasswordAuthentication:
   1338   1.1  christos 		intptr = &options->password_authentication;
   1339   1.1  christos 		goto parse_flag;
   1340   1.1  christos 
   1341   1.1  christos 	case oKbdInteractiveAuthentication:
   1342   1.1  christos 		intptr = &options->kbd_interactive_authentication;
   1343   1.1  christos 		goto parse_flag;
   1344   1.1  christos 
   1345   1.1  christos 	case oKbdInteractiveDevices:
   1346   1.1  christos 		charptr = &options->kbd_interactive_devices;
   1347   1.1  christos 		goto parse_string;
   1348   1.1  christos 
   1349   1.1  christos 	case oPubkeyAuthentication:
   1350  1.38  christos 		multistate_ptr = multistate_pubkey_auth;
   1351   1.1  christos 		intptr = &options->pubkey_authentication;
   1352  1.38  christos 		goto parse_multistate;
   1353   1.1  christos 
   1354   1.1  christos 	case oHostbasedAuthentication:
   1355   1.1  christos 		intptr = &options->hostbased_authentication;
   1356   1.1  christos 		goto parse_flag;
   1357   1.1  christos 
   1358   1.2  christos #if defined(KRB4) || defined(KRB5)
   1359   1.2  christos 	case oKerberosAuthentication:
   1360   1.2  christos 		intptr = &options->kerberos_authentication;
   1361   1.2  christos 		goto parse_flag;
   1362   1.2  christos #endif
   1363   1.2  christos #if defined(AFS) || defined(KRB5)
   1364   1.2  christos 	case oKerberosTgtPassing:
   1365   1.2  christos 		intptr = &options->kerberos_tgt_passing;
   1366   1.2  christos 		goto parse_flag;
   1367   1.2  christos #endif
   1368   1.2  christos 
   1369   1.1  christos 	case oGssAuthentication:
   1370   1.1  christos 		intptr = &options->gss_authentication;
   1371   1.1  christos 		goto parse_flag;
   1372   1.1  christos 
   1373   1.2  christos #ifdef AFS
   1374   1.2  christos 	case oAFSTokenPassing:
   1375   1.2  christos 		intptr = &options->afs_token_passing;
   1376   1.2  christos  		goto parse_flag;
   1377   1.2  christos #endif
   1378   1.2  christos 
   1379   1.1  christos 	case oGssDelegateCreds:
   1380   1.1  christos 		intptr = &options->gss_deleg_creds;
   1381   1.1  christos 		goto parse_flag;
   1382   1.1  christos 
   1383   1.1  christos 	case oBatchMode:
   1384   1.1  christos 		intptr = &options->batch_mode;
   1385   1.1  christos 		goto parse_flag;
   1386   1.1  christos 
   1387   1.1  christos 	case oCheckHostIP:
   1388   1.1  christos 		intptr = &options->check_host_ip;
   1389   1.1  christos 		goto parse_flag;
   1390   1.1  christos 
   1391   1.2  christos 	case oNoneEnabled:
   1392   1.2  christos 		intptr = &options->none_enabled;
   1393   1.2  christos 		goto parse_flag;
   1394   1.2  christos 
   1395   1.2  christos 	/* we check to see if the command comes from the */
   1396   1.2  christos 	/* command line or not. If it does then enable it */
   1397   1.2  christos 	/* otherwise fail. NONE should never be a default configuration */
   1398   1.2  christos 	case oNoneSwitch:
   1399   1.2  christos 		if(strcmp(filename,"command-line")==0)
   1400   1.2  christos 		{
   1401   1.2  christos 		    intptr = &options->none_switch;
   1402   1.2  christos 		    goto parse_flag;
   1403   1.2  christos 		} else {
   1404   1.2  christos 		    error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
   1405   1.2  christos 		    error("Continuing...");
   1406   1.2  christos 		    debug("NoneSwitch directive found in %.200s.", filename);
   1407   1.2  christos 		    return 0;
   1408   1.2  christos 	        }
   1409   1.2  christos 
   1410   1.2  christos 	case oHPNDisabled:
   1411   1.2  christos 		intptr = &options->hpn_disabled;
   1412   1.2  christos 		goto parse_flag;
   1413   1.2  christos 
   1414   1.2  christos 	case oHPNBufferSize:
   1415   1.2  christos 		intptr = &options->hpn_buffer_size;
   1416   1.2  christos 		goto parse_int;
   1417   1.2  christos 
   1418   1.2  christos 	case oTcpRcvBufPoll:
   1419   1.2  christos 		intptr = &options->tcp_rcv_buf_poll;
   1420   1.2  christos 		goto parse_flag;
   1421   1.2  christos 
   1422   1.1  christos 	case oVerifyHostKeyDNS:
   1423   1.1  christos 		intptr = &options->verify_host_key_dns;
   1424  1.12  christos 		multistate_ptr = multistate_yesnoask;
   1425  1.12  christos 		goto parse_multistate;
   1426   1.1  christos 
   1427   1.1  christos 	case oStrictHostKeyChecking:
   1428   1.1  christos 		intptr = &options->strict_host_key_checking;
   1429  1.22  christos 		multistate_ptr = multistate_strict_hostkey;
   1430  1.12  christos 		goto parse_multistate;
   1431   1.1  christos 
   1432   1.1  christos 	case oCompression:
   1433   1.1  christos 		intptr = &options->compression;
   1434  1.29  christos 		multistate_ptr = multistate_compression;
   1435  1.29  christos 		goto parse_multistate;
   1436   1.1  christos 
   1437   1.1  christos 	case oTCPKeepAlive:
   1438   1.1  christos 		intptr = &options->tcp_keep_alive;
   1439   1.1  christos 		goto parse_flag;
   1440   1.1  christos 
   1441   1.1  christos 	case oNoHostAuthenticationForLocalhost:
   1442   1.1  christos 		intptr = &options->no_host_authentication_for_localhost;
   1443   1.1  christos 		goto parse_flag;
   1444   1.1  christos 
   1445   1.1  christos 	case oNumberOfPasswordPrompts:
   1446   1.1  christos 		intptr = &options->number_of_password_prompts;
   1447   1.1  christos 		goto parse_int;
   1448   1.1  christos 
   1449   1.1  christos 	case oRekeyLimit:
   1450  1.35  christos 		arg = argv_next(&ac, &av);
   1451  1.33  christos 		if (!arg || *arg == '\0') {
   1452  1.33  christos 			error("%.200s line %d: Missing argument.", filename,
   1453  1.11  christos 			    linenum);
   1454  1.35  christos 			goto out;
   1455  1.33  christos 		}
   1456  1.11  christos 		if (strcmp(arg, "default") == 0) {
   1457  1.11  christos 			val64 = 0;
   1458  1.11  christos 		} else {
   1459  1.33  christos 			if (scan_scaled(arg, &val64) == -1) {
   1460  1.33  christos 				error("%.200s line %d: Bad number '%s': %s",
   1461  1.11  christos 				    filename, linenum, arg, strerror(errno));
   1462  1.35  christos 				goto out;
   1463  1.33  christos 			}
   1464  1.33  christos 			if (val64 != 0 && val64 < 16) {
   1465  1.33  christos 				error("%.200s line %d: RekeyLimit too small",
   1466  1.11  christos 				    filename, linenum);
   1467  1.35  christos 				goto out;
   1468  1.33  christos 			}
   1469   1.1  christos 		}
   1470   1.1  christos 		if (*activep && options->rekey_limit == -1)
   1471  1.18  christos 			options->rekey_limit = val64;
   1472  1.35  christos 		if (ac != 0) { /* optional rekey interval present */
   1473  1.35  christos 			if (strcmp(av[0], "none") == 0) {
   1474  1.35  christos 				(void)argv_next(&ac, &av);	/* discard */
   1475  1.11  christos 				break;
   1476  1.11  christos 			}
   1477  1.11  christos 			intptr = &options->rekey_interval;
   1478  1.11  christos 			goto parse_time;
   1479  1.11  christos 		}
   1480   1.1  christos 		break;
   1481   1.1  christos 
   1482   1.1  christos 	case oIdentityFile:
   1483  1.35  christos 		arg = argv_next(&ac, &av);
   1484  1.33  christos 		if (!arg || *arg == '\0') {
   1485  1.33  christos 			error("%.200s line %d: Missing argument.",
   1486  1.33  christos 			    filename, linenum);
   1487  1.35  christos 			goto out;
   1488  1.33  christos 		}
   1489   1.1  christos 		if (*activep) {
   1490   1.1  christos 			intptr = &options->num_identity_files;
   1491  1.33  christos 			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
   1492  1.33  christos 				error("%.200s line %d: Too many identity files "
   1493  1.33  christos 				    "specified (max %d).", filename, linenum,
   1494  1.33  christos 				    SSH_MAX_IDENTITY_FILES);
   1495  1.35  christos 				goto out;
   1496  1.33  christos 			}
   1497  1.13  christos 			add_identity_file(options, NULL,
   1498  1.13  christos 			    arg, flags & SSHCONF_USERCONF);
   1499   1.1  christos 		}
   1500   1.1  christos 		break;
   1501   1.1  christos 
   1502  1.18  christos 	case oCertificateFile:
   1503  1.35  christos 		arg = argv_next(&ac, &av);
   1504  1.33  christos 		if (!arg || *arg == '\0') {
   1505  1.33  christos 			error("%.200s line %d: Missing argument.",
   1506  1.18  christos 			    filename, linenum);
   1507  1.35  christos 			goto out;
   1508  1.33  christos 		}
   1509  1.18  christos 		if (*activep) {
   1510  1.18  christos 			intptr = &options->num_certificate_files;
   1511  1.18  christos 			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
   1512  1.33  christos 				error("%.200s line %d: Too many certificate "
   1513  1.18  christos 				    "files specified (max %d).",
   1514  1.18  christos 				    filename, linenum,
   1515  1.18  christos 				    SSH_MAX_CERTIFICATE_FILES);
   1516  1.35  christos 				goto out;
   1517  1.18  christos 			}
   1518  1.18  christos 			add_certificate_file(options, arg,
   1519  1.18  christos 			    flags & SSHCONF_USERCONF);
   1520  1.18  christos 		}
   1521  1.18  christos 		break;
   1522  1.18  christos 
   1523   1.1  christos 	case oXAuthLocation:
   1524   1.1  christos 		charptr=&options->xauth_location;
   1525   1.1  christos 		goto parse_string;
   1526   1.1  christos 
   1527   1.1  christos 	case oUser:
   1528   1.1  christos 		charptr = &options->user;
   1529   1.1  christos parse_string:
   1530  1.35  christos 		arg = argv_next(&ac, &av);
   1531  1.33  christos 		if (!arg || *arg == '\0') {
   1532  1.33  christos 			error("%.200s line %d: Missing argument.",
   1533   1.6  christos 			    filename, linenum);
   1534  1.35  christos 			goto out;
   1535  1.33  christos 		}
   1536   1.1  christos 		if (*activep && *charptr == NULL)
   1537   1.1  christos 			*charptr = xstrdup(arg);
   1538   1.1  christos 		break;
   1539   1.1  christos 
   1540   1.1  christos 	case oGlobalKnownHostsFile:
   1541   1.6  christos 		cpptr = (char **)&options->system_hostfiles;
   1542   1.6  christos 		uintptr = &options->num_system_hostfiles;
   1543   1.6  christos 		max_entries = SSH_MAX_HOSTS_FILES;
   1544   1.6  christos parse_char_array:
   1545  1.35  christos 		i = 0;
   1546  1.35  christos 		value = *uintptr == 0; /* was array empty when we started? */
   1547  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   1548  1.35  christos 			if (*arg == '\0') {
   1549  1.35  christos 				error("%s line %d: keyword %s empty argument",
   1550  1.35  christos 				    filename, linenum, keyword);
   1551  1.35  christos 				goto out;
   1552  1.35  christos 			}
   1553  1.35  christos 			/* Allow "none" only in first position */
   1554  1.35  christos 			if (strcasecmp(arg, "none") == 0) {
   1555  1.35  christos 				if (i > 0 || ac > 0) {
   1556  1.35  christos 					error("%s line %d: keyword %s \"none\" "
   1557  1.35  christos 					    "argument must appear alone.",
   1558  1.35  christos 					    filename, linenum, keyword);
   1559  1.35  christos 					goto out;
   1560  1.35  christos 				}
   1561  1.35  christos 			}
   1562  1.35  christos 			i++;
   1563  1.35  christos 			if (*activep && value) {
   1564  1.33  christos 				if ((*uintptr) >= max_entries) {
   1565  1.35  christos 					error("%s line %d: too many %s "
   1566  1.35  christos 					    "entries.", filename, linenum,
   1567  1.35  christos 					    keyword);
   1568  1.35  christos 					goto out;
   1569  1.33  christos 				}
   1570   1.6  christos 				cpptr[(*uintptr)++] = xstrdup(arg);
   1571   1.6  christos 			}
   1572   1.6  christos 		}
   1573  1.35  christos 		break;
   1574   1.1  christos 
   1575   1.1  christos 	case oUserKnownHostsFile:
   1576   1.6  christos 		cpptr = (char **)&options->user_hostfiles;
   1577   1.6  christos 		uintptr = &options->num_user_hostfiles;
   1578   1.6  christos 		max_entries = SSH_MAX_HOSTS_FILES;
   1579   1.6  christos 		goto parse_char_array;
   1580   1.1  christos 
   1581  1.28  christos 	case oHostname:
   1582   1.1  christos 		charptr = &options->hostname;
   1583   1.1  christos 		goto parse_string;
   1584   1.1  christos 
   1585  1.42  christos 	case oTag:
   1586  1.42  christos 		charptr = &options->tag;
   1587  1.42  christos 		goto parse_string;
   1588  1.42  christos 
   1589   1.1  christos 	case oHostKeyAlias:
   1590   1.1  christos 		charptr = &options->host_key_alias;
   1591   1.1  christos 		goto parse_string;
   1592   1.1  christos 
   1593   1.1  christos 	case oPreferredAuthentications:
   1594   1.1  christos 		charptr = &options->preferred_authentications;
   1595   1.1  christos 		goto parse_string;
   1596   1.1  christos 
   1597   1.1  christos 	case oBindAddress:
   1598   1.1  christos 		charptr = &options->bind_address;
   1599   1.1  christos 		goto parse_string;
   1600   1.1  christos 
   1601  1.23  christos 	case oBindInterface:
   1602  1.23  christos 		charptr = &options->bind_interface;
   1603  1.23  christos 		goto parse_string;
   1604  1.23  christos 
   1605  1.43        ws 	case oIPv6PreferTemporary:
   1606  1.43        ws 		intptr = &options->ipv6_prefer_temporary;
   1607  1.43        ws 		goto parse_flag;
   1608  1.43        ws 
   1609   1.4      adam 	case oPKCS11Provider:
   1610   1.4      adam 		charptr = &options->pkcs11_provider;
   1611   1.1  christos 		goto parse_string;
   1612   1.1  christos 
   1613  1.29  christos 	case oSecurityKeyProvider:
   1614  1.29  christos 		charptr = &options->sk_provider;
   1615  1.29  christos 		goto parse_string;
   1616  1.29  christos 
   1617  1.33  christos 	case oKnownHostsCommand:
   1618  1.33  christos 		charptr = &options->known_hosts_command;
   1619  1.33  christos 		goto parse_command;
   1620  1.33  christos 
   1621   1.1  christos 	case oProxyCommand:
   1622   1.1  christos 		charptr = &options->proxy_command;
   1623   1.1  christos parse_command:
   1624  1.35  christos 		if (str == NULL) {
   1625  1.33  christos 			error("%.200s line %d: Missing argument.",
   1626  1.33  christos 			    filename, linenum);
   1627  1.35  christos 			goto out;
   1628  1.33  christos 		}
   1629  1.35  christos 		len = strspn(str, WHITESPACE "=");
   1630   1.1  christos 		if (*activep && *charptr == NULL)
   1631  1.35  christos 			*charptr = xstrdup(str + len);
   1632  1.35  christos 		argv_consume(&ac);
   1633  1.35  christos 		break;
   1634   1.1  christos 
   1635  1.19  christos 	case oProxyJump:
   1636  1.35  christos 		if (str == NULL) {
   1637  1.33  christos 			error("%.200s line %d: Missing argument.",
   1638  1.19  christos 			    filename, linenum);
   1639  1.35  christos 			goto out;
   1640  1.19  christos 		}
   1641  1.35  christos 		len = strspn(str, WHITESPACE "=");
   1642  1.35  christos 		/* XXX use argv? */
   1643  1.51  christos 		if (parse_jump(str + len, options, cmdline, *activep) == -1) {
   1644  1.33  christos 			error("%.200s line %d: Invalid ProxyJump \"%s\"",
   1645  1.35  christos 			    filename, linenum, str + len);
   1646  1.35  christos 			goto out;
   1647  1.19  christos 		}
   1648  1.35  christos 		argv_consume(&ac);
   1649  1.35  christos 		break;
   1650  1.19  christos 
   1651   1.1  christos 	case oPort:
   1652  1.35  christos 		arg = argv_next(&ac, &av);
   1653  1.33  christos 		if (!arg || *arg == '\0') {
   1654  1.33  christos 			error("%.200s line %d: Missing argument.",
   1655  1.27  christos 			    filename, linenum);
   1656  1.35  christos 			goto out;
   1657  1.33  christos 		}
   1658  1.27  christos 		value = a2port(arg);
   1659  1.33  christos 		if (value <= 0) {
   1660  1.33  christos 			error("%.200s line %d: Bad port '%s'.",
   1661  1.27  christos 			    filename, linenum, arg);
   1662  1.35  christos 			goto out;
   1663  1.33  christos 		}
   1664  1.27  christos 		if (*activep && options->port == -1)
   1665  1.27  christos 			options->port = value;
   1666  1.27  christos 		break;
   1667  1.27  christos 
   1668  1.27  christos 	case oConnectionAttempts:
   1669  1.27  christos 		intptr = &options->connection_attempts;
   1670   1.1  christos parse_int:
   1671  1.35  christos 		arg = argv_next(&ac, &av);
   1672  1.33  christos 		if ((errstr = atoi_err(arg, &value)) != NULL) {
   1673  1.33  christos 			error("%s line %d: integer value %s.",
   1674  1.23  christos 			    filename, linenum, errstr);
   1675  1.35  christos 			goto out;
   1676  1.33  christos 		}
   1677   1.1  christos 		if (*activep && *intptr == -1)
   1678   1.1  christos 			*intptr = value;
   1679   1.1  christos 		break;
   1680   1.1  christos 
   1681   1.2  christos 	case oTcpRcvBuf:
   1682   1.2  christos 		intptr = &options->tcp_rcv_buf;
   1683   1.2  christos 		goto parse_int;
   1684   1.2  christos 
   1685   1.1  christos 	case oCiphers:
   1686  1.35  christos 		arg = argv_next(&ac, &av);
   1687  1.33  christos 		if (!arg || *arg == '\0') {
   1688  1.33  christos 			error("%.200s line %d: Missing argument.",
   1689  1.33  christos 			    filename, linenum);
   1690  1.35  christos 			goto out;
   1691  1.33  christos 		}
   1692  1.28  christos 		if (*arg != '-' &&
   1693  1.33  christos 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
   1694  1.33  christos 			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
   1695   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1696  1.35  christos 			goto out;
   1697  1.33  christos 		}
   1698   1.1  christos 		if (*activep && options->ciphers == NULL)
   1699   1.1  christos 			options->ciphers = xstrdup(arg);
   1700   1.1  christos 		break;
   1701   1.1  christos 
   1702   1.1  christos 	case oMacs:
   1703  1.35  christos 		arg = argv_next(&ac, &av);
   1704  1.33  christos 		if (!arg || *arg == '\0') {
   1705  1.33  christos 			error("%.200s line %d: Missing argument.",
   1706  1.33  christos 			    filename, linenum);
   1707  1.35  christos 			goto out;
   1708  1.33  christos 		}
   1709  1.28  christos 		if (*arg != '-' &&
   1710  1.33  christos 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
   1711  1.33  christos 			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
   1712   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1713  1.35  christos 			goto out;
   1714  1.33  christos 		}
   1715   1.1  christos 		if (*activep && options->macs == NULL)
   1716   1.1  christos 			options->macs = xstrdup(arg);
   1717   1.1  christos 		break;
   1718   1.1  christos 
   1719   1.5  christos 	case oKexAlgorithms:
   1720  1.35  christos 		arg = argv_next(&ac, &av);
   1721  1.33  christos 		if (!arg || *arg == '\0') {
   1722  1.33  christos 			error("%.200s line %d: Missing argument.",
   1723   1.5  christos 			    filename, linenum);
   1724  1.35  christos 			goto out;
   1725  1.33  christos 		}
   1726  1.21  christos 		if (*arg != '-' &&
   1727  1.28  christos 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
   1728  1.33  christos 		    arg + 1 : arg)) {
   1729  1.33  christos 			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
   1730   1.5  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1731  1.35  christos 			goto out;
   1732  1.33  christos 		}
   1733   1.5  christos 		if (*activep && options->kex_algorithms == NULL)
   1734   1.5  christos 			options->kex_algorithms = xstrdup(arg);
   1735   1.5  christos 		break;
   1736   1.5  christos 
   1737   1.1  christos 	case oHostKeyAlgorithms:
   1738  1.16  christos 		charptr = &options->hostkeyalgorithms;
   1739  1.42  christos 		ca_only = 0;
   1740  1.33  christos parse_pubkey_algos:
   1741  1.35  christos 		arg = argv_next(&ac, &av);
   1742  1.33  christos 		if (!arg || *arg == '\0') {
   1743  1.33  christos 			error("%.200s line %d: Missing argument.",
   1744  1.16  christos 			    filename, linenum);
   1745  1.35  christos 			goto out;
   1746  1.33  christos 		}
   1747  1.21  christos 		if (*arg != '-' &&
   1748  1.28  christos 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
   1749  1.42  christos 		    arg + 1 : arg, 1, ca_only)) {
   1750  1.33  christos 			error("%s line %d: Bad key types '%s'.",
   1751  1.33  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1752  1.35  christos 			goto out;
   1753  1.33  christos 		}
   1754  1.16  christos 		if (*activep && *charptr == NULL)
   1755  1.16  christos 			*charptr = xstrdup(arg);
   1756   1.1  christos 		break;
   1757   1.1  christos 
   1758  1.27  christos 	case oCASignatureAlgorithms:
   1759  1.27  christos 		charptr = &options->ca_sign_algorithms;
   1760  1.42  christos 		ca_only = 1;
   1761  1.33  christos 		goto parse_pubkey_algos;
   1762  1.27  christos 
   1763   1.1  christos 	case oLogLevel:
   1764   1.1  christos 		log_level_ptr = &options->log_level;
   1765  1.35  christos 		arg = argv_next(&ac, &av);
   1766   1.1  christos 		value = log_level_number(arg);
   1767  1.33  christos 		if (value == SYSLOG_LEVEL_NOT_SET) {
   1768  1.33  christos 			error("%.200s line %d: unsupported log level '%s'",
   1769   1.1  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1770  1.35  christos 			goto out;
   1771  1.33  christos 		}
   1772   1.1  christos 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
   1773   1.1  christos 			*log_level_ptr = (LogLevel) value;
   1774   1.1  christos 		break;
   1775   1.1  christos 
   1776  1.22  christos 	case oLogFacility:
   1777  1.22  christos 		log_facility_ptr = &options->log_facility;
   1778  1.35  christos 		arg = argv_next(&ac, &av);
   1779  1.22  christos 		value = log_facility_number(arg);
   1780  1.33  christos 		if (value == SYSLOG_FACILITY_NOT_SET) {
   1781  1.33  christos 			error("%.200s line %d: unsupported log facility '%s'",
   1782  1.22  christos 			    filename, linenum, arg ? arg : "<NONE>");
   1783  1.35  christos 			goto out;
   1784  1.33  christos 		}
   1785  1.22  christos 		if (*log_facility_ptr == -1)
   1786  1.22  christos 			*log_facility_ptr = (SyslogFacility) value;
   1787  1.22  christos 		break;
   1788  1.22  christos 
   1789  1.33  christos 	case oLogVerbose:
   1790  1.33  christos 		cppptr = &options->log_verbose;
   1791  1.33  christos 		uintptr = &options->num_log_verbose;
   1792  1.35  christos 		i = 0;
   1793  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   1794  1.35  christos 			if (*arg == '\0') {
   1795  1.35  christos 				error("%s line %d: keyword %s empty argument",
   1796  1.35  christos 				    filename, linenum, keyword);
   1797  1.35  christos 				goto out;
   1798  1.35  christos 			}
   1799  1.35  christos 			/* Allow "none" only in first position */
   1800  1.35  christos 			if (strcasecmp(arg, "none") == 0) {
   1801  1.35  christos 				if (i > 0 || ac > 0) {
   1802  1.35  christos 					error("%s line %d: keyword %s \"none\" "
   1803  1.35  christos 					    "argument must appear alone.",
   1804  1.35  christos 					    filename, linenum, keyword);
   1805  1.35  christos 					goto out;
   1806  1.35  christos 				}
   1807  1.35  christos 			}
   1808  1.35  christos 			i++;
   1809  1.35  christos 			if (*activep && *uintptr == 0) {
   1810  1.33  christos 				*cppptr = xrecallocarray(*cppptr, *uintptr,
   1811  1.33  christos 				    *uintptr + 1, sizeof(**cppptr));
   1812  1.33  christos 				(*cppptr)[(*uintptr)++] = xstrdup(arg);
   1813  1.33  christos 			}
   1814  1.33  christos 		}
   1815  1.35  christos 		break;
   1816  1.33  christos 
   1817   1.1  christos 	case oLocalForward:
   1818   1.1  christos 	case oRemoteForward:
   1819   1.1  christos 	case oDynamicForward:
   1820  1.35  christos 		arg = argv_next(&ac, &av);
   1821  1.33  christos 		if (!arg || *arg == '\0') {
   1822  1.33  christos 			error("%.200s line %d: Missing argument.",
   1823   1.1  christos 			    filename, linenum);
   1824  1.35  christos 			goto out;
   1825  1.33  christos 		}
   1826   1.1  christos 
   1827  1.22  christos 		remotefwd = (opcode == oRemoteForward);
   1828  1.22  christos 		dynamicfwd = (opcode == oDynamicForward);
   1829  1.22  christos 
   1830  1.22  christos 		if (!dynamicfwd) {
   1831  1.35  christos 			arg2 = argv_next(&ac, &av);
   1832  1.22  christos 			if (arg2 == NULL || *arg2 == '\0') {
   1833  1.22  christos 				if (remotefwd)
   1834  1.22  christos 					dynamicfwd = 1;
   1835  1.33  christos 				else {
   1836  1.33  christos 					error("%.200s line %d: Missing target "
   1837  1.22  christos 					    "argument.", filename, linenum);
   1838  1.35  christos 					goto out;
   1839  1.33  christos 				}
   1840  1.22  christos 			} else {
   1841  1.22  christos 				/* construct a string for parse_forward */
   1842  1.22  christos 				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
   1843  1.22  christos 				    arg2);
   1844  1.22  christos 			}
   1845  1.22  christos 		}
   1846  1.22  christos 		if (dynamicfwd)
   1847   1.1  christos 			strlcpy(fwdarg, arg, sizeof(fwdarg));
   1848   1.1  christos 
   1849  1.33  christos 		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
   1850  1.33  christos 			error("%.200s line %d: Bad forwarding specification.",
   1851   1.1  christos 			    filename, linenum);
   1852  1.35  christos 			goto out;
   1853  1.33  christos 		}
   1854   1.1  christos 
   1855   1.1  christos 		if (*activep) {
   1856  1.22  christos 			if (remotefwd) {
   1857  1.22  christos 				add_remote_forward(options, &fwd);
   1858  1.22  christos 			} else {
   1859   1.1  christos 				add_local_forward(options, &fwd);
   1860  1.22  christos 			}
   1861   1.1  christos 		}
   1862   1.1  christos 		break;
   1863   1.1  christos 
   1864  1.33  christos 	case oPermitRemoteOpen:
   1865  1.33  christos 		uintptr = &options->num_permitted_remote_opens;
   1866  1.33  christos 		cppptr = &options->permitted_remote_opens;
   1867  1.45  christos 		found = *uintptr == 0;
   1868  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   1869  1.33  christos 			arg2 = xstrdup(arg);
   1870  1.41  christos 			/* Allow any/none only in first position */
   1871  1.41  christos 			if (strcasecmp(arg, "none") == 0 ||
   1872  1.41  christos 			    strcasecmp(arg, "any") == 0) {
   1873  1.45  christos 				if (nstrs > 0 || ac > 0) {
   1874  1.41  christos 					error("%s line %d: keyword %s \"%s\" "
   1875  1.41  christos 					    "argument must appear alone.",
   1876  1.41  christos 					    filename, linenum, keyword, arg);
   1877  1.42  christos 					free(arg2);
   1878  1.41  christos 					goto out;
   1879  1.41  christos 				}
   1880  1.41  christos 			} else {
   1881  1.41  christos 				p = hpdelim(&arg);
   1882  1.41  christos 				if (p == NULL) {
   1883  1.41  christos 					fatal("%s line %d: missing host in %s",
   1884  1.41  christos 					    filename, linenum,
   1885  1.41  christos 					    lookup_opcode_name(opcode));
   1886  1.41  christos 				}
   1887  1.41  christos 				p = cleanhostname(p);
   1888  1.41  christos 				/*
   1889  1.41  christos 				 * don't want to use permitopen_port to avoid
   1890  1.41  christos 				 * dependency on channels.[ch] here.
   1891  1.41  christos 				 */
   1892  1.41  christos 				if (arg == NULL || (strcmp(arg, "*") != 0 &&
   1893  1.41  christos 				    a2port(arg) <= 0)) {
   1894  1.41  christos 					fatal("%s line %d: bad port number "
   1895  1.41  christos 					    "in %s", filename, linenum,
   1896  1.41  christos 					    lookup_opcode_name(opcode));
   1897  1.41  christos 				}
   1898  1.33  christos 			}
   1899  1.45  christos 			opt_array_append(filename, linenum,
   1900  1.45  christos 			    lookup_opcode_name(opcode),
   1901  1.45  christos 			    &strs, &nstrs, arg2);
   1902  1.33  christos 			free(arg2);
   1903  1.33  christos 		}
   1904  1.45  christos 		if (nstrs == 0)
   1905  1.41  christos 			fatal("%s line %d: missing %s specification",
   1906  1.41  christos 			    filename, linenum, lookup_opcode_name(opcode));
   1907  1.45  christos 		if (found && *activep) {
   1908  1.45  christos 			*cppptr = strs;
   1909  1.45  christos 			*uintptr = nstrs;
   1910  1.45  christos 			strs = NULL; /* transferred */
   1911  1.45  christos 			nstrs = 0;
   1912  1.45  christos 		}
   1913  1.33  christos 		break;
   1914  1.33  christos 
   1915   1.1  christos 	case oClearAllForwardings:
   1916   1.1  christos 		intptr = &options->clear_forwardings;
   1917   1.1  christos 		goto parse_flag;
   1918   1.1  christos 
   1919   1.1  christos 	case oHost:
   1920  1.33  christos 		if (cmdline) {
   1921  1.33  christos 			error("Host directive not supported as a command-line "
   1922  1.12  christos 			    "option");
   1923  1.35  christos 			goto out;
   1924  1.33  christos 		}
   1925   1.1  christos 		*activep = 0;
   1926   1.6  christos 		arg2 = NULL;
   1927  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   1928  1.35  christos 			if (*arg == '\0') {
   1929  1.35  christos 				error("%s line %d: keyword %s empty argument",
   1930  1.35  christos 				    filename, linenum, keyword);
   1931  1.35  christos 				goto out;
   1932  1.35  christos 			}
   1933  1.35  christos 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
   1934  1.35  christos 				argv_consume(&ac);
   1935  1.19  christos 				break;
   1936  1.35  christos 			}
   1937   1.6  christos 			negated = *arg == '!';
   1938   1.6  christos 			if (negated)
   1939   1.6  christos 				arg++;
   1940   1.1  christos 			if (match_pattern(host, arg)) {
   1941   1.6  christos 				if (negated) {
   1942   1.6  christos 					debug("%.200s line %d: Skipping Host "
   1943   1.6  christos 					    "block because of negated match "
   1944   1.6  christos 					    "for %.100s", filename, linenum,
   1945   1.6  christos 					    arg);
   1946   1.6  christos 					*activep = 0;
   1947  1.35  christos 					argv_consume(&ac);
   1948   1.6  christos 					break;
   1949   1.6  christos 				}
   1950   1.6  christos 				if (!*activep)
   1951   1.6  christos 					arg2 = arg; /* logged below */
   1952   1.1  christos 				*activep = 1;
   1953   1.1  christos 			}
   1954   1.6  christos 		}
   1955   1.6  christos 		if (*activep)
   1956   1.6  christos 			debug("%.200s line %d: Applying options for %.100s",
   1957   1.6  christos 			    filename, linenum, arg2);
   1958  1.35  christos 		break;
   1959   1.1  christos 
   1960  1.12  christos 	case oMatch:
   1961  1.33  christos 		if (cmdline) {
   1962  1.33  christos 			error("Host directive not supported as a command-line "
   1963  1.12  christos 			    "option");
   1964  1.35  christos 			goto out;
   1965  1.33  christos 		}
   1966  1.47  christos 		value = match_cfg_line(options, str, &ac, &av, pw, host,
   1967  1.49  christos 		    original_host, remote_command, flags & SSHCONF_FINAL,
   1968  1.49  christos 		    want_final_pass, filename, linenum);
   1969  1.33  christos 		if (value < 0) {
   1970  1.33  christos 			error("%.200s line %d: Bad Match condition", filename,
   1971  1.12  christos 			    linenum);
   1972  1.35  christos 			goto out;
   1973  1.33  christos 		}
   1974  1.19  christos 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
   1975  1.12  christos 		break;
   1976  1.12  christos 
   1977   1.1  christos 	case oEscapeChar:
   1978   1.1  christos 		intptr = &options->escape_char;
   1979  1.35  christos 		arg = argv_next(&ac, &av);
   1980  1.33  christos 		if (!arg || *arg == '\0') {
   1981  1.33  christos 			error("%.200s line %d: Missing argument.",
   1982  1.33  christos 			    filename, linenum);
   1983  1.35  christos 			goto out;
   1984  1.33  christos 		}
   1985  1.14  christos 		if (strcmp(arg, "none") == 0)
   1986  1.14  christos 			value = SSH_ESCAPECHAR_NONE;
   1987  1.14  christos 		else if (arg[1] == '\0')
   1988  1.14  christos 			value = (u_char) arg[0];
   1989  1.14  christos 		else if (arg[0] == '^' && arg[2] == 0 &&
   1990   1.1  christos 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
   1991   1.1  christos 			value = (u_char) arg[1] & 31;
   1992   1.1  christos 		else {
   1993  1.33  christos 			error("%.200s line %d: Bad escape character.",
   1994   1.1  christos 			    filename, linenum);
   1995  1.35  christos 			goto out;
   1996   1.1  christos 		}
   1997   1.1  christos 		if (*activep && *intptr == -1)
   1998   1.1  christos 			*intptr = value;
   1999   1.1  christos 		break;
   2000   1.1  christos 
   2001   1.1  christos 	case oAddressFamily:
   2002   1.1  christos 		intptr = &options->address_family;
   2003  1.12  christos 		multistate_ptr = multistate_addressfamily;
   2004  1.12  christos 		goto parse_multistate;
   2005   1.1  christos 
   2006   1.1  christos 	case oEnableSSHKeysign:
   2007   1.1  christos 		intptr = &options->enable_ssh_keysign;
   2008   1.1  christos 		goto parse_flag;
   2009   1.1  christos 
   2010   1.1  christos 	case oIdentitiesOnly:
   2011   1.1  christos 		intptr = &options->identities_only;
   2012   1.1  christos 		goto parse_flag;
   2013   1.1  christos 
   2014   1.1  christos 	case oServerAliveInterval:
   2015   1.1  christos 		intptr = &options->server_alive_interval;
   2016   1.1  christos 		goto parse_time;
   2017   1.1  christos 
   2018   1.1  christos 	case oServerAliveCountMax:
   2019   1.1  christos 		intptr = &options->server_alive_count_max;
   2020   1.1  christos 		goto parse_int;
   2021   1.1  christos 
   2022   1.1  christos 	case oSendEnv:
   2023  1.45  christos 		/* XXX appends to list; doesn't respect first-match-wins */
   2024  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2025  1.35  christos 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
   2026  1.33  christos 				error("%s line %d: Invalid environment name.",
   2027   1.1  christos 				    filename, linenum);
   2028  1.35  christos 				goto out;
   2029  1.33  christos 			}
   2030  1.45  christos 			found = 1;
   2031   1.1  christos 			if (!*activep)
   2032   1.1  christos 				continue;
   2033  1.25  christos 			if (*arg == '-') {
   2034  1.25  christos 				/* Removing an env var */
   2035  1.25  christos 				rm_env(options, arg, filename, linenum);
   2036  1.25  christos 				continue;
   2037  1.25  christos 			}
   2038  1.40  christos 			opt_array_append(filename, linenum,
   2039  1.40  christos 			    lookup_opcode_name(opcode),
   2040  1.40  christos 			    &options->send_env, &options->num_send_env, arg);
   2041  1.25  christos 		}
   2042  1.45  christos 		if (!found) {
   2043  1.45  christos 			fatal("%s line %d: no %s specified",
   2044  1.45  christos 			    filename, linenum, keyword);
   2045  1.45  christos 		}
   2046  1.25  christos 		break;
   2047  1.25  christos 
   2048  1.25  christos 	case oSetEnv:
   2049  1.45  christos 		found = options->num_setenv == 0;
   2050  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2051  1.33  christos 			if (strchr(arg, '=') == NULL) {
   2052  1.33  christos 				error("%s line %d: Invalid SetEnv.",
   2053  1.25  christos 				    filename, linenum);
   2054  1.35  christos 				goto out;
   2055  1.33  christos 			}
   2056  1.45  christos 			if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
   2057  1.40  christos 				debug2("%s line %d: ignoring duplicate env "
   2058  1.40  christos 				    "name \"%.64s\"", filename, linenum, arg);
   2059  1.40  christos 				continue;
   2060  1.33  christos 			}
   2061  1.40  christos 			opt_array_append(filename, linenum,
   2062  1.40  christos 			    lookup_opcode_name(opcode),
   2063  1.45  christos 			    &strs, &nstrs, arg);
   2064  1.45  christos 		}
   2065  1.45  christos 		if (nstrs == 0) {
   2066  1.45  christos 			fatal("%s line %d: no %s specified",
   2067  1.45  christos 			    filename, linenum, keyword);
   2068  1.45  christos 		}
   2069  1.45  christos 		if (found && *activep) {
   2070  1.45  christos 			options->setenv = strs;
   2071  1.45  christos 			options->num_setenv = nstrs;
   2072  1.45  christos 			strs = NULL; /* transferred */
   2073  1.45  christos 			nstrs = 0;
   2074   1.1  christos 		}
   2075   1.1  christos 		break;
   2076   1.1  christos 
   2077   1.1  christos 	case oControlPath:
   2078   1.1  christos 		charptr = &options->control_path;
   2079   1.1  christos 		goto parse_string;
   2080   1.1  christos 
   2081   1.1  christos 	case oControlMaster:
   2082   1.1  christos 		intptr = &options->control_master;
   2083  1.12  christos 		multistate_ptr = multistate_controlmaster;
   2084  1.12  christos 		goto parse_multistate;
   2085   1.1  christos 
   2086   1.4      adam 	case oControlPersist:
   2087   1.4      adam 		/* no/false/yes/true, or a time spec */
   2088   1.4      adam 		intptr = &options->control_persist;
   2089  1.35  christos 		arg = argv_next(&ac, &av);
   2090  1.33  christos 		if (!arg || *arg == '\0') {
   2091  1.33  christos 			error("%.200s line %d: Missing ControlPersist"
   2092   1.4      adam 			    " argument.", filename, linenum);
   2093  1.35  christos 			goto out;
   2094  1.33  christos 		}
   2095   1.4      adam 		value = 0;
   2096   1.4      adam 		value2 = 0;	/* timeout */
   2097   1.4      adam 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
   2098   1.4      adam 			value = 0;
   2099   1.4      adam 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
   2100   1.4      adam 			value = 1;
   2101   1.4      adam 		else if ((value2 = convtime(arg)) >= 0)
   2102   1.4      adam 			value = 1;
   2103  1.33  christos 		else {
   2104  1.33  christos 			error("%.200s line %d: Bad ControlPersist argument.",
   2105   1.4      adam 			    filename, linenum);
   2106  1.35  christos 			goto out;
   2107  1.33  christos 		}
   2108   1.4      adam 		if (*activep && *intptr == -1) {
   2109   1.4      adam 			*intptr = value;
   2110   1.4      adam 			options->control_persist_timeout = value2;
   2111   1.4      adam 		}
   2112   1.4      adam 		break;
   2113   1.4      adam 
   2114   1.1  christos 	case oHashKnownHosts:
   2115   1.1  christos 		intptr = &options->hash_known_hosts;
   2116   1.1  christos 		goto parse_flag;
   2117   1.1  christos 
   2118   1.1  christos 	case oTunnel:
   2119   1.1  christos 		intptr = &options->tun_open;
   2120  1.12  christos 		multistate_ptr = multistate_tunnel;
   2121  1.12  christos 		goto parse_multistate;
   2122   1.1  christos 
   2123   1.1  christos 	case oTunnelDevice:
   2124  1.35  christos 		arg = argv_next(&ac, &av);
   2125  1.33  christos 		if (!arg || *arg == '\0') {
   2126  1.33  christos 			error("%.200s line %d: Missing argument.",
   2127  1.33  christos 			    filename, linenum);
   2128  1.35  christos 			goto out;
   2129  1.33  christos 		}
   2130   1.1  christos 		value = a2tun(arg, &value2);
   2131  1.33  christos 		if (value == SSH_TUNID_ERR) {
   2132  1.33  christos 			error("%.200s line %d: Bad tun device.",
   2133  1.33  christos 			    filename, linenum);
   2134  1.35  christos 			goto out;
   2135  1.33  christos 		}
   2136  1.35  christos 		if (*activep && options->tun_local == -1) {
   2137   1.1  christos 			options->tun_local = value;
   2138   1.1  christos 			options->tun_remote = value2;
   2139   1.1  christos 		}
   2140   1.1  christos 		break;
   2141   1.1  christos 
   2142   1.1  christos 	case oLocalCommand:
   2143   1.1  christos 		charptr = &options->local_command;
   2144   1.1  christos 		goto parse_command;
   2145   1.1  christos 
   2146   1.1  christos 	case oPermitLocalCommand:
   2147   1.1  christos 		intptr = &options->permit_local_command;
   2148   1.1  christos 		goto parse_flag;
   2149   1.1  christos 
   2150  1.22  christos 	case oRemoteCommand:
   2151  1.22  christos 		charptr = &options->remote_command;
   2152  1.22  christos 		goto parse_command;
   2153  1.22  christos 
   2154   1.1  christos 	case oVisualHostKey:
   2155   1.1  christos 		intptr = &options->visual_host_key;
   2156   1.1  christos 		goto parse_flag;
   2157   1.1  christos 
   2158  1.19  christos 	case oInclude:
   2159  1.33  christos 		if (cmdline) {
   2160  1.33  christos 			error("Include directive not supported as a "
   2161  1.19  christos 			    "command-line option");
   2162  1.35  christos 			goto out;
   2163  1.33  christos 		}
   2164  1.19  christos 		value = 0;
   2165  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2166  1.35  christos 			if (*arg == '\0') {
   2167  1.35  christos 				error("%s line %d: keyword %s empty argument",
   2168  1.35  christos 				    filename, linenum, keyword);
   2169  1.35  christos 				goto out;
   2170  1.35  christos 			}
   2171  1.47  christos 			/* Expand %tokens and environment variables */
   2172  1.47  christos 			if ((p = expand_match_exec_or_include_path(arg,
   2173  1.47  christos 			    options, pw, host, original_host,
   2174  1.47  christos 			    flags & SSHCONF_FINAL, 1)) == NULL) {
   2175  1.47  christos 				error("%.200s line %d: Unable to expand user "
   2176  1.47  christos 				    "config file '%.100s'",
   2177  1.47  christos 				    filename, linenum, arg);
   2178  1.47  christos 				continue;
   2179  1.47  christos 			}
   2180  1.19  christos 			/*
   2181  1.19  christos 			 * Ensure all paths are anchored. User configuration
   2182  1.19  christos 			 * files may begin with '~/' but system configurations
   2183  1.19  christos 			 * must not. If the path is relative, then treat it
   2184  1.19  christos 			 * as living in ~/.ssh for user configurations or
   2185  1.19  christos 			 * /etc/ssh for system ones.
   2186  1.19  christos 			 */
   2187  1.47  christos 			if (*p == '~' && (flags & SSHCONF_USERCONF) == 0) {
   2188  1.33  christos 				error("%.200s line %d: bad include path %s.",
   2189  1.47  christos 				    filename, linenum, p);
   2190  1.35  christos 				goto out;
   2191  1.33  christos 			}
   2192  1.47  christos 			if (!path_absolute(p) && *p != '~') {
   2193  1.19  christos 				xasprintf(&arg2, "%s/%s",
   2194  1.19  christos 				    (flags & SSHCONF_USERCONF) ?
   2195  1.47  christos 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, p);
   2196  1.47  christos 			} else {
   2197  1.47  christos 				arg2 = xstrdup(p);
   2198  1.47  christos 			}
   2199  1.47  christos 			free(p);
   2200  1.19  christos 			memset(&gl, 0, sizeof(gl));
   2201  1.19  christos 			r = glob(arg2, GLOB_TILDE | GLOB_LIMIT, NULL, &gl);
   2202  1.19  christos 			if (r == GLOB_NOMATCH) {
   2203  1.19  christos 				debug("%.200s line %d: include %s matched no "
   2204  1.19  christos 				    "files",filename, linenum, arg2);
   2205  1.21  christos 				free(arg2);
   2206  1.19  christos 				continue;
   2207  1.33  christos 			} else if (r != 0) {
   2208  1.33  christos 				error("%.200s line %d: glob failed for %s.",
   2209  1.19  christos 				    filename, linenum, arg2);
   2210  1.35  christos 				goto out;
   2211  1.33  christos 			}
   2212  1.19  christos 			free(arg2);
   2213  1.19  christos 			oactive = *activep;
   2214  1.29  christos 			for (i = 0; i < gl.gl_pathc; i++) {
   2215  1.19  christos 				debug3("%.200s line %d: Including file %s "
   2216  1.19  christos 				    "depth %d%s", filename, linenum,
   2217  1.19  christos 				    gl.gl_pathv[i], depth,
   2218  1.19  christos 				    oactive ? "" : " (parse only)");
   2219  1.19  christos 				r = read_config_file_depth(gl.gl_pathv[i],
   2220  1.49  christos 				    pw, host, original_host, remote_command,
   2221  1.49  christos 				    options, flags | SSHCONF_CHECKPERM |
   2222  1.19  christos 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
   2223  1.27  christos 				    activep, want_final_pass, depth + 1);
   2224  1.21  christos 				if (r != 1 && errno != ENOENT) {
   2225  1.47  christos 					error("%.200s line %d: Can't open user "
   2226  1.47  christos 					    "config file %.100s: %.100s",
   2227  1.47  christos 					    filename, linenum, gl.gl_pathv[i],
   2228  1.21  christos 					    strerror(errno));
   2229  1.33  christos 					globfree(&gl);
   2230  1.35  christos 					goto out;
   2231  1.21  christos 				}
   2232  1.19  christos 				/*
   2233  1.19  christos 				 * don't let Match in includes clobber the
   2234  1.19  christos 				 * containing file's Match state.
   2235  1.19  christos 				 */
   2236  1.19  christos 				*activep = oactive;
   2237  1.19  christos 				if (r != 1)
   2238  1.19  christos 					value = -1;
   2239  1.19  christos 			}
   2240  1.19  christos 			globfree(&gl);
   2241  1.19  christos 		}
   2242  1.19  christos 		if (value != 0)
   2243  1.35  christos 			ret = value;
   2244  1.19  christos 		break;
   2245  1.19  christos 
   2246   1.5  christos 	case oIPQoS:
   2247  1.35  christos 		arg = argv_next(&ac, &av);
   2248  1.33  christos 		if ((value = parse_ipqos(arg)) == -1) {
   2249  1.33  christos 			error("%s line %d: Bad IPQoS value: %s",
   2250   1.5  christos 			    filename, linenum, arg);
   2251  1.35  christos 			goto out;
   2252  1.33  christos 		}
   2253  1.50  christos 		if (value == INT_MIN) {
   2254  1.50  christos 			debug("%s line %d: Deprecated IPQoS value \"%s\" "
   2255  1.50  christos 			    "ignored - using system default instead. Consider"
   2256  1.50  christos 			    " using DSCP values.", filename, linenum, arg);
   2257  1.50  christos 			value = INT_MAX;
   2258  1.50  christos 		}
   2259  1.35  christos 		arg = argv_next(&ac, &av);
   2260   1.5  christos 		if (arg == NULL)
   2261   1.5  christos 			value2 = value;
   2262  1.33  christos 		else if ((value2 = parse_ipqos(arg)) == -1) {
   2263  1.33  christos 			error("%s line %d: Bad IPQoS value: %s",
   2264   1.5  christos 			    filename, linenum, arg);
   2265  1.35  christos 			goto out;
   2266  1.33  christos 		}
   2267  1.50  christos 		if (value2 == INT_MIN) {
   2268  1.50  christos 			debug("%s line %d: Deprecated IPQoS value \"%s\" "
   2269  1.50  christos 			    "ignored - using system default instead. Consider"
   2270  1.50  christos 			    " using DSCP values.", filename, linenum, arg);
   2271  1.50  christos 			value2 = INT_MAX;
   2272  1.50  christos 		}
   2273  1.35  christos 		if (*activep && options->ip_qos_interactive == -1) {
   2274   1.5  christos 			options->ip_qos_interactive = value;
   2275   1.5  christos 			options->ip_qos_bulk = value2;
   2276   1.5  christos 		}
   2277   1.5  christos 		break;
   2278   1.5  christos 
   2279   1.6  christos 	case oRequestTTY:
   2280   1.6  christos 		intptr = &options->request_tty;
   2281  1.12  christos 		multistate_ptr = multistate_requesttty;
   2282  1.12  christos 		goto parse_multistate;
   2283   1.6  christos 
   2284   1.7       tls 	case oSendVersionFirst:
   2285   1.7       tls 		intptr = &options->send_version_first;
   2286   1.7       tls 		goto parse_flag;
   2287   1.7       tls 
   2288  1.35  christos 	case oSessionType:
   2289  1.35  christos 		intptr = &options->session_type;
   2290  1.35  christos 		multistate_ptr = multistate_sessiontype;
   2291  1.35  christos 		goto parse_multistate;
   2292  1.35  christos 
   2293  1.35  christos 	case oStdinNull:
   2294  1.35  christos 		intptr = &options->stdin_null;
   2295  1.35  christos 		goto parse_flag;
   2296  1.35  christos 
   2297  1.35  christos 	case oForkAfterAuthentication:
   2298  1.35  christos 		intptr = &options->fork_after_authentication;
   2299  1.35  christos 		goto parse_flag;
   2300  1.35  christos 
   2301  1.11  christos 	case oIgnoreUnknown:
   2302  1.11  christos 		charptr = &options->ignored_unknown;
   2303  1.11  christos 		goto parse_string;
   2304  1.11  christos 
   2305  1.12  christos 	case oProxyUseFdpass:
   2306  1.12  christos 		intptr = &options->proxy_use_fdpass;
   2307  1.12  christos 		goto parse_flag;
   2308  1.12  christos 
   2309  1.12  christos 	case oCanonicalDomains:
   2310  1.45  christos 		found = options->num_canonical_domains == 0;
   2311  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2312  1.35  christos 			/* Allow "none" only in first position */
   2313  1.35  christos 			if (strcasecmp(arg, "none") == 0) {
   2314  1.45  christos 				if (nstrs > 0 || ac > 0) {
   2315  1.35  christos 					error("%s line %d: keyword %s \"none\" "
   2316  1.35  christos 					    "argument must appear alone.",
   2317  1.35  christos 					    filename, linenum, keyword);
   2318  1.35  christos 					goto out;
   2319  1.35  christos 				}
   2320  1.35  christos 			}
   2321  1.23  christos 			if (!valid_domain(arg, 1, &errstr)) {
   2322  1.33  christos 				error("%s line %d: %s", filename, linenum,
   2323  1.23  christos 				    errstr);
   2324  1.35  christos 				goto out;
   2325  1.23  christos 			}
   2326  1.45  christos 			opt_array_append(filename, linenum, keyword,
   2327  1.45  christos 			    &strs, &nstrs, arg);
   2328  1.45  christos 		}
   2329  1.45  christos 		if (nstrs == 0) {
   2330  1.45  christos 			fatal("%s line %d: no %s specified",
   2331  1.45  christos 			    filename, linenum, keyword);
   2332  1.45  christos 		}
   2333  1.45  christos 		if (found && *activep) {
   2334  1.45  christos 			options->canonical_domains = strs;
   2335  1.45  christos 			options->num_canonical_domains = nstrs;
   2336  1.45  christos 			strs = NULL; /* transferred */
   2337  1.45  christos 			nstrs = 0;
   2338  1.12  christos 		}
   2339  1.12  christos 		break;
   2340  1.12  christos 
   2341  1.12  christos 	case oCanonicalizePermittedCNAMEs:
   2342  1.45  christos 		found = options->num_permitted_cnames == 0;
   2343  1.35  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2344  1.37  christos 			char empty[] = "";
   2345  1.37  christos 			/*
   2346  1.37  christos 			 * Either 'none' (only in first position), '*' for
   2347  1.37  christos 			 * everything or 'list:list'
   2348  1.37  christos 			 */
   2349  1.37  christos 			if (strcasecmp(arg, "none") == 0) {
   2350  1.45  christos 				if (ncnames > 0 || ac > 0) {
   2351  1.37  christos 					error("%s line %d: keyword %s \"none\" "
   2352  1.37  christos 					    "argument must appear alone.",
   2353  1.37  christos 					    filename, linenum, keyword);
   2354  1.37  christos 					goto out;
   2355  1.37  christos 				}
   2356  1.37  christos 				arg2 = empty;
   2357  1.37  christos 			} else if (strcmp(arg, "*") == 0) {
   2358  1.12  christos 				arg2 = arg;
   2359  1.37  christos 			} else {
   2360  1.12  christos 				lowercase(arg);
   2361  1.12  christos 				if ((arg2 = strchr(arg, ':')) == NULL ||
   2362  1.12  christos 				    arg2[1] == '\0') {
   2363  1.33  christos 					error("%s line %d: "
   2364  1.12  christos 					    "Invalid permitted CNAME \"%s\"",
   2365  1.12  christos 					    filename, linenum, arg);
   2366  1.35  christos 					goto out;
   2367  1.12  christos 				}
   2368  1.12  christos 				*arg2 = '\0';
   2369  1.12  christos 				arg2++;
   2370  1.12  christos 			}
   2371  1.45  christos 			cnames = xrecallocarray(cnames, ncnames, ncnames + 1,
   2372  1.45  christos 			    sizeof(*cnames));
   2373  1.45  christos 			cnames[ncnames].source_list = xstrdup(arg);
   2374  1.45  christos 			cnames[ncnames].target_list = xstrdup(arg2);
   2375  1.45  christos 			ncnames++;
   2376  1.45  christos 		}
   2377  1.45  christos 		if (ncnames == 0) {
   2378  1.45  christos 			fatal("%s line %d: no %s specified",
   2379  1.45  christos 			    filename, linenum, keyword);
   2380  1.45  christos 		}
   2381  1.45  christos 		if (found && *activep) {
   2382  1.45  christos 			options->permitted_cnames = cnames;
   2383  1.45  christos 			options->num_permitted_cnames = ncnames;
   2384  1.45  christos 			cnames = NULL; /* transferred */
   2385  1.45  christos 			ncnames = 0;
   2386  1.12  christos 		}
   2387  1.45  christos 		/* un-transferred cnames is cleaned up before exit */
   2388  1.12  christos 		break;
   2389  1.12  christos 
   2390  1.12  christos 	case oCanonicalizeHostname:
   2391  1.12  christos 		intptr = &options->canonicalize_hostname;
   2392  1.12  christos 		multistate_ptr = multistate_canonicalizehostname;
   2393  1.12  christos 		goto parse_multistate;
   2394  1.12  christos 
   2395  1.12  christos 	case oCanonicalizeMaxDots:
   2396  1.12  christos 		intptr = &options->canonicalize_max_dots;
   2397  1.12  christos 		goto parse_int;
   2398  1.12  christos 
   2399  1.12  christos 	case oCanonicalizeFallbackLocal:
   2400  1.12  christos 		intptr = &options->canonicalize_fallback_local;
   2401  1.12  christos 		goto parse_flag;
   2402  1.12  christos 
   2403  1.12  christos 	case oStreamLocalBindMask:
   2404  1.35  christos 		arg = argv_next(&ac, &av);
   2405  1.33  christos 		if (!arg || *arg == '\0') {
   2406  1.33  christos 			error("%.200s line %d: Missing StreamLocalBindMask "
   2407  1.33  christos 			    "argument.", filename, linenum);
   2408  1.35  christos 			goto out;
   2409  1.33  christos 		}
   2410  1.12  christos 		/* Parse mode in octal format */
   2411  1.12  christos 		value = strtol(arg, &endofnumber, 8);
   2412  1.33  christos 		if (arg == endofnumber || value < 0 || value > 0777) {
   2413  1.33  christos 			error("%.200s line %d: Bad mask.", filename, linenum);
   2414  1.35  christos 			goto out;
   2415  1.33  christos 		}
   2416  1.12  christos 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
   2417  1.12  christos 		break;
   2418  1.12  christos 
   2419  1.12  christos 	case oStreamLocalBindUnlink:
   2420  1.12  christos 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
   2421  1.12  christos 		goto parse_flag;
   2422  1.12  christos 
   2423  1.13  christos 	case oRevokedHostKeys:
   2424  1.51  christos 		uintptr = &options->num_revoked_host_keys;
   2425  1.51  christos 		cppptr = &options->revoked_host_keys;
   2426  1.51  christos 		found = *uintptr == 0;
   2427  1.51  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2428  1.51  christos 			if (*arg == '\0') {
   2429  1.51  christos 				error("%s line %d: keyword %s empty argument",
   2430  1.51  christos 				    filename, linenum, keyword);
   2431  1.51  christos 				goto out;
   2432  1.51  christos 			}
   2433  1.51  christos 			/* Allow "none" only in first position */
   2434  1.51  christos 			if (strcasecmp(arg, "none") == 0) {
   2435  1.51  christos 				if (nstrs > 0 || ac > 0) {
   2436  1.51  christos 					error("%s line %d: keyword %s \"none\" "
   2437  1.51  christos 					    "argument must appear alone.",
   2438  1.51  christos 					    filename, linenum, keyword);
   2439  1.51  christos 					goto out;
   2440  1.51  christos 				}
   2441  1.51  christos 			}
   2442  1.51  christos 			opt_array_append(filename, linenum, keyword,
   2443  1.51  christos 			    &strs, &nstrs, arg);
   2444  1.51  christos 		}
   2445  1.51  christos 		if (nstrs == 0) {
   2446  1.51  christos 			fatal("%s line %d: no %s specified",
   2447  1.51  christos 			    filename, linenum, keyword);
   2448  1.51  christos 		}
   2449  1.51  christos 		if (found && *activep) {
   2450  1.51  christos 			*cppptr = strs;
   2451  1.51  christos 			*uintptr = nstrs;
   2452  1.51  christos 			strs = NULL; /* transferred */
   2453  1.51  christos 			nstrs = 0;
   2454  1.51  christos 		}
   2455  1.51  christos 		break;
   2456  1.13  christos 
   2457  1.13  christos 	case oFingerprintHash:
   2458  1.13  christos 		intptr = &options->fingerprint_hash;
   2459  1.35  christos 		arg = argv_next(&ac, &av);
   2460  1.33  christos 		if (!arg || *arg == '\0') {
   2461  1.33  christos 			error("%.200s line %d: Missing argument.",
   2462  1.13  christos 			    filename, linenum);
   2463  1.35  christos 			goto out;
   2464  1.33  christos 		}
   2465  1.33  christos 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
   2466  1.33  christos 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
   2467  1.13  christos 			    filename, linenum, arg);
   2468  1.35  christos 			goto out;
   2469  1.33  christos 		}
   2470  1.13  christos 		if (*activep && *intptr == -1)
   2471  1.13  christos 			*intptr = value;
   2472  1.13  christos 		break;
   2473  1.13  christos 
   2474  1.13  christos 	case oUpdateHostkeys:
   2475  1.13  christos 		intptr = &options->update_hostkeys;
   2476  1.13  christos 		multistate_ptr = multistate_yesnoask;
   2477  1.13  christos 		goto parse_multistate;
   2478  1.13  christos 
   2479  1.33  christos 	case oHostbasedAcceptedAlgorithms:
   2480  1.33  christos 		charptr = &options->hostbased_accepted_algos;
   2481  1.42  christos 		ca_only = 0;
   2482  1.33  christos 		goto parse_pubkey_algos;
   2483  1.33  christos 
   2484  1.33  christos 	case oPubkeyAcceptedAlgorithms:
   2485  1.33  christos 		charptr = &options->pubkey_accepted_algos;
   2486  1.42  christos 		ca_only = 0;
   2487  1.33  christos 		goto parse_pubkey_algos;
   2488  1.13  christos 
   2489  1.18  christos 	case oAddKeysToAgent:
   2490  1.35  christos 		arg = argv_next(&ac, &av);
   2491  1.35  christos 		arg2 = argv_next(&ac, &av);
   2492  1.32  christos 		value = parse_multistate_value(arg, filename, linenum,
   2493  1.34  christos 		    multistate_yesnoaskconfirm);
   2494  1.32  christos 		value2 = 0; /* unlimited lifespan by default */
   2495  1.32  christos 		if (value == 3 && arg2 != NULL) {
   2496  1.32  christos 			/* allow "AddKeysToAgent confirm 5m" */
   2497  1.41  christos 			if ((value2 = convtime(arg2)) == -1) {
   2498  1.33  christos 				error("%s line %d: invalid time value.",
   2499  1.32  christos 				    filename, linenum);
   2500  1.35  christos 				goto out;
   2501  1.33  christos 			}
   2502  1.32  christos 		} else if (value == -1 && arg2 == NULL) {
   2503  1.41  christos 			if ((value2 = convtime(arg)) == -1) {
   2504  1.33  christos 				error("%s line %d: unsupported option",
   2505  1.32  christos 				    filename, linenum);
   2506  1.35  christos 				goto out;
   2507  1.33  christos 			}
   2508  1.32  christos 			value = 1; /* yes */
   2509  1.32  christos 		} else if (value == -1 || arg2 != NULL) {
   2510  1.33  christos 			error("%s line %d: unsupported option",
   2511  1.32  christos 			    filename, linenum);
   2512  1.35  christos 			goto out;
   2513  1.32  christos 		}
   2514  1.32  christos 		if (*activep && options->add_keys_to_agent == -1) {
   2515  1.32  christos 			options->add_keys_to_agent = value;
   2516  1.32  christos 			options->add_keys_to_agent_lifespan = value2;
   2517  1.32  christos 		}
   2518  1.32  christos 		break;
   2519  1.18  christos 
   2520  1.19  christos 	case oIdentityAgent:
   2521  1.19  christos 		charptr = &options->identity_agent;
   2522  1.35  christos 		arg = argv_next(&ac, &av);
   2523  1.33  christos 		if (!arg || *arg == '\0') {
   2524  1.33  christos 			error("%.200s line %d: Missing argument.",
   2525  1.27  christos 			    filename, linenum);
   2526  1.35  christos 			goto out;
   2527  1.33  christos 		}
   2528  1.29  christos   parse_agent_path:
   2529  1.27  christos 		/* Extra validation if the string represents an env var. */
   2530  1.33  christos 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
   2531  1.33  christos 			error("%.200s line %d: Invalid environment expansion "
   2532  1.32  christos 			    "%s.", filename, linenum, arg);
   2533  1.35  christos 			goto out;
   2534  1.33  christos 		}
   2535  1.32  christos 		free(arg2);
   2536  1.32  christos 		/* check for legacy environment format */
   2537  1.33  christos 		if (arg[0] == '$' && arg[1] != '{' &&
   2538  1.33  christos 		    !valid_env_name(arg + 1)) {
   2539  1.33  christos 			error("%.200s line %d: Invalid environment name %s.",
   2540  1.27  christos 			    filename, linenum, arg);
   2541  1.35  christos 			goto out;
   2542  1.27  christos 		}
   2543  1.27  christos 		if (*activep && *charptr == NULL)
   2544  1.27  christos 			*charptr = xstrdup(arg);
   2545  1.27  christos 		break;
   2546  1.19  christos 
   2547  1.41  christos 	case oEnableEscapeCommandline:
   2548  1.41  christos 		intptr = &options->enable_escape_commandline;
   2549  1.41  christos 		goto parse_flag;
   2550  1.41  christos 
   2551  1.40  christos 	case oRequiredRSASize:
   2552  1.40  christos 		intptr = &options->required_rsa_size;
   2553  1.40  christos 		goto parse_int;
   2554  1.40  christos 
   2555  1.50  christos 	case oWarnWeakCrypto:
   2556  1.50  christos 		intptr = &options->warn_weak_crypto;
   2557  1.50  christos 		multistate_ptr = multistate_warnweakcrypto;
   2558  1.50  christos 		goto parse_multistate;
   2559  1.50  christos 
   2560  1.42  christos 	case oObscureKeystrokeTiming:
   2561  1.42  christos 		value = -1;
   2562  1.42  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2563  1.42  christos 			if (value != -1) {
   2564  1.42  christos 				error("%s line %d: invalid arguments",
   2565  1.42  christos 				    filename, linenum);
   2566  1.42  christos 				goto out;
   2567  1.42  christos 			}
   2568  1.42  christos 			if (strcmp(arg, "yes") == 0 ||
   2569  1.42  christos 			    strcmp(arg, "true") == 0)
   2570  1.42  christos 				value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
   2571  1.42  christos 			else if (strcmp(arg, "no") == 0 ||
   2572  1.42  christos 			    strcmp(arg, "false") == 0)
   2573  1.42  christos 				value = 0;
   2574  1.42  christos 			else if (strncmp(arg, "interval:", 9) == 0) {
   2575  1.42  christos 				if ((errstr = atoi_err(arg + 9,
   2576  1.42  christos 				    &value)) != NULL) {
   2577  1.42  christos 					error("%s line %d: integer value %s.",
   2578  1.42  christos 					    filename, linenum, errstr);
   2579  1.42  christos 					goto out;
   2580  1.42  christos 				}
   2581  1.42  christos 				if (value <= 0 || value > 1000) {
   2582  1.42  christos 					error("%s line %d: value out of range.",
   2583  1.42  christos 					    filename, linenum);
   2584  1.42  christos 					goto out;
   2585  1.42  christos 				}
   2586  1.42  christos 			} else {
   2587  1.42  christos 				error("%s line %d: unsupported argument \"%s\"",
   2588  1.42  christos 				    filename, linenum, arg);
   2589  1.42  christos 				goto out;
   2590  1.42  christos 			}
   2591  1.42  christos 		}
   2592  1.42  christos 		if (value == -1) {
   2593  1.42  christos 			error("%s line %d: missing argument",
   2594  1.42  christos 			    filename, linenum);
   2595  1.42  christos 			goto out;
   2596  1.42  christos 		}
   2597  1.42  christos 		intptr = &options->obscure_keystroke_timing_interval;
   2598  1.42  christos 		if (*activep && *intptr == -1)
   2599  1.42  christos 			*intptr = value;
   2600  1.42  christos 		break;
   2601  1.42  christos 
   2602  1.44  christos 	case oChannelTimeout:
   2603  1.45  christos 		found = options->num_channel_timeouts == 0;
   2604  1.44  christos 		while ((arg = argv_next(&ac, &av)) != NULL) {
   2605  1.44  christos 			/* Allow "none" only in first position */
   2606  1.44  christos 			if (strcasecmp(arg, "none") == 0) {
   2607  1.45  christos 				if (nstrs > 0 || ac > 0) {
   2608  1.44  christos 					error("%s line %d: keyword %s \"none\" "
   2609  1.44  christos 					    "argument must appear alone.",
   2610  1.44  christos 					    filename, linenum, keyword);
   2611  1.44  christos 					goto out;
   2612  1.44  christos 				}
   2613  1.44  christos 			} else if (parse_pattern_interval(arg,
   2614  1.44  christos 			    NULL, NULL) != 0) {
   2615  1.44  christos 				fatal("%s line %d: invalid channel timeout %s",
   2616  1.44  christos 				    filename, linenum, arg);
   2617  1.44  christos 			}
   2618  1.44  christos 			opt_array_append(filename, linenum, keyword,
   2619  1.45  christos 			    &strs, &nstrs, arg);
   2620  1.45  christos 		}
   2621  1.45  christos 		if (nstrs == 0) {
   2622  1.45  christos 			fatal("%s line %d: no %s specified",
   2623  1.45  christos 			    filename, linenum, keyword);
   2624  1.45  christos 		}
   2625  1.45  christos 		if (found && *activep) {
   2626  1.45  christos 			options->channel_timeouts = strs;
   2627  1.45  christos 			options->num_channel_timeouts = nstrs;
   2628  1.45  christos 			strs = NULL; /* transferred */
   2629  1.45  christos 			nstrs = 0;
   2630  1.44  christos 		}
   2631  1.44  christos 		break;
   2632  1.44  christos 
   2633  1.49  christos 	case oVersionAddendum:
   2634  1.49  christos 		if (str == NULL || *str == '\0')
   2635  1.49  christos 			fatal("%s line %d: %s missing argument.",
   2636  1.49  christos 			    filename, linenum, keyword);
   2637  1.49  christos 		len = strspn(str, WHITESPACE);
   2638  1.49  christos 		if (strchr(str + len, '\r') != NULL) {
   2639  1.49  christos 			fatal("%.200s line %d: Invalid %s argument",
   2640  1.49  christos 			    filename, linenum, keyword);
   2641  1.49  christos 		}
   2642  1.49  christos 		if ((arg = strchr(line, '#')) != NULL) {
   2643  1.49  christos 			*arg = '\0';
   2644  1.49  christos 			rtrim(line);
   2645  1.49  christos 		}
   2646  1.49  christos 		if (*activep && options->version_addendum == NULL) {
   2647  1.49  christos 			if (strcasecmp(str + len, "none") == 0)
   2648  1.49  christos 				options->version_addendum = xstrdup("");
   2649  1.49  christos 			else
   2650  1.49  christos 				options->version_addendum = xstrdup(str + len);
   2651  1.49  christos 		}
   2652  1.49  christos 		argv_consume(&ac);
   2653  1.49  christos 		break;
   2654  1.49  christos 
   2655  1.50  christos 	case oRefuseConnection:
   2656  1.50  christos 		arg = argv_next(&ac, &av);
   2657  1.50  christos 		if (!arg || *arg == '\0') {
   2658  1.50  christos 			error("%.200s line %d: Missing argument.",
   2659  1.50  christos 			    filename, linenum);
   2660  1.50  christos 			goto out;
   2661  1.50  christos 		}
   2662  1.50  christos 		if (*activep) {
   2663  1.50  christos 			fatal("%.200s line %d: RefuseConnection: %s",
   2664  1.50  christos 			    filename, linenum, arg);
   2665  1.50  christos 		}
   2666  1.50  christos 		break;
   2667  1.50  christos 
   2668   1.1  christos 	case oDeprecated:
   2669   1.1  christos 		debug("%s line %d: Deprecated option \"%s\"",
   2670   1.1  christos 		    filename, linenum, keyword);
   2671  1.35  christos 		argv_consume(&ac);
   2672  1.35  christos 		break;
   2673   1.1  christos 
   2674   1.1  christos 	case oUnsupported:
   2675   1.1  christos 		error("%s line %d: Unsupported option \"%s\"",
   2676   1.1  christos 		    filename, linenum, keyword);
   2677  1.35  christos 		argv_consume(&ac);
   2678  1.35  christos 		break;
   2679   1.1  christos 
   2680   1.1  christos 	default:
   2681  1.33  christos 		error("%s line %d: Unimplemented opcode %d",
   2682  1.33  christos 		    filename, linenum, opcode);
   2683  1.35  christos 		goto out;
   2684   1.1  christos 	}
   2685   1.1  christos 
   2686   1.1  christos 	/* Check that there is no garbage at end of line. */
   2687  1.35  christos 	if (ac > 0) {
   2688  1.35  christos 		error("%.200s line %d: keyword %s extra arguments "
   2689  1.35  christos 		    "at end of line", filename, linenum, keyword);
   2690  1.35  christos 		goto out;
   2691   1.1  christos 	}
   2692  1.35  christos 
   2693  1.35  christos 	/* success */
   2694  1.35  christos 	ret = 0;
   2695  1.35  christos  out:
   2696  1.45  christos 	free_canon_cnames(cnames, ncnames);
   2697  1.45  christos 	opt_array_free2(strs, NULL, nstrs);
   2698  1.35  christos 	argv_free(oav, oac);
   2699  1.35  christos 	return ret;
   2700   1.1  christos }
   2701   1.1  christos 
   2702   1.1  christos /*
   2703   1.1  christos  * Reads the config file and modifies the options accordingly.  Options
   2704   1.1  christos  * should already be initialized before this call.  This never returns if
   2705   1.1  christos  * there is an error.  If the file does not exist, this returns 0.
   2706   1.1  christos  */
   2707   1.1  christos int
   2708  1.12  christos read_config_file(const char *filename, struct passwd *pw, const char *host,
   2709  1.49  christos     const char *original_host, const char *remote_command, Options *options, int flags,
   2710  1.27  christos     int *want_final_pass)
   2711   1.1  christos {
   2712  1.19  christos 	int active = 1;
   2713  1.19  christos 
   2714  1.19  christos 	return read_config_file_depth(filename, pw, host, original_host,
   2715  1.49  christos 	    remote_command, options, flags, &active, want_final_pass, 0);
   2716  1.19  christos }
   2717  1.19  christos 
   2718  1.19  christos #define READCONF_MAX_DEPTH	16
   2719  1.19  christos static int
   2720  1.19  christos read_config_file_depth(const char *filename, struct passwd *pw,
   2721  1.49  christos     const char *host, const char *original_host, const char *remote_command,
   2722  1.49  christos     Options *options, int flags, int *activep, int *want_final_pass, int depth)
   2723  1.19  christos {
   2724   1.1  christos 	FILE *f;
   2725  1.35  christos 	char *line = NULL;
   2726  1.25  christos 	size_t linesize = 0;
   2727  1.19  christos 	int linenum;
   2728   1.1  christos 	int bad_options = 0;
   2729   1.1  christos 
   2730  1.19  christos 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
   2731  1.19  christos 		fatal("Too many recursive configuration includes");
   2732  1.19  christos 
   2733   1.1  christos 	if ((f = fopen(filename, "r")) == NULL)
   2734   1.1  christos 		return 0;
   2735   1.1  christos 
   2736   1.9   mlelstv 	if (flags & SSHCONF_CHECKPERM) {
   2737   1.1  christos 		struct stat sb;
   2738   1.1  christos 
   2739   1.1  christos 		if (fstat(fileno(f), &sb) == -1)
   2740   1.1  christos 			fatal("fstat %s: %s", filename, strerror(errno));
   2741   1.1  christos 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
   2742   1.1  christos 		    (sb.st_mode & 022) != 0))
   2743   1.1  christos 			fatal("Bad owner or permissions on %s", filename);
   2744   1.1  christos 	}
   2745   1.1  christos 
   2746   1.1  christos 	debug("Reading configuration data %.200s", filename);
   2747   1.1  christos 
   2748   1.1  christos 	/*
   2749   1.1  christos 	 * Mark that we are now processing the options.  This flag is turned
   2750   1.1  christos 	 * on/off by Host specifications.
   2751   1.1  christos 	 */
   2752   1.1  christos 	linenum = 0;
   2753  1.25  christos 	while (getline(&line, &linesize, f) != -1) {
   2754   1.1  christos 		/* Update line number counter. */
   2755   1.1  christos 		linenum++;
   2756  1.33  christos 		/*
   2757  1.33  christos 		 * Trim out comments and strip whitespace.
   2758  1.33  christos 		 * NB - preserve newlines, they are needed to reproduce
   2759  1.33  christos 		 * line numbers later for error messages.
   2760  1.33  christos 		 */
   2761  1.19  christos 		if (process_config_line_depth(options, pw, host, original_host,
   2762  1.49  christos 		    remote_command, line, filename, linenum, activep, flags,
   2763  1.49  christos 		    want_final_pass, depth) != 0)
   2764   1.1  christos 			bad_options++;
   2765   1.1  christos 	}
   2766  1.25  christos 	free(line);
   2767   1.1  christos 	fclose(f);
   2768   1.1  christos 	if (bad_options > 0)
   2769   1.1  christos 		fatal("%s: terminating, %d bad configuration options",
   2770   1.1  christos 		    filename, bad_options);
   2771   1.1  christos 	return 1;
   2772   1.1  christos }
   2773   1.1  christos 
   2774  1.12  christos /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
   2775  1.12  christos int
   2776  1.12  christos option_clear_or_none(const char *o)
   2777  1.12  christos {
   2778  1.12  christos 	return o == NULL || strcasecmp(o, "none") == 0;
   2779  1.12  christos }
   2780  1.12  christos 
   2781   1.1  christos /*
   2782  1.37  christos  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
   2783  1.37  christos  * Allowed to be called on non-final configuration.
   2784  1.37  christos  */
   2785  1.37  christos int
   2786  1.37  christos config_has_permitted_cnames(Options *options)
   2787  1.37  christos {
   2788  1.37  christos 	if (options->num_permitted_cnames == 1 &&
   2789  1.37  christos 	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
   2790  1.37  christos 	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
   2791  1.37  christos 		return 0;
   2792  1.37  christos 	return options->num_permitted_cnames > 0;
   2793  1.37  christos }
   2794  1.37  christos 
   2795  1.37  christos /*
   2796   1.1  christos  * Initializes options to special values that indicate that they have not yet
   2797   1.1  christos  * been set.  Read_config_file will only set options with this value. Options
   2798   1.1  christos  * are processed in the following order: command line, user config file,
   2799   1.1  christos  * system config file.  Last, fill_default_options is called.
   2800   1.1  christos  */
   2801   1.1  christos 
   2802   1.1  christos void
   2803   1.1  christos initialize_options(Options * options)
   2804   1.1  christos {
   2805   1.1  christos 	memset(options, 'X', sizeof(*options));
   2806  1.41  christos 	options->host_arg = NULL;
   2807   1.1  christos 	options->forward_agent = -1;
   2808  1.29  christos 	options->forward_agent_sock_path = NULL;
   2809   1.1  christos 	options->forward_x11 = -1;
   2810   1.1  christos 	options->forward_x11_trusted = -1;
   2811   1.4      adam 	options->forward_x11_timeout = -1;
   2812  1.19  christos 	options->stdio_forward_host = NULL;
   2813  1.19  christos 	options->stdio_forward_port = 0;
   2814  1.19  christos 	options->clear_forwardings = -1;
   2815   1.1  christos 	options->exit_on_forward_failure = -1;
   2816   1.1  christos 	options->xauth_location = NULL;
   2817  1.12  christos 	options->fwd_opts.gateway_ports = -1;
   2818  1.12  christos 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
   2819  1.12  christos 	options->fwd_opts.streamlocal_bind_unlink = -1;
   2820   1.1  christos 	options->pubkey_authentication = -1;
   2821   1.2  christos #if defined(KRB4) || defined(KRB5)
   2822   1.2  christos 	options->kerberos_authentication = -1;
   2823   1.2  christos #endif
   2824   1.2  christos #if defined(AFS) || defined(KRB5)
   2825   1.2  christos 	options->kerberos_tgt_passing = -1;
   2826   1.2  christos #endif
   2827   1.2  christos #ifdef AFS
   2828   1.2  christos 	options->afs_token_passing = -1;
   2829   1.2  christos #endif
   2830   1.1  christos 	options->gss_authentication = -1;
   2831   1.1  christos 	options->gss_deleg_creds = -1;
   2832   1.1  christos 	options->password_authentication = -1;
   2833   1.1  christos 	options->kbd_interactive_authentication = -1;
   2834   1.1  christos 	options->kbd_interactive_devices = NULL;
   2835   1.1  christos 	options->hostbased_authentication = -1;
   2836   1.1  christos 	options->batch_mode = -1;
   2837   1.1  christos 	options->check_host_ip = -1;
   2838   1.1  christos 	options->strict_host_key_checking = -1;
   2839   1.1  christos 	options->compression = -1;
   2840   1.1  christos 	options->tcp_keep_alive = -1;
   2841   1.1  christos 	options->port = -1;
   2842   1.1  christos 	options->address_family = -1;
   2843   1.1  christos 	options->connection_attempts = -1;
   2844   1.1  christos 	options->connection_timeout = -1;
   2845   1.1  christos 	options->number_of_password_prompts = -1;
   2846   1.1  christos 	options->ciphers = NULL;
   2847   1.1  christos 	options->macs = NULL;
   2848   1.5  christos 	options->kex_algorithms = NULL;
   2849   1.1  christos 	options->hostkeyalgorithms = NULL;
   2850  1.27  christos 	options->ca_sign_algorithms = NULL;
   2851   1.1  christos 	options->num_identity_files = 0;
   2852  1.33  christos 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
   2853  1.18  christos 	options->num_certificate_files = 0;
   2854  1.33  christos 	memset(options->certificates, 0, sizeof(options->certificates));
   2855   1.1  christos 	options->hostname = NULL;
   2856   1.1  christos 	options->host_key_alias = NULL;
   2857   1.1  christos 	options->proxy_command = NULL;
   2858  1.19  christos 	options->jump_user = NULL;
   2859  1.19  christos 	options->jump_host = NULL;
   2860  1.19  christos 	options->jump_port = -1;
   2861  1.19  christos 	options->jump_extra = NULL;
   2862   1.1  christos 	options->user = NULL;
   2863   1.1  christos 	options->escape_char = -1;
   2864   1.6  christos 	options->num_system_hostfiles = 0;
   2865   1.6  christos 	options->num_user_hostfiles = 0;
   2866   1.4      adam 	options->local_forwards = NULL;
   2867   1.1  christos 	options->num_local_forwards = 0;
   2868   1.4      adam 	options->remote_forwards = NULL;
   2869   1.1  christos 	options->num_remote_forwards = 0;
   2870  1.33  christos 	options->permitted_remote_opens = NULL;
   2871  1.33  christos 	options->num_permitted_remote_opens = 0;
   2872  1.22  christos 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
   2873   1.1  christos 	options->log_level = SYSLOG_LEVEL_NOT_SET;
   2874  1.33  christos 	options->num_log_verbose = 0;
   2875  1.33  christos 	options->log_verbose = NULL;
   2876   1.1  christos 	options->preferred_authentications = NULL;
   2877   1.1  christos 	options->bind_address = NULL;
   2878  1.23  christos 	options->bind_interface = NULL;
   2879  1.43        ws 	options->ipv6_prefer_temporary = -1;
   2880   1.4      adam 	options->pkcs11_provider = NULL;
   2881  1.29  christos 	options->sk_provider = NULL;
   2882   1.1  christos 	options->enable_ssh_keysign = - 1;
   2883   1.1  christos 	options->no_host_authentication_for_localhost = - 1;
   2884   1.1  christos 	options->identities_only = - 1;
   2885   1.1  christos 	options->rekey_limit = - 1;
   2886  1.11  christos 	options->rekey_interval = -1;
   2887   1.1  christos 	options->verify_host_key_dns = -1;
   2888   1.1  christos 	options->server_alive_interval = -1;
   2889   1.1  christos 	options->server_alive_count_max = -1;
   2890  1.25  christos 	options->send_env = NULL;
   2891   1.1  christos 	options->num_send_env = 0;
   2892  1.25  christos 	options->setenv = NULL;
   2893  1.25  christos 	options->num_setenv = 0;
   2894   1.1  christos 	options->control_path = NULL;
   2895   1.1  christos 	options->control_master = -1;
   2896   1.4      adam 	options->control_persist = -1;
   2897   1.4      adam 	options->control_persist_timeout = 0;
   2898   1.1  christos 	options->hash_known_hosts = -1;
   2899   1.1  christos 	options->tun_open = -1;
   2900   1.1  christos 	options->tun_local = -1;
   2901   1.1  christos 	options->tun_remote = -1;
   2902   1.1  christos 	options->local_command = NULL;
   2903   1.1  christos 	options->permit_local_command = -1;
   2904  1.22  christos 	options->remote_command = NULL;
   2905  1.18  christos 	options->add_keys_to_agent = -1;
   2906  1.32  christos 	options->add_keys_to_agent_lifespan = -1;
   2907  1.19  christos 	options->identity_agent = NULL;
   2908   1.1  christos 	options->visual_host_key = -1;
   2909   1.5  christos 	options->ip_qos_interactive = -1;
   2910   1.5  christos 	options->ip_qos_bulk = -1;
   2911   1.6  christos 	options->request_tty = -1;
   2912  1.35  christos 	options->session_type = -1;
   2913  1.35  christos 	options->stdin_null = -1;
   2914  1.35  christos 	options->fork_after_authentication = -1;
   2915  1.12  christos 	options->proxy_use_fdpass = -1;
   2916  1.11  christos 	options->ignored_unknown = NULL;
   2917  1.12  christos 	options->num_canonical_domains = 0;
   2918  1.12  christos 	options->num_permitted_cnames = 0;
   2919  1.12  christos 	options->canonicalize_max_dots = -1;
   2920  1.12  christos 	options->canonicalize_fallback_local = -1;
   2921  1.12  christos 	options->canonicalize_hostname = -1;
   2922  1.13  christos 	options->revoked_host_keys = NULL;
   2923  1.51  christos 	options->num_revoked_host_keys = 0;
   2924  1.13  christos 	options->fingerprint_hash = -1;
   2925  1.13  christos 	options->update_hostkeys = -1;
   2926  1.33  christos 	options->hostbased_accepted_algos = NULL;
   2927  1.33  christos 	options->pubkey_accepted_algos = NULL;
   2928  1.33  christos 	options->known_hosts_command = NULL;
   2929  1.40  christos 	options->required_rsa_size = -1;
   2930  1.50  christos 	options->warn_weak_crypto = -1;
   2931  1.41  christos 	options->enable_escape_commandline = -1;
   2932  1.42  christos 	options->obscure_keystroke_timing_interval = -1;
   2933  1.42  christos 	options->tag = NULL;
   2934  1.44  christos 	options->channel_timeouts = NULL;
   2935  1.44  christos 	options->num_channel_timeouts = 0;
   2936  1.49  christos 	options->version_addendum = NULL;
   2937   1.2  christos 	options->none_switch = -1;
   2938   1.2  christos 	options->none_enabled = -1;
   2939   1.2  christos 	options->hpn_disabled = -1;
   2940   1.2  christos 	options->hpn_buffer_size = -1;
   2941   1.2  christos 	options->tcp_rcv_buf_poll = -1;
   2942   1.2  christos 	options->tcp_rcv_buf = -1;
   2943   1.7       tls 	options->send_version_first = -1;
   2944   1.1  christos }
   2945   1.1  christos 
   2946   1.1  christos /*
   2947  1.12  christos  * A petite version of fill_default_options() that just fills the options
   2948  1.12  christos  * needed for hostname canonicalization to proceed.
   2949  1.12  christos  */
   2950  1.12  christos void
   2951  1.12  christos fill_default_options_for_canonicalization(Options *options)
   2952  1.12  christos {
   2953  1.12  christos 	if (options->canonicalize_max_dots == -1)
   2954  1.12  christos 		options->canonicalize_max_dots = 1;
   2955  1.12  christos 	if (options->canonicalize_fallback_local == -1)
   2956  1.12  christos 		options->canonicalize_fallback_local = 1;
   2957  1.12  christos 	if (options->canonicalize_hostname == -1)
   2958  1.12  christos 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   2959  1.12  christos }
   2960  1.12  christos 
   2961  1.12  christos /*
   2962   1.1  christos  * Called after processing other sources of option data, this fills those
   2963   1.1  christos  * options for which no value has been specified with their default values.
   2964   1.1  christos  */
   2965  1.33  christos int
   2966   1.1  christos fill_default_options(Options * options)
   2967   1.1  christos {
   2968  1.27  christos 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
   2969  1.29  christos 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
   2970  1.33  christos 	int ret = 0, r;
   2971  1.25  christos 
   2972   1.1  christos 	if (options->forward_agent == -1)
   2973   1.1  christos 		options->forward_agent = 0;
   2974   1.1  christos 	if (options->forward_x11 == -1)
   2975   1.1  christos 		options->forward_x11 = 0;
   2976   1.1  christos 	if (options->forward_x11_trusted == -1)
   2977   1.1  christos 		options->forward_x11_trusted = 0;
   2978   1.4      adam 	if (options->forward_x11_timeout == -1)
   2979   1.4      adam 		options->forward_x11_timeout = 1200;
   2980  1.19  christos 	/*
   2981  1.19  christos 	 * stdio forwarding (-W) changes the default for these but we defer
   2982  1.19  christos 	 * setting the values so they can be overridden.
   2983  1.19  christos 	 */
   2984   1.1  christos 	if (options->exit_on_forward_failure == -1)
   2985  1.19  christos 		options->exit_on_forward_failure =
   2986  1.19  christos 		    options->stdio_forward_host != NULL ? 1 : 0;
   2987  1.19  christos 	if (options->clear_forwardings == -1)
   2988  1.19  christos 		options->clear_forwardings =
   2989  1.19  christos 		    options->stdio_forward_host != NULL ? 1 : 0;
   2990  1.19  christos 	if (options->clear_forwardings == 1)
   2991  1.19  christos 		clear_forwardings(options);
   2992  1.19  christos 
   2993   1.1  christos 	if (options->xauth_location == NULL)
   2994  1.33  christos 		options->xauth_location = xstrdup(_PATH_XAUTH);
   2995  1.12  christos 	if (options->fwd_opts.gateway_ports == -1)
   2996  1.12  christos 		options->fwd_opts.gateway_ports = 0;
   2997  1.12  christos 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
   2998  1.12  christos 		options->fwd_opts.streamlocal_bind_mask = 0177;
   2999  1.12  christos 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
   3000  1.12  christos 		options->fwd_opts.streamlocal_bind_unlink = 0;
   3001   1.1  christos 	if (options->pubkey_authentication == -1)
   3002  1.38  christos 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
   3003   1.2  christos #if defined(KRB4) || defined(KRB5)
   3004   1.2  christos 	if (options->kerberos_authentication == -1)
   3005   1.2  christos 		options->kerberos_authentication = 1;
   3006   1.2  christos #endif
   3007   1.2  christos #if defined(AFS) || defined(KRB5)
   3008   1.2  christos 	if (options->kerberos_tgt_passing == -1)
   3009   1.2  christos 		options->kerberos_tgt_passing = 1;
   3010   1.2  christos #endif
   3011   1.2  christos #ifdef AFS
   3012   1.2  christos 	if (options->afs_token_passing == -1)
   3013   1.2  christos 		options->afs_token_passing = 1;
   3014   1.2  christos #endif
   3015   1.1  christos 	if (options->gss_authentication == -1)
   3016   1.1  christos 		options->gss_authentication = 0;
   3017   1.1  christos 	if (options->gss_deleg_creds == -1)
   3018   1.1  christos 		options->gss_deleg_creds = 0;
   3019   1.1  christos 	if (options->password_authentication == -1)
   3020   1.1  christos 		options->password_authentication = 1;
   3021   1.1  christos 	if (options->kbd_interactive_authentication == -1)
   3022   1.1  christos 		options->kbd_interactive_authentication = 1;
   3023   1.1  christos 	if (options->hostbased_authentication == -1)
   3024   1.1  christos 		options->hostbased_authentication = 0;
   3025   1.1  christos 	if (options->batch_mode == -1)
   3026   1.1  christos 		options->batch_mode = 0;
   3027   1.1  christos 	if (options->check_host_ip == -1)
   3028  1.33  christos 		options->check_host_ip = 0;
   3029   1.1  christos 	if (options->strict_host_key_checking == -1)
   3030  1.22  christos 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
   3031   1.1  christos 	if (options->compression == -1)
   3032   1.1  christos 		options->compression = 0;
   3033   1.1  christos 	if (options->tcp_keep_alive == -1)
   3034   1.1  christos 		options->tcp_keep_alive = 1;
   3035   1.1  christos 	if (options->port == -1)
   3036   1.1  christos 		options->port = 0;	/* Filled in ssh_connect. */
   3037   1.1  christos 	if (options->address_family == -1)
   3038   1.1  christos 		options->address_family = AF_UNSPEC;
   3039   1.1  christos 	if (options->connection_attempts == -1)
   3040   1.1  christos 		options->connection_attempts = 1;
   3041   1.1  christos 	if (options->number_of_password_prompts == -1)
   3042   1.1  christos 		options->number_of_password_prompts = 3;
   3043   1.1  christos 	/* options->hostkeyalgorithms, default set in myproposals.h */
   3044  1.32  christos 	if (options->add_keys_to_agent == -1) {
   3045  1.18  christos 		options->add_keys_to_agent = 0;
   3046  1.32  christos 		options->add_keys_to_agent_lifespan = 0;
   3047  1.32  christos 	}
   3048   1.1  christos 	if (options->num_identity_files == 0) {
   3049  1.22  christos 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
   3050  1.22  christos 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
   3051  1.22  christos 		add_identity_file(options, "~/",
   3052  1.29  christos 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
   3053  1.29  christos 		add_identity_file(options, "~/",
   3054  1.22  christos 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
   3055  1.29  christos 		add_identity_file(options, "~/",
   3056  1.29  christos 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
   3057   1.1  christos 	}
   3058   1.1  christos 	if (options->escape_char == -1)
   3059   1.1  christos 		options->escape_char = '~';
   3060   1.6  christos 	if (options->num_system_hostfiles == 0) {
   3061   1.6  christos 		options->system_hostfiles[options->num_system_hostfiles++] =
   3062   1.6  christos 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
   3063   1.6  christos 		options->system_hostfiles[options->num_system_hostfiles++] =
   3064   1.6  christos 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
   3065   1.6  christos 	}
   3066  1.33  christos 	if (options->update_hostkeys == -1) {
   3067  1.33  christos 		if (options->verify_host_key_dns <= 0 &&
   3068  1.33  christos 		    (options->num_user_hostfiles == 0 ||
   3069  1.33  christos 		    (options->num_user_hostfiles == 1 && strcmp(options->
   3070  1.33  christos 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
   3071  1.33  christos 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
   3072  1.33  christos 		else
   3073  1.29  christos 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
   3074  1.33  christos 	}
   3075   1.6  christos 	if (options->num_user_hostfiles == 0) {
   3076   1.6  christos 		options->user_hostfiles[options->num_user_hostfiles++] =
   3077   1.6  christos 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
   3078   1.6  christos 		options->user_hostfiles[options->num_user_hostfiles++] =
   3079   1.6  christos 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
   3080   1.6  christos 	}
   3081   1.1  christos 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
   3082   1.1  christos 		options->log_level = SYSLOG_LEVEL_INFO;
   3083  1.22  christos 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
   3084  1.22  christos 		options->log_facility = SYSLOG_FACILITY_USER;
   3085   1.1  christos 	if (options->no_host_authentication_for_localhost == - 1)
   3086   1.1  christos 		options->no_host_authentication_for_localhost = 0;
   3087   1.1  christos 	if (options->identities_only == -1)
   3088   1.1  christos 		options->identities_only = 0;
   3089   1.1  christos 	if (options->enable_ssh_keysign == -1)
   3090   1.1  christos 		options->enable_ssh_keysign = 0;
   3091   1.1  christos 	if (options->rekey_limit == -1)
   3092   1.1  christos 		options->rekey_limit = 0;
   3093  1.11  christos 	if (options->rekey_interval == -1)
   3094  1.11  christos 		options->rekey_interval = 0;
   3095   1.1  christos 	if (options->verify_host_key_dns == -1)
   3096   1.1  christos 		options->verify_host_key_dns = 0;
   3097   1.1  christos 	if (options->server_alive_interval == -1)
   3098   1.1  christos 		options->server_alive_interval = 0;
   3099   1.1  christos 	if (options->server_alive_count_max == -1)
   3100   1.1  christos 		options->server_alive_count_max = 3;
   3101   1.2  christos 	if (options->none_switch == -1)
   3102   1.2  christos 	        options->none_switch = 0;
   3103   1.2  christos 	if (options->hpn_disabled == -1)
   3104   1.2  christos 	        options->hpn_disabled = 0;
   3105   1.2  christos 	if (options->hpn_buffer_size > -1)
   3106   1.2  christos 	{
   3107   1.2  christos 	  /* if a user tries to set the size to 0 set it to 1KB */
   3108   1.2  christos 		if (options->hpn_buffer_size == 0)
   3109  1.39   mlelstv 			options->hpn_buffer_size = 1;
   3110   1.2  christos 		/*limit the buffer to 64MB*/
   3111  1.39   mlelstv 		if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024))
   3112   1.2  christos 		{
   3113  1.39   mlelstv 			options->hpn_buffer_size = SSHBUF_SIZE_MAX;
   3114  1.39   mlelstv 			debug("User requested buffer larger than 256MB. Request reverted to 256MB");
   3115  1.39   mlelstv 		} else
   3116  1.39   mlelstv 			options->hpn_buffer_size *= 1024;
   3117   1.2  christos 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
   3118   1.2  christos 	}
   3119   1.2  christos 	if (options->tcp_rcv_buf == 0)
   3120   1.2  christos 		options->tcp_rcv_buf = 1;
   3121   1.2  christos 	if (options->tcp_rcv_buf > -1)
   3122   1.2  christos 		options->tcp_rcv_buf *=1024;
   3123   1.2  christos 	if (options->tcp_rcv_buf_poll == -1)
   3124   1.2  christos 		options->tcp_rcv_buf_poll = 1;
   3125   1.1  christos 	if (options->control_master == -1)
   3126   1.1  christos 		options->control_master = 0;
   3127   1.4      adam 	if (options->control_persist == -1) {
   3128   1.4      adam 		options->control_persist = 0;
   3129   1.4      adam 		options->control_persist_timeout = 0;
   3130   1.4      adam 	}
   3131   1.1  christos 	if (options->hash_known_hosts == -1)
   3132   1.1  christos 		options->hash_known_hosts = 0;
   3133   1.1  christos 	if (options->tun_open == -1)
   3134   1.1  christos 		options->tun_open = SSH_TUNMODE_NO;
   3135   1.1  christos 	if (options->tun_local == -1)
   3136   1.1  christos 		options->tun_local = SSH_TUNID_ANY;
   3137   1.1  christos 	if (options->tun_remote == -1)
   3138   1.1  christos 		options->tun_remote = SSH_TUNID_ANY;
   3139   1.1  christos 	if (options->permit_local_command == -1)
   3140   1.1  christos 		options->permit_local_command = 0;
   3141   1.1  christos 	if (options->visual_host_key == -1)
   3142   1.1  christos 		options->visual_host_key = 0;
   3143   1.5  christos 	if (options->ip_qos_interactive == -1)
   3144  1.50  christos 		options->ip_qos_interactive = IPTOS_DSCP_EF;
   3145   1.5  christos 	if (options->ip_qos_bulk == -1)
   3146  1.50  christos 		options->ip_qos_bulk = IPTOS_DSCP_CS0;
   3147   1.6  christos 	if (options->request_tty == -1)
   3148   1.6  christos 		options->request_tty = REQUEST_TTY_AUTO;
   3149  1.35  christos 	if (options->session_type == -1)
   3150  1.35  christos 		options->session_type = SESSION_TYPE_DEFAULT;
   3151  1.35  christos 	if (options->stdin_null == -1)
   3152  1.35  christos 		options->stdin_null = 0;
   3153  1.35  christos 	if (options->fork_after_authentication == -1)
   3154  1.35  christos 		options->fork_after_authentication = 0;
   3155  1.12  christos 	if (options->proxy_use_fdpass == -1)
   3156  1.12  christos 		options->proxy_use_fdpass = 0;
   3157  1.12  christos 	if (options->canonicalize_max_dots == -1)
   3158  1.12  christos 		options->canonicalize_max_dots = 1;
   3159  1.12  christos 	if (options->canonicalize_fallback_local == -1)
   3160  1.12  christos 		options->canonicalize_fallback_local = 1;
   3161  1.12  christos 	if (options->canonicalize_hostname == -1)
   3162  1.12  christos 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
   3163  1.13  christos 	if (options->fingerprint_hash == -1)
   3164  1.13  christos 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
   3165  1.29  christos 	if (options->sk_provider == NULL)
   3166  1.29  christos 		options->sk_provider = xstrdup("internal");
   3167  1.40  christos 	if (options->required_rsa_size == -1)
   3168  1.40  christos 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
   3169  1.50  christos 	if (options->warn_weak_crypto == -1)
   3170  1.50  christos 		options->warn_weak_crypto = 1;
   3171  1.41  christos 	if (options->enable_escape_commandline == -1)
   3172  1.41  christos 		options->enable_escape_commandline = 0;
   3173  1.42  christos 	if (options->obscure_keystroke_timing_interval == -1) {
   3174  1.42  christos 		options->obscure_keystroke_timing_interval =
   3175  1.42  christos 		    SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
   3176  1.42  christos 	}
   3177  1.25  christos 
   3178  1.25  christos 	/* Expand KEX name lists */
   3179  1.25  christos 	all_cipher = cipher_alg_list(',', 0);
   3180  1.25  christos 	all_mac = mac_alg_list(',');
   3181  1.25  christos 	all_kex = kex_alg_list(',');
   3182  1.25  christos 	all_key = sshkey_alg_list(0, 0, 1, ',');
   3183  1.27  christos 	all_sig = sshkey_alg_list(0, 1, 1, ',');
   3184  1.29  christos 	/* remove unsupported algos from default lists */
   3185  1.32  christos 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
   3186  1.32  christos 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
   3187  1.32  christos 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
   3188  1.32  christos 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
   3189  1.32  christos 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
   3190  1.25  christos #define ASSEMBLE(what, defaults, all) \
   3191  1.25  christos 	do { \
   3192  1.25  christos 		if ((r = kex_assemble_names(&options->what, \
   3193  1.33  christos 		    defaults, all)) != 0) { \
   3194  1.33  christos 			error_fr(r, "%s", #what); \
   3195  1.33  christos 			goto fail; \
   3196  1.33  christos 		} \
   3197  1.25  christos 	} while (0)
   3198  1.50  christos 	options->kex_algorithms_set = options->kex_algorithms != NULL;
   3199  1.29  christos 	ASSEMBLE(ciphers, def_cipher, all_cipher);
   3200  1.29  christos 	ASSEMBLE(macs, def_mac, all_mac);
   3201  1.29  christos 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
   3202  1.33  christos 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
   3203  1.33  christos 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
   3204  1.29  christos 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
   3205  1.25  christos #undef ASSEMBLE
   3206  1.13  christos 
   3207   1.7       tls 	if (options->send_version_first == -1)
   3208   1.7       tls 		options->send_version_first = 1;
   3209  1.12  christos #define CLEAR_ON_NONE(v) \
   3210  1.12  christos 	do { \
   3211  1.12  christos 		if (option_clear_or_none(v)) { \
   3212  1.12  christos 			free(v); \
   3213  1.12  christos 			v = NULL; \
   3214  1.12  christos 		} \
   3215  1.12  christos 	} while(0)
   3216  1.44  christos #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
   3217  1.44  christos 	do { \
   3218  1.44  christos 		if (options->nv == 1 && \
   3219  1.44  christos 		    strcasecmp(options->v[0], none) == 0) { \
   3220  1.44  christos 			free(options->v[0]); \
   3221  1.44  christos 			free(options->v); \
   3222  1.44  christos 			options->v = NULL; \
   3223  1.44  christos 			options->nv = 0; \
   3224  1.44  christos 		} \
   3225  1.44  christos 	} while (0)
   3226  1.12  christos 	CLEAR_ON_NONE(options->local_command);
   3227  1.22  christos 	CLEAR_ON_NONE(options->remote_command);
   3228  1.12  christos 	CLEAR_ON_NONE(options->proxy_command);
   3229  1.12  christos 	CLEAR_ON_NONE(options->control_path);
   3230  1.27  christos 	CLEAR_ON_NONE(options->pkcs11_provider);
   3231  1.29  christos 	CLEAR_ON_NONE(options->sk_provider);
   3232  1.33  christos 	CLEAR_ON_NONE(options->known_hosts_command);
   3233  1.44  christos 	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
   3234  1.51  christos 	CLEAR_ON_NONE_ARRAY(revoked_host_keys, num_revoked_host_keys, "none");
   3235  1.44  christos #undef CLEAR_ON_NONE
   3236  1.44  christos #undef CLEAR_ON_NONE_ARRAY
   3237  1.25  christos 	if (options->jump_host != NULL &&
   3238  1.25  christos 	    strcmp(options->jump_host, "none") == 0 &&
   3239  1.25  christos 	    options->jump_port == 0 && options->jump_user == NULL) {
   3240  1.25  christos 		free(options->jump_host);
   3241  1.25  christos 		options->jump_host = NULL;
   3242  1.25  christos 	}
   3243  1.37  christos 	if (options->num_permitted_cnames == 1 &&
   3244  1.37  christos 	    !config_has_permitted_cnames(options)) {
   3245  1.37  christos 		/* clean up CanonicalizePermittedCNAMEs=none */
   3246  1.37  christos 		free(options->permitted_cnames[0].source_list);
   3247  1.37  christos 		free(options->permitted_cnames[0].target_list);
   3248  1.37  christos 		memset(options->permitted_cnames, '\0',
   3249  1.37  christos 		    sizeof(*options->permitted_cnames));
   3250  1.37  christos 		options->num_permitted_cnames = 0;
   3251  1.37  christos 	}
   3252  1.19  christos 	/* options->identity_agent distinguishes NULL from 'none' */
   3253   1.1  christos 	/* options->user will be set in the main program if appropriate */
   3254   1.1  christos 	/* options->hostname will be set in the main program if appropriate */
   3255   1.1  christos 	/* options->host_key_alias should not be set by default */
   3256   1.1  christos 	/* options->preferred_authentications will be set in ssh */
   3257  1.33  christos 
   3258  1.33  christos 	/* success */
   3259  1.33  christos 	ret = 0;
   3260  1.33  christos  fail:
   3261  1.33  christos 	free(all_cipher);
   3262  1.33  christos 	free(all_mac);
   3263  1.33  christos 	free(all_kex);
   3264  1.33  christos 	free(all_key);
   3265  1.33  christos 	free(all_sig);
   3266  1.33  christos 	free(def_cipher);
   3267  1.33  christos 	free(def_mac);
   3268  1.33  christos 	free(def_kex);
   3269  1.33  christos 	free(def_key);
   3270  1.33  christos 	free(def_sig);
   3271  1.33  christos 	return ret;
   3272  1.33  christos }
   3273  1.33  christos 
   3274  1.33  christos void
   3275  1.33  christos free_options(Options *o)
   3276  1.33  christos {
   3277  1.33  christos 	int i;
   3278  1.33  christos 
   3279  1.33  christos 	if (o == NULL)
   3280  1.33  christos 		return;
   3281  1.33  christos 
   3282  1.33  christos #define FREE_ARRAY(type, n, a) \
   3283  1.33  christos 	do { \
   3284  1.33  christos 		type _i; \
   3285  1.33  christos 		for (_i = 0; _i < (n); _i++) \
   3286  1.33  christos 			free((a)[_i]); \
   3287  1.33  christos 	} while (0)
   3288  1.33  christos 
   3289  1.33  christos 	free(o->forward_agent_sock_path);
   3290  1.33  christos 	free(o->xauth_location);
   3291  1.33  christos 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
   3292  1.33  christos 	free(o->log_verbose);
   3293  1.33  christos 	free(o->ciphers);
   3294  1.33  christos 	free(o->macs);
   3295  1.33  christos 	free(o->hostkeyalgorithms);
   3296  1.33  christos 	free(o->kex_algorithms);
   3297  1.33  christos 	free(o->ca_sign_algorithms);
   3298  1.33  christos 	free(o->hostname);
   3299  1.33  christos 	free(o->host_key_alias);
   3300  1.33  christos 	free(o->proxy_command);
   3301  1.33  christos 	free(o->user);
   3302  1.33  christos 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
   3303  1.33  christos 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
   3304  1.33  christos 	free(o->preferred_authentications);
   3305  1.33  christos 	free(o->bind_address);
   3306  1.33  christos 	free(o->bind_interface);
   3307  1.33  christos 	free(o->pkcs11_provider);
   3308  1.33  christos 	free(o->sk_provider);
   3309  1.33  christos 	for (i = 0; i < o->num_identity_files; i++) {
   3310  1.33  christos 		free(o->identity_files[i]);
   3311  1.33  christos 		sshkey_free(o->identity_keys[i]);
   3312  1.33  christos 	}
   3313  1.33  christos 	for (i = 0; i < o->num_certificate_files; i++) {
   3314  1.33  christos 		free(o->certificate_files[i]);
   3315  1.33  christos 		sshkey_free(o->certificates[i]);
   3316  1.33  christos 	}
   3317  1.33  christos 	free(o->identity_agent);
   3318  1.33  christos 	for (i = 0; i < o->num_local_forwards; i++) {
   3319  1.33  christos 		free(o->local_forwards[i].listen_host);
   3320  1.33  christos 		free(o->local_forwards[i].listen_path);
   3321  1.33  christos 		free(o->local_forwards[i].connect_host);
   3322  1.33  christos 		free(o->local_forwards[i].connect_path);
   3323  1.33  christos 	}
   3324  1.33  christos 	free(o->local_forwards);
   3325  1.33  christos 	for (i = 0; i < o->num_remote_forwards; i++) {
   3326  1.33  christos 		free(o->remote_forwards[i].listen_host);
   3327  1.33  christos 		free(o->remote_forwards[i].listen_path);
   3328  1.33  christos 		free(o->remote_forwards[i].connect_host);
   3329  1.33  christos 		free(o->remote_forwards[i].connect_path);
   3330  1.33  christos 	}
   3331  1.33  christos 	free(o->remote_forwards);
   3332  1.33  christos 	free(o->stdio_forward_host);
   3333  1.40  christos 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
   3334  1.33  christos 	free(o->send_env);
   3335  1.40  christos 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
   3336  1.33  christos 	free(o->setenv);
   3337  1.33  christos 	free(o->control_path);
   3338  1.33  christos 	free(o->local_command);
   3339  1.33  christos 	free(o->remote_command);
   3340  1.33  christos 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
   3341  1.33  christos 	for (i = 0; i < o->num_permitted_cnames; i++) {
   3342  1.33  christos 		free(o->permitted_cnames[i].source_list);
   3343  1.33  christos 		free(o->permitted_cnames[i].target_list);
   3344  1.33  christos 	}
   3345  1.51  christos 	FREE_ARRAY(u_int, o->num_revoked_host_keys, o->revoked_host_keys);
   3346  1.33  christos 	free(o->revoked_host_keys);
   3347  1.33  christos 	free(o->hostbased_accepted_algos);
   3348  1.33  christos 	free(o->pubkey_accepted_algos);
   3349  1.33  christos 	free(o->jump_user);
   3350  1.33  christos 	free(o->jump_host);
   3351  1.33  christos 	free(o->jump_extra);
   3352  1.33  christos 	free(o->ignored_unknown);
   3353  1.33  christos 	explicit_bzero(o, sizeof(*o));
   3354  1.33  christos #undef FREE_ARRAY
   3355   1.1  christos }
   3356   1.1  christos 
   3357  1.12  christos struct fwdarg {
   3358  1.12  christos 	char *arg;
   3359  1.12  christos 	int ispath;
   3360  1.12  christos };
   3361  1.12  christos 
   3362  1.12  christos /*
   3363  1.12  christos  * parse_fwd_field
   3364  1.12  christos  * parses the next field in a port forwarding specification.
   3365  1.12  christos  * sets fwd to the parsed field and advances p past the colon
   3366  1.12  christos  * or sets it to NULL at end of string.
   3367  1.12  christos  * returns 0 on success, else non-zero.
   3368  1.12  christos  */
   3369  1.12  christos static int
   3370  1.12  christos parse_fwd_field(char **p, struct fwdarg *fwd)
   3371  1.12  christos {
   3372  1.12  christos 	char *ep, *cp = *p;
   3373  1.12  christos 	int ispath = 0;
   3374  1.12  christos 
   3375  1.12  christos 	if (*cp == '\0') {
   3376  1.12  christos 		*p = NULL;
   3377  1.12  christos 		return -1;	/* end of string */
   3378  1.12  christos 	}
   3379  1.12  christos 
   3380  1.12  christos 	/*
   3381  1.12  christos 	 * A field escaped with square brackets is used literally.
   3382  1.12  christos 	 * XXX - allow ']' to be escaped via backslash?
   3383  1.12  christos 	 */
   3384  1.12  christos 	if (*cp == '[') {
   3385  1.12  christos 		/* find matching ']' */
   3386  1.12  christos 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
   3387  1.12  christos 			if (*ep == '/')
   3388  1.12  christos 				ispath = 1;
   3389  1.12  christos 		}
   3390  1.12  christos 		/* no matching ']' or not at end of field. */
   3391  1.12  christos 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
   3392  1.12  christos 			return -1;
   3393  1.12  christos 		/* NUL terminate the field and advance p past the colon */
   3394  1.12  christos 		*ep++ = '\0';
   3395  1.12  christos 		if (*ep != '\0')
   3396  1.12  christos 			*ep++ = '\0';
   3397  1.12  christos 		fwd->arg = cp + 1;
   3398  1.12  christos 		fwd->ispath = ispath;
   3399  1.12  christos 		*p = ep;
   3400  1.12  christos 		return 0;
   3401  1.12  christos 	}
   3402  1.12  christos 
   3403  1.12  christos 	for (cp = *p; *cp != '\0'; cp++) {
   3404  1.12  christos 		switch (*cp) {
   3405  1.12  christos 		case '\\':
   3406  1.12  christos 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
   3407  1.14  christos 			if (*cp == '\0')
   3408  1.14  christos 				return -1;
   3409  1.12  christos 			break;
   3410  1.12  christos 		case '/':
   3411  1.12  christos 			ispath = 1;
   3412  1.12  christos 			break;
   3413  1.12  christos 		case ':':
   3414  1.12  christos 			*cp++ = '\0';
   3415  1.12  christos 			goto done;
   3416  1.12  christos 		}
   3417  1.12  christos 	}
   3418  1.12  christos done:
   3419  1.12  christos 	fwd->arg = *p;
   3420  1.12  christos 	fwd->ispath = ispath;
   3421  1.12  christos 	*p = cp;
   3422  1.12  christos 	return 0;
   3423  1.12  christos }
   3424  1.12  christos 
   3425   1.1  christos /*
   3426   1.1  christos  * parse_forward
   3427   1.1  christos  * parses a string containing a port forwarding specification of the form:
   3428   1.1  christos  *   dynamicfwd == 0
   3429  1.12  christos  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
   3430  1.12  christos  *	listenpath:connectpath
   3431   1.1  christos  *   dynamicfwd == 1
   3432   1.1  christos  *	[listenhost:]listenport
   3433   1.1  christos  * returns number of arguments parsed or zero on error
   3434   1.1  christos  */
   3435   1.1  christos int
   3436  1.12  christos parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
   3437   1.1  christos {
   3438  1.12  christos 	struct fwdarg fwdargs[4];
   3439  1.12  christos 	char *p, *cp;
   3440  1.32  christos 	int i, err;
   3441   1.1  christos 
   3442  1.12  christos 	memset(fwd, 0, sizeof(*fwd));
   3443  1.12  christos 	memset(fwdargs, 0, sizeof(fwdargs));
   3444   1.1  christos 
   3445  1.32  christos 	/*
   3446  1.32  christos 	 * We expand environment variables before checking if we think they're
   3447  1.32  christos 	 * paths so that if ${VAR} expands to a fully qualified path it is
   3448  1.32  christos 	 * treated as a path.
   3449  1.32  christos 	 */
   3450  1.32  christos 	cp = p = dollar_expand(&err, fwdspec);
   3451  1.32  christos 	if (p == NULL || err)
   3452  1.32  christos 		return 0;
   3453   1.1  christos 
   3454   1.1  christos 	/* skip leading spaces */
   3455  1.12  christos 	while (isspace((u_char)*cp))
   3456   1.1  christos 		cp++;
   3457   1.1  christos 
   3458  1.12  christos 	for (i = 0; i < 4; ++i) {
   3459  1.12  christos 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
   3460   1.1  christos 			break;
   3461  1.12  christos 	}
   3462   1.1  christos 
   3463   1.1  christos 	/* Check for trailing garbage */
   3464  1.12  christos 	if (cp != NULL && *cp != '\0') {
   3465   1.1  christos 		i = 0;	/* failure */
   3466  1.12  christos 	}
   3467   1.1  christos 
   3468   1.1  christos 	switch (i) {
   3469   1.1  christos 	case 1:
   3470  1.12  christos 		if (fwdargs[0].ispath) {
   3471  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   3472  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   3473  1.12  christos 		} else {
   3474  1.12  christos 			fwd->listen_host = NULL;
   3475  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   3476  1.12  christos 		}
   3477   1.1  christos 		fwd->connect_host = xstrdup("socks");
   3478   1.1  christos 		break;
   3479   1.1  christos 
   3480   1.1  christos 	case 2:
   3481  1.12  christos 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
   3482  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   3483  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   3484  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   3485  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   3486  1.12  christos 		} else if (fwdargs[1].ispath) {
   3487  1.12  christos 			fwd->listen_host = NULL;
   3488  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   3489  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[1].arg);
   3490  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   3491  1.12  christos 		} else {
   3492  1.12  christos 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   3493  1.12  christos 			fwd->listen_port = a2port(fwdargs[1].arg);
   3494  1.12  christos 			fwd->connect_host = xstrdup("socks");
   3495  1.12  christos 		}
   3496   1.1  christos 		break;
   3497   1.1  christos 
   3498   1.1  christos 	case 3:
   3499  1.12  christos 		if (fwdargs[0].ispath) {
   3500  1.12  christos 			fwd->listen_path = xstrdup(fwdargs[0].arg);
   3501  1.12  christos 			fwd->listen_port = PORT_STREAMLOCAL;
   3502  1.12  christos 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   3503  1.12  christos 			fwd->connect_port = a2port(fwdargs[2].arg);
   3504  1.12  christos 		} else if (fwdargs[2].ispath) {
   3505  1.12  christos 			fwd->listen_host = xstrdup(fwdargs[0].arg);
   3506  1.12  christos 			fwd->listen_port = a2port(fwdargs[1].arg);
   3507  1.12  christos 			fwd->connect_path = xstrdup(fwdargs[2].arg);
   3508  1.12  christos 			fwd->connect_port = PORT_STREAMLOCAL;
   3509  1.12  christos 		} else {
   3510  1.12  christos 			fwd->listen_host = NULL;
   3511  1.12  christos 			fwd->listen_port = a2port(fwdargs[0].arg);
   3512  1.12  christos 			fwd->connect_host = xstrdup(fwdargs[1].arg);
   3513  1.12  christos 			fwd->connect_port = a2port(fwdargs[2].arg);
   3514  1.12  christos 		}
   3515   1.1  christos 		break;
   3516   1.1  christos 
   3517   1.1  christos 	case 4:
   3518  1.12  christos 		fwd->listen_host = xstrdup(fwdargs[0].arg);
   3519  1.12  christos 		fwd->listen_port = a2port(fwdargs[1].arg);
   3520  1.12  christos 		fwd->connect_host = xstrdup(fwdargs[2].arg);
   3521  1.12  christos 		fwd->connect_port = a2port(fwdargs[3].arg);
   3522   1.1  christos 		break;
   3523   1.1  christos 	default:
   3524   1.1  christos 		i = 0; /* failure */
   3525   1.1  christos 	}
   3526   1.1  christos 
   3527  1.11  christos 	free(p);
   3528   1.1  christos 
   3529   1.1  christos 	if (dynamicfwd) {
   3530   1.1  christos 		if (!(i == 1 || i == 2))
   3531   1.1  christos 			goto fail_free;
   3532   1.1  christos 	} else {
   3533  1.12  christos 		if (!(i == 3 || i == 4)) {
   3534  1.12  christos 			if (fwd->connect_path == NULL &&
   3535  1.12  christos 			    fwd->listen_path == NULL)
   3536  1.12  christos 				goto fail_free;
   3537  1.12  christos 		}
   3538  1.12  christos 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
   3539   1.1  christos 			goto fail_free;
   3540   1.1  christos 	}
   3541   1.1  christos 
   3542  1.12  christos 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
   3543  1.12  christos 	    (!remotefwd && fwd->listen_port == 0))
   3544   1.1  christos 		goto fail_free;
   3545   1.1  christos 	if (fwd->connect_host != NULL &&
   3546   1.1  christos 	    strlen(fwd->connect_host) >= NI_MAXHOST)
   3547   1.1  christos 		goto fail_free;
   3548  1.35  christos 	/*
   3549  1.35  christos 	 * XXX - if connecting to a remote socket, max sun len may not
   3550  1.35  christos 	 * match this host
   3551  1.35  christos 	 */
   3552  1.12  christos 	if (fwd->connect_path != NULL &&
   3553  1.12  christos 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
   3554  1.12  christos 		goto fail_free;
   3555   1.1  christos 	if (fwd->listen_host != NULL &&
   3556   1.1  christos 	    strlen(fwd->listen_host) >= NI_MAXHOST)
   3557   1.1  christos 		goto fail_free;
   3558  1.12  christos 	if (fwd->listen_path != NULL &&
   3559  1.12  christos 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
   3560  1.12  christos 		goto fail_free;
   3561   1.1  christos 
   3562   1.1  christos 	return (i);
   3563   1.1  christos 
   3564   1.1  christos  fail_free:
   3565  1.11  christos 	free(fwd->connect_host);
   3566  1.11  christos 	fwd->connect_host = NULL;
   3567  1.12  christos 	free(fwd->connect_path);
   3568  1.12  christos 	fwd->connect_path = NULL;
   3569  1.11  christos 	free(fwd->listen_host);
   3570  1.11  christos 	fwd->listen_host = NULL;
   3571  1.12  christos 	free(fwd->listen_path);
   3572  1.12  christos 	fwd->listen_path = NULL;
   3573   1.1  christos 	return (0);
   3574   1.1  christos }
   3575  1.13  christos 
   3576  1.19  christos int
   3577  1.51  christos ssh_valid_hostname(const char *s)
   3578  1.19  christos {
   3579  1.51  christos 	size_t i;
   3580  1.51  christos 
   3581  1.51  christos 	if (*s == '-')
   3582  1.51  christos 		return 0;
   3583  1.51  christos 	for (i = 0; s[i] != 0; i++) {
   3584  1.51  christos 		if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL ||
   3585  1.51  christos 		    isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
   3586  1.51  christos 			return 0;
   3587  1.51  christos 	}
   3588  1.51  christos 	return 1;
   3589  1.51  christos }
   3590  1.19  christos 
   3591  1.51  christos int
   3592  1.51  christos ssh_valid_ruser(const char *s)
   3593  1.51  christos {
   3594  1.51  christos 	size_t i;
   3595  1.51  christos 
   3596  1.51  christos 	if (*s == '-')
   3597  1.51  christos 		return 0;
   3598  1.51  christos 	for (i = 0; s[i] != 0; i++) {
   3599  1.51  christos 		if (iscntrl((u_char)s[i]))
   3600  1.51  christos 			return 0;
   3601  1.51  christos 		if (strchr("'`\";&<>|(){}", s[i]) != NULL)
   3602  1.51  christos 			return 0;
   3603  1.51  christos 		/* Disallow '-' after whitespace */
   3604  1.51  christos 		if (isspace((u_char)s[i]) && s[i + 1] == '-')
   3605  1.51  christos 			return 0;
   3606  1.51  christos 		/* Disallow \ in last position */
   3607  1.51  christos 		if (s[i] == '\\' && s[i + 1] == '\0')
   3608  1.51  christos 			return 0;
   3609  1.51  christos 	}
   3610  1.51  christos 	return 1;
   3611  1.51  christos }
   3612  1.19  christos 
   3613  1.51  christos int
   3614  1.51  christos parse_jump(const char *s, Options *o, int strict, int active)
   3615  1.51  christos {
   3616  1.51  christos 	char *orig = NULL, *sdup = NULL, *cp;
   3617  1.51  christos 	char *tmp_user = NULL, *tmp_host = NULL, *host = NULL, *user = NULL;
   3618  1.51  christos 	int r, ret = -1, tmp_port = -1, port = -1, first = 1;
   3619  1.35  christos 
   3620  1.51  christos 	if (strcasecmp(s, "none") == 0) {
   3621  1.51  christos 		if (active && o->jump_host == NULL) {
   3622  1.51  christos 			o->jump_host = xstrdup("none");
   3623  1.51  christos 			o->jump_port = 0;
   3624  1.51  christos 		}
   3625  1.51  christos 		return 0;
   3626  1.51  christos 	}
   3627  1.51  christos 
   3628  1.51  christos 	orig = xstrdup(s);
   3629  1.35  christos 	if ((cp = strchr(orig, '#')) != NULL)
   3630  1.35  christos 		*cp = '\0';
   3631  1.35  christos 	rtrim(orig);
   3632  1.35  christos 
   3633  1.51  christos 	active &= o->proxy_command == NULL && o->jump_host == NULL;
   3634  1.51  christos 	sdup = xstrdup(orig);
   3635  1.19  christos 	do {
   3636  1.51  christos 		/* Work backwards through string */
   3637  1.19  christos 		if ((cp = strrchr(sdup, ',')) == NULL)
   3638  1.19  christos 			cp = sdup; /* last */
   3639  1.19  christos 		else
   3640  1.19  christos 			*cp++ = '\0';
   3641  1.19  christos 
   3642  1.51  christos 		r = parse_ssh_uri(cp, &tmp_user, &tmp_host, &tmp_port);
   3643  1.51  christos 		if (r == -1 || (r == 1 && parse_user_host_port(cp,
   3644  1.51  christos 		    &tmp_user, &tmp_host, &tmp_port) != 0))
   3645  1.51  christos 			goto out; /* error already logged */
   3646  1.51  christos 		if (strict) {
   3647  1.51  christos 			if (!ssh_valid_hostname(tmp_host)) {
   3648  1.51  christos 				error_f("invalid hostname \"%s\"", tmp_host);
   3649  1.19  christos 				goto out;
   3650  1.51  christos 			}
   3651  1.51  christos 			if (tmp_user != NULL && !ssh_valid_ruser(tmp_user)) {
   3652  1.51  christos 				error_f("invalid username \"%s\"", tmp_user);
   3653  1.19  christos 				goto out;
   3654  1.51  christos 			}
   3655  1.51  christos 		}
   3656  1.51  christos 		if (first) {
   3657  1.51  christos 			user = tmp_user;
   3658  1.51  christos 			host = tmp_host;
   3659  1.51  christos 			port = tmp_port;
   3660  1.51  christos 			tmp_user = tmp_host = NULL; /* transferred */
   3661  1.19  christos 		}
   3662  1.19  christos 		first = 0; /* only check syntax for subsequent hosts */
   3663  1.51  christos 		free(tmp_user);
   3664  1.51  christos 		free(tmp_host);
   3665  1.51  christos 		tmp_user = tmp_host = NULL;
   3666  1.51  christos 		tmp_port = -1;
   3667  1.19  christos 	} while (cp != sdup);
   3668  1.51  christos 
   3669  1.19  christos 	/* success */
   3670  1.19  christos 	if (active) {
   3671  1.51  christos 		o->jump_user = user;
   3672  1.51  christos 		o->jump_host = host;
   3673  1.51  christos 		o->jump_port = port;
   3674  1.51  christos 		o->proxy_command = xstrdup("none");
   3675  1.51  christos 		user = host = NULL; /* transferred */
   3676  1.51  christos 		if (orig != NULL && (cp = strrchr(orig, ',')) != NULL) {
   3677  1.51  christos 			o->jump_extra = xstrdup(orig);
   3678  1.51  christos 			o->jump_extra[cp - orig] = '\0';
   3679  1.19  christos 		}
   3680  1.19  christos 	}
   3681  1.19  christos 	ret = 0;
   3682  1.19  christos  out:
   3683  1.19  christos 	free(orig);
   3684  1.51  christos 	free(sdup);
   3685  1.51  christos 	free(tmp_user);
   3686  1.51  christos 	free(tmp_host);
   3687  1.19  christos 	free(user);
   3688  1.19  christos 	free(host);
   3689  1.19  christos 	return ret;
   3690  1.19  christos }
   3691  1.19  christos 
   3692  1.23  christos int
   3693  1.23  christos parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
   3694  1.23  christos {
   3695  1.33  christos 	char *user = NULL, *host = NULL, *path = NULL;
   3696  1.33  christos 	int r, port;
   3697  1.23  christos 
   3698  1.33  christos 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
   3699  1.23  christos 	if (r == 0 && path != NULL)
   3700  1.23  christos 		r = -1;		/* path not allowed */
   3701  1.33  christos 	if (r == 0) {
   3702  1.33  christos 		if (userp != NULL) {
   3703  1.33  christos 			*userp = user;
   3704  1.33  christos 			user = NULL;
   3705  1.33  christos 		}
   3706  1.33  christos 		if (hostp != NULL) {
   3707  1.33  christos 			*hostp = host;
   3708  1.33  christos 			host = NULL;
   3709  1.33  christos 		}
   3710  1.33  christos 		if (portp != NULL)
   3711  1.33  christos 			*portp = port;
   3712  1.33  christos 	}
   3713  1.33  christos 	free(user);
   3714  1.33  christos 	free(host);
   3715  1.33  christos 	free(path);
   3716  1.23  christos 	return r;
   3717  1.23  christos }
   3718  1.23  christos 
   3719  1.46  christos /* XXX the following is a near-verbatim copy from servconf.c; refactor */
   3720  1.13  christos static const char *
   3721  1.13  christos fmt_multistate_int(int val, const struct multistate *m)
   3722  1.13  christos {
   3723  1.13  christos 	u_int i;
   3724  1.13  christos 
   3725  1.13  christos 	for (i = 0; m[i].key != NULL; i++) {
   3726  1.13  christos 		if (m[i].value == val)
   3727  1.13  christos 			return m[i].key;
   3728  1.13  christos 	}
   3729  1.13  christos 	return "UNKNOWN";
   3730  1.13  christos }
   3731  1.13  christos 
   3732  1.13  christos static const char *
   3733  1.13  christos fmt_intarg(OpCodes code, int val)
   3734  1.13  christos {
   3735  1.13  christos 	if (val == -1)
   3736  1.13  christos 		return "unset";
   3737  1.13  christos 	switch (code) {
   3738  1.13  christos 	case oAddressFamily:
   3739  1.13  christos 		return fmt_multistate_int(val, multistate_addressfamily);
   3740  1.49  christos 	case oCompression:
   3741  1.49  christos 		return fmt_multistate_int(val, multistate_compression);
   3742  1.13  christos 	case oVerifyHostKeyDNS:
   3743  1.13  christos 	case oUpdateHostkeys:
   3744  1.13  christos 		return fmt_multistate_int(val, multistate_yesnoask);
   3745  1.22  christos 	case oStrictHostKeyChecking:
   3746  1.22  christos 		return fmt_multistate_int(val, multistate_strict_hostkey);
   3747  1.13  christos 	case oControlMaster:
   3748  1.13  christos 		return fmt_multistate_int(val, multistate_controlmaster);
   3749  1.13  christos 	case oTunnel:
   3750  1.13  christos 		return fmt_multistate_int(val, multistate_tunnel);
   3751  1.13  christos 	case oRequestTTY:
   3752  1.13  christos 		return fmt_multistate_int(val, multistate_requesttty);
   3753  1.35  christos 	case oSessionType:
   3754  1.35  christos 		return fmt_multistate_int(val, multistate_sessiontype);
   3755  1.13  christos 	case oCanonicalizeHostname:
   3756  1.13  christos 		return fmt_multistate_int(val, multistate_canonicalizehostname);
   3757  1.25  christos 	case oAddKeysToAgent:
   3758  1.25  christos 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
   3759  1.38  christos 	case oPubkeyAuthentication:
   3760  1.38  christos 		return fmt_multistate_int(val, multistate_pubkey_auth);
   3761  1.13  christos 	case oFingerprintHash:
   3762  1.13  christos 		return ssh_digest_alg_name(val);
   3763  1.13  christos 	default:
   3764  1.13  christos 		switch (val) {
   3765  1.13  christos 		case 0:
   3766  1.13  christos 			return "no";
   3767  1.13  christos 		case 1:
   3768  1.13  christos 			return "yes";
   3769  1.13  christos 		default:
   3770  1.13  christos 			return "UNKNOWN";
   3771  1.13  christos 		}
   3772  1.13  christos 	}
   3773  1.13  christos }
   3774  1.13  christos 
   3775  1.13  christos static const char *
   3776  1.13  christos lookup_opcode_name(OpCodes code)
   3777  1.13  christos {
   3778  1.13  christos 	u_int i;
   3779  1.13  christos 
   3780  1.13  christos 	for (i = 0; keywords[i].name != NULL; i++)
   3781  1.13  christos 		if (keywords[i].opcode == code)
   3782  1.13  christos 			return(keywords[i].name);
   3783  1.13  christos 	return "UNKNOWN";
   3784  1.13  christos }
   3785  1.13  christos 
   3786  1.13  christos static void
   3787  1.13  christos dump_cfg_int(OpCodes code, int val)
   3788  1.13  christos {
   3789  1.42  christos 	if (code == oObscureKeystrokeTiming) {
   3790  1.42  christos 		if (val == 0) {
   3791  1.42  christos 			printf("%s no\n", lookup_opcode_name(code));
   3792  1.42  christos 			return;
   3793  1.42  christos 		} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
   3794  1.42  christos 			printf("%s yes\n", lookup_opcode_name(code));
   3795  1.42  christos 			return;
   3796  1.42  christos 		}
   3797  1.42  christos 		/* FALLTHROUGH */
   3798  1.42  christos 	}
   3799  1.13  christos 	printf("%s %d\n", lookup_opcode_name(code), val);
   3800  1.13  christos }
   3801  1.13  christos 
   3802  1.13  christos static void
   3803  1.13  christos dump_cfg_fmtint(OpCodes code, int val)
   3804  1.13  christos {
   3805  1.13  christos 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
   3806  1.13  christos }
   3807  1.13  christos 
   3808  1.13  christos static void
   3809  1.13  christos dump_cfg_string(OpCodes code, const char *val)
   3810  1.13  christos {
   3811  1.13  christos 	if (val == NULL)
   3812  1.13  christos 		return;
   3813  1.13  christos 	printf("%s %s\n", lookup_opcode_name(code), val);
   3814  1.13  christos }
   3815  1.13  christos 
   3816  1.13  christos static void
   3817  1.13  christos dump_cfg_strarray(OpCodes code, u_int count, char **vals)
   3818  1.13  christos {
   3819  1.13  christos 	u_int i;
   3820  1.13  christos 
   3821  1.13  christos 	for (i = 0; i < count; i++)
   3822  1.13  christos 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
   3823  1.13  christos }
   3824  1.13  christos 
   3825  1.13  christos static void
   3826  1.13  christos dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
   3827  1.13  christos {
   3828  1.13  christos 	u_int i;
   3829  1.13  christos 
   3830  1.13  christos 	printf("%s", lookup_opcode_name(code));
   3831  1.35  christos 	if (count == 0)
   3832  1.35  christos 		printf(" none");
   3833  1.13  christos 	for (i = 0; i < count; i++)
   3834  1.13  christos 		printf(" %s",  vals[i]);
   3835  1.13  christos 	printf("\n");
   3836  1.13  christos }
   3837  1.13  christos 
   3838  1.13  christos static void
   3839  1.13  christos dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
   3840  1.13  christos {
   3841  1.13  christos 	const struct Forward *fwd;
   3842  1.13  christos 	u_int i;
   3843  1.13  christos 
   3844  1.13  christos 	/* oDynamicForward */
   3845  1.13  christos 	for (i = 0; i < count; i++) {
   3846  1.13  christos 		fwd = &fwds[i];
   3847  1.21  christos 		if (code == oDynamicForward && fwd->connect_host != NULL &&
   3848  1.13  christos 		    strcmp(fwd->connect_host, "socks") != 0)
   3849  1.13  christos 			continue;
   3850  1.21  christos 		if (code == oLocalForward && fwd->connect_host != NULL &&
   3851  1.13  christos 		    strcmp(fwd->connect_host, "socks") == 0)
   3852  1.13  christos 			continue;
   3853  1.13  christos 		printf("%s", lookup_opcode_name(code));
   3854  1.13  christos 		if (fwd->listen_port == PORT_STREAMLOCAL)
   3855  1.13  christos 			printf(" %s", fwd->listen_path);
   3856  1.13  christos 		else if (fwd->listen_host == NULL)
   3857  1.13  christos 			printf(" %d", fwd->listen_port);
   3858  1.13  christos 		else {
   3859  1.13  christos 			printf(" [%s]:%d",
   3860  1.13  christos 			    fwd->listen_host, fwd->listen_port);
   3861  1.13  christos 		}
   3862  1.13  christos 		if (code != oDynamicForward) {
   3863  1.13  christos 			if (fwd->connect_port == PORT_STREAMLOCAL)
   3864  1.13  christos 				printf(" %s", fwd->connect_path);
   3865  1.13  christos 			else if (fwd->connect_host == NULL)
   3866  1.13  christos 				printf(" %d", fwd->connect_port);
   3867  1.13  christos 			else {
   3868  1.13  christos 				printf(" [%s]:%d",
   3869  1.13  christos 				    fwd->connect_host, fwd->connect_port);
   3870  1.13  christos 			}
   3871  1.13  christos 		}
   3872  1.13  christos 		printf("\n");
   3873  1.13  christos 	}
   3874  1.13  christos }
   3875  1.13  christos 
   3876  1.13  christos void
   3877  1.13  christos dump_client_config(Options *o, const char *host)
   3878  1.13  christos {
   3879  1.29  christos 	int i, r;
   3880  1.25  christos 	char buf[8], *all_key;
   3881  1.13  christos 
   3882  1.29  christos 	/*
   3883  1.29  christos 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
   3884  1.29  christos 	 * fill_default_options() like the other algorithm lists because
   3885  1.29  christos 	 * the host key algorithms are by default dynamically chosen based
   3886  1.29  christos 	 * on the host's keys found in known_hosts.
   3887  1.29  christos 	 */
   3888  1.25  christos 	all_key = sshkey_alg_list(0, 0, 1, ',');
   3889  1.29  christos 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
   3890  1.29  christos 	    all_key)) != 0)
   3891  1.33  christos 		fatal_fr(r, "expand HostKeyAlgorithms");
   3892  1.25  christos 	free(all_key);
   3893  1.18  christos 
   3894  1.13  christos 	/* Most interesting options first: user, host, port */
   3895  1.41  christos 	dump_cfg_string(oHost, o->host_arg);
   3896  1.13  christos 	dump_cfg_string(oUser, o->user);
   3897  1.28  christos 	dump_cfg_string(oHostname, host);
   3898  1.13  christos 	dump_cfg_int(oPort, o->port);
   3899  1.13  christos 
   3900  1.13  christos 	/* Flag options */
   3901  1.13  christos 	dump_cfg_fmtint(oAddressFamily, o->address_family);
   3902  1.13  christos 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
   3903  1.13  christos 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
   3904  1.13  christos 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
   3905  1.13  christos 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
   3906  1.13  christos 	dump_cfg_fmtint(oCompression, o->compression);
   3907  1.13  christos 	dump_cfg_fmtint(oControlMaster, o->control_master);
   3908  1.13  christos 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
   3909  1.19  christos 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
   3910  1.13  christos 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
   3911  1.13  christos 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
   3912  1.13  christos 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
   3913  1.13  christos 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
   3914  1.13  christos 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
   3915  1.13  christos #ifdef GSSAPI
   3916  1.13  christos 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
   3917  1.13  christos 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
   3918  1.13  christos #endif /* GSSAPI */
   3919  1.13  christos 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
   3920  1.13  christos 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
   3921  1.13  christos 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
   3922  1.13  christos 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
   3923  1.13  christos 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
   3924  1.13  christos 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
   3925  1.13  christos 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
   3926  1.13  christos 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
   3927  1.13  christos 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
   3928  1.13  christos 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
   3929  1.35  christos 	dump_cfg_fmtint(oSessionType, o->session_type);
   3930  1.35  christos 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
   3931  1.35  christos 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
   3932  1.13  christos 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
   3933  1.13  christos 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
   3934  1.13  christos 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
   3935  1.13  christos 	dump_cfg_fmtint(oTunnel, o->tun_open);
   3936  1.13  christos 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
   3937  1.13  christos 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
   3938  1.13  christos 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
   3939  1.41  christos 	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
   3940  1.50  christos 	dump_cfg_fmtint(oWarnWeakCrypto, o->warn_weak_crypto);
   3941  1.13  christos 
   3942  1.13  christos 	/* Integer options */
   3943  1.13  christos 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
   3944  1.13  christos 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
   3945  1.13  christos 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
   3946  1.13  christos 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
   3947  1.13  christos 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
   3948  1.13  christos 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
   3949  1.40  christos 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
   3950  1.42  christos 	dump_cfg_int(oObscureKeystrokeTiming,
   3951  1.42  christos 	    o->obscure_keystroke_timing_interval);
   3952  1.13  christos 
   3953  1.13  christos 	/* String options */
   3954  1.13  christos 	dump_cfg_string(oBindAddress, o->bind_address);
   3955  1.23  christos 	dump_cfg_string(oBindInterface, o->bind_interface);
   3956  1.29  christos 	dump_cfg_string(oCiphers, o->ciphers);
   3957  1.13  christos 	dump_cfg_string(oControlPath, o->control_path);
   3958  1.18  christos 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
   3959  1.13  christos 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
   3960  1.33  christos 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
   3961  1.19  christos 	dump_cfg_string(oIdentityAgent, o->identity_agent);
   3962  1.25  christos 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
   3963  1.13  christos 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
   3964  1.29  christos 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
   3965  1.29  christos 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
   3966  1.13  christos 	dump_cfg_string(oLocalCommand, o->local_command);
   3967  1.22  christos 	dump_cfg_string(oRemoteCommand, o->remote_command);
   3968  1.13  christos 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
   3969  1.29  christos 	dump_cfg_string(oMacs, o->macs);
   3970  1.21  christos #ifdef ENABLE_PKCS11
   3971  1.13  christos 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
   3972  1.21  christos #endif
   3973  1.29  christos 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
   3974  1.13  christos 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
   3975  1.33  christos 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
   3976  1.13  christos 	dump_cfg_string(oXAuthLocation, o->xauth_location);
   3977  1.33  christos 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
   3978  1.42  christos 	dump_cfg_string(oTag, o->tag);
   3979  1.49  christos 	dump_cfg_string(oVersionAddendum, o->version_addendum);
   3980  1.13  christos 
   3981  1.13  christos 	/* Forwards */
   3982  1.13  christos 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
   3983  1.13  christos 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
   3984  1.13  christos 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
   3985  1.13  christos 
   3986  1.13  christos 	/* String array options */
   3987  1.13  christos 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
   3988  1.13  christos 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
   3989  1.25  christos 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
   3990  1.13  christos 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
   3991  1.13  christos 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
   3992  1.51  christos 	dump_cfg_strarray_oneline(oRevokedHostKeys, o->num_revoked_host_keys, o->revoked_host_keys);
   3993  1.13  christos 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
   3994  1.25  christos 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
   3995  1.33  christos 	dump_cfg_strarray_oneline(oLogVerbose,
   3996  1.33  christos 	    o->num_log_verbose, o->log_verbose);
   3997  1.44  christos 	dump_cfg_strarray_oneline(oChannelTimeout,
   3998  1.44  christos 	    o->num_channel_timeouts, o->channel_timeouts);
   3999  1.13  christos 
   4000  1.13  christos 	/* Special cases */
   4001  1.13  christos 
   4002  1.33  christos 	/* PermitRemoteOpen */
   4003  1.33  christos 	if (o->num_permitted_remote_opens == 0)
   4004  1.33  christos 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
   4005  1.33  christos 	else
   4006  1.33  christos 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
   4007  1.33  christos 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
   4008  1.33  christos 
   4009  1.32  christos 	/* AddKeysToAgent */
   4010  1.32  christos 	if (o->add_keys_to_agent_lifespan <= 0)
   4011  1.32  christos 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
   4012  1.32  christos 	else {
   4013  1.32  christos 		printf("addkeystoagent%s %d\n",
   4014  1.32  christos 		    o->add_keys_to_agent == 3 ? " confirm" : "",
   4015  1.32  christos 		    o->add_keys_to_agent_lifespan);
   4016  1.32  christos 	}
   4017  1.32  christos 
   4018  1.29  christos 	/* oForwardAgent */
   4019  1.29  christos 	if (o->forward_agent_sock_path == NULL)
   4020  1.29  christos 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
   4021  1.29  christos 	else
   4022  1.29  christos 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
   4023  1.29  christos 
   4024  1.13  christos 	/* oConnectTimeout */
   4025  1.13  christos 	if (o->connection_timeout == -1)
   4026  1.13  christos 		printf("connecttimeout none\n");
   4027  1.13  christos 	else
   4028  1.13  christos 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
   4029  1.13  christos 
   4030  1.13  christos 	/* oTunnelDevice */
   4031  1.13  christos 	printf("tunneldevice");
   4032  1.13  christos 	if (o->tun_local == SSH_TUNID_ANY)
   4033  1.13  christos 		printf(" any");
   4034  1.13  christos 	else
   4035  1.13  christos 		printf(" %d", o->tun_local);
   4036  1.13  christos 	if (o->tun_remote == SSH_TUNID_ANY)
   4037  1.13  christos 		printf(":any");
   4038  1.13  christos 	else
   4039  1.13  christos 		printf(":%d", o->tun_remote);
   4040  1.13  christos 	printf("\n");
   4041  1.13  christos 
   4042  1.13  christos 	/* oCanonicalizePermittedCNAMEs */
   4043  1.37  christos 	printf("canonicalizePermittedcnames");
   4044  1.37  christos 	if (o->num_permitted_cnames == 0)
   4045  1.37  christos 		printf(" none");
   4046  1.37  christos 	for (i = 0; i < o->num_permitted_cnames; i++) {
   4047  1.37  christos 		printf(" %s:%s", o->permitted_cnames[i].source_list,
   4048  1.37  christos 		    o->permitted_cnames[i].target_list);
   4049  1.13  christos 	}
   4050  1.37  christos 	printf("\n");
   4051  1.13  christos 
   4052  1.13  christos 	/* oControlPersist */
   4053  1.13  christos 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
   4054  1.13  christos 		dump_cfg_fmtint(oControlPersist, o->control_persist);
   4055  1.13  christos 	else
   4056  1.13  christos 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
   4057  1.13  christos 
   4058  1.13  christos 	/* oEscapeChar */
   4059  1.13  christos 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
   4060  1.13  christos 		printf("escapechar none\n");
   4061  1.13  christos 	else {
   4062  1.19  christos 		vis(buf, o->escape_char, VIS_WHITE, 0);
   4063  1.19  christos 		printf("escapechar %s\n", buf);
   4064  1.13  christos 	}
   4065  1.13  christos 
   4066  1.13  christos 	/* oIPQoS */
   4067  1.13  christos 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
   4068  1.13  christos 	printf("%s\n", iptos2str(o->ip_qos_bulk));
   4069  1.13  christos 
   4070  1.13  christos 	/* oRekeyLimit */
   4071  1.18  christos 	printf("rekeylimit %llu %d\n",
   4072  1.18  christos 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
   4073  1.13  christos 
   4074  1.13  christos 	/* oStreamLocalBindMask */
   4075  1.13  christos 	printf("streamlocalbindmask 0%o\n",
   4076  1.13  christos 	    o->fwd_opts.streamlocal_bind_mask);
   4077  1.19  christos 
   4078  1.25  christos 	/* oLogFacility */
   4079  1.25  christos 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
   4080  1.25  christos 
   4081  1.19  christos 	/* oProxyCommand / oProxyJump */
   4082  1.19  christos 	if (o->jump_host == NULL)
   4083  1.19  christos 		dump_cfg_string(oProxyCommand, o->proxy_command);
   4084  1.19  christos 	else {
   4085  1.19  christos 		/* Check for numeric addresses */
   4086  1.19  christos 		i = strchr(o->jump_host, ':') != NULL ||
   4087  1.19  christos 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
   4088  1.19  christos 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
   4089  1.19  christos 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
   4090  1.19  christos 		    /* optional additional jump spec */
   4091  1.19  christos 		    o->jump_extra == NULL ? "" : o->jump_extra,
   4092  1.19  christos 		    o->jump_extra == NULL ? "" : ",",
   4093  1.19  christos 		    /* optional user */
   4094  1.19  christos 		    o->jump_user == NULL ? "" : o->jump_user,
   4095  1.19  christos 		    o->jump_user == NULL ? "" : "@",
   4096  1.19  christos 		    /* opening [ if hostname is numeric */
   4097  1.19  christos 		    i ? "[" : "",
   4098  1.19  christos 		    /* mandatory hostname */
   4099  1.19  christos 		    o->jump_host,
   4100  1.19  christos 		    /* closing ] if hostname is numeric */
   4101  1.19  christos 		    i ? "]" : "",
   4102  1.19  christos 		    /* optional port number */
   4103  1.19  christos 		    o->jump_port <= 0 ? "" : ":",
   4104  1.19  christos 		    o->jump_port <= 0 ? "" : buf);
   4105  1.19  christos 	}
   4106  1.13  christos }
   4107