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