10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 30Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 40Sstevel@tonic-gate * All rights reserved 50Sstevel@tonic-gate * Functions for reading the configuration files. 60Sstevel@tonic-gate * 70Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 80Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 90Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 100Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 110Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 120Sstevel@tonic-gate */ 130Sstevel@tonic-gate /* 143946Sjp161948 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 150Sstevel@tonic-gate * Use is subject to license terms. 160Sstevel@tonic-gate */ 170Sstevel@tonic-gate 180Sstevel@tonic-gate #include "includes.h" 190Sstevel@tonic-gate RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); 200Sstevel@tonic-gate 210Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 220Sstevel@tonic-gate 230Sstevel@tonic-gate #include "ssh.h" 240Sstevel@tonic-gate #include "xmalloc.h" 250Sstevel@tonic-gate #include "compat.h" 260Sstevel@tonic-gate #include "cipher.h" 270Sstevel@tonic-gate #include "pathnames.h" 280Sstevel@tonic-gate #include "log.h" 290Sstevel@tonic-gate #include "readconf.h" 300Sstevel@tonic-gate #include "match.h" 310Sstevel@tonic-gate #include "misc.h" 320Sstevel@tonic-gate #include "kex.h" 330Sstevel@tonic-gate #include "mac.h" 340Sstevel@tonic-gate 350Sstevel@tonic-gate /* Format of the configuration file: 360Sstevel@tonic-gate 370Sstevel@tonic-gate # Configuration data is parsed as follows: 380Sstevel@tonic-gate # 1. command line options 390Sstevel@tonic-gate # 2. user-specific file 400Sstevel@tonic-gate # 3. system-wide file 410Sstevel@tonic-gate # Any configuration value is only changed the first time it is set. 420Sstevel@tonic-gate # Thus, host-specific definitions should be at the beginning of the 430Sstevel@tonic-gate # configuration file, and defaults at the end. 440Sstevel@tonic-gate 450Sstevel@tonic-gate # Host-specific declarations. These may override anything above. A single 460Sstevel@tonic-gate # host may match multiple declarations; these are processed in the order 470Sstevel@tonic-gate # that they are given in. 480Sstevel@tonic-gate 490Sstevel@tonic-gate Host *.ngs.fi ngs.fi 500Sstevel@tonic-gate User foo 510Sstevel@tonic-gate 520Sstevel@tonic-gate Host fake.com 530Sstevel@tonic-gate HostName another.host.name.real.org 540Sstevel@tonic-gate User blaah 550Sstevel@tonic-gate Port 34289 560Sstevel@tonic-gate ForwardX11 no 570Sstevel@tonic-gate ForwardAgent no 580Sstevel@tonic-gate 590Sstevel@tonic-gate Host books.com 600Sstevel@tonic-gate RemoteForward 9999 shadows.cs.hut.fi:9999 610Sstevel@tonic-gate Cipher 3des 620Sstevel@tonic-gate 630Sstevel@tonic-gate Host fascist.blob.com 640Sstevel@tonic-gate Port 23123 650Sstevel@tonic-gate User tylonen 660Sstevel@tonic-gate RhostsAuthentication no 670Sstevel@tonic-gate PasswordAuthentication no 680Sstevel@tonic-gate 690Sstevel@tonic-gate Host puukko.hut.fi 700Sstevel@tonic-gate User t35124p 710Sstevel@tonic-gate ProxyCommand ssh-proxy %h %p 720Sstevel@tonic-gate 730Sstevel@tonic-gate Host *.fr 740Sstevel@tonic-gate PublicKeyAuthentication no 750Sstevel@tonic-gate 760Sstevel@tonic-gate Host *.su 770Sstevel@tonic-gate Cipher none 780Sstevel@tonic-gate PasswordAuthentication no 790Sstevel@tonic-gate 800Sstevel@tonic-gate # Defaults for various options 810Sstevel@tonic-gate Host * 820Sstevel@tonic-gate ForwardAgent no 830Sstevel@tonic-gate ForwardX11 no 840Sstevel@tonic-gate RhostsAuthentication yes 850Sstevel@tonic-gate PasswordAuthentication yes 860Sstevel@tonic-gate RSAAuthentication yes 870Sstevel@tonic-gate RhostsRSAAuthentication yes 880Sstevel@tonic-gate StrictHostKeyChecking yes 890Sstevel@tonic-gate KeepAlives no 900Sstevel@tonic-gate IdentityFile ~/.ssh/identity 910Sstevel@tonic-gate Port 22 920Sstevel@tonic-gate EscapeChar ~ 930Sstevel@tonic-gate 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate 960Sstevel@tonic-gate /* Keyword tokens. */ 970Sstevel@tonic-gate 980Sstevel@tonic-gate typedef enum { 990Sstevel@tonic-gate oBadOption, 1004907Sjp161948 oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, 1014907Sjp161948 oRhostsAuthentication, 1020Sstevel@tonic-gate oPasswordAuthentication, oRSAAuthentication, 1030Sstevel@tonic-gate oChallengeResponseAuthentication, oXAuthLocation, 1040Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 1050Sstevel@tonic-gate oKerberosAuthentication, 1060Sstevel@tonic-gate #endif 1070Sstevel@tonic-gate #ifdef GSSAPI 1080Sstevel@tonic-gate oGssKeyEx, oGssAuthentication, oGssDelegateCreds, 1090Sstevel@tonic-gate #ifdef GSI 1100Sstevel@tonic-gate oGssGlobusDelegateLimitedCreds, 1110Sstevel@tonic-gate #endif /* GSI */ 1120Sstevel@tonic-gate #endif /* GSSAPI */ 1130Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 1140Sstevel@tonic-gate oKerberosTgtPassing, 1150Sstevel@tonic-gate #endif 1160Sstevel@tonic-gate #ifdef AFS 1170Sstevel@tonic-gate oAFSTokenPassing, 1180Sstevel@tonic-gate #endif 1190Sstevel@tonic-gate oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 1200Sstevel@tonic-gate oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 1210Sstevel@tonic-gate oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 1220Sstevel@tonic-gate oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 1230Sstevel@tonic-gate oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, 1240Sstevel@tonic-gate oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 1250Sstevel@tonic-gate oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 1260Sstevel@tonic-gate oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 1270Sstevel@tonic-gate oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 1280Sstevel@tonic-gate oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 1290Sstevel@tonic-gate oClearAllForwardings, oNoHostAuthenticationForLocalhost, 1305243Sjp161948 oFallBackToRsh, oUseRsh, oConnectTimeout, oHashKnownHosts, 1314958Sjp161948 oServerAliveInterval, oServerAliveCountMax, oDisableBanner, 132*5266Sjp161948 oIgnoreIfUnknown, oDeprecated 1330Sstevel@tonic-gate } OpCodes; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* Textual representations of the tokens. */ 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate static struct { 1380Sstevel@tonic-gate const char *name; 1390Sstevel@tonic-gate OpCodes opcode; 1400Sstevel@tonic-gate } keywords[] = { 1410Sstevel@tonic-gate { "forwardagent", oForwardAgent }, 1420Sstevel@tonic-gate { "forwardx11", oForwardX11 }, 1434907Sjp161948 { "forwardx11trusted", oForwardX11Trusted }, 1440Sstevel@tonic-gate { "xauthlocation", oXAuthLocation }, 1450Sstevel@tonic-gate { "gatewayports", oGatewayPorts }, 1460Sstevel@tonic-gate { "useprivilegedport", oUsePrivilegedPort }, 1470Sstevel@tonic-gate { "rhostsauthentication", oRhostsAuthentication }, 1480Sstevel@tonic-gate { "passwordauthentication", oPasswordAuthentication }, 1490Sstevel@tonic-gate { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 1500Sstevel@tonic-gate { "kbdinteractivedevices", oKbdInteractiveDevices }, 1510Sstevel@tonic-gate { "rsaauthentication", oRSAAuthentication }, 1520Sstevel@tonic-gate { "pubkeyauthentication", oPubkeyAuthentication }, 1530Sstevel@tonic-gate { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 1540Sstevel@tonic-gate { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 1550Sstevel@tonic-gate { "hostbasedauthentication", oHostbasedAuthentication }, 1560Sstevel@tonic-gate { "challengeresponseauthentication", oChallengeResponseAuthentication }, 1570Sstevel@tonic-gate { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 1580Sstevel@tonic-gate { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 1590Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 1600Sstevel@tonic-gate { "kerberosauthentication", oKerberosAuthentication }, 1610Sstevel@tonic-gate #endif 1620Sstevel@tonic-gate #ifdef GSSAPI 1630Sstevel@tonic-gate { "gssapikeyexchange", oGssKeyEx }, 1640Sstevel@tonic-gate { "gssapiauthentication", oGssAuthentication }, 1650Sstevel@tonic-gate { "gssapidelegatecredentials", oGssDelegateCreds }, 1660Sstevel@tonic-gate { "gsskeyex", oGssKeyEx }, /* alias */ 1670Sstevel@tonic-gate { "gssauthentication", oGssAuthentication }, /* alias */ 1680Sstevel@tonic-gate { "gssdelegatecreds", oGssDelegateCreds }, /* alias */ 1690Sstevel@tonic-gate #ifdef GSI 1700Sstevel@tonic-gate /* For backwards compatability with old 1.2.27 client code */ 1710Sstevel@tonic-gate { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */ 1720Sstevel@tonic-gate { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds }, 1730Sstevel@tonic-gate #endif /* GSI */ 1740Sstevel@tonic-gate #endif /* GSSAPI */ 1750Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 1760Sstevel@tonic-gate { "kerberostgtpassing", oKerberosTgtPassing }, 1770Sstevel@tonic-gate #endif 1780Sstevel@tonic-gate #ifdef AFS 1790Sstevel@tonic-gate { "afstokenpassing", oAFSTokenPassing }, 1800Sstevel@tonic-gate #endif 1810Sstevel@tonic-gate { "fallbacktorsh", oFallBackToRsh }, 1820Sstevel@tonic-gate { "usersh", oUseRsh }, 1830Sstevel@tonic-gate { "identityfile", oIdentityFile }, 1840Sstevel@tonic-gate { "identityfile2", oIdentityFile }, /* alias */ 1850Sstevel@tonic-gate { "hostname", oHostName }, 1860Sstevel@tonic-gate { "hostkeyalias", oHostKeyAlias }, 1870Sstevel@tonic-gate { "proxycommand", oProxyCommand }, 1880Sstevel@tonic-gate { "port", oPort }, 1890Sstevel@tonic-gate { "cipher", oCipher }, 1900Sstevel@tonic-gate { "ciphers", oCiphers }, 1910Sstevel@tonic-gate { "macs", oMacs }, 1920Sstevel@tonic-gate { "protocol", oProtocol }, 1930Sstevel@tonic-gate { "remoteforward", oRemoteForward }, 1940Sstevel@tonic-gate { "localforward", oLocalForward }, 1950Sstevel@tonic-gate { "user", oUser }, 1960Sstevel@tonic-gate { "host", oHost }, 1970Sstevel@tonic-gate { "escapechar", oEscapeChar }, 1980Sstevel@tonic-gate { "globalknownhostsfile", oGlobalKnownHostsFile }, 1990Sstevel@tonic-gate { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ 2000Sstevel@tonic-gate { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, 2010Sstevel@tonic-gate { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 2020Sstevel@tonic-gate { "connectionattempts", oConnectionAttempts }, 2030Sstevel@tonic-gate { "batchmode", oBatchMode }, 2040Sstevel@tonic-gate { "checkhostip", oCheckHostIP }, 2050Sstevel@tonic-gate { "stricthostkeychecking", oStrictHostKeyChecking }, 2060Sstevel@tonic-gate { "compression", oCompression }, 2070Sstevel@tonic-gate { "compressionlevel", oCompressionLevel }, 2080Sstevel@tonic-gate { "keepalive", oKeepAlives }, 2090Sstevel@tonic-gate { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 2100Sstevel@tonic-gate { "loglevel", oLogLevel }, 2110Sstevel@tonic-gate { "dynamicforward", oDynamicForward }, 2120Sstevel@tonic-gate { "preferredauthentications", oPreferredAuthentications }, 2130Sstevel@tonic-gate { "hostkeyalgorithms", oHostKeyAlgorithms }, 2140Sstevel@tonic-gate { "bindaddress", oBindAddress }, 2150Sstevel@tonic-gate { "smartcarddevice", oSmartcardDevice }, 2160Sstevel@tonic-gate { "clearallforwardings", oClearAllForwardings }, 2170Sstevel@tonic-gate { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 2183946Sjp161948 { "connecttimeout", oConnectTimeout }, 2194668Sjp161948 { "serveraliveinterval", oServerAliveInterval }, 2204668Sjp161948 { "serveralivecountmax", oServerAliveCountMax }, 2214958Sjp161948 { "disablebanner", oDisableBanner }, 2225243Sjp161948 { "hashknownhosts", oHashKnownHosts }, 223*5266Sjp161948 { "ignoreifunknown", oIgnoreIfUnknown }, 2240Sstevel@tonic-gate { NULL, oBadOption } 2250Sstevel@tonic-gate }; 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate /* 2280Sstevel@tonic-gate * Adds a local TCP/IP port forward to options. Never returns if there is an 2290Sstevel@tonic-gate * error. 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate void 2330Sstevel@tonic-gate add_local_forward(Options *options, u_short port, const char *host, 2340Sstevel@tonic-gate u_short host_port) 2350Sstevel@tonic-gate { 2360Sstevel@tonic-gate Forward *fwd; 2370Sstevel@tonic-gate #ifndef NO_IPPORT_RESERVED_CONCEPT 2380Sstevel@tonic-gate extern uid_t original_real_uid; 2390Sstevel@tonic-gate if (port < IPPORT_RESERVED && original_real_uid != 0) 2400Sstevel@tonic-gate fatal("Privileged ports can only be forwarded by root."); 2410Sstevel@tonic-gate #endif 2420Sstevel@tonic-gate if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2430Sstevel@tonic-gate fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 2440Sstevel@tonic-gate fwd = &options->local_forwards[options->num_local_forwards++]; 2450Sstevel@tonic-gate fwd->port = port; 2460Sstevel@tonic-gate fwd->host = xstrdup(host); 2470Sstevel@tonic-gate fwd->host_port = host_port; 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * Adds a remote TCP/IP port forward to options. Never returns if there is 2520Sstevel@tonic-gate * an error. 2530Sstevel@tonic-gate */ 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate void 2560Sstevel@tonic-gate add_remote_forward(Options *options, u_short port, const char *host, 2570Sstevel@tonic-gate u_short host_port) 2580Sstevel@tonic-gate { 2590Sstevel@tonic-gate Forward *fwd; 2600Sstevel@tonic-gate if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2610Sstevel@tonic-gate fatal("Too many remote forwards (max %d).", 2620Sstevel@tonic-gate SSH_MAX_FORWARDS_PER_DIRECTION); 2630Sstevel@tonic-gate fwd = &options->remote_forwards[options->num_remote_forwards++]; 2640Sstevel@tonic-gate fwd->port = port; 2650Sstevel@tonic-gate fwd->host = xstrdup(host); 2660Sstevel@tonic-gate fwd->host_port = host_port; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate static void 2700Sstevel@tonic-gate clear_forwardings(Options *options) 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate int i; 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate for (i = 0; i < options->num_local_forwards; i++) 2750Sstevel@tonic-gate xfree(options->local_forwards[i].host); 2760Sstevel@tonic-gate options->num_local_forwards = 0; 2770Sstevel@tonic-gate for (i = 0; i < options->num_remote_forwards; i++) 2780Sstevel@tonic-gate xfree(options->remote_forwards[i].host); 2790Sstevel@tonic-gate options->num_remote_forwards = 0; 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate /* 2830Sstevel@tonic-gate * Returns the number of the token pointed to by cp or oBadOption. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate static OpCodes 2870Sstevel@tonic-gate parse_token(const char *cp, const char *filename, int linenum) 2880Sstevel@tonic-gate { 2890Sstevel@tonic-gate u_int i; 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate for (i = 0; keywords[i].name; i++) 2920Sstevel@tonic-gate if (strcasecmp(cp, keywords[i].name) == 0) 2930Sstevel@tonic-gate return keywords[i].opcode; 2940Sstevel@tonic-gate 295*5266Sjp161948 debug("%s: line %d: unknown configuration option: %s", 2960Sstevel@tonic-gate filename, linenum, cp); 2970Sstevel@tonic-gate return oBadOption; 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Processes a single option line as used in the configuration files. This 3020Sstevel@tonic-gate * only sets those values that have not already been set. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate int 3060Sstevel@tonic-gate process_config_line(Options *options, const char *host, 3070Sstevel@tonic-gate char *line, const char *filename, int linenum, 3080Sstevel@tonic-gate int *activep) 3090Sstevel@tonic-gate { 3100Sstevel@tonic-gate char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg; 311*5266Sjp161948 int opcode, *intptr, value, i; 3120Sstevel@tonic-gate u_short fwd_port, fwd_host_port; 3130Sstevel@tonic-gate char sfwd_host_port[6]; 314*5266Sjp161948 StoredOption *so; 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate s = line; 3170Sstevel@tonic-gate /* Get the keyword. (Each line is supposed to begin with a keyword). */ 3180Sstevel@tonic-gate keyword = strdelim(&s); 3190Sstevel@tonic-gate /* Ignore leading whitespace. */ 3200Sstevel@tonic-gate if (*keyword == '\0') 3210Sstevel@tonic-gate keyword = strdelim(&s); 3220Sstevel@tonic-gate if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 3230Sstevel@tonic-gate return 0; 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate opcode = parse_token(keyword, filename, linenum); 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate switch (opcode) { 3280Sstevel@tonic-gate case oBadOption: 329*5266Sjp161948 if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) { 330*5266Sjp161948 error("we can't have more than %d unknown options:", 331*5266Sjp161948 MAX_UNKNOWN_OPTIONS); 332*5266Sjp161948 for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) { 333*5266Sjp161948 so = &options->unknown_opts[i]; 334*5266Sjp161948 error("%s:%d:%s", 335*5266Sjp161948 so->filename, so->linenum, so->keyword); 336*5266Sjp161948 xfree(so->keyword); 337*5266Sjp161948 xfree(so->filename); 338*5266Sjp161948 } 339*5266Sjp161948 fatal("too many unknown options found, can't continue"); 340*5266Sjp161948 } 341*5266Sjp161948 342*5266Sjp161948 /* unknown options will be processed later */ 343*5266Sjp161948 so = &options->unknown_opts[options->unknown_opts_num]; 344*5266Sjp161948 so->keyword = xstrdup(keyword); 345*5266Sjp161948 so->filename = xstrdup(filename); 346*5266Sjp161948 so->linenum = linenum; 347*5266Sjp161948 options->unknown_opts_num++; 348*5266Sjp161948 return (0); 349*5266Sjp161948 3500Sstevel@tonic-gate /* NOTREACHED */ 3513946Sjp161948 case oConnectTimeout: 3523946Sjp161948 intptr = &options->connection_timeout; 3533946Sjp161948 parse_time: 3543946Sjp161948 arg = strdelim(&s); 3553946Sjp161948 if (!arg || *arg == '\0') 3563946Sjp161948 fatal("%s line %d: missing time value.", 3573946Sjp161948 filename, linenum); 3583946Sjp161948 if ((value = convtime(arg)) == -1) 3593946Sjp161948 fatal("%s line %d: invalid time value.", 3603946Sjp161948 filename, linenum); 3613984Sjp161948 if (*activep && *intptr == -1) 3623946Sjp161948 *intptr = value; 3633946Sjp161948 break; 3643946Sjp161948 3650Sstevel@tonic-gate case oForwardAgent: 3660Sstevel@tonic-gate intptr = &options->forward_agent; 3670Sstevel@tonic-gate parse_flag: 3680Sstevel@tonic-gate arg = strdelim(&s); 3690Sstevel@tonic-gate if (!arg || *arg == '\0') 3700Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 3710Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 3720Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 3730Sstevel@tonic-gate value = 1; 3740Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 3750Sstevel@tonic-gate value = 0; 3760Sstevel@tonic-gate else 3770Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 3780Sstevel@tonic-gate if (*activep && *intptr == -1) 3790Sstevel@tonic-gate *intptr = value; 3800Sstevel@tonic-gate break; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate case oForwardX11: 3830Sstevel@tonic-gate intptr = &options->forward_x11; 3840Sstevel@tonic-gate goto parse_flag; 3850Sstevel@tonic-gate 3864907Sjp161948 case oForwardX11Trusted: 3874907Sjp161948 intptr = &options->forward_x11_trusted; 3884907Sjp161948 goto parse_flag; 3894907Sjp161948 3900Sstevel@tonic-gate case oGatewayPorts: 3910Sstevel@tonic-gate intptr = &options->gateway_ports; 3920Sstevel@tonic-gate goto parse_flag; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate case oUsePrivilegedPort: 3950Sstevel@tonic-gate intptr = &options->use_privileged_port; 3960Sstevel@tonic-gate goto parse_flag; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate case oRhostsAuthentication: 3990Sstevel@tonic-gate intptr = &options->rhosts_authentication; 4000Sstevel@tonic-gate goto parse_flag; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate case oPasswordAuthentication: 4030Sstevel@tonic-gate intptr = &options->password_authentication; 4040Sstevel@tonic-gate goto parse_flag; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate case oKbdInteractiveAuthentication: 4070Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication; 4080Sstevel@tonic-gate goto parse_flag; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate case oKbdInteractiveDevices: 4110Sstevel@tonic-gate charptr = &options->kbd_interactive_devices; 4120Sstevel@tonic-gate goto parse_string; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate case oPubkeyAuthentication: 4150Sstevel@tonic-gate intptr = &options->pubkey_authentication; 4160Sstevel@tonic-gate goto parse_flag; 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate case oRSAAuthentication: 4190Sstevel@tonic-gate intptr = &options->rsa_authentication; 4200Sstevel@tonic-gate goto parse_flag; 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate case oRhostsRSAAuthentication: 4230Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication; 4240Sstevel@tonic-gate goto parse_flag; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate case oHostbasedAuthentication: 4270Sstevel@tonic-gate intptr = &options->hostbased_authentication; 4280Sstevel@tonic-gate goto parse_flag; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate case oChallengeResponseAuthentication: 4310Sstevel@tonic-gate intptr = &options->challenge_response_authentication; 4320Sstevel@tonic-gate goto parse_flag; 4330Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 4340Sstevel@tonic-gate case oKerberosAuthentication: 4350Sstevel@tonic-gate intptr = &options->kerberos_authentication; 4360Sstevel@tonic-gate goto parse_flag; 4370Sstevel@tonic-gate #endif 4380Sstevel@tonic-gate #ifdef GSSAPI 4390Sstevel@tonic-gate case oGssKeyEx: 4400Sstevel@tonic-gate intptr = &options->gss_keyex; 4410Sstevel@tonic-gate goto parse_flag; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate case oGssAuthentication: 4440Sstevel@tonic-gate intptr = &options->gss_authentication; 4450Sstevel@tonic-gate goto parse_flag; 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate case oGssDelegateCreds: 4480Sstevel@tonic-gate intptr = &options->gss_deleg_creds; 4490Sstevel@tonic-gate goto parse_flag; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate #ifdef GSI 4520Sstevel@tonic-gate case oGssGlobusDelegateLimitedCreds: 4530Sstevel@tonic-gate intptr = &options->gss_globus_deleg_limited_proxy; 4540Sstevel@tonic-gate goto parse_flag; 4550Sstevel@tonic-gate #endif /* GSI */ 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate #endif /* GSSAPI */ 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 4600Sstevel@tonic-gate case oKerberosTgtPassing: 4610Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing; 4620Sstevel@tonic-gate goto parse_flag; 4630Sstevel@tonic-gate #endif 4640Sstevel@tonic-gate #ifdef AFS 4650Sstevel@tonic-gate case oAFSTokenPassing: 4660Sstevel@tonic-gate intptr = &options->afs_token_passing; 4670Sstevel@tonic-gate goto parse_flag; 4680Sstevel@tonic-gate #endif 4690Sstevel@tonic-gate case oFallBackToRsh: 4700Sstevel@tonic-gate intptr = &options->fallback_to_rsh; 4710Sstevel@tonic-gate goto parse_flag; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate case oUseRsh: 4740Sstevel@tonic-gate intptr = &options->use_rsh; 4750Sstevel@tonic-gate goto parse_flag; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate case oBatchMode: 4780Sstevel@tonic-gate intptr = &options->batch_mode; 4790Sstevel@tonic-gate goto parse_flag; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate case oCheckHostIP: 4820Sstevel@tonic-gate intptr = &options->check_host_ip; 4830Sstevel@tonic-gate goto parse_flag; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate case oStrictHostKeyChecking: 4860Sstevel@tonic-gate intptr = &options->strict_host_key_checking; 4870Sstevel@tonic-gate arg = strdelim(&s); 4880Sstevel@tonic-gate if (!arg || *arg == '\0') 4890Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no/ask argument.", 4900Sstevel@tonic-gate filename, linenum); 4910Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 4920Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 4930Sstevel@tonic-gate value = 1; 4940Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 4950Sstevel@tonic-gate value = 0; 4960Sstevel@tonic-gate else if (strcmp(arg, "ask") == 0) 4970Sstevel@tonic-gate value = 2; 4980Sstevel@tonic-gate else 4990Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 5000Sstevel@tonic-gate if (*activep && *intptr == -1) 5010Sstevel@tonic-gate *intptr = value; 5020Sstevel@tonic-gate break; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate case oCompression: 5050Sstevel@tonic-gate intptr = &options->compression; 5060Sstevel@tonic-gate goto parse_flag; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate case oKeepAlives: 5090Sstevel@tonic-gate intptr = &options->keepalives; 5100Sstevel@tonic-gate goto parse_flag; 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate case oNoHostAuthenticationForLocalhost: 5130Sstevel@tonic-gate intptr = &options->no_host_authentication_for_localhost; 5140Sstevel@tonic-gate goto parse_flag; 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate case oNumberOfPasswordPrompts: 5170Sstevel@tonic-gate intptr = &options->number_of_password_prompts; 5180Sstevel@tonic-gate goto parse_int; 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate case oCompressionLevel: 5210Sstevel@tonic-gate intptr = &options->compression_level; 5220Sstevel@tonic-gate goto parse_int; 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate case oIdentityFile: 5250Sstevel@tonic-gate arg = strdelim(&s); 5260Sstevel@tonic-gate if (!arg || *arg == '\0') 5270Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5280Sstevel@tonic-gate if (*activep) { 5290Sstevel@tonic-gate intptr = &options->num_identity_files; 5300Sstevel@tonic-gate if (*intptr >= SSH_MAX_IDENTITY_FILES) 5310Sstevel@tonic-gate fatal("%.200s line %d: Too many identity files specified (max %d).", 5320Sstevel@tonic-gate filename, linenum, SSH_MAX_IDENTITY_FILES); 5330Sstevel@tonic-gate charptr = &options->identity_files[*intptr]; 5340Sstevel@tonic-gate *charptr = xstrdup(arg); 5350Sstevel@tonic-gate *intptr = *intptr + 1; 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate break; 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate case oXAuthLocation: 5400Sstevel@tonic-gate charptr=&options->xauth_location; 5410Sstevel@tonic-gate goto parse_string; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate case oUser: 5440Sstevel@tonic-gate charptr = &options->user; 5450Sstevel@tonic-gate parse_string: 5460Sstevel@tonic-gate arg = strdelim(&s); 5470Sstevel@tonic-gate if (!arg || *arg == '\0') 5480Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5490Sstevel@tonic-gate if (*activep && *charptr == NULL) 5500Sstevel@tonic-gate *charptr = xstrdup(arg); 5510Sstevel@tonic-gate break; 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate case oGlobalKnownHostsFile: 5540Sstevel@tonic-gate charptr = &options->system_hostfile; 5550Sstevel@tonic-gate goto parse_string; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate case oUserKnownHostsFile: 5580Sstevel@tonic-gate charptr = &options->user_hostfile; 5590Sstevel@tonic-gate goto parse_string; 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate case oGlobalKnownHostsFile2: 5620Sstevel@tonic-gate charptr = &options->system_hostfile2; 5630Sstevel@tonic-gate goto parse_string; 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate case oUserKnownHostsFile2: 5660Sstevel@tonic-gate charptr = &options->user_hostfile2; 5670Sstevel@tonic-gate goto parse_string; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate case oHostName: 5700Sstevel@tonic-gate charptr = &options->hostname; 5710Sstevel@tonic-gate goto parse_string; 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate case oHostKeyAlias: 5740Sstevel@tonic-gate charptr = &options->host_key_alias; 5750Sstevel@tonic-gate goto parse_string; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate case oPreferredAuthentications: 5780Sstevel@tonic-gate charptr = &options->preferred_authentications; 5790Sstevel@tonic-gate goto parse_string; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate case oBindAddress: 5820Sstevel@tonic-gate charptr = &options->bind_address; 5830Sstevel@tonic-gate goto parse_string; 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate case oSmartcardDevice: 5860Sstevel@tonic-gate charptr = &options->smartcard_device; 5870Sstevel@tonic-gate goto parse_string; 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate case oProxyCommand: 5900Sstevel@tonic-gate charptr = &options->proxy_command; 5910Sstevel@tonic-gate string = xstrdup(""); 5920Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 5930Sstevel@tonic-gate string = xrealloc(string, strlen(string) + strlen(arg) + 2); 5940Sstevel@tonic-gate strcat(string, " "); 5950Sstevel@tonic-gate strcat(string, arg); 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate if (*activep && *charptr == NULL) 5980Sstevel@tonic-gate *charptr = string; 5990Sstevel@tonic-gate else 6000Sstevel@tonic-gate xfree(string); 6010Sstevel@tonic-gate return 0; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate case oPort: 6040Sstevel@tonic-gate intptr = &options->port; 6050Sstevel@tonic-gate parse_int: 6060Sstevel@tonic-gate arg = strdelim(&s); 6070Sstevel@tonic-gate if (!arg || *arg == '\0') 6080Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6090Sstevel@tonic-gate if (arg[0] < '0' || arg[0] > '9') 6100Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* Octal, decimal, or hex format? */ 6130Sstevel@tonic-gate value = strtol(arg, &endofnumber, 0); 6140Sstevel@tonic-gate if (arg == endofnumber) 6150Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 6160Sstevel@tonic-gate if (*activep && *intptr == -1) 6170Sstevel@tonic-gate *intptr = value; 6180Sstevel@tonic-gate break; 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate case oConnectionAttempts: 6210Sstevel@tonic-gate intptr = &options->connection_attempts; 6220Sstevel@tonic-gate goto parse_int; 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate case oCipher: 6250Sstevel@tonic-gate intptr = &options->cipher; 6260Sstevel@tonic-gate arg = strdelim(&s); 6270Sstevel@tonic-gate if (!arg || *arg == '\0') 6280Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6290Sstevel@tonic-gate value = cipher_number(arg); 6300Sstevel@tonic-gate if (value == -1) 6310Sstevel@tonic-gate fatal("%.200s line %d: Bad cipher '%s'.", 6320Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6330Sstevel@tonic-gate if (*activep && *intptr == -1) 6340Sstevel@tonic-gate *intptr = value; 6350Sstevel@tonic-gate break; 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate case oCiphers: 6380Sstevel@tonic-gate arg = strdelim(&s); 6390Sstevel@tonic-gate if (!arg || *arg == '\0') 6400Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6410Sstevel@tonic-gate if (!ciphers_valid(arg)) 6420Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 6430Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6440Sstevel@tonic-gate if (*activep && options->ciphers == NULL) 6450Sstevel@tonic-gate options->ciphers = xstrdup(arg); 6460Sstevel@tonic-gate break; 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate case oMacs: 6490Sstevel@tonic-gate arg = strdelim(&s); 6500Sstevel@tonic-gate if (!arg || *arg == '\0') 6510Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6520Sstevel@tonic-gate if (!mac_valid(arg)) 6530Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 6540Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6550Sstevel@tonic-gate if (*activep && options->macs == NULL) 6560Sstevel@tonic-gate options->macs = xstrdup(arg); 6570Sstevel@tonic-gate break; 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate case oHostKeyAlgorithms: 6600Sstevel@tonic-gate arg = strdelim(&s); 6610Sstevel@tonic-gate if (!arg || *arg == '\0') 6620Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6630Sstevel@tonic-gate if (!key_names_valid2(arg)) 6640Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 6650Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6660Sstevel@tonic-gate if (*activep && options->hostkeyalgorithms == NULL) 6670Sstevel@tonic-gate options->hostkeyalgorithms = xstrdup(arg); 6680Sstevel@tonic-gate break; 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate case oProtocol: 6710Sstevel@tonic-gate intptr = &options->protocol; 6720Sstevel@tonic-gate arg = strdelim(&s); 6730Sstevel@tonic-gate if (!arg || *arg == '\0') 6740Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6750Sstevel@tonic-gate value = proto_spec(arg); 6760Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN) 6770Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol spec '%s'.", 6780Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6790Sstevel@tonic-gate if (*activep && *intptr == SSH_PROTO_UNKNOWN) 6800Sstevel@tonic-gate *intptr = value; 6810Sstevel@tonic-gate break; 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate case oLogLevel: 6840Sstevel@tonic-gate intptr = (int *) &options->log_level; 6850Sstevel@tonic-gate arg = strdelim(&s); 6860Sstevel@tonic-gate value = log_level_number(arg); 6870Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET) 6880Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'", 6890Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6900Sstevel@tonic-gate if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) 6910Sstevel@tonic-gate *intptr = (LogLevel) value; 6920Sstevel@tonic-gate break; 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate case oLocalForward: 6950Sstevel@tonic-gate case oRemoteForward: 6960Sstevel@tonic-gate arg = strdelim(&s); 6970Sstevel@tonic-gate if (!arg || *arg == '\0') 6980Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 6990Sstevel@tonic-gate filename, linenum); 7000Sstevel@tonic-gate if ((fwd_port = a2port(arg)) == 0) 7010Sstevel@tonic-gate fatal("%.200s line %d: Bad listen port.", 7020Sstevel@tonic-gate filename, linenum); 7030Sstevel@tonic-gate arg = strdelim(&s); 7040Sstevel@tonic-gate if (!arg || *arg == '\0') 7050Sstevel@tonic-gate fatal("%.200s line %d: Missing second argument.", 7060Sstevel@tonic-gate filename, linenum); 7070Sstevel@tonic-gate if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && 7080Sstevel@tonic-gate sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) 7090Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding specification.", 7100Sstevel@tonic-gate filename, linenum); 7110Sstevel@tonic-gate if ((fwd_host_port = a2port(sfwd_host_port)) == 0) 7120Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding port.", 7130Sstevel@tonic-gate filename, linenum); 7140Sstevel@tonic-gate if (*activep) { 7150Sstevel@tonic-gate if (opcode == oLocalForward) 7160Sstevel@tonic-gate add_local_forward(options, fwd_port, buf, 7170Sstevel@tonic-gate fwd_host_port); 7180Sstevel@tonic-gate else if (opcode == oRemoteForward) 7190Sstevel@tonic-gate add_remote_forward(options, fwd_port, buf, 7200Sstevel@tonic-gate fwd_host_port); 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate break; 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate case oDynamicForward: 7250Sstevel@tonic-gate arg = strdelim(&s); 7260Sstevel@tonic-gate if (!arg || *arg == '\0') 7270Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 7280Sstevel@tonic-gate filename, linenum); 7290Sstevel@tonic-gate fwd_port = a2port(arg); 7300Sstevel@tonic-gate if (fwd_port == 0) 7310Sstevel@tonic-gate fatal("%.200s line %d: Badly formatted port number.", 7320Sstevel@tonic-gate filename, linenum); 7330Sstevel@tonic-gate if (*activep) 7340Sstevel@tonic-gate add_local_forward(options, fwd_port, "socks4", 0); 7350Sstevel@tonic-gate break; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate case oClearAllForwardings: 7380Sstevel@tonic-gate intptr = &options->clear_forwardings; 7390Sstevel@tonic-gate goto parse_flag; 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate case oHost: 7420Sstevel@tonic-gate *activep = 0; 7430Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') 7440Sstevel@tonic-gate if (match_pattern(host, arg)) { 7450Sstevel@tonic-gate debug("Applying options for %.100s", arg); 7460Sstevel@tonic-gate *activep = 1; 7470Sstevel@tonic-gate break; 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate /* Avoid garbage check below, as strdelim is done. */ 7500Sstevel@tonic-gate return 0; 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate case oEscapeChar: 7530Sstevel@tonic-gate intptr = &options->escape_char; 7540Sstevel@tonic-gate arg = strdelim(&s); 7550Sstevel@tonic-gate if (!arg || *arg == '\0') 7560Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 7570Sstevel@tonic-gate if (arg[0] == '^' && arg[2] == 0 && 7580Sstevel@tonic-gate (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 7590Sstevel@tonic-gate value = (u_char) arg[1] & 31; 7600Sstevel@tonic-gate else if (strlen(arg) == 1) 7610Sstevel@tonic-gate value = (u_char) arg[0]; 7620Sstevel@tonic-gate else if (strcmp(arg, "none") == 0) 7630Sstevel@tonic-gate value = SSH_ESCAPECHAR_NONE; 7640Sstevel@tonic-gate else { 7650Sstevel@tonic-gate fatal("%.200s line %d: Bad escape character.", 7660Sstevel@tonic-gate filename, linenum); 7670Sstevel@tonic-gate /* NOTREACHED */ 7680Sstevel@tonic-gate value = 0; /* Avoid compiler warning. */ 7690Sstevel@tonic-gate } 7700Sstevel@tonic-gate if (*activep && *intptr == -1) 7710Sstevel@tonic-gate *intptr = value; 7720Sstevel@tonic-gate break; 7730Sstevel@tonic-gate 7744668Sjp161948 case oServerAliveInterval: 7754668Sjp161948 intptr = &options->server_alive_interval; 7764668Sjp161948 goto parse_time; 7774668Sjp161948 7784668Sjp161948 case oServerAliveCountMax: 7794668Sjp161948 intptr = &options->server_alive_count_max; 7804668Sjp161948 goto parse_int; 7814668Sjp161948 7825243Sjp161948 case oHashKnownHosts: 7835243Sjp161948 intptr = &options->hash_known_hosts; 7845243Sjp161948 goto parse_flag; 7855243Sjp161948 7864958Sjp161948 case oDisableBanner: 7874958Sjp161948 arg = strdelim(&s); 7884958Sjp161948 if (get_yes_no_flag(&options->disable_banner, arg, filename, 7894958Sjp161948 linenum, *activep) == 1) 7904958Sjp161948 break; 7914958Sjp161948 7924958Sjp161948 if (strcmp(arg, "in-exec-mode") == 0) 7934958Sjp161948 options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE; 7944958Sjp161948 else 7954958Sjp161948 fatal("%.200s line %d: Bad yes/no/in-exec-mode " 7964958Sjp161948 "argument.", filename, linenum); 7974958Sjp161948 break; 7984958Sjp161948 799*5266Sjp161948 case oIgnoreIfUnknown: 800*5266Sjp161948 charptr = &options->ignore_if_unknown; 801*5266Sjp161948 goto parse_string; 802*5266Sjp161948 8030Sstevel@tonic-gate case oDeprecated: 8040Sstevel@tonic-gate debug("%s line %d: Deprecated option \"%s\"", 8050Sstevel@tonic-gate filename, linenum, keyword); 8060Sstevel@tonic-gate return 0; 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate default: 8090Sstevel@tonic-gate fatal("process_config_line: Unimplemented opcode %d", opcode); 8100Sstevel@tonic-gate } 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate /* Check that there is no garbage at end of line. */ 8130Sstevel@tonic-gate if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 8140Sstevel@tonic-gate fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 8150Sstevel@tonic-gate filename, linenum, arg); 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate return 0; 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* 8220Sstevel@tonic-gate * Reads the config file and modifies the options accordingly. Options 8230Sstevel@tonic-gate * should already be initialized before this call. This never returns if 8240Sstevel@tonic-gate * there is an error. If the file does not exist, this returns 0. 8250Sstevel@tonic-gate */ 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate int 8280Sstevel@tonic-gate read_config_file(const char *filename, const char *host, Options *options) 8290Sstevel@tonic-gate { 8300Sstevel@tonic-gate FILE *f; 8310Sstevel@tonic-gate char line[1024]; 8320Sstevel@tonic-gate int active, linenum; 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate /* Open the file. */ 8350Sstevel@tonic-gate f = fopen(filename, "r"); 8360Sstevel@tonic-gate if (!f) 8370Sstevel@tonic-gate return 0; 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate debug("Reading configuration data %.200s", filename); 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate /* 8420Sstevel@tonic-gate * Mark that we are now processing the options. This flag is turned 8430Sstevel@tonic-gate * on/off by Host specifications. 8440Sstevel@tonic-gate */ 8450Sstevel@tonic-gate active = 1; 8460Sstevel@tonic-gate linenum = 0; 8470Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 8480Sstevel@tonic-gate /* Update line number counter. */ 8490Sstevel@tonic-gate linenum++; 850*5266Sjp161948 process_config_line(options, host, line, filename, linenum, &active); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate fclose(f); 8530Sstevel@tonic-gate return 1; 8540Sstevel@tonic-gate } 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate /* 8570Sstevel@tonic-gate * Initializes options to special values that indicate that they have not yet 8580Sstevel@tonic-gate * been set. Read_config_file will only set options with this value. Options 8590Sstevel@tonic-gate * are processed in the following order: command line, user config file, 8600Sstevel@tonic-gate * system config file. Last, fill_default_options is called. 8610Sstevel@tonic-gate */ 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate void 8640Sstevel@tonic-gate initialize_options(Options * options) 8650Sstevel@tonic-gate { 8660Sstevel@tonic-gate memset(options, 'X', sizeof(*options)); 8670Sstevel@tonic-gate options->forward_agent = -1; 8680Sstevel@tonic-gate options->forward_x11 = -1; 8694907Sjp161948 options->forward_x11_trusted = -1; 8700Sstevel@tonic-gate options->xauth_location = NULL; 8710Sstevel@tonic-gate options->gateway_ports = -1; 8720Sstevel@tonic-gate options->use_privileged_port = -1; 8730Sstevel@tonic-gate options->rhosts_authentication = -1; 8740Sstevel@tonic-gate options->rsa_authentication = -1; 8750Sstevel@tonic-gate options->pubkey_authentication = -1; 8760Sstevel@tonic-gate options->challenge_response_authentication = -1; 8770Sstevel@tonic-gate #ifdef GSSAPI 8780Sstevel@tonic-gate options->gss_keyex = -1; 8790Sstevel@tonic-gate options->gss_authentication = -1; 8800Sstevel@tonic-gate options->gss_deleg_creds = -1; 8810Sstevel@tonic-gate #ifdef GSI 8820Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = -1; 8830Sstevel@tonic-gate #endif /* GSI */ 8840Sstevel@tonic-gate #endif /* GSSAPI */ 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 8870Sstevel@tonic-gate options->kerberos_authentication = -1; 8880Sstevel@tonic-gate #endif 8890Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 8900Sstevel@tonic-gate options->kerberos_tgt_passing = -1; 8910Sstevel@tonic-gate #endif 8920Sstevel@tonic-gate #ifdef AFS 8930Sstevel@tonic-gate options->afs_token_passing = -1; 8940Sstevel@tonic-gate #endif 8950Sstevel@tonic-gate options->password_authentication = -1; 8960Sstevel@tonic-gate options->kbd_interactive_authentication = -1; 8970Sstevel@tonic-gate options->kbd_interactive_devices = NULL; 8980Sstevel@tonic-gate options->rhosts_rsa_authentication = -1; 8990Sstevel@tonic-gate options->hostbased_authentication = -1; 9000Sstevel@tonic-gate options->batch_mode = -1; 9010Sstevel@tonic-gate options->check_host_ip = -1; 9020Sstevel@tonic-gate options->strict_host_key_checking = -1; 9030Sstevel@tonic-gate options->compression = -1; 9040Sstevel@tonic-gate options->keepalives = -1; 9050Sstevel@tonic-gate options->compression_level = -1; 9060Sstevel@tonic-gate options->port = -1; 9070Sstevel@tonic-gate options->connection_attempts = -1; 9083946Sjp161948 options->connection_timeout = -1; 9090Sstevel@tonic-gate options->number_of_password_prompts = -1; 9100Sstevel@tonic-gate options->cipher = -1; 9110Sstevel@tonic-gate options->ciphers = NULL; 9120Sstevel@tonic-gate options->macs = NULL; 9130Sstevel@tonic-gate options->hostkeyalgorithms = NULL; 9140Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN; 9150Sstevel@tonic-gate options->num_identity_files = 0; 9160Sstevel@tonic-gate options->hostname = NULL; 9170Sstevel@tonic-gate options->host_key_alias = NULL; 9180Sstevel@tonic-gate options->proxy_command = NULL; 9190Sstevel@tonic-gate options->user = NULL; 9200Sstevel@tonic-gate options->escape_char = -1; 9210Sstevel@tonic-gate options->system_hostfile = NULL; 9220Sstevel@tonic-gate options->user_hostfile = NULL; 9230Sstevel@tonic-gate options->system_hostfile2 = NULL; 9240Sstevel@tonic-gate options->user_hostfile2 = NULL; 9250Sstevel@tonic-gate options->num_local_forwards = 0; 9260Sstevel@tonic-gate options->num_remote_forwards = 0; 9270Sstevel@tonic-gate options->clear_forwardings = -1; 9280Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET; 9290Sstevel@tonic-gate options->preferred_authentications = NULL; 9300Sstevel@tonic-gate options->bind_address = NULL; 9310Sstevel@tonic-gate options->smartcard_device = NULL; 9320Sstevel@tonic-gate options->no_host_authentication_for_localhost = - 1; 9330Sstevel@tonic-gate options->fallback_to_rsh = -1; 9340Sstevel@tonic-gate options->use_rsh = -1; 9354668Sjp161948 options->server_alive_interval = -1; 9364668Sjp161948 options->server_alive_count_max = -1; 9375243Sjp161948 options->hash_known_hosts = -1; 938*5266Sjp161948 options->ignore_if_unknown = NULL; 939*5266Sjp161948 options->unknown_opts_num = 0; 9404958Sjp161948 options->disable_banner = -1; 9410Sstevel@tonic-gate } 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate /* 9440Sstevel@tonic-gate * Called after processing other sources of option data, this fills those 9450Sstevel@tonic-gate * options for which no value has been specified with their default values. 9460Sstevel@tonic-gate */ 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate void 9490Sstevel@tonic-gate fill_default_options(Options * options) 9500Sstevel@tonic-gate { 9510Sstevel@tonic-gate int len; 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate if (options->forward_agent == -1) 9540Sstevel@tonic-gate options->forward_agent = 0; 9550Sstevel@tonic-gate if (options->forward_x11 == -1) 9560Sstevel@tonic-gate options->forward_x11 = 0; 9574907Sjp161948 /* 9584907Sjp161948 * Unlike OpenSSH, we keep backward compatibility for '-X' option 9594907Sjp161948 * which means that X11 forwarding is trusted by default. 9604907Sjp161948 */ 9614907Sjp161948 if (options->forward_x11_trusted == -1) 9624907Sjp161948 options->forward_x11_trusted = 1; 9630Sstevel@tonic-gate if (options->xauth_location == NULL) 9640Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH; 9650Sstevel@tonic-gate if (options->gateway_ports == -1) 9660Sstevel@tonic-gate options->gateway_ports = 0; 9670Sstevel@tonic-gate if (options->use_privileged_port == -1) 9680Sstevel@tonic-gate options->use_privileged_port = 0; 9690Sstevel@tonic-gate if (options->rhosts_authentication == -1) 9700Sstevel@tonic-gate options->rhosts_authentication = 0; 9710Sstevel@tonic-gate if (options->rsa_authentication == -1) 9720Sstevel@tonic-gate options->rsa_authentication = 1; 9730Sstevel@tonic-gate if (options->pubkey_authentication == -1) 9740Sstevel@tonic-gate options->pubkey_authentication = 1; 9750Sstevel@tonic-gate if (options->challenge_response_authentication == -1) 9760Sstevel@tonic-gate options->challenge_response_authentication = 1; 9770Sstevel@tonic-gate #ifdef GSSAPI 9780Sstevel@tonic-gate if (options->gss_keyex == -1) 9790Sstevel@tonic-gate options->gss_keyex = 1; 9800Sstevel@tonic-gate if (options->gss_authentication == -1) 9810Sstevel@tonic-gate options->gss_authentication = 1; 9820Sstevel@tonic-gate if (options->gss_deleg_creds == -1) 9830Sstevel@tonic-gate options->gss_deleg_creds = 0; 9840Sstevel@tonic-gate #ifdef GSI 9850Sstevel@tonic-gate if (options->gss_globus_deleg_limited_proxy == -1) 9860Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = 0; 9870Sstevel@tonic-gate #endif /* GSI */ 9880Sstevel@tonic-gate #endif /* GSSAPI */ 9890Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 9900Sstevel@tonic-gate if (options->kerberos_authentication == -1) 9910Sstevel@tonic-gate options->kerberos_authentication = 1; 9920Sstevel@tonic-gate #endif 9930Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 9940Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1) 9950Sstevel@tonic-gate options->kerberos_tgt_passing = 1; 9960Sstevel@tonic-gate #endif 9970Sstevel@tonic-gate #ifdef AFS 9980Sstevel@tonic-gate if (options->afs_token_passing == -1) 9990Sstevel@tonic-gate options->afs_token_passing = 1; 10000Sstevel@tonic-gate #endif 10010Sstevel@tonic-gate if (options->password_authentication == -1) 10020Sstevel@tonic-gate options->password_authentication = 1; 10030Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1) 10040Sstevel@tonic-gate options->kbd_interactive_authentication = 1; 10050Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1) 10060Sstevel@tonic-gate options->rhosts_rsa_authentication = 0; 10070Sstevel@tonic-gate if (options->hostbased_authentication == -1) 10080Sstevel@tonic-gate options->hostbased_authentication = 0; 10090Sstevel@tonic-gate if (options->batch_mode == -1) 10100Sstevel@tonic-gate options->batch_mode = 0; 10110Sstevel@tonic-gate if (options->check_host_ip == -1) 10120Sstevel@tonic-gate options->check_host_ip = 1; 10130Sstevel@tonic-gate if (options->strict_host_key_checking == -1) 10140Sstevel@tonic-gate options->strict_host_key_checking = 2; /* 2 is default */ 10150Sstevel@tonic-gate if (options->compression == -1) 10160Sstevel@tonic-gate options->compression = 0; 10170Sstevel@tonic-gate if (options->keepalives == -1) 10180Sstevel@tonic-gate options->keepalives = 1; 10190Sstevel@tonic-gate if (options->compression_level == -1) 10200Sstevel@tonic-gate options->compression_level = 6; 10210Sstevel@tonic-gate if (options->port == -1) 10220Sstevel@tonic-gate options->port = 0; /* Filled in ssh_connect. */ 10230Sstevel@tonic-gate if (options->connection_attempts == -1) 10240Sstevel@tonic-gate options->connection_attempts = 1; 10250Sstevel@tonic-gate if (options->number_of_password_prompts == -1) 10260Sstevel@tonic-gate options->number_of_password_prompts = 3; 10270Sstevel@tonic-gate /* Selected in ssh_login(). */ 10280Sstevel@tonic-gate if (options->cipher == -1) 10290Sstevel@tonic-gate options->cipher = SSH_CIPHER_NOT_SET; 10300Sstevel@tonic-gate /* options->ciphers, default set in myproposals.h */ 10310Sstevel@tonic-gate /* options->macs, default set in myproposals.h */ 10320Sstevel@tonic-gate /* options->hostkeyalgorithms, default set in myproposals.h */ 10330Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN) 10340Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2; 10350Sstevel@tonic-gate if (options->num_identity_files == 0) { 10360Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) { 10370Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 10380Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10390Sstevel@tonic-gate xmalloc(len); 10400Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10410Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 10420Sstevel@tonic-gate } 10430Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) { 10440Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 10450Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10460Sstevel@tonic-gate xmalloc(len); 10470Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10480Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 10510Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10520Sstevel@tonic-gate xmalloc(len); 10530Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10540Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate if (options->escape_char == -1) 10580Sstevel@tonic-gate options->escape_char = '~'; 10590Sstevel@tonic-gate if (options->system_hostfile == NULL) 10600Sstevel@tonic-gate options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 10610Sstevel@tonic-gate if (options->user_hostfile == NULL) 10620Sstevel@tonic-gate options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 10630Sstevel@tonic-gate if (options->system_hostfile2 == NULL) 10640Sstevel@tonic-gate options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 10650Sstevel@tonic-gate if (options->user_hostfile2 == NULL) 10660Sstevel@tonic-gate options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 10670Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET) 10680Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO; 10690Sstevel@tonic-gate if (options->clear_forwardings == 1) 10700Sstevel@tonic-gate clear_forwardings(options); 10710Sstevel@tonic-gate if (options->no_host_authentication_for_localhost == - 1) 10720Sstevel@tonic-gate options->no_host_authentication_for_localhost = 0; 10730Sstevel@tonic-gate if (options->fallback_to_rsh == - 1) 10740Sstevel@tonic-gate options->fallback_to_rsh = 0; 10750Sstevel@tonic-gate if (options->use_rsh == - 1) 10760Sstevel@tonic-gate options->use_rsh = 0; 10774668Sjp161948 if (options->server_alive_interval == -1) 10784668Sjp161948 options->server_alive_interval = 0; 10794668Sjp161948 if (options->server_alive_count_max == -1) 10804668Sjp161948 options->server_alive_count_max = 3; 10815243Sjp161948 if (options->hash_known_hosts == -1) 10825243Sjp161948 options->hash_known_hosts = 0; 10834958Sjp161948 if (options->disable_banner == -1) 10844958Sjp161948 options->disable_banner = 0; 10850Sstevel@tonic-gate /* options->proxy_command should not be set by default */ 10860Sstevel@tonic-gate /* options->user will be set in the main program if appropriate */ 10870Sstevel@tonic-gate /* options->hostname will be set in the main program if appropriate */ 10880Sstevel@tonic-gate /* options->host_key_alias should not be set by default */ 10890Sstevel@tonic-gate /* options->preferred_authentications will be set in ssh */ 1090*5266Sjp161948 /* options->ignore_if_unknown should not be set by default */ 10910Sstevel@tonic-gate } 1092*5266Sjp161948 1093*5266Sjp161948 /* 1094*5266Sjp161948 * Process previously stored unknown options. When this function is called we 1095*5266Sjp161948 * already have IgnoreIfUnknown set so finally we can decide whether each 1096*5266Sjp161948 * unknown option is to be ignored or not. 1097*5266Sjp161948 */ 1098*5266Sjp161948 void 1099*5266Sjp161948 process_unknown_options(Options *options) 1100*5266Sjp161948 { 1101*5266Sjp161948 StoredOption *so; 1102*5266Sjp161948 int m, i, bad_options = 0; 1103*5266Sjp161948 1104*5266Sjp161948 /* if there is no unknown option we are done */ 1105*5266Sjp161948 if (options->unknown_opts_num == 0) 1106*5266Sjp161948 return; 1107*5266Sjp161948 1108*5266Sjp161948 /* 1109*5266Sjp161948 * Now go through the list of unknown options and report any one that 1110*5266Sjp161948 * is not explicitly listed in IgnoreIfUnknown option. If at least one 1111*5266Sjp161948 * such as that is found it's a show stopper. 1112*5266Sjp161948 */ 1113*5266Sjp161948 for (i = 0; i < options->unknown_opts_num; ++i) { 1114*5266Sjp161948 so = &options->unknown_opts[i]; 1115*5266Sjp161948 if (options->ignore_if_unknown == NULL) 1116*5266Sjp161948 m = 0; 1117*5266Sjp161948 else 1118*5266Sjp161948 m = match_pattern_list(tolowercase(so->keyword), 1119*5266Sjp161948 options->ignore_if_unknown, 1120*5266Sjp161948 strlen(options->ignore_if_unknown), 1); 1121*5266Sjp161948 if (m == 1) { 1122*5266Sjp161948 debug("%s: line %d: ignoring unknown option: %s", 1123*5266Sjp161948 so->filename, so->linenum, so->keyword); 1124*5266Sjp161948 } 1125*5266Sjp161948 else { 1126*5266Sjp161948 error("%s: line %d: unknown configuration option: %s", 1127*5266Sjp161948 so->filename, so->linenum, so->keyword); 1128*5266Sjp161948 bad_options++; 1129*5266Sjp161948 } 1130*5266Sjp161948 xfree(so->keyword); 1131*5266Sjp161948 xfree(so->filename); 1132*5266Sjp161948 } 1133*5266Sjp161948 1134*5266Sjp161948 /* exit if we found at least one unignored unknown option */ 1135*5266Sjp161948 if (bad_options > 0) 1136*5266Sjp161948 fatal("terminating, %d bad configuration option(s)", 1137*5266Sjp161948 bad_options); 1138*5266Sjp161948 } 1139