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, 1303946Sjp161948 oFallBackToRsh, oUseRsh, oConnectTimeout, 131*4958Sjp161948 oServerAliveInterval, oServerAliveCountMax, oDisableBanner, 1320Sstevel@tonic-gate 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 }, 221*4958Sjp161948 { "disablebanner", oDisableBanner }, 2220Sstevel@tonic-gate { NULL, oBadOption } 2230Sstevel@tonic-gate }; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * Adds a local TCP/IP port forward to options. Never returns if there is an 2270Sstevel@tonic-gate * error. 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate void 2310Sstevel@tonic-gate add_local_forward(Options *options, u_short port, const char *host, 2320Sstevel@tonic-gate u_short host_port) 2330Sstevel@tonic-gate { 2340Sstevel@tonic-gate Forward *fwd; 2350Sstevel@tonic-gate #ifndef NO_IPPORT_RESERVED_CONCEPT 2360Sstevel@tonic-gate extern uid_t original_real_uid; 2370Sstevel@tonic-gate if (port < IPPORT_RESERVED && original_real_uid != 0) 2380Sstevel@tonic-gate fatal("Privileged ports can only be forwarded by root."); 2390Sstevel@tonic-gate #endif 2400Sstevel@tonic-gate if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2410Sstevel@tonic-gate fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 2420Sstevel@tonic-gate fwd = &options->local_forwards[options->num_local_forwards++]; 2430Sstevel@tonic-gate fwd->port = port; 2440Sstevel@tonic-gate fwd->host = xstrdup(host); 2450Sstevel@tonic-gate fwd->host_port = host_port; 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * Adds a remote TCP/IP port forward to options. Never returns if there is 2500Sstevel@tonic-gate * an error. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate void 2540Sstevel@tonic-gate add_remote_forward(Options *options, u_short port, const char *host, 2550Sstevel@tonic-gate u_short host_port) 2560Sstevel@tonic-gate { 2570Sstevel@tonic-gate Forward *fwd; 2580Sstevel@tonic-gate if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 2590Sstevel@tonic-gate fatal("Too many remote forwards (max %d).", 2600Sstevel@tonic-gate SSH_MAX_FORWARDS_PER_DIRECTION); 2610Sstevel@tonic-gate fwd = &options->remote_forwards[options->num_remote_forwards++]; 2620Sstevel@tonic-gate fwd->port = port; 2630Sstevel@tonic-gate fwd->host = xstrdup(host); 2640Sstevel@tonic-gate fwd->host_port = host_port; 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate static void 2680Sstevel@tonic-gate clear_forwardings(Options *options) 2690Sstevel@tonic-gate { 2700Sstevel@tonic-gate int i; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate for (i = 0; i < options->num_local_forwards; i++) 2730Sstevel@tonic-gate xfree(options->local_forwards[i].host); 2740Sstevel@tonic-gate options->num_local_forwards = 0; 2750Sstevel@tonic-gate for (i = 0; i < options->num_remote_forwards; i++) 2760Sstevel@tonic-gate xfree(options->remote_forwards[i].host); 2770Sstevel@tonic-gate options->num_remote_forwards = 0; 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* 2810Sstevel@tonic-gate * Returns the number of the token pointed to by cp or oBadOption. 2820Sstevel@tonic-gate */ 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate static OpCodes 2850Sstevel@tonic-gate parse_token(const char *cp, const char *filename, int linenum) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate u_int i; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate for (i = 0; keywords[i].name; i++) 2900Sstevel@tonic-gate if (strcasecmp(cp, keywords[i].name) == 0) 2910Sstevel@tonic-gate return keywords[i].opcode; 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate error("%s: line %d: Bad configuration option: %s", 2940Sstevel@tonic-gate filename, linenum, cp); 2950Sstevel@tonic-gate return oBadOption; 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * Processes a single option line as used in the configuration files. This 3000Sstevel@tonic-gate * only sets those values that have not already been set. 3010Sstevel@tonic-gate */ 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate int 3040Sstevel@tonic-gate process_config_line(Options *options, const char *host, 3050Sstevel@tonic-gate char *line, const char *filename, int linenum, 3060Sstevel@tonic-gate int *activep) 3070Sstevel@tonic-gate { 3080Sstevel@tonic-gate char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg; 3090Sstevel@tonic-gate int opcode, *intptr, value; 3100Sstevel@tonic-gate u_short fwd_port, fwd_host_port; 3110Sstevel@tonic-gate char sfwd_host_port[6]; 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate s = line; 3140Sstevel@tonic-gate /* Get the keyword. (Each line is supposed to begin with a keyword). */ 3150Sstevel@tonic-gate keyword = strdelim(&s); 3160Sstevel@tonic-gate /* Ignore leading whitespace. */ 3170Sstevel@tonic-gate if (*keyword == '\0') 3180Sstevel@tonic-gate keyword = strdelim(&s); 3190Sstevel@tonic-gate if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 3200Sstevel@tonic-gate return 0; 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate opcode = parse_token(keyword, filename, linenum); 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate switch (opcode) { 3250Sstevel@tonic-gate case oBadOption: 3260Sstevel@tonic-gate /* don't panic, but count bad options */ 3270Sstevel@tonic-gate return -1; 3280Sstevel@tonic-gate /* NOTREACHED */ 3293946Sjp161948 case oConnectTimeout: 3303946Sjp161948 intptr = &options->connection_timeout; 3313946Sjp161948 parse_time: 3323946Sjp161948 arg = strdelim(&s); 3333946Sjp161948 if (!arg || *arg == '\0') 3343946Sjp161948 fatal("%s line %d: missing time value.", 3353946Sjp161948 filename, linenum); 3363946Sjp161948 if ((value = convtime(arg)) == -1) 3373946Sjp161948 fatal("%s line %d: invalid time value.", 3383946Sjp161948 filename, linenum); 3393984Sjp161948 if (*activep && *intptr == -1) 3403946Sjp161948 *intptr = value; 3413946Sjp161948 break; 3423946Sjp161948 3430Sstevel@tonic-gate case oForwardAgent: 3440Sstevel@tonic-gate intptr = &options->forward_agent; 3450Sstevel@tonic-gate parse_flag: 3460Sstevel@tonic-gate arg = strdelim(&s); 3470Sstevel@tonic-gate if (!arg || *arg == '\0') 3480Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 3490Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 3500Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 3510Sstevel@tonic-gate value = 1; 3520Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 3530Sstevel@tonic-gate value = 0; 3540Sstevel@tonic-gate else 3550Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 3560Sstevel@tonic-gate if (*activep && *intptr == -1) 3570Sstevel@tonic-gate *intptr = value; 3580Sstevel@tonic-gate break; 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate case oForwardX11: 3610Sstevel@tonic-gate intptr = &options->forward_x11; 3620Sstevel@tonic-gate goto parse_flag; 3630Sstevel@tonic-gate 3644907Sjp161948 case oForwardX11Trusted: 3654907Sjp161948 intptr = &options->forward_x11_trusted; 3664907Sjp161948 goto parse_flag; 3674907Sjp161948 3680Sstevel@tonic-gate case oGatewayPorts: 3690Sstevel@tonic-gate intptr = &options->gateway_ports; 3700Sstevel@tonic-gate goto parse_flag; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate case oUsePrivilegedPort: 3730Sstevel@tonic-gate intptr = &options->use_privileged_port; 3740Sstevel@tonic-gate goto parse_flag; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate case oRhostsAuthentication: 3770Sstevel@tonic-gate intptr = &options->rhosts_authentication; 3780Sstevel@tonic-gate goto parse_flag; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate case oPasswordAuthentication: 3810Sstevel@tonic-gate intptr = &options->password_authentication; 3820Sstevel@tonic-gate goto parse_flag; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate case oKbdInteractiveAuthentication: 3850Sstevel@tonic-gate intptr = &options->kbd_interactive_authentication; 3860Sstevel@tonic-gate goto parse_flag; 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate case oKbdInteractiveDevices: 3890Sstevel@tonic-gate charptr = &options->kbd_interactive_devices; 3900Sstevel@tonic-gate goto parse_string; 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate case oPubkeyAuthentication: 3930Sstevel@tonic-gate intptr = &options->pubkey_authentication; 3940Sstevel@tonic-gate goto parse_flag; 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate case oRSAAuthentication: 3970Sstevel@tonic-gate intptr = &options->rsa_authentication; 3980Sstevel@tonic-gate goto parse_flag; 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate case oRhostsRSAAuthentication: 4010Sstevel@tonic-gate intptr = &options->rhosts_rsa_authentication; 4020Sstevel@tonic-gate goto parse_flag; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate case oHostbasedAuthentication: 4050Sstevel@tonic-gate intptr = &options->hostbased_authentication; 4060Sstevel@tonic-gate goto parse_flag; 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate case oChallengeResponseAuthentication: 4090Sstevel@tonic-gate intptr = &options->challenge_response_authentication; 4100Sstevel@tonic-gate goto parse_flag; 4110Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 4120Sstevel@tonic-gate case oKerberosAuthentication: 4130Sstevel@tonic-gate intptr = &options->kerberos_authentication; 4140Sstevel@tonic-gate goto parse_flag; 4150Sstevel@tonic-gate #endif 4160Sstevel@tonic-gate #ifdef GSSAPI 4170Sstevel@tonic-gate case oGssKeyEx: 4180Sstevel@tonic-gate intptr = &options->gss_keyex; 4190Sstevel@tonic-gate goto parse_flag; 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate case oGssAuthentication: 4220Sstevel@tonic-gate intptr = &options->gss_authentication; 4230Sstevel@tonic-gate goto parse_flag; 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate case oGssDelegateCreds: 4260Sstevel@tonic-gate intptr = &options->gss_deleg_creds; 4270Sstevel@tonic-gate goto parse_flag; 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate #ifdef GSI 4300Sstevel@tonic-gate case oGssGlobusDelegateLimitedCreds: 4310Sstevel@tonic-gate intptr = &options->gss_globus_deleg_limited_proxy; 4320Sstevel@tonic-gate goto parse_flag; 4330Sstevel@tonic-gate #endif /* GSI */ 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate #endif /* GSSAPI */ 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 4380Sstevel@tonic-gate case oKerberosTgtPassing: 4390Sstevel@tonic-gate intptr = &options->kerberos_tgt_passing; 4400Sstevel@tonic-gate goto parse_flag; 4410Sstevel@tonic-gate #endif 4420Sstevel@tonic-gate #ifdef AFS 4430Sstevel@tonic-gate case oAFSTokenPassing: 4440Sstevel@tonic-gate intptr = &options->afs_token_passing; 4450Sstevel@tonic-gate goto parse_flag; 4460Sstevel@tonic-gate #endif 4470Sstevel@tonic-gate case oFallBackToRsh: 4480Sstevel@tonic-gate intptr = &options->fallback_to_rsh; 4490Sstevel@tonic-gate goto parse_flag; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate case oUseRsh: 4520Sstevel@tonic-gate intptr = &options->use_rsh; 4530Sstevel@tonic-gate goto parse_flag; 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate case oBatchMode: 4560Sstevel@tonic-gate intptr = &options->batch_mode; 4570Sstevel@tonic-gate goto parse_flag; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate case oCheckHostIP: 4600Sstevel@tonic-gate intptr = &options->check_host_ip; 4610Sstevel@tonic-gate goto parse_flag; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate case oStrictHostKeyChecking: 4640Sstevel@tonic-gate intptr = &options->strict_host_key_checking; 4650Sstevel@tonic-gate arg = strdelim(&s); 4660Sstevel@tonic-gate if (!arg || *arg == '\0') 4670Sstevel@tonic-gate fatal("%.200s line %d: Missing yes/no/ask argument.", 4680Sstevel@tonic-gate filename, linenum); 4690Sstevel@tonic-gate value = 0; /* To avoid compiler warning... */ 4700Sstevel@tonic-gate if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 4710Sstevel@tonic-gate value = 1; 4720Sstevel@tonic-gate else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 4730Sstevel@tonic-gate value = 0; 4740Sstevel@tonic-gate else if (strcmp(arg, "ask") == 0) 4750Sstevel@tonic-gate value = 2; 4760Sstevel@tonic-gate else 4770Sstevel@tonic-gate fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 4780Sstevel@tonic-gate if (*activep && *intptr == -1) 4790Sstevel@tonic-gate *intptr = value; 4800Sstevel@tonic-gate break; 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate case oCompression: 4830Sstevel@tonic-gate intptr = &options->compression; 4840Sstevel@tonic-gate goto parse_flag; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate case oKeepAlives: 4870Sstevel@tonic-gate intptr = &options->keepalives; 4880Sstevel@tonic-gate goto parse_flag; 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate case oNoHostAuthenticationForLocalhost: 4910Sstevel@tonic-gate intptr = &options->no_host_authentication_for_localhost; 4920Sstevel@tonic-gate goto parse_flag; 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate case oNumberOfPasswordPrompts: 4950Sstevel@tonic-gate intptr = &options->number_of_password_prompts; 4960Sstevel@tonic-gate goto parse_int; 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate case oCompressionLevel: 4990Sstevel@tonic-gate intptr = &options->compression_level; 5000Sstevel@tonic-gate goto parse_int; 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate case oIdentityFile: 5030Sstevel@tonic-gate arg = strdelim(&s); 5040Sstevel@tonic-gate if (!arg || *arg == '\0') 5050Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5060Sstevel@tonic-gate if (*activep) { 5070Sstevel@tonic-gate intptr = &options->num_identity_files; 5080Sstevel@tonic-gate if (*intptr >= SSH_MAX_IDENTITY_FILES) 5090Sstevel@tonic-gate fatal("%.200s line %d: Too many identity files specified (max %d).", 5100Sstevel@tonic-gate filename, linenum, SSH_MAX_IDENTITY_FILES); 5110Sstevel@tonic-gate charptr = &options->identity_files[*intptr]; 5120Sstevel@tonic-gate *charptr = xstrdup(arg); 5130Sstevel@tonic-gate *intptr = *intptr + 1; 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate break; 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate case oXAuthLocation: 5180Sstevel@tonic-gate charptr=&options->xauth_location; 5190Sstevel@tonic-gate goto parse_string; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate case oUser: 5220Sstevel@tonic-gate charptr = &options->user; 5230Sstevel@tonic-gate parse_string: 5240Sstevel@tonic-gate arg = strdelim(&s); 5250Sstevel@tonic-gate if (!arg || *arg == '\0') 5260Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5270Sstevel@tonic-gate if (*activep && *charptr == NULL) 5280Sstevel@tonic-gate *charptr = xstrdup(arg); 5290Sstevel@tonic-gate break; 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate case oGlobalKnownHostsFile: 5320Sstevel@tonic-gate charptr = &options->system_hostfile; 5330Sstevel@tonic-gate goto parse_string; 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate case oUserKnownHostsFile: 5360Sstevel@tonic-gate charptr = &options->user_hostfile; 5370Sstevel@tonic-gate goto parse_string; 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate case oGlobalKnownHostsFile2: 5400Sstevel@tonic-gate charptr = &options->system_hostfile2; 5410Sstevel@tonic-gate goto parse_string; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate case oUserKnownHostsFile2: 5440Sstevel@tonic-gate charptr = &options->user_hostfile2; 5450Sstevel@tonic-gate goto parse_string; 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate case oHostName: 5480Sstevel@tonic-gate charptr = &options->hostname; 5490Sstevel@tonic-gate goto parse_string; 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate case oHostKeyAlias: 5520Sstevel@tonic-gate charptr = &options->host_key_alias; 5530Sstevel@tonic-gate goto parse_string; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate case oPreferredAuthentications: 5560Sstevel@tonic-gate charptr = &options->preferred_authentications; 5570Sstevel@tonic-gate goto parse_string; 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate case oBindAddress: 5600Sstevel@tonic-gate charptr = &options->bind_address; 5610Sstevel@tonic-gate goto parse_string; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate case oSmartcardDevice: 5640Sstevel@tonic-gate charptr = &options->smartcard_device; 5650Sstevel@tonic-gate goto parse_string; 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate case oProxyCommand: 5680Sstevel@tonic-gate charptr = &options->proxy_command; 5690Sstevel@tonic-gate string = xstrdup(""); 5700Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 5710Sstevel@tonic-gate string = xrealloc(string, strlen(string) + strlen(arg) + 2); 5720Sstevel@tonic-gate strcat(string, " "); 5730Sstevel@tonic-gate strcat(string, arg); 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate if (*activep && *charptr == NULL) 5760Sstevel@tonic-gate *charptr = string; 5770Sstevel@tonic-gate else 5780Sstevel@tonic-gate xfree(string); 5790Sstevel@tonic-gate return 0; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate case oPort: 5820Sstevel@tonic-gate intptr = &options->port; 5830Sstevel@tonic-gate parse_int: 5840Sstevel@tonic-gate arg = strdelim(&s); 5850Sstevel@tonic-gate if (!arg || *arg == '\0') 5860Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 5870Sstevel@tonic-gate if (arg[0] < '0' || arg[0] > '9') 5880Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* Octal, decimal, or hex format? */ 5910Sstevel@tonic-gate value = strtol(arg, &endofnumber, 0); 5920Sstevel@tonic-gate if (arg == endofnumber) 5930Sstevel@tonic-gate fatal("%.200s line %d: Bad number.", filename, linenum); 5940Sstevel@tonic-gate if (*activep && *intptr == -1) 5950Sstevel@tonic-gate *intptr = value; 5960Sstevel@tonic-gate break; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate case oConnectionAttempts: 5990Sstevel@tonic-gate intptr = &options->connection_attempts; 6000Sstevel@tonic-gate goto parse_int; 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate case oCipher: 6030Sstevel@tonic-gate intptr = &options->cipher; 6040Sstevel@tonic-gate arg = strdelim(&s); 6050Sstevel@tonic-gate if (!arg || *arg == '\0') 6060Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6070Sstevel@tonic-gate value = cipher_number(arg); 6080Sstevel@tonic-gate if (value == -1) 6090Sstevel@tonic-gate fatal("%.200s line %d: Bad cipher '%s'.", 6100Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6110Sstevel@tonic-gate if (*activep && *intptr == -1) 6120Sstevel@tonic-gate *intptr = value; 6130Sstevel@tonic-gate break; 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate case oCiphers: 6160Sstevel@tonic-gate arg = strdelim(&s); 6170Sstevel@tonic-gate if (!arg || *arg == '\0') 6180Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6190Sstevel@tonic-gate if (!ciphers_valid(arg)) 6200Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 6210Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6220Sstevel@tonic-gate if (*activep && options->ciphers == NULL) 6230Sstevel@tonic-gate options->ciphers = xstrdup(arg); 6240Sstevel@tonic-gate break; 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate case oMacs: 6270Sstevel@tonic-gate arg = strdelim(&s); 6280Sstevel@tonic-gate if (!arg || *arg == '\0') 6290Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6300Sstevel@tonic-gate if (!mac_valid(arg)) 6310Sstevel@tonic-gate fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 6320Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6330Sstevel@tonic-gate if (*activep && options->macs == NULL) 6340Sstevel@tonic-gate options->macs = xstrdup(arg); 6350Sstevel@tonic-gate break; 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate case oHostKeyAlgorithms: 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 (!key_names_valid2(arg)) 6420Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 6430Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6440Sstevel@tonic-gate if (*activep && options->hostkeyalgorithms == NULL) 6450Sstevel@tonic-gate options->hostkeyalgorithms = xstrdup(arg); 6460Sstevel@tonic-gate break; 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate case oProtocol: 6490Sstevel@tonic-gate intptr = &options->protocol; 6500Sstevel@tonic-gate arg = strdelim(&s); 6510Sstevel@tonic-gate if (!arg || *arg == '\0') 6520Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 6530Sstevel@tonic-gate value = proto_spec(arg); 6540Sstevel@tonic-gate if (value == SSH_PROTO_UNKNOWN) 6550Sstevel@tonic-gate fatal("%.200s line %d: Bad protocol spec '%s'.", 6560Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6570Sstevel@tonic-gate if (*activep && *intptr == SSH_PROTO_UNKNOWN) 6580Sstevel@tonic-gate *intptr = value; 6590Sstevel@tonic-gate break; 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate case oLogLevel: 6620Sstevel@tonic-gate intptr = (int *) &options->log_level; 6630Sstevel@tonic-gate arg = strdelim(&s); 6640Sstevel@tonic-gate value = log_level_number(arg); 6650Sstevel@tonic-gate if (value == SYSLOG_LEVEL_NOT_SET) 6660Sstevel@tonic-gate fatal("%.200s line %d: unsupported log level '%s'", 6670Sstevel@tonic-gate filename, linenum, arg ? arg : "<NONE>"); 6680Sstevel@tonic-gate if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) 6690Sstevel@tonic-gate *intptr = (LogLevel) value; 6700Sstevel@tonic-gate break; 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate case oLocalForward: 6730Sstevel@tonic-gate case oRemoteForward: 6740Sstevel@tonic-gate arg = strdelim(&s); 6750Sstevel@tonic-gate if (!arg || *arg == '\0') 6760Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 6770Sstevel@tonic-gate filename, linenum); 6780Sstevel@tonic-gate if ((fwd_port = a2port(arg)) == 0) 6790Sstevel@tonic-gate fatal("%.200s line %d: Bad listen port.", 6800Sstevel@tonic-gate filename, linenum); 6810Sstevel@tonic-gate arg = strdelim(&s); 6820Sstevel@tonic-gate if (!arg || *arg == '\0') 6830Sstevel@tonic-gate fatal("%.200s line %d: Missing second argument.", 6840Sstevel@tonic-gate filename, linenum); 6850Sstevel@tonic-gate if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && 6860Sstevel@tonic-gate sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) 6870Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding specification.", 6880Sstevel@tonic-gate filename, linenum); 6890Sstevel@tonic-gate if ((fwd_host_port = a2port(sfwd_host_port)) == 0) 6900Sstevel@tonic-gate fatal("%.200s line %d: Bad forwarding port.", 6910Sstevel@tonic-gate filename, linenum); 6920Sstevel@tonic-gate if (*activep) { 6930Sstevel@tonic-gate if (opcode == oLocalForward) 6940Sstevel@tonic-gate add_local_forward(options, fwd_port, buf, 6950Sstevel@tonic-gate fwd_host_port); 6960Sstevel@tonic-gate else if (opcode == oRemoteForward) 6970Sstevel@tonic-gate add_remote_forward(options, fwd_port, buf, 6980Sstevel@tonic-gate fwd_host_port); 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate break; 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate case oDynamicForward: 7030Sstevel@tonic-gate arg = strdelim(&s); 7040Sstevel@tonic-gate if (!arg || *arg == '\0') 7050Sstevel@tonic-gate fatal("%.200s line %d: Missing port argument.", 7060Sstevel@tonic-gate filename, linenum); 7070Sstevel@tonic-gate fwd_port = a2port(arg); 7080Sstevel@tonic-gate if (fwd_port == 0) 7090Sstevel@tonic-gate fatal("%.200s line %d: Badly formatted port number.", 7100Sstevel@tonic-gate filename, linenum); 7110Sstevel@tonic-gate if (*activep) 7120Sstevel@tonic-gate add_local_forward(options, fwd_port, "socks4", 0); 7130Sstevel@tonic-gate break; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate case oClearAllForwardings: 7160Sstevel@tonic-gate intptr = &options->clear_forwardings; 7170Sstevel@tonic-gate goto parse_flag; 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate case oHost: 7200Sstevel@tonic-gate *activep = 0; 7210Sstevel@tonic-gate while ((arg = strdelim(&s)) != NULL && *arg != '\0') 7220Sstevel@tonic-gate if (match_pattern(host, arg)) { 7230Sstevel@tonic-gate debug("Applying options for %.100s", arg); 7240Sstevel@tonic-gate *activep = 1; 7250Sstevel@tonic-gate break; 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate /* Avoid garbage check below, as strdelim is done. */ 7280Sstevel@tonic-gate return 0; 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate case oEscapeChar: 7310Sstevel@tonic-gate intptr = &options->escape_char; 7320Sstevel@tonic-gate arg = strdelim(&s); 7330Sstevel@tonic-gate if (!arg || *arg == '\0') 7340Sstevel@tonic-gate fatal("%.200s line %d: Missing argument.", filename, linenum); 7350Sstevel@tonic-gate if (arg[0] == '^' && arg[2] == 0 && 7360Sstevel@tonic-gate (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 7370Sstevel@tonic-gate value = (u_char) arg[1] & 31; 7380Sstevel@tonic-gate else if (strlen(arg) == 1) 7390Sstevel@tonic-gate value = (u_char) arg[0]; 7400Sstevel@tonic-gate else if (strcmp(arg, "none") == 0) 7410Sstevel@tonic-gate value = SSH_ESCAPECHAR_NONE; 7420Sstevel@tonic-gate else { 7430Sstevel@tonic-gate fatal("%.200s line %d: Bad escape character.", 7440Sstevel@tonic-gate filename, linenum); 7450Sstevel@tonic-gate /* NOTREACHED */ 7460Sstevel@tonic-gate value = 0; /* Avoid compiler warning. */ 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate if (*activep && *intptr == -1) 7490Sstevel@tonic-gate *intptr = value; 7500Sstevel@tonic-gate break; 7510Sstevel@tonic-gate 7524668Sjp161948 case oServerAliveInterval: 7534668Sjp161948 intptr = &options->server_alive_interval; 7544668Sjp161948 goto parse_time; 7554668Sjp161948 7564668Sjp161948 case oServerAliveCountMax: 7574668Sjp161948 intptr = &options->server_alive_count_max; 7584668Sjp161948 goto parse_int; 7594668Sjp161948 760*4958Sjp161948 case oDisableBanner: 761*4958Sjp161948 arg = strdelim(&s); 762*4958Sjp161948 if (get_yes_no_flag(&options->disable_banner, arg, filename, 763*4958Sjp161948 linenum, *activep) == 1) 764*4958Sjp161948 break; 765*4958Sjp161948 766*4958Sjp161948 if (strcmp(arg, "in-exec-mode") == 0) 767*4958Sjp161948 options->disable_banner = SSH_NO_BANNER_IN_EXEC_MODE; 768*4958Sjp161948 else 769*4958Sjp161948 fatal("%.200s line %d: Bad yes/no/in-exec-mode " 770*4958Sjp161948 "argument.", filename, linenum); 771*4958Sjp161948 break; 772*4958Sjp161948 7730Sstevel@tonic-gate case oDeprecated: 7740Sstevel@tonic-gate debug("%s line %d: Deprecated option \"%s\"", 7750Sstevel@tonic-gate filename, linenum, keyword); 7760Sstevel@tonic-gate return 0; 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate default: 7790Sstevel@tonic-gate fatal("process_config_line: Unimplemented opcode %d", opcode); 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate /* Check that there is no garbage at end of line. */ 7830Sstevel@tonic-gate if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 7840Sstevel@tonic-gate fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 7850Sstevel@tonic-gate filename, linenum, arg); 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate return 0; 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate /* 7920Sstevel@tonic-gate * Reads the config file and modifies the options accordingly. Options 7930Sstevel@tonic-gate * should already be initialized before this call. This never returns if 7940Sstevel@tonic-gate * there is an error. If the file does not exist, this returns 0. 7950Sstevel@tonic-gate */ 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate int 7980Sstevel@tonic-gate read_config_file(const char *filename, const char *host, Options *options) 7990Sstevel@tonic-gate { 8000Sstevel@tonic-gate FILE *f; 8010Sstevel@tonic-gate char line[1024]; 8020Sstevel@tonic-gate int active, linenum; 8030Sstevel@tonic-gate int bad_options = 0; 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate /* Open the file. */ 8060Sstevel@tonic-gate f = fopen(filename, "r"); 8070Sstevel@tonic-gate if (!f) 8080Sstevel@tonic-gate return 0; 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate debug("Reading configuration data %.200s", filename); 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate /* 8130Sstevel@tonic-gate * Mark that we are now processing the options. This flag is turned 8140Sstevel@tonic-gate * on/off by Host specifications. 8150Sstevel@tonic-gate */ 8160Sstevel@tonic-gate active = 1; 8170Sstevel@tonic-gate linenum = 0; 8180Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 8190Sstevel@tonic-gate /* Update line number counter. */ 8200Sstevel@tonic-gate linenum++; 8210Sstevel@tonic-gate if (process_config_line(options, host, line, filename, linenum, &active) != 0) 8220Sstevel@tonic-gate bad_options++; 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate fclose(f); 8250Sstevel@tonic-gate if (bad_options > 0) 8260Sstevel@tonic-gate fatal("%s: terminating, %d bad configuration options", 8270Sstevel@tonic-gate filename, bad_options); 8280Sstevel@tonic-gate return 1; 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate /* 8320Sstevel@tonic-gate * Initializes options to special values that indicate that they have not yet 8330Sstevel@tonic-gate * been set. Read_config_file will only set options with this value. Options 8340Sstevel@tonic-gate * are processed in the following order: command line, user config file, 8350Sstevel@tonic-gate * system config file. Last, fill_default_options is called. 8360Sstevel@tonic-gate */ 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate void 8390Sstevel@tonic-gate initialize_options(Options * options) 8400Sstevel@tonic-gate { 8410Sstevel@tonic-gate memset(options, 'X', sizeof(*options)); 8420Sstevel@tonic-gate options->forward_agent = -1; 8430Sstevel@tonic-gate options->forward_x11 = -1; 8444907Sjp161948 options->forward_x11_trusted = -1; 8450Sstevel@tonic-gate options->xauth_location = NULL; 8460Sstevel@tonic-gate options->gateway_ports = -1; 8470Sstevel@tonic-gate options->use_privileged_port = -1; 8480Sstevel@tonic-gate options->rhosts_authentication = -1; 8490Sstevel@tonic-gate options->rsa_authentication = -1; 8500Sstevel@tonic-gate options->pubkey_authentication = -1; 8510Sstevel@tonic-gate options->challenge_response_authentication = -1; 8520Sstevel@tonic-gate #ifdef GSSAPI 8530Sstevel@tonic-gate options->gss_keyex = -1; 8540Sstevel@tonic-gate options->gss_authentication = -1; 8550Sstevel@tonic-gate options->gss_deleg_creds = -1; 8560Sstevel@tonic-gate #ifdef GSI 8570Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = -1; 8580Sstevel@tonic-gate #endif /* GSI */ 8590Sstevel@tonic-gate #endif /* GSSAPI */ 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 8620Sstevel@tonic-gate options->kerberos_authentication = -1; 8630Sstevel@tonic-gate #endif 8640Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 8650Sstevel@tonic-gate options->kerberos_tgt_passing = -1; 8660Sstevel@tonic-gate #endif 8670Sstevel@tonic-gate #ifdef AFS 8680Sstevel@tonic-gate options->afs_token_passing = -1; 8690Sstevel@tonic-gate #endif 8700Sstevel@tonic-gate options->password_authentication = -1; 8710Sstevel@tonic-gate options->kbd_interactive_authentication = -1; 8720Sstevel@tonic-gate options->kbd_interactive_devices = NULL; 8730Sstevel@tonic-gate options->rhosts_rsa_authentication = -1; 8740Sstevel@tonic-gate options->hostbased_authentication = -1; 8750Sstevel@tonic-gate options->batch_mode = -1; 8760Sstevel@tonic-gate options->check_host_ip = -1; 8770Sstevel@tonic-gate options->strict_host_key_checking = -1; 8780Sstevel@tonic-gate options->compression = -1; 8790Sstevel@tonic-gate options->keepalives = -1; 8800Sstevel@tonic-gate options->compression_level = -1; 8810Sstevel@tonic-gate options->port = -1; 8820Sstevel@tonic-gate options->connection_attempts = -1; 8833946Sjp161948 options->connection_timeout = -1; 8840Sstevel@tonic-gate options->number_of_password_prompts = -1; 8850Sstevel@tonic-gate options->cipher = -1; 8860Sstevel@tonic-gate options->ciphers = NULL; 8870Sstevel@tonic-gate options->macs = NULL; 8880Sstevel@tonic-gate options->hostkeyalgorithms = NULL; 8890Sstevel@tonic-gate options->protocol = SSH_PROTO_UNKNOWN; 8900Sstevel@tonic-gate options->num_identity_files = 0; 8910Sstevel@tonic-gate options->hostname = NULL; 8920Sstevel@tonic-gate options->host_key_alias = NULL; 8930Sstevel@tonic-gate options->proxy_command = NULL; 8940Sstevel@tonic-gate options->user = NULL; 8950Sstevel@tonic-gate options->escape_char = -1; 8960Sstevel@tonic-gate options->system_hostfile = NULL; 8970Sstevel@tonic-gate options->user_hostfile = NULL; 8980Sstevel@tonic-gate options->system_hostfile2 = NULL; 8990Sstevel@tonic-gate options->user_hostfile2 = NULL; 9000Sstevel@tonic-gate options->num_local_forwards = 0; 9010Sstevel@tonic-gate options->num_remote_forwards = 0; 9020Sstevel@tonic-gate options->clear_forwardings = -1; 9030Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_NOT_SET; 9040Sstevel@tonic-gate options->preferred_authentications = NULL; 9050Sstevel@tonic-gate options->bind_address = NULL; 9060Sstevel@tonic-gate options->smartcard_device = NULL; 9070Sstevel@tonic-gate options->no_host_authentication_for_localhost = - 1; 9080Sstevel@tonic-gate options->fallback_to_rsh = -1; 9090Sstevel@tonic-gate options->use_rsh = -1; 9104668Sjp161948 options->server_alive_interval = -1; 9114668Sjp161948 options->server_alive_count_max = -1; 912*4958Sjp161948 options->disable_banner = -1; 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate /* 9160Sstevel@tonic-gate * Called after processing other sources of option data, this fills those 9170Sstevel@tonic-gate * options for which no value has been specified with their default values. 9180Sstevel@tonic-gate */ 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate void 9210Sstevel@tonic-gate fill_default_options(Options * options) 9220Sstevel@tonic-gate { 9230Sstevel@tonic-gate int len; 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate if (options->forward_agent == -1) 9260Sstevel@tonic-gate options->forward_agent = 0; 9270Sstevel@tonic-gate if (options->forward_x11 == -1) 9280Sstevel@tonic-gate options->forward_x11 = 0; 9294907Sjp161948 /* 9304907Sjp161948 * Unlike OpenSSH, we keep backward compatibility for '-X' option 9314907Sjp161948 * which means that X11 forwarding is trusted by default. 9324907Sjp161948 */ 9334907Sjp161948 if (options->forward_x11_trusted == -1) 9344907Sjp161948 options->forward_x11_trusted = 1; 9350Sstevel@tonic-gate if (options->xauth_location == NULL) 9360Sstevel@tonic-gate options->xauth_location = _PATH_XAUTH; 9370Sstevel@tonic-gate if (options->gateway_ports == -1) 9380Sstevel@tonic-gate options->gateway_ports = 0; 9390Sstevel@tonic-gate if (options->use_privileged_port == -1) 9400Sstevel@tonic-gate options->use_privileged_port = 0; 9410Sstevel@tonic-gate if (options->rhosts_authentication == -1) 9420Sstevel@tonic-gate options->rhosts_authentication = 0; 9430Sstevel@tonic-gate if (options->rsa_authentication == -1) 9440Sstevel@tonic-gate options->rsa_authentication = 1; 9450Sstevel@tonic-gate if (options->pubkey_authentication == -1) 9460Sstevel@tonic-gate options->pubkey_authentication = 1; 9470Sstevel@tonic-gate if (options->challenge_response_authentication == -1) 9480Sstevel@tonic-gate options->challenge_response_authentication = 1; 9490Sstevel@tonic-gate #ifdef GSSAPI 9500Sstevel@tonic-gate if (options->gss_keyex == -1) 9510Sstevel@tonic-gate options->gss_keyex = 1; 9520Sstevel@tonic-gate if (options->gss_authentication == -1) 9530Sstevel@tonic-gate options->gss_authentication = 1; 9540Sstevel@tonic-gate if (options->gss_deleg_creds == -1) 9550Sstevel@tonic-gate options->gss_deleg_creds = 0; 9560Sstevel@tonic-gate #ifdef GSI 9570Sstevel@tonic-gate if (options->gss_globus_deleg_limited_proxy == -1) 9580Sstevel@tonic-gate options->gss_globus_deleg_limited_proxy = 0; 9590Sstevel@tonic-gate #endif /* GSI */ 9600Sstevel@tonic-gate #endif /* GSSAPI */ 9610Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 9620Sstevel@tonic-gate if (options->kerberos_authentication == -1) 9630Sstevel@tonic-gate options->kerberos_authentication = 1; 9640Sstevel@tonic-gate #endif 9650Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 9660Sstevel@tonic-gate if (options->kerberos_tgt_passing == -1) 9670Sstevel@tonic-gate options->kerberos_tgt_passing = 1; 9680Sstevel@tonic-gate #endif 9690Sstevel@tonic-gate #ifdef AFS 9700Sstevel@tonic-gate if (options->afs_token_passing == -1) 9710Sstevel@tonic-gate options->afs_token_passing = 1; 9720Sstevel@tonic-gate #endif 9730Sstevel@tonic-gate if (options->password_authentication == -1) 9740Sstevel@tonic-gate options->password_authentication = 1; 9750Sstevel@tonic-gate if (options->kbd_interactive_authentication == -1) 9760Sstevel@tonic-gate options->kbd_interactive_authentication = 1; 9770Sstevel@tonic-gate if (options->rhosts_rsa_authentication == -1) 9780Sstevel@tonic-gate options->rhosts_rsa_authentication = 0; 9790Sstevel@tonic-gate if (options->hostbased_authentication == -1) 9800Sstevel@tonic-gate options->hostbased_authentication = 0; 9810Sstevel@tonic-gate if (options->batch_mode == -1) 9820Sstevel@tonic-gate options->batch_mode = 0; 9830Sstevel@tonic-gate if (options->check_host_ip == -1) 9840Sstevel@tonic-gate options->check_host_ip = 1; 9850Sstevel@tonic-gate if (options->strict_host_key_checking == -1) 9860Sstevel@tonic-gate options->strict_host_key_checking = 2; /* 2 is default */ 9870Sstevel@tonic-gate if (options->compression == -1) 9880Sstevel@tonic-gate options->compression = 0; 9890Sstevel@tonic-gate if (options->keepalives == -1) 9900Sstevel@tonic-gate options->keepalives = 1; 9910Sstevel@tonic-gate if (options->compression_level == -1) 9920Sstevel@tonic-gate options->compression_level = 6; 9930Sstevel@tonic-gate if (options->port == -1) 9940Sstevel@tonic-gate options->port = 0; /* Filled in ssh_connect. */ 9950Sstevel@tonic-gate if (options->connection_attempts == -1) 9960Sstevel@tonic-gate options->connection_attempts = 1; 9970Sstevel@tonic-gate if (options->number_of_password_prompts == -1) 9980Sstevel@tonic-gate options->number_of_password_prompts = 3; 9990Sstevel@tonic-gate /* Selected in ssh_login(). */ 10000Sstevel@tonic-gate if (options->cipher == -1) 10010Sstevel@tonic-gate options->cipher = SSH_CIPHER_NOT_SET; 10020Sstevel@tonic-gate /* options->ciphers, default set in myproposals.h */ 10030Sstevel@tonic-gate /* options->macs, default set in myproposals.h */ 10040Sstevel@tonic-gate /* options->hostkeyalgorithms, default set in myproposals.h */ 10050Sstevel@tonic-gate if (options->protocol == SSH_PROTO_UNKNOWN) 10060Sstevel@tonic-gate options->protocol = SSH_PROTO_1|SSH_PROTO_2; 10070Sstevel@tonic-gate if (options->num_identity_files == 0) { 10080Sstevel@tonic-gate if (options->protocol & SSH_PROTO_1) { 10090Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 10100Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10110Sstevel@tonic-gate xmalloc(len); 10120Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10130Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate if (options->protocol & SSH_PROTO_2) { 10160Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 10170Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10180Sstevel@tonic-gate xmalloc(len); 10190Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10200Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 10230Sstevel@tonic-gate options->identity_files[options->num_identity_files] = 10240Sstevel@tonic-gate xmalloc(len); 10250Sstevel@tonic-gate snprintf(options->identity_files[options->num_identity_files++], 10260Sstevel@tonic-gate len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate if (options->escape_char == -1) 10300Sstevel@tonic-gate options->escape_char = '~'; 10310Sstevel@tonic-gate if (options->system_hostfile == NULL) 10320Sstevel@tonic-gate options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 10330Sstevel@tonic-gate if (options->user_hostfile == NULL) 10340Sstevel@tonic-gate options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 10350Sstevel@tonic-gate if (options->system_hostfile2 == NULL) 10360Sstevel@tonic-gate options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 10370Sstevel@tonic-gate if (options->user_hostfile2 == NULL) 10380Sstevel@tonic-gate options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 10390Sstevel@tonic-gate if (options->log_level == SYSLOG_LEVEL_NOT_SET) 10400Sstevel@tonic-gate options->log_level = SYSLOG_LEVEL_INFO; 10410Sstevel@tonic-gate if (options->clear_forwardings == 1) 10420Sstevel@tonic-gate clear_forwardings(options); 10430Sstevel@tonic-gate if (options->no_host_authentication_for_localhost == - 1) 10440Sstevel@tonic-gate options->no_host_authentication_for_localhost = 0; 10450Sstevel@tonic-gate if (options->fallback_to_rsh == - 1) 10460Sstevel@tonic-gate options->fallback_to_rsh = 0; 10470Sstevel@tonic-gate if (options->use_rsh == - 1) 10480Sstevel@tonic-gate options->use_rsh = 0; 10494668Sjp161948 if (options->server_alive_interval == -1) 10504668Sjp161948 options->server_alive_interval = 0; 10514668Sjp161948 if (options->server_alive_count_max == -1) 10524668Sjp161948 options->server_alive_count_max = 3; 1053*4958Sjp161948 if (options->disable_banner == -1) 1054*4958Sjp161948 options->disable_banner = 0; 10550Sstevel@tonic-gate /* options->proxy_command should not be set by default */ 10560Sstevel@tonic-gate /* options->user will be set in the main program if appropriate */ 10570Sstevel@tonic-gate /* options->hostname will be set in the main program if appropriate */ 10580Sstevel@tonic-gate /* options->host_key_alias should not be set by default */ 10590Sstevel@tonic-gate /* options->preferred_authentications will be set in ssh */ 10600Sstevel@tonic-gate } 1061