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, 1325266Sjp161948 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 }, 2235266Sjp161948 { "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 233*5334Sjp161948 add_local_forward(Options *options, const Forward *newfwd) 2340Sstevel@tonic-gate { 2350Sstevel@tonic-gate Forward *fwd; 2360Sstevel@tonic-gate #ifndef NO_IPPORT_RESERVED_CONCEPT 2370Sstevel@tonic-gate extern uid_t original_real_uid; 238*5334Sjp161948 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 2390Sstevel@tonic-gate fatal("Privileged ports can only be forwarded by root."); 2400Sstevel@tonic-gate #endif 2410Sstevel@tonic-gate if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2420Sstevel@tonic-gate fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 2430Sstevel@tonic-gate fwd = &options->local_forwards[options->num_local_forwards++]; 244*5334Sjp161948 245*5334Sjp161948 fwd->listen_host = (newfwd->listen_host == NULL) ? 246*5334Sjp161948 NULL : xstrdup(newfwd->listen_host); 247*5334Sjp161948 fwd->listen_port = newfwd->listen_port; 248*5334Sjp161948 fwd->connect_host = xstrdup(newfwd->connect_host); 249*5334Sjp161948 fwd->connect_port = newfwd->connect_port; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * Adds a remote TCP/IP port forward to options. Never returns if there is 2540Sstevel@tonic-gate * an error. 2550Sstevel@tonic-gate */ 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate void 258*5334Sjp161948 add_remote_forward(Options *options, const Forward *newfwd) 2590Sstevel@tonic-gate { 2600Sstevel@tonic-gate Forward *fwd; 2610Sstevel@tonic-gate if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2620Sstevel@tonic-gate fatal("Too many remote forwards (max %d).", 2630Sstevel@tonic-gate SSH_MAX_FORWARDS_PER_DIRECTION); 2640Sstevel@tonic-gate fwd = &options->remote_forwards[options->num_remote_forwards++]; 265*5334Sjp161948 266*5334Sjp161948 fwd->listen_host = (newfwd->listen_host == NULL) ? 267*5334Sjp161948 NULL : xstrdup(newfwd->listen_host); 268*5334Sjp161948 fwd->listen_port = newfwd->listen_port; 269*5334Sjp161948 fwd->connect_host = xstrdup(newfwd->connect_host); 270*5334Sjp161948 fwd->connect_port = newfwd->connect_port; 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate static void 2740Sstevel@tonic-gate clear_forwardings(Options *options) 2750Sstevel@tonic-gate { 2760Sstevel@tonic-gate int i; 2770Sstevel@tonic-gate 278*5334Sjp161948 for (i = 0; i < options->num_local_forwards; i++) { 279*5334Sjp161948 if (options->local_forwards[i].listen_host != NULL) 280*5334Sjp161948 xfree(options->local_forwards[i].listen_host); 281*5334Sjp161948 xfree(options->local_forwards[i].connect_host); 282*5334Sjp161948 } 2830Sstevel@tonic-gate options->num_local_forwards = 0; 284*5334Sjp161948 for (i = 0; i < options->num_remote_forwards; i++) { 285*5334Sjp161948 if (options->remote_forwards[i].listen_host != NULL) 286*5334Sjp161948 xfree(options->remote_forwards[i].listen_host); 287*5334Sjp161948 xfree(options->remote_forwards[i].connect_host); 288*5334Sjp161948 } 2890Sstevel@tonic-gate options->num_remote_forwards = 0; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Returns the number of the token pointed to by cp or oBadOption. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate static OpCodes 2970Sstevel@tonic-gate parse_token(const char *cp, const char *filename, int linenum) 2980Sstevel@tonic-gate { 2990Sstevel@tonic-gate u_int i; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate for (i = 0; keywords[i].name; i++) 3020Sstevel@tonic-gate if (strcasecmp(cp, keywords[i].name) == 0) 3030Sstevel@tonic-gate return keywords[i].opcode; 3040Sstevel@tonic-gate 3055266Sjp161948 debug("%s: line %d: unknown configuration option: %s", 3060Sstevel@tonic-gate filename, linenum, cp); 3070Sstevel@tonic-gate return oBadOption; 3080Sstevel@tonic-gate } 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* 3110Sstevel@tonic-gate * Processes a single option line as used in the configuration files. This 3120Sstevel@tonic-gate * only sets those values that have not already been set. 3130Sstevel@tonic-gate */ 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate int 3160Sstevel@tonic-gate process_config_line(Options *options, const char *host, 3170Sstevel@tonic-gate char *line, const char *filename, int linenum, 3180Sstevel@tonic-gate int *activep) 3190Sstevel@tonic-gate { 320*5334Sjp161948 char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; 3215266Sjp161948 int opcode, *intptr, value, i; 3225266Sjp161948 StoredOption *so; 323*5334Sjp161948 Forward fwd; 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate s = line; 3260Sstevel@tonic-gate /* Get the keyword. (Each line is supposed to begin with a keyword). */ 3270Sstevel@tonic-gate keyword = strdelim(&s); 3280Sstevel@tonic-gate /* Ignore leading whitespace. */ 3290Sstevel@tonic-gate if (*keyword == '\0') 3300Sstevel@tonic-gate keyword = strdelim(&s); 3310Sstevel@tonic-gate if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 3320Sstevel@tonic-gate return 0; 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate opcode = parse_token(keyword, filename, linenum); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate switch (opcode) { 3370Sstevel@tonic-gate case oBadOption: 3385266Sjp161948 if (options->unknown_opts_num == MAX_UNKNOWN_OPTIONS) { 3395266Sjp161948 error("we can't have more than %d unknown options:", 3405266Sjp161948 MAX_UNKNOWN_OPTIONS); 3415266Sjp161948 for (i = 0; i < MAX_UNKNOWN_OPTIONS; ++i) { 3425266Sjp161948 so = &options->unknown_opts[i]; 3435266Sjp161948 error("%s:%d:%s", 3445266Sjp161948 so->filename, so->linenum, so->keyword); 3455266Sjp161948 xfree(so->keyword); 3465266Sjp161948 xfree(so->filename); 3475266Sjp161948 } 3485266Sjp161948 fatal("too many unknown options found, can't continue"); 3495266Sjp161948 } 3505266Sjp161948 3515266Sjp161948 /* unknown options will be processed later */ 3525266Sjp161948 so = &options->unknown_opts[options->unknown_opts_num]; 3535266Sjp161948 so->keyword = xstrdup(keyword); 3545266Sjp161948 so->filename = xstrdup(filename); 3555266Sjp161948 so->linenum = linenum; 3565266Sjp161948 options->unknown_opts_num++; 3575266Sjp161948 return (0); 3585266Sjp161948 3590Sstevel@tonic-gate /* NOTREACHED */ 3603946Sjp161948 case oConnectTimeout: 3613946Sjp161948 intptr = &options->connection_timeout; 3623946Sjp161948 parse_time: 3633946Sjp161948 arg = strdelim(&s); 3643946Sjp161948 if (!arg || *arg == '\0') 3653946Sjp161948 fatal("%s line %d: missing time value.", 3663946Sjp161948 filename, linenum); 3673946Sjp161948 if ((value = convtime(arg)) == -1) 3683946Sjp161948 fatal("%s line %d: invalid time value.", 3693946Sjp161948 filename, linenum); 3703984Sjp161948 if (*activep && *intptr == -1) 3713946Sjp161948 *intptr = value; 3723946Sjp161948 break; 3733946Sjp161948 3740Sstevel@tonic-gate case oForwardAgent: 3750Sstevel@tonic-gate intptr = &options->forward_agent; 3760Sstevel@tonic-gate parse_flag: 3770Sstevel@tonic-gate arg = strdelim(&s); 3780Sstevel@tonic-gate if (!arg || *arg == '\0') 3790Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 3800Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 3810Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 3820Sstevel@tonic-gate value = 1; 3830Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 3840Sstevel@tonic-gate value = 0; 3850Sstevel@tonic-gate else 3860Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 3870Sstevel@tonic-gate if (*activep && *intptr == -1) 3880Sstevel@tonic-gate *intptr = value; 3890Sstevel@tonic-gate break; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate case oForwardX11: 3920Sstevel@tonic-gate intptr = &options->forward_x11; 3930Sstevel@tonic-gate goto parse_flag; 3940Sstevel@tonic-gate 3954907Sjp161948 case oForwardX11Trusted: 3964907Sjp161948 intptr = &options->forward_x11_trusted; 3974907Sjp161948 goto parse_flag; 3984907Sjp161948 3990Sstevel@tonic-gate case oGatewayPorts: 4000Sstevel@tonic-gate intptr = &options->gateway_ports; 4010Sstevel@tonic-gate goto parse_flag; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate case oUsePrivilegedPort: 4040Sstevel@tonic-gate intptr = &options->use_privileged_port; 4050Sstevel@tonic-gate goto parse_flag; 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate case oRhostsAuthentication: 4080Sstevel@tonic-gate intptr = &options->rhosts_authentication; 4090Sstevel@tonic-gate goto parse_flag; 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate case oPasswordAuthentication: 4120Sstevel@tonic-gate intptr = &options->password_authentication; 4130Sstevel@tonic-gate goto parse_flag; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate case oKbdInteractiveAuthentication: 4160Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication; 4170Sstevel@tonic-gate goto parse_flag; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate case oKbdInteractiveDevices: 4200Sstevel@tonic-gate charptr = &options->kbd_interactive_devices; 4210Sstevel@tonic-gate goto parse_string; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate case oPubkeyAuthentication: 4240Sstevel@tonic-gate intptr = &options->pubkey_authentication; 4250Sstevel@tonic-gate goto parse_flag; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate case oRSAAuthentication: 4280Sstevel@tonic-gate intptr = &options->rsa_authentication; 4290Sstevel@tonic-gate goto parse_flag; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate case oRhostsRSAAuthentication: 4320Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication; 4330Sstevel@tonic-gate goto parse_flag; 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate case oHostbasedAuthentication: 4360Sstevel@tonic-gate intptr = &options->hostbased_authentication; 4370Sstevel@tonic-gate goto parse_flag; 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate case oChallengeResponseAuthentication: 4400Sstevel@tonic-gate intptr = &options->challenge_response_authentication; 4410Sstevel@tonic-gate goto parse_flag; 4420Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 4430Sstevel@tonic-gate case oKerberosAuthentication: 4440Sstevel@tonic-gate intptr = &options->kerberos_authentication; 4450Sstevel@tonic-gate goto parse_flag; 4460Sstevel@tonic-gate #endif 4470Sstevel@tonic-gate #ifdef GSSAPI 4480Sstevel@tonic-gate case oGssKeyEx: 4490Sstevel@tonic-gate intptr = &options->gss_keyex; 4500Sstevel@tonic-gate goto parse_flag; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate case oGssAuthentication: 4530Sstevel@tonic-gate intptr = &options->gss_authentication; 4540Sstevel@tonic-gate goto parse_flag; 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate case oGssDelegateCreds: 4570Sstevel@tonic-gate intptr = &options->gss_deleg_creds; 4580Sstevel@tonic-gate goto parse_flag; 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate #ifdef GSI 4610Sstevel@tonic-gate case oGssGlobusDelegateLimitedCreds: 4620Sstevel@tonic-gate intptr = &options->gss_globus_deleg_limited_proxy; 4630Sstevel@tonic-gate goto parse_flag; 4640Sstevel@tonic-gate #endif /* GSI */ 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate #endif /* GSSAPI */ 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 4690Sstevel@tonic-gate case oKerberosTgtPassing: 4700Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing; 4710Sstevel@tonic-gate goto parse_flag; 4720Sstevel@tonic-gate #endif 4730Sstevel@tonic-gate #ifdef AFS 4740Sstevel@tonic-gate case oAFSTokenPassing: 4750Sstevel@tonic-gate intptr = &options->afs_token_passing; 4760Sstevel@tonic-gate goto parse_flag; 4770Sstevel@tonic-gate #endif 4780Sstevel@tonic-gate case oFallBackToRsh: 4790Sstevel@tonic-gate intptr = &options->fallback_to_rsh; 4800Sstevel@tonic-gate goto parse_flag; 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate case oUseRsh: 4830Sstevel@tonic-gate intptr = &options->use_rsh; 4840Sstevel@tonic-gate goto parse_flag; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate case oBatchMode: 4870Sstevel@tonic-gate intptr = &options->batch_mode; 4880Sstevel@tonic-gate goto parse_flag; 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate case oCheckHostIP: 4910Sstevel@tonic-gate intptr = &options->check_host_ip; 4920Sstevel@tonic-gate goto parse_flag; 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate case oStrictHostKeyChecking: 4950Sstevel@tonic-gate intptr = &options->strict_host_key_checking; 4960Sstevel@tonic-gate arg = strdelim(&s); 4970Sstevel@tonic-gate if (!arg || *arg == '\0') 4980Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no/ask argument.", 4990Sstevel@tonic-gate filename, linenum); 5000Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 5010Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 5020Sstevel@tonic-gate value = 1; 5030Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 5040Sstevel@tonic-gate value = 0; 5050Sstevel@tonic-gate else if (strcmp(arg, "ask") == 0) 5060Sstevel@tonic-gate value = 2; 5070Sstevel@tonic-gate else 5080Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 5090Sstevel@tonic-gate if (*activep && *intptr == -1) 5100Sstevel@tonic-gate *intptr = value; 5110Sstevel@tonic-gate break; 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate case oCompression: 5140Sstevel@tonic-gate intptr = &options->compression; 5150Sstevel@tonic-gate goto parse_flag; 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate case oKeepAlives: 5180Sstevel@tonic-gate intptr = &options->keepalives; 5190Sstevel@tonic-gate goto parse_flag; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate case oNoHostAuthenticationForLocalhost: 5220Sstevel@tonic-gate intptr = &options->no_host_authentication_for_localhost; 5230Sstevel@tonic-gate goto parse_flag; 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate case oNumberOfPasswordPrompts: 5260Sstevel@tonic-gate intptr = &options->number_of_password_prompts; 5270Sstevel@tonic-gate goto parse_int; 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate case oCompressionLevel: 5300Sstevel@tonic-gate intptr = &options->compression_level; 5310Sstevel@tonic-gate goto parse_int; 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate case oIdentityFile: 5340Sstevel@tonic-gate arg = strdelim(&s); 5350Sstevel@tonic-gate if (!arg || *arg == '\0') 5360Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5370Sstevel@tonic-gate if (*activep) { 5380Sstevel@tonic-gate intptr = &options->num_identity_files; 5390Sstevel@tonic-gate if (*intptr >= SSH_MAX_IDENTITY_FILES) 5400Sstevel@tonic-gate fatal("%.200s line %d: Too many identity files specified (max %d).", 5410Sstevel@tonic-gate filename, linenum, SSH_MAX_IDENTITY_FILES); 5420Sstevel@tonic-gate charptr = &options->identity_files[*intptr]; 5430Sstevel@tonic-gate *charptr = xstrdup(arg); 5440Sstevel@tonic-gate *intptr = *intptr + 1; 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate break; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate case oXAuthLocation: 5490Sstevel@tonic-gate charptr=&options->xauth_location; 5500Sstevel@tonic-gate goto parse_string; 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate case oUser: 5530Sstevel@tonic-gate charptr = &options->user; 5540Sstevel@tonic-gate parse_string: 5550Sstevel@tonic-gate arg = strdelim(&s); 5560Sstevel@tonic-gate if (!arg || *arg == '\0') 5570Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5580Sstevel@tonic-gate if (*activep && *charptr == NULL) 5590Sstevel@tonic-gate *charptr = xstrdup(arg); 5600Sstevel@tonic-gate break; 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate case oGlobalKnownHostsFile: 5630Sstevel@tonic-gate charptr = &options->system_hostfile; 5640Sstevel@tonic-gate goto parse_string; 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate case oUserKnownHostsFile: 5670Sstevel@tonic-gate charptr = &options->user_hostfile; 5680Sstevel@tonic-gate goto parse_string; 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate case oGlobalKnownHostsFile2: 5710Sstevel@tonic-gate charptr = &options->system_hostfile2; 5720Sstevel@tonic-gate goto parse_string; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate case oUserKnownHostsFile2: 5750Sstevel@tonic-gate charptr = &options->user_hostfile2; 5760Sstevel@tonic-gate goto parse_string; 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate case oHostName: 5790Sstevel@tonic-gate charptr = &options->hostname; 5800Sstevel@tonic-gate goto parse_string; 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate case oHostKeyAlias: 5830Sstevel@tonic-gate charptr = &options->host_key_alias; 5840Sstevel@tonic-gate goto parse_string; 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate case oPreferredAuthentications: 5870Sstevel@tonic-gate charptr = &options->preferred_authentications; 5880Sstevel@tonic-gate goto parse_string; 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate case oBindAddress: 5910Sstevel@tonic-gate charptr = &options->bind_address; 5920Sstevel@tonic-gate goto parse_string; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate case oSmartcardDevice: 5950Sstevel@tonic-gate charptr = &options->smartcard_device; 5960Sstevel@tonic-gate goto parse_string; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate case oProxyCommand: 5990Sstevel@tonic-gate charptr = &options->proxy_command; 6000Sstevel@tonic-gate string = xstrdup(""); 6010Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 6020Sstevel@tonic-gate string = xrealloc(string, strlen(string) + strlen(arg) + 2); 6030Sstevel@tonic-gate strcat(string, " "); 6040Sstevel@tonic-gate strcat(string, arg); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate if (*activep && *charptr == NULL) 6070Sstevel@tonic-gate *charptr = string; 6080Sstevel@tonic-gate else 6090Sstevel@tonic-gate xfree(string); 6100Sstevel@tonic-gate return 0; 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate case oPort: 6130Sstevel@tonic-gate intptr = &options->port; 6140Sstevel@tonic-gate parse_int: 6150Sstevel@tonic-gate arg = strdelim(&s); 6160Sstevel@tonic-gate if (!arg || *arg == '\0') 6170Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6180Sstevel@tonic-gate if (arg[0] < '0' || arg[0] > '9') 6190Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate /* Octal, decimal, or hex format? */ 6220Sstevel@tonic-gate value = strtol(arg, &endofnumber, 0); 6230Sstevel@tonic-gate if (arg == endofnumber) 6240Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 6250Sstevel@tonic-gate if (*activep && *intptr == -1) 6260Sstevel@tonic-gate *intptr = value; 6270Sstevel@tonic-gate break; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate case oConnectionAttempts: 6300Sstevel@tonic-gate intptr = &options->connection_attempts; 6310Sstevel@tonic-gate goto parse_int; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate case oCipher: 6340Sstevel@tonic-gate intptr = &options->cipher; 6350Sstevel@tonic-gate arg = strdelim(&s); 6360Sstevel@tonic-gate if (!arg || *arg == '\0') 6370Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6380Sstevel@tonic-gate value = cipher_number(arg); 6390Sstevel@tonic-gate if (value == -1) 6400Sstevel@tonic-gate fatal("%.200s line %d: Bad cipher '%s'.", 6410Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6420Sstevel@tonic-gate if (*activep && *intptr == -1) 6430Sstevel@tonic-gate *intptr = value; 6440Sstevel@tonic-gate break; 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate case oCiphers: 6470Sstevel@tonic-gate arg = strdelim(&s); 6480Sstevel@tonic-gate if (!arg || *arg == '\0') 6490Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6500Sstevel@tonic-gate if (!ciphers_valid(arg)) 6510Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 6520Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6530Sstevel@tonic-gate if (*activep && options->ciphers == NULL) 6540Sstevel@tonic-gate options->ciphers = xstrdup(arg); 6550Sstevel@tonic-gate break; 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate case oMacs: 6580Sstevel@tonic-gate arg = strdelim(&s); 6590Sstevel@tonic-gate if (!arg || *arg == '\0') 6600Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6610Sstevel@tonic-gate if (!mac_valid(arg)) 6620Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 6630Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6640Sstevel@tonic-gate if (*activep && options->macs == NULL) 6650Sstevel@tonic-gate options->macs = xstrdup(arg); 6660Sstevel@tonic-gate break; 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate case oHostKeyAlgorithms: 6690Sstevel@tonic-gate arg = strdelim(&s); 6700Sstevel@tonic-gate if (!arg || *arg == '\0') 6710Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6720Sstevel@tonic-gate if (!key_names_valid2(arg)) 6730Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 6740Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6750Sstevel@tonic-gate if (*activep && options->hostkeyalgorithms == NULL) 6760Sstevel@tonic-gate options->hostkeyalgorithms = xstrdup(arg); 6770Sstevel@tonic-gate break; 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate case oProtocol: 6800Sstevel@tonic-gate intptr = &options->protocol; 6810Sstevel@tonic-gate arg = strdelim(&s); 6820Sstevel@tonic-gate if (!arg || *arg == '\0') 6830Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6840Sstevel@tonic-gate value = proto_spec(arg); 6850Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN) 6860Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol spec '%s'.", 6870Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6880Sstevel@tonic-gate if (*activep && *intptr == SSH_PROTO_UNKNOWN) 6890Sstevel@tonic-gate *intptr = value; 6900Sstevel@tonic-gate break; 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate case oLogLevel: 6930Sstevel@tonic-gate intptr = (int *) &options->log_level; 6940Sstevel@tonic-gate arg = strdelim(&s); 6950Sstevel@tonic-gate value = log_level_number(arg); 6960Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET) 6970Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'", 6980Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6990Sstevel@tonic-gate if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) 7000Sstevel@tonic-gate *intptr = (LogLevel) value; 7010Sstevel@tonic-gate break; 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate case oLocalForward: 7040Sstevel@tonic-gate case oRemoteForward: 7050Sstevel@tonic-gate arg = strdelim(&s); 706*5334Sjp161948 if (arg == NULL || *arg == '\0') 7070Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 7080Sstevel@tonic-gate filename, linenum); 709*5334Sjp161948 arg2 = strdelim(&s); 710*5334Sjp161948 if (arg2 == NULL || *arg2 == '\0') 711*5334Sjp161948 fatal("%.200s line %d: Missing target argument.", 7120Sstevel@tonic-gate filename, linenum); 713*5334Sjp161948 714*5334Sjp161948 /* construct a string for parse_forward */ 715*5334Sjp161948 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 716*5334Sjp161948 717*5334Sjp161948 if (parse_forward(1, &fwd, fwdarg) == 0) 7180Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding specification.", 7190Sstevel@tonic-gate filename, linenum); 720*5334Sjp161948 7210Sstevel@tonic-gate if (*activep) { 7220Sstevel@tonic-gate if (opcode == oLocalForward) 723*5334Sjp161948 add_local_forward(options, &fwd); 7240Sstevel@tonic-gate else if (opcode == oRemoteForward) 725*5334Sjp161948 add_remote_forward(options, &fwd); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate break; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate case oDynamicForward: 7300Sstevel@tonic-gate arg = strdelim(&s); 7310Sstevel@tonic-gate if (!arg || *arg == '\0') 7320Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 7330Sstevel@tonic-gate filename, linenum); 734*5334Sjp161948 735*5334Sjp161948 if (parse_forward(0, &fwd, arg) == 0) { 736*5334Sjp161948 fatal("%.200s line %d: Bad dynamic forwarding specification.", 7370Sstevel@tonic-gate filename, linenum); 738*5334Sjp161948 } 739*5334Sjp161948 740*5334Sjp161948 if (*activep) { 741*5334Sjp161948 fwd.connect_host = "socks"; 742*5334Sjp161948 add_local_forward(options, &fwd); 743*5334Sjp161948 } 7440Sstevel@tonic-gate break; 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate case oClearAllForwardings: 7470Sstevel@tonic-gate intptr = &options->clear_forwardings; 7480Sstevel@tonic-gate goto parse_flag; 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate case oHost: 7510Sstevel@tonic-gate *activep = 0; 7520Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') 7530Sstevel@tonic-gate if (match_pattern(host, arg)) { 7540Sstevel@tonic-gate debug("Applying options for %.100s", arg); 7550Sstevel@tonic-gate *activep = 1; 7560Sstevel@tonic-gate break; 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate /* Avoid garbage check below, as strdelim is done. */ 7590Sstevel@tonic-gate return 0; 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate case oEscapeChar: 7620Sstevel@tonic-gate intptr = &options->escape_char; 7630Sstevel@tonic-gate arg = strdelim(&s); 7640Sstevel@tonic-gate if (!arg || *arg == '\0') 7650Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 7660Sstevel@tonic-gate if (arg[0] == '^' && arg[2] == 0 && 7670Sstevel@tonic-gate (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 7680Sstevel@tonic-gate value = (u_char) arg[1] & 31; 7690Sstevel@tonic-gate else if (strlen(arg) == 1) 7700Sstevel@tonic-gate value = (u_char) arg[0]; 7710Sstevel@tonic-gate else if (strcmp(arg, "none") == 0) 7720Sstevel@tonic-gate value = SSH_ESCAPECHAR_NONE; 7730Sstevel@tonic-gate else { 7740Sstevel@tonic-gate fatal("%.200s line %d: Bad escape character.", 7750Sstevel@tonic-gate filename, linenum); 7760Sstevel@tonic-gate /* NOTREACHED */ 7770Sstevel@tonic-gate value = 0; /* Avoid compiler warning. */ 7780Sstevel@tonic-gate } 7790Sstevel@tonic-gate if (*activep && *intptr == -1) 7800Sstevel@tonic-gate *intptr = value; 7810Sstevel@tonic-gate break; 7820Sstevel@tonic-gate 7834668Sjp161948 case oServerAliveInterval: 7844668Sjp161948 intptr = &options->server_alive_interval; 7854668Sjp161948 goto parse_time; 7864668Sjp161948 7874668Sjp161948 case oServerAliveCountMax: 7884668Sjp161948 intptr = &options->server_alive_count_max; 7894668Sjp161948 goto parse_int; 7904668Sjp161948 7915243Sjp161948 case oHashKnownHosts: 7925243Sjp161948 intptr = &options->hash_known_hosts; 7935243Sjp161948 goto parse_flag; 7945243Sjp161948 7954958Sjp161948 case oDisableBanner: 7964958Sjp161948 arg = strdelim(&s); 7974958Sjp161948 if (get_yes_no_flag(&options->disable_banner, arg, filename, 7984958Sjp161948 linenum, *activep) == 1) 7994958Sjp161948 break; 8004958Sjp161948 8014958Sjp161948 if (strcmp(arg, "in-exec-mode") == 0) 8024958Sjp161948 options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE; 8034958Sjp161948 else 8044958Sjp161948 fatal("%.200s line %d: Bad yes/no/in-exec-mode " 8054958Sjp161948 "argument.", filename, linenum); 8064958Sjp161948 break; 8074958Sjp161948 8085266Sjp161948 case oIgnoreIfUnknown: 8095266Sjp161948 charptr = &options->ignore_if_unknown; 8105266Sjp161948 goto parse_string; 8115266Sjp161948 8120Sstevel@tonic-gate case oDeprecated: 8130Sstevel@tonic-gate debug("%s line %d: Deprecated option \"%s\"", 8140Sstevel@tonic-gate filename, linenum, keyword); 8150Sstevel@tonic-gate return 0; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate default: 8180Sstevel@tonic-gate fatal("process_config_line: Unimplemented opcode %d", opcode); 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* Check that there is no garbage at end of line. */ 8220Sstevel@tonic-gate if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 8230Sstevel@tonic-gate fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 8240Sstevel@tonic-gate filename, linenum, arg); 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate return 0; 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate /* 8310Sstevel@tonic-gate * Reads the config file and modifies the options accordingly. Options 8320Sstevel@tonic-gate * should already be initialized before this call. This never returns if 8330Sstevel@tonic-gate * there is an error. If the file does not exist, this returns 0. 8340Sstevel@tonic-gate */ 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate int 8370Sstevel@tonic-gate read_config_file(const char *filename, const char *host, Options *options) 8380Sstevel@tonic-gate { 8390Sstevel@tonic-gate FILE *f; 8400Sstevel@tonic-gate char line[1024]; 8410Sstevel@tonic-gate int active, linenum; 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate /* Open the file. */ 8440Sstevel@tonic-gate f = fopen(filename, "r"); 8450Sstevel@tonic-gate if (!f) 8460Sstevel@tonic-gate return 0; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate debug("Reading configuration data %.200s", filename); 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate /* 8510Sstevel@tonic-gate * Mark that we are now processing the options. This flag is turned 8520Sstevel@tonic-gate * on/off by Host specifications. 8530Sstevel@tonic-gate */ 8540Sstevel@tonic-gate active = 1; 8550Sstevel@tonic-gate linenum = 0; 8560Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 8570Sstevel@tonic-gate /* Update line number counter. */ 8580Sstevel@tonic-gate linenum++; 8595266Sjp161948 process_config_line(options, host, line, filename, linenum, &active); 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate fclose(f); 8620Sstevel@tonic-gate return 1; 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate /* 8660Sstevel@tonic-gate * Initializes options to special values that indicate that they have not yet 8670Sstevel@tonic-gate * been set. Read_config_file will only set options with this value. Options 8680Sstevel@tonic-gate * are processed in the following order: command line, user config file, 8690Sstevel@tonic-gate * system config file. Last, fill_default_options is called. 8700Sstevel@tonic-gate */ 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate void 8730Sstevel@tonic-gate initialize_options(Options * options) 8740Sstevel@tonic-gate { 8750Sstevel@tonic-gate memset(options, 'X', sizeof(*options)); 8760Sstevel@tonic-gate options->forward_agent = -1; 8770Sstevel@tonic-gate options->forward_x11 = -1; 8784907Sjp161948 options->forward_x11_trusted = -1; 8790Sstevel@tonic-gate options->xauth_location = NULL; 8800Sstevel@tonic-gate options->gateway_ports = -1; 8810Sstevel@tonic-gate options->use_privileged_port = -1; 8820Sstevel@tonic-gate options->rhosts_authentication = -1; 8830Sstevel@tonic-gate options->rsa_authentication = -1; 8840Sstevel@tonic-gate options->pubkey_authentication = -1; 8850Sstevel@tonic-gate options->challenge_response_authentication = -1; 8860Sstevel@tonic-gate #ifdef GSSAPI 8870Sstevel@tonic-gate options->gss_keyex = -1; 8880Sstevel@tonic-gate options->gss_authentication = -1; 8890Sstevel@tonic-gate options->gss_deleg_creds = -1; 8900Sstevel@tonic-gate #ifdef GSI 8910Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = -1; 8920Sstevel@tonic-gate #endif /* GSI */ 8930Sstevel@tonic-gate #endif /* GSSAPI */ 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 8960Sstevel@tonic-gate options->kerberos_authentication = -1; 8970Sstevel@tonic-gate #endif 8980Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 8990Sstevel@tonic-gate options->kerberos_tgt_passing = -1; 9000Sstevel@tonic-gate #endif 9010Sstevel@tonic-gate #ifdef AFS 9020Sstevel@tonic-gate options->afs_token_passing = -1; 9030Sstevel@tonic-gate #endif 9040Sstevel@tonic-gate options->password_authentication = -1; 9050Sstevel@tonic-gate options->kbd_interactive_authentication = -1; 9060Sstevel@tonic-gate options->kbd_interactive_devices = NULL; 9070Sstevel@tonic-gate options->rhosts_rsa_authentication = -1; 9080Sstevel@tonic-gate options->hostbased_authentication = -1; 9090Sstevel@tonic-gate options->batch_mode = -1; 9100Sstevel@tonic-gate options->check_host_ip = -1; 9110Sstevel@tonic-gate options->strict_host_key_checking = -1; 9120Sstevel@tonic-gate options->compression = -1; 9130Sstevel@tonic-gate options->keepalives = -1; 9140Sstevel@tonic-gate options->compression_level = -1; 9150Sstevel@tonic-gate options->port = -1; 9160Sstevel@tonic-gate options->connection_attempts = -1; 9173946Sjp161948 options->connection_timeout = -1; 9180Sstevel@tonic-gate options->number_of_password_prompts = -1; 9190Sstevel@tonic-gate options->cipher = -1; 9200Sstevel@tonic-gate options->ciphers = NULL; 9210Sstevel@tonic-gate options->macs = NULL; 9220Sstevel@tonic-gate options->hostkeyalgorithms = NULL; 9230Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN; 9240Sstevel@tonic-gate options->num_identity_files = 0; 9250Sstevel@tonic-gate options->hostname = NULL; 9260Sstevel@tonic-gate options->host_key_alias = NULL; 9270Sstevel@tonic-gate options->proxy_command = NULL; 9280Sstevel@tonic-gate options->user = NULL; 9290Sstevel@tonic-gate options->escape_char = -1; 9300Sstevel@tonic-gate options->system_hostfile = NULL; 9310Sstevel@tonic-gate options->user_hostfile = NULL; 9320Sstevel@tonic-gate options->system_hostfile2 = NULL; 9330Sstevel@tonic-gate options->user_hostfile2 = NULL; 9340Sstevel@tonic-gate options->num_local_forwards = 0; 9350Sstevel@tonic-gate options->num_remote_forwards = 0; 9360Sstevel@tonic-gate options->clear_forwardings = -1; 9370Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET; 9380Sstevel@tonic-gate options->preferred_authentications = NULL; 9390Sstevel@tonic-gate options->bind_address = NULL; 9400Sstevel@tonic-gate options->smartcard_device = NULL; 9410Sstevel@tonic-gate options->no_host_authentication_for_localhost = - 1; 9420Sstevel@tonic-gate options->fallback_to_rsh = -1; 9430Sstevel@tonic-gate options->use_rsh = -1; 9444668Sjp161948 options->server_alive_interval = -1; 9454668Sjp161948 options->server_alive_count_max = -1; 9465243Sjp161948 options->hash_known_hosts = -1; 9475266Sjp161948 options->ignore_if_unknown = NULL; 9485266Sjp161948 options->unknown_opts_num = 0; 9494958Sjp161948 options->disable_banner = -1; 9500Sstevel@tonic-gate } 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate /* 9530Sstevel@tonic-gate * Called after processing other sources of option data, this fills those 9540Sstevel@tonic-gate * options for which no value has been specified with their default values. 9550Sstevel@tonic-gate */ 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate void 9580Sstevel@tonic-gate fill_default_options(Options * options) 9590Sstevel@tonic-gate { 9600Sstevel@tonic-gate int len; 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate if (options->forward_agent == -1) 9630Sstevel@tonic-gate options->forward_agent = 0; 9640Sstevel@tonic-gate if (options->forward_x11 == -1) 9650Sstevel@tonic-gate options->forward_x11 = 0; 9664907Sjp161948 /* 9674907Sjp161948 * Unlike OpenSSH, we keep backward compatibility for '-X' option 9684907Sjp161948 * which means that X11 forwarding is trusted by default. 9694907Sjp161948 */ 9704907Sjp161948 if (options->forward_x11_trusted == -1) 9714907Sjp161948 options->forward_x11_trusted = 1; 9720Sstevel@tonic-gate if (options->xauth_location == NULL) 9730Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH; 9740Sstevel@tonic-gate if (options->gateway_ports == -1) 9750Sstevel@tonic-gate options->gateway_ports = 0; 9760Sstevel@tonic-gate if (options->use_privileged_port == -1) 9770Sstevel@tonic-gate options->use_privileged_port = 0; 9780Sstevel@tonic-gate if (options->rhosts_authentication == -1) 9790Sstevel@tonic-gate options->rhosts_authentication = 0; 9800Sstevel@tonic-gate if (options->rsa_authentication == -1) 9810Sstevel@tonic-gate options->rsa_authentication = 1; 9820Sstevel@tonic-gate if (options->pubkey_authentication == -1) 9830Sstevel@tonic-gate options->pubkey_authentication = 1; 9840Sstevel@tonic-gate if (options->challenge_response_authentication == -1) 9850Sstevel@tonic-gate options->challenge_response_authentication = 1; 9860Sstevel@tonic-gate #ifdef GSSAPI 9870Sstevel@tonic-gate if (options->gss_keyex == -1) 9880Sstevel@tonic-gate options->gss_keyex = 1; 9890Sstevel@tonic-gate if (options->gss_authentication == -1) 9900Sstevel@tonic-gate options->gss_authentication = 1; 9910Sstevel@tonic-gate if (options->gss_deleg_creds == -1) 9920Sstevel@tonic-gate options->gss_deleg_creds = 0; 9930Sstevel@tonic-gate #ifdef GSI 9940Sstevel@tonic-gate if (options->gss_globus_deleg_limited_proxy == -1) 9950Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = 0; 9960Sstevel@tonic-gate #endif /* GSI */ 9970Sstevel@tonic-gate #endif /* GSSAPI */ 9980Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 9990Sstevel@tonic-gate if (options->kerberos_authentication == -1) 10000Sstevel@tonic-gate options->kerberos_authentication = 1; 10010Sstevel@tonic-gate #endif 10020Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 10030Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1) 10040Sstevel@tonic-gate options->kerberos_tgt_passing = 1; 10050Sstevel@tonic-gate #endif 10060Sstevel@tonic-gate #ifdef AFS 10070Sstevel@tonic-gate if (options->afs_token_passing == -1) 10080Sstevel@tonic-gate options->afs_token_passing = 1; 10090Sstevel@tonic-gate #endif 10100Sstevel@tonic-gate if (options->password_authentication == -1) 10110Sstevel@tonic-gate options->password_authentication = 1; 10120Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1) 10130Sstevel@tonic-gate options->kbd_interactive_authentication = 1; 10140Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1) 10150Sstevel@tonic-gate options->rhosts_rsa_authentication = 0; 10160Sstevel@tonic-gate if (options->hostbased_authentication == -1) 10170Sstevel@tonic-gate options->hostbased_authentication = 0; 10180Sstevel@tonic-gate if (options->batch_mode == -1) 10190Sstevel@tonic-gate options->batch_mode = 0; 10200Sstevel@tonic-gate if (options->check_host_ip == -1) 10210Sstevel@tonic-gate options->check_host_ip = 1; 10220Sstevel@tonic-gate if (options->strict_host_key_checking == -1) 10230Sstevel@tonic-gate options->strict_host_key_checking = 2; /* 2 is default */ 10240Sstevel@tonic-gate if (options->compression == -1) 10250Sstevel@tonic-gate options->compression = 0; 10260Sstevel@tonic-gate if (options->keepalives == -1) 10270Sstevel@tonic-gate options->keepalives = 1; 10280Sstevel@tonic-gate if (options->compression_level == -1) 10290Sstevel@tonic-gate options->compression_level = 6; 10300Sstevel@tonic-gate if (options->port == -1) 10310Sstevel@tonic-gate options->port = 0; /* Filled in ssh_connect. */ 10320Sstevel@tonic-gate if (options->connection_attempts == -1) 10330Sstevel@tonic-gate options->connection_attempts = 1; 10340Sstevel@tonic-gate if (options->number_of_password_prompts == -1) 10350Sstevel@tonic-gate options->number_of_password_prompts = 3; 10360Sstevel@tonic-gate /* Selected in ssh_login(). */ 10370Sstevel@tonic-gate if (options->cipher == -1) 10380Sstevel@tonic-gate options->cipher = SSH_CIPHER_NOT_SET; 10390Sstevel@tonic-gate /* options->ciphers, default set in myproposals.h */ 10400Sstevel@tonic-gate /* options->macs, default set in myproposals.h */ 10410Sstevel@tonic-gate /* options->hostkeyalgorithms, default set in myproposals.h */ 10420Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN) 10430Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2; 10440Sstevel@tonic-gate if (options->num_identity_files == 0) { 10450Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) { 10460Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 10470Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10480Sstevel@tonic-gate xmalloc(len); 10490Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10500Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 10510Sstevel@tonic-gate } 10520Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) { 10530Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 10540Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10550Sstevel@tonic-gate xmalloc(len); 10560Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10570Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 10600Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10610Sstevel@tonic-gate xmalloc(len); 10620Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10630Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 10640Sstevel@tonic-gate } 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate if (options->escape_char == -1) 10670Sstevel@tonic-gate options->escape_char = '~'; 10680Sstevel@tonic-gate if (options->system_hostfile == NULL) 10690Sstevel@tonic-gate options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 10700Sstevel@tonic-gate if (options->user_hostfile == NULL) 10710Sstevel@tonic-gate options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 10720Sstevel@tonic-gate if (options->system_hostfile2 == NULL) 10730Sstevel@tonic-gate options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 10740Sstevel@tonic-gate if (options->user_hostfile2 == NULL) 10750Sstevel@tonic-gate options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 10760Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET) 10770Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO; 10780Sstevel@tonic-gate if (options->clear_forwardings == 1) 10790Sstevel@tonic-gate clear_forwardings(options); 10800Sstevel@tonic-gate if (options->no_host_authentication_for_localhost == - 1) 10810Sstevel@tonic-gate options->no_host_authentication_for_localhost = 0; 10820Sstevel@tonic-gate if (options->fallback_to_rsh == - 1) 10830Sstevel@tonic-gate options->fallback_to_rsh = 0; 10840Sstevel@tonic-gate if (options->use_rsh == - 1) 10850Sstevel@tonic-gate options->use_rsh = 0; 10864668Sjp161948 if (options->server_alive_interval == -1) 10874668Sjp161948 options->server_alive_interval = 0; 10884668Sjp161948 if (options->server_alive_count_max == -1) 10894668Sjp161948 options->server_alive_count_max = 3; 10905243Sjp161948 if (options->hash_known_hosts == -1) 10915243Sjp161948 options->hash_known_hosts = 0; 10924958Sjp161948 if (options->disable_banner == -1) 10934958Sjp161948 options->disable_banner = 0; 10940Sstevel@tonic-gate /* options->proxy_command should not be set by default */ 10950Sstevel@tonic-gate /* options->user will be set in the main program if appropriate */ 10960Sstevel@tonic-gate /* options->hostname will be set in the main program if appropriate */ 10970Sstevel@tonic-gate /* options->host_key_alias should not be set by default */ 10980Sstevel@tonic-gate /* options->preferred_authentications will be set in ssh */ 10995266Sjp161948 /* options->ignore_if_unknown should not be set by default */ 11000Sstevel@tonic-gate } 11015266Sjp161948 11025266Sjp161948 /* 1103*5334Sjp161948 * Parses a string containing a port forwarding specification of one of the 1104*5334Sjp161948 * two forms, short or long: 1105*5334Sjp161948 * 1106*5334Sjp161948 * [listenhost:]listenport 1107*5334Sjp161948 * [listenhost:]listenport:connecthost:connectport 1108*5334Sjp161948 * 1109*5334Sjp161948 * short forwarding specification is used for dynamic port forwarding and for 1110*5334Sjp161948 * port forwarding cancelation in process_cmdline(). The function returns number 1111*5334Sjp161948 * of arguments parsed or zero on any error. 1112*5334Sjp161948 */ 1113*5334Sjp161948 int 1114*5334Sjp161948 parse_forward(int long_form, Forward *fwd, const char *fwdspec) 1115*5334Sjp161948 { 1116*5334Sjp161948 int i; 1117*5334Sjp161948 char *p, *cp, *fwdarg[5]; 1118*5334Sjp161948 1119*5334Sjp161948 memset(fwd, '\0', sizeof(*fwd)); 1120*5334Sjp161948 1121*5334Sjp161948 cp = p = xstrdup(fwdspec); 1122*5334Sjp161948 1123*5334Sjp161948 /* skip leading spaces */ 1124*5334Sjp161948 while (isspace(*cp)) 1125*5334Sjp161948 cp++; 1126*5334Sjp161948 1127*5334Sjp161948 for (i = 0; i < 5; ++i) 1128*5334Sjp161948 if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1129*5334Sjp161948 break; 1130*5334Sjp161948 1131*5334Sjp161948 if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5)) 1132*5334Sjp161948 goto fail_free; 1133*5334Sjp161948 1134*5334Sjp161948 switch (i) { 1135*5334Sjp161948 case 0: 1136*5334Sjp161948 goto fail_free; 1137*5334Sjp161948 1138*5334Sjp161948 case 1: 1139*5334Sjp161948 fwd->listen_host = NULL; 1140*5334Sjp161948 fwd->listen_port = a2port(fwdarg[0]); 1141*5334Sjp161948 break; 1142*5334Sjp161948 1143*5334Sjp161948 case 2: 1144*5334Sjp161948 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1145*5334Sjp161948 fwd->listen_port = a2port(fwdarg[1]); 1146*5334Sjp161948 break; 1147*5334Sjp161948 1148*5334Sjp161948 case 3: 1149*5334Sjp161948 fwd->listen_host = NULL; 1150*5334Sjp161948 fwd->listen_port = a2port(fwdarg[0]); 1151*5334Sjp161948 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1152*5334Sjp161948 fwd->connect_port = a2port(fwdarg[2]); 1153*5334Sjp161948 break; 1154*5334Sjp161948 1155*5334Sjp161948 case 4: 1156*5334Sjp161948 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1157*5334Sjp161948 fwd->listen_port = a2port(fwdarg[1]); 1158*5334Sjp161948 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1159*5334Sjp161948 fwd->connect_port = a2port(fwdarg[3]); 1160*5334Sjp161948 break; 1161*5334Sjp161948 } 1162*5334Sjp161948 1163*5334Sjp161948 xfree(p); 1164*5334Sjp161948 1165*5334Sjp161948 if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2)) 1166*5334Sjp161948 goto fail_free; 1167*5334Sjp161948 1168*5334Sjp161948 return (i); 1169*5334Sjp161948 1170*5334Sjp161948 fail_free: 1171*5334Sjp161948 if (p != NULL) 1172*5334Sjp161948 xfree(p); 1173*5334Sjp161948 if (fwd->connect_host != NULL) 1174*5334Sjp161948 xfree(fwd->connect_host); 1175*5334Sjp161948 if (fwd->listen_host != NULL) 1176*5334Sjp161948 xfree(fwd->listen_host); 1177*5334Sjp161948 return (0); 1178*5334Sjp161948 } 1179*5334Sjp161948 1180*5334Sjp161948 /* 11815266Sjp161948 * Process previously stored unknown options. When this function is called we 11825266Sjp161948 * already have IgnoreIfUnknown set so finally we can decide whether each 11835266Sjp161948 * unknown option is to be ignored or not. 11845266Sjp161948 */ 11855266Sjp161948 void 11865266Sjp161948 process_unknown_options(Options *options) 11875266Sjp161948 { 11885266Sjp161948 StoredOption *so; 11895266Sjp161948 int m, i, bad_options = 0; 11905266Sjp161948 11915266Sjp161948 /* if there is no unknown option we are done */ 11925266Sjp161948 if (options->unknown_opts_num == 0) 11935266Sjp161948 return; 11945266Sjp161948 11955266Sjp161948 /* 11965266Sjp161948 * Now go through the list of unknown options and report any one that 11975266Sjp161948 * is not explicitly listed in IgnoreIfUnknown option. If at least one 11985266Sjp161948 * such as that is found it's a show stopper. 11995266Sjp161948 */ 12005266Sjp161948 for (i = 0; i < options->unknown_opts_num; ++i) { 12015266Sjp161948 so = &options->unknown_opts[i]; 12025266Sjp161948 if (options->ignore_if_unknown == NULL) 12035266Sjp161948 m = 0; 12045266Sjp161948 else 12055266Sjp161948 m = match_pattern_list(tolowercase(so->keyword), 12065266Sjp161948 options->ignore_if_unknown, 12075266Sjp161948 strlen(options->ignore_if_unknown), 1); 12085266Sjp161948 if (m == 1) { 12095266Sjp161948 debug("%s: line %d: ignoring unknown option: %s", 12105266Sjp161948 so->filename, so->linenum, so->keyword); 12115266Sjp161948 } 12125266Sjp161948 else { 12135266Sjp161948 error("%s: line %d: unknown configuration option: %s", 12145266Sjp161948 so->filename, so->linenum, so->keyword); 12155266Sjp161948 bad_options++; 12165266Sjp161948 } 12175266Sjp161948 xfree(so->keyword); 12185266Sjp161948 xfree(so->filename); 12195266Sjp161948 } 12205266Sjp161948 12215266Sjp161948 /* exit if we found at least one unignored unknown option */ 12225266Sjp161948 if (bad_options > 0) 12235266Sjp161948 fatal("terminating, %d bad configuration option(s)", 12245266Sjp161948 bad_options); 12255266Sjp161948 } 1226