1296853Sdes/* $OpenBSD: readconf.c,v 1.250 2016/02/08 23:40:12 djm Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 657429Smarkm * Functions for reading the configuration files. 760576Skris * 865674Skris * As far as I am concerned, the code I have written for this software 965674Skris * can be used freely for any purpose. Any derived versions of this 1065674Skris * software must be clearly marked as such, and if the derived work is 1165674Skris * incompatible with the protocol description in the RFC file, it must be 1265674Skris * called by a name other than "ssh" or "Secure Shell". 1357429Smarkm */ 1457429Smarkm 1557429Smarkm#include "includes.h" 16162856Sdes__RCSID("$FreeBSD: releng/10.3/crypto/openssh/readconf.c 296853 2016-03-14 13:05:13Z des $"); 1757429Smarkm 18162856Sdes#include <sys/types.h> 19162856Sdes#include <sys/stat.h> 20162856Sdes#include <sys/socket.h> 21181918Sdes#include <sys/sysctl.h> 22262566Sdes#include <sys/wait.h> 23295367Sdes#include <sys/un.h> 24162856Sdes 25162856Sdes#include <netinet/in.h> 26221420Sdes#include <netinet/in_systm.h> 27221420Sdes#include <netinet/ip.h> 28264377Sdes#include <arpa/inet.h> 29162856Sdes 30162856Sdes#include <ctype.h> 31162856Sdes#include <errno.h> 32262566Sdes#include <fcntl.h> 33295367Sdes#include <limits.h> 34162856Sdes#include <netdb.h> 35262566Sdes#ifdef HAVE_PATHS_H 36262566Sdes# include <paths.h> 37262566Sdes#endif 38262566Sdes#include <pwd.h> 39162856Sdes#include <signal.h> 40162856Sdes#include <stdarg.h> 41162856Sdes#include <stdio.h> 42162856Sdes#include <string.h> 43162856Sdes#include <unistd.h> 44255767Sdes#ifdef HAVE_UTIL_H 45255767Sdes#include <util.h> 46255767Sdes#endif 47295367Sdes#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 48295367Sdes# include <vis.h> 49295367Sdes#endif 50162856Sdes 51162856Sdes#include "xmalloc.h" 5257429Smarkm#include "ssh.h" 5376262Sgreen#include "compat.h" 5476262Sgreen#include "cipher.h" 5576262Sgreen#include "pathnames.h" 5676262Sgreen#include "log.h" 57295367Sdes#include "sshkey.h" 58295367Sdes#include "misc.h" 5957429Smarkm#include "readconf.h" 6060576Skris#include "match.h" 6176262Sgreen#include "kex.h" 6276262Sgreen#include "mac.h" 63262566Sdes#include "uidswap.h" 64295367Sdes#include "myproposal.h" 65295367Sdes#include "digest.h" 66192595Sdes#include "version.h" 6757429Smarkm 6857429Smarkm/* Format of the configuration file: 6957429Smarkm 7057429Smarkm # Configuration data is parsed as follows: 7157429Smarkm # 1. command line options 7257429Smarkm # 2. user-specific file 7357429Smarkm # 3. system-wide file 7457429Smarkm # Any configuration value is only changed the first time it is set. 7557429Smarkm # Thus, host-specific definitions should be at the beginning of the 7657429Smarkm # configuration file, and defaults at the end. 7757429Smarkm 7857429Smarkm # Host-specific declarations. These may override anything above. A single 7957429Smarkm # host may match multiple declarations; these are processed in the order 8057429Smarkm # that they are given in. 8157429Smarkm 8257429Smarkm Host *.ngs.fi ngs.fi 8398684Sdes User foo 8457429Smarkm 8557429Smarkm Host fake.com 8657429Smarkm HostName another.host.name.real.org 8757429Smarkm User blaah 8857429Smarkm Port 34289 8957429Smarkm ForwardX11 no 9057429Smarkm ForwardAgent no 9157429Smarkm 9257429Smarkm Host books.com 9357429Smarkm RemoteForward 9999 shadows.cs.hut.fi:9999 9457429Smarkm Cipher 3des 9557429Smarkm 9657429Smarkm Host fascist.blob.com 9757429Smarkm Port 23123 9857429Smarkm User tylonen 9957429Smarkm PasswordAuthentication no 10057429Smarkm 10157429Smarkm Host puukko.hut.fi 10257429Smarkm User t35124p 10357429Smarkm ProxyCommand ssh-proxy %h %p 10457429Smarkm 10557429Smarkm Host *.fr 10698684Sdes PublicKeyAuthentication no 10757429Smarkm 10857429Smarkm Host *.su 10957429Smarkm Cipher none 11057429Smarkm PasswordAuthentication no 11157429Smarkm 112157019Sdes Host vpn.fake.com 113157019Sdes Tunnel yes 114157019Sdes TunnelDevice 3 115157019Sdes 11657429Smarkm # Defaults for various options 11757429Smarkm Host * 11857429Smarkm ForwardAgent no 11976262Sgreen ForwardX11 no 12057429Smarkm PasswordAuthentication yes 12157429Smarkm RSAAuthentication yes 12257429Smarkm RhostsRSAAuthentication yes 12357429Smarkm StrictHostKeyChecking yes 124126277Sdes TcpKeepAlive no 12557429Smarkm IdentityFile ~/.ssh/identity 12657429Smarkm Port 22 12757429Smarkm EscapeChar ~ 12857429Smarkm 12957429Smarkm*/ 13057429Smarkm 13157429Smarkm/* Keyword tokens. */ 13257429Smarkm 13357429Smarkmtypedef enum { 13457429Smarkm oBadOption, 135295367Sdes oVersionAddendum, 136262566Sdes oHost, oMatch, 137215116Sdes oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, 138215116Sdes oGatewayPorts, oExitOnForwardFailure, 13998684Sdes oPasswordAuthentication, oRSAAuthentication, 14076262Sgreen oChallengeResponseAuthentication, oXAuthLocation, 14157429Smarkm oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 142296853Sdes oCertificateFile, oAddKeysToAgent, 143262566Sdes oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 14457429Smarkm oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 14557429Smarkm oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 146126277Sdes oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 14776262Sgreen oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 148295367Sdes oPubkeyAuthentication, 14976262Sgreen oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 15076262Sgreen oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 151204917Sdes oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, 15293698Sdes oClearAllForwardings, oNoHostAuthenticationForLocalhost, 153124211Sdes oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 154124211Sdes oAddressFamily, oGssAuthentication, oGssDelegateCreds, 155128461Sdes oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 156215116Sdes oSendEnv, oControlPath, oControlMaster, oControlPersist, 157215116Sdes oHashKnownHosts, 158157019Sdes oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 159296853Sdes oVisualHostKey, 160262566Sdes oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 161262566Sdes oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 162262566Sdes oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 163295367Sdes oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 164295367Sdes oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, 165295367Sdes oPubkeyAcceptedKeyTypes, 166294693Sdes oIgnoredUnknownOption, oDeprecated, oUnsupported 16757429Smarkm} OpCodes; 16857429Smarkm 16957429Smarkm/* Textual representations of the tokens. */ 17057429Smarkm 17157429Smarkmstatic struct { 17257429Smarkm const char *name; 17357429Smarkm OpCodes opcode; 17457429Smarkm} keywords[] = { 17557429Smarkm { "forwardagent", oForwardAgent }, 17657429Smarkm { "forwardx11", oForwardX11 }, 177126277Sdes { "forwardx11trusted", oForwardX11Trusted }, 178215116Sdes { "forwardx11timeout", oForwardX11Timeout }, 179162856Sdes { "exitonforwardfailure", oExitOnForwardFailure }, 18065674Skris { "xauthlocation", oXAuthLocation }, 18157429Smarkm { "gatewayports", oGatewayPorts }, 18257429Smarkm { "useprivilegedport", oUsePrivilegedPort }, 183124211Sdes { "rhostsauthentication", oDeprecated }, 18457429Smarkm { "passwordauthentication", oPasswordAuthentication }, 18569591Sgreen { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 18669591Sgreen { "kbdinteractivedevices", oKbdInteractiveDevices }, 18757429Smarkm { "rsaauthentication", oRSAAuthentication }, 18876262Sgreen { "pubkeyauthentication", oPubkeyAuthentication }, 18976262Sgreen { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 19076262Sgreen { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 19176262Sgreen { "hostbasedauthentication", oHostbasedAuthentication }, 19276262Sgreen { "challengeresponseauthentication", oChallengeResponseAuthentication }, 19376262Sgreen { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 19476262Sgreen { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 195124211Sdes { "kerberosauthentication", oUnsupported }, 196124211Sdes { "kerberostgtpassing", oUnsupported }, 197124211Sdes { "afstokenpassing", oUnsupported }, 198124211Sdes#if defined(GSSAPI) 199124211Sdes { "gssapiauthentication", oGssAuthentication }, 200124211Sdes { "gssapidelegatecredentials", oGssDelegateCreds }, 201124211Sdes#else 202124211Sdes { "gssapiauthentication", oUnsupported }, 203124211Sdes { "gssapidelegatecredentials", oUnsupported }, 20492559Sdes#endif 20598684Sdes { "fallbacktorsh", oDeprecated }, 20698684Sdes { "usersh", oDeprecated }, 20757429Smarkm { "identityfile", oIdentityFile }, 208192595Sdes { "identityfile2", oIdentityFile }, /* obsolete */ 209128460Sdes { "identitiesonly", oIdentitiesOnly }, 210296853Sdes { "certificatefile", oCertificateFile }, 211296853Sdes { "addkeystoagent", oAddKeysToAgent }, 21257429Smarkm { "hostname", oHostName }, 21376262Sgreen { "hostkeyalias", oHostKeyAlias }, 21457429Smarkm { "proxycommand", oProxyCommand }, 21557429Smarkm { "port", oPort }, 21657429Smarkm { "cipher", oCipher }, 21760576Skris { "ciphers", oCiphers }, 21876262Sgreen { "macs", oMacs }, 21960576Skris { "protocol", oProtocol }, 22057429Smarkm { "remoteforward", oRemoteForward }, 22157429Smarkm { "localforward", oLocalForward }, 22257429Smarkm { "user", oUser }, 22357429Smarkm { "host", oHost }, 224262566Sdes { "match", oMatch }, 22557429Smarkm { "escapechar", oEscapeChar }, 22657429Smarkm { "globalknownhostsfile", oGlobalKnownHostsFile }, 227226046Sdes { "globalknownhostsfile2", oDeprecated }, 228192595Sdes { "userknownhostsfile", oUserKnownHostsFile }, 229295367Sdes { "userknownhostsfile2", oDeprecated }, 23057429Smarkm { "connectionattempts", oConnectionAttempts }, 23157429Smarkm { "batchmode", oBatchMode }, 23257429Smarkm { "checkhostip", oCheckHostIP }, 23357429Smarkm { "stricthostkeychecking", oStrictHostKeyChecking }, 23457429Smarkm { "compression", oCompression }, 23557429Smarkm { "compressionlevel", oCompressionLevel }, 236126277Sdes { "tcpkeepalive", oTCPKeepAlive }, 237126277Sdes { "keepalive", oTCPKeepAlive }, /* obsolete */ 23857429Smarkm { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 23957429Smarkm { "loglevel", oLogLevel }, 24076262Sgreen { "dynamicforward", oDynamicForward }, 24176262Sgreen { "preferredauthentications", oPreferredAuthentications }, 24276262Sgreen { "hostkeyalgorithms", oHostKeyAlgorithms }, 24392559Sdes { "bindaddress", oBindAddress }, 244204917Sdes#ifdef ENABLE_PKCS11 245204917Sdes { "smartcarddevice", oPKCS11Provider }, 246204917Sdes { "pkcs11provider", oPKCS11Provider }, 247124211Sdes#else 248124211Sdes { "smartcarddevice", oUnsupported }, 249204917Sdes { "pkcs11provider", oUnsupported }, 250124211Sdes#endif 25192559Sdes { "clearallforwardings", oClearAllForwardings }, 252113911Sdes { "enablesshkeysign", oEnableSSHKeysign }, 253124211Sdes { "verifyhostkeydns", oVerifyHostKeyDNS }, 25492559Sdes { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 255124211Sdes { "rekeylimit", oRekeyLimit }, 256124211Sdes { "connecttimeout", oConnectTimeout }, 257124211Sdes { "addressfamily", oAddressFamily }, 258126277Sdes { "serveraliveinterval", oServerAliveInterval }, 259126277Sdes { "serveralivecountmax", oServerAliveCountMax }, 260137019Sdes { "sendenv", oSendEnv }, 261137019Sdes { "controlpath", oControlPath }, 262137019Sdes { "controlmaster", oControlMaster }, 263215116Sdes { "controlpersist", oControlPersist }, 264147005Sdes { "hashknownhosts", oHashKnownHosts }, 265157019Sdes { "tunnel", oTunnel }, 266157019Sdes { "tunneldevice", oTunnelDevice }, 267157019Sdes { "localcommand", oLocalCommand }, 268157019Sdes { "permitlocalcommand", oPermitLocalCommand }, 269181111Sdes { "visualhostkey", oVisualHostKey }, 270296853Sdes { "useroaming", oDeprecated }, 271221420Sdes { "kexalgorithms", oKexAlgorithms }, 272221420Sdes { "ipqos", oIPQoS }, 273226046Sdes { "requesttty", oRequestTTY }, 274262566Sdes { "proxyusefdpass", oProxyUseFdpass }, 275262566Sdes { "canonicaldomains", oCanonicalDomains }, 276262566Sdes { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, 277262566Sdes { "canonicalizehostname", oCanonicalizeHostname }, 278262566Sdes { "canonicalizemaxdots", oCanonicalizeMaxDots }, 279262566Sdes { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 280295367Sdes { "streamlocalbindmask", oStreamLocalBindMask }, 281295367Sdes { "streamlocalbindunlink", oStreamLocalBindUnlink }, 282295367Sdes { "revokedhostkeys", oRevokedHostKeys }, 283295367Sdes { "fingerprinthash", oFingerprintHash }, 284295367Sdes { "updatehostkeys", oUpdateHostkeys }, 285295367Sdes { "hostbasedkeytypes", oHostbasedKeyTypes }, 286295367Sdes { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, 287255767Sdes { "ignoreunknown", oIgnoreUnknown }, 288294693Sdes { "hpndisabled", oDeprecated }, 289294693Sdes { "hpnbuffersize", oDeprecated }, 290294693Sdes { "tcprcvbufpoll", oDeprecated }, 291294693Sdes { "tcprcvbuf", oDeprecated }, 292295367Sdes { "noneenabled", oUnsupported }, 293295367Sdes { "noneswitch", oUnsupported }, 29499048Sdes { "versionaddendum", oVersionAddendum }, 295231584Sed 29692559Sdes { NULL, oBadOption } 29757429Smarkm}; 29857429Smarkm 29957429Smarkm/* 30057429Smarkm * Adds a local TCP/IP port forward to options. Never returns if there is an 30157429Smarkm * error. 30257429Smarkm */ 30357429Smarkm 30460576Skrisvoid 305295367Sdesadd_local_forward(Options *options, const struct Forward *newfwd) 30657429Smarkm{ 307295367Sdes struct Forward *fwd; 308106130Sdes#ifndef NO_IPPORT_RESERVED_CONCEPT 30957429Smarkm extern uid_t original_real_uid; 310181918Sdes int ipport_reserved; 311181918Sdes#ifdef __FreeBSD__ 312181918Sdes size_t len_ipport_reserved = sizeof(ipport_reserved); 313181918Sdes 314181918Sdes if (sysctlbyname("net.inet.ip.portrange.reservedhigh", 315181918Sdes &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0) 316181918Sdes ipport_reserved = IPPORT_RESERVED; 317181918Sdes else 318181918Sdes ipport_reserved++; 319181918Sdes#else 320181918Sdes ipport_reserved = IPPORT_RESERVED; 321181918Sdes#endif 322181918Sdes if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) 323295367Sdes if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 && 324295367Sdes newfwd->listen_path == NULL) 32576262Sgreen fatal("Privileged ports can only be forwarded by root."); 32698941Sdes#endif 327295367Sdes options->local_forwards = xreallocarray(options->local_forwards, 328215116Sdes options->num_local_forwards + 1, 329215116Sdes sizeof(*options->local_forwards)); 33057429Smarkm fwd = &options->local_forwards[options->num_local_forwards++]; 331147005Sdes 332192595Sdes fwd->listen_host = newfwd->listen_host; 333147005Sdes fwd->listen_port = newfwd->listen_port; 334295367Sdes fwd->listen_path = newfwd->listen_path; 335192595Sdes fwd->connect_host = newfwd->connect_host; 336147005Sdes fwd->connect_port = newfwd->connect_port; 337295367Sdes fwd->connect_path = newfwd->connect_path; 33857429Smarkm} 33957429Smarkm 34057429Smarkm/* 34157429Smarkm * Adds a remote TCP/IP port forward to options. Never returns if there is 34257429Smarkm * an error. 34357429Smarkm */ 34457429Smarkm 34560576Skrisvoid 346295367Sdesadd_remote_forward(Options *options, const struct Forward *newfwd) 34757429Smarkm{ 348295367Sdes struct Forward *fwd; 349215116Sdes 350295367Sdes options->remote_forwards = xreallocarray(options->remote_forwards, 351215116Sdes options->num_remote_forwards + 1, 352215116Sdes sizeof(*options->remote_forwards)); 35357429Smarkm fwd = &options->remote_forwards[options->num_remote_forwards++]; 354147005Sdes 355192595Sdes fwd->listen_host = newfwd->listen_host; 356147005Sdes fwd->listen_port = newfwd->listen_port; 357295367Sdes fwd->listen_path = newfwd->listen_path; 358192595Sdes fwd->connect_host = newfwd->connect_host; 359147005Sdes fwd->connect_port = newfwd->connect_port; 360295367Sdes fwd->connect_path = newfwd->connect_path; 361240075Sdes fwd->handle = newfwd->handle; 362215116Sdes fwd->allocated_port = 0; 36357429Smarkm} 36457429Smarkm 36592559Sdesstatic void 36692559Sdesclear_forwardings(Options *options) 36792559Sdes{ 36892559Sdes int i; 36992559Sdes 370147005Sdes for (i = 0; i < options->num_local_forwards; i++) { 371255767Sdes free(options->local_forwards[i].listen_host); 372295367Sdes free(options->local_forwards[i].listen_path); 373255767Sdes free(options->local_forwards[i].connect_host); 374295367Sdes free(options->local_forwards[i].connect_path); 375147005Sdes } 376215116Sdes if (options->num_local_forwards > 0) { 377255767Sdes free(options->local_forwards); 378215116Sdes options->local_forwards = NULL; 379215116Sdes } 38092559Sdes options->num_local_forwards = 0; 381147005Sdes for (i = 0; i < options->num_remote_forwards; i++) { 382255767Sdes free(options->remote_forwards[i].listen_host); 383295367Sdes free(options->remote_forwards[i].listen_path); 384255767Sdes free(options->remote_forwards[i].connect_host); 385295367Sdes free(options->remote_forwards[i].connect_path); 386147005Sdes } 387215116Sdes if (options->num_remote_forwards > 0) { 388255767Sdes free(options->remote_forwards); 389215116Sdes options->remote_forwards = NULL; 390215116Sdes } 39192559Sdes options->num_remote_forwards = 0; 392157019Sdes options->tun_open = SSH_TUNMODE_NO; 39392559Sdes} 39492559Sdes 395249016Sdesvoid 396296853Sdesadd_certificate_file(Options *options, const char *path, int userprovided) 397296853Sdes{ 398296853Sdes int i; 399296853Sdes 400296853Sdes if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) 401296853Sdes fatal("Too many certificate files specified (max %d)", 402296853Sdes SSH_MAX_CERTIFICATE_FILES); 403296853Sdes 404296853Sdes /* Avoid registering duplicates */ 405296853Sdes for (i = 0; i < options->num_certificate_files; i++) { 406296853Sdes if (options->certificate_file_userprovided[i] == userprovided && 407296853Sdes strcmp(options->certificate_files[i], path) == 0) { 408296853Sdes debug2("%s: ignoring duplicate key %s", __func__, path); 409296853Sdes return; 410296853Sdes } 411296853Sdes } 412296853Sdes 413296853Sdes options->certificate_file_userprovided[options->num_certificate_files] = 414296853Sdes userprovided; 415296853Sdes options->certificate_files[options->num_certificate_files++] = 416296853Sdes xstrdup(path); 417296853Sdes} 418296853Sdes 419296853Sdesvoid 420249016Sdesadd_identity_file(Options *options, const char *dir, const char *filename, 421249016Sdes int userprovided) 422249016Sdes{ 423249016Sdes char *path; 424295367Sdes int i; 425249016Sdes 426249016Sdes if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 427249016Sdes fatal("Too many identity files specified (max %d)", 428249016Sdes SSH_MAX_IDENTITY_FILES); 429249016Sdes 430249016Sdes if (dir == NULL) /* no dir, filename is absolute */ 431249016Sdes path = xstrdup(filename); 432249016Sdes else 433249016Sdes (void)xasprintf(&path, "%.100s%.100s", dir, filename); 434249016Sdes 435295367Sdes /* Avoid registering duplicates */ 436295367Sdes for (i = 0; i < options->num_identity_files; i++) { 437295367Sdes if (options->identity_file_userprovided[i] == userprovided && 438295367Sdes strcmp(options->identity_files[i], path) == 0) { 439295367Sdes debug2("%s: ignoring duplicate key %s", __func__, path); 440295367Sdes free(path); 441295367Sdes return; 442295367Sdes } 443295367Sdes } 444295367Sdes 445249016Sdes options->identity_file_userprovided[options->num_identity_files] = 446249016Sdes userprovided; 447249016Sdes options->identity_files[options->num_identity_files++] = path; 448249016Sdes} 449249016Sdes 450262566Sdesint 451262566Sdesdefault_ssh_port(void) 452262566Sdes{ 453262566Sdes static int port; 454262566Sdes struct servent *sp; 455262566Sdes 456262566Sdes if (port == 0) { 457262566Sdes sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 458262566Sdes port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; 459262566Sdes } 460262566Sdes return port; 461262566Sdes} 462262566Sdes 46357429Smarkm/* 464262566Sdes * Execute a command in a shell. 465262566Sdes * Return its exit status or -1 on abnormal exit. 466262566Sdes */ 467262566Sdesstatic int 468262566Sdesexecute_in_shell(const char *cmd) 469262566Sdes{ 470296853Sdes char *shell; 471262566Sdes pid_t pid; 472262566Sdes int devnull, status; 473262566Sdes extern uid_t original_real_uid; 474262566Sdes 475262566Sdes if ((shell = getenv("SHELL")) == NULL) 476262566Sdes shell = _PATH_BSHELL; 477262566Sdes 478262566Sdes /* Need this to redirect subprocess stdin/out */ 479262566Sdes if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) 480262566Sdes fatal("open(/dev/null): %s", strerror(errno)); 481262566Sdes 482262566Sdes debug("Executing command: '%.500s'", cmd); 483262566Sdes 484262566Sdes /* Fork and execute the command. */ 485262566Sdes if ((pid = fork()) == 0) { 486262566Sdes char *argv[4]; 487262566Sdes 488262566Sdes /* Child. Permanently give up superuser privileges. */ 489262566Sdes permanently_drop_suid(original_real_uid); 490262566Sdes 491262566Sdes /* Redirect child stdin and stdout. Leave stderr */ 492262566Sdes if (dup2(devnull, STDIN_FILENO) == -1) 493262566Sdes fatal("dup2: %s", strerror(errno)); 494262566Sdes if (dup2(devnull, STDOUT_FILENO) == -1) 495262566Sdes fatal("dup2: %s", strerror(errno)); 496262566Sdes if (devnull > STDERR_FILENO) 497262566Sdes close(devnull); 498262566Sdes closefrom(STDERR_FILENO + 1); 499262566Sdes 500262566Sdes argv[0] = shell; 501262566Sdes argv[1] = "-c"; 502296853Sdes argv[2] = xstrdup(cmd); 503262566Sdes argv[3] = NULL; 504262566Sdes 505262566Sdes execv(argv[0], argv); 506262566Sdes error("Unable to execute '%.100s': %s", cmd, strerror(errno)); 507262566Sdes /* Die with signal to make this error apparent to parent. */ 508262566Sdes signal(SIGTERM, SIG_DFL); 509262566Sdes kill(getpid(), SIGTERM); 510262566Sdes _exit(1); 511262566Sdes } 512262566Sdes /* Parent. */ 513262566Sdes if (pid < 0) 514262566Sdes fatal("%s: fork: %.100s", __func__, strerror(errno)); 515262566Sdes 516262566Sdes close(devnull); 517262566Sdes 518262566Sdes while (waitpid(pid, &status, 0) == -1) { 519262566Sdes if (errno != EINTR && errno != EAGAIN) 520262566Sdes fatal("%s: waitpid: %s", __func__, strerror(errno)); 521262566Sdes } 522262566Sdes if (!WIFEXITED(status)) { 523262566Sdes error("command '%.100s' exited abnormally", cmd); 524262566Sdes return -1; 525295367Sdes } 526262566Sdes debug3("command returned status %d", WEXITSTATUS(status)); 527262566Sdes return WEXITSTATUS(status); 528262566Sdes} 529262566Sdes 530262566Sdes/* 531262566Sdes * Parse and execute a Match directive. 532262566Sdes */ 533262566Sdesstatic int 534262566Sdesmatch_cfg_line(Options *options, char **condition, struct passwd *pw, 535295367Sdes const char *host_arg, const char *original_host, int post_canon, 536295367Sdes const char *filename, int linenum) 537262566Sdes{ 538295367Sdes char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; 539262566Sdes const char *ruser; 540295367Sdes int r, port, this_result, result = 1, attributes = 0, negate; 541262566Sdes char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; 542262566Sdes 543262566Sdes /* 544262566Sdes * Configuration is likely to be incomplete at this point so we 545262566Sdes * must be prepared to use default values. 546262566Sdes */ 547262566Sdes port = options->port <= 0 ? default_ssh_port() : options->port; 548262566Sdes ruser = options->user == NULL ? pw->pw_name : options->user; 549296853Sdes if (post_canon) { 550296853Sdes host = xstrdup(options->hostname); 551296853Sdes } else if (options->hostname != NULL) { 552262566Sdes /* NB. Please keep in sync with ssh.c:main() */ 553262566Sdes host = percent_expand(options->hostname, 554262566Sdes "h", host_arg, (char *)NULL); 555296853Sdes } else { 556262566Sdes host = xstrdup(host_arg); 557296853Sdes } 558262566Sdes 559295367Sdes debug2("checking match for '%s' host %s originally %s", 560295367Sdes cp, host, original_host); 561295367Sdes while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { 562295367Sdes criteria = NULL; 563295367Sdes this_result = 1; 564295367Sdes if ((negate = attrib[0] == '!')) 565295367Sdes attrib++; 566295367Sdes /* criteria "all" and "canonical" have no argument */ 567262566Sdes if (strcasecmp(attrib, "all") == 0) { 568295367Sdes if (attributes > 1 || 569262566Sdes ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { 570295367Sdes error("%.200s line %d: '%s' cannot be combined " 571295367Sdes "with other Match attributes", 572295367Sdes filename, linenum, oattrib); 573262566Sdes result = -1; 574262566Sdes goto out; 575262566Sdes } 576295367Sdes if (result) 577295367Sdes result = negate ? 0 : 1; 578262566Sdes goto out; 579262566Sdes } 580295367Sdes attributes++; 581295367Sdes if (strcasecmp(attrib, "canonical") == 0) { 582295367Sdes r = !!post_canon; /* force bitmask member to boolean */ 583295367Sdes if (r == (negate ? 1 : 0)) 584295367Sdes this_result = result = 0; 585295367Sdes debug3("%.200s line %d: %smatched '%s'", 586295367Sdes filename, linenum, 587295367Sdes this_result ? "" : "not ", oattrib); 588295367Sdes continue; 589295367Sdes } 590295367Sdes /* All other criteria require an argument */ 591262566Sdes if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 592262566Sdes error("Missing Match criteria for %s", attrib); 593262566Sdes result = -1; 594262566Sdes goto out; 595262566Sdes } 596262566Sdes if (strcasecmp(attrib, "host") == 0) { 597295367Sdes criteria = xstrdup(host); 598295367Sdes r = match_hostname(host, arg) == 1; 599295367Sdes if (r == (negate ? 1 : 0)) 600295367Sdes this_result = result = 0; 601262566Sdes } else if (strcasecmp(attrib, "originalhost") == 0) { 602295367Sdes criteria = xstrdup(original_host); 603295367Sdes r = match_hostname(original_host, arg) == 1; 604295367Sdes if (r == (negate ? 1 : 0)) 605295367Sdes this_result = result = 0; 606262566Sdes } else if (strcasecmp(attrib, "user") == 0) { 607295367Sdes criteria = xstrdup(ruser); 608295367Sdes r = match_pattern_list(ruser, arg, 0) == 1; 609295367Sdes if (r == (negate ? 1 : 0)) 610295367Sdes this_result = result = 0; 611262566Sdes } else if (strcasecmp(attrib, "localuser") == 0) { 612295367Sdes criteria = xstrdup(pw->pw_name); 613295367Sdes r = match_pattern_list(pw->pw_name, arg, 0) == 1; 614295367Sdes if (r == (negate ? 1 : 0)) 615295367Sdes this_result = result = 0; 616262566Sdes } else if (strcasecmp(attrib, "exec") == 0) { 617262566Sdes if (gethostname(thishost, sizeof(thishost)) == -1) 618262566Sdes fatal("gethostname: %s", strerror(errno)); 619262566Sdes strlcpy(shorthost, thishost, sizeof(shorthost)); 620262566Sdes shorthost[strcspn(thishost, ".")] = '\0'; 621262566Sdes snprintf(portstr, sizeof(portstr), "%d", port); 622262566Sdes 623262566Sdes cmd = percent_expand(arg, 624262566Sdes "L", shorthost, 625262566Sdes "d", pw->pw_dir, 626262566Sdes "h", host, 627262566Sdes "l", thishost, 628295367Sdes "n", original_host, 629262566Sdes "p", portstr, 630262566Sdes "r", ruser, 631262566Sdes "u", pw->pw_name, 632262566Sdes (char *)NULL); 633264377Sdes if (result != 1) { 634264377Sdes /* skip execution if prior predicate failed */ 635295367Sdes debug3("%.200s line %d: skipped exec " 636295367Sdes "\"%.100s\"", filename, linenum, cmd); 637295367Sdes free(cmd); 638295367Sdes continue; 639264377Sdes } 640295367Sdes r = execute_in_shell(cmd); 641295367Sdes if (r == -1) { 642295367Sdes fatal("%.200s line %d: match exec " 643295367Sdes "'%.100s' error", filename, 644295367Sdes linenum, cmd); 645295367Sdes } 646295367Sdes criteria = xstrdup(cmd); 647262566Sdes free(cmd); 648295367Sdes /* Force exit status to boolean */ 649295367Sdes r = r == 0; 650295367Sdes if (r == (negate ? 1 : 0)) 651295367Sdes this_result = result = 0; 652262566Sdes } else { 653262566Sdes error("Unsupported Match attribute %s", attrib); 654262566Sdes result = -1; 655262566Sdes goto out; 656262566Sdes } 657295367Sdes debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", 658295367Sdes filename, linenum, this_result ? "": "not ", 659295367Sdes oattrib, criteria); 660295367Sdes free(criteria); 661262566Sdes } 662262566Sdes if (attributes == 0) { 663262566Sdes error("One or more attributes required for Match"); 664262566Sdes result = -1; 665262566Sdes goto out; 666262566Sdes } 667295367Sdes out: 668295367Sdes if (result != -1) 669295367Sdes debug2("match %sfound", result ? "" : "not "); 670262566Sdes *condition = cp; 671262566Sdes free(host); 672262566Sdes return result; 673262566Sdes} 674262566Sdes 675262566Sdes/* Check and prepare a domain name: removes trailing '.' and lowercases */ 676262566Sdesstatic void 677262566Sdesvalid_domain(char *name, const char *filename, int linenum) 678262566Sdes{ 679262566Sdes size_t i, l = strlen(name); 680262566Sdes u_char c, last = '\0'; 681262566Sdes 682262566Sdes if (l == 0) 683262566Sdes fatal("%s line %d: empty hostname suffix", filename, linenum); 684262566Sdes if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) 685262566Sdes fatal("%s line %d: hostname suffix \"%.100s\" " 686262566Sdes "starts with invalid character", filename, linenum, name); 687262566Sdes for (i = 0; i < l; i++) { 688262566Sdes c = tolower((u_char)name[i]); 689262566Sdes name[i] = (char)c; 690262566Sdes if (last == '.' && c == '.') 691262566Sdes fatal("%s line %d: hostname suffix \"%.100s\" contains " 692262566Sdes "consecutive separators", filename, linenum, name); 693262566Sdes if (c != '.' && c != '-' && !isalnum(c) && 694262566Sdes c != '_') /* technically invalid, but common */ 695262566Sdes fatal("%s line %d: hostname suffix \"%.100s\" contains " 696262566Sdes "invalid characters", filename, linenum, name); 697262566Sdes last = c; 698262566Sdes } 699262566Sdes if (name[l - 1] == '.') 700262566Sdes name[l - 1] = '\0'; 701262566Sdes} 702262566Sdes 703262566Sdes/* 70476262Sgreen * Returns the number of the token pointed to by cp or oBadOption. 70557429Smarkm */ 70660576Skrisstatic OpCodes 707255767Sdesparse_token(const char *cp, const char *filename, int linenum, 708255767Sdes const char *ignored_unknown) 70957429Smarkm{ 710255767Sdes int i; 71157429Smarkm 71257429Smarkm for (i = 0; keywords[i].name; i++) 713255767Sdes if (strcmp(cp, keywords[i].name) == 0) 71457429Smarkm return keywords[i].opcode; 715295367Sdes if (ignored_unknown != NULL && 716295367Sdes match_pattern_list(cp, ignored_unknown, 1) == 1) 717255767Sdes return oIgnoredUnknownOption; 71876262Sgreen error("%s: line %d: Bad configuration option: %s", 71976262Sgreen filename, linenum, cp); 72057429Smarkm return oBadOption; 72157429Smarkm} 72257429Smarkm 723262566Sdes/* Multistate option parsing */ 724262566Sdesstruct multistate { 725262566Sdes char *key; 726262566Sdes int value; 727262566Sdes}; 728262566Sdesstatic const struct multistate multistate_flag[] = { 729262566Sdes { "true", 1 }, 730262566Sdes { "false", 0 }, 731262566Sdes { "yes", 1 }, 732262566Sdes { "no", 0 }, 733262566Sdes { NULL, -1 } 734262566Sdes}; 735262566Sdesstatic const struct multistate multistate_yesnoask[] = { 736262566Sdes { "true", 1 }, 737262566Sdes { "false", 0 }, 738262566Sdes { "yes", 1 }, 739262566Sdes { "no", 0 }, 740262566Sdes { "ask", 2 }, 741262566Sdes { NULL, -1 } 742262566Sdes}; 743296853Sdesstatic const struct multistate multistate_yesnoaskconfirm[] = { 744296853Sdes { "true", 1 }, 745296853Sdes { "false", 0 }, 746296853Sdes { "yes", 1 }, 747296853Sdes { "no", 0 }, 748296853Sdes { "ask", 2 }, 749296853Sdes { "confirm", 3 }, 750296853Sdes { NULL, -1 } 751296853Sdes}; 752262566Sdesstatic const struct multistate multistate_addressfamily[] = { 753262566Sdes { "inet", AF_INET }, 754262566Sdes { "inet6", AF_INET6 }, 755262566Sdes { "any", AF_UNSPEC }, 756262566Sdes { NULL, -1 } 757262566Sdes}; 758262566Sdesstatic const struct multistate multistate_controlmaster[] = { 759262566Sdes { "true", SSHCTL_MASTER_YES }, 760262566Sdes { "yes", SSHCTL_MASTER_YES }, 761262566Sdes { "false", SSHCTL_MASTER_NO }, 762262566Sdes { "no", SSHCTL_MASTER_NO }, 763262566Sdes { "auto", SSHCTL_MASTER_AUTO }, 764262566Sdes { "ask", SSHCTL_MASTER_ASK }, 765262566Sdes { "autoask", SSHCTL_MASTER_AUTO_ASK }, 766262566Sdes { NULL, -1 } 767262566Sdes}; 768262566Sdesstatic const struct multistate multistate_tunnel[] = { 769262566Sdes { "ethernet", SSH_TUNMODE_ETHERNET }, 770262566Sdes { "point-to-point", SSH_TUNMODE_POINTOPOINT }, 771262566Sdes { "true", SSH_TUNMODE_DEFAULT }, 772262566Sdes { "yes", SSH_TUNMODE_DEFAULT }, 773262566Sdes { "false", SSH_TUNMODE_NO }, 774262566Sdes { "no", SSH_TUNMODE_NO }, 775262566Sdes { NULL, -1 } 776262566Sdes}; 777262566Sdesstatic const struct multistate multistate_requesttty[] = { 778262566Sdes { "true", REQUEST_TTY_YES }, 779262566Sdes { "yes", REQUEST_TTY_YES }, 780262566Sdes { "false", REQUEST_TTY_NO }, 781262566Sdes { "no", REQUEST_TTY_NO }, 782262566Sdes { "force", REQUEST_TTY_FORCE }, 783262566Sdes { "auto", REQUEST_TTY_AUTO }, 784262566Sdes { NULL, -1 } 785262566Sdes}; 786262566Sdesstatic const struct multistate multistate_canonicalizehostname[] = { 787262566Sdes { "true", SSH_CANONICALISE_YES }, 788262566Sdes { "false", SSH_CANONICALISE_NO }, 789262566Sdes { "yes", SSH_CANONICALISE_YES }, 790262566Sdes { "no", SSH_CANONICALISE_NO }, 791262566Sdes { "always", SSH_CANONICALISE_ALWAYS }, 792262566Sdes { NULL, -1 } 793262566Sdes}; 794262566Sdes 79557429Smarkm/* 79657429Smarkm * Processes a single option line as used in the configuration files. This 79757429Smarkm * only sets those values that have not already been set. 79857429Smarkm */ 799113911Sdes#define WHITESPACE " \t\r\n" 80057429Smarkmint 801262566Sdesprocess_config_line(Options *options, struct passwd *pw, const char *host, 802295367Sdes const char *original_host, char *line, const char *filename, 803295367Sdes int linenum, int *activep, int flags) 80457429Smarkm{ 805226046Sdes char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; 806226046Sdes char **cpptr, fwdarg[256]; 807255767Sdes u_int i, *uintptr, max_entries = 0; 808262566Sdes int negated, opcode, *intptr, value, value2, cmdline = 0; 809181111Sdes LogLevel *log_level_ptr; 810255767Sdes long long val64; 811113911Sdes size_t len; 812295367Sdes struct Forward fwd; 813262566Sdes const struct multistate *multistate_ptr; 814262566Sdes struct allowed_cname *cname; 81557429Smarkm 816262566Sdes if (activep == NULL) { /* We are processing a command line directive */ 817262566Sdes cmdline = 1; 818262566Sdes activep = &cmdline; 819262566Sdes } 820262566Sdes 821124211Sdes /* Strip trailing whitespace */ 822295367Sdes if ((len = strlen(line)) == 0) 823295367Sdes return 0; 824295367Sdes for (len--; len > 0; len--) { 825124211Sdes if (strchr(WHITESPACE, line[len]) == NULL) 826124211Sdes break; 827124211Sdes line[len] = '\0'; 828124211Sdes } 829124211Sdes 83065674Skris s = line; 83165674Skris /* Get the keyword. (Each line is supposed to begin with a keyword). */ 832162856Sdes if ((keyword = strdelim(&s)) == NULL) 833162856Sdes return 0; 83465674Skris /* Ignore leading whitespace. */ 83565674Skris if (*keyword == '\0') 83665674Skris keyword = strdelim(&s); 83776262Sgreen if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 83857429Smarkm return 0; 839255767Sdes /* Match lowercase keyword */ 840262566Sdes lowercase(keyword); 84157429Smarkm 842255767Sdes opcode = parse_token(keyword, filename, linenum, 843255767Sdes options->ignored_unknown); 84457429Smarkm 84557429Smarkm switch (opcode) { 84657429Smarkm case oBadOption: 84757429Smarkm /* don't panic, but count bad options */ 84857429Smarkm return -1; 84957429Smarkm /* NOTREACHED */ 850255767Sdes case oIgnoredUnknownOption: 851255767Sdes debug("%s line %d: Ignored unknown option \"%s\"", 852255767Sdes filename, linenum, keyword); 853255767Sdes return 0; 854124211Sdes case oConnectTimeout: 855124211Sdes intptr = &options->connection_timeout; 856126277Sdesparse_time: 857124211Sdes arg = strdelim(&s); 858124211Sdes if (!arg || *arg == '\0') 859124211Sdes fatal("%s line %d: missing time value.", 860124211Sdes filename, linenum); 861295367Sdes if (strcmp(arg, "none") == 0) 862295367Sdes value = -1; 863295367Sdes else if ((value = convtime(arg)) == -1) 864124211Sdes fatal("%s line %d: invalid time value.", 865124211Sdes filename, linenum); 866181111Sdes if (*activep && *intptr == -1) 867124211Sdes *intptr = value; 868124211Sdes break; 869124211Sdes 87057429Smarkm case oForwardAgent: 87157429Smarkm intptr = &options->forward_agent; 872262566Sdes parse_flag: 873262566Sdes multistate_ptr = multistate_flag; 874262566Sdes parse_multistate: 87565674Skris arg = strdelim(&s); 87665674Skris if (!arg || *arg == '\0') 877262566Sdes fatal("%s line %d: missing argument.", 878262566Sdes filename, linenum); 879262566Sdes value = -1; 880262566Sdes for (i = 0; multistate_ptr[i].key != NULL; i++) { 881262566Sdes if (strcasecmp(arg, multistate_ptr[i].key) == 0) { 882262566Sdes value = multistate_ptr[i].value; 883262566Sdes break; 884262566Sdes } 885262566Sdes } 886262566Sdes if (value == -1) 887262566Sdes fatal("%s line %d: unsupported option \"%s\".", 888262566Sdes filename, linenum, arg); 88957429Smarkm if (*activep && *intptr == -1) 89057429Smarkm *intptr = value; 89157429Smarkm break; 89257429Smarkm 89357429Smarkm case oForwardX11: 89457429Smarkm intptr = &options->forward_x11; 89557429Smarkm goto parse_flag; 89657429Smarkm 897126277Sdes case oForwardX11Trusted: 898126277Sdes intptr = &options->forward_x11_trusted; 899126277Sdes goto parse_flag; 900295367Sdes 901215116Sdes case oForwardX11Timeout: 902215116Sdes intptr = &options->forward_x11_timeout; 903215116Sdes goto parse_time; 904126277Sdes 90557429Smarkm case oGatewayPorts: 906295367Sdes intptr = &options->fwd_opts.gateway_ports; 90757429Smarkm goto parse_flag; 90857429Smarkm 909162856Sdes case oExitOnForwardFailure: 910162856Sdes intptr = &options->exit_on_forward_failure; 911162856Sdes goto parse_flag; 912162856Sdes 91357429Smarkm case oUsePrivilegedPort: 91457429Smarkm intptr = &options->use_privileged_port; 91557429Smarkm goto parse_flag; 91657429Smarkm 91757429Smarkm case oPasswordAuthentication: 91857429Smarkm intptr = &options->password_authentication; 91957429Smarkm goto parse_flag; 92057429Smarkm 92169591Sgreen case oKbdInteractiveAuthentication: 92269591Sgreen intptr = &options->kbd_interactive_authentication; 92369591Sgreen goto parse_flag; 92469591Sgreen 92569591Sgreen case oKbdInteractiveDevices: 92669591Sgreen charptr = &options->kbd_interactive_devices; 92769591Sgreen goto parse_string; 92869591Sgreen 92976262Sgreen case oPubkeyAuthentication: 93076262Sgreen intptr = &options->pubkey_authentication; 93160576Skris goto parse_flag; 93260576Skris 93357429Smarkm case oRSAAuthentication: 93457429Smarkm intptr = &options->rsa_authentication; 93557429Smarkm goto parse_flag; 93657429Smarkm 93757429Smarkm case oRhostsRSAAuthentication: 93857429Smarkm intptr = &options->rhosts_rsa_authentication; 93957429Smarkm goto parse_flag; 94057429Smarkm 94176262Sgreen case oHostbasedAuthentication: 94276262Sgreen intptr = &options->hostbased_authentication; 94357429Smarkm goto parse_flag; 94457429Smarkm 94592559Sdes case oChallengeResponseAuthentication: 94692559Sdes intptr = &options->challenge_response_authentication; 94792559Sdes goto parse_flag; 948124211Sdes 949124211Sdes case oGssAuthentication: 950124211Sdes intptr = &options->gss_authentication; 95157429Smarkm goto parse_flag; 952124211Sdes 953124211Sdes case oGssDelegateCreds: 954124211Sdes intptr = &options->gss_deleg_creds; 95576262Sgreen goto parse_flag; 956124211Sdes 95757429Smarkm case oBatchMode: 95857429Smarkm intptr = &options->batch_mode; 95957429Smarkm goto parse_flag; 96057429Smarkm 96157429Smarkm case oCheckHostIP: 96257429Smarkm intptr = &options->check_host_ip; 96357429Smarkm goto parse_flag; 96457429Smarkm 965124211Sdes case oVerifyHostKeyDNS: 966124211Sdes intptr = &options->verify_host_key_dns; 967262566Sdes multistate_ptr = multistate_yesnoask; 968262566Sdes goto parse_multistate; 969124211Sdes 97057429Smarkm case oStrictHostKeyChecking: 97157429Smarkm intptr = &options->strict_host_key_checking; 972262566Sdes multistate_ptr = multistate_yesnoask; 973262566Sdes goto parse_multistate; 97457429Smarkm 97557429Smarkm case oCompression: 97657429Smarkm intptr = &options->compression; 97757429Smarkm goto parse_flag; 97857429Smarkm 979126277Sdes case oTCPKeepAlive: 980126277Sdes intptr = &options->tcp_keep_alive; 98157429Smarkm goto parse_flag; 98257429Smarkm 98392559Sdes case oNoHostAuthenticationForLocalhost: 98492559Sdes intptr = &options->no_host_authentication_for_localhost; 98592559Sdes goto parse_flag; 98692559Sdes 98757429Smarkm case oNumberOfPasswordPrompts: 98857429Smarkm intptr = &options->number_of_password_prompts; 98957429Smarkm goto parse_int; 99057429Smarkm 99157429Smarkm case oCompressionLevel: 99257429Smarkm intptr = &options->compression_level; 99357429Smarkm goto parse_int; 99457429Smarkm 995124211Sdes case oRekeyLimit: 996124211Sdes arg = strdelim(&s); 997124211Sdes if (!arg || *arg == '\0') 998255767Sdes fatal("%.200s line %d: Missing argument.", filename, 999255767Sdes linenum); 1000255767Sdes if (strcmp(arg, "default") == 0) { 1001255767Sdes val64 = 0; 1002255767Sdes } else { 1003255767Sdes if (scan_scaled(arg, &val64) == -1) 1004255767Sdes fatal("%.200s line %d: Bad number '%s': %s", 1005255767Sdes filename, linenum, arg, strerror(errno)); 1006255767Sdes if (val64 != 0 && val64 < 16) 1007255767Sdes fatal("%.200s line %d: RekeyLimit too small", 1008255767Sdes filename, linenum); 1009124211Sdes } 1010181111Sdes if (*activep && options->rekey_limit == -1) 1011296853Sdes options->rekey_limit = val64; 1012255767Sdes if (s != NULL) { /* optional rekey interval present */ 1013255767Sdes if (strcmp(s, "none") == 0) { 1014255767Sdes (void)strdelim(&s); /* discard */ 1015255767Sdes break; 1016255767Sdes } 1017255767Sdes intptr = &options->rekey_interval; 1018255767Sdes goto parse_time; 1019255767Sdes } 1020124211Sdes break; 1021124211Sdes 102257429Smarkm case oIdentityFile: 102365674Skris arg = strdelim(&s); 102465674Skris if (!arg || *arg == '\0') 102557429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 102657429Smarkm if (*activep) { 102776262Sgreen intptr = &options->num_identity_files; 102860576Skris if (*intptr >= SSH_MAX_IDENTITY_FILES) 102957429Smarkm fatal("%.200s line %d: Too many identity files specified (max %d).", 103092559Sdes filename, linenum, SSH_MAX_IDENTITY_FILES); 1031295367Sdes add_identity_file(options, NULL, 1032295367Sdes arg, flags & SSHCONF_USERCONF); 103357429Smarkm } 103457429Smarkm break; 103557429Smarkm 1036296853Sdes case oCertificateFile: 1037296853Sdes arg = strdelim(&s); 1038296853Sdes if (!arg || *arg == '\0') 1039296853Sdes fatal("%.200s line %d: Missing argument.", 1040296853Sdes filename, linenum); 1041296853Sdes if (*activep) { 1042296853Sdes intptr = &options->num_certificate_files; 1043296853Sdes if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { 1044296853Sdes fatal("%.200s line %d: Too many certificate " 1045296853Sdes "files specified (max %d).", 1046296853Sdes filename, linenum, 1047296853Sdes SSH_MAX_CERTIFICATE_FILES); 1048296853Sdes } 1049296853Sdes add_certificate_file(options, arg, 1050296853Sdes flags & SSHCONF_USERCONF); 1051296853Sdes } 1052296853Sdes break; 1053296853Sdes 105465674Skris case oXAuthLocation: 105565674Skris charptr=&options->xauth_location; 105665674Skris goto parse_string; 105765674Skris 105857429Smarkm case oUser: 105957429Smarkm charptr = &options->user; 106057429Smarkmparse_string: 106165674Skris arg = strdelim(&s); 106265674Skris if (!arg || *arg == '\0') 1063226046Sdes fatal("%.200s line %d: Missing argument.", 1064226046Sdes filename, linenum); 106557429Smarkm if (*activep && *charptr == NULL) 106665674Skris *charptr = xstrdup(arg); 106757429Smarkm break; 106857429Smarkm 106957429Smarkm case oGlobalKnownHostsFile: 1070226046Sdes cpptr = (char **)&options->system_hostfiles; 1071226046Sdes uintptr = &options->num_system_hostfiles; 1072226046Sdes max_entries = SSH_MAX_HOSTS_FILES; 1073226046Sdesparse_char_array: 1074226046Sdes if (*activep && *uintptr == 0) { 1075226046Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1076226046Sdes if ((*uintptr) >= max_entries) 1077226046Sdes fatal("%s line %d: " 1078226046Sdes "too many authorized keys files.", 1079226046Sdes filename, linenum); 1080226046Sdes cpptr[(*uintptr)++] = xstrdup(arg); 1081226046Sdes } 1082226046Sdes } 1083226046Sdes return 0; 108457429Smarkm 108557429Smarkm case oUserKnownHostsFile: 1086226046Sdes cpptr = (char **)&options->user_hostfiles; 1087226046Sdes uintptr = &options->num_user_hostfiles; 1088226046Sdes max_entries = SSH_MAX_HOSTS_FILES; 1089226046Sdes goto parse_char_array; 109057429Smarkm 109157429Smarkm case oHostName: 109257429Smarkm charptr = &options->hostname; 109357429Smarkm goto parse_string; 109457429Smarkm 109576262Sgreen case oHostKeyAlias: 109676262Sgreen charptr = &options->host_key_alias; 109776262Sgreen goto parse_string; 109876262Sgreen 109976262Sgreen case oPreferredAuthentications: 110076262Sgreen charptr = &options->preferred_authentications; 110176262Sgreen goto parse_string; 110276262Sgreen 110392559Sdes case oBindAddress: 110492559Sdes charptr = &options->bind_address; 110592559Sdes goto parse_string; 110692559Sdes 1107204917Sdes case oPKCS11Provider: 1108204917Sdes charptr = &options->pkcs11_provider; 110992559Sdes goto parse_string; 111092559Sdes 111157429Smarkm case oProxyCommand: 1112157019Sdes charptr = &options->proxy_command; 1113157019Sdesparse_command: 1114124211Sdes if (s == NULL) 1115124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 1116113911Sdes len = strspn(s, WHITESPACE "="); 111757429Smarkm if (*activep && *charptr == NULL) 1118113911Sdes *charptr = xstrdup(s + len); 111957429Smarkm return 0; 112057429Smarkm 112157429Smarkm case oPort: 112257429Smarkm intptr = &options->port; 112357429Smarkmparse_int: 112465674Skris arg = strdelim(&s); 112565674Skris if (!arg || *arg == '\0') 112657429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 112765674Skris if (arg[0] < '0' || arg[0] > '9') 112857429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 112957429Smarkm 113057429Smarkm /* Octal, decimal, or hex format? */ 113165674Skris value = strtol(arg, &endofnumber, 0); 113265674Skris if (arg == endofnumber) 113357429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 113457429Smarkm if (*activep && *intptr == -1) 113557429Smarkm *intptr = value; 113657429Smarkm break; 113757429Smarkm 113857429Smarkm case oConnectionAttempts: 113957429Smarkm intptr = &options->connection_attempts; 114057429Smarkm goto parse_int; 114157429Smarkm 114257429Smarkm case oCipher: 114357429Smarkm intptr = &options->cipher; 114465674Skris arg = strdelim(&s); 114565674Skris if (!arg || *arg == '\0') 114661203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 114765674Skris value = cipher_number(arg); 114857429Smarkm if (value == -1) 114957429Smarkm fatal("%.200s line %d: Bad cipher '%s'.", 115092559Sdes filename, linenum, arg ? arg : "<NONE>"); 115157429Smarkm if (*activep && *intptr == -1) 115257429Smarkm *intptr = value; 115357429Smarkm break; 115457429Smarkm 115560576Skris case oCiphers: 115665674Skris arg = strdelim(&s); 115765674Skris if (!arg || *arg == '\0') 115861203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 1159295367Sdes if (!ciphers_valid(*arg == '+' ? arg + 1 : arg)) 116060576Skris fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 116192559Sdes filename, linenum, arg ? arg : "<NONE>"); 116260576Skris if (*activep && options->ciphers == NULL) 116365674Skris options->ciphers = xstrdup(arg); 116460576Skris break; 116560576Skris 116676262Sgreen case oMacs: 116776262Sgreen arg = strdelim(&s); 116876262Sgreen if (!arg || *arg == '\0') 116976262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 1170295367Sdes if (!mac_valid(*arg == '+' ? arg + 1 : arg)) 117176262Sgreen fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 117292559Sdes filename, linenum, arg ? arg : "<NONE>"); 117376262Sgreen if (*activep && options->macs == NULL) 117476262Sgreen options->macs = xstrdup(arg); 117576262Sgreen break; 117676262Sgreen 1177221420Sdes case oKexAlgorithms: 1178221420Sdes arg = strdelim(&s); 1179221420Sdes if (!arg || *arg == '\0') 1180221420Sdes fatal("%.200s line %d: Missing argument.", 1181221420Sdes filename, linenum); 1182295367Sdes if (!kex_names_valid(*arg == '+' ? arg + 1 : arg)) 1183221420Sdes fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", 1184221420Sdes filename, linenum, arg ? arg : "<NONE>"); 1185221420Sdes if (*activep && options->kex_algorithms == NULL) 1186221420Sdes options->kex_algorithms = xstrdup(arg); 1187221420Sdes break; 1188221420Sdes 118976262Sgreen case oHostKeyAlgorithms: 1190295367Sdes charptr = &options->hostkeyalgorithms; 1191295367Sdesparse_keytypes: 119276262Sgreen arg = strdelim(&s); 119376262Sgreen if (!arg || *arg == '\0') 1194295367Sdes fatal("%.200s line %d: Missing argument.", 1195295367Sdes filename, linenum); 1196295367Sdes if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) 1197295367Sdes fatal("%s line %d: Bad key types '%s'.", 1198295367Sdes filename, linenum, arg ? arg : "<NONE>"); 1199295367Sdes if (*activep && *charptr == NULL) 1200295367Sdes *charptr = xstrdup(arg); 120176262Sgreen break; 120276262Sgreen 120360576Skris case oProtocol: 120460576Skris intptr = &options->protocol; 120565674Skris arg = strdelim(&s); 120665674Skris if (!arg || *arg == '\0') 120761203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 120865674Skris value = proto_spec(arg); 120960576Skris if (value == SSH_PROTO_UNKNOWN) 121060576Skris fatal("%.200s line %d: Bad protocol spec '%s'.", 121192559Sdes filename, linenum, arg ? arg : "<NONE>"); 121260576Skris if (*activep && *intptr == SSH_PROTO_UNKNOWN) 121360576Skris *intptr = value; 121460576Skris break; 121560576Skris 121657429Smarkm case oLogLevel: 1217181111Sdes log_level_ptr = &options->log_level; 121865674Skris arg = strdelim(&s); 121965674Skris value = log_level_number(arg); 122092559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 122176262Sgreen fatal("%.200s line %d: unsupported log level '%s'", 122292559Sdes filename, linenum, arg ? arg : "<NONE>"); 1223181111Sdes if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 1224181111Sdes *log_level_ptr = (LogLevel) value; 122557429Smarkm break; 122657429Smarkm 122792559Sdes case oLocalForward: 122857429Smarkm case oRemoteForward: 1229192595Sdes case oDynamicForward: 123065674Skris arg = strdelim(&s); 1231147005Sdes if (arg == NULL || *arg == '\0') 123292559Sdes fatal("%.200s line %d: Missing port argument.", 123392559Sdes filename, linenum); 1234147005Sdes 1235192595Sdes if (opcode == oLocalForward || 1236192595Sdes opcode == oRemoteForward) { 1237192595Sdes arg2 = strdelim(&s); 1238192595Sdes if (arg2 == NULL || *arg2 == '\0') 1239192595Sdes fatal("%.200s line %d: Missing target argument.", 1240192595Sdes filename, linenum); 1241147005Sdes 1242192595Sdes /* construct a string for parse_forward */ 1243192595Sdes snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 1244192595Sdes } else if (opcode == oDynamicForward) { 1245192595Sdes strlcpy(fwdarg, arg, sizeof(fwdarg)); 1246192595Sdes } 1247192595Sdes 1248192595Sdes if (parse_forward(&fwd, fwdarg, 1249192595Sdes opcode == oDynamicForward ? 1 : 0, 1250192595Sdes opcode == oRemoteForward ? 1 : 0) == 0) 125192559Sdes fatal("%.200s line %d: Bad forwarding specification.", 125292559Sdes filename, linenum); 1253147005Sdes 125492559Sdes if (*activep) { 1255192595Sdes if (opcode == oLocalForward || 1256192595Sdes opcode == oDynamicForward) 1257147005Sdes add_local_forward(options, &fwd); 125892559Sdes else if (opcode == oRemoteForward) 1259147005Sdes add_remote_forward(options, &fwd); 126092559Sdes } 126157429Smarkm break; 126257429Smarkm 126392559Sdes case oClearAllForwardings: 126492559Sdes intptr = &options->clear_forwardings; 126592559Sdes goto parse_flag; 126692559Sdes 126757429Smarkm case oHost: 1268262566Sdes if (cmdline) 1269262566Sdes fatal("Host directive not supported as a command-line " 1270262566Sdes "option"); 127157429Smarkm *activep = 0; 1272226046Sdes arg2 = NULL; 1273226046Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1274226046Sdes negated = *arg == '!'; 1275226046Sdes if (negated) 1276226046Sdes arg++; 127765674Skris if (match_pattern(host, arg)) { 1278226046Sdes if (negated) { 1279226046Sdes debug("%.200s line %d: Skipping Host " 1280226046Sdes "block because of negated match " 1281226046Sdes "for %.100s", filename, linenum, 1282226046Sdes arg); 1283226046Sdes *activep = 0; 1284226046Sdes break; 1285226046Sdes } 1286226046Sdes if (!*activep) 1287226046Sdes arg2 = arg; /* logged below */ 128857429Smarkm *activep = 1; 128957429Smarkm } 1290226046Sdes } 1291226046Sdes if (*activep) 1292226046Sdes debug("%.200s line %d: Applying options for %.100s", 1293226046Sdes filename, linenum, arg2); 129465674Skris /* Avoid garbage check below, as strdelim is done. */ 129557429Smarkm return 0; 129657429Smarkm 1297262566Sdes case oMatch: 1298262566Sdes if (cmdline) 1299262566Sdes fatal("Host directive not supported as a command-line " 1300262566Sdes "option"); 1301295367Sdes value = match_cfg_line(options, &s, pw, host, original_host, 1302295367Sdes flags & SSHCONF_POSTCANON, filename, linenum); 1303262566Sdes if (value < 0) 1304262566Sdes fatal("%.200s line %d: Bad Match condition", filename, 1305262566Sdes linenum); 1306262566Sdes *activep = value; 1307262566Sdes break; 1308262566Sdes 130957429Smarkm case oEscapeChar: 131057429Smarkm intptr = &options->escape_char; 131165674Skris arg = strdelim(&s); 131265674Skris if (!arg || *arg == '\0') 131357429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 1314295367Sdes if (strcmp(arg, "none") == 0) 1315295367Sdes value = SSH_ESCAPECHAR_NONE; 1316295367Sdes else if (arg[1] == '\0') 1317295367Sdes value = (u_char) arg[0]; 1318295367Sdes else if (arg[0] == '^' && arg[2] == 0 && 131976262Sgreen (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 132076262Sgreen value = (u_char) arg[1] & 31; 132157429Smarkm else { 132257429Smarkm fatal("%.200s line %d: Bad escape character.", 132392559Sdes filename, linenum); 132457429Smarkm /* NOTREACHED */ 132557429Smarkm value = 0; /* Avoid compiler warning. */ 132657429Smarkm } 132757429Smarkm if (*activep && *intptr == -1) 132857429Smarkm *intptr = value; 132957429Smarkm break; 133057429Smarkm 1331124211Sdes case oAddressFamily: 1332124211Sdes intptr = &options->address_family; 1333262566Sdes multistate_ptr = multistate_addressfamily; 1334262566Sdes goto parse_multistate; 1335124211Sdes 1336113911Sdes case oEnableSSHKeysign: 1337113911Sdes intptr = &options->enable_ssh_keysign; 1338113911Sdes goto parse_flag; 1339113911Sdes 1340128460Sdes case oIdentitiesOnly: 1341128460Sdes intptr = &options->identities_only; 1342128460Sdes goto parse_flag; 1343128460Sdes 1344126277Sdes case oServerAliveInterval: 1345126277Sdes intptr = &options->server_alive_interval; 1346126277Sdes goto parse_time; 1347126277Sdes 1348126277Sdes case oServerAliveCountMax: 1349126277Sdes intptr = &options->server_alive_count_max; 1350126277Sdes goto parse_int; 1351126277Sdes 1352137019Sdes case oSendEnv: 1353137019Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1354137019Sdes if (strchr(arg, '=') != NULL) 1355137019Sdes fatal("%s line %d: Invalid environment name.", 1356137019Sdes filename, linenum); 1357147005Sdes if (!*activep) 1358147005Sdes continue; 1359137019Sdes if (options->num_send_env >= MAX_SEND_ENV) 1360137019Sdes fatal("%s line %d: too many send env.", 1361137019Sdes filename, linenum); 1362137019Sdes options->send_env[options->num_send_env++] = 1363137019Sdes xstrdup(arg); 1364137019Sdes } 1365137019Sdes break; 1366137019Sdes 1367137019Sdes case oControlPath: 1368137019Sdes charptr = &options->control_path; 1369137019Sdes goto parse_string; 1370137019Sdes 1371137019Sdes case oControlMaster: 1372137019Sdes intptr = &options->control_master; 1373262566Sdes multistate_ptr = multistate_controlmaster; 1374262566Sdes goto parse_multistate; 1375137019Sdes 1376215116Sdes case oControlPersist: 1377215116Sdes /* no/false/yes/true, or a time spec */ 1378215116Sdes intptr = &options->control_persist; 1379215116Sdes arg = strdelim(&s); 1380215116Sdes if (!arg || *arg == '\0') 1381215116Sdes fatal("%.200s line %d: Missing ControlPersist" 1382215116Sdes " argument.", filename, linenum); 1383215116Sdes value = 0; 1384215116Sdes value2 = 0; /* timeout */ 1385215116Sdes if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 1386215116Sdes value = 0; 1387215116Sdes else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 1388215116Sdes value = 1; 1389215116Sdes else if ((value2 = convtime(arg)) >= 0) 1390215116Sdes value = 1; 1391215116Sdes else 1392215116Sdes fatal("%.200s line %d: Bad ControlPersist argument.", 1393215116Sdes filename, linenum); 1394215116Sdes if (*activep && *intptr == -1) { 1395215116Sdes *intptr = value; 1396215116Sdes options->control_persist_timeout = value2; 1397215116Sdes } 1398215116Sdes break; 1399215116Sdes 1400147005Sdes case oHashKnownHosts: 1401147005Sdes intptr = &options->hash_known_hosts; 1402147005Sdes goto parse_flag; 1403147005Sdes 1404157019Sdes case oTunnel: 1405157019Sdes intptr = &options->tun_open; 1406262566Sdes multistate_ptr = multistate_tunnel; 1407262566Sdes goto parse_multistate; 1408157019Sdes 1409157019Sdes case oTunnelDevice: 1410157019Sdes arg = strdelim(&s); 1411157019Sdes if (!arg || *arg == '\0') 1412157019Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 1413157019Sdes value = a2tun(arg, &value2); 1414157019Sdes if (value == SSH_TUNID_ERR) 1415157019Sdes fatal("%.200s line %d: Bad tun device.", filename, linenum); 1416157019Sdes if (*activep) { 1417157019Sdes options->tun_local = value; 1418157019Sdes options->tun_remote = value2; 1419157019Sdes } 1420157019Sdes break; 1421157019Sdes 1422157019Sdes case oLocalCommand: 1423157019Sdes charptr = &options->local_command; 1424157019Sdes goto parse_command; 1425157019Sdes 1426157019Sdes case oPermitLocalCommand: 1427157019Sdes intptr = &options->permit_local_command; 1428157019Sdes goto parse_flag; 1429157019Sdes 1430181111Sdes case oVisualHostKey: 1431181111Sdes intptr = &options->visual_host_key; 1432181111Sdes goto parse_flag; 1433181111Sdes 1434221420Sdes case oIPQoS: 1435221420Sdes arg = strdelim(&s); 1436221420Sdes if ((value = parse_ipqos(arg)) == -1) 1437221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1438221420Sdes filename, linenum, arg); 1439221420Sdes arg = strdelim(&s); 1440221420Sdes if (arg == NULL) 1441221420Sdes value2 = value; 1442221420Sdes else if ((value2 = parse_ipqos(arg)) == -1) 1443221420Sdes fatal("%s line %d: Bad IPQoS value: %s", 1444221420Sdes filename, linenum, arg); 1445221420Sdes if (*activep) { 1446221420Sdes options->ip_qos_interactive = value; 1447221420Sdes options->ip_qos_bulk = value2; 1448221420Sdes } 1449221420Sdes break; 1450221420Sdes 1451226046Sdes case oRequestTTY: 1452226046Sdes intptr = &options->request_tty; 1453262566Sdes multistate_ptr = multistate_requesttty; 1454262566Sdes goto parse_multistate; 145599048Sdes 1456226046Sdes case oVersionAddendum: 1457240075Sdes if (s == NULL) 1458240075Sdes fatal("%.200s line %d: Missing argument.", filename, 1459240075Sdes linenum); 1460240075Sdes len = strspn(s, WHITESPACE); 1461240075Sdes if (*activep && options->version_addendum == NULL) { 1462240075Sdes if (strcasecmp(s + len, "none") == 0) 1463240075Sdes options->version_addendum = xstrdup(""); 1464240075Sdes else if (strchr(s + len, '\r') != NULL) 1465240075Sdes fatal("%.200s line %d: Invalid argument", 1466240075Sdes filename, linenum); 1467240075Sdes else 1468240075Sdes options->version_addendum = xstrdup(s + len); 1469240075Sdes } 1470240075Sdes return 0; 1471226046Sdes 1472255767Sdes case oIgnoreUnknown: 1473255767Sdes charptr = &options->ignored_unknown; 1474255767Sdes goto parse_string; 1475255767Sdes 1476262566Sdes case oProxyUseFdpass: 1477262566Sdes intptr = &options->proxy_use_fdpass; 1478262566Sdes goto parse_flag; 1479262566Sdes 1480262566Sdes case oCanonicalDomains: 1481262566Sdes value = options->num_canonical_domains != 0; 1482262566Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1483262566Sdes valid_domain(arg, filename, linenum); 1484262566Sdes if (!*activep || value) 1485262566Sdes continue; 1486262566Sdes if (options->num_canonical_domains >= MAX_CANON_DOMAINS) 1487262566Sdes fatal("%s line %d: too many hostname suffixes.", 1488262566Sdes filename, linenum); 1489262566Sdes options->canonical_domains[ 1490262566Sdes options->num_canonical_domains++] = xstrdup(arg); 1491262566Sdes } 1492262566Sdes break; 1493262566Sdes 1494262566Sdes case oCanonicalizePermittedCNAMEs: 1495262566Sdes value = options->num_permitted_cnames != 0; 1496262566Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 1497262566Sdes /* Either '*' for everything or 'list:list' */ 1498262566Sdes if (strcmp(arg, "*") == 0) 1499262566Sdes arg2 = arg; 1500262566Sdes else { 1501262566Sdes lowercase(arg); 1502262566Sdes if ((arg2 = strchr(arg, ':')) == NULL || 1503262566Sdes arg2[1] == '\0') { 1504262566Sdes fatal("%s line %d: " 1505262566Sdes "Invalid permitted CNAME \"%s\"", 1506262566Sdes filename, linenum, arg); 1507262566Sdes } 1508262566Sdes *arg2 = '\0'; 1509262566Sdes arg2++; 1510262566Sdes } 1511262566Sdes if (!*activep || value) 1512262566Sdes continue; 1513262566Sdes if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) 1514262566Sdes fatal("%s line %d: too many permitted CNAMEs.", 1515262566Sdes filename, linenum); 1516262566Sdes cname = options->permitted_cnames + 1517262566Sdes options->num_permitted_cnames++; 1518262566Sdes cname->source_list = xstrdup(arg); 1519262566Sdes cname->target_list = xstrdup(arg2); 1520262566Sdes } 1521262566Sdes break; 1522262566Sdes 1523262566Sdes case oCanonicalizeHostname: 1524262566Sdes intptr = &options->canonicalize_hostname; 1525262566Sdes multistate_ptr = multistate_canonicalizehostname; 1526262566Sdes goto parse_multistate; 1527262566Sdes 1528262566Sdes case oCanonicalizeMaxDots: 1529262566Sdes intptr = &options->canonicalize_max_dots; 1530262566Sdes goto parse_int; 1531262566Sdes 1532262566Sdes case oCanonicalizeFallbackLocal: 1533262566Sdes intptr = &options->canonicalize_fallback_local; 1534262566Sdes goto parse_flag; 1535262566Sdes 1536295367Sdes case oStreamLocalBindMask: 1537295367Sdes arg = strdelim(&s); 1538295367Sdes if (!arg || *arg == '\0') 1539295367Sdes fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); 1540295367Sdes /* Parse mode in octal format */ 1541295367Sdes value = strtol(arg, &endofnumber, 8); 1542295367Sdes if (arg == endofnumber || value < 0 || value > 0777) 1543295367Sdes fatal("%.200s line %d: Bad mask.", filename, linenum); 1544295367Sdes options->fwd_opts.streamlocal_bind_mask = (mode_t)value; 1545295367Sdes break; 1546295367Sdes 1547295367Sdes case oStreamLocalBindUnlink: 1548295367Sdes intptr = &options->fwd_opts.streamlocal_bind_unlink; 1549295367Sdes goto parse_flag; 1550295367Sdes 1551295367Sdes case oRevokedHostKeys: 1552295367Sdes charptr = &options->revoked_host_keys; 1553295367Sdes goto parse_string; 1554295367Sdes 1555295367Sdes case oFingerprintHash: 1556295367Sdes intptr = &options->fingerprint_hash; 1557295367Sdes arg = strdelim(&s); 1558295367Sdes if (!arg || *arg == '\0') 1559295367Sdes fatal("%.200s line %d: Missing argument.", 1560295367Sdes filename, linenum); 1561295367Sdes if ((value = ssh_digest_alg_by_name(arg)) == -1) 1562295367Sdes fatal("%.200s line %d: Invalid hash algorithm \"%s\".", 1563295367Sdes filename, linenum, arg); 1564295367Sdes if (*activep && *intptr == -1) 1565295367Sdes *intptr = value; 1566295367Sdes break; 1567295367Sdes 1568295367Sdes case oUpdateHostkeys: 1569295367Sdes intptr = &options->update_hostkeys; 1570295367Sdes multistate_ptr = multistate_yesnoask; 1571295367Sdes goto parse_multistate; 1572295367Sdes 1573295367Sdes case oHostbasedKeyTypes: 1574295367Sdes charptr = &options->hostbased_key_types; 1575295367Sdes goto parse_keytypes; 1576295367Sdes 1577295367Sdes case oPubkeyAcceptedKeyTypes: 1578295367Sdes charptr = &options->pubkey_key_types; 1579295367Sdes goto parse_keytypes; 1580295367Sdes 1581296853Sdes case oAddKeysToAgent: 1582296853Sdes intptr = &options->add_keys_to_agent; 1583296853Sdes multistate_ptr = multistate_yesnoaskconfirm; 1584296853Sdes goto parse_multistate; 1585296853Sdes 158698684Sdes case oDeprecated: 158798684Sdes debug("%s line %d: Deprecated option \"%s\"", 158898684Sdes filename, linenum, keyword); 158998684Sdes return 0; 159098684Sdes 1591124211Sdes case oUnsupported: 1592124211Sdes error("%s line %d: Unsupported option \"%s\"", 1593124211Sdes filename, linenum, keyword); 1594124211Sdes return 0; 1595124211Sdes 159657429Smarkm default: 1597295367Sdes fatal("%s: Unimplemented opcode %d", __func__, opcode); 159857429Smarkm } 159957429Smarkm 160057429Smarkm /* Check that there is no garbage at end of line. */ 160176262Sgreen if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 160265674Skris fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 1603149753Sdes filename, linenum, arg); 160465674Skris } 160557429Smarkm return 0; 160657429Smarkm} 160757429Smarkm 160857429Smarkm 160957429Smarkm/* 161057429Smarkm * Reads the config file and modifies the options accordingly. Options 161157429Smarkm * should already be initialized before this call. This never returns if 161292559Sdes * there is an error. If the file does not exist, this returns 0. 161357429Smarkm */ 161457429Smarkm 161592559Sdesint 1616262566Sdesread_config_file(const char *filename, struct passwd *pw, const char *host, 1617295367Sdes const char *original_host, Options *options, int flags) 161857429Smarkm{ 161957429Smarkm FILE *f; 162057429Smarkm char line[1024]; 162157429Smarkm int active, linenum; 162257429Smarkm int bad_options = 0; 162357429Smarkm 1624137019Sdes if ((f = fopen(filename, "r")) == NULL) 162592559Sdes return 0; 162657429Smarkm 1627249839Sdes if (flags & SSHCONF_CHECKPERM) { 1628137019Sdes struct stat sb; 1629137019Sdes 1630137019Sdes if (fstat(fileno(f), &sb) == -1) 1631137019Sdes fatal("fstat %s: %s", filename, strerror(errno)); 1632137019Sdes if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 1633137019Sdes (sb.st_mode & 022) != 0)) 1634137019Sdes fatal("Bad owner or permissions on %s", filename); 1635137019Sdes } 1636137019Sdes 163757429Smarkm debug("Reading configuration data %.200s", filename); 163857429Smarkm 163957429Smarkm /* 164057429Smarkm * Mark that we are now processing the options. This flag is turned 164157429Smarkm * on/off by Host specifications. 164257429Smarkm */ 164357429Smarkm active = 1; 164457429Smarkm linenum = 0; 164557429Smarkm while (fgets(line, sizeof(line), f)) { 164657429Smarkm /* Update line number counter. */ 164757429Smarkm linenum++; 1648295367Sdes if (process_config_line(options, pw, host, original_host, 1649295367Sdes line, filename, linenum, &active, flags) != 0) 165057429Smarkm bad_options++; 165157429Smarkm } 165257429Smarkm fclose(f); 165357429Smarkm if (bad_options > 0) 165476262Sgreen fatal("%s: terminating, %d bad configuration options", 165592559Sdes filename, bad_options); 165692559Sdes return 1; 165757429Smarkm} 165857429Smarkm 1659264377Sdes/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 1660264377Sdesint 1661264377Sdesoption_clear_or_none(const char *o) 1662264377Sdes{ 1663264377Sdes return o == NULL || strcasecmp(o, "none") == 0; 1664264377Sdes} 1665264377Sdes 166657429Smarkm/* 166757429Smarkm * Initializes options to special values that indicate that they have not yet 166857429Smarkm * been set. Read_config_file will only set options with this value. Options 166957429Smarkm * are processed in the following order: command line, user config file, 167057429Smarkm * system config file. Last, fill_default_options is called. 167157429Smarkm */ 167257429Smarkm 167360576Skrisvoid 167457429Smarkminitialize_options(Options * options) 167557429Smarkm{ 167657429Smarkm memset(options, 'X', sizeof(*options)); 1677295367Sdes options->version_addendum = NULL; 167857429Smarkm options->forward_agent = -1; 167957429Smarkm options->forward_x11 = -1; 1680126277Sdes options->forward_x11_trusted = -1; 1681215116Sdes options->forward_x11_timeout = -1; 1682162856Sdes options->exit_on_forward_failure = -1; 168365674Skris options->xauth_location = NULL; 1684295367Sdes options->fwd_opts.gateway_ports = -1; 1685295367Sdes options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; 1686295367Sdes options->fwd_opts.streamlocal_bind_unlink = -1; 168757429Smarkm options->use_privileged_port = -1; 168857429Smarkm options->rsa_authentication = -1; 168976262Sgreen options->pubkey_authentication = -1; 169092559Sdes options->challenge_response_authentication = -1; 1691124211Sdes options->gss_authentication = -1; 1692124211Sdes options->gss_deleg_creds = -1; 169357429Smarkm options->password_authentication = -1; 169469591Sgreen options->kbd_interactive_authentication = -1; 169569591Sgreen options->kbd_interactive_devices = NULL; 169657429Smarkm options->rhosts_rsa_authentication = -1; 169776262Sgreen options->hostbased_authentication = -1; 169857429Smarkm options->batch_mode = -1; 169957429Smarkm options->check_host_ip = -1; 170057429Smarkm options->strict_host_key_checking = -1; 170157429Smarkm options->compression = -1; 1702126277Sdes options->tcp_keep_alive = -1; 170357429Smarkm options->compression_level = -1; 170457429Smarkm options->port = -1; 1705124211Sdes options->address_family = -1; 170657429Smarkm options->connection_attempts = -1; 1707124211Sdes options->connection_timeout = -1; 170857429Smarkm options->number_of_password_prompts = -1; 170957429Smarkm options->cipher = -1; 171060576Skris options->ciphers = NULL; 171176262Sgreen options->macs = NULL; 1712221420Sdes options->kex_algorithms = NULL; 171376262Sgreen options->hostkeyalgorithms = NULL; 171460576Skris options->protocol = SSH_PROTO_UNKNOWN; 171557429Smarkm options->num_identity_files = 0; 1716296853Sdes options->num_certificate_files = 0; 171757429Smarkm options->hostname = NULL; 171876262Sgreen options->host_key_alias = NULL; 171957429Smarkm options->proxy_command = NULL; 172057429Smarkm options->user = NULL; 172157429Smarkm options->escape_char = -1; 1722226046Sdes options->num_system_hostfiles = 0; 1723226046Sdes options->num_user_hostfiles = 0; 1724215116Sdes options->local_forwards = NULL; 172557429Smarkm options->num_local_forwards = 0; 1726215116Sdes options->remote_forwards = NULL; 172757429Smarkm options->num_remote_forwards = 0; 172892559Sdes options->clear_forwardings = -1; 172992559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 173076262Sgreen options->preferred_authentications = NULL; 173192559Sdes options->bind_address = NULL; 1732204917Sdes options->pkcs11_provider = NULL; 1733113911Sdes options->enable_ssh_keysign = - 1; 173492559Sdes options->no_host_authentication_for_localhost = - 1; 1735128460Sdes options->identities_only = - 1; 1736124211Sdes options->rekey_limit = - 1; 1737255767Sdes options->rekey_interval = -1; 1738124211Sdes options->verify_host_key_dns = -1; 1739126277Sdes options->server_alive_interval = -1; 1740126277Sdes options->server_alive_count_max = -1; 1741137019Sdes options->num_send_env = 0; 1742137019Sdes options->control_path = NULL; 1743137019Sdes options->control_master = -1; 1744215116Sdes options->control_persist = -1; 1745215116Sdes options->control_persist_timeout = 0; 1746147005Sdes options->hash_known_hosts = -1; 1747157019Sdes options->tun_open = -1; 1748157019Sdes options->tun_local = -1; 1749157019Sdes options->tun_remote = -1; 1750157019Sdes options->local_command = NULL; 1751157019Sdes options->permit_local_command = -1; 1752296853Sdes options->add_keys_to_agent = -1; 1753181111Sdes options->visual_host_key = -1; 1754221420Sdes options->ip_qos_interactive = -1; 1755221420Sdes options->ip_qos_bulk = -1; 1756226046Sdes options->request_tty = -1; 1757262566Sdes options->proxy_use_fdpass = -1; 1758262566Sdes options->ignored_unknown = NULL; 1759262566Sdes options->num_canonical_domains = 0; 1760262566Sdes options->num_permitted_cnames = 0; 1761262566Sdes options->canonicalize_max_dots = -1; 1762262566Sdes options->canonicalize_fallback_local = -1; 1763262566Sdes options->canonicalize_hostname = -1; 1764295367Sdes options->revoked_host_keys = NULL; 1765295367Sdes options->fingerprint_hash = -1; 1766295367Sdes options->update_hostkeys = -1; 1767295367Sdes options->hostbased_key_types = NULL; 1768295367Sdes options->pubkey_key_types = NULL; 176957429Smarkm} 177057429Smarkm 177157429Smarkm/* 1772264377Sdes * A petite version of fill_default_options() that just fills the options 1773264377Sdes * needed for hostname canonicalization to proceed. 1774264377Sdes */ 1775264377Sdesvoid 1776264377Sdesfill_default_options_for_canonicalization(Options *options) 1777264377Sdes{ 1778264377Sdes if (options->canonicalize_max_dots == -1) 1779264377Sdes options->canonicalize_max_dots = 1; 1780264377Sdes if (options->canonicalize_fallback_local == -1) 1781264377Sdes options->canonicalize_fallback_local = 1; 1782264377Sdes if (options->canonicalize_hostname == -1) 1783264377Sdes options->canonicalize_hostname = SSH_CANONICALISE_NO; 1784264377Sdes} 1785264377Sdes 1786264377Sdes/* 178757429Smarkm * Called after processing other sources of option data, this fills those 178857429Smarkm * options for which no value has been specified with their default values. 178957429Smarkm */ 179060576Skrisvoid 179157429Smarkmfill_default_options(Options * options) 179257429Smarkm{ 179357429Smarkm if (options->forward_agent == -1) 179461203Skris options->forward_agent = 0; 179557429Smarkm if (options->forward_x11 == -1) 179657708Sgreen options->forward_x11 = 0; 1797126277Sdes if (options->forward_x11_trusted == -1) 1798126277Sdes options->forward_x11_trusted = 0; 1799215116Sdes if (options->forward_x11_timeout == -1) 1800215116Sdes options->forward_x11_timeout = 1200; 1801162856Sdes if (options->exit_on_forward_failure == -1) 1802162856Sdes options->exit_on_forward_failure = 0; 180365674Skris if (options->xauth_location == NULL) 180492559Sdes options->xauth_location = _PATH_XAUTH; 1805295367Sdes if (options->fwd_opts.gateway_ports == -1) 1806295367Sdes options->fwd_opts.gateway_ports = 0; 1807295367Sdes if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 1808295367Sdes options->fwd_opts.streamlocal_bind_mask = 0177; 1809295367Sdes if (options->fwd_opts.streamlocal_bind_unlink == -1) 1810295367Sdes options->fwd_opts.streamlocal_bind_unlink = 0; 181157429Smarkm if (options->use_privileged_port == -1) 181276262Sgreen options->use_privileged_port = 0; 181357429Smarkm if (options->rsa_authentication == -1) 181457429Smarkm options->rsa_authentication = 1; 181576262Sgreen if (options->pubkey_authentication == -1) 181676262Sgreen options->pubkey_authentication = 1; 181792559Sdes if (options->challenge_response_authentication == -1) 181892559Sdes options->challenge_response_authentication = 1; 1819124211Sdes if (options->gss_authentication == -1) 1820126277Sdes options->gss_authentication = 0; 1821124211Sdes if (options->gss_deleg_creds == -1) 1822124211Sdes options->gss_deleg_creds = 0; 182357429Smarkm if (options->password_authentication == -1) 182457429Smarkm options->password_authentication = 1; 182569591Sgreen if (options->kbd_interactive_authentication == -1) 182676262Sgreen options->kbd_interactive_authentication = 1; 182757429Smarkm if (options->rhosts_rsa_authentication == -1) 182898684Sdes options->rhosts_rsa_authentication = 0; 182976262Sgreen if (options->hostbased_authentication == -1) 183076262Sgreen options->hostbased_authentication = 0; 183157429Smarkm if (options->batch_mode == -1) 183257429Smarkm options->batch_mode = 0; 183357429Smarkm if (options->check_host_ip == -1) 183499048Sdes options->check_host_ip = 0; 183557429Smarkm if (options->strict_host_key_checking == -1) 183657429Smarkm options->strict_host_key_checking = 2; /* 2 is default */ 183757429Smarkm if (options->compression == -1) 183857429Smarkm options->compression = 0; 1839126277Sdes if (options->tcp_keep_alive == -1) 1840126277Sdes options->tcp_keep_alive = 1; 184157429Smarkm if (options->compression_level == -1) 184257429Smarkm options->compression_level = 6; 184357429Smarkm if (options->port == -1) 184457429Smarkm options->port = 0; /* Filled in ssh_connect. */ 1845124211Sdes if (options->address_family == -1) 1846124211Sdes options->address_family = AF_UNSPEC; 184757429Smarkm if (options->connection_attempts == -1) 184892559Sdes options->connection_attempts = 1; 184957429Smarkm if (options->number_of_password_prompts == -1) 185057429Smarkm options->number_of_password_prompts = 3; 185157429Smarkm /* Selected in ssh_login(). */ 185257429Smarkm if (options->cipher == -1) 185357429Smarkm options->cipher = SSH_CIPHER_NOT_SET; 185476262Sgreen /* options->hostkeyalgorithms, default set in myproposals.h */ 185560576Skris if (options->protocol == SSH_PROTO_UNKNOWN) 1856204917Sdes options->protocol = SSH_PROTO_2; 1857296853Sdes if (options->add_keys_to_agent == -1) 1858296853Sdes options->add_keys_to_agent = 0; 185957429Smarkm if (options->num_identity_files == 0) { 186076262Sgreen if (options->protocol & SSH_PROTO_1) { 1861249839Sdes add_identity_file(options, "~/", 1862249839Sdes _PATH_SSH_CLIENT_IDENTITY, 0); 186376262Sgreen } 186476262Sgreen if (options->protocol & SSH_PROTO_2) { 1865249839Sdes add_identity_file(options, "~/", 1866249839Sdes _PATH_SSH_CLIENT_ID_RSA, 0); 1867249839Sdes add_identity_file(options, "~/", 1868249839Sdes _PATH_SSH_CLIENT_ID_DSA, 0); 1869221420Sdes#ifdef OPENSSL_HAS_ECC 1870249839Sdes add_identity_file(options, "~/", 1871249839Sdes _PATH_SSH_CLIENT_ID_ECDSA, 0); 1872221420Sdes#endif 1873262566Sdes add_identity_file(options, "~/", 1874262566Sdes _PATH_SSH_CLIENT_ID_ED25519, 0); 187576262Sgreen } 187657429Smarkm } 187757429Smarkm if (options->escape_char == -1) 187857429Smarkm options->escape_char = '~'; 1879226046Sdes if (options->num_system_hostfiles == 0) { 1880226046Sdes options->system_hostfiles[options->num_system_hostfiles++] = 1881226046Sdes xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); 1882226046Sdes options->system_hostfiles[options->num_system_hostfiles++] = 1883226046Sdes xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); 1884226046Sdes } 1885226046Sdes if (options->num_user_hostfiles == 0) { 1886226046Sdes options->user_hostfiles[options->num_user_hostfiles++] = 1887226046Sdes xstrdup(_PATH_SSH_USER_HOSTFILE); 1888226046Sdes options->user_hostfiles[options->num_user_hostfiles++] = 1889226046Sdes xstrdup(_PATH_SSH_USER_HOSTFILE2); 1890226046Sdes } 189192559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 189257429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 189392559Sdes if (options->clear_forwardings == 1) 189492559Sdes clear_forwardings(options); 189592559Sdes if (options->no_host_authentication_for_localhost == - 1) 189692559Sdes options->no_host_authentication_for_localhost = 0; 1897128460Sdes if (options->identities_only == -1) 1898128460Sdes options->identities_only = 0; 1899113911Sdes if (options->enable_ssh_keysign == -1) 1900113911Sdes options->enable_ssh_keysign = 0; 1901124211Sdes if (options->rekey_limit == -1) 1902124211Sdes options->rekey_limit = 0; 1903255767Sdes if (options->rekey_interval == -1) 1904255767Sdes options->rekey_interval = 0; 1905255461Sdes#if HAVE_LDNS 1906124211Sdes if (options->verify_host_key_dns == -1) 1907255461Sdes /* automatically trust a verified SSHFP record */ 1908255461Sdes options->verify_host_key_dns = 1; 1909255461Sdes#else 1910255461Sdes if (options->verify_host_key_dns == -1) 1911124211Sdes options->verify_host_key_dns = 0; 1912255461Sdes#endif 1913126277Sdes if (options->server_alive_interval == -1) 1914126277Sdes options->server_alive_interval = 0; 1915126277Sdes if (options->server_alive_count_max == -1) 1916126277Sdes options->server_alive_count_max = 3; 1917137019Sdes if (options->control_master == -1) 1918137019Sdes options->control_master = 0; 1919215116Sdes if (options->control_persist == -1) { 1920215116Sdes options->control_persist = 0; 1921215116Sdes options->control_persist_timeout = 0; 1922215116Sdes } 1923147005Sdes if (options->hash_known_hosts == -1) 1924147005Sdes options->hash_known_hosts = 0; 1925157019Sdes if (options->tun_open == -1) 1926157019Sdes options->tun_open = SSH_TUNMODE_NO; 1927157019Sdes if (options->tun_local == -1) 1928157019Sdes options->tun_local = SSH_TUNID_ANY; 1929157019Sdes if (options->tun_remote == -1) 1930157019Sdes options->tun_remote = SSH_TUNID_ANY; 1931157019Sdes if (options->permit_local_command == -1) 1932157019Sdes options->permit_local_command = 0; 1933181111Sdes if (options->visual_host_key == -1) 1934181111Sdes options->visual_host_key = 0; 1935221420Sdes if (options->ip_qos_interactive == -1) 1936221420Sdes options->ip_qos_interactive = IPTOS_LOWDELAY; 1937221420Sdes if (options->ip_qos_bulk == -1) 1938221420Sdes options->ip_qos_bulk = IPTOS_THROUGHPUT; 1939226046Sdes if (options->request_tty == -1) 1940226046Sdes options->request_tty = REQUEST_TTY_AUTO; 1941262566Sdes if (options->proxy_use_fdpass == -1) 1942262566Sdes options->proxy_use_fdpass = 0; 1943262566Sdes if (options->canonicalize_max_dots == -1) 1944262566Sdes options->canonicalize_max_dots = 1; 1945262566Sdes if (options->canonicalize_fallback_local == -1) 1946262566Sdes options->canonicalize_fallback_local = 1; 1947262566Sdes if (options->canonicalize_hostname == -1) 1948262566Sdes options->canonicalize_hostname = SSH_CANONICALISE_NO; 1949295367Sdes if (options->fingerprint_hash == -1) 1950295367Sdes options->fingerprint_hash = SSH_FP_HASH_DEFAULT; 1951295367Sdes if (options->update_hostkeys == -1) 1952295367Sdes options->update_hostkeys = 0; 1953295367Sdes if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || 1954295367Sdes kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || 1955295367Sdes kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || 1956295367Sdes kex_assemble_names(KEX_DEFAULT_PK_ALG, 1957295367Sdes &options->hostbased_key_types) != 0 || 1958295367Sdes kex_assemble_names(KEX_DEFAULT_PK_ALG, 1959295367Sdes &options->pubkey_key_types) != 0) 1960295367Sdes fatal("%s: kex_assemble_names failed", __func__); 1961295367Sdes 1962262566Sdes#define CLEAR_ON_NONE(v) \ 1963262566Sdes do { \ 1964264377Sdes if (option_clear_or_none(v)) { \ 1965262566Sdes free(v); \ 1966262566Sdes v = NULL; \ 1967262566Sdes } \ 1968262566Sdes } while(0) 1969262566Sdes CLEAR_ON_NONE(options->local_command); 1970262566Sdes CLEAR_ON_NONE(options->proxy_command); 1971262566Sdes CLEAR_ON_NONE(options->control_path); 1972295367Sdes CLEAR_ON_NONE(options->revoked_host_keys); 197357429Smarkm /* options->user will be set in the main program if appropriate */ 197457429Smarkm /* options->hostname will be set in the main program if appropriate */ 197576262Sgreen /* options->host_key_alias should not be set by default */ 197676262Sgreen /* options->preferred_authentications will be set in ssh */ 1977240075Sdes if (options->version_addendum == NULL) 1978240075Sdes options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); 197957429Smarkm} 1980147005Sdes 1981295367Sdesstruct fwdarg { 1982295367Sdes char *arg; 1983295367Sdes int ispath; 1984295367Sdes}; 1985295367Sdes 1986147005Sdes/* 1987295367Sdes * parse_fwd_field 1988295367Sdes * parses the next field in a port forwarding specification. 1989295367Sdes * sets fwd to the parsed field and advances p past the colon 1990295367Sdes * or sets it to NULL at end of string. 1991295367Sdes * returns 0 on success, else non-zero. 1992295367Sdes */ 1993295367Sdesstatic int 1994295367Sdesparse_fwd_field(char **p, struct fwdarg *fwd) 1995295367Sdes{ 1996295367Sdes char *ep, *cp = *p; 1997295367Sdes int ispath = 0; 1998295367Sdes 1999295367Sdes if (*cp == '\0') { 2000295367Sdes *p = NULL; 2001295367Sdes return -1; /* end of string */ 2002295367Sdes } 2003295367Sdes 2004295367Sdes /* 2005295367Sdes * A field escaped with square brackets is used literally. 2006295367Sdes * XXX - allow ']' to be escaped via backslash? 2007295367Sdes */ 2008295367Sdes if (*cp == '[') { 2009295367Sdes /* find matching ']' */ 2010295367Sdes for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { 2011295367Sdes if (*ep == '/') 2012295367Sdes ispath = 1; 2013295367Sdes } 2014295367Sdes /* no matching ']' or not at end of field. */ 2015295367Sdes if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) 2016295367Sdes return -1; 2017295367Sdes /* NUL terminate the field and advance p past the colon */ 2018295367Sdes *ep++ = '\0'; 2019295367Sdes if (*ep != '\0') 2020295367Sdes *ep++ = '\0'; 2021295367Sdes fwd->arg = cp + 1; 2022295367Sdes fwd->ispath = ispath; 2023295367Sdes *p = ep; 2024295367Sdes return 0; 2025295367Sdes } 2026295367Sdes 2027295367Sdes for (cp = *p; *cp != '\0'; cp++) { 2028295367Sdes switch (*cp) { 2029295367Sdes case '\\': 2030295367Sdes memmove(cp, cp + 1, strlen(cp + 1) + 1); 2031295367Sdes if (*cp == '\0') 2032295367Sdes return -1; 2033295367Sdes break; 2034295367Sdes case '/': 2035295367Sdes ispath = 1; 2036295367Sdes break; 2037295367Sdes case ':': 2038295367Sdes *cp++ = '\0'; 2039295367Sdes goto done; 2040295367Sdes } 2041295367Sdes } 2042295367Sdesdone: 2043295367Sdes fwd->arg = *p; 2044295367Sdes fwd->ispath = ispath; 2045295367Sdes *p = cp; 2046295367Sdes return 0; 2047295367Sdes} 2048295367Sdes 2049295367Sdes/* 2050147005Sdes * parse_forward 2051147005Sdes * parses a string containing a port forwarding specification of the form: 2052192595Sdes * dynamicfwd == 0 2053295367Sdes * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath 2054295367Sdes * listenpath:connectpath 2055192595Sdes * dynamicfwd == 1 2056192595Sdes * [listenhost:]listenport 2057147005Sdes * returns number of arguments parsed or zero on error 2058147005Sdes */ 2059147005Sdesint 2060295367Sdesparse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 2061147005Sdes{ 2062295367Sdes struct fwdarg fwdargs[4]; 2063295367Sdes char *p, *cp; 2064147005Sdes int i; 2065147005Sdes 2066295367Sdes memset(fwd, 0, sizeof(*fwd)); 2067295367Sdes memset(fwdargs, 0, sizeof(fwdargs)); 2068147005Sdes 2069147005Sdes cp = p = xstrdup(fwdspec); 2070147005Sdes 2071147005Sdes /* skip leading spaces */ 2072262566Sdes while (isspace((u_char)*cp)) 2073147005Sdes cp++; 2074147005Sdes 2075295367Sdes for (i = 0; i < 4; ++i) { 2076295367Sdes if (parse_fwd_field(&cp, &fwdargs[i]) != 0) 2077147005Sdes break; 2078295367Sdes } 2079147005Sdes 2080192595Sdes /* Check for trailing garbage */ 2081295367Sdes if (cp != NULL && *cp != '\0') { 2082147005Sdes i = 0; /* failure */ 2083295367Sdes } 2084147005Sdes 2085147005Sdes switch (i) { 2086192595Sdes case 1: 2087295367Sdes if (fwdargs[0].ispath) { 2088295367Sdes fwd->listen_path = xstrdup(fwdargs[0].arg); 2089295367Sdes fwd->listen_port = PORT_STREAMLOCAL; 2090295367Sdes } else { 2091295367Sdes fwd->listen_host = NULL; 2092295367Sdes fwd->listen_port = a2port(fwdargs[0].arg); 2093295367Sdes } 2094192595Sdes fwd->connect_host = xstrdup("socks"); 2095192595Sdes break; 2096192595Sdes 2097192595Sdes case 2: 2098295367Sdes if (fwdargs[0].ispath && fwdargs[1].ispath) { 2099295367Sdes fwd->listen_path = xstrdup(fwdargs[0].arg); 2100295367Sdes fwd->listen_port = PORT_STREAMLOCAL; 2101295367Sdes fwd->connect_path = xstrdup(fwdargs[1].arg); 2102295367Sdes fwd->connect_port = PORT_STREAMLOCAL; 2103295367Sdes } else if (fwdargs[1].ispath) { 2104295367Sdes fwd->listen_host = NULL; 2105295367Sdes fwd->listen_port = a2port(fwdargs[0].arg); 2106295367Sdes fwd->connect_path = xstrdup(fwdargs[1].arg); 2107295367Sdes fwd->connect_port = PORT_STREAMLOCAL; 2108295367Sdes } else { 2109295367Sdes fwd->listen_host = xstrdup(fwdargs[0].arg); 2110295367Sdes fwd->listen_port = a2port(fwdargs[1].arg); 2111295367Sdes fwd->connect_host = xstrdup("socks"); 2112295367Sdes } 2113192595Sdes break; 2114192595Sdes 2115147005Sdes case 3: 2116295367Sdes if (fwdargs[0].ispath) { 2117295367Sdes fwd->listen_path = xstrdup(fwdargs[0].arg); 2118295367Sdes fwd->listen_port = PORT_STREAMLOCAL; 2119295367Sdes fwd->connect_host = xstrdup(fwdargs[1].arg); 2120295367Sdes fwd->connect_port = a2port(fwdargs[2].arg); 2121295367Sdes } else if (fwdargs[2].ispath) { 2122295367Sdes fwd->listen_host = xstrdup(fwdargs[0].arg); 2123295367Sdes fwd->listen_port = a2port(fwdargs[1].arg); 2124295367Sdes fwd->connect_path = xstrdup(fwdargs[2].arg); 2125295367Sdes fwd->connect_port = PORT_STREAMLOCAL; 2126295367Sdes } else { 2127295367Sdes fwd->listen_host = NULL; 2128295367Sdes fwd->listen_port = a2port(fwdargs[0].arg); 2129295367Sdes fwd->connect_host = xstrdup(fwdargs[1].arg); 2130295367Sdes fwd->connect_port = a2port(fwdargs[2].arg); 2131295367Sdes } 2132147005Sdes break; 2133147005Sdes 2134147005Sdes case 4: 2135295367Sdes fwd->listen_host = xstrdup(fwdargs[0].arg); 2136295367Sdes fwd->listen_port = a2port(fwdargs[1].arg); 2137295367Sdes fwd->connect_host = xstrdup(fwdargs[2].arg); 2138295367Sdes fwd->connect_port = a2port(fwdargs[3].arg); 2139147005Sdes break; 2140147005Sdes default: 2141147005Sdes i = 0; /* failure */ 2142147005Sdes } 2143147005Sdes 2144255767Sdes free(p); 2145147005Sdes 2146192595Sdes if (dynamicfwd) { 2147192595Sdes if (!(i == 1 || i == 2)) 2148192595Sdes goto fail_free; 2149192595Sdes } else { 2150295367Sdes if (!(i == 3 || i == 4)) { 2151295367Sdes if (fwd->connect_path == NULL && 2152295367Sdes fwd->listen_path == NULL) 2153295367Sdes goto fail_free; 2154295367Sdes } 2155295367Sdes if (fwd->connect_port <= 0 && fwd->connect_path == NULL) 2156192595Sdes goto fail_free; 2157192595Sdes } 2158192595Sdes 2159295367Sdes if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || 2160295367Sdes (!remotefwd && fwd->listen_port == 0)) 2161147005Sdes goto fail_free; 2162147005Sdes if (fwd->connect_host != NULL && 2163147005Sdes strlen(fwd->connect_host) >= NI_MAXHOST) 2164147005Sdes goto fail_free; 2165295367Sdes /* XXX - if connecting to a remote socket, max sun len may not match this host */ 2166295367Sdes if (fwd->connect_path != NULL && 2167295367Sdes strlen(fwd->connect_path) >= PATH_MAX_SUN) 2168295367Sdes goto fail_free; 2169192595Sdes if (fwd->listen_host != NULL && 2170192595Sdes strlen(fwd->listen_host) >= NI_MAXHOST) 2171192595Sdes goto fail_free; 2172295367Sdes if (fwd->listen_path != NULL && 2173295367Sdes strlen(fwd->listen_path) >= PATH_MAX_SUN) 2174295367Sdes goto fail_free; 2175147005Sdes 2176147005Sdes return (i); 2177147005Sdes 2178147005Sdes fail_free: 2179255767Sdes free(fwd->connect_host); 2180255767Sdes fwd->connect_host = NULL; 2181295367Sdes free(fwd->connect_path); 2182295367Sdes fwd->connect_path = NULL; 2183255767Sdes free(fwd->listen_host); 2184255767Sdes fwd->listen_host = NULL; 2185295367Sdes free(fwd->listen_path); 2186295367Sdes fwd->listen_path = NULL; 2187147005Sdes return (0); 2188147005Sdes} 2189295367Sdes 2190295367Sdes/* XXX the following is a near-vebatim copy from servconf.c; refactor */ 2191295367Sdesstatic const char * 2192295367Sdesfmt_multistate_int(int val, const struct multistate *m) 2193295367Sdes{ 2194295367Sdes u_int i; 2195295367Sdes 2196295367Sdes for (i = 0; m[i].key != NULL; i++) { 2197295367Sdes if (m[i].value == val) 2198295367Sdes return m[i].key; 2199295367Sdes } 2200295367Sdes return "UNKNOWN"; 2201295367Sdes} 2202295367Sdes 2203295367Sdesstatic const char * 2204295367Sdesfmt_intarg(OpCodes code, int val) 2205295367Sdes{ 2206295367Sdes if (val == -1) 2207295367Sdes return "unset"; 2208295367Sdes switch (code) { 2209295367Sdes case oAddressFamily: 2210295367Sdes return fmt_multistate_int(val, multistate_addressfamily); 2211295367Sdes case oVerifyHostKeyDNS: 2212295367Sdes case oStrictHostKeyChecking: 2213295367Sdes case oUpdateHostkeys: 2214295367Sdes return fmt_multistate_int(val, multistate_yesnoask); 2215295367Sdes case oControlMaster: 2216295367Sdes return fmt_multistate_int(val, multistate_controlmaster); 2217295367Sdes case oTunnel: 2218295367Sdes return fmt_multistate_int(val, multistate_tunnel); 2219295367Sdes case oRequestTTY: 2220295367Sdes return fmt_multistate_int(val, multistate_requesttty); 2221295367Sdes case oCanonicalizeHostname: 2222295367Sdes return fmt_multistate_int(val, multistate_canonicalizehostname); 2223295367Sdes case oFingerprintHash: 2224295367Sdes return ssh_digest_alg_name(val); 2225295367Sdes case oProtocol: 2226295367Sdes switch (val) { 2227295367Sdes case SSH_PROTO_1: 2228295367Sdes return "1"; 2229295367Sdes case SSH_PROTO_2: 2230295367Sdes return "2"; 2231295367Sdes case (SSH_PROTO_1|SSH_PROTO_2): 2232295367Sdes return "2,1"; 2233295367Sdes default: 2234295367Sdes return "UNKNOWN"; 2235295367Sdes } 2236295367Sdes default: 2237295367Sdes switch (val) { 2238295367Sdes case 0: 2239295367Sdes return "no"; 2240295367Sdes case 1: 2241295367Sdes return "yes"; 2242295367Sdes default: 2243295367Sdes return "UNKNOWN"; 2244295367Sdes } 2245295367Sdes } 2246295367Sdes} 2247295367Sdes 2248295367Sdesstatic const char * 2249295367Sdeslookup_opcode_name(OpCodes code) 2250295367Sdes{ 2251295367Sdes u_int i; 2252295367Sdes 2253295367Sdes for (i = 0; keywords[i].name != NULL; i++) 2254295367Sdes if (keywords[i].opcode == code) 2255295367Sdes return(keywords[i].name); 2256295367Sdes return "UNKNOWN"; 2257295367Sdes} 2258295367Sdes 2259295367Sdesstatic void 2260295367Sdesdump_cfg_int(OpCodes code, int val) 2261295367Sdes{ 2262295367Sdes printf("%s %d\n", lookup_opcode_name(code), val); 2263295367Sdes} 2264295367Sdes 2265295367Sdesstatic void 2266295367Sdesdump_cfg_fmtint(OpCodes code, int val) 2267295367Sdes{ 2268295367Sdes printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); 2269295367Sdes} 2270295367Sdes 2271295367Sdesstatic void 2272295367Sdesdump_cfg_string(OpCodes code, const char *val) 2273295367Sdes{ 2274295367Sdes if (val == NULL) 2275295367Sdes return; 2276295367Sdes printf("%s %s\n", lookup_opcode_name(code), val); 2277295367Sdes} 2278295367Sdes 2279295367Sdesstatic void 2280295367Sdesdump_cfg_strarray(OpCodes code, u_int count, char **vals) 2281295367Sdes{ 2282295367Sdes u_int i; 2283295367Sdes 2284295367Sdes for (i = 0; i < count; i++) 2285295367Sdes printf("%s %s\n", lookup_opcode_name(code), vals[i]); 2286295367Sdes} 2287295367Sdes 2288295367Sdesstatic void 2289295367Sdesdump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) 2290295367Sdes{ 2291295367Sdes u_int i; 2292295367Sdes 2293295367Sdes printf("%s", lookup_opcode_name(code)); 2294295367Sdes for (i = 0; i < count; i++) 2295295367Sdes printf(" %s", vals[i]); 2296295367Sdes printf("\n"); 2297295367Sdes} 2298295367Sdes 2299295367Sdesstatic void 2300295367Sdesdump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) 2301295367Sdes{ 2302295367Sdes const struct Forward *fwd; 2303295367Sdes u_int i; 2304295367Sdes 2305295367Sdes /* oDynamicForward */ 2306295367Sdes for (i = 0; i < count; i++) { 2307295367Sdes fwd = &fwds[i]; 2308295367Sdes if (code == oDynamicForward && 2309295367Sdes strcmp(fwd->connect_host, "socks") != 0) 2310295367Sdes continue; 2311295367Sdes if (code == oLocalForward && 2312295367Sdes strcmp(fwd->connect_host, "socks") == 0) 2313295367Sdes continue; 2314295367Sdes printf("%s", lookup_opcode_name(code)); 2315295367Sdes if (fwd->listen_port == PORT_STREAMLOCAL) 2316295367Sdes printf(" %s", fwd->listen_path); 2317295367Sdes else if (fwd->listen_host == NULL) 2318295367Sdes printf(" %d", fwd->listen_port); 2319295367Sdes else { 2320295367Sdes printf(" [%s]:%d", 2321295367Sdes fwd->listen_host, fwd->listen_port); 2322295367Sdes } 2323295367Sdes if (code != oDynamicForward) { 2324295367Sdes if (fwd->connect_port == PORT_STREAMLOCAL) 2325295367Sdes printf(" %s", fwd->connect_path); 2326295367Sdes else if (fwd->connect_host == NULL) 2327295367Sdes printf(" %d", fwd->connect_port); 2328295367Sdes else { 2329295367Sdes printf(" [%s]:%d", 2330295367Sdes fwd->connect_host, fwd->connect_port); 2331295367Sdes } 2332295367Sdes } 2333295367Sdes printf("\n"); 2334295367Sdes } 2335295367Sdes} 2336295367Sdes 2337295367Sdesvoid 2338295367Sdesdump_client_config(Options *o, const char *host) 2339295367Sdes{ 2340295367Sdes int i; 2341295367Sdes char vbuf[5]; 2342295367Sdes 2343296853Sdes /* This is normally prepared in ssh_kex2 */ 2344296853Sdes if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0) 2345296853Sdes fatal("%s: kex_assemble_names failed", __func__); 2346296853Sdes 2347295367Sdes /* Most interesting options first: user, host, port */ 2348295367Sdes dump_cfg_string(oUser, o->user); 2349295367Sdes dump_cfg_string(oHostName, host); 2350295367Sdes dump_cfg_int(oPort, o->port); 2351295367Sdes 2352295367Sdes /* Flag options */ 2353295367Sdes dump_cfg_fmtint(oAddressFamily, o->address_family); 2354295367Sdes dump_cfg_fmtint(oBatchMode, o->batch_mode); 2355295367Sdes dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); 2356295367Sdes dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); 2357295367Sdes dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); 2358295367Sdes dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); 2359295367Sdes dump_cfg_fmtint(oCompression, o->compression); 2360295367Sdes dump_cfg_fmtint(oControlMaster, o->control_master); 2361295367Sdes dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); 2362295367Sdes dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); 2363295367Sdes dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); 2364295367Sdes dump_cfg_fmtint(oForwardAgent, o->forward_agent); 2365295367Sdes dump_cfg_fmtint(oForwardX11, o->forward_x11); 2366295367Sdes dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); 2367295367Sdes dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); 2368295367Sdes#ifdef GSSAPI 2369295367Sdes dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); 2370295367Sdes dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); 2371295367Sdes#endif /* GSSAPI */ 2372295367Sdes dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); 2373295367Sdes dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); 2374295367Sdes dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); 2375295367Sdes dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); 2376295367Sdes dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); 2377295367Sdes dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); 2378295367Sdes dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); 2379295367Sdes dump_cfg_fmtint(oProtocol, o->protocol); 2380295367Sdes dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); 2381295367Sdes dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); 2382295367Sdes dump_cfg_fmtint(oRequestTTY, o->request_tty); 2383295367Sdes dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication); 2384295367Sdes dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication); 2385295367Sdes dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); 2386295367Sdes dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); 2387295367Sdes dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); 2388295367Sdes dump_cfg_fmtint(oTunnel, o->tun_open); 2389295367Sdes dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); 2390295367Sdes dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); 2391295367Sdes dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); 2392295367Sdes dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); 2393295367Sdes 2394295367Sdes /* Integer options */ 2395295367Sdes dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); 2396295367Sdes dump_cfg_int(oCompressionLevel, o->compression_level); 2397295367Sdes dump_cfg_int(oConnectionAttempts, o->connection_attempts); 2398295367Sdes dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); 2399295367Sdes dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); 2400295367Sdes dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); 2401295367Sdes dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 2402295367Sdes 2403295367Sdes /* String options */ 2404295367Sdes dump_cfg_string(oBindAddress, o->bind_address); 2405295367Sdes dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); 2406295367Sdes dump_cfg_string(oControlPath, o->control_path); 2407296853Sdes dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); 2408295367Sdes dump_cfg_string(oHostKeyAlias, o->host_key_alias); 2409295367Sdes dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); 2410295367Sdes dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); 2411295367Sdes dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); 2412295367Sdes dump_cfg_string(oLocalCommand, o->local_command); 2413295367Sdes dump_cfg_string(oLogLevel, log_level_name(o->log_level)); 2414295367Sdes dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); 2415295367Sdes dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); 2416295367Sdes dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); 2417295367Sdes dump_cfg_string(oProxyCommand, o->proxy_command); 2418296853Sdes dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); 2419295367Sdes dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); 2420295367Sdes dump_cfg_string(oXAuthLocation, o->xauth_location); 2421295367Sdes 2422295367Sdes /* Forwards */ 2423295367Sdes dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); 2424295367Sdes dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); 2425295367Sdes dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); 2426295367Sdes 2427295367Sdes /* String array options */ 2428295367Sdes dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); 2429295367Sdes dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); 2430295367Sdes dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); 2431295367Sdes dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); 2432295367Sdes dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); 2433295367Sdes 2434295367Sdes /* Special cases */ 2435295367Sdes 2436295367Sdes /* oConnectTimeout */ 2437295367Sdes if (o->connection_timeout == -1) 2438295367Sdes printf("connecttimeout none\n"); 2439295367Sdes else 2440295367Sdes dump_cfg_int(oConnectTimeout, o->connection_timeout); 2441295367Sdes 2442295367Sdes /* oTunnelDevice */ 2443295367Sdes printf("tunneldevice"); 2444295367Sdes if (o->tun_local == SSH_TUNID_ANY) 2445295367Sdes printf(" any"); 2446295367Sdes else 2447295367Sdes printf(" %d", o->tun_local); 2448295367Sdes if (o->tun_remote == SSH_TUNID_ANY) 2449295367Sdes printf(":any"); 2450295367Sdes else 2451295367Sdes printf(":%d", o->tun_remote); 2452295367Sdes printf("\n"); 2453295367Sdes 2454295367Sdes /* oCanonicalizePermittedCNAMEs */ 2455295367Sdes if ( o->num_permitted_cnames > 0) { 2456295367Sdes printf("canonicalizePermittedcnames"); 2457295367Sdes for (i = 0; i < o->num_permitted_cnames; i++) { 2458295367Sdes printf(" %s:%s", o->permitted_cnames[i].source_list, 2459295367Sdes o->permitted_cnames[i].target_list); 2460295367Sdes } 2461295367Sdes printf("\n"); 2462295367Sdes } 2463295367Sdes 2464295367Sdes /* oCipher */ 2465295367Sdes if (o->cipher != SSH_CIPHER_NOT_SET) 2466295367Sdes printf("Cipher %s\n", cipher_name(o->cipher)); 2467295367Sdes 2468295367Sdes /* oControlPersist */ 2469295367Sdes if (o->control_persist == 0 || o->control_persist_timeout == 0) 2470295367Sdes dump_cfg_fmtint(oControlPersist, o->control_persist); 2471295367Sdes else 2472295367Sdes dump_cfg_int(oControlPersist, o->control_persist_timeout); 2473295367Sdes 2474295367Sdes /* oEscapeChar */ 2475295367Sdes if (o->escape_char == SSH_ESCAPECHAR_NONE) 2476295367Sdes printf("escapechar none\n"); 2477295367Sdes else { 2478295367Sdes vis(vbuf, o->escape_char, VIS_WHITE, 0); 2479295367Sdes printf("escapechar %s\n", vbuf); 2480295367Sdes } 2481295367Sdes 2482295367Sdes /* oIPQoS */ 2483295367Sdes printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); 2484295367Sdes printf("%s\n", iptos2str(o->ip_qos_bulk)); 2485295367Sdes 2486295367Sdes /* oRekeyLimit */ 2487296853Sdes printf("rekeylimit %llu %d\n", 2488296853Sdes (unsigned long long)o->rekey_limit, o->rekey_interval); 2489295367Sdes 2490295367Sdes /* oStreamLocalBindMask */ 2491295367Sdes printf("streamlocalbindmask 0%o\n", 2492295367Sdes o->fwd_opts.streamlocal_bind_mask); 2493295367Sdes} 2494