17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi>
37c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
47c478bd9Sstevel@tonic-gate * All rights reserved
57c478bd9Sstevel@tonic-gate * Functions for reading the configuration files.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software
87c478bd9Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this
97c478bd9Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is
107c478bd9Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be
117c478bd9Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell".
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate /*
14b9aa66a7SJan Pechanec * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
157c478bd9Sstevel@tonic-gate * Use is subject to license terms.
16*33c41f2bSJoshua M. Clulow * Copyright 2013 Joyent, Inc. All rights reserved.
177c478bd9Sstevel@tonic-gate */
187c478bd9Sstevel@tonic-gate
197c478bd9Sstevel@tonic-gate #include "includes.h"
207c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate #include "ssh.h"
237c478bd9Sstevel@tonic-gate #include "xmalloc.h"
247c478bd9Sstevel@tonic-gate #include "compat.h"
257c478bd9Sstevel@tonic-gate #include "cipher.h"
267c478bd9Sstevel@tonic-gate #include "pathnames.h"
277c478bd9Sstevel@tonic-gate #include "log.h"
287c478bd9Sstevel@tonic-gate #include "readconf.h"
297c478bd9Sstevel@tonic-gate #include "match.h"
307c478bd9Sstevel@tonic-gate #include "misc.h"
317c478bd9Sstevel@tonic-gate #include "kex.h"
327c478bd9Sstevel@tonic-gate #include "mac.h"
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /* Format of the configuration file:
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate # Configuration data is parsed as follows:
377c478bd9Sstevel@tonic-gate # 1. command line options
387c478bd9Sstevel@tonic-gate # 2. user-specific file
397c478bd9Sstevel@tonic-gate # 3. system-wide file
407c478bd9Sstevel@tonic-gate # Any configuration value is only changed the first time it is set.
417c478bd9Sstevel@tonic-gate # Thus, host-specific definitions should be at the beginning of the
427c478bd9Sstevel@tonic-gate # configuration file, and defaults at the end.
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate # Host-specific declarations. These may override anything above. A single
457c478bd9Sstevel@tonic-gate # host may match multiple declarations; these are processed in the order
467c478bd9Sstevel@tonic-gate # that they are given in.
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate Host *.ngs.fi ngs.fi
497c478bd9Sstevel@tonic-gate User foo
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate Host fake.com
527c478bd9Sstevel@tonic-gate HostName another.host.name.real.org
537c478bd9Sstevel@tonic-gate User blaah
547c478bd9Sstevel@tonic-gate Port 34289
557c478bd9Sstevel@tonic-gate ForwardX11 no
567c478bd9Sstevel@tonic-gate ForwardAgent no
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate Host books.com
597c478bd9Sstevel@tonic-gate RemoteForward 9999 shadows.cs.hut.fi:9999
607c478bd9Sstevel@tonic-gate Cipher 3des
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate Host fascist.blob.com
637c478bd9Sstevel@tonic-gate Port 23123
647c478bd9Sstevel@tonic-gate User tylonen
657c478bd9Sstevel@tonic-gate RhostsAuthentication no
667c478bd9Sstevel@tonic-gate PasswordAuthentication no
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate Host puukko.hut.fi
697c478bd9Sstevel@tonic-gate User t35124p
707c478bd9Sstevel@tonic-gate ProxyCommand ssh-proxy %h %p
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate Host *.fr
737c478bd9Sstevel@tonic-gate PublicKeyAuthentication no
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate Host *.su
767c478bd9Sstevel@tonic-gate Cipher none
777c478bd9Sstevel@tonic-gate PasswordAuthentication no
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate # Defaults for various options
807c478bd9Sstevel@tonic-gate Host *
817c478bd9Sstevel@tonic-gate ForwardAgent no
827c478bd9Sstevel@tonic-gate ForwardX11 no
837c478bd9Sstevel@tonic-gate RhostsAuthentication yes
847c478bd9Sstevel@tonic-gate PasswordAuthentication yes
857c478bd9Sstevel@tonic-gate RSAAuthentication yes
867c478bd9Sstevel@tonic-gate RhostsRSAAuthentication yes
877c478bd9Sstevel@tonic-gate StrictHostKeyChecking yes
887c478bd9Sstevel@tonic-gate KeepAlives no
897c478bd9Sstevel@tonic-gate IdentityFile ~/.ssh/identity
907c478bd9Sstevel@tonic-gate Port 22
917c478bd9Sstevel@tonic-gate EscapeChar ~
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate */
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate /* Keyword tokens. */
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate typedef enum {
987c478bd9Sstevel@tonic-gate oBadOption,
99383a1232Sjp161948 oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
100383a1232Sjp161948 oRhostsAuthentication,
1017c478bd9Sstevel@tonic-gate oPasswordAuthentication, oRSAAuthentication,
1027c478bd9Sstevel@tonic-gate oChallengeResponseAuthentication, oXAuthLocation,
1037c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
1047c478bd9Sstevel@tonic-gate oKerberosAuthentication,
1057c478bd9Sstevel@tonic-gate #endif
1067c478bd9Sstevel@tonic-gate #ifdef GSSAPI
1077c478bd9Sstevel@tonic-gate oGssKeyEx, oGssAuthentication, oGssDelegateCreds,
1087c478bd9Sstevel@tonic-gate #ifdef GSI
1097c478bd9Sstevel@tonic-gate oGssGlobusDelegateLimitedCreds,
1107c478bd9Sstevel@tonic-gate #endif /* GSI */
1117c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
1127c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
1137c478bd9Sstevel@tonic-gate oKerberosTgtPassing,
1147c478bd9Sstevel@tonic-gate #endif
1157c478bd9Sstevel@tonic-gate #ifdef AFS
1167c478bd9Sstevel@tonic-gate oAFSTokenPassing,
1177c478bd9Sstevel@tonic-gate #endif
1187c478bd9Sstevel@tonic-gate oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
1197c478bd9Sstevel@tonic-gate oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
1207c478bd9Sstevel@tonic-gate oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
1217c478bd9Sstevel@tonic-gate oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
1227c478bd9Sstevel@tonic-gate oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
1237c478bd9Sstevel@tonic-gate oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
1247c478bd9Sstevel@tonic-gate oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
1257c478bd9Sstevel@tonic-gate oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
1267c478bd9Sstevel@tonic-gate oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
1277c478bd9Sstevel@tonic-gate oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
1287c478bd9Sstevel@tonic-gate oClearAllForwardings, oNoHostAuthenticationForLocalhost,
129442d23f4Sjp161948 oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts,
130e5e9dedaSjp161948 oServerAliveInterval, oServerAliveCountMax, oDisableBanner,
131cd7d5fafSJan Pechanec oIgnoreIfUnknown, oRekeyLimit, oUseOpenSSLEngine,
1329a8058b5Sjp161948 oDeprecated
1337c478bd9Sstevel@tonic-gate } OpCodes;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate /* Textual representations of the tokens. */
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate static struct {
1387c478bd9Sstevel@tonic-gate const char *name;
1397c478bd9Sstevel@tonic-gate OpCodes opcode;
1407c478bd9Sstevel@tonic-gate } keywords[] = {
1417c478bd9Sstevel@tonic-gate { "forwardagent", oForwardAgent },
1427c478bd9Sstevel@tonic-gate { "forwardx11", oForwardX11 },
143383a1232Sjp161948 { "forwardx11trusted", oForwardX11Trusted },
1447c478bd9Sstevel@tonic-gate { "xauthlocation", oXAuthLocation },
1457c478bd9Sstevel@tonic-gate { "gatewayports", oGatewayPorts },
1467c478bd9Sstevel@tonic-gate { "useprivilegedport", oUsePrivilegedPort },
1477c478bd9Sstevel@tonic-gate { "rhostsauthentication", oRhostsAuthentication },
1487c478bd9Sstevel@tonic-gate { "passwordauthentication", oPasswordAuthentication },
1497c478bd9Sstevel@tonic-gate { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
1507c478bd9Sstevel@tonic-gate { "kbdinteractivedevices", oKbdInteractiveDevices },
1517c478bd9Sstevel@tonic-gate { "rsaauthentication", oRSAAuthentication },
1527c478bd9Sstevel@tonic-gate { "pubkeyauthentication", oPubkeyAuthentication },
1537c478bd9Sstevel@tonic-gate { "dsaauthentication", oPubkeyAuthentication }, /* alias */
1547c478bd9Sstevel@tonic-gate { "rhostsrsaauthentication", oRhostsRSAAuthentication },
1557c478bd9Sstevel@tonic-gate { "hostbasedauthentication", oHostbasedAuthentication },
1567c478bd9Sstevel@tonic-gate { "challengeresponseauthentication", oChallengeResponseAuthentication },
1577c478bd9Sstevel@tonic-gate { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
1587c478bd9Sstevel@tonic-gate { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
1597c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
1607c478bd9Sstevel@tonic-gate { "kerberosauthentication", oKerberosAuthentication },
1617c478bd9Sstevel@tonic-gate #endif
1627c478bd9Sstevel@tonic-gate #ifdef GSSAPI
1637c478bd9Sstevel@tonic-gate { "gssapikeyexchange", oGssKeyEx },
1647c478bd9Sstevel@tonic-gate { "gssapiauthentication", oGssAuthentication },
1657c478bd9Sstevel@tonic-gate { "gssapidelegatecredentials", oGssDelegateCreds },
1667c478bd9Sstevel@tonic-gate { "gsskeyex", oGssKeyEx }, /* alias */
1677c478bd9Sstevel@tonic-gate { "gssauthentication", oGssAuthentication }, /* alias */
1687c478bd9Sstevel@tonic-gate { "gssdelegatecreds", oGssDelegateCreds }, /* alias */
1697c478bd9Sstevel@tonic-gate #ifdef GSI
1707c478bd9Sstevel@tonic-gate /* For backwards compatability with old 1.2.27 client code */
1717c478bd9Sstevel@tonic-gate { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
1727c478bd9Sstevel@tonic-gate { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
1737c478bd9Sstevel@tonic-gate #endif /* GSI */
1747c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
1757c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
1767c478bd9Sstevel@tonic-gate { "kerberostgtpassing", oKerberosTgtPassing },
1777c478bd9Sstevel@tonic-gate #endif
1787c478bd9Sstevel@tonic-gate #ifdef AFS
1797c478bd9Sstevel@tonic-gate { "afstokenpassing", oAFSTokenPassing },
1807c478bd9Sstevel@tonic-gate #endif
1817c478bd9Sstevel@tonic-gate { "fallbacktorsh", oFallBackToRsh },
1827c478bd9Sstevel@tonic-gate { "usersh", oUseRsh },
1837c478bd9Sstevel@tonic-gate { "identityfile", oIdentityFile },
1847c478bd9Sstevel@tonic-gate { "identityfile2", oIdentityFile }, /* alias */
1857c478bd9Sstevel@tonic-gate { "hostname", oHostName },
1867c478bd9Sstevel@tonic-gate { "hostkeyalias", oHostKeyAlias },
1877c478bd9Sstevel@tonic-gate { "proxycommand", oProxyCommand },
1887c478bd9Sstevel@tonic-gate { "port", oPort },
1897c478bd9Sstevel@tonic-gate { "cipher", oCipher },
1907c478bd9Sstevel@tonic-gate { "ciphers", oCiphers },
1917c478bd9Sstevel@tonic-gate { "macs", oMacs },
1927c478bd9Sstevel@tonic-gate { "protocol", oProtocol },
1937c478bd9Sstevel@tonic-gate { "remoteforward", oRemoteForward },
1947c478bd9Sstevel@tonic-gate { "localforward", oLocalForward },
1957c478bd9Sstevel@tonic-gate { "user", oUser },
1967c478bd9Sstevel@tonic-gate { "host", oHost },
1977c478bd9Sstevel@tonic-gate { "escapechar", oEscapeChar },
1987c478bd9Sstevel@tonic-gate { "globalknownhostsfile", oGlobalKnownHostsFile },
1997c478bd9Sstevel@tonic-gate { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */
2007c478bd9Sstevel@tonic-gate { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
2017c478bd9Sstevel@tonic-gate { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
2027c478bd9Sstevel@tonic-gate { "connectionattempts", oConnectionAttempts },
2037c478bd9Sstevel@tonic-gate { "batchmode", oBatchMode },
2047c478bd9Sstevel@tonic-gate { "checkhostip", oCheckHostIP },
2057c478bd9Sstevel@tonic-gate { "stricthostkeychecking", oStrictHostKeyChecking },
2067c478bd9Sstevel@tonic-gate { "compression", oCompression },
2077c478bd9Sstevel@tonic-gate { "compressionlevel", oCompressionLevel },
208*33c41f2bSJoshua M. Clulow { "tcpkeepalive", oKeepAlives },
209*33c41f2bSJoshua M. Clulow { "keepalive", oKeepAlives }, /* obsolete */
2107c478bd9Sstevel@tonic-gate { "numberofpasswordprompts", oNumberOfPasswordPrompts },
2117c478bd9Sstevel@tonic-gate { "loglevel", oLogLevel },
2127c478bd9Sstevel@tonic-gate { "dynamicforward", oDynamicForward },
2137c478bd9Sstevel@tonic-gate { "preferredauthentications", oPreferredAuthentications },
2147c478bd9Sstevel@tonic-gate { "hostkeyalgorithms", oHostKeyAlgorithms },
2157c478bd9Sstevel@tonic-gate { "bindaddress", oBindAddress },
2167c478bd9Sstevel@tonic-gate { "smartcarddevice", oSmartcardDevice },
2177c478bd9Sstevel@tonic-gate { "clearallforwardings", oClearAllForwardings },
2187c478bd9Sstevel@tonic-gate { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
2199a8058b5Sjp161948 { "rekeylimit", oRekeyLimit },
22047b374ffSjp161948 { "connecttimeout", oConnectTimeout },
2211434cf01Sjp161948 { "serveraliveinterval", oServerAliveInterval },
2221434cf01Sjp161948 { "serveralivecountmax", oServerAliveCountMax },
223e5e9dedaSjp161948 { "disablebanner", oDisableBanner },
224442d23f4Sjp161948 { "hashknownhosts", oHashKnownHosts },
2255d7f3ec0Sjp161948 { "ignoreifunknown", oIgnoreIfUnknown },
226cd7d5fafSJan Pechanec { "useopensslengine", oUseOpenSSLEngine },
2277c478bd9Sstevel@tonic-gate { NULL, oBadOption }
2287c478bd9Sstevel@tonic-gate };
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * Adds a local TCP/IP port forward to options. Never returns if there is an
2327c478bd9Sstevel@tonic-gate * error.
2337c478bd9Sstevel@tonic-gate */
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate void
add_local_forward(Options * options,const Forward * newfwd)2369b03ea0fSjp161948 add_local_forward(Options *options, const Forward *newfwd)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate Forward *fwd;
2397c478bd9Sstevel@tonic-gate #ifndef NO_IPPORT_RESERVED_CONCEPT
2407c478bd9Sstevel@tonic-gate extern uid_t original_real_uid;
2419b03ea0fSjp161948 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
2427c478bd9Sstevel@tonic-gate fatal("Privileged ports can only be forwarded by root.");
2437c478bd9Sstevel@tonic-gate #endif
2447c478bd9Sstevel@tonic-gate if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
2457c478bd9Sstevel@tonic-gate fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
2467c478bd9Sstevel@tonic-gate fwd = &options->local_forwards[options->num_local_forwards++];
2479b03ea0fSjp161948
2489b03ea0fSjp161948 fwd->listen_host = (newfwd->listen_host == NULL) ?
2499b03ea0fSjp161948 NULL : xstrdup(newfwd->listen_host);
2509b03ea0fSjp161948 fwd->listen_port = newfwd->listen_port;
2519b03ea0fSjp161948 fwd->connect_host = xstrdup(newfwd->connect_host);
2529b03ea0fSjp161948 fwd->connect_port = newfwd->connect_port;
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /*
2567c478bd9Sstevel@tonic-gate * Adds a remote TCP/IP port forward to options. Never returns if there is
2577c478bd9Sstevel@tonic-gate * an error.
2587c478bd9Sstevel@tonic-gate */
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate void
add_remote_forward(Options * options,const Forward * newfwd)2619b03ea0fSjp161948 add_remote_forward(Options *options, const Forward *newfwd)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate Forward *fwd;
2647c478bd9Sstevel@tonic-gate if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
2657c478bd9Sstevel@tonic-gate fatal("Too many remote forwards (max %d).",
2667c478bd9Sstevel@tonic-gate SSH_MAX_FORWARDS_PER_DIRECTION);
2677c478bd9Sstevel@tonic-gate fwd = &options->remote_forwards[options->num_remote_forwards++];
2689b03ea0fSjp161948
2699b03ea0fSjp161948 fwd->listen_host = (newfwd->listen_host == NULL) ?
2709b03ea0fSjp161948 NULL : xstrdup(newfwd->listen_host);
2719b03ea0fSjp161948 fwd->listen_port = newfwd->listen_port;
2729b03ea0fSjp161948 fwd->connect_host = xstrdup(newfwd->connect_host);
2739b03ea0fSjp161948 fwd->connect_port = newfwd->connect_port;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate static void
clear_forwardings(Options * options)2777c478bd9Sstevel@tonic-gate clear_forwardings(Options *options)
2787c478bd9Sstevel@tonic-gate {
2797c478bd9Sstevel@tonic-gate int i;
2807c478bd9Sstevel@tonic-gate
2819b03ea0fSjp161948 for (i = 0; i < options->num_local_forwards; i++) {
2829b03ea0fSjp161948 if (options->local_forwards[i].listen_host != NULL)
2839b03ea0fSjp161948 xfree(options->local_forwards[i].listen_host);
2849b03ea0fSjp161948 xfree(options->local_forwards[i].connect_host);
2859b03ea0fSjp161948 }
2867c478bd9Sstevel@tonic-gate options->num_local_forwards = 0;
2879b03ea0fSjp161948 for (i = 0; i < options->num_remote_forwards; i++) {
2889b03ea0fSjp161948 if (options->remote_forwards[i].listen_host != NULL)
2899b03ea0fSjp161948 xfree(options->remote_forwards[i].listen_host);
2909b03ea0fSjp161948 xfree(options->remote_forwards[i].connect_host);
2919b03ea0fSjp161948 }
2927c478bd9Sstevel@tonic-gate options->num_remote_forwards = 0;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate * Returns the number of the token pointed to by cp or oBadOption.
2977c478bd9Sstevel@tonic-gate */
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate static OpCodes
parse_token(const char * cp,const char * filename,int linenum)3007c478bd9Sstevel@tonic-gate parse_token(const char *cp, const char *filename, int linenum)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate u_int i;
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate for (i = 0; keywords[i].name; i++)
3057c478bd9Sstevel@tonic-gate if (strcasecmp(cp, keywords[i].name) == 0)
3067c478bd9Sstevel@tonic-gate return keywords[i].opcode;
3077c478bd9Sstevel@tonic-gate
3085d7f3ec0Sjp161948 debug("%s: line %d: unknown configuration option: %s",
3097c478bd9Sstevel@tonic-gate filename, linenum, cp);
3107c478bd9Sstevel@tonic-gate return oBadOption;
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate * Processes a single option line as used in the configuration files. This
3157c478bd9Sstevel@tonic-gate * only sets those values that have not already been set.
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate int
process_config_line(Options * options,const char * host,char * line,const char * filename,int linenum,int * activep)3197c478bd9Sstevel@tonic-gate process_config_line(Options *options, const char *host,
3207c478bd9Sstevel@tonic-gate char *line, const char *filename, int linenum,
3217c478bd9Sstevel@tonic-gate int *activep)
3227c478bd9Sstevel@tonic-gate {
3239b03ea0fSjp161948 char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
3249a8058b5Sjp161948 int opcode, *intptr, value, scale, i;
3259a8058b5Sjp161948 long long orig, val64;
3265d7f3ec0Sjp161948 StoredOption *so;
3279b03ea0fSjp161948 Forward fwd;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate s = line;
3307c478bd9Sstevel@tonic-gate /* Get the keyword. (Each line is supposed to begin with a keyword). */
3317c478bd9Sstevel@tonic-gate keyword = strdelim(&s);
3327c478bd9Sstevel@tonic-gate /* Ignore leading whitespace. */
3337c478bd9Sstevel@tonic-gate if (*keyword == '\0')
3347c478bd9Sstevel@tonic-gate keyword = strdelim(&s);
3357c478bd9Sstevel@tonic-gate if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
3367c478bd9Sstevel@tonic-gate return 0;
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate opcode = parse_token(keyword, filename, linenum);
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate switch (opcode) {
3417c478bd9Sstevel@tonic-gate case oBadOption:
3425d7f3ec0Sjp161948 if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) {
3435d7f3ec0Sjp161948 error("we can't have more than %d unknown options:",
3445d7f3ec0Sjp161948 MAX_UNKNOWN_OPTIONS);
3455d7f3ec0Sjp161948 for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) {
3465d7f3ec0Sjp161948 so = &options->unknown_opts[i];
3475d7f3ec0Sjp161948 error("%s:%d:%s",
3485d7f3ec0Sjp161948 so->filename, so->linenum, so->keyword);
3495d7f3ec0Sjp161948 xfree(so->keyword);
3505d7f3ec0Sjp161948 xfree(so->filename);
3515d7f3ec0Sjp161948 }
3525d7f3ec0Sjp161948 fatal("too many unknown options found, can't continue");
3535d7f3ec0Sjp161948 }
3545d7f3ec0Sjp161948
3555d7f3ec0Sjp161948 /* unknown options will be processed later */
3565d7f3ec0Sjp161948 so = &options->unknown_opts[options->unknown_opts_num];
3575d7f3ec0Sjp161948 so->keyword = xstrdup(keyword);
3585d7f3ec0Sjp161948 so->filename = xstrdup(filename);
3595d7f3ec0Sjp161948 so->linenum = linenum;
3605d7f3ec0Sjp161948 options->unknown_opts_num++;
3615d7f3ec0Sjp161948 return (0);
3625d7f3ec0Sjp161948
3637c478bd9Sstevel@tonic-gate /* NOTREACHED */
36447b374ffSjp161948 case oConnectTimeout:
36547b374ffSjp161948 intptr = &options->connection_timeout;
36647b374ffSjp161948 parse_time:
36747b374ffSjp161948 arg = strdelim(&s);
36847b374ffSjp161948 if (!arg || *arg == '\0')
36947b374ffSjp161948 fatal("%s line %d: missing time value.",
37047b374ffSjp161948 filename, linenum);
37147b374ffSjp161948 if ((value = convtime(arg)) == -1)
37247b374ffSjp161948 fatal("%s line %d: invalid time value.",
37347b374ffSjp161948 filename, linenum);
374aa9b2b45Sjp161948 if (*activep && *intptr == -1)
37547b374ffSjp161948 *intptr = value;
37647b374ffSjp161948 break;
37747b374ffSjp161948
3787c478bd9Sstevel@tonic-gate case oForwardAgent:
3797c478bd9Sstevel@tonic-gate intptr = &options->forward_agent;
3807c478bd9Sstevel@tonic-gate parse_flag:
3817c478bd9Sstevel@tonic-gate arg = strdelim(&s);
3827c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
3837c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
3847c478bd9Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */
3857c478bd9Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
3867c478bd9Sstevel@tonic-gate value = 1;
3877c478bd9Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
3887c478bd9Sstevel@tonic-gate value = 0;
3897c478bd9Sstevel@tonic-gate else
3907c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
3917c478bd9Sstevel@tonic-gate if (*activep && *intptr == -1)
3927c478bd9Sstevel@tonic-gate *intptr = value;
3937c478bd9Sstevel@tonic-gate break;
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate case oForwardX11:
3967c478bd9Sstevel@tonic-gate intptr = &options->forward_x11;
3977c478bd9Sstevel@tonic-gate goto parse_flag;
3987c478bd9Sstevel@tonic-gate
399383a1232Sjp161948 case oForwardX11Trusted:
400383a1232Sjp161948 intptr = &options->forward_x11_trusted;
401383a1232Sjp161948 goto parse_flag;
402383a1232Sjp161948
4037c478bd9Sstevel@tonic-gate case oGatewayPorts:
4047c478bd9Sstevel@tonic-gate intptr = &options->gateway_ports;
4057c478bd9Sstevel@tonic-gate goto parse_flag;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate case oUsePrivilegedPort:
4087c478bd9Sstevel@tonic-gate intptr = &options->use_privileged_port;
4097c478bd9Sstevel@tonic-gate goto parse_flag;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate case oRhostsAuthentication:
4127c478bd9Sstevel@tonic-gate intptr = &options->rhosts_authentication;
4137c478bd9Sstevel@tonic-gate goto parse_flag;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate case oPasswordAuthentication:
4167c478bd9Sstevel@tonic-gate intptr = &options->password_authentication;
4177c478bd9Sstevel@tonic-gate goto parse_flag;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate case oKbdInteractiveAuthentication:
4207c478bd9Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication;
4217c478bd9Sstevel@tonic-gate goto parse_flag;
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate case oKbdInteractiveDevices:
4247c478bd9Sstevel@tonic-gate charptr = &options->kbd_interactive_devices;
4257c478bd9Sstevel@tonic-gate goto parse_string;
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate case oPubkeyAuthentication:
4287c478bd9Sstevel@tonic-gate intptr = &options->pubkey_authentication;
4297c478bd9Sstevel@tonic-gate goto parse_flag;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate case oRSAAuthentication:
4327c478bd9Sstevel@tonic-gate intptr = &options->rsa_authentication;
4337c478bd9Sstevel@tonic-gate goto parse_flag;
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate case oRhostsRSAAuthentication:
4367c478bd9Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication;
4377c478bd9Sstevel@tonic-gate goto parse_flag;
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate case oHostbasedAuthentication:
4407c478bd9Sstevel@tonic-gate intptr = &options->hostbased_authentication;
4417c478bd9Sstevel@tonic-gate goto parse_flag;
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate case oChallengeResponseAuthentication:
4447c478bd9Sstevel@tonic-gate intptr = &options->challenge_response_authentication;
4457c478bd9Sstevel@tonic-gate goto parse_flag;
4467c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
4477c478bd9Sstevel@tonic-gate case oKerberosAuthentication:
4487c478bd9Sstevel@tonic-gate intptr = &options->kerberos_authentication;
4497c478bd9Sstevel@tonic-gate goto parse_flag;
4507c478bd9Sstevel@tonic-gate #endif
4517c478bd9Sstevel@tonic-gate #ifdef GSSAPI
4527c478bd9Sstevel@tonic-gate case oGssKeyEx:
4537c478bd9Sstevel@tonic-gate intptr = &options->gss_keyex;
4547c478bd9Sstevel@tonic-gate goto parse_flag;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate case oGssAuthentication:
4577c478bd9Sstevel@tonic-gate intptr = &options->gss_authentication;
4587c478bd9Sstevel@tonic-gate goto parse_flag;
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate case oGssDelegateCreds:
4617c478bd9Sstevel@tonic-gate intptr = &options->gss_deleg_creds;
4627c478bd9Sstevel@tonic-gate goto parse_flag;
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate #ifdef GSI
4657c478bd9Sstevel@tonic-gate case oGssGlobusDelegateLimitedCreds:
4667c478bd9Sstevel@tonic-gate intptr = &options->gss_globus_deleg_limited_proxy;
4677c478bd9Sstevel@tonic-gate goto parse_flag;
4687c478bd9Sstevel@tonic-gate #endif /* GSI */
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
4737c478bd9Sstevel@tonic-gate case oKerberosTgtPassing:
4747c478bd9Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing;
4757c478bd9Sstevel@tonic-gate goto parse_flag;
4767c478bd9Sstevel@tonic-gate #endif
4777c478bd9Sstevel@tonic-gate #ifdef AFS
4787c478bd9Sstevel@tonic-gate case oAFSTokenPassing:
4797c478bd9Sstevel@tonic-gate intptr = &options->afs_token_passing;
4807c478bd9Sstevel@tonic-gate goto parse_flag;
4817c478bd9Sstevel@tonic-gate #endif
4827c478bd9Sstevel@tonic-gate case oFallBackToRsh:
4837c478bd9Sstevel@tonic-gate intptr = &options->fallback_to_rsh;
4847c478bd9Sstevel@tonic-gate goto parse_flag;
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate case oUseRsh:
4877c478bd9Sstevel@tonic-gate intptr = &options->use_rsh;
4887c478bd9Sstevel@tonic-gate goto parse_flag;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate case oBatchMode:
4917c478bd9Sstevel@tonic-gate intptr = &options->batch_mode;
4927c478bd9Sstevel@tonic-gate goto parse_flag;
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate case oCheckHostIP:
4957c478bd9Sstevel@tonic-gate intptr = &options->check_host_ip;
4967c478bd9Sstevel@tonic-gate goto parse_flag;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate case oStrictHostKeyChecking:
4997c478bd9Sstevel@tonic-gate intptr = &options->strict_host_key_checking;
5007c478bd9Sstevel@tonic-gate arg = strdelim(&s);
5017c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
5027c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no/ask argument.",
5037c478bd9Sstevel@tonic-gate filename, linenum);
5047c478bd9Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */
5057c478bd9Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
5067c478bd9Sstevel@tonic-gate value = 1;
5077c478bd9Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
5087c478bd9Sstevel@tonic-gate value = 0;
5097c478bd9Sstevel@tonic-gate else if (strcmp(arg, "ask") == 0)
5107c478bd9Sstevel@tonic-gate value = 2;
5117c478bd9Sstevel@tonic-gate else
5127c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
5137c478bd9Sstevel@tonic-gate if (*activep && *intptr == -1)
5147c478bd9Sstevel@tonic-gate *intptr = value;
5157c478bd9Sstevel@tonic-gate break;
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate case oCompression:
5187c478bd9Sstevel@tonic-gate intptr = &options->compression;
5197c478bd9Sstevel@tonic-gate goto parse_flag;
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate case oKeepAlives:
5227c478bd9Sstevel@tonic-gate intptr = &options->keepalives;
5237c478bd9Sstevel@tonic-gate goto parse_flag;
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate case oNoHostAuthenticationForLocalhost:
5267c478bd9Sstevel@tonic-gate intptr = &options->no_host_authentication_for_localhost;
5277c478bd9Sstevel@tonic-gate goto parse_flag;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate case oNumberOfPasswordPrompts:
5307c478bd9Sstevel@tonic-gate intptr = &options->number_of_password_prompts;
5317c478bd9Sstevel@tonic-gate goto parse_int;
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate case oCompressionLevel:
5347c478bd9Sstevel@tonic-gate intptr = &options->compression_level;
5357c478bd9Sstevel@tonic-gate goto parse_int;
5367c478bd9Sstevel@tonic-gate
5379a8058b5Sjp161948 case oRekeyLimit:
5389a8058b5Sjp161948 arg = strdelim(&s);
5399a8058b5Sjp161948 if (!arg || *arg == '\0')
5409a8058b5Sjp161948 fatal("%.200s line %d: Missing argument.", filename, linenum);
5419a8058b5Sjp161948 if (arg[0] < '0' || arg[0] > '9')
5429a8058b5Sjp161948 fatal("%.200s line %d: Bad number.", filename, linenum);
5439a8058b5Sjp161948 orig = val64 = strtoll(arg, &endofnumber, 10);
5449a8058b5Sjp161948 if (arg == endofnumber)
5459a8058b5Sjp161948 fatal("%.200s line %d: Bad number.", filename, linenum);
5469a8058b5Sjp161948 switch (toupper(*endofnumber)) {
5479a8058b5Sjp161948 case '\0':
5489a8058b5Sjp161948 scale = 1;
5499a8058b5Sjp161948 break;
5509a8058b5Sjp161948 case 'K':
5519a8058b5Sjp161948 scale = 1<<10;
5529a8058b5Sjp161948 break;
5539a8058b5Sjp161948 case 'M':
5549a8058b5Sjp161948 scale = 1<<20;
5559a8058b5Sjp161948 break;
5569a8058b5Sjp161948 case 'G':
5579a8058b5Sjp161948 scale = 1<<30;
5589a8058b5Sjp161948 break;
5599a8058b5Sjp161948 default:
5609a8058b5Sjp161948 fatal("%.200s line %d: Invalid RekeyLimit suffix",
5619a8058b5Sjp161948 filename, linenum);
5629a8058b5Sjp161948 }
5639a8058b5Sjp161948 val64 *= scale;
5649a8058b5Sjp161948 /* detect integer wrap and too-large limits */
5659a8058b5Sjp161948 if ((val64 / scale) != orig || val64 > UINT_MAX)
5669a8058b5Sjp161948 fatal("%.200s line %d: RekeyLimit too large",
5679a8058b5Sjp161948 filename, linenum);
5689a8058b5Sjp161948 if (val64 < 16)
5699a8058b5Sjp161948 fatal("%.200s line %d: RekeyLimit too small",
5709a8058b5Sjp161948 filename, linenum);
5719a8058b5Sjp161948 if (*activep && options->rekey_limit == -1)
5729a8058b5Sjp161948 options->rekey_limit = (u_int32_t)val64;
5739a8058b5Sjp161948 break;
5749a8058b5Sjp161948
5757c478bd9Sstevel@tonic-gate case oIdentityFile:
5767c478bd9Sstevel@tonic-gate arg = strdelim(&s);
5777c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
5787c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
5797c478bd9Sstevel@tonic-gate if (*activep) {
5807c478bd9Sstevel@tonic-gate intptr = &options->num_identity_files;
5817c478bd9Sstevel@tonic-gate if (*intptr >= SSH_MAX_IDENTITY_FILES)
5827c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Too many identity files specified (max %d).",
5837c478bd9Sstevel@tonic-gate filename, linenum, SSH_MAX_IDENTITY_FILES);
5847c478bd9Sstevel@tonic-gate charptr = &options->identity_files[*intptr];
5857c478bd9Sstevel@tonic-gate *charptr = xstrdup(arg);
5867c478bd9Sstevel@tonic-gate *intptr = *intptr + 1;
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate break;
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate case oXAuthLocation:
5917c478bd9Sstevel@tonic-gate charptr=&options->xauth_location;
5927c478bd9Sstevel@tonic-gate goto parse_string;
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate case oUser:
5957c478bd9Sstevel@tonic-gate charptr = &options->user;
5967c478bd9Sstevel@tonic-gate parse_string:
5977c478bd9Sstevel@tonic-gate arg = strdelim(&s);
5987c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
5997c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
6007c478bd9Sstevel@tonic-gate if (*activep && *charptr == NULL)
6017c478bd9Sstevel@tonic-gate *charptr = xstrdup(arg);
6027c478bd9Sstevel@tonic-gate break;
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate case oGlobalKnownHostsFile:
6057c478bd9Sstevel@tonic-gate charptr = &options->system_hostfile;
6067c478bd9Sstevel@tonic-gate goto parse_string;
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate case oUserKnownHostsFile:
6097c478bd9Sstevel@tonic-gate charptr = &options->user_hostfile;
6107c478bd9Sstevel@tonic-gate goto parse_string;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate case oGlobalKnownHostsFile2:
6137c478bd9Sstevel@tonic-gate charptr = &options->system_hostfile2;
6147c478bd9Sstevel@tonic-gate goto parse_string;
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate case oUserKnownHostsFile2:
6177c478bd9Sstevel@tonic-gate charptr = &options->user_hostfile2;
6187c478bd9Sstevel@tonic-gate goto parse_string;
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate case oHostName:
6217c478bd9Sstevel@tonic-gate charptr = &options->hostname;
6227c478bd9Sstevel@tonic-gate goto parse_string;
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate case oHostKeyAlias:
6257c478bd9Sstevel@tonic-gate charptr = &options->host_key_alias;
6267c478bd9Sstevel@tonic-gate goto parse_string;
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate case oPreferredAuthentications:
6297c478bd9Sstevel@tonic-gate charptr = &options->preferred_authentications;
6307c478bd9Sstevel@tonic-gate goto parse_string;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate case oBindAddress:
6337c478bd9Sstevel@tonic-gate charptr = &options->bind_address;
6347c478bd9Sstevel@tonic-gate goto parse_string;
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate case oSmartcardDevice:
6377c478bd9Sstevel@tonic-gate charptr = &options->smartcard_device;
6387c478bd9Sstevel@tonic-gate goto parse_string;
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate case oProxyCommand:
6417c478bd9Sstevel@tonic-gate charptr = &options->proxy_command;
6427c478bd9Sstevel@tonic-gate string = xstrdup("");
6437c478bd9Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
6447c478bd9Sstevel@tonic-gate string = xrealloc(string, strlen(string) + strlen(arg) + 2);
6457c478bd9Sstevel@tonic-gate strcat(string, " ");
6467c478bd9Sstevel@tonic-gate strcat(string, arg);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate if (*activep && *charptr == NULL)
6497c478bd9Sstevel@tonic-gate *charptr = string;
6507c478bd9Sstevel@tonic-gate else
6517c478bd9Sstevel@tonic-gate xfree(string);
6527c478bd9Sstevel@tonic-gate return 0;
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate case oPort:
6557c478bd9Sstevel@tonic-gate intptr = &options->port;
6567c478bd9Sstevel@tonic-gate parse_int:
6577c478bd9Sstevel@tonic-gate arg = strdelim(&s);
6587c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
6597c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
6607c478bd9Sstevel@tonic-gate if (arg[0] < '0' || arg[0] > '9')
6617c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum);
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate /* Octal, decimal, or hex format? */
6647c478bd9Sstevel@tonic-gate value = strtol(arg, &endofnumber, 0);
6657c478bd9Sstevel@tonic-gate if (arg == endofnumber)
6667c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum);
6677c478bd9Sstevel@tonic-gate if (*activep && *intptr == -1)
6687c478bd9Sstevel@tonic-gate *intptr = value;
6697c478bd9Sstevel@tonic-gate break;
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate case oConnectionAttempts:
6727c478bd9Sstevel@tonic-gate intptr = &options->connection_attempts;
6737c478bd9Sstevel@tonic-gate goto parse_int;
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate case oCipher:
6767c478bd9Sstevel@tonic-gate intptr = &options->cipher;
6777c478bd9Sstevel@tonic-gate arg = strdelim(&s);
6787c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
6797c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
6807c478bd9Sstevel@tonic-gate value = cipher_number(arg);
6817c478bd9Sstevel@tonic-gate if (value == -1)
6827c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad cipher '%s'.",
6837c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
6847c478bd9Sstevel@tonic-gate if (*activep && *intptr == -1)
6857c478bd9Sstevel@tonic-gate *intptr = value;
6867c478bd9Sstevel@tonic-gate break;
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate case oCiphers:
6897c478bd9Sstevel@tonic-gate arg = strdelim(&s);
6907c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
6917c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
6927c478bd9Sstevel@tonic-gate if (!ciphers_valid(arg))
6937c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
6947c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
6957c478bd9Sstevel@tonic-gate if (*activep && options->ciphers == NULL)
6967c478bd9Sstevel@tonic-gate options->ciphers = xstrdup(arg);
6977c478bd9Sstevel@tonic-gate break;
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate case oMacs:
7007c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7017c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
7027c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
7037c478bd9Sstevel@tonic-gate if (!mac_valid(arg))
7047c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
7057c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
7067c478bd9Sstevel@tonic-gate if (*activep && options->macs == NULL)
7077c478bd9Sstevel@tonic-gate options->macs = xstrdup(arg);
7087c478bd9Sstevel@tonic-gate break;
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate case oHostKeyAlgorithms:
7117c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7127c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
7137c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
7147c478bd9Sstevel@tonic-gate if (!key_names_valid2(arg))
7157c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
7167c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
7177c478bd9Sstevel@tonic-gate if (*activep && options->hostkeyalgorithms == NULL)
7187c478bd9Sstevel@tonic-gate options->hostkeyalgorithms = xstrdup(arg);
7197c478bd9Sstevel@tonic-gate break;
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate case oProtocol:
7227c478bd9Sstevel@tonic-gate intptr = &options->protocol;
7237c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7247c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
7257c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
7267c478bd9Sstevel@tonic-gate value = proto_spec(arg);
7277c478bd9Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN)
7287c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol spec '%s'.",
7297c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
7307c478bd9Sstevel@tonic-gate if (*activep && *intptr == SSH_PROTO_UNKNOWN)
7317c478bd9Sstevel@tonic-gate *intptr = value;
7327c478bd9Sstevel@tonic-gate break;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate case oLogLevel:
7357c478bd9Sstevel@tonic-gate intptr = (int *) &options->log_level;
7367c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7377c478bd9Sstevel@tonic-gate value = log_level_number(arg);
7387c478bd9Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET)
7397c478bd9Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'",
7407c478bd9Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>");
7417c478bd9Sstevel@tonic-gate if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
7427c478bd9Sstevel@tonic-gate *intptr = (LogLevel) value;
7437c478bd9Sstevel@tonic-gate break;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate case oLocalForward:
7467c478bd9Sstevel@tonic-gate case oRemoteForward:
7477c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7489b03ea0fSjp161948 if (arg == NULL || *arg == '\0')
7497c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.",
7507c478bd9Sstevel@tonic-gate filename, linenum);
7519b03ea0fSjp161948 arg2 = strdelim(&s);
7529b03ea0fSjp161948 if (arg2 == NULL || *arg2 == '\0')
7539b03ea0fSjp161948 fatal("%.200s line %d: Missing target argument.",
7547c478bd9Sstevel@tonic-gate filename, linenum);
7559b03ea0fSjp161948
7569b03ea0fSjp161948 /* construct a string for parse_forward */
7579b03ea0fSjp161948 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
7589b03ea0fSjp161948
7599b03ea0fSjp161948 if (parse_forward(1, &fwd, fwdarg) == 0)
7607c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding specification.",
7617c478bd9Sstevel@tonic-gate filename, linenum);
7629b03ea0fSjp161948
7637c478bd9Sstevel@tonic-gate if (*activep) {
7647c478bd9Sstevel@tonic-gate if (opcode == oLocalForward)
7659b03ea0fSjp161948 add_local_forward(options, &fwd);
7667c478bd9Sstevel@tonic-gate else if (opcode == oRemoteForward)
7679b03ea0fSjp161948 add_remote_forward(options, &fwd);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate case oDynamicForward:
7727c478bd9Sstevel@tonic-gate arg = strdelim(&s);
7737c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
7747c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.",
7757c478bd9Sstevel@tonic-gate filename, linenum);
7769b03ea0fSjp161948
7779b03ea0fSjp161948 if (parse_forward(0, &fwd, arg) == 0) {
7789b03ea0fSjp161948 fatal("%.200s line %d: Bad dynamic forwarding specification.",
7797c478bd9Sstevel@tonic-gate filename, linenum);
7809b03ea0fSjp161948 }
7819b03ea0fSjp161948
7829b03ea0fSjp161948 if (*activep) {
7839b03ea0fSjp161948 fwd.connect_host = "socks";
7849b03ea0fSjp161948 add_local_forward(options, &fwd);
7859b03ea0fSjp161948 }
7867c478bd9Sstevel@tonic-gate break;
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate case oClearAllForwardings:
7897c478bd9Sstevel@tonic-gate intptr = &options->clear_forwardings;
7907c478bd9Sstevel@tonic-gate goto parse_flag;
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate case oHost:
7937c478bd9Sstevel@tonic-gate *activep = 0;
7947c478bd9Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0')
7957c478bd9Sstevel@tonic-gate if (match_pattern(host, arg)) {
7967c478bd9Sstevel@tonic-gate debug("Applying options for %.100s", arg);
7977c478bd9Sstevel@tonic-gate *activep = 1;
7987c478bd9Sstevel@tonic-gate break;
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate /* Avoid garbage check below, as strdelim is done. */
8017c478bd9Sstevel@tonic-gate return 0;
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate case oEscapeChar:
8047c478bd9Sstevel@tonic-gate intptr = &options->escape_char;
8057c478bd9Sstevel@tonic-gate arg = strdelim(&s);
8067c478bd9Sstevel@tonic-gate if (!arg || *arg == '\0')
8077c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum);
8087c478bd9Sstevel@tonic-gate if (arg[0] == '^' && arg[2] == 0 &&
8097c478bd9Sstevel@tonic-gate (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
8107c478bd9Sstevel@tonic-gate value = (u_char) arg[1] & 31;
8117c478bd9Sstevel@tonic-gate else if (strlen(arg) == 1)
8127c478bd9Sstevel@tonic-gate value = (u_char) arg[0];
8137c478bd9Sstevel@tonic-gate else if (strcmp(arg, "none") == 0)
8147c478bd9Sstevel@tonic-gate value = SSH_ESCAPECHAR_NONE;
8157c478bd9Sstevel@tonic-gate else {
8167c478bd9Sstevel@tonic-gate fatal("%.200s line %d: Bad escape character.",
8177c478bd9Sstevel@tonic-gate filename, linenum);
8187c478bd9Sstevel@tonic-gate /* NOTREACHED */
8197c478bd9Sstevel@tonic-gate value = 0; /* Avoid compiler warning. */
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate if (*activep && *intptr == -1)
8227c478bd9Sstevel@tonic-gate *intptr = value;
8237c478bd9Sstevel@tonic-gate break;
8247c478bd9Sstevel@tonic-gate
8251434cf01Sjp161948 case oServerAliveInterval:
8261434cf01Sjp161948 intptr = &options->server_alive_interval;
8271434cf01Sjp161948 goto parse_time;
8281434cf01Sjp161948
8291434cf01Sjp161948 case oServerAliveCountMax:
8301434cf01Sjp161948 intptr = &options->server_alive_count_max;
8311434cf01Sjp161948 goto parse_int;
8321434cf01Sjp161948
833442d23f4Sjp161948 case oHashKnownHosts:
834442d23f4Sjp161948 intptr = &options->hash_known_hosts;
835442d23f4Sjp161948 goto parse_flag;
836442d23f4Sjp161948
837e5e9dedaSjp161948 case oDisableBanner:
838e5e9dedaSjp161948 arg = strdelim(&s);
839e5e9dedaSjp161948 if (get_yes_no_flag(&options->disable_banner, arg, filename,
840e5e9dedaSjp161948 linenum, *activep) == 1)
841e5e9dedaSjp161948 break;
842e5e9dedaSjp161948
843e5e9dedaSjp161948 if (strcmp(arg, "in-exec-mode") == 0)
844e5e9dedaSjp161948 options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE;
845e5e9dedaSjp161948 else
846e5e9dedaSjp161948 fatal("%.200s line %d: Bad yes/no/in-exec-mode "
847e5e9dedaSjp161948 "argument.", filename, linenum);
848e5e9dedaSjp161948 break;
849e5e9dedaSjp161948
8505d7f3ec0Sjp161948 case oIgnoreIfUnknown:
8515d7f3ec0Sjp161948 charptr = &options->ignore_if_unknown;
8525d7f3ec0Sjp161948 goto parse_string;
8535d7f3ec0Sjp161948
854cd7d5fafSJan Pechanec case oUseOpenSSLEngine:
855cd7d5fafSJan Pechanec intptr = &options->use_openssl_engine;
856cd7d5fafSJan Pechanec goto parse_flag;
857cd7d5fafSJan Pechanec
8587c478bd9Sstevel@tonic-gate case oDeprecated:
8597c478bd9Sstevel@tonic-gate debug("%s line %d: Deprecated option \"%s\"",
8607c478bd9Sstevel@tonic-gate filename, linenum, keyword);
8617c478bd9Sstevel@tonic-gate return 0;
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate default:
8647c478bd9Sstevel@tonic-gate fatal("process_config_line: Unimplemented opcode %d", opcode);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate /* Check that there is no garbage at end of line. */
8687c478bd9Sstevel@tonic-gate if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
8697c478bd9Sstevel@tonic-gate fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
8707c478bd9Sstevel@tonic-gate filename, linenum, arg);
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate return 0;
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate /*
8777c478bd9Sstevel@tonic-gate * Reads the config file and modifies the options accordingly. Options
8787c478bd9Sstevel@tonic-gate * should already be initialized before this call. This never returns if
8797c478bd9Sstevel@tonic-gate * there is an error. If the file does not exist, this returns 0.
8807c478bd9Sstevel@tonic-gate */
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate int
read_config_file(const char * filename,const char * host,Options * options)8837c478bd9Sstevel@tonic-gate read_config_file(const char *filename, const char *host, Options *options)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate FILE *f;
8867c478bd9Sstevel@tonic-gate char line[1024];
8877c478bd9Sstevel@tonic-gate int active, linenum;
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate /* Open the file. */
8907c478bd9Sstevel@tonic-gate f = fopen(filename, "r");
8917c478bd9Sstevel@tonic-gate if (!f)
8927c478bd9Sstevel@tonic-gate return 0;
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate debug("Reading configuration data %.200s", filename);
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate /*
8977c478bd9Sstevel@tonic-gate * Mark that we are now processing the options. This flag is turned
8987c478bd9Sstevel@tonic-gate * on/off by Host specifications.
8997c478bd9Sstevel@tonic-gate */
9007c478bd9Sstevel@tonic-gate active = 1;
9017c478bd9Sstevel@tonic-gate linenum = 0;
9027c478bd9Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) {
9037c478bd9Sstevel@tonic-gate /* Update line number counter. */
9047c478bd9Sstevel@tonic-gate linenum++;
9055d7f3ec0Sjp161948 process_config_line(options, host, line, filename, linenum, &active);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate fclose(f);
9087c478bd9Sstevel@tonic-gate return 1;
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate /*
9127c478bd9Sstevel@tonic-gate * Initializes options to special values that indicate that they have not yet
9137c478bd9Sstevel@tonic-gate * been set. Read_config_file will only set options with this value. Options
9147c478bd9Sstevel@tonic-gate * are processed in the following order: command line, user config file,
9157c478bd9Sstevel@tonic-gate * system config file. Last, fill_default_options is called.
9167c478bd9Sstevel@tonic-gate */
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate void
initialize_options(Options * options)9197c478bd9Sstevel@tonic-gate initialize_options(Options * options)
9207c478bd9Sstevel@tonic-gate {
9217c478bd9Sstevel@tonic-gate memset(options, 'X', sizeof(*options));
9227c478bd9Sstevel@tonic-gate options->forward_agent = -1;
9237c478bd9Sstevel@tonic-gate options->forward_x11 = -1;
924383a1232Sjp161948 options->forward_x11_trusted = -1;
9257c478bd9Sstevel@tonic-gate options->xauth_location = NULL;
9267c478bd9Sstevel@tonic-gate options->gateway_ports = -1;
9277c478bd9Sstevel@tonic-gate options->use_privileged_port = -1;
9287c478bd9Sstevel@tonic-gate options->rhosts_authentication = -1;
9297c478bd9Sstevel@tonic-gate options->rsa_authentication = -1;
9307c478bd9Sstevel@tonic-gate options->pubkey_authentication = -1;
9317c478bd9Sstevel@tonic-gate options->challenge_response_authentication = -1;
9327c478bd9Sstevel@tonic-gate #ifdef GSSAPI
9337c478bd9Sstevel@tonic-gate options->gss_keyex = -1;
9347c478bd9Sstevel@tonic-gate options->gss_authentication = -1;
9357c478bd9Sstevel@tonic-gate options->gss_deleg_creds = -1;
9367c478bd9Sstevel@tonic-gate #ifdef GSI
9377c478bd9Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = -1;
9387c478bd9Sstevel@tonic-gate #endif /* GSI */
9397c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
9427c478bd9Sstevel@tonic-gate options->kerberos_authentication = -1;
9437c478bd9Sstevel@tonic-gate #endif
9447c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
9457c478bd9Sstevel@tonic-gate options->kerberos_tgt_passing = -1;
9467c478bd9Sstevel@tonic-gate #endif
9477c478bd9Sstevel@tonic-gate #ifdef AFS
9487c478bd9Sstevel@tonic-gate options->afs_token_passing = -1;
9497c478bd9Sstevel@tonic-gate #endif
9507c478bd9Sstevel@tonic-gate options->password_authentication = -1;
9517c478bd9Sstevel@tonic-gate options->kbd_interactive_authentication = -1;
9527c478bd9Sstevel@tonic-gate options->kbd_interactive_devices = NULL;
9537c478bd9Sstevel@tonic-gate options->rhosts_rsa_authentication = -1;
9547c478bd9Sstevel@tonic-gate options->hostbased_authentication = -1;
9557c478bd9Sstevel@tonic-gate options->batch_mode = -1;
9567c478bd9Sstevel@tonic-gate options->check_host_ip = -1;
9577c478bd9Sstevel@tonic-gate options->strict_host_key_checking = -1;
9587c478bd9Sstevel@tonic-gate options->compression = -1;
9597c478bd9Sstevel@tonic-gate options->keepalives = -1;
9607c478bd9Sstevel@tonic-gate options->compression_level = -1;
9617c478bd9Sstevel@tonic-gate options->port = -1;
9627c478bd9Sstevel@tonic-gate options->connection_attempts = -1;
96347b374ffSjp161948 options->connection_timeout = -1;
9647c478bd9Sstevel@tonic-gate options->number_of_password_prompts = -1;
9657c478bd9Sstevel@tonic-gate options->cipher = -1;
9667c478bd9Sstevel@tonic-gate options->ciphers = NULL;
9677c478bd9Sstevel@tonic-gate options->macs = NULL;
9687c478bd9Sstevel@tonic-gate options->hostkeyalgorithms = NULL;
9697c478bd9Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN;
9707c478bd9Sstevel@tonic-gate options->num_identity_files = 0;
9717c478bd9Sstevel@tonic-gate options->hostname = NULL;
9727c478bd9Sstevel@tonic-gate options->host_key_alias = NULL;
9737c478bd9Sstevel@tonic-gate options->proxy_command = NULL;
9747c478bd9Sstevel@tonic-gate options->user = NULL;
9757c478bd9Sstevel@tonic-gate options->escape_char = -1;
9767c478bd9Sstevel@tonic-gate options->system_hostfile = NULL;
9777c478bd9Sstevel@tonic-gate options->user_hostfile = NULL;
9787c478bd9Sstevel@tonic-gate options->system_hostfile2 = NULL;
9797c478bd9Sstevel@tonic-gate options->user_hostfile2 = NULL;
9807c478bd9Sstevel@tonic-gate options->num_local_forwards = 0;
9817c478bd9Sstevel@tonic-gate options->num_remote_forwards = 0;
9827c478bd9Sstevel@tonic-gate options->clear_forwardings = -1;
9837c478bd9Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET;
9847c478bd9Sstevel@tonic-gate options->preferred_authentications = NULL;
9857c478bd9Sstevel@tonic-gate options->bind_address = NULL;
9867c478bd9Sstevel@tonic-gate options->smartcard_device = NULL;
9877c478bd9Sstevel@tonic-gate options->no_host_authentication_for_localhost = -1;
9889a8058b5Sjp161948 options->rekey_limit = -1;
9897c478bd9Sstevel@tonic-gate options->fallback_to_rsh = -1;
9907c478bd9Sstevel@tonic-gate options->use_rsh = -1;
9911434cf01Sjp161948 options->server_alive_interval = -1;
9921434cf01Sjp161948 options->server_alive_count_max = -1;
993442d23f4Sjp161948 options->hash_known_hosts = -1;
9945d7f3ec0Sjp161948 options->ignore_if_unknown = NULL;
9955d7f3ec0Sjp161948 options->unknown_opts_num = 0;
996e5e9dedaSjp161948 options->disable_banner = -1;
997cd7d5fafSJan Pechanec options->use_openssl_engine = -1;
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate
10007c478bd9Sstevel@tonic-gate /*
10017c478bd9Sstevel@tonic-gate * Called after processing other sources of option data, this fills those
10027c478bd9Sstevel@tonic-gate * options for which no value has been specified with their default values.
10037c478bd9Sstevel@tonic-gate */
10047c478bd9Sstevel@tonic-gate
10057c478bd9Sstevel@tonic-gate void
fill_default_options(Options * options)10067c478bd9Sstevel@tonic-gate fill_default_options(Options * options)
10077c478bd9Sstevel@tonic-gate {
10087c478bd9Sstevel@tonic-gate int len;
10097c478bd9Sstevel@tonic-gate
10107c478bd9Sstevel@tonic-gate if (options->forward_agent == -1)
10117c478bd9Sstevel@tonic-gate options->forward_agent = 0;
10127c478bd9Sstevel@tonic-gate if (options->forward_x11 == -1)
10137c478bd9Sstevel@tonic-gate options->forward_x11 = 0;
1014383a1232Sjp161948 /*
1015383a1232Sjp161948 * Unlike OpenSSH, we keep backward compatibility for '-X' option
1016383a1232Sjp161948 * which means that X11 forwarding is trusted by default.
1017383a1232Sjp161948 */
1018383a1232Sjp161948 if (options->forward_x11_trusted == -1)
1019383a1232Sjp161948 options->forward_x11_trusted = 1;
10207c478bd9Sstevel@tonic-gate if (options->xauth_location == NULL)
10217c478bd9Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH;
10227c478bd9Sstevel@tonic-gate if (options->gateway_ports == -1)
10237c478bd9Sstevel@tonic-gate options->gateway_ports = 0;
10247c478bd9Sstevel@tonic-gate if (options->use_privileged_port == -1)
10257c478bd9Sstevel@tonic-gate options->use_privileged_port = 0;
10267c478bd9Sstevel@tonic-gate if (options->rhosts_authentication == -1)
10277c478bd9Sstevel@tonic-gate options->rhosts_authentication = 0;
10287c478bd9Sstevel@tonic-gate if (options->rsa_authentication == -1)
10297c478bd9Sstevel@tonic-gate options->rsa_authentication = 1;
10307c478bd9Sstevel@tonic-gate if (options->pubkey_authentication == -1)
10317c478bd9Sstevel@tonic-gate options->pubkey_authentication = 1;
10327c478bd9Sstevel@tonic-gate if (options->challenge_response_authentication == -1)
10337c478bd9Sstevel@tonic-gate options->challenge_response_authentication = 1;
10347c478bd9Sstevel@tonic-gate #ifdef GSSAPI
10357c478bd9Sstevel@tonic-gate if (options->gss_keyex == -1)
10367c478bd9Sstevel@tonic-gate options->gss_keyex = 1;
10377c478bd9Sstevel@tonic-gate if (options->gss_authentication == -1)
10387c478bd9Sstevel@tonic-gate options->gss_authentication = 1;
10397c478bd9Sstevel@tonic-gate if (options->gss_deleg_creds == -1)
10407c478bd9Sstevel@tonic-gate options->gss_deleg_creds = 0;
10417c478bd9Sstevel@tonic-gate #ifdef GSI
10427c478bd9Sstevel@tonic-gate if (options->gss_globus_deleg_limited_proxy == -1)
10437c478bd9Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = 0;
10447c478bd9Sstevel@tonic-gate #endif /* GSI */
10457c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
10467c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
10477c478bd9Sstevel@tonic-gate if (options->kerberos_authentication == -1)
10487c478bd9Sstevel@tonic-gate options->kerberos_authentication = 1;
10497c478bd9Sstevel@tonic-gate #endif
10507c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
10517c478bd9Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1)
10527c478bd9Sstevel@tonic-gate options->kerberos_tgt_passing = 1;
10537c478bd9Sstevel@tonic-gate #endif
10547c478bd9Sstevel@tonic-gate #ifdef AFS
10557c478bd9Sstevel@tonic-gate if (options->afs_token_passing == -1)
10567c478bd9Sstevel@tonic-gate options->afs_token_passing = 1;
10577c478bd9Sstevel@tonic-gate #endif
10587c478bd9Sstevel@tonic-gate if (options->password_authentication == -1)
10597c478bd9Sstevel@tonic-gate options->password_authentication = 1;
10607c478bd9Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1)
10617c478bd9Sstevel@tonic-gate options->kbd_interactive_authentication = 1;
10627c478bd9Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1)
10637c478bd9Sstevel@tonic-gate options->rhosts_rsa_authentication = 0;
10647c478bd9Sstevel@tonic-gate if (options->hostbased_authentication == -1)
10657c478bd9Sstevel@tonic-gate options->hostbased_authentication = 0;
10667c478bd9Sstevel@tonic-gate if (options->batch_mode == -1)
10677c478bd9Sstevel@tonic-gate options->batch_mode = 0;
10687c478bd9Sstevel@tonic-gate if (options->check_host_ip == -1)
10697c478bd9Sstevel@tonic-gate options->check_host_ip = 1;
10707c478bd9Sstevel@tonic-gate if (options->strict_host_key_checking == -1)
10717c478bd9Sstevel@tonic-gate options->strict_host_key_checking = 2; /* 2 is default */
10727c478bd9Sstevel@tonic-gate if (options->compression == -1)
10737c478bd9Sstevel@tonic-gate options->compression = 0;
10747c478bd9Sstevel@tonic-gate if (options->keepalives == -1)
10757c478bd9Sstevel@tonic-gate options->keepalives = 1;
10767c478bd9Sstevel@tonic-gate if (options->compression_level == -1)
10777c478bd9Sstevel@tonic-gate options->compression_level = 6;
10787c478bd9Sstevel@tonic-gate if (options->port == -1)
10797c478bd9Sstevel@tonic-gate options->port = 0; /* Filled in ssh_connect. */
10807c478bd9Sstevel@tonic-gate if (options->connection_attempts == -1)
10817c478bd9Sstevel@tonic-gate options->connection_attempts = 1;
10827c478bd9Sstevel@tonic-gate if (options->number_of_password_prompts == -1)
10837c478bd9Sstevel@tonic-gate options->number_of_password_prompts = 3;
10847c478bd9Sstevel@tonic-gate /* Selected in ssh_login(). */
10857c478bd9Sstevel@tonic-gate if (options->cipher == -1)
10867c478bd9Sstevel@tonic-gate options->cipher = SSH_CIPHER_NOT_SET;
10877c478bd9Sstevel@tonic-gate /* options->ciphers, default set in myproposals.h */
10887c478bd9Sstevel@tonic-gate /* options->macs, default set in myproposals.h */
10897c478bd9Sstevel@tonic-gate /* options->hostkeyalgorithms, default set in myproposals.h */
10907c478bd9Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN)
10917c478bd9Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2;
10927c478bd9Sstevel@tonic-gate if (options->num_identity_files == 0) {
10937c478bd9Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) {
10947c478bd9Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
10957c478bd9Sstevel@tonic-gate options->identity_files[options->num_identity_files] =
10967c478bd9Sstevel@tonic-gate xmalloc(len);
10977c478bd9Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++],
10987c478bd9Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) {
11017c478bd9Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
11027c478bd9Sstevel@tonic-gate options->identity_files[options->num_identity_files] =
11037c478bd9Sstevel@tonic-gate xmalloc(len);
11047c478bd9Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++],
11057c478bd9Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
11087c478bd9Sstevel@tonic-gate options->identity_files[options->num_identity_files] =
11097c478bd9Sstevel@tonic-gate xmalloc(len);
11107c478bd9Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++],
11117c478bd9Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate if (options->escape_char == -1)
11157c478bd9Sstevel@tonic-gate options->escape_char = '~';
11167c478bd9Sstevel@tonic-gate if (options->system_hostfile == NULL)
11177c478bd9Sstevel@tonic-gate options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
11187c478bd9Sstevel@tonic-gate if (options->user_hostfile == NULL)
11197c478bd9Sstevel@tonic-gate options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
11207c478bd9Sstevel@tonic-gate if (options->system_hostfile2 == NULL)
11217c478bd9Sstevel@tonic-gate options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
11227c478bd9Sstevel@tonic-gate if (options->user_hostfile2 == NULL)
11237c478bd9Sstevel@tonic-gate options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
11247c478bd9Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET)
11257c478bd9Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO;
11267c478bd9Sstevel@tonic-gate if (options->clear_forwardings == 1)
11277c478bd9Sstevel@tonic-gate clear_forwardings(options);
11287c478bd9Sstevel@tonic-gate if (options->no_host_authentication_for_localhost == -1)
11297c478bd9Sstevel@tonic-gate options->no_host_authentication_for_localhost = 0;
11309a8058b5Sjp161948 if (options->rekey_limit == -1)
11319a8058b5Sjp161948 options->rekey_limit = 0;
11327c478bd9Sstevel@tonic-gate if (options->fallback_to_rsh == -1)
11337c478bd9Sstevel@tonic-gate options->fallback_to_rsh = 0;
11347c478bd9Sstevel@tonic-gate if (options->use_rsh == -1)
11357c478bd9Sstevel@tonic-gate options->use_rsh = 0;
11361434cf01Sjp161948 if (options->server_alive_interval == -1)
11371434cf01Sjp161948 options->server_alive_interval = 0;
11381434cf01Sjp161948 if (options->server_alive_count_max == -1)
11391434cf01Sjp161948 options->server_alive_count_max = 3;
1140442d23f4Sjp161948 if (options->hash_known_hosts == -1)
1141442d23f4Sjp161948 options->hash_known_hosts = 0;
1142e5e9dedaSjp161948 if (options->disable_banner == -1)
1143e5e9dedaSjp161948 options->disable_banner = 0;
1144cd7d5fafSJan Pechanec if (options->use_openssl_engine == -1)
1145cd7d5fafSJan Pechanec options->use_openssl_engine = 1;
11467c478bd9Sstevel@tonic-gate /* options->proxy_command should not be set by default */
11477c478bd9Sstevel@tonic-gate /* options->user will be set in the main program if appropriate */
11487c478bd9Sstevel@tonic-gate /* options->hostname will be set in the main program if appropriate */
11497c478bd9Sstevel@tonic-gate /* options->host_key_alias should not be set by default */
11507c478bd9Sstevel@tonic-gate /* options->preferred_authentications will be set in ssh */
11515d7f3ec0Sjp161948 /* options->ignore_if_unknown should not be set by default */
11525d7f3ec0Sjp161948 }
11535d7f3ec0Sjp161948
11545d7f3ec0Sjp161948 /*
11559b03ea0fSjp161948 * Parses a string containing a port forwarding specification of one of the
11569b03ea0fSjp161948 * two forms, short or long:
11579b03ea0fSjp161948 *
11589b03ea0fSjp161948 * [listenhost:]listenport
11599b03ea0fSjp161948 * [listenhost:]listenport:connecthost:connectport
11609b03ea0fSjp161948 *
11619b03ea0fSjp161948 * short forwarding specification is used for dynamic port forwarding and for
11629b03ea0fSjp161948 * port forwarding cancelation in process_cmdline(). The function returns number
11639b03ea0fSjp161948 * of arguments parsed or zero on any error.
11649b03ea0fSjp161948 */
11659b03ea0fSjp161948 int
parse_forward(int long_form,Forward * fwd,const char * fwdspec)11669b03ea0fSjp161948 parse_forward(int long_form, Forward *fwd, const char *fwdspec)
11679b03ea0fSjp161948 {
11689b03ea0fSjp161948 int i;
11699b03ea0fSjp161948 char *p, *cp, *fwdarg[5];
11709b03ea0fSjp161948
11719b03ea0fSjp161948 memset(fwd, '\0', sizeof(*fwd));
11729b03ea0fSjp161948
11739b03ea0fSjp161948 cp = p = xstrdup(fwdspec);
11749b03ea0fSjp161948
11759b03ea0fSjp161948 /* skip leading spaces */
11769b03ea0fSjp161948 while (isspace(*cp))
11779b03ea0fSjp161948 cp++;
11789b03ea0fSjp161948
11799b03ea0fSjp161948 for (i = 0; i < 5; ++i)
11809b03ea0fSjp161948 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
11819b03ea0fSjp161948 break;
11829b03ea0fSjp161948
11839b03ea0fSjp161948 if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5))
11849b03ea0fSjp161948 goto fail_free;
11859b03ea0fSjp161948
11869b03ea0fSjp161948 switch (i) {
11879b03ea0fSjp161948 case 0:
11889b03ea0fSjp161948 goto fail_free;
11899b03ea0fSjp161948
11909b03ea0fSjp161948 case 1:
11919b03ea0fSjp161948 fwd->listen_host = NULL;
11929b03ea0fSjp161948 fwd->listen_port = a2port(fwdarg[0]);
11939b03ea0fSjp161948 break;
11949b03ea0fSjp161948
11959b03ea0fSjp161948 case 2:
11969b03ea0fSjp161948 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
11979b03ea0fSjp161948 fwd->listen_port = a2port(fwdarg[1]);
11989b03ea0fSjp161948 break;
11999b03ea0fSjp161948
12009b03ea0fSjp161948 case 3:
12019b03ea0fSjp161948 fwd->listen_host = NULL;
12029b03ea0fSjp161948 fwd->listen_port = a2port(fwdarg[0]);
12039b03ea0fSjp161948 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
12049b03ea0fSjp161948 fwd->connect_port = a2port(fwdarg[2]);
12059b03ea0fSjp161948 break;
12069b03ea0fSjp161948
12079b03ea0fSjp161948 case 4:
12089b03ea0fSjp161948 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
12099b03ea0fSjp161948 fwd->listen_port = a2port(fwdarg[1]);
12109b03ea0fSjp161948 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
12119b03ea0fSjp161948 fwd->connect_port = a2port(fwdarg[3]);
12129b03ea0fSjp161948 break;
12139b03ea0fSjp161948 }
12149b03ea0fSjp161948
12159b03ea0fSjp161948 if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2))
12169b03ea0fSjp161948 goto fail_free;
12179b03ea0fSjp161948
1218b9aa66a7SJan Pechanec xfree(p);
12199b03ea0fSjp161948 return (i);
12209b03ea0fSjp161948
12219b03ea0fSjp161948 fail_free:
12229b03ea0fSjp161948 if (p != NULL)
12239b03ea0fSjp161948 xfree(p);
12249b03ea0fSjp161948 if (fwd->connect_host != NULL)
12259b03ea0fSjp161948 xfree(fwd->connect_host);
12269b03ea0fSjp161948 if (fwd->listen_host != NULL)
12279b03ea0fSjp161948 xfree(fwd->listen_host);
12289b03ea0fSjp161948 return (0);
12299b03ea0fSjp161948 }
12309b03ea0fSjp161948
12319b03ea0fSjp161948 /*
12325d7f3ec0Sjp161948 * Process previously stored unknown options. When this function is called we
12335d7f3ec0Sjp161948 * already have IgnoreIfUnknown set so finally we can decide whether each
12345d7f3ec0Sjp161948 * unknown option is to be ignored or not.
12355d7f3ec0Sjp161948 */
12365d7f3ec0Sjp161948 void
process_unknown_options(Options * options)12375d7f3ec0Sjp161948 process_unknown_options(Options *options)
12385d7f3ec0Sjp161948 {
12395d7f3ec0Sjp161948 StoredOption *so;
12405d7f3ec0Sjp161948 int m, i, bad_options = 0;
12415d7f3ec0Sjp161948
12425d7f3ec0Sjp161948 /* if there is no unknown option we are done */
12435d7f3ec0Sjp161948 if (options->unknown_opts_num == 0)
12445d7f3ec0Sjp161948 return;
12455d7f3ec0Sjp161948
12465d7f3ec0Sjp161948 /*
12475d7f3ec0Sjp161948 * Now go through the list of unknown options and report any one that
12485d7f3ec0Sjp161948 * is not explicitly listed in IgnoreIfUnknown option. If at least one
12495d7f3ec0Sjp161948 * such as that is found it's a show stopper.
12505d7f3ec0Sjp161948 */
12515d7f3ec0Sjp161948 for (i = 0; i < options->unknown_opts_num; ++i) {
12525d7f3ec0Sjp161948 so = &options->unknown_opts[i];
12535d7f3ec0Sjp161948 if (options->ignore_if_unknown == NULL)
12545d7f3ec0Sjp161948 m = 0;
12555d7f3ec0Sjp161948 else
12565d7f3ec0Sjp161948 m = match_pattern_list(tolowercase(so->keyword),
12575d7f3ec0Sjp161948 options->ignore_if_unknown,
12585d7f3ec0Sjp161948 strlen(options->ignore_if_unknown), 1);
12595d7f3ec0Sjp161948 if (m == 1) {
12605d7f3ec0Sjp161948 debug("%s: line %d: ignoring unknown option: %s",
12615d7f3ec0Sjp161948 so->filename, so->linenum, so->keyword);
12625d7f3ec0Sjp161948 }
12635d7f3ec0Sjp161948 else {
12645d7f3ec0Sjp161948 error("%s: line %d: unknown configuration option: %s",
12655d7f3ec0Sjp161948 so->filename, so->linenum, so->keyword);
12665d7f3ec0Sjp161948 bad_options++;
12675d7f3ec0Sjp161948 }
12685d7f3ec0Sjp161948 xfree(so->keyword);
12695d7f3ec0Sjp161948 xfree(so->filename);
12705d7f3ec0Sjp161948 }
12715d7f3ec0Sjp161948
12725d7f3ec0Sjp161948 /* exit if we found at least one unignored unknown option */
12735d7f3ec0Sjp161948 if (bad_options > 0)
12745d7f3ec0Sjp161948 fatal("terminating, %d bad configuration option(s)",
12755d7f3ec0Sjp161948 bad_options);
12767c478bd9Sstevel@tonic-gate }
1277