1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409 |
- /* $OpenBSD: readconf.c,v 1.335 2020/08/27 02:11:09 djm Exp $ */
- /*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- * All rights reserved
- * Functions for reading the configuration files.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose. Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- */
- #include "includes.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <arpa/inet.h>
- #include <ctype.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <netdb.h>
- #ifdef HAVE_PATHS_H
- # include <paths.h>
- #endif
- #include <pwd.h>
- #include <signal.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <unistd.h>
- #ifdef USE_SYSTEM_GLOB
- # include <glob.h>
- #else
- # include "openbsd-compat/glob.h"
- #endif
- #ifdef HAVE_UTIL_H
- #include <util.h>
- #endif
- #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
- # include <vis.h>
- #endif
- #include "xmalloc.h"
- #include "ssh.h"
- #include "ssherr.h"
- #include "compat.h"
- #include "cipher.h"
- #include "pathnames.h"
- #include "log.h"
- #include "sshkey.h"
- #include "misc.h"
- #include "readconf.h"
- #include "match.h"
- #include "kex.h"
- #include "mac.h"
- #include "uidswap.h"
- #include "myproposal.h"
- #include "digest.h"
- #include "sshbuf.h"
- /* Format of the configuration file:
- # Configuration data is parsed as follows:
- # 1. command line options
- # 2. user-specific file
- # 3. system-wide file
- # Any configuration value is only changed the first time it is set.
- # Thus, host-specific definitions should be at the beginning of the
- # configuration file, and defaults at the end.
- # Host-specific declarations. These may override anything above. A single
- # host may match multiple declarations; these are processed in the order
- # that they are given in.
- Host *.ngs.fi ngs.fi
- User foo
- Host fake.com
- Hostname another.host.name.real.org
- User blaah
- Port 34289
- ForwardX11 no
- ForwardAgent no
- Host books.com
- RemoteForward 9999 shadows.cs.hut.fi:9999
- Ciphers 3des-cbc
- Host fascist.blob.com
- Port 23123
- User tylonen
- PasswordAuthentication no
- Host puukko.hut.fi
- User t35124p
- ProxyCommand ssh-proxy %h %p
- Host *.fr
- PublicKeyAuthentication no
- Host *.su
- Ciphers aes128-ctr
- PasswordAuthentication no
- Host vpn.fake.com
- Tunnel yes
- TunnelDevice 3
- # Defaults for various options
- Host *
- ForwardAgent no
- ForwardX11 no
- PasswordAuthentication yes
- StrictHostKeyChecking yes
- TcpKeepAlive no
- IdentityFile ~/.ssh/identity
- Port 22
- EscapeChar ~
- */
- static int read_config_file_depth(const char *filename, struct passwd *pw,
- const char *host, const char *original_host, Options *options,
- int flags, int *activep, int *want_final_pass, int depth);
- static int process_config_line_depth(Options *options, struct passwd *pw,
- const char *host, const char *original_host, char *line,
- const char *filename, int linenum, int *activep, int flags,
- int *want_final_pass, int depth);
- /* Keyword tokens. */
- typedef enum {
- oBadOption,
- oHost, oMatch, oInclude,
- oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
- oGatewayPorts, oExitOnForwardFailure,
- oPasswordAuthentication,
- oChallengeResponseAuthentication, oXAuthLocation,
- oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
- oPermitRemoteOpen,
- oCertificateFile, oAddKeysToAgent, oIdentityAgent,
- oUser, oEscapeChar, oProxyCommand,
- oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
- oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
- oTCPKeepAlive, oNumberOfPasswordPrompts,
- oLogFacility, oLogLevel, oCiphers, oMacs,
- oPubkeyAuthentication,
- oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
- oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
- oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
- oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
- oAddressFamily, oGssAuthentication, oGssDelegateCreds,
- oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
- oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
- oHashKnownHosts,
- oTunnel, oTunnelDevice,
- oLocalCommand, oPermitLocalCommand, oRemoteCommand,
- oTcpRcvBufPoll, oTcpRcvBuf, oHPNDisabled, oHPNBufferSize,
- oNoneEnabled, oNoneMacEnabled, oNoneSwitch,
- oDisableMTAES,
- oVisualHostKey,
- oKexAlgorithms, oIPQoS, oRequestTTY, oNoShell, oStdinNull,
- oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
- oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
- oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
- oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
- oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
- oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
- oSecurityKeyProvider,
- oProtocolKeepAlives, oSetupTimeOut,
- oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
- } OpCodes;
- /* Textual representations of the tokens. */
- static struct {
- const char *name;
- OpCodes opcode;
- } keywords[] = {
- /* Deprecated options */
- { "protocol", oIgnore }, /* NB. silently ignored */
- { "cipher", oDeprecated },
- { "fallbacktorsh", oDeprecated },
- { "globalknownhostsfile2", oDeprecated },
- { "rhostsauthentication", oDeprecated },
- { "useblacklistedkeys", oDeprecated },
- { "userknownhostsfile2", oDeprecated },
- { "useroaming", oDeprecated },
- { "usersh", oDeprecated },
- { "useprivilegedport", oDeprecated },
- /* Unsupported options */
- { "afstokenpassing", oUnsupported },
- { "kerberosauthentication", oUnsupported },
- { "kerberostgtpassing", oUnsupported },
- { "rsaauthentication", oUnsupported },
- { "rhostsrsaauthentication", oUnsupported },
- { "compressionlevel", oUnsupported },
- /* Sometimes-unsupported options */
- #if defined(GSSAPI)
- { "gssapiauthentication", oGssAuthentication },
- { "gssapidelegatecredentials", oGssDelegateCreds },
- # else
- { "gssapiauthentication", oUnsupported },
- { "gssapidelegatecredentials", oUnsupported },
- #endif
- #ifdef ENABLE_PKCS11
- { "pkcs11provider", oPKCS11Provider },
- { "smartcarddevice", oPKCS11Provider },
- # else
- { "smartcarddevice", oUnsupported },
- { "pkcs11provider", oUnsupported },
- #endif
- { "forwardagent", oForwardAgent },
- { "forwardx11", oForwardX11 },
- { "forwardx11trusted", oForwardX11Trusted },
- { "forwardx11timeout", oForwardX11Timeout },
- { "exitonforwardfailure", oExitOnForwardFailure },
- { "xauthlocation", oXAuthLocation },
- { "gatewayports", oGatewayPorts },
- { "passwordauthentication", oPasswordAuthentication },
- { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
- { "kbdinteractivedevices", oKbdInteractiveDevices },
- { "pubkeyauthentication", oPubkeyAuthentication },
- { "dsaauthentication", oPubkeyAuthentication }, /* alias */
- { "hostbasedauthentication", oHostbasedAuthentication },
- { "challengeresponseauthentication", oChallengeResponseAuthentication },
- { "skeyauthentication", oUnsupported },
- { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
- { "identityfile", oIdentityFile },
- { "identityfile2", oIdentityFile }, /* obsolete */
- { "identitiesonly", oIdentitiesOnly },
- { "certificatefile", oCertificateFile },
- { "addkeystoagent", oAddKeysToAgent },
- { "identityagent", oIdentityAgent },
- { "hostname", oHostname },
- { "hostkeyalias", oHostKeyAlias },
- { "proxycommand", oProxyCommand },
- { "port", oPort },
- { "ciphers", oCiphers },
- { "macs", oMacs },
- { "remoteforward", oRemoteForward },
- { "localforward", oLocalForward },
- { "permitremoteopen", oPermitRemoteOpen },
- { "user", oUser },
- { "host", oHost },
- { "match", oMatch },
- { "escapechar", oEscapeChar },
- { "globalknownhostsfile", oGlobalKnownHostsFile },
- { "userknownhostsfile", oUserKnownHostsFile },
- { "connectionattempts", oConnectionAttempts },
- { "batchmode", oBatchMode },
- { "checkhostip", oCheckHostIP },
- { "stricthostkeychecking", oStrictHostKeyChecking },
- { "compression", oCompression },
- { "tcpkeepalive", oTCPKeepAlive },
- { "keepalive", oTCPKeepAlive }, /* obsolete */
- { "numberofpasswordprompts", oNumberOfPasswordPrompts },
- { "syslogfacility", oLogFacility },
- { "loglevel", oLogLevel },
- { "dynamicforward", oDynamicForward },
- { "preferredauthentications", oPreferredAuthentications },
- { "hostkeyalgorithms", oHostKeyAlgorithms },
- { "casignaturealgorithms", oCASignatureAlgorithms },
- { "bindaddress", oBindAddress },
- { "bindinterface", oBindInterface },
- { "clearallforwardings", oClearAllForwardings },
- { "enablesshkeysign", oEnableSSHKeysign },
- { "verifyhostkeydns", oVerifyHostKeyDNS },
- { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
- { "rekeylimit", oRekeyLimit },
- { "connecttimeout", oConnectTimeout },
- { "addressfamily", oAddressFamily },
- { "serveraliveinterval", oServerAliveInterval },
- { "serveralivecountmax", oServerAliveCountMax },
- { "sendenv", oSendEnv },
- { "setenv", oSetEnv },
- { "controlpath", oControlPath },
- { "controlmaster", oControlMaster },
- { "controlpersist", oControlPersist },
- { "hashknownhosts", oHashKnownHosts },
- { "include", oInclude },
- { "tunnel", oTunnel },
- { "tunneldevice", oTunnelDevice },
- { "localcommand", oLocalCommand },
- { "permitlocalcommand", oPermitLocalCommand },
- { "remotecommand", oRemoteCommand },
- { "visualhostkey", oVisualHostKey },
- { "kexalgorithms", oKexAlgorithms },
- { "ipqos", oIPQoS },
- { "requesttty", oRequestTTY },
- { "noshell", oNoShell },
- { "stdinnull", oStdinNull },
- { "forkafterauthentication", oForkAfterAuthentication },
- { "noneenabled", oNoneEnabled },
- { "nonemacenabled", oNoneMacEnabled },
- { "noneswitch", oNoneSwitch },
- { "disablemtaes", oDisableMTAES },
- { "proxyusefdpass", oProxyUseFdpass },
- { "canonicaldomains", oCanonicalDomains },
- { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
- { "canonicalizehostname", oCanonicalizeHostname },
- { "canonicalizemaxdots", oCanonicalizeMaxDots },
- { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
- { "streamlocalbindmask", oStreamLocalBindMask },
- { "streamlocalbindunlink", oStreamLocalBindUnlink },
- { "revokedhostkeys", oRevokedHostKeys },
- { "fingerprinthash", oFingerprintHash },
- { "updatehostkeys", oUpdateHostkeys },
- { "hostbasedalgorithms", oHostbasedAcceptedAlgorithms },
- { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
- { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
- { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
- { "ignoreunknown", oIgnoreUnknown },
- { "proxyjump", oProxyJump },
- { "protocolkeepalives", oProtocolKeepAlives },
- { "setuptimeout", oSetupTimeOut },
- { "securitykeyprovider", oSecurityKeyProvider },
- { "tcprcvbufpoll", oTcpRcvBufPoll },
- { "tcprcvbuf", oTcpRcvBuf },
- { "hpndisabled", oHPNDisabled },
- { "hpnbuffersize", oHPNBufferSize },
- { NULL, oBadOption }
- };
- static const char *lookup_opcode_name(OpCodes code);
- const char *
- kex_default_pk_alg(void)
- {
- static char *pkalgs;
- if (pkalgs == NULL) {
- char *all_key;
- all_key = sshkey_alg_list(0, 0, 1, ',');
- pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- free(all_key);
- }
- return pkalgs;
- }
- char *
- ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
- const char *user)
- {
- struct ssh_digest_ctx *md;
- u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
- if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
- ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
- ssh_digest_update(md, host, strlen(host)) < 0 ||
- ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
- ssh_digest_update(md, user, strlen(user)) < 0 ||
- ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
- fatal("%s: mux digest failed", __func__);
- ssh_digest_free(md);
- return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
- }
- /*
- * Adds a local TCP/IP port forward to options. Never returns if there is an
- * error.
- */
- void
- add_local_forward(Options *options, const struct Forward *newfwd)
- {
- struct Forward *fwd;
- int i;
- /* Don't add duplicates */
- for (i = 0; i < options->num_local_forwards; i++) {
- if (forward_equals(newfwd, options->local_forwards + i))
- return;
- }
- options->local_forwards = xreallocarray(options->local_forwards,
- options->num_local_forwards + 1,
- sizeof(*options->local_forwards));
- fwd = &options->local_forwards[options->num_local_forwards++];
- fwd->listen_host = newfwd->listen_host;
- fwd->listen_port = newfwd->listen_port;
- fwd->listen_path = newfwd->listen_path;
- fwd->connect_host = newfwd->connect_host;
- fwd->connect_port = newfwd->connect_port;
- fwd->connect_path = newfwd->connect_path;
- }
- /*
- * Adds a remote TCP/IP port forward to options. Never returns if there is
- * an error.
- */
- void
- add_remote_forward(Options *options, const struct Forward *newfwd)
- {
- struct Forward *fwd;
- int i;
- /* Don't add duplicates */
- for (i = 0; i < options->num_remote_forwards; i++) {
- if (forward_equals(newfwd, options->remote_forwards + i))
- return;
- }
- options->remote_forwards = xreallocarray(options->remote_forwards,
- options->num_remote_forwards + 1,
- sizeof(*options->remote_forwards));
- fwd = &options->remote_forwards[options->num_remote_forwards++];
- fwd->listen_host = newfwd->listen_host;
- fwd->listen_port = newfwd->listen_port;
- fwd->listen_path = newfwd->listen_path;
- fwd->connect_host = newfwd->connect_host;
- fwd->connect_port = newfwd->connect_port;
- fwd->connect_path = newfwd->connect_path;
- fwd->handle = newfwd->handle;
- fwd->allocated_port = 0;
- }
- static void
- clear_forwardings(Options *options)
- {
- int i;
- for (i = 0; i < options->num_local_forwards; i++) {
- free(options->local_forwards[i].listen_host);
- free(options->local_forwards[i].listen_path);
- free(options->local_forwards[i].connect_host);
- free(options->local_forwards[i].connect_path);
- }
- if (options->num_local_forwards > 0) {
- free(options->local_forwards);
- options->local_forwards = NULL;
- }
- options->num_local_forwards = 0;
- for (i = 0; i < options->num_remote_forwards; i++) {
- free(options->remote_forwards[i].listen_host);
- free(options->remote_forwards[i].listen_path);
- free(options->remote_forwards[i].connect_host);
- free(options->remote_forwards[i].connect_path);
- }
- if (options->num_remote_forwards > 0) {
- free(options->remote_forwards);
- options->remote_forwards = NULL;
- }
- options->num_remote_forwards = 0;
- options->tun_open = SSH_TUNMODE_NO;
- }
- void
- add_certificate_file(Options *options, const char *path, int userprovided)
- {
- int i;
- if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
- fatal("Too many certificate files specified (max %d)",
- SSH_MAX_CERTIFICATE_FILES);
- /* Avoid registering duplicates */
- for (i = 0; i < options->num_certificate_files; i++) {
- if (options->certificate_file_userprovided[i] == userprovided &&
- strcmp(options->certificate_files[i], path) == 0) {
- debug2("%s: ignoring duplicate key %s", __func__, path);
- return;
- }
- }
- options->certificate_file_userprovided[options->num_certificate_files] =
- userprovided;
- options->certificate_files[options->num_certificate_files++] =
- xstrdup(path);
- }
- void
- add_identity_file(Options *options, const char *dir, const char *filename,
- int userprovided)
- {
- char *path;
- int i;
- if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
- fatal("Too many identity files specified (max %d)",
- SSH_MAX_IDENTITY_FILES);
- if (dir == NULL) /* no dir, filename is absolute */
- path = xstrdup(filename);
- else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
- fatal("Identity file path %s too long", path);
- /* Avoid registering duplicates */
- for (i = 0; i < options->num_identity_files; i++) {
- if (options->identity_file_userprovided[i] == userprovided &&
- strcmp(options->identity_files[i], path) == 0) {
- debug2("%s: ignoring duplicate key %s", __func__, path);
- free(path);
- return;
- }
- }
- options->identity_file_userprovided[options->num_identity_files] =
- userprovided;
- options->identity_files[options->num_identity_files++] = path;
- }
- int
- default_ssh_port(void)
- {
- static int port;
- struct servent *sp;
- if (port == 0) {
- sp = getservbyname(SSH_SERVICE_NAME, "tcp");
- port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
- }
- return port;
- }
- /*
- * Execute a command in a shell.
- * Return its exit status or -1 on abnormal exit.
- */
- static int
- execute_in_shell(const char *cmd)
- {
- char *shell;
- pid_t pid;
- int devnull, status;
- if ((shell = getenv("SHELL")) == NULL)
- shell = _PATH_BSHELL;
- if (access(shell, X_OK) == -1) {
- fatal("Shell \"%s\" is not executable: %s",
- shell, strerror(errno));
- }
- /* Need this to redirect subprocess stdin/out */
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- debug("Executing command: '%.500s'", cmd);
- /* Fork and execute the command. */
- if ((pid = fork()) == 0) {
- char *argv[4];
- /* Redirect child stdin and stdout. Leave stderr */
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (dup2(devnull, STDOUT_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- closefrom(STDERR_FILENO + 1);
- argv[0] = shell;
- argv[1] = "-c";
- argv[2] = xstrdup(cmd);
- argv[3] = NULL;
- execv(argv[0], argv);
- error("Unable to execute '%.100s': %s", cmd, strerror(errno));
- /* Die with signal to make this error apparent to parent. */
- ssh_signal(SIGTERM, SIG_DFL);
- kill(getpid(), SIGTERM);
- _exit(1);
- }
- /* Parent. */
- if (pid == -1)
- fatal("%s: fork: %.100s", __func__, strerror(errno));
- close(devnull);
- while (waitpid(pid, &status, 0) == -1) {
- if (errno != EINTR && errno != EAGAIN)
- fatal("%s: waitpid: %s", __func__, strerror(errno));
- }
- if (!WIFEXITED(status)) {
- error("command '%.100s' exited abnormally", cmd);
- return -1;
- }
- debug3("command returned status %d", WEXITSTATUS(status));
- return WEXITSTATUS(status);
- }
- /*
- * Parse and execute a Match directive.
- */
- static int
- match_cfg_line(Options *options, char **condition, struct passwd *pw,
- const char *host_arg, const char *original_host, int final_pass,
- int *want_final_pass, const char *filename, int linenum)
- {
- char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
- const char *ruser;
- int r, port, this_result, result = 1, attributes = 0, negate;
- char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
- char uidstr[32];
- /*
- * Configuration is likely to be incomplete at this point so we
- * must be prepared to use default values.
- */
- port = options->port <= 0 ? default_ssh_port() : options->port;
- ruser = options->user == NULL ? pw->pw_name : options->user;
- if (final_pass) {
- host = xstrdup(options->hostname);
- } else if (options->hostname != NULL) {
- /* NB. Please keep in sync with ssh.c:main() */
- host = percent_expand(options->hostname,
- "h", host_arg, (char *)NULL);
- } else {
- host = xstrdup(host_arg);
- }
- debug2("checking match for '%s' host %s originally %s",
- cp, host, original_host);
- while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
- criteria = NULL;
- this_result = 1;
- if ((negate = attrib[0] == '!'))
- attrib++;
- /* criteria "all" and "canonical" have no argument */
- if (strcasecmp(attrib, "all") == 0) {
- if (attributes > 1 ||
- ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
- error("%.200s line %d: '%s' cannot be combined "
- "with other Match attributes",
- filename, linenum, oattrib);
- result = -1;
- goto out;
- }
- if (result)
- result = negate ? 0 : 1;
- goto out;
- }
- attributes++;
- if (strcasecmp(attrib, "canonical") == 0 ||
- strcasecmp(attrib, "final") == 0) {
- /*
- * If the config requests "Match final" then remember
- * this so we can perform a second pass later.
- */
- if (strcasecmp(attrib, "final") == 0 &&
- want_final_pass != NULL)
- *want_final_pass = 1;
- r = !!final_pass; /* force bitmask member to boolean */
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- debug3("%.200s line %d: %smatched '%s'",
- filename, linenum,
- this_result ? "" : "not ", oattrib);
- continue;
- }
- /* All other criteria require an argument */
- if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
- error("Missing Match criteria for %s", attrib);
- result = -1;
- goto out;
- }
- if (strcasecmp(attrib, "host") == 0) {
- criteria = xstrdup(host);
- r = match_hostname(host, arg) == 1;
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- } else if (strcasecmp(attrib, "originalhost") == 0) {
- criteria = xstrdup(original_host);
- r = match_hostname(original_host, arg) == 1;
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- } else if (strcasecmp(attrib, "user") == 0) {
- criteria = xstrdup(ruser);
- r = match_pattern_list(ruser, arg, 0) == 1;
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- } else if (strcasecmp(attrib, "localuser") == 0) {
- criteria = xstrdup(pw->pw_name);
- r = match_pattern_list(pw->pw_name, arg, 0) == 1;
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- } else if (strcasecmp(attrib, "exec") == 0) {
- char *conn_hash_hex, *keyalias;
- if (gethostname(thishost, sizeof(thishost)) == -1)
- fatal("gethostname: %s", strerror(errno));
- strlcpy(shorthost, thishost, sizeof(shorthost));
- shorthost[strcspn(thishost, ".")] = '\0';
- snprintf(portstr, sizeof(portstr), "%d", port);
- snprintf(uidstr, sizeof(uidstr), "%llu",
- (unsigned long long)pw->pw_uid);
- conn_hash_hex = ssh_connection_hash(thishost, host,
- portstr, ruser);
- keyalias = options->host_key_alias ?
- options->host_key_alias : host;
- cmd = percent_expand(arg,
- "C", conn_hash_hex,
- "L", shorthost,
- "d", pw->pw_dir,
- "h", host,
- "k", keyalias,
- "l", thishost,
- "n", original_host,
- "p", portstr,
- "r", ruser,
- "u", pw->pw_name,
- "i", uidstr,
- (char *)NULL);
- free(conn_hash_hex);
- if (result != 1) {
- /* skip execution if prior predicate failed */
- debug3("%.200s line %d: skipped exec "
- "\"%.100s\"", filename, linenum, cmd);
- free(cmd);
- continue;
- }
- r = execute_in_shell(cmd);
- if (r == -1) {
- fatal("%.200s line %d: match exec "
- "'%.100s' error", filename,
- linenum, cmd);
- }
- criteria = xstrdup(cmd);
- free(cmd);
- /* Force exit status to boolean */
- r = r == 0;
- if (r == (negate ? 1 : 0))
- this_result = result = 0;
- } else {
- error("Unsupported Match attribute %s", attrib);
- result = -1;
- goto out;
- }
- debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
- filename, linenum, this_result ? "": "not ",
- oattrib, criteria);
- free(criteria);
- }
- if (attributes == 0) {
- error("One or more attributes required for Match");
- result = -1;
- goto out;
- }
- out:
- if (result != -1)
- debug2("match %sfound", result ? "" : "not ");
- *condition = cp;
- free(host);
- return result;
- }
- /* Remove environment variable by pattern */
- static void
- rm_env(Options *options, const char *arg, const char *filename, int linenum)
- {
- int i, j, onum_send_env = options->num_send_env;
- char *cp;
- /* Remove an environment variable */
- for (i = 0; i < options->num_send_env; ) {
- cp = xstrdup(options->send_env[i]);
- if (!match_pattern(cp, arg + 1)) {
- free(cp);
- i++;
- continue;
- }
- debug3("%s line %d: removing environment %s",
- filename, linenum, cp);
- free(cp);
- free(options->send_env[i]);
- options->send_env[i] = NULL;
- for (j = i; j < options->num_send_env - 1; j++) {
- options->send_env[j] = options->send_env[j + 1];
- options->send_env[j + 1] = NULL;
- }
- options->num_send_env--;
- /* NB. don't increment i */
- }
- if (onum_send_env != options->num_send_env) {
- options->send_env = xrecallocarray(options->send_env,
- onum_send_env, options->num_send_env,
- sizeof(*options->send_env));
- }
- }
- /*
- * Returns the number of the token pointed to by cp or oBadOption.
- */
- static OpCodes
- parse_token(const char *cp, const char *filename, int linenum,
- const char *ignored_unknown)
- {
- int i;
- for (i = 0; keywords[i].name; i++)
- if (strcmp(cp, keywords[i].name) == 0)
- return keywords[i].opcode;
- if (ignored_unknown != NULL &&
- match_pattern_list(cp, ignored_unknown, 1) == 1)
- return oIgnoredUnknownOption;
- error("%s: line %d: Bad configuration option: %s",
- filename, linenum, cp);
- return oBadOption;
- }
- /* Multistate option parsing */
- struct multistate {
- char *key;
- int value;
- };
- static const struct multistate multistate_flag[] = {
- { "true", 1 },
- { "false", 0 },
- { "yes", 1 },
- { "no", 0 },
- { NULL, -1 }
- };
- static const struct multistate multistate_yesnoask[] = {
- { "true", 1 },
- { "false", 0 },
- { "yes", 1 },
- { "no", 0 },
- { "ask", 2 },
- { NULL, -1 }
- };
- static const struct multistate multistate_strict_hostkey[] = {
- { "true", SSH_STRICT_HOSTKEY_YES },
- { "false", SSH_STRICT_HOSTKEY_OFF },
- { "yes", SSH_STRICT_HOSTKEY_YES },
- { "no", SSH_STRICT_HOSTKEY_OFF },
- { "ask", SSH_STRICT_HOSTKEY_ASK },
- { "off", SSH_STRICT_HOSTKEY_OFF },
- { "accept-new", SSH_STRICT_HOSTKEY_NEW },
- { NULL, -1 }
- };
- static const struct multistate multistate_yesnoaskconfirm[] = {
- { "true", 1 },
- { "false", 0 },
- { "yes", 1 },
- { "no", 0 },
- { "ask", 2 },
- { "confirm", 3 },
- { NULL, -1 }
- };
- static const struct multistate multistate_addressfamily[] = {
- { "inet", AF_INET },
- { "inet6", AF_INET6 },
- { "any", AF_UNSPEC },
- { NULL, -1 }
- };
- static const struct multistate multistate_controlmaster[] = {
- { "true", SSHCTL_MASTER_YES },
- { "yes", SSHCTL_MASTER_YES },
- { "false", SSHCTL_MASTER_NO },
- { "no", SSHCTL_MASTER_NO },
- { "auto", SSHCTL_MASTER_AUTO },
- { "ask", SSHCTL_MASTER_ASK },
- { "autoask", SSHCTL_MASTER_AUTO_ASK },
- { NULL, -1 }
- };
- static const struct multistate multistate_tunnel[] = {
- { "ethernet", SSH_TUNMODE_ETHERNET },
- { "point-to-point", SSH_TUNMODE_POINTOPOINT },
- { "true", SSH_TUNMODE_DEFAULT },
- { "yes", SSH_TUNMODE_DEFAULT },
- { "false", SSH_TUNMODE_NO },
- { "no", SSH_TUNMODE_NO },
- { NULL, -1 }
- };
- static const struct multistate multistate_requesttty[] = {
- { "true", REQUEST_TTY_YES },
- { "yes", REQUEST_TTY_YES },
- { "false", REQUEST_TTY_NO },
- { "no", REQUEST_TTY_NO },
- { "force", REQUEST_TTY_FORCE },
- { "auto", REQUEST_TTY_AUTO },
- { NULL, -1 }
- };
- static const struct multistate multistate_canonicalizehostname[] = {
- { "true", SSH_CANONICALISE_YES },
- { "false", SSH_CANONICALISE_NO },
- { "yes", SSH_CANONICALISE_YES },
- { "no", SSH_CANONICALISE_NO },
- { "always", SSH_CANONICALISE_ALWAYS },
- { NULL, -1 }
- };
- static const struct multistate multistate_compression[] = {
- #ifdef WITH_ZLIB
- { "yes", COMP_ZLIB },
- #endif
- { "no", COMP_NONE },
- { NULL, -1 }
- };
- static int
- parse_multistate_value(const char *arg, const char *filename, int linenum,
- const struct multistate *multistate_ptr)
- {
- int i;
- if (!arg || *arg == '\0') {
- error("%s line %d: missing argument.", filename, linenum);
- return -1;
- }
- for (i = 0; multistate_ptr[i].key != NULL; i++) {
- if (strcasecmp(arg, multistate_ptr[i].key) == 0)
- return multistate_ptr[i].value;
- }
- return -1;
- }
- /*
- * Processes a single option line as used in the configuration files. This
- * only sets those values that have not already been set.
- */
- int
- process_config_line(Options *options, struct passwd *pw, const char *host,
- const char *original_host, char *line, const char *filename,
- int linenum, int *activep, int flags)
- {
- return process_config_line_depth(options, pw, host, original_host,
- line, filename, linenum, activep, flags, NULL, 0);
- }
- #define WHITESPACE " \t\r\n"
- static int
- process_config_line_depth(Options *options, struct passwd *pw, const char *host,
- const char *original_host, char *line, const char *filename,
- int linenum, int *activep, int flags, int *want_final_pass, int depth)
- {
- char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
- char **cpptr, ***cppptr, fwdarg[512];
- u_int i, *uintptr, uvalue, max_entries = 0;
- int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
- int remotefwd, dynamicfwd;
- LogLevel *log_level_ptr;
- SyslogFacility *log_facility_ptr;
- long long val64;
- size_t len;
- struct Forward fwd;
- const struct multistate *multistate_ptr;
- struct allowed_cname *cname;
- glob_t gl;
- const char *errstr;
- if (activep == NULL) { /* We are processing a command line directive */
- cmdline = 1;
- activep = &cmdline;
- }
- /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
- if ((len = strlen(line)) == 0)
- return 0;
- for (len--; len > 0; len--) {
- if (strchr(WHITESPACE "\f", line[len]) == NULL)
- break;
- line[len] = '\0';
- }
- s = line;
- /* Get the keyword. (Each line is supposed to begin with a keyword). */
- if ((keyword = strdelim(&s)) == NULL)
- return 0;
- /* Ignore leading whitespace. */
- if (*keyword == '\0')
- keyword = strdelim(&s);
- if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
- return 0;
- /* Match lowercase keyword */
- lowercase(keyword);
- opcode = parse_token(keyword, filename, linenum,
- options->ignored_unknown);
- switch (opcode) {
- case oBadOption:
- /* don't panic, but count bad options */
- return -1;
- case oIgnore:
- return 0;
- case oIgnoredUnknownOption:
- debug("%s line %d: Ignored unknown option \"%s\"",
- filename, linenum, keyword);
- return 0;
- case oConnectTimeout:
- intptr = &options->connection_timeout;
- parse_time:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%s line %d: missing time value.",
- filename, linenum);
- return -1;
- }
- if (strcmp(arg, "none") == 0)
- value = -1;
- else if ((value = convtime(arg)) == -1) {
- error("%s line %d: invalid time value.",
- filename, linenum);
- return -1;
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- case oForwardAgent:
- intptr = &options->forward_agent;
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%s line %d: missing argument.",
- filename, linenum);
- return -1;
- }
- value = -1;
- multistate_ptr = multistate_flag;
- for (i = 0; multistate_ptr[i].key != NULL; i++) {
- if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
- value = multistate_ptr[i].value;
- break;
- }
- }
- if (value != -1) {
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- }
- /* ForwardAgent wasn't 'yes' or 'no', assume a path */
- if (*activep && *intptr == -1)
- *intptr = 1;
- charptr = &options->forward_agent_sock_path;
- goto parse_agent_path;
- case oForwardX11:
- intptr = &options->forward_x11;
- parse_flag:
- multistate_ptr = multistate_flag;
- parse_multistate:
- arg = strdelim(&s);
- if ((value = parse_multistate_value(arg, filename, linenum,
- multistate_ptr)) == -1) {
- error("%s line %d: unsupported option \"%s\".",
- filename, linenum, arg);
- return -1;
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- case oForwardX11Trusted:
- intptr = &options->forward_x11_trusted;
- goto parse_flag;
- case oForwardX11Timeout:
- intptr = &options->forward_x11_timeout;
- goto parse_time;
- case oGatewayPorts:
- intptr = &options->fwd_opts.gateway_ports;
- goto parse_flag;
- case oExitOnForwardFailure:
- intptr = &options->exit_on_forward_failure;
- goto parse_flag;
- case oPasswordAuthentication:
- intptr = &options->password_authentication;
- goto parse_flag;
- case oKbdInteractiveAuthentication:
- intptr = &options->kbd_interactive_authentication;
- goto parse_flag;
- case oKbdInteractiveDevices:
- charptr = &options->kbd_interactive_devices;
- goto parse_string;
- case oPubkeyAuthentication:
- intptr = &options->pubkey_authentication;
- goto parse_flag;
- case oHostbasedAuthentication:
- intptr = &options->hostbased_authentication;
- goto parse_flag;
- case oChallengeResponseAuthentication:
- intptr = &options->challenge_response_authentication;
- goto parse_flag;
- case oGssAuthentication:
- intptr = &options->gss_authentication;
- goto parse_flag;
- case oGssDelegateCreds:
- intptr = &options->gss_deleg_creds;
- goto parse_flag;
- case oBatchMode:
- intptr = &options->batch_mode;
- goto parse_flag;
- case oCheckHostIP:
- intptr = &options->check_host_ip;
- goto parse_flag;
- case oHPNDisabled:
- intptr = &options->hpn_disabled;
- goto parse_flag;
- case oHPNBufferSize:
- intptr = &options->hpn_buffer_size;
- goto parse_int;
- case oTcpRcvBufPoll:
- intptr = &options->tcp_rcv_buf_poll;
- goto parse_flag;
- case oNoneEnabled:
- intptr = &options->none_enabled;
- goto parse_flag;
- case oNoneMacEnabled:
- intptr = &options->nonemac_enabled;
- goto parse_flag;
-
- case oDisableMTAES:
- intptr = &options->disable_multithreaded;
- goto parse_flag;
-
- /*
- * We check to see if the command comes from the command
- * line or not. If it does then enable it otherwise fail.
- * NONE should never be a default configuration.
- */
- case oNoneSwitch:
- if (strcmp(filename, "command-line") == 0) {
- intptr = &options->none_switch;
- goto parse_flag;
- } else {
- error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
- error("Continuing...");
- debug("NoneSwitch directive found in %.200s.", filename);
- return 0;
- }
- case oVerifyHostKeyDNS:
- intptr = &options->verify_host_key_dns;
- multistate_ptr = multistate_yesnoask;
- goto parse_multistate;
- case oStrictHostKeyChecking:
- intptr = &options->strict_host_key_checking;
- multistate_ptr = multistate_strict_hostkey;
- goto parse_multistate;
- case oCompression:
- intptr = &options->compression;
- multistate_ptr = multistate_compression;
- goto parse_multistate;
- case oTCPKeepAlive:
- intptr = &options->tcp_keep_alive;
- goto parse_flag;
- case oNoHostAuthenticationForLocalhost:
- intptr = &options->no_host_authentication_for_localhost;
- goto parse_flag;
- case oNumberOfPasswordPrompts:
- intptr = &options->number_of_password_prompts;
- goto parse_int;
- case oRekeyLimit:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.", filename,
- linenum);
- return -1;
- }
- if (strcmp(arg, "default") == 0) {
- val64 = 0;
- } else {
- if (scan_scaled(arg, &val64) == -1) {
- error("%.200s line %d: Bad number '%s': %s",
- filename, linenum, arg, strerror(errno));
- return -1;
- }
- if (val64 != 0 && val64 < 16) {
- error("%.200s line %d: RekeyLimit too small",
- filename, linenum);
- return -1;
- }
- }
- if (*activep && options->rekey_limit == -1)
- options->rekey_limit = val64;
- if (s != NULL) { /* optional rekey interval present */
- if (strcmp(s, "none") == 0) {
- (void)strdelim(&s); /* discard */
- break;
- }
- intptr = &options->rekey_interval;
- goto parse_time;
- }
- break;
- case oIdentityFile:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*activep) {
- intptr = &options->num_identity_files;
- if (*intptr >= SSH_MAX_IDENTITY_FILES) {
- error("%.200s line %d: Too many identity files "
- "specified (max %d).", filename, linenum,
- SSH_MAX_IDENTITY_FILES);
- return -1;
- }
- add_identity_file(options, NULL,
- arg, flags & SSHCONF_USERCONF);
- }
- break;
- case oCertificateFile:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*activep) {
- intptr = &options->num_certificate_files;
- if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
- error("%.200s line %d: Too many certificate "
- "files specified (max %d).",
- filename, linenum,
- SSH_MAX_CERTIFICATE_FILES);
- return -1;
- }
- add_certificate_file(options, arg,
- flags & SSHCONF_USERCONF);
- }
- break;
- case oXAuthLocation:
- charptr=&options->xauth_location;
- goto parse_string;
- case oUser:
- charptr = &options->user;
- parse_string:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(arg);
- break;
- case oGlobalKnownHostsFile:
- cpptr = (char **)&options->system_hostfiles;
- uintptr = &options->num_system_hostfiles;
- max_entries = SSH_MAX_HOSTS_FILES;
- parse_char_array:
- if (*activep && *uintptr == 0) {
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if ((*uintptr) >= max_entries) {
- error("%s line %d: too many known "
- "hosts files.", filename, linenum);
- return -1;
- }
- cpptr[(*uintptr)++] = xstrdup(arg);
- }
- }
- return 0;
- case oUserKnownHostsFile:
- cpptr = (char **)&options->user_hostfiles;
- uintptr = &options->num_user_hostfiles;
- max_entries = SSH_MAX_HOSTS_FILES;
- goto parse_char_array;
- case oHostname:
- charptr = &options->hostname;
- goto parse_string;
- case oHostKeyAlias:
- charptr = &options->host_key_alias;
- goto parse_string;
- case oPreferredAuthentications:
- charptr = &options->preferred_authentications;
- goto parse_string;
- case oBindAddress:
- charptr = &options->bind_address;
- goto parse_string;
- case oBindInterface:
- charptr = &options->bind_interface;
- goto parse_string;
- case oPKCS11Provider:
- charptr = &options->pkcs11_provider;
- goto parse_string;
- case oSecurityKeyProvider:
- charptr = &options->sk_provider;
- goto parse_string;
- case oProxyCommand:
- charptr = &options->proxy_command;
- /* Ignore ProxyCommand if ProxyJump already specified */
- if (options->jump_host != NULL)
- charptr = &options->jump_host; /* Skip below */
- parse_command:
- if (s == NULL) {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- len = strspn(s, WHITESPACE "=");
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(s + len);
- return 0;
- case oProxyJump:
- if (s == NULL) {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- len = strspn(s, WHITESPACE "=");
- if (parse_jump(s + len, options, *activep) == -1) {
- error("%.200s line %d: Invalid ProxyJump \"%s\"",
- filename, linenum, s + len);
- return -1;
- }
- return 0;
- case oPort:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- value = a2port(arg);
- if (value <= 0) {
- error("%.200s line %d: Bad port '%s'.",
- filename, linenum, arg);
- return -1;
- }
- if (*activep && options->port == -1)
- options->port = value;
- break;
- case oConnectionAttempts:
- intptr = &options->connection_attempts;
- parse_int:
- arg = strdelim(&s);
- if ((errstr = atoi_err(arg, &value)) != NULL) {
- error("%s line %d: integer value %s.",
- filename, linenum, errstr);
- return -1;
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- case oTcpRcvBuf:
- intptr = &options->tcp_rcv_buf;
- goto parse_int;
- case oCiphers:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*arg != '-' &&
- !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
- error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*activep && options->ciphers == NULL)
- options->ciphers = xstrdup(arg);
- break;
- case oMacs:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*arg != '-' &&
- !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
- error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*activep && options->macs == NULL)
- options->macs = xstrdup(arg);
- break;
- case oKexAlgorithms:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*arg != '-' &&
- !kex_names_valid(*arg == '+' || *arg == '^' ?
- arg + 1 : arg)) {
- error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*activep && options->kex_algorithms == NULL)
- options->kex_algorithms = xstrdup(arg);
- break;
- case oHostKeyAlgorithms:
- charptr = &options->hostkeyalgorithms;
- parse_pubkey_algos:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (*arg != '-' &&
- !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
- arg + 1 : arg, 1)) {
- error("%s line %d: Bad key types '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(arg);
- break;
- case oCASignatureAlgorithms:
- charptr = &options->ca_sign_algorithms;
- goto parse_pubkey_algos;
- case oLogLevel:
- log_level_ptr = &options->log_level;
- arg = strdelim(&s);
- value = log_level_number(arg);
- if (value == SYSLOG_LEVEL_NOT_SET) {
- error("%.200s line %d: unsupported log level '%s'",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
- *log_level_ptr = (LogLevel) value;
- break;
- case oLogFacility:
- log_facility_ptr = &options->log_facility;
- arg = strdelim(&s);
- value = log_facility_number(arg);
- if (value == SYSLOG_FACILITY_NOT_SET) {
- error("%.200s line %d: unsupported log facility '%s'",
- filename, linenum, arg ? arg : "<NONE>");
- return -1;
- }
- if (*log_facility_ptr == -1)
- *log_facility_ptr = (SyslogFacility) value;
- break;
- case oLocalForward:
- case oRemoteForward:
- case oDynamicForward:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- remotefwd = (opcode == oRemoteForward);
- dynamicfwd = (opcode == oDynamicForward);
- if (!dynamicfwd) {
- arg2 = strdelim(&s);
- if (arg2 == NULL || *arg2 == '\0') {
- if (remotefwd)
- dynamicfwd = 1;
- else {
- error("%.200s line %d: Missing target "
- "argument.", filename, linenum);
- return -1;
- }
- } else {
- /* construct a string for parse_forward */
- snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
- arg2);
- }
- }
- if (dynamicfwd)
- strlcpy(fwdarg, arg, sizeof(fwdarg));
- if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
- error("%.200s line %d: Bad forwarding specification.",
- filename, linenum);
- return -1;
- }
- if (*activep) {
- if (remotefwd) {
- add_remote_forward(options, &fwd);
- } else {
- add_local_forward(options, &fwd);
- }
- }
- break;
- case oPermitRemoteOpen:
- uintptr = &options->num_permitted_remote_opens;
- cppptr = &options->permitted_remote_opens;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing %s specification",
- filename, linenum, lookup_opcode_name(opcode));
- uvalue = *uintptr; /* modified later */
- if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
- if (*activep && uvalue == 0) {
- *uintptr = 1;
- *cppptr = xcalloc(1, sizeof(**cppptr));
- (*cppptr)[0] = xstrdup(arg);
- }
- break;
- }
- for (; arg != NULL && *arg != '\0'; arg = strdelim(&s)) {
- arg2 = xstrdup(arg);
- ch = '\0';
- p = hpdelim2(&arg, &ch);
- if (p == NULL || ch == '/') {
- fatal("%s line %d: missing host in %s",
- filename, linenum,
- lookup_opcode_name(opcode));
- }
- p = cleanhostname(p);
- /*
- * don't want to use permitopen_port to avoid
- * dependency on channels.[ch] here.
- */
- if (arg == NULL ||
- (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
- fatal("%s line %d: bad port number in %s",
- filename, linenum,
- lookup_opcode_name(opcode));
- }
- if (*activep && uvalue == 0) {
- opt_array_append(filename, linenum,
- lookup_opcode_name(opcode),
- cppptr, uintptr, arg2);
- }
- free(arg2);
- }
- break;
- case oClearAllForwardings:
- intptr = &options->clear_forwardings;
- goto parse_flag;
- case oHost:
- if (cmdline) {
- error("Host directive not supported as a command-line "
- "option");
- return -1;
- }
- *activep = 0;
- arg2 = NULL;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if ((flags & SSHCONF_NEVERMATCH) != 0)
- break;
- negated = *arg == '!';
- if (negated)
- arg++;
- if (match_pattern(host, arg)) {
- if (negated) {
- debug("%.200s line %d: Skipping Host "
- "block because of negated match "
- "for %.100s", filename, linenum,
- arg);
- *activep = 0;
- break;
- }
- if (!*activep)
- arg2 = arg; /* logged below */
- *activep = 1;
- }
- }
- if (*activep)
- debug("%.200s line %d: Applying options for %.100s",
- filename, linenum, arg2);
- /* Avoid garbage check below, as strdelim is done. */
- return 0;
- case oMatch:
- if (cmdline) {
- error("Host directive not supported as a command-line "
- "option");
- return -1;
- }
- value = match_cfg_line(options, &s, pw, host, original_host,
- flags & SSHCONF_FINAL, want_final_pass,
- filename, linenum);
- if (value < 0) {
- error("%.200s line %d: Bad Match condition", filename,
- linenum);
- return -1;
- }
- *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
- break;
- case oEscapeChar:
- intptr = &options->escape_char;
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if (strcmp(arg, "none") == 0)
- value = SSH_ESCAPECHAR_NONE;
- else if (arg[1] == '\0')
- value = (u_char) arg[0];
- else if (arg[0] == '^' && arg[2] == 0 &&
- (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
- value = (u_char) arg[1] & 31;
- else {
- error("%.200s line %d: Bad escape character.",
- filename, linenum);
- value = 0; /* Avoid compiler warning. */
- return -1;
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- case oAddressFamily:
- intptr = &options->address_family;
- multistate_ptr = multistate_addressfamily;
- goto parse_multistate;
- case oEnableSSHKeysign:
- intptr = &options->enable_ssh_keysign;
- goto parse_flag;
- case oIdentitiesOnly:
- intptr = &options->identities_only;
- goto parse_flag;
- case oServerAliveInterval:
- case oProtocolKeepAlives: /* Debian-specific compatibility alias */
- case oSetupTimeOut: /* Debian-specific compatibility alias */
- intptr = &options->server_alive_interval;
- goto parse_time;
- case oServerAliveCountMax:
- intptr = &options->server_alive_count_max;
- goto parse_int;
- case oSendEnv:
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if (strchr(arg, '=') != NULL) {
- error("%s line %d: Invalid environment name.",
- filename, linenum);
- return -1;
- }
- if (!*activep)
- continue;
- if (*arg == '-') {
- /* Removing an env var */
- rm_env(options, arg, filename, linenum);
- continue;
- } else {
- /* Adding an env var */
- if (options->num_send_env >= INT_MAX) {
- error("%s line %d: too many send env.",
- filename, linenum);
- return -1;
- }
- options->send_env = xrecallocarray(
- options->send_env, options->num_send_env,
- options->num_send_env + 1,
- sizeof(*options->send_env));
- options->send_env[options->num_send_env++] =
- xstrdup(arg);
- }
- }
- break;
- case oSetEnv:
- value = options->num_setenv;
- while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
- if (strchr(arg, '=') == NULL) {
- error("%s line %d: Invalid SetEnv.",
- filename, linenum);
- return -1;
- }
- if (!*activep || value != 0)
- continue;
- /* Adding a setenv var */
- if (options->num_setenv >= INT_MAX) {
- error("%s line %d: too many SetEnv.",
- filename, linenum);
- return -1;
- }
- options->setenv = xrecallocarray(
- options->setenv, options->num_setenv,
- options->num_setenv + 1, sizeof(*options->setenv));
- options->setenv[options->num_setenv++] = xstrdup(arg);
- }
- break;
- case oControlPath:
- charptr = &options->control_path;
- goto parse_string;
- case oControlMaster:
- intptr = &options->control_master;
- multistate_ptr = multistate_controlmaster;
- goto parse_multistate;
- case oControlPersist:
- /* no/false/yes/true, or a time spec */
- intptr = &options->control_persist;
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing ControlPersist"
- " argument.", filename, linenum);
- return -1;
- }
- value = 0;
- value2 = 0; /* timeout */
- if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
- value = 0;
- else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
- value = 1;
- else if ((value2 = convtime(arg)) >= 0)
- value = 1;
- else {
- error("%.200s line %d: Bad ControlPersist argument.",
- filename, linenum);
- return -1;
- }
- if (*activep && *intptr == -1) {
- *intptr = value;
- options->control_persist_timeout = value2;
- }
- break;
- case oHashKnownHosts:
- intptr = &options->hash_known_hosts;
- goto parse_flag;
- case oTunnel:
- intptr = &options->tun_open;
- multistate_ptr = multistate_tunnel;
- goto parse_multistate;
- case oTunnelDevice:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- value = a2tun(arg, &value2);
- if (value == SSH_TUNID_ERR) {
- error("%.200s line %d: Bad tun device.",
- filename, linenum);
- return -1;
- }
- if (*activep) {
- options->tun_local = value;
- options->tun_remote = value2;
- }
- break;
- case oLocalCommand:
- charptr = &options->local_command;
- goto parse_command;
- case oPermitLocalCommand:
- intptr = &options->permit_local_command;
- goto parse_flag;
- case oRemoteCommand:
- charptr = &options->remote_command;
- goto parse_command;
- case oVisualHostKey:
- intptr = &options->visual_host_key;
- goto parse_flag;
- case oInclude:
- if (cmdline) {
- error("Include directive not supported as a "
- "command-line option");
- return -1;
- }
- value = 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- /*
- * Ensure all paths are anchored. User configuration
- * files may begin with '~/' but system configurations
- * must not. If the path is relative, then treat it
- * as living in ~/.ssh for user configurations or
- * /etc/ssh for system ones.
- */
- if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
- error("%.200s line %d: bad include path %s.",
- filename, linenum, arg);
- return -1;
- }
- if (!path_absolute(arg) && *arg != '~') {
- xasprintf(&arg2, "%s/%s",
- (flags & SSHCONF_USERCONF) ?
- "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
- } else
- arg2 = xstrdup(arg);
- memset(&gl, 0, sizeof(gl));
- r = glob(arg2, GLOB_TILDE, NULL, &gl);
- if (r == GLOB_NOMATCH) {
- debug("%.200s line %d: include %s matched no "
- "files",filename, linenum, arg2);
- free(arg2);
- continue;
- } else if (r != 0) {
- error("%.200s line %d: glob failed for %s.",
- filename, linenum, arg2);
- return -1;
- }
- free(arg2);
- oactive = *activep;
- for (i = 0; i < gl.gl_pathc; i++) {
- debug3("%.200s line %d: Including file %s "
- "depth %d%s", filename, linenum,
- gl.gl_pathv[i], depth,
- oactive ? "" : " (parse only)");
- r = read_config_file_depth(gl.gl_pathv[i],
- pw, host, original_host, options,
- flags | SSHCONF_CHECKPERM |
- (oactive ? 0 : SSHCONF_NEVERMATCH),
- activep, want_final_pass, depth + 1);
- if (r != 1 && errno != ENOENT) {
- error("Can't open user config file "
- "%.100s: %.100s", gl.gl_pathv[i],
- strerror(errno));
- globfree(&gl);
- return -1;
- }
- /*
- * don't let Match in includes clobber the
- * containing file's Match state.
- */
- *activep = oactive;
- if (r != 1)
- value = -1;
- }
- globfree(&gl);
- }
- if (value != 0)
- return value;
- break;
- case oIPQoS:
- arg = strdelim(&s);
- if ((value = parse_ipqos(arg)) == -1) {
- error("%s line %d: Bad IPQoS value: %s",
- filename, linenum, arg);
- return -1;
- }
- arg = strdelim(&s);
- if (arg == NULL)
- value2 = value;
- else if ((value2 = parse_ipqos(arg)) == -1) {
- error("%s line %d: Bad IPQoS value: %s",
- filename, linenum, arg);
- return -1;
- }
- if (*activep) {
- options->ip_qos_interactive = value;
- options->ip_qos_bulk = value2;
- }
- break;
- case oRequestTTY:
- intptr = &options->request_tty;
- multistate_ptr = multistate_requesttty;
- goto parse_multistate;
- case oNoShell:
- intptr = &options->no_shell;
- goto parse_flag;
- case oStdinNull:
- intptr = &options->stdin_null;
- goto parse_flag;
- case oForkAfterAuthentication:
- intptr = &options->fork_after_authentication;
- goto parse_flag;
- case oIgnoreUnknown:
- charptr = &options->ignored_unknown;
- goto parse_string;
- case oProxyUseFdpass:
- intptr = &options->proxy_use_fdpass;
- goto parse_flag;
- case oCanonicalDomains:
- value = options->num_canonical_domains != 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if (!valid_domain(arg, 1, &errstr)) {
- error("%s line %d: %s", filename, linenum,
- errstr);
- return -1;
- }
- if (!*activep || value)
- continue;
- if (options->num_canonical_domains >=
- MAX_CANON_DOMAINS) {
- error("%s line %d: too many hostname suffixes.",
- filename, linenum);
- return -1;
- }
- options->canonical_domains[
- options->num_canonical_domains++] = xstrdup(arg);
- }
- break;
- case oCanonicalizePermittedCNAMEs:
- value = options->num_permitted_cnames != 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- /* Either '*' for everything or 'list:list' */
- if (strcmp(arg, "*") == 0)
- arg2 = arg;
- else {
- lowercase(arg);
- if ((arg2 = strchr(arg, ':')) == NULL ||
- arg2[1] == '\0') {
- error("%s line %d: "
- "Invalid permitted CNAME \"%s\"",
- filename, linenum, arg);
- return -1;
- }
- *arg2 = '\0';
- arg2++;
- }
- if (!*activep || value)
- continue;
- if (options->num_permitted_cnames >=
- MAX_CANON_DOMAINS) {
- error("%s line %d: too many permitted CNAMEs.",
- filename, linenum);
- return -1;
- }
- cname = options->permitted_cnames +
- options->num_permitted_cnames++;
- cname->source_list = xstrdup(arg);
- cname->target_list = xstrdup(arg2);
- }
- break;
- case oCanonicalizeHostname:
- intptr = &options->canonicalize_hostname;
- multistate_ptr = multistate_canonicalizehostname;
- goto parse_multistate;
- case oCanonicalizeMaxDots:
- intptr = &options->canonicalize_max_dots;
- goto parse_int;
- case oCanonicalizeFallbackLocal:
- intptr = &options->canonicalize_fallback_local;
- goto parse_flag;
- case oStreamLocalBindMask:
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing StreamLocalBindMask "
- "argument.", filename, linenum);
- return -1;
- }
- /* Parse mode in octal format */
- value = strtol(arg, &endofnumber, 8);
- if (arg == endofnumber || value < 0 || value > 0777) {
- error("%.200s line %d: Bad mask.", filename, linenum);
- return -1;
- }
- options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
- break;
- case oStreamLocalBindUnlink:
- intptr = &options->fwd_opts.streamlocal_bind_unlink;
- goto parse_flag;
- case oRevokedHostKeys:
- charptr = &options->revoked_host_keys;
- goto parse_string;
- case oFingerprintHash:
- intptr = &options->fingerprint_hash;
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- if ((value = ssh_digest_alg_by_name(arg)) == -1) {
- error("%.200s line %d: Invalid hash algorithm \"%s\".",
- filename, linenum, arg);
- return -1;
- }
- if (*activep && *intptr == -1)
- *intptr = value;
- break;
- case oUpdateHostkeys:
- intptr = &options->update_hostkeys;
- multistate_ptr = multistate_yesnoask;
- goto parse_multistate;
- case oHostbasedAcceptedAlgorithms:
- charptr = &options->hostbased_accepted_algos;
- goto parse_pubkey_algos;
- case oPubkeyAcceptedAlgorithms:
- charptr = &options->pubkey_accepted_algos;
- goto parse_pubkey_algos;
- case oAddKeysToAgent:
- arg = strdelim(&s);
- arg2 = strdelim(&s);
- value = parse_multistate_value(arg, filename, linenum,
- multistate_yesnoaskconfirm);
- value2 = 0; /* unlimited lifespan by default */
- if (value == 3 && arg2 != NULL) {
- /* allow "AddKeysToAgent confirm 5m" */
- if ((value2 = convtime(arg2)) == -1 ||
- value2 > INT_MAX) {
- error("%s line %d: invalid time value.",
- filename, linenum);
- return -1;
- }
- } else if (value == -1 && arg2 == NULL) {
- if ((value2 = convtime(arg)) == -1 ||
- value2 > INT_MAX) {
- error("%s line %d: unsupported option",
- filename, linenum);
- return -1;
- }
- value = 1; /* yes */
- } else if (value == -1 || arg2 != NULL) {
- error("%s line %d: unsupported option",
- filename, linenum);
- return -1;
- }
- if (*activep && options->add_keys_to_agent == -1) {
- options->add_keys_to_agent = value;
- options->add_keys_to_agent_lifespan = value2;
- }
- break;
- case oIdentityAgent:
- charptr = &options->identity_agent;
- arg = strdelim(&s);
- if (!arg || *arg == '\0') {
- error("%.200s line %d: Missing argument.",
- filename, linenum);
- return -1;
- }
- parse_agent_path:
- /* Extra validation if the string represents an env var. */
- if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
- error("%.200s line %d: Invalid environment expansion "
- "%s.", filename, linenum, arg);
- return -1;
- }
- free(arg2);
- /* check for legacy environment format */
- if (arg[0] == '$' && arg[1] != '{' &&
- !valid_env_name(arg + 1)) {
- error("%.200s line %d: Invalid environment name %s.",
- filename, linenum, arg);
- return -1;
- }
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(arg);
- break;
- case oDeprecated:
- debug("%s line %d: Deprecated option \"%s\"",
- filename, linenum, keyword);
- return 0;
- case oUnsupported:
- error("%s line %d: Unsupported option \"%s\"",
- filename, linenum, keyword);
- return 0;
- default:
- error("%s line %d: Unimplemented opcode %d",
- filename, linenum, opcode);
- }
- /* Check that there is no garbage at end of line. */
- if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- error("%.200s line %d: garbage at end of line; \"%.200s\".",
- filename, linenum, arg);
- return -1;
- }
- return 0;
- }
- /*
- * Reads the config file and modifies the options accordingly. Options
- * should already be initialized before this call. This never returns if
- * there is an error. If the file does not exist, this returns 0.
- */
- int
- read_config_file(const char *filename, struct passwd *pw, const char *host,
- const char *original_host, Options *options, int flags,
- int *want_final_pass)
- {
- int active = 1;
- return read_config_file_depth(filename, pw, host, original_host,
- options, flags, &active, want_final_pass, 0);
- }
- #define READCONF_MAX_DEPTH 16
- static int
- read_config_file_depth(const char *filename, struct passwd *pw,
- const char *host, const char *original_host, Options *options,
- int flags, int *activep, int *want_final_pass, int depth)
- {
- FILE *f;
- char *cp, *line = NULL;
- size_t linesize = 0;
- int linenum;
- int bad_options = 0;
- if (depth < 0 || depth > READCONF_MAX_DEPTH)
- fatal("Too many recursive configuration includes");
- if ((f = fopen(filename, "r")) == NULL)
- return 0;
- if (flags & SSHCONF_CHECKPERM) {
- struct stat sb;
- if (fstat(fileno(f), &sb) == -1)
- fatal("fstat %s: %s", filename, strerror(errno));
- if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
- (sb.st_mode & 022) != 0))
- fatal("Bad owner or permissions on %s", filename);
- }
- debug("Reading configuration data %.200s", filename);
- /*
- * Mark that we are now processing the options. This flag is turned
- * on/off by Host specifications.
- */
- linenum = 0;
- while (getline(&line, &linesize, f) != -1) {
- /* Update line number counter. */
- linenum++;
- /*
- * Trim out comments and strip whitespace.
- * NB - preserve newlines, they are needed to reproduce
- * line numbers later for error messages.
- */
- if ((cp = strchr(line, '#')) != NULL)
- *cp = '\0';
- if (process_config_line_depth(options, pw, host, original_host,
- line, filename, linenum, activep, flags, want_final_pass,
- depth) != 0)
- bad_options++;
- }
- free(line);
- fclose(f);
- if (bad_options > 0)
- fatal("%s: terminating, %d bad configuration options",
- filename, bad_options);
- return 1;
- }
- /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
- int
- option_clear_or_none(const char *o)
- {
- return o == NULL || strcasecmp(o, "none") == 0;
- }
- /*
- * Initializes options to special values that indicate that they have not yet
- * been set. Read_config_file will only set options with this value. Options
- * are processed in the following order: command line, user config file,
- * system config file. Last, fill_default_options is called.
- */
- void
- initialize_options(Options * options)
- {
- memset(options, 'X', sizeof(*options));
- options->forward_agent = -1;
- options->forward_agent_sock_path = NULL;
- options->forward_x11 = -1;
- options->forward_x11_trusted = -1;
- options->forward_x11_timeout = -1;
- options->stdio_forward_host = NULL;
- options->stdio_forward_port = 0;
- options->clear_forwardings = -1;
- options->exit_on_forward_failure = -1;
- options->xauth_location = NULL;
- options->fwd_opts.gateway_ports = -1;
- options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
- options->fwd_opts.streamlocal_bind_unlink = -1;
- options->pubkey_authentication = -1;
- options->challenge_response_authentication = -1;
- options->gss_authentication = -1;
- options->gss_deleg_creds = -1;
- options->password_authentication = -1;
- options->kbd_interactive_authentication = -1;
- options->kbd_interactive_devices = NULL;
- options->hostbased_authentication = -1;
- options->batch_mode = -1;
- options->check_host_ip = -1;
- options->strict_host_key_checking = -1;
- options->compression = -1;
- options->tcp_keep_alive = -1;
- options->port = -1;
- options->address_family = -1;
- options->connection_attempts = -1;
- options->connection_timeout = -1;
- options->number_of_password_prompts = -1;
- options->ciphers = NULL;
- options->macs = NULL;
- options->kex_algorithms = NULL;
- options->hostkeyalgorithms = NULL;
- options->ca_sign_algorithms = NULL;
- options->num_identity_files = 0;
- memset(options->identity_keys, 0, sizeof(options->identity_keys));
- options->num_certificate_files = 0;
- memset(options->certificates, 0, sizeof(options->certificates));
- options->hostname = NULL;
- options->host_key_alias = NULL;
- options->proxy_command = NULL;
- options->jump_user = NULL;
- options->jump_host = NULL;
- options->jump_port = -1;
- options->jump_extra = NULL;
- options->user = NULL;
- options->escape_char = -1;
- options->num_system_hostfiles = 0;
- options->num_user_hostfiles = 0;
- options->local_forwards = NULL;
- options->num_local_forwards = 0;
- options->remote_forwards = NULL;
- options->num_remote_forwards = 0;
- options->permitted_remote_opens = NULL;
- options->num_permitted_remote_opens = 0;
- options->log_facility = SYSLOG_FACILITY_NOT_SET;
- options->log_level = SYSLOG_LEVEL_NOT_SET;
- options->preferred_authentications = NULL;
- options->bind_address = NULL;
- options->bind_interface = NULL;
- options->pkcs11_provider = NULL;
- options->sk_provider = NULL;
- options->enable_ssh_keysign = - 1;
- options->no_host_authentication_for_localhost = - 1;
- options->identities_only = - 1;
- options->rekey_limit = - 1;
- options->rekey_interval = -1;
- options->verify_host_key_dns = -1;
- options->server_alive_interval = -1;
- options->server_alive_count_max = -1;
- options->send_env = NULL;
- options->num_send_env = 0;
- options->setenv = NULL;
- options->num_setenv = 0;
- options->control_path = NULL;
- options->control_master = -1;
- options->control_persist = -1;
- options->control_persist_timeout = 0;
- options->hash_known_hosts = -1;
- options->tun_open = -1;
- options->tun_local = -1;
- options->tun_remote = -1;
- options->local_command = NULL;
- options->permit_local_command = -1;
- options->remote_command = NULL;
- options->add_keys_to_agent = -1;
- options->add_keys_to_agent_lifespan = -1;
- options->identity_agent = NULL;
- options->visual_host_key = -1;
- options->ip_qos_interactive = -1;
- options->ip_qos_bulk = -1;
- options->request_tty = -1;
- options->no_shell = -1;
- options->stdin_null = -1;
- options->fork_after_authentication = -1;
- options->none_switch = -1;
- options->none_enabled = -1;
- options->nonemac_enabled = -1;
- options->disable_multithreaded = -1;
- options->hpn_disabled = -1;
- options->hpn_buffer_size = -1;
- options->tcp_rcv_buf_poll = -1;
- options->tcp_rcv_buf = -1;
- options->proxy_use_fdpass = -1;
- options->ignored_unknown = NULL;
- options->num_canonical_domains = 0;
- options->num_permitted_cnames = 0;
- options->canonicalize_max_dots = -1;
- options->canonicalize_fallback_local = -1;
- options->canonicalize_hostname = -1;
- options->revoked_host_keys = NULL;
- options->fingerprint_hash = -1;
- options->update_hostkeys = -1;
- options->hostbased_accepted_algos = NULL;
- options->pubkey_accepted_algos = NULL;
- }
- /*
- * A petite version of fill_default_options() that just fills the options
- * needed for hostname canonicalization to proceed.
- */
- void
- fill_default_options_for_canonicalization(Options *options)
- {
- if (options->canonicalize_max_dots == -1)
- options->canonicalize_max_dots = 1;
- if (options->canonicalize_fallback_local == -1)
- options->canonicalize_fallback_local = 1;
- if (options->canonicalize_hostname == -1)
- options->canonicalize_hostname = SSH_CANONICALISE_NO;
- }
- /*
- * Called after processing other sources of option data, this fills those
- * options for which no value has been specified with their default values.
- */
- int
- fill_default_options(Options * options)
- {
- char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
- char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
- int ret = 0, r;
- if (options->forward_agent == -1)
- options->forward_agent = 0;
- if (options->forward_x11 == -1)
- options->forward_x11 = 0;
- if (options->forward_x11_trusted == -1)
- options->forward_x11_trusted = 0;
- if (options->forward_x11_timeout == -1)
- options->forward_x11_timeout = 1200;
- /*
- * stdio forwarding (-W) changes the default for these but we defer
- * setting the values so they can be overridden.
- */
- if (options->exit_on_forward_failure == -1)
- options->exit_on_forward_failure =
- options->stdio_forward_host != NULL ? 1 : 0;
- if (options->clear_forwardings == -1)
- options->clear_forwardings =
- options->stdio_forward_host != NULL ? 1 : 0;
- if (options->clear_forwardings == 1)
- clear_forwardings(options);
- if (options->xauth_location == NULL)
- options->xauth_location = xstrdup(_PATH_XAUTH);
- if (options->fwd_opts.gateway_ports == -1)
- options->fwd_opts.gateway_ports = 0;
- if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
- options->fwd_opts.streamlocal_bind_mask = 0177;
- if (options->fwd_opts.streamlocal_bind_unlink == -1)
- options->fwd_opts.streamlocal_bind_unlink = 0;
- if (options->pubkey_authentication == -1)
- options->pubkey_authentication = 1;
- if (options->challenge_response_authentication == -1)
- options->challenge_response_authentication = 1;
- if (options->gss_authentication == -1)
- options->gss_authentication = 0;
- if (options->gss_deleg_creds == -1)
- options->gss_deleg_creds = 0;
- if (options->password_authentication == -1)
- options->password_authentication = 1;
- if (options->kbd_interactive_authentication == -1)
- options->kbd_interactive_authentication = 1;
- if (options->hostbased_authentication == -1)
- options->hostbased_authentication = 0;
- if (options->batch_mode == -1)
- options->batch_mode = 0;
- if (options->check_host_ip == -1)
- options->check_host_ip = 0;
- if (options->strict_host_key_checking == -1)
- options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
- if (options->compression == -1)
- options->compression = 0;
- if (options->tcp_keep_alive == -1)
- options->tcp_keep_alive = 1;
- if (options->port == -1)
- options->port = 0; /* Filled in ssh_connect. */
- if (options->address_family == -1)
- options->address_family = AF_UNSPEC;
- if (options->connection_attempts == -1)
- options->connection_attempts = 1;
- if (options->number_of_password_prompts == -1)
- options->number_of_password_prompts = 3;
- /* options->hostkeyalgorithms, default set in myproposals.h */
- if (options->add_keys_to_agent == -1) {
- options->add_keys_to_agent = 0;
- options->add_keys_to_agent_lifespan = 0;
- }
- if (options->num_identity_files == 0) {
- add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
- add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
- #ifdef OPENSSL_HAS_ECC
- add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
- #endif
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_ED25519, 0);
- add_identity_file(options, "~/",
- _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
- add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
- }
- if (options->escape_char == -1)
- options->escape_char = '~';
- if (options->num_system_hostfiles == 0) {
- options->system_hostfiles[options->num_system_hostfiles++] =
- xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
- options->system_hostfiles[options->num_system_hostfiles++] =
- xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
- }
- if (options->update_hostkeys == -1) {
- if (options->verify_host_key_dns <= 0 &&
- (options->num_user_hostfiles == 0 ||
- (options->num_user_hostfiles == 1 && strcmp(options->
- user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
- options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
- else
- options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
- }
- if (options->num_user_hostfiles == 0) {
- options->user_hostfiles[options->num_user_hostfiles++] =
- xstrdup(_PATH_SSH_USER_HOSTFILE);
- options->user_hostfiles[options->num_user_hostfiles++] =
- xstrdup(_PATH_SSH_USER_HOSTFILE2);
- }
- if (options->log_level == SYSLOG_LEVEL_NOT_SET)
- options->log_level = SYSLOG_LEVEL_INFO;
- if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
- options->log_facility = SYSLOG_FACILITY_USER;
- if (options->no_host_authentication_for_localhost == - 1)
- options->no_host_authentication_for_localhost = 0;
- if (options->identities_only == -1)
- options->identities_only = 0;
- if (options->enable_ssh_keysign == -1)
- options->enable_ssh_keysign = 0;
- if (options->rekey_limit == -1)
- options->rekey_limit = 0;
- if (options->rekey_interval == -1)
- options->rekey_interval = 0;
- if (options->verify_host_key_dns == -1)
- options->verify_host_key_dns = 0;
- if (options->server_alive_interval == -1) {
- /* in batch mode, default is 5mins */
- if (options->batch_mode == 1)
- options->server_alive_interval = 300;
- else
- options->server_alive_interval = 0;
- }
- if (options->server_alive_count_max == -1)
- options->server_alive_count_max = 3;
- if (options->hpn_disabled == -1)
- options->hpn_disabled = 0;
- if (options->hpn_buffer_size > -1) {
- /* if a user tries to set the size to 0 set it to 6MB */
- if (options->hpn_buffer_size == 0)
- options->hpn_buffer_size = 6 * 1024 * 1024;
- /* limit the buffer to SSHBUF_SIZE_MAX (currently 256MB) */
- if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024)) {
- options->hpn_buffer_size = SSHBUF_SIZE_MAX;
- debug("User requested buffer larger than 256MB. Request reverted to 256MB");
- } else
- options->hpn_buffer_size *= 1024;
- debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
- }
- if (options->tcp_rcv_buf == 0)
- options->tcp_rcv_buf = 1;
- if (options->tcp_rcv_buf > -1)
- options->tcp_rcv_buf *=1024;
- if (options->tcp_rcv_buf_poll == -1)
- options->tcp_rcv_buf_poll = 1;
- if (options->none_switch == -1)
- options->none_switch = 0;
- if (options->none_enabled == -1)
- options->none_enabled = 0;
- if (options->none_enabled == 0 && options->none_switch > 0) {
- fprintf(stderr, "NoneEnabled must be enabled to use the None Switch option. None cipher disabled.\n");
- options->none_enabled = 0;
- }
- if (options->nonemac_enabled == -1)
- options->nonemac_enabled = 0;
- if (options->nonemac_enabled > 0 && (options->none_enabled == 0 ||
- options->none_switch == 0)) {
- fprintf(stderr, "None MAC can only be used with the None cipher. None MAC disabled.\n");
- options->nonemac_enabled = 0;
- }
- if (options->disable_multithreaded == -1)
- options->disable_multithreaded = 0;
- if (options->control_master == -1)
- options->control_master = 0;
- if (options->control_persist == -1) {
- options->control_persist = 0;
- options->control_persist_timeout = 0;
- }
- if (options->hash_known_hosts == -1)
- options->hash_known_hosts = 0;
- if (options->tun_open == -1)
- options->tun_open = SSH_TUNMODE_NO;
- if (options->tun_local == -1)
- options->tun_local = SSH_TUNID_ANY;
- if (options->tun_remote == -1)
- options->tun_remote = SSH_TUNID_ANY;
- if (options->permit_local_command == -1)
- options->permit_local_command = 0;
- if (options->visual_host_key == -1)
- options->visual_host_key = 0;
- if (options->ip_qos_interactive == -1)
- options->ip_qos_interactive = IPTOS_LOWDELAY;
- if (options->ip_qos_bulk == -1)
- options->ip_qos_bulk = IPTOS_THROUGHPUT;
- if (options->request_tty == -1)
- options->request_tty = REQUEST_TTY_AUTO;
- if (options->no_shell == -1)
- options->no_shell = 0;
- if (options->stdin_null == -1)
- options->stdin_null = 0;
- if (options->fork_after_authentication == -1)
- options->fork_after_authentication = 0;
- if (options->proxy_use_fdpass == -1)
- options->proxy_use_fdpass = 0;
- if (options->canonicalize_max_dots == -1)
- options->canonicalize_max_dots = 1;
- if (options->canonicalize_fallback_local == -1)
- options->canonicalize_fallback_local = 1;
- if (options->canonicalize_hostname == -1)
- options->canonicalize_hostname = SSH_CANONICALISE_NO;
- if (options->fingerprint_hash == -1)
- options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
- #ifdef ENABLE_SK_INTERNAL
- if (options->sk_provider == NULL)
- options->sk_provider = xstrdup("internal");
- #else
- if (options->sk_provider == NULL)
- options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
- #endif
- /* Expand KEX name lists */
- all_cipher = cipher_alg_list(',', 0);
- all_mac = mac_alg_list(',');
- all_kex = kex_alg_list(',');
- all_key = sshkey_alg_list(0, 0, 1, ',');
- all_sig = sshkey_alg_list(0, 1, 1, ',');
- /* remove unsupported algos from default lists */
- def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
- def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
- def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
- #define ASSEMBLE(what, defaults, all) \
- do { \
- if ((r = kex_assemble_names(&options->what, \
- defaults, all)) != 0) { \
- error(r, "%s", #what); \
- goto fail; \
- } \
- } while (0)
- ASSEMBLE(ciphers, def_cipher, all_cipher);
- ASSEMBLE(macs, def_mac, all_mac);
- ASSEMBLE(kex_algorithms, def_kex, all_kex);
- ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
- ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
- ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
- #undef ASSEMBLE
- #define CLEAR_ON_NONE(v) \
- do { \
- if (option_clear_or_none(v)) { \
- free(v); \
- v = NULL; \
- } \
- } while(0)
- CLEAR_ON_NONE(options->local_command);
- CLEAR_ON_NONE(options->remote_command);
- CLEAR_ON_NONE(options->proxy_command);
- CLEAR_ON_NONE(options->control_path);
- CLEAR_ON_NONE(options->revoked_host_keys);
- CLEAR_ON_NONE(options->pkcs11_provider);
- CLEAR_ON_NONE(options->sk_provider);
- if (options->jump_host != NULL &&
- strcmp(options->jump_host, "none") == 0 &&
- options->jump_port == 0 && options->jump_user == NULL) {
- free(options->jump_host);
- options->jump_host = NULL;
- }
- /* options->identity_agent distinguishes NULL from 'none' */
- /* options->user will be set in the main program if appropriate */
- /* options->hostname will be set in the main program if appropriate */
- /* options->host_key_alias should not be set by default */
- /* options->preferred_authentications will be set in ssh */
- /* success */
- ret = 0;
- fail:
- free(all_cipher);
- free(all_mac);
- free(all_kex);
- free(all_key);
- free(all_sig);
- free(def_cipher);
- free(def_mac);
- free(def_kex);
- free(def_key);
- free(def_sig);
- return ret;
- }
- void
- free_options(Options *o)
- {
- int i;
- if (o == NULL)
- return;
- #define FREE_ARRAY(type, n, a) \
- do { \
- type _i; \
- for (_i = 0; _i < (n); _i++) \
- free((a)[_i]); \
- } while (0)
- free(o->forward_agent_sock_path);
- free(o->xauth_location);
- //FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
- //free(o->log_verbose);
- free(o->ciphers);
- free(o->macs);
- free(o->hostkeyalgorithms);
- free(o->kex_algorithms);
- free(o->ca_sign_algorithms);
- free(o->hostname);
- free(o->host_key_alias);
- free(o->proxy_command);
- free(o->user);
- FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
- FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
- free(o->preferred_authentications);
- free(o->bind_address);
- free(o->bind_interface);
- free(o->pkcs11_provider);
- free(o->sk_provider);
- for (i = 0; i < o->num_identity_files; i++) {
- free(o->identity_files[i]);
- sshkey_free(o->identity_keys[i]);
- }
- for (i = 0; i < o->num_certificate_files; i++) {
- free(o->certificate_files[i]);
- sshkey_free(o->certificates[i]);
- }
- free(o->identity_agent);
- for (i = 0; i < o->num_local_forwards; i++) {
- free(o->local_forwards[i].listen_host);
- free(o->local_forwards[i].listen_path);
- free(o->local_forwards[i].connect_host);
- free(o->local_forwards[i].connect_path);
- }
- free(o->local_forwards);
- for (i = 0; i < o->num_remote_forwards; i++) {
- free(o->remote_forwards[i].listen_host);
- free(o->remote_forwards[i].listen_path);
- free(o->remote_forwards[i].connect_host);
- free(o->remote_forwards[i].connect_path);
- }
- free(o->remote_forwards);
- free(o->stdio_forward_host);
- FREE_ARRAY(int, o->num_send_env, o->send_env);
- free(o->send_env);
- FREE_ARRAY(int, o->num_setenv, o->setenv);
- free(o->setenv);
- free(o->control_path);
- free(o->local_command);
- free(o->remote_command);
- FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
- for (i = 0; i < o->num_permitted_cnames; i++) {
- free(o->permitted_cnames[i].source_list);
- free(o->permitted_cnames[i].target_list);
- }
- free(o->revoked_host_keys);
- free(o->hostbased_accepted_algos);
- free(o->pubkey_accepted_algos);
- free(o->jump_user);
- free(o->jump_host);
- free(o->jump_extra);
- free(o->ignored_unknown);
- explicit_bzero(o, sizeof(*o));
- #undef FREE_ARRAY
- }
- struct fwdarg {
- char *arg;
- int ispath;
- };
- /*
- * parse_fwd_field
- * parses the next field in a port forwarding specification.
- * sets fwd to the parsed field and advances p past the colon
- * or sets it to NULL at end of string.
- * returns 0 on success, else non-zero.
- */
- static int
- parse_fwd_field(char **p, struct fwdarg *fwd)
- {
- char *ep, *cp = *p;
- int ispath = 0;
- if (*cp == '\0') {
- *p = NULL;
- return -1; /* end of string */
- }
- /*
- * A field escaped with square brackets is used literally.
- * XXX - allow ']' to be escaped via backslash?
- */
- if (*cp == '[') {
- /* find matching ']' */
- for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
- if (*ep == '/')
- ispath = 1;
- }
- /* no matching ']' or not at end of field. */
- if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
- return -1;
- /* NUL terminate the field and advance p past the colon */
- *ep++ = '\0';
- if (*ep != '\0')
- *ep++ = '\0';
- fwd->arg = cp + 1;
- fwd->ispath = ispath;
- *p = ep;
- return 0;
- }
- for (cp = *p; *cp != '\0'; cp++) {
- switch (*cp) {
- case '\\':
- memmove(cp, cp + 1, strlen(cp + 1) + 1);
- if (*cp == '\0')
- return -1;
- break;
- case '/':
- ispath = 1;
- break;
- case ':':
- *cp++ = '\0';
- goto done;
- }
- }
- done:
- fwd->arg = *p;
- fwd->ispath = ispath;
- *p = cp;
- return 0;
- }
- /*
- * parse_forward
- * parses a string containing a port forwarding specification of the form:
- * dynamicfwd == 0
- * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
- * listenpath:connectpath
- * dynamicfwd == 1
- * [listenhost:]listenport
- * returns number of arguments parsed or zero on error
- */
- int
- parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
- {
- struct fwdarg fwdargs[4];
- char *p, *cp;
- int i, err;
- memset(fwd, 0, sizeof(*fwd));
- memset(fwdargs, 0, sizeof(fwdargs));
- /*
- * We expand environment variables before checking if we think they're
- * paths so that if ${VAR} expands to a fully qualified path it is
- * treated as a path.
- */
- cp = p = dollar_expand(&err, fwdspec);
- if (p == NULL || err)
- return 0;
- /* skip leading spaces */
- while (isspace((u_char)*cp))
- cp++;
- for (i = 0; i < 4; ++i) {
- if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
- break;
- }
- /* Check for trailing garbage */
- if (cp != NULL && *cp != '\0') {
- i = 0; /* failure */
- }
- switch (i) {
- case 1:
- if (fwdargs[0].ispath) {
- fwd->listen_path = xstrdup(fwdargs[0].arg);
- fwd->listen_port = PORT_STREAMLOCAL;
- } else {
- fwd->listen_host = NULL;
- fwd->listen_port = a2port(fwdargs[0].arg);
- }
- fwd->connect_host = xstrdup("socks");
- break;
- case 2:
- if (fwdargs[0].ispath && fwdargs[1].ispath) {
- fwd->listen_path = xstrdup(fwdargs[0].arg);
- fwd->listen_port = PORT_STREAMLOCAL;
- fwd->connect_path = xstrdup(fwdargs[1].arg);
- fwd->connect_port = PORT_STREAMLOCAL;
- } else if (fwdargs[1].ispath) {
- fwd->listen_host = NULL;
- fwd->listen_port = a2port(fwdargs[0].arg);
- fwd->connect_path = xstrdup(fwdargs[1].arg);
- fwd->connect_port = PORT_STREAMLOCAL;
- } else {
- fwd->listen_host = xstrdup(fwdargs[0].arg);
- fwd->listen_port = a2port(fwdargs[1].arg);
- fwd->connect_host = xstrdup("socks");
- }
- break;
- case 3:
- if (fwdargs[0].ispath) {
- fwd->listen_path = xstrdup(fwdargs[0].arg);
- fwd->listen_port = PORT_STREAMLOCAL;
- fwd->connect_host = xstrdup(fwdargs[1].arg);
- fwd->connect_port = a2port(fwdargs[2].arg);
- } else if (fwdargs[2].ispath) {
- fwd->listen_host = xstrdup(fwdargs[0].arg);
- fwd->listen_port = a2port(fwdargs[1].arg);
- fwd->connect_path = xstrdup(fwdargs[2].arg);
- fwd->connect_port = PORT_STREAMLOCAL;
- } else {
- fwd->listen_host = NULL;
- fwd->listen_port = a2port(fwdargs[0].arg);
- fwd->connect_host = xstrdup(fwdargs[1].arg);
- fwd->connect_port = a2port(fwdargs[2].arg);
- }
- break;
- case 4:
- fwd->listen_host = xstrdup(fwdargs[0].arg);
- fwd->listen_port = a2port(fwdargs[1].arg);
- fwd->connect_host = xstrdup(fwdargs[2].arg);
- fwd->connect_port = a2port(fwdargs[3].arg);
- break;
- default:
- i = 0; /* failure */
- }
- free(p);
- if (dynamicfwd) {
- if (!(i == 1 || i == 2))
- goto fail_free;
- } else {
- if (!(i == 3 || i == 4)) {
- if (fwd->connect_path == NULL &&
- fwd->listen_path == NULL)
- goto fail_free;
- }
- if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
- goto fail_free;
- }
- if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
- (!remotefwd && fwd->listen_port == 0))
- goto fail_free;
- if (fwd->connect_host != NULL &&
- strlen(fwd->connect_host) >= NI_MAXHOST)
- goto fail_free;
- /* XXX - if connecting to a remote socket, max sun len may not match this host */
- if (fwd->connect_path != NULL &&
- strlen(fwd->connect_path) >= PATH_MAX_SUN)
- goto fail_free;
- if (fwd->listen_host != NULL &&
- strlen(fwd->listen_host) >= NI_MAXHOST)
- goto fail_free;
- if (fwd->listen_path != NULL &&
- strlen(fwd->listen_path) >= PATH_MAX_SUN)
- goto fail_free;
- return (i);
- fail_free:
- free(fwd->connect_host);
- fwd->connect_host = NULL;
- free(fwd->connect_path);
- fwd->connect_path = NULL;
- free(fwd->listen_host);
- fwd->listen_host = NULL;
- free(fwd->listen_path);
- fwd->listen_path = NULL;
- return (0);
- }
- int
- parse_jump(const char *s, Options *o, int active)
- {
- char *orig, *sdup, *cp;
- char *host = NULL, *user = NULL;
- int r, ret = -1, port = -1, first;
- active &= o->proxy_command == NULL && o->jump_host == NULL;
- orig = sdup = xstrdup(s);
- first = active;
- do {
- if (strcasecmp(s, "none") == 0)
- break;
- if ((cp = strrchr(sdup, ',')) == NULL)
- cp = sdup; /* last */
- else
- *cp++ = '\0';
- if (first) {
- /* First argument and configuration is active */
- r = parse_ssh_uri(cp, &user, &host, &port);
- if (r == -1 || (r == 1 &&
- parse_user_host_port(cp, &user, &host, &port) != 0))
- goto out;
- } else {
- /* Subsequent argument or inactive configuration */
- r = parse_ssh_uri(cp, NULL, NULL, NULL);
- if (r == -1 || (r == 1 &&
- parse_user_host_port(cp, NULL, NULL, NULL) != 0))
- goto out;
- }
- first = 0; /* only check syntax for subsequent hosts */
- } while (cp != sdup);
- /* success */
- if (active) {
- if (strcasecmp(s, "none") == 0) {
- o->jump_host = xstrdup("none");
- o->jump_port = 0;
- } else {
- o->jump_user = user;
- o->jump_host = host;
- o->jump_port = port;
- o->proxy_command = xstrdup("none");
- user = host = NULL;
- if ((cp = strrchr(s, ',')) != NULL && cp != s) {
- o->jump_extra = xstrdup(s);
- o->jump_extra[cp - s] = '\0';
- }
- }
- }
- ret = 0;
- out:
- free(orig);
- free(user);
- free(host);
- return ret;
- }
- int
- parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
- {
- char *user = NULL, *host = NULL, *path = NULL;
- int r, port;
- r = parse_uri("ssh", uri, &user, &host, &port, &path);
- if (r == 0 && path != NULL)
- r = -1; /* path not allowed */
- if (r == 0) {
- if (userp != NULL) {
- *userp = user;
- user = NULL;
- }
- if (hostp != NULL) {
- *hostp = host;
- host = NULL;
- }
- if (portp != NULL)
- *portp = port;
- }
- free(user);
- free(host);
- free(path);
- return r;
- }
- /* XXX the following is a near-vebatim copy from servconf.c; refactor */
- static const char *
- fmt_multistate_int(int val, const struct multistate *m)
- {
- u_int i;
- for (i = 0; m[i].key != NULL; i++) {
- if (m[i].value == val)
- return m[i].key;
- }
- return "UNKNOWN";
- }
- static const char *
- fmt_intarg(OpCodes code, int val)
- {
- if (val == -1)
- return "unset";
- switch (code) {
- case oAddressFamily:
- return fmt_multistate_int(val, multistate_addressfamily);
- case oVerifyHostKeyDNS:
- case oUpdateHostkeys:
- return fmt_multistate_int(val, multistate_yesnoask);
- case oStrictHostKeyChecking:
- return fmt_multistate_int(val, multistate_strict_hostkey);
- case oControlMaster:
- return fmt_multistate_int(val, multistate_controlmaster);
- case oTunnel:
- return fmt_multistate_int(val, multistate_tunnel);
- case oRequestTTY:
- return fmt_multistate_int(val, multistate_requesttty);
- case oCanonicalizeHostname:
- return fmt_multistate_int(val, multistate_canonicalizehostname);
- case oAddKeysToAgent:
- return fmt_multistate_int(val, multistate_yesnoaskconfirm);
- case oFingerprintHash:
- return ssh_digest_alg_name(val);
- default:
- switch (val) {
- case 0:
- return "no";
- case 1:
- return "yes";
- default:
- return "UNKNOWN";
- }
- }
- }
- static const char *
- lookup_opcode_name(OpCodes code)
- {
- u_int i;
- for (i = 0; keywords[i].name != NULL; i++)
- if (keywords[i].opcode == code)
- return(keywords[i].name);
- return "UNKNOWN";
- }
- static void
- dump_cfg_int(OpCodes code, int val)
- {
- printf("%s %d\n", lookup_opcode_name(code), val);
- }
- static void
- dump_cfg_fmtint(OpCodes code, int val)
- {
- printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
- }
- static void
- dump_cfg_string(OpCodes code, const char *val)
- {
- if (val == NULL)
- return;
- printf("%s %s\n", lookup_opcode_name(code), val);
- }
- static void
- dump_cfg_strarray(OpCodes code, u_int count, char **vals)
- {
- u_int i;
- for (i = 0; i < count; i++)
- printf("%s %s\n", lookup_opcode_name(code), vals[i]);
- }
- static void
- dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
- {
- u_int i;
- printf("%s", lookup_opcode_name(code));
- for (i = 0; i < count; i++)
- printf(" %s", vals[i]);
- printf("\n");
- }
- static void
- dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
- {
- const struct Forward *fwd;
- u_int i;
- /* oDynamicForward */
- for (i = 0; i < count; i++) {
- fwd = &fwds[i];
- if (code == oDynamicForward && fwd->connect_host != NULL &&
- strcmp(fwd->connect_host, "socks") != 0)
- continue;
- if (code == oLocalForward && fwd->connect_host != NULL &&
- strcmp(fwd->connect_host, "socks") == 0)
- continue;
- printf("%s", lookup_opcode_name(code));
- if (fwd->listen_port == PORT_STREAMLOCAL)
- printf(" %s", fwd->listen_path);
- else if (fwd->listen_host == NULL)
- printf(" %d", fwd->listen_port);
- else {
- printf(" [%s]:%d",
- fwd->listen_host, fwd->listen_port);
- }
- if (code != oDynamicForward) {
- if (fwd->connect_port == PORT_STREAMLOCAL)
- printf(" %s", fwd->connect_path);
- else if (fwd->connect_host == NULL)
- printf(" %d", fwd->connect_port);
- else {
- printf(" [%s]:%d",
- fwd->connect_host, fwd->connect_port);
- }
- }
- printf("\n");
- }
- }
- void
- dump_client_config(Options *o, const char *host)
- {
- int i, r;
- char buf[8], *all_key;
- /*
- * Expand HostKeyAlgorithms name lists. This isn't handled in
- * fill_default_options() like the other algorithm lists because
- * the host key algorithms are by default dynamically chosen based
- * on the host's keys found in known_hosts.
- */
- all_key = sshkey_alg_list(0, 0, 1, ',');
- if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
- all_key)) != 0)
- fatal("%s: expand HostKeyAlgorithms: %s", __func__, ssh_err(r));
- free(all_key);
- /* Most interesting options first: user, host, port */
- dump_cfg_string(oUser, o->user);
- dump_cfg_string(oHostname, host);
- dump_cfg_int(oPort, o->port);
- /* Flag options */
- dump_cfg_fmtint(oAddressFamily, o->address_family);
- dump_cfg_fmtint(oBatchMode, o->batch_mode);
- dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
- dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
- dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
- dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
- dump_cfg_fmtint(oCompression, o->compression);
- dump_cfg_fmtint(oControlMaster, o->control_master);
- dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
- dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
- dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
- dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
- dump_cfg_fmtint(oForwardX11, o->forward_x11);
- dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
- dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
- #ifdef GSSAPI
- dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
- dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
- #endif /* GSSAPI */
- dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
- dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
- dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
- dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
- dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
- dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
- dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
- dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
- dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
- dump_cfg_fmtint(oRequestTTY, o->request_tty);
- dump_cfg_fmtint(oNoShell, o->no_shell);
- dump_cfg_fmtint(oStdinNull, o->stdin_null);
- dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
- dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
- dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
- dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
- dump_cfg_fmtint(oTunnel, o->tun_open);
- dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
- dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
- dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
- /* Integer options */
- dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
- dump_cfg_int(oConnectionAttempts, o->connection_attempts);
- dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
- dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
- dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
- dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
- /* String options */
- dump_cfg_string(oBindAddress, o->bind_address);
- dump_cfg_string(oBindInterface, o->bind_interface);
- dump_cfg_string(oCiphers, o->ciphers);
- dump_cfg_string(oControlPath, o->control_path);
- dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
- dump_cfg_string(oHostKeyAlias, o->host_key_alias);
- dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
- dump_cfg_string(oIdentityAgent, o->identity_agent);
- dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
- dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
- dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
- dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
- dump_cfg_string(oLocalCommand, o->local_command);
- dump_cfg_string(oRemoteCommand, o->remote_command);
- dump_cfg_string(oLogLevel, log_level_name(o->log_level));
- dump_cfg_string(oMacs, o->macs);
- #ifdef ENABLE_PKCS11
- dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
- #endif
- dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
- dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
- dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
- dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
- dump_cfg_string(oXAuthLocation, o->xauth_location);
- /* Forwards */
- dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
- dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
- dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
- /* String array options */
- dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
- dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
- dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
- dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
- dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
- dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
- dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
- /* Special cases */
- /* PermitRemoteOpen */
- if (o->num_permitted_remote_opens == 0)
- printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
- else
- dump_cfg_strarray_oneline(oPermitRemoteOpen,
- o->num_permitted_remote_opens, o->permitted_remote_opens);
- /* AddKeysToAgent */
- if (o->add_keys_to_agent_lifespan <= 0)
- dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
- else {
- printf("addkeystoagent%s %d\n",
- o->add_keys_to_agent == 3 ? " confirm" : "",
- o->add_keys_to_agent_lifespan);
- }
- /* oForwardAgent */
- if (o->forward_agent_sock_path == NULL)
- dump_cfg_fmtint(oForwardAgent, o->forward_agent);
- else
- dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
- /* oConnectTimeout */
- if (o->connection_timeout == -1)
- printf("connecttimeout none\n");
- else
- dump_cfg_int(oConnectTimeout, o->connection_timeout);
- /* oTunnelDevice */
- printf("tunneldevice");
- if (o->tun_local == SSH_TUNID_ANY)
- printf(" any");
- else
- printf(" %d", o->tun_local);
- if (o->tun_remote == SSH_TUNID_ANY)
- printf(":any");
- else
- printf(":%d", o->tun_remote);
- printf("\n");
- /* oCanonicalizePermittedCNAMEs */
- if ( o->num_permitted_cnames > 0) {
- printf("canonicalizePermittedcnames");
- for (i = 0; i < o->num_permitted_cnames; i++) {
- printf(" %s:%s", o->permitted_cnames[i].source_list,
- o->permitted_cnames[i].target_list);
- }
- printf("\n");
- }
- /* oControlPersist */
- if (o->control_persist == 0 || o->control_persist_timeout == 0)
- dump_cfg_fmtint(oControlPersist, o->control_persist);
- else
- dump_cfg_int(oControlPersist, o->control_persist_timeout);
- /* oEscapeChar */
- if (o->escape_char == SSH_ESCAPECHAR_NONE)
- printf("escapechar none\n");
- else {
- vis(buf, o->escape_char, VIS_WHITE, 0);
- printf("escapechar %s\n", buf);
- }
- /* oIPQoS */
- printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
- printf("%s\n", iptos2str(o->ip_qos_bulk));
- /* oRekeyLimit */
- printf("rekeylimit %llu %d\n",
- (unsigned long long)o->rekey_limit, o->rekey_interval);
- /* oStreamLocalBindMask */
- printf("streamlocalbindmask 0%o\n",
- o->fwd_opts.streamlocal_bind_mask);
- /* oLogFacility */
- printf("syslogfacility %s\n", log_facility_name(o->log_facility));
- /* oProxyCommand / oProxyJump */
- if (o->jump_host == NULL)
- dump_cfg_string(oProxyCommand, o->proxy_command);
- else {
- /* Check for numeric addresses */
- i = strchr(o->jump_host, ':') != NULL ||
- strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
- snprintf(buf, sizeof(buf), "%d", o->jump_port);
- printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
- /* optional additional jump spec */
- o->jump_extra == NULL ? "" : o->jump_extra,
- o->jump_extra == NULL ? "" : ",",
- /* optional user */
- o->jump_user == NULL ? "" : o->jump_user,
- o->jump_user == NULL ? "" : "@",
- /* opening [ if hostname is numeric */
- i ? "[" : "",
- /* mandatory hostname */
- o->jump_host,
- /* closing ] if hostname is numeric */
- i ? "]" : "",
- /* optional port number */
- o->jump_port <= 0 ? "" : ":",
- o->jump_port <= 0 ? "" : buf);
- }
- }
|