readconf.c revision 181111
1181111Sdes/* $OpenBSD: readconf.c,v 1.167 2008/06/26 11:46:31 grunk Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 657429Smarkm * Functions for reading the configuration files. 760576Skris * 865674Skris * As far as I am concerned, the code I have written for this software 965674Skris * can be used freely for any purpose. Any derived versions of this 1065674Skris * software must be clearly marked as such, and if the derived work is 1165674Skris * incompatible with the protocol description in the RFC file, it must be 1265674Skris * called by a name other than "ssh" or "Secure Shell". 1357429Smarkm */ 1457429Smarkm 1557429Smarkm#include "includes.h" 16162856Sdes__RCSID("$FreeBSD: head/crypto/openssh/readconf.c 181111 2008-08-01 02:48:36Z des $"); 1757429Smarkm 18162856Sdes#include <sys/types.h> 19162856Sdes#include <sys/stat.h> 20162856Sdes#include <sys/socket.h> 21162856Sdes 22162856Sdes#include <netinet/in.h> 23162856Sdes 24162856Sdes#include <ctype.h> 25162856Sdes#include <errno.h> 26162856Sdes#include <netdb.h> 27162856Sdes#include <signal.h> 28162856Sdes#include <stdarg.h> 29162856Sdes#include <stdio.h> 30162856Sdes#include <string.h> 31162856Sdes#include <unistd.h> 32162856Sdes 33162856Sdes#include "xmalloc.h" 3457429Smarkm#include "ssh.h" 3576262Sgreen#include "compat.h" 3676262Sgreen#include "cipher.h" 3776262Sgreen#include "pathnames.h" 3876262Sgreen#include "log.h" 39162856Sdes#include "key.h" 4057429Smarkm#include "readconf.h" 4160576Skris#include "match.h" 4276262Sgreen#include "misc.h" 43162856Sdes#include "buffer.h" 4476262Sgreen#include "kex.h" 4576262Sgreen#include "mac.h" 4657429Smarkm 4757429Smarkm/* Format of the configuration file: 4857429Smarkm 4957429Smarkm # Configuration data is parsed as follows: 5057429Smarkm # 1. command line options 5157429Smarkm # 2. user-specific file 5257429Smarkm # 3. system-wide file 5357429Smarkm # Any configuration value is only changed the first time it is set. 5457429Smarkm # Thus, host-specific definitions should be at the beginning of the 5557429Smarkm # configuration file, and defaults at the end. 5657429Smarkm 5757429Smarkm # Host-specific declarations. These may override anything above. A single 5857429Smarkm # host may match multiple declarations; these are processed in the order 5957429Smarkm # that they are given in. 6057429Smarkm 6157429Smarkm Host *.ngs.fi ngs.fi 6298684Sdes User foo 6357429Smarkm 6457429Smarkm Host fake.com 6557429Smarkm HostName another.host.name.real.org 6657429Smarkm User blaah 6757429Smarkm Port 34289 6857429Smarkm ForwardX11 no 6957429Smarkm ForwardAgent no 7057429Smarkm 7157429Smarkm Host books.com 7257429Smarkm RemoteForward 9999 shadows.cs.hut.fi:9999 7357429Smarkm Cipher 3des 7457429Smarkm 7557429Smarkm Host fascist.blob.com 7657429Smarkm Port 23123 7757429Smarkm User tylonen 7857429Smarkm PasswordAuthentication no 7957429Smarkm 8057429Smarkm Host puukko.hut.fi 8157429Smarkm User t35124p 8257429Smarkm ProxyCommand ssh-proxy %h %p 8357429Smarkm 8457429Smarkm Host *.fr 8598684Sdes PublicKeyAuthentication no 8657429Smarkm 8757429Smarkm Host *.su 8857429Smarkm Cipher none 8957429Smarkm PasswordAuthentication no 9057429Smarkm 91157019Sdes Host vpn.fake.com 92157019Sdes Tunnel yes 93157019Sdes TunnelDevice 3 94157019Sdes 9557429Smarkm # Defaults for various options 9657429Smarkm Host * 9757429Smarkm ForwardAgent no 9876262Sgreen ForwardX11 no 9957429Smarkm PasswordAuthentication yes 10057429Smarkm RSAAuthentication yes 10157429Smarkm RhostsRSAAuthentication yes 10257429Smarkm StrictHostKeyChecking yes 103126277Sdes TcpKeepAlive no 10457429Smarkm IdentityFile ~/.ssh/identity 10557429Smarkm Port 22 10657429Smarkm EscapeChar ~ 10757429Smarkm 10857429Smarkm*/ 10957429Smarkm 11057429Smarkm/* Keyword tokens. */ 11157429Smarkm 11257429Smarkmtypedef enum { 11357429Smarkm oBadOption, 114126277Sdes oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, 115162856Sdes oExitOnForwardFailure, 11698684Sdes oPasswordAuthentication, oRSAAuthentication, 11776262Sgreen oChallengeResponseAuthentication, oXAuthLocation, 11857429Smarkm oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 11957429Smarkm oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 12057429Smarkm oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 12157429Smarkm oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 122126277Sdes oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 12376262Sgreen oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 12476262Sgreen oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 12576262Sgreen oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 12676262Sgreen oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 12792559Sdes oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 12893698Sdes oClearAllForwardings, oNoHostAuthenticationForLocalhost, 129124211Sdes oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 130124211Sdes oAddressFamily, oGssAuthentication, oGssDelegateCreds, 131128461Sdes oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 132147005Sdes oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, 133157019Sdes oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 134181111Sdes oVisualHostKey, 13599048Sdes oVersionAddendum, 136124211Sdes oDeprecated, oUnsupported 13757429Smarkm} OpCodes; 13857429Smarkm 13957429Smarkm/* Textual representations of the tokens. */ 14057429Smarkm 14157429Smarkmstatic struct { 14257429Smarkm const char *name; 14357429Smarkm OpCodes opcode; 14457429Smarkm} keywords[] = { 14557429Smarkm { "forwardagent", oForwardAgent }, 14657429Smarkm { "forwardx11", oForwardX11 }, 147126277Sdes { "forwardx11trusted", oForwardX11Trusted }, 148162856Sdes { "exitonforwardfailure", oExitOnForwardFailure }, 14965674Skris { "xauthlocation", oXAuthLocation }, 15057429Smarkm { "gatewayports", oGatewayPorts }, 15157429Smarkm { "useprivilegedport", oUsePrivilegedPort }, 152124211Sdes { "rhostsauthentication", oDeprecated }, 15357429Smarkm { "passwordauthentication", oPasswordAuthentication }, 15469591Sgreen { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 15569591Sgreen { "kbdinteractivedevices", oKbdInteractiveDevices }, 15657429Smarkm { "rsaauthentication", oRSAAuthentication }, 15776262Sgreen { "pubkeyauthentication", oPubkeyAuthentication }, 15876262Sgreen { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 15976262Sgreen { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 16076262Sgreen { "hostbasedauthentication", oHostbasedAuthentication }, 16176262Sgreen { "challengeresponseauthentication", oChallengeResponseAuthentication }, 16276262Sgreen { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 16376262Sgreen { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 164124211Sdes { "kerberosauthentication", oUnsupported }, 165124211Sdes { "kerberostgtpassing", oUnsupported }, 166124211Sdes { "afstokenpassing", oUnsupported }, 167124211Sdes#if defined(GSSAPI) 168124211Sdes { "gssapiauthentication", oGssAuthentication }, 169124211Sdes { "gssapidelegatecredentials", oGssDelegateCreds }, 170124211Sdes#else 171124211Sdes { "gssapiauthentication", oUnsupported }, 172124211Sdes { "gssapidelegatecredentials", oUnsupported }, 17392559Sdes#endif 17498684Sdes { "fallbacktorsh", oDeprecated }, 17598684Sdes { "usersh", oDeprecated }, 17657429Smarkm { "identityfile", oIdentityFile }, 17776262Sgreen { "identityfile2", oIdentityFile }, /* alias */ 178128460Sdes { "identitiesonly", oIdentitiesOnly }, 17957429Smarkm { "hostname", oHostName }, 18076262Sgreen { "hostkeyalias", oHostKeyAlias }, 18157429Smarkm { "proxycommand", oProxyCommand }, 18257429Smarkm { "port", oPort }, 18357429Smarkm { "cipher", oCipher }, 18460576Skris { "ciphers", oCiphers }, 18576262Sgreen { "macs", oMacs }, 18660576Skris { "protocol", oProtocol }, 18757429Smarkm { "remoteforward", oRemoteForward }, 18857429Smarkm { "localforward", oLocalForward }, 18957429Smarkm { "user", oUser }, 19057429Smarkm { "host", oHost }, 19157429Smarkm { "escapechar", oEscapeChar }, 19257429Smarkm { "globalknownhostsfile", oGlobalKnownHostsFile }, 19392559Sdes { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ 19460576Skris { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, 19592559Sdes { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 19657429Smarkm { "connectionattempts", oConnectionAttempts }, 19757429Smarkm { "batchmode", oBatchMode }, 19857429Smarkm { "checkhostip", oCheckHostIP }, 19957429Smarkm { "stricthostkeychecking", oStrictHostKeyChecking }, 20057429Smarkm { "compression", oCompression }, 20157429Smarkm { "compressionlevel", oCompressionLevel }, 202126277Sdes { "tcpkeepalive", oTCPKeepAlive }, 203126277Sdes { "keepalive", oTCPKeepAlive }, /* obsolete */ 20457429Smarkm { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 20557429Smarkm { "loglevel", oLogLevel }, 20676262Sgreen { "dynamicforward", oDynamicForward }, 20776262Sgreen { "preferredauthentications", oPreferredAuthentications }, 20876262Sgreen { "hostkeyalgorithms", oHostKeyAlgorithms }, 20992559Sdes { "bindaddress", oBindAddress }, 210124211Sdes#ifdef SMARTCARD 21192559Sdes { "smartcarddevice", oSmartcardDevice }, 212124211Sdes#else 213124211Sdes { "smartcarddevice", oUnsupported }, 214124211Sdes#endif 21592559Sdes { "clearallforwardings", oClearAllForwardings }, 216113911Sdes { "enablesshkeysign", oEnableSSHKeysign }, 217124211Sdes { "verifyhostkeydns", oVerifyHostKeyDNS }, 21892559Sdes { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 219124211Sdes { "rekeylimit", oRekeyLimit }, 220124211Sdes { "connecttimeout", oConnectTimeout }, 221124211Sdes { "addressfamily", oAddressFamily }, 222126277Sdes { "serveraliveinterval", oServerAliveInterval }, 223126277Sdes { "serveralivecountmax", oServerAliveCountMax }, 224137019Sdes { "sendenv", oSendEnv }, 225137019Sdes { "controlpath", oControlPath }, 226137019Sdes { "controlmaster", oControlMaster }, 227147005Sdes { "hashknownhosts", oHashKnownHosts }, 228157019Sdes { "tunnel", oTunnel }, 229157019Sdes { "tunneldevice", oTunnelDevice }, 230157019Sdes { "localcommand", oLocalCommand }, 231157019Sdes { "permitlocalcommand", oPermitLocalCommand }, 232181111Sdes { "visualhostkey", oVisualHostKey }, 23399048Sdes { "versionaddendum", oVersionAddendum }, 23492559Sdes { NULL, oBadOption } 23557429Smarkm}; 23657429Smarkm 23757429Smarkm/* 23857429Smarkm * Adds a local TCP/IP port forward to options. Never returns if there is an 23957429Smarkm * error. 24057429Smarkm */ 24157429Smarkm 24260576Skrisvoid 243147005Sdesadd_local_forward(Options *options, const Forward *newfwd) 24457429Smarkm{ 24557429Smarkm Forward *fwd; 246106130Sdes#ifndef NO_IPPORT_RESERVED_CONCEPT 24757429Smarkm extern uid_t original_real_uid; 248147005Sdes if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 24976262Sgreen fatal("Privileged ports can only be forwarded by root."); 25098941Sdes#endif 25157429Smarkm if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 25257429Smarkm fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 25357429Smarkm fwd = &options->local_forwards[options->num_local_forwards++]; 254147005Sdes 255147005Sdes fwd->listen_host = (newfwd->listen_host == NULL) ? 256147005Sdes NULL : xstrdup(newfwd->listen_host); 257147005Sdes fwd->listen_port = newfwd->listen_port; 258147005Sdes fwd->connect_host = xstrdup(newfwd->connect_host); 259147005Sdes fwd->connect_port = newfwd->connect_port; 26057429Smarkm} 26157429Smarkm 26257429Smarkm/* 26357429Smarkm * Adds a remote TCP/IP port forward to options. Never returns if there is 26457429Smarkm * an error. 26557429Smarkm */ 26657429Smarkm 26760576Skrisvoid 268147005Sdesadd_remote_forward(Options *options, const Forward *newfwd) 26957429Smarkm{ 27057429Smarkm Forward *fwd; 27157429Smarkm if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 27257429Smarkm fatal("Too many remote forwards (max %d).", 27392559Sdes SSH_MAX_FORWARDS_PER_DIRECTION); 27457429Smarkm fwd = &options->remote_forwards[options->num_remote_forwards++]; 275147005Sdes 276147005Sdes fwd->listen_host = (newfwd->listen_host == NULL) ? 277147005Sdes NULL : xstrdup(newfwd->listen_host); 278147005Sdes fwd->listen_port = newfwd->listen_port; 279147005Sdes fwd->connect_host = xstrdup(newfwd->connect_host); 280147005Sdes fwd->connect_port = newfwd->connect_port; 28157429Smarkm} 28257429Smarkm 28392559Sdesstatic void 28492559Sdesclear_forwardings(Options *options) 28592559Sdes{ 28692559Sdes int i; 28792559Sdes 288147005Sdes for (i = 0; i < options->num_local_forwards; i++) { 289147005Sdes if (options->local_forwards[i].listen_host != NULL) 290147005Sdes xfree(options->local_forwards[i].listen_host); 291147005Sdes xfree(options->local_forwards[i].connect_host); 292147005Sdes } 29392559Sdes options->num_local_forwards = 0; 294147005Sdes for (i = 0; i < options->num_remote_forwards; i++) { 295147005Sdes if (options->remote_forwards[i].listen_host != NULL) 296147005Sdes xfree(options->remote_forwards[i].listen_host); 297147005Sdes xfree(options->remote_forwards[i].connect_host); 298147005Sdes } 29992559Sdes options->num_remote_forwards = 0; 300157019Sdes options->tun_open = SSH_TUNMODE_NO; 30192559Sdes} 30292559Sdes 30357429Smarkm/* 30476262Sgreen * Returns the number of the token pointed to by cp or oBadOption. 30557429Smarkm */ 30657429Smarkm 30760576Skrisstatic OpCodes 30857429Smarkmparse_token(const char *cp, const char *filename, int linenum) 30957429Smarkm{ 31076262Sgreen u_int i; 31157429Smarkm 31257429Smarkm for (i = 0; keywords[i].name; i++) 31357429Smarkm if (strcasecmp(cp, keywords[i].name) == 0) 31457429Smarkm return keywords[i].opcode; 31557429Smarkm 31676262Sgreen error("%s: line %d: Bad configuration option: %s", 31776262Sgreen filename, linenum, cp); 31857429Smarkm return oBadOption; 31957429Smarkm} 32057429Smarkm 32157429Smarkm/* 32257429Smarkm * Processes a single option line as used in the configuration files. This 32357429Smarkm * only sets those values that have not already been set. 32457429Smarkm */ 325113911Sdes#define WHITESPACE " \t\r\n" 32657429Smarkm 32757429Smarkmint 32857429Smarkmprocess_config_line(Options *options, const char *host, 32957429Smarkm char *line, const char *filename, int linenum, 33057429Smarkm int *activep) 33157429Smarkm{ 332147005Sdes char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; 333162856Sdes int opcode, *intptr, value, value2, scale; 334181111Sdes LogLevel *log_level_ptr; 335162856Sdes long long orig, val64; 336113911Sdes size_t len; 337147005Sdes Forward fwd; 33857429Smarkm 339124211Sdes /* Strip trailing whitespace */ 340147005Sdes for (len = strlen(line) - 1; len > 0; len--) { 341124211Sdes if (strchr(WHITESPACE, line[len]) == NULL) 342124211Sdes break; 343124211Sdes line[len] = '\0'; 344124211Sdes } 345124211Sdes 34665674Skris s = line; 34765674Skris /* Get the keyword. (Each line is supposed to begin with a keyword). */ 348162856Sdes if ((keyword = strdelim(&s)) == NULL) 349162856Sdes return 0; 35065674Skris /* Ignore leading whitespace. */ 35165674Skris if (*keyword == '\0') 35265674Skris keyword = strdelim(&s); 35376262Sgreen if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 35457429Smarkm return 0; 35557429Smarkm 35665674Skris opcode = parse_token(keyword, filename, linenum); 35757429Smarkm 35857429Smarkm switch (opcode) { 35957429Smarkm case oBadOption: 36057429Smarkm /* don't panic, but count bad options */ 36157429Smarkm return -1; 36257429Smarkm /* NOTREACHED */ 363124211Sdes case oConnectTimeout: 364124211Sdes intptr = &options->connection_timeout; 365126277Sdesparse_time: 366124211Sdes arg = strdelim(&s); 367124211Sdes if (!arg || *arg == '\0') 368124211Sdes fatal("%s line %d: missing time value.", 369124211Sdes filename, linenum); 370124211Sdes if ((value = convtime(arg)) == -1) 371124211Sdes fatal("%s line %d: invalid time value.", 372124211Sdes filename, linenum); 373181111Sdes if (*activep && *intptr == -1) 374124211Sdes *intptr = value; 375124211Sdes break; 376124211Sdes 37757429Smarkm case oForwardAgent: 37857429Smarkm intptr = &options->forward_agent; 37957429Smarkmparse_flag: 38065674Skris arg = strdelim(&s); 38165674Skris if (!arg || *arg == '\0') 38257429Smarkm fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 38357429Smarkm value = 0; /* To avoid compiler warning... */ 38465674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 38557429Smarkm value = 1; 38665674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 38757429Smarkm value = 0; 38857429Smarkm else 38957429Smarkm fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 39057429Smarkm if (*activep && *intptr == -1) 39157429Smarkm *intptr = value; 39257429Smarkm break; 39357429Smarkm 39457429Smarkm case oForwardX11: 39557429Smarkm intptr = &options->forward_x11; 39657429Smarkm goto parse_flag; 39757429Smarkm 398126277Sdes case oForwardX11Trusted: 399126277Sdes intptr = &options->forward_x11_trusted; 400126277Sdes goto parse_flag; 401126277Sdes 40257429Smarkm case oGatewayPorts: 40357429Smarkm intptr = &options->gateway_ports; 40457429Smarkm goto parse_flag; 40557429Smarkm 406162856Sdes case oExitOnForwardFailure: 407162856Sdes intptr = &options->exit_on_forward_failure; 408162856Sdes goto parse_flag; 409162856Sdes 41057429Smarkm case oUsePrivilegedPort: 41157429Smarkm intptr = &options->use_privileged_port; 41257429Smarkm goto parse_flag; 41357429Smarkm 41457429Smarkm case oPasswordAuthentication: 41557429Smarkm intptr = &options->password_authentication; 41657429Smarkm goto parse_flag; 41757429Smarkm 41869591Sgreen case oKbdInteractiveAuthentication: 41969591Sgreen intptr = &options->kbd_interactive_authentication; 42069591Sgreen goto parse_flag; 42169591Sgreen 42269591Sgreen case oKbdInteractiveDevices: 42369591Sgreen charptr = &options->kbd_interactive_devices; 42469591Sgreen goto parse_string; 42569591Sgreen 42676262Sgreen case oPubkeyAuthentication: 42776262Sgreen intptr = &options->pubkey_authentication; 42860576Skris goto parse_flag; 42960576Skris 43057429Smarkm case oRSAAuthentication: 43157429Smarkm intptr = &options->rsa_authentication; 43257429Smarkm goto parse_flag; 43357429Smarkm 43457429Smarkm case oRhostsRSAAuthentication: 43557429Smarkm intptr = &options->rhosts_rsa_authentication; 43657429Smarkm goto parse_flag; 43757429Smarkm 43876262Sgreen case oHostbasedAuthentication: 43976262Sgreen intptr = &options->hostbased_authentication; 44057429Smarkm goto parse_flag; 44157429Smarkm 44292559Sdes case oChallengeResponseAuthentication: 44392559Sdes intptr = &options->challenge_response_authentication; 44492559Sdes goto parse_flag; 445124211Sdes 446124211Sdes case oGssAuthentication: 447124211Sdes intptr = &options->gss_authentication; 44857429Smarkm goto parse_flag; 449124211Sdes 450124211Sdes case oGssDelegateCreds: 451124211Sdes intptr = &options->gss_deleg_creds; 45276262Sgreen goto parse_flag; 453124211Sdes 45457429Smarkm case oBatchMode: 45557429Smarkm intptr = &options->batch_mode; 45657429Smarkm goto parse_flag; 45757429Smarkm 45857429Smarkm case oCheckHostIP: 45957429Smarkm intptr = &options->check_host_ip; 46057429Smarkm goto parse_flag; 46157429Smarkm 462124211Sdes case oVerifyHostKeyDNS: 463124211Sdes intptr = &options->verify_host_key_dns; 464126277Sdes goto parse_yesnoask; 465124211Sdes 46657429Smarkm case oStrictHostKeyChecking: 46757429Smarkm intptr = &options->strict_host_key_checking; 468126277Sdesparse_yesnoask: 46965674Skris arg = strdelim(&s); 47065674Skris if (!arg || *arg == '\0') 47176262Sgreen fatal("%.200s line %d: Missing yes/no/ask argument.", 47292559Sdes filename, linenum); 47357429Smarkm value = 0; /* To avoid compiler warning... */ 47465674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 47557429Smarkm value = 1; 47665674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 47757429Smarkm value = 0; 47865674Skris else if (strcmp(arg, "ask") == 0) 47957429Smarkm value = 2; 48057429Smarkm else 48157429Smarkm fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 48257429Smarkm if (*activep && *intptr == -1) 48357429Smarkm *intptr = value; 48457429Smarkm break; 48557429Smarkm 48657429Smarkm case oCompression: 48757429Smarkm intptr = &options->compression; 48857429Smarkm goto parse_flag; 48957429Smarkm 490126277Sdes case oTCPKeepAlive: 491126277Sdes intptr = &options->tcp_keep_alive; 49257429Smarkm goto parse_flag; 49357429Smarkm 49492559Sdes case oNoHostAuthenticationForLocalhost: 49592559Sdes intptr = &options->no_host_authentication_for_localhost; 49692559Sdes goto parse_flag; 49792559Sdes 49857429Smarkm case oNumberOfPasswordPrompts: 49957429Smarkm intptr = &options->number_of_password_prompts; 50057429Smarkm goto parse_int; 50157429Smarkm 50257429Smarkm case oCompressionLevel: 50357429Smarkm intptr = &options->compression_level; 50457429Smarkm goto parse_int; 50557429Smarkm 506124211Sdes case oRekeyLimit: 507124211Sdes arg = strdelim(&s); 508124211Sdes if (!arg || *arg == '\0') 509124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 510124211Sdes if (arg[0] < '0' || arg[0] > '9') 511124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 512162856Sdes orig = val64 = strtoll(arg, &endofnumber, 10); 513124211Sdes if (arg == endofnumber) 514124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 515124211Sdes switch (toupper(*endofnumber)) { 516162856Sdes case '\0': 517162856Sdes scale = 1; 518162856Sdes break; 519124211Sdes case 'K': 520162856Sdes scale = 1<<10; 521124211Sdes break; 522124211Sdes case 'M': 523162856Sdes scale = 1<<20; 524124211Sdes break; 525124211Sdes case 'G': 526162856Sdes scale = 1<<30; 527124211Sdes break; 528162856Sdes default: 529162856Sdes fatal("%.200s line %d: Invalid RekeyLimit suffix", 530162856Sdes filename, linenum); 531124211Sdes } 532162856Sdes val64 *= scale; 533162856Sdes /* detect integer wrap and too-large limits */ 534181111Sdes if ((val64 / scale) != orig || val64 > UINT_MAX) 535162856Sdes fatal("%.200s line %d: RekeyLimit too large", 536162856Sdes filename, linenum); 537162856Sdes if (val64 < 16) 538162856Sdes fatal("%.200s line %d: RekeyLimit too small", 539162856Sdes filename, linenum); 540181111Sdes if (*activep && options->rekey_limit == -1) 541181111Sdes options->rekey_limit = (u_int32_t)val64; 542124211Sdes break; 543124211Sdes 54457429Smarkm case oIdentityFile: 54565674Skris arg = strdelim(&s); 54665674Skris if (!arg || *arg == '\0') 54757429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 54857429Smarkm if (*activep) { 54976262Sgreen intptr = &options->num_identity_files; 55060576Skris if (*intptr >= SSH_MAX_IDENTITY_FILES) 55157429Smarkm fatal("%.200s line %d: Too many identity files specified (max %d).", 55292559Sdes filename, linenum, SSH_MAX_IDENTITY_FILES); 553181111Sdes charptr = &options->identity_files[*intptr]; 55465674Skris *charptr = xstrdup(arg); 55560576Skris *intptr = *intptr + 1; 55657429Smarkm } 55757429Smarkm break; 55857429Smarkm 55965674Skris case oXAuthLocation: 56065674Skris charptr=&options->xauth_location; 56165674Skris goto parse_string; 56265674Skris 56357429Smarkm case oUser: 56457429Smarkm charptr = &options->user; 56557429Smarkmparse_string: 56665674Skris arg = strdelim(&s); 56765674Skris if (!arg || *arg == '\0') 56857429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 56957429Smarkm if (*activep && *charptr == NULL) 57065674Skris *charptr = xstrdup(arg); 57157429Smarkm break; 57257429Smarkm 57357429Smarkm case oGlobalKnownHostsFile: 57457429Smarkm charptr = &options->system_hostfile; 57557429Smarkm goto parse_string; 57657429Smarkm 57757429Smarkm case oUserKnownHostsFile: 57857429Smarkm charptr = &options->user_hostfile; 57957429Smarkm goto parse_string; 58057429Smarkm 58160576Skris case oGlobalKnownHostsFile2: 58260576Skris charptr = &options->system_hostfile2; 58360576Skris goto parse_string; 58460576Skris 58560576Skris case oUserKnownHostsFile2: 58660576Skris charptr = &options->user_hostfile2; 58760576Skris goto parse_string; 58860576Skris 58957429Smarkm case oHostName: 59057429Smarkm charptr = &options->hostname; 59157429Smarkm goto parse_string; 59257429Smarkm 59376262Sgreen case oHostKeyAlias: 59476262Sgreen charptr = &options->host_key_alias; 59576262Sgreen goto parse_string; 59676262Sgreen 59776262Sgreen case oPreferredAuthentications: 59876262Sgreen charptr = &options->preferred_authentications; 59976262Sgreen goto parse_string; 60076262Sgreen 60192559Sdes case oBindAddress: 60292559Sdes charptr = &options->bind_address; 60392559Sdes goto parse_string; 60492559Sdes 60592559Sdes case oSmartcardDevice: 60692559Sdes charptr = &options->smartcard_device; 60792559Sdes goto parse_string; 60892559Sdes 60957429Smarkm case oProxyCommand: 610157019Sdes charptr = &options->proxy_command; 611157019Sdesparse_command: 612124211Sdes if (s == NULL) 613124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 614113911Sdes len = strspn(s, WHITESPACE "="); 61557429Smarkm if (*activep && *charptr == NULL) 616113911Sdes *charptr = xstrdup(s + len); 61757429Smarkm return 0; 61857429Smarkm 61957429Smarkm case oPort: 62057429Smarkm intptr = &options->port; 62157429Smarkmparse_int: 62265674Skris arg = strdelim(&s); 62365674Skris if (!arg || *arg == '\0') 62457429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 62565674Skris if (arg[0] < '0' || arg[0] > '9') 62657429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 62757429Smarkm 62857429Smarkm /* Octal, decimal, or hex format? */ 62965674Skris value = strtol(arg, &endofnumber, 0); 63065674Skris if (arg == endofnumber) 63157429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 63257429Smarkm if (*activep && *intptr == -1) 63357429Smarkm *intptr = value; 63457429Smarkm break; 63557429Smarkm 63657429Smarkm case oConnectionAttempts: 63757429Smarkm intptr = &options->connection_attempts; 63857429Smarkm goto parse_int; 63957429Smarkm 64057429Smarkm case oCipher: 64157429Smarkm intptr = &options->cipher; 64265674Skris arg = strdelim(&s); 64365674Skris if (!arg || *arg == '\0') 64461203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 64565674Skris value = cipher_number(arg); 64657429Smarkm if (value == -1) 64757429Smarkm fatal("%.200s line %d: Bad cipher '%s'.", 64892559Sdes filename, linenum, arg ? arg : "<NONE>"); 64957429Smarkm if (*activep && *intptr == -1) 65057429Smarkm *intptr = value; 65157429Smarkm break; 65257429Smarkm 65360576Skris case oCiphers: 65465674Skris arg = strdelim(&s); 65565674Skris if (!arg || *arg == '\0') 65661203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 65765674Skris if (!ciphers_valid(arg)) 65860576Skris fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 65992559Sdes filename, linenum, arg ? arg : "<NONE>"); 66060576Skris if (*activep && options->ciphers == NULL) 66165674Skris options->ciphers = xstrdup(arg); 66260576Skris break; 66360576Skris 66476262Sgreen case oMacs: 66576262Sgreen arg = strdelim(&s); 66676262Sgreen if (!arg || *arg == '\0') 66776262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 66876262Sgreen if (!mac_valid(arg)) 66976262Sgreen fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 67092559Sdes filename, linenum, arg ? arg : "<NONE>"); 67176262Sgreen if (*activep && options->macs == NULL) 67276262Sgreen options->macs = xstrdup(arg); 67376262Sgreen break; 67476262Sgreen 67576262Sgreen case oHostKeyAlgorithms: 67676262Sgreen arg = strdelim(&s); 67776262Sgreen if (!arg || *arg == '\0') 67876262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 67976262Sgreen if (!key_names_valid2(arg)) 68076262Sgreen fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 68192559Sdes filename, linenum, arg ? arg : "<NONE>"); 68276262Sgreen if (*activep && options->hostkeyalgorithms == NULL) 68376262Sgreen options->hostkeyalgorithms = xstrdup(arg); 68476262Sgreen break; 68576262Sgreen 68660576Skris case oProtocol: 68760576Skris intptr = &options->protocol; 68865674Skris arg = strdelim(&s); 68965674Skris if (!arg || *arg == '\0') 69061203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 69165674Skris value = proto_spec(arg); 69260576Skris if (value == SSH_PROTO_UNKNOWN) 69360576Skris fatal("%.200s line %d: Bad protocol spec '%s'.", 69492559Sdes filename, linenum, arg ? arg : "<NONE>"); 69560576Skris if (*activep && *intptr == SSH_PROTO_UNKNOWN) 69660576Skris *intptr = value; 69760576Skris break; 69860576Skris 69957429Smarkm case oLogLevel: 700181111Sdes log_level_ptr = &options->log_level; 70165674Skris arg = strdelim(&s); 70265674Skris value = log_level_number(arg); 70392559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 70476262Sgreen fatal("%.200s line %d: unsupported log level '%s'", 70592559Sdes filename, linenum, arg ? arg : "<NONE>"); 706181111Sdes if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 707181111Sdes *log_level_ptr = (LogLevel) value; 70857429Smarkm break; 70957429Smarkm 71092559Sdes case oLocalForward: 71157429Smarkm case oRemoteForward: 71265674Skris arg = strdelim(&s); 713147005Sdes if (arg == NULL || *arg == '\0') 71492559Sdes fatal("%.200s line %d: Missing port argument.", 71592559Sdes filename, linenum); 716147005Sdes arg2 = strdelim(&s); 717147005Sdes if (arg2 == NULL || *arg2 == '\0') 718147005Sdes fatal("%.200s line %d: Missing target argument.", 71992559Sdes filename, linenum); 720147005Sdes 721147005Sdes /* construct a string for parse_forward */ 722147005Sdes snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 723147005Sdes 724147005Sdes if (parse_forward(&fwd, fwdarg) == 0) 72592559Sdes fatal("%.200s line %d: Bad forwarding specification.", 72692559Sdes filename, linenum); 727147005Sdes 72892559Sdes if (*activep) { 72992559Sdes if (opcode == oLocalForward) 730147005Sdes add_local_forward(options, &fwd); 73192559Sdes else if (opcode == oRemoteForward) 732147005Sdes add_remote_forward(options, &fwd); 73392559Sdes } 73457429Smarkm break; 73557429Smarkm 73676262Sgreen case oDynamicForward: 73776262Sgreen arg = strdelim(&s); 73876262Sgreen if (!arg || *arg == '\0') 73976262Sgreen fatal("%.200s line %d: Missing port argument.", 74076262Sgreen filename, linenum); 741147005Sdes memset(&fwd, '\0', sizeof(fwd)); 742147005Sdes fwd.connect_host = "socks"; 743147005Sdes fwd.listen_host = hpdelim(&arg); 744147005Sdes if (fwd.listen_host == NULL || 745147005Sdes strlen(fwd.listen_host) >= NI_MAXHOST) 746147005Sdes fatal("%.200s line %d: Bad forwarding specification.", 747147005Sdes filename, linenum); 748147005Sdes if (arg) { 749147005Sdes fwd.listen_port = a2port(arg); 750147005Sdes fwd.listen_host = cleanhostname(fwd.listen_host); 751147005Sdes } else { 752147005Sdes fwd.listen_port = a2port(fwd.listen_host); 753149753Sdes fwd.listen_host = NULL; 754147005Sdes } 755147005Sdes if (fwd.listen_port == 0) 75676262Sgreen fatal("%.200s line %d: Badly formatted port number.", 75776262Sgreen filename, linenum); 75892559Sdes if (*activep) 759147005Sdes add_local_forward(options, &fwd); 76076262Sgreen break; 76176262Sgreen 76292559Sdes case oClearAllForwardings: 76392559Sdes intptr = &options->clear_forwardings; 76492559Sdes goto parse_flag; 76592559Sdes 76657429Smarkm case oHost: 76757429Smarkm *activep = 0; 76865674Skris while ((arg = strdelim(&s)) != NULL && *arg != '\0') 76965674Skris if (match_pattern(host, arg)) { 77065674Skris debug("Applying options for %.100s", arg); 77157429Smarkm *activep = 1; 77257429Smarkm break; 77357429Smarkm } 77465674Skris /* Avoid garbage check below, as strdelim is done. */ 77557429Smarkm return 0; 77657429Smarkm 77757429Smarkm case oEscapeChar: 77857429Smarkm intptr = &options->escape_char; 77965674Skris arg = strdelim(&s); 78065674Skris if (!arg || *arg == '\0') 78157429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 78265674Skris if (arg[0] == '^' && arg[2] == 0 && 78376262Sgreen (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 78476262Sgreen value = (u_char) arg[1] & 31; 78565674Skris else if (strlen(arg) == 1) 78676262Sgreen value = (u_char) arg[0]; 78765674Skris else if (strcmp(arg, "none") == 0) 78892559Sdes value = SSH_ESCAPECHAR_NONE; 78957429Smarkm else { 79057429Smarkm fatal("%.200s line %d: Bad escape character.", 79192559Sdes filename, linenum); 79257429Smarkm /* NOTREACHED */ 79357429Smarkm value = 0; /* Avoid compiler warning. */ 79457429Smarkm } 79557429Smarkm if (*activep && *intptr == -1) 79657429Smarkm *intptr = value; 79757429Smarkm break; 79857429Smarkm 799124211Sdes case oAddressFamily: 800124211Sdes arg = strdelim(&s); 801149753Sdes if (!arg || *arg == '\0') 802149753Sdes fatal("%s line %d: missing address family.", 803149753Sdes filename, linenum); 804124211Sdes intptr = &options->address_family; 805124211Sdes if (strcasecmp(arg, "inet") == 0) 806124211Sdes value = AF_INET; 807124211Sdes else if (strcasecmp(arg, "inet6") == 0) 808124211Sdes value = AF_INET6; 809124211Sdes else if (strcasecmp(arg, "any") == 0) 810124211Sdes value = AF_UNSPEC; 811124211Sdes else 812124211Sdes fatal("Unsupported AddressFamily \"%s\"", arg); 813124211Sdes if (*activep && *intptr == -1) 814124211Sdes *intptr = value; 815124211Sdes break; 816124211Sdes 817113911Sdes case oEnableSSHKeysign: 818113911Sdes intptr = &options->enable_ssh_keysign; 819113911Sdes goto parse_flag; 820113911Sdes 821128460Sdes case oIdentitiesOnly: 822128460Sdes intptr = &options->identities_only; 823128460Sdes goto parse_flag; 824128460Sdes 825126277Sdes case oServerAliveInterval: 826126277Sdes intptr = &options->server_alive_interval; 827126277Sdes goto parse_time; 828126277Sdes 829126277Sdes case oServerAliveCountMax: 830126277Sdes intptr = &options->server_alive_count_max; 831126277Sdes goto parse_int; 832126277Sdes 833137019Sdes case oSendEnv: 834137019Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 835137019Sdes if (strchr(arg, '=') != NULL) 836137019Sdes fatal("%s line %d: Invalid environment name.", 837137019Sdes filename, linenum); 838147005Sdes if (!*activep) 839147005Sdes continue; 840137019Sdes if (options->num_send_env >= MAX_SEND_ENV) 841137019Sdes fatal("%s line %d: too many send env.", 842137019Sdes filename, linenum); 843137019Sdes options->send_env[options->num_send_env++] = 844137019Sdes xstrdup(arg); 845137019Sdes } 846137019Sdes break; 847137019Sdes 848137019Sdes case oControlPath: 849137019Sdes charptr = &options->control_path; 850137019Sdes goto parse_string; 851137019Sdes 852137019Sdes case oControlMaster: 853137019Sdes intptr = &options->control_master; 854149753Sdes arg = strdelim(&s); 855149753Sdes if (!arg || *arg == '\0') 856149753Sdes fatal("%.200s line %d: Missing ControlMaster argument.", 857149753Sdes filename, linenum); 858149753Sdes value = 0; /* To avoid compiler warning... */ 859149753Sdes if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 860149753Sdes value = SSHCTL_MASTER_YES; 861149753Sdes else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 862149753Sdes value = SSHCTL_MASTER_NO; 863149753Sdes else if (strcmp(arg, "auto") == 0) 864149753Sdes value = SSHCTL_MASTER_AUTO; 865149753Sdes else if (strcmp(arg, "ask") == 0) 866149753Sdes value = SSHCTL_MASTER_ASK; 867149753Sdes else if (strcmp(arg, "autoask") == 0) 868149753Sdes value = SSHCTL_MASTER_AUTO_ASK; 869149753Sdes else 870149753Sdes fatal("%.200s line %d: Bad ControlMaster argument.", 871149753Sdes filename, linenum); 872149753Sdes if (*activep && *intptr == -1) 873149753Sdes *intptr = value; 874149753Sdes break; 875137019Sdes 876147005Sdes case oHashKnownHosts: 877147005Sdes intptr = &options->hash_known_hosts; 878147005Sdes goto parse_flag; 879147005Sdes 880157019Sdes case oTunnel: 881157019Sdes intptr = &options->tun_open; 882157019Sdes arg = strdelim(&s); 883157019Sdes if (!arg || *arg == '\0') 884157019Sdes fatal("%s line %d: Missing yes/point-to-point/" 885157019Sdes "ethernet/no argument.", filename, linenum); 886157019Sdes value = 0; /* silence compiler */ 887157019Sdes if (strcasecmp(arg, "ethernet") == 0) 888157019Sdes value = SSH_TUNMODE_ETHERNET; 889157019Sdes else if (strcasecmp(arg, "point-to-point") == 0) 890157019Sdes value = SSH_TUNMODE_POINTOPOINT; 891157019Sdes else if (strcasecmp(arg, "yes") == 0) 892157019Sdes value = SSH_TUNMODE_DEFAULT; 893157019Sdes else if (strcasecmp(arg, "no") == 0) 894157019Sdes value = SSH_TUNMODE_NO; 895157019Sdes else 896157019Sdes fatal("%s line %d: Bad yes/point-to-point/ethernet/" 897157019Sdes "no argument: %s", filename, linenum, arg); 898157019Sdes if (*activep) 899157019Sdes *intptr = value; 900157019Sdes break; 901157019Sdes 902157019Sdes case oTunnelDevice: 903157019Sdes arg = strdelim(&s); 904157019Sdes if (!arg || *arg == '\0') 905157019Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 906157019Sdes value = a2tun(arg, &value2); 907157019Sdes if (value == SSH_TUNID_ERR) 908157019Sdes fatal("%.200s line %d: Bad tun device.", filename, linenum); 909157019Sdes if (*activep) { 910157019Sdes options->tun_local = value; 911157019Sdes options->tun_remote = value2; 912157019Sdes } 913157019Sdes break; 914157019Sdes 915157019Sdes case oLocalCommand: 916157019Sdes charptr = &options->local_command; 917157019Sdes goto parse_command; 918157019Sdes 919157019Sdes case oPermitLocalCommand: 920157019Sdes intptr = &options->permit_local_command; 921157019Sdes goto parse_flag; 922157019Sdes 923181111Sdes case oVisualHostKey: 924181111Sdes intptr = &options->visual_host_key; 925181111Sdes goto parse_flag; 926181111Sdes 92799048Sdes case oVersionAddendum: 92899048Sdes ssh_version_set_addendum(strtok(s, "\n")); 92999048Sdes do { 93099048Sdes arg = strdelim(&s); 93199048Sdes } while (arg != NULL && *arg != '\0'); 93299048Sdes break; 93399048Sdes 93498684Sdes case oDeprecated: 93598684Sdes debug("%s line %d: Deprecated option \"%s\"", 93698684Sdes filename, linenum, keyword); 93798684Sdes return 0; 93898684Sdes 939124211Sdes case oUnsupported: 940124211Sdes error("%s line %d: Unsupported option \"%s\"", 941124211Sdes filename, linenum, keyword); 942124211Sdes return 0; 943124211Sdes 94457429Smarkm default: 94557429Smarkm fatal("process_config_line: Unimplemented opcode %d", opcode); 94657429Smarkm } 94757429Smarkm 94857429Smarkm /* Check that there is no garbage at end of line. */ 94976262Sgreen if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 95065674Skris fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 951149753Sdes filename, linenum, arg); 95265674Skris } 95357429Smarkm return 0; 95457429Smarkm} 95557429Smarkm 95657429Smarkm 95757429Smarkm/* 95857429Smarkm * Reads the config file and modifies the options accordingly. Options 95957429Smarkm * should already be initialized before this call. This never returns if 96092559Sdes * there is an error. If the file does not exist, this returns 0. 96157429Smarkm */ 96257429Smarkm 96392559Sdesint 964137019Sdesread_config_file(const char *filename, const char *host, Options *options, 965137019Sdes int checkperm) 96657429Smarkm{ 96757429Smarkm FILE *f; 96857429Smarkm char line[1024]; 96957429Smarkm int active, linenum; 97057429Smarkm int bad_options = 0; 97157429Smarkm 97257429Smarkm /* Open the file. */ 973137019Sdes if ((f = fopen(filename, "r")) == NULL) 97492559Sdes return 0; 97557429Smarkm 976137019Sdes if (checkperm) { 977137019Sdes struct stat sb; 978137019Sdes 979137019Sdes if (fstat(fileno(f), &sb) == -1) 980137019Sdes fatal("fstat %s: %s", filename, strerror(errno)); 981137019Sdes if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 982137019Sdes (sb.st_mode & 022) != 0)) 983137019Sdes fatal("Bad owner or permissions on %s", filename); 984137019Sdes } 985137019Sdes 98657429Smarkm debug("Reading configuration data %.200s", filename); 98757429Smarkm 98857429Smarkm /* 98957429Smarkm * Mark that we are now processing the options. This flag is turned 99057429Smarkm * on/off by Host specifications. 99157429Smarkm */ 99257429Smarkm active = 1; 99357429Smarkm linenum = 0; 99457429Smarkm while (fgets(line, sizeof(line), f)) { 99557429Smarkm /* Update line number counter. */ 99657429Smarkm linenum++; 99757429Smarkm if (process_config_line(options, host, line, filename, linenum, &active) != 0) 99857429Smarkm bad_options++; 99957429Smarkm } 100057429Smarkm fclose(f); 100157429Smarkm if (bad_options > 0) 100276262Sgreen fatal("%s: terminating, %d bad configuration options", 100392559Sdes filename, bad_options); 100492559Sdes return 1; 100557429Smarkm} 100657429Smarkm 100757429Smarkm/* 100857429Smarkm * Initializes options to special values that indicate that they have not yet 100957429Smarkm * been set. Read_config_file will only set options with this value. Options 101057429Smarkm * are processed in the following order: command line, user config file, 101157429Smarkm * system config file. Last, fill_default_options is called. 101257429Smarkm */ 101357429Smarkm 101460576Skrisvoid 101557429Smarkminitialize_options(Options * options) 101657429Smarkm{ 101757429Smarkm memset(options, 'X', sizeof(*options)); 101857429Smarkm options->forward_agent = -1; 101957429Smarkm options->forward_x11 = -1; 1020126277Sdes options->forward_x11_trusted = -1; 1021162856Sdes options->exit_on_forward_failure = -1; 102265674Skris options->xauth_location = NULL; 102357429Smarkm options->gateway_ports = -1; 102457429Smarkm options->use_privileged_port = -1; 102557429Smarkm options->rsa_authentication = -1; 102676262Sgreen options->pubkey_authentication = -1; 102792559Sdes options->challenge_response_authentication = -1; 1028124211Sdes options->gss_authentication = -1; 1029124211Sdes options->gss_deleg_creds = -1; 103057429Smarkm options->password_authentication = -1; 103169591Sgreen options->kbd_interactive_authentication = -1; 103269591Sgreen options->kbd_interactive_devices = NULL; 103357429Smarkm options->rhosts_rsa_authentication = -1; 103476262Sgreen options->hostbased_authentication = -1; 103557429Smarkm options->batch_mode = -1; 103657429Smarkm options->check_host_ip = -1; 103757429Smarkm options->strict_host_key_checking = -1; 103857429Smarkm options->compression = -1; 1039126277Sdes options->tcp_keep_alive = -1; 104057429Smarkm options->compression_level = -1; 104157429Smarkm options->port = -1; 1042124211Sdes options->address_family = -1; 104357429Smarkm options->connection_attempts = -1; 1044124211Sdes options->connection_timeout = -1; 104557429Smarkm options->number_of_password_prompts = -1; 104657429Smarkm options->cipher = -1; 104760576Skris options->ciphers = NULL; 104876262Sgreen options->macs = NULL; 104976262Sgreen options->hostkeyalgorithms = NULL; 105060576Skris options->protocol = SSH_PROTO_UNKNOWN; 105157429Smarkm options->num_identity_files = 0; 105257429Smarkm options->hostname = NULL; 105376262Sgreen options->host_key_alias = NULL; 105457429Smarkm options->proxy_command = NULL; 105557429Smarkm options->user = NULL; 105657429Smarkm options->escape_char = -1; 105757429Smarkm options->system_hostfile = NULL; 105857429Smarkm options->user_hostfile = NULL; 105960576Skris options->system_hostfile2 = NULL; 106060576Skris options->user_hostfile2 = NULL; 106157429Smarkm options->num_local_forwards = 0; 106257429Smarkm options->num_remote_forwards = 0; 106392559Sdes options->clear_forwardings = -1; 106492559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 106576262Sgreen options->preferred_authentications = NULL; 106692559Sdes options->bind_address = NULL; 106792559Sdes options->smartcard_device = NULL; 1068113911Sdes options->enable_ssh_keysign = - 1; 106992559Sdes options->no_host_authentication_for_localhost = - 1; 1070128460Sdes options->identities_only = - 1; 1071124211Sdes options->rekey_limit = - 1; 1072124211Sdes options->verify_host_key_dns = -1; 1073126277Sdes options->server_alive_interval = -1; 1074126277Sdes options->server_alive_count_max = -1; 1075137019Sdes options->num_send_env = 0; 1076137019Sdes options->control_path = NULL; 1077137019Sdes options->control_master = -1; 1078147005Sdes options->hash_known_hosts = -1; 1079157019Sdes options->tun_open = -1; 1080157019Sdes options->tun_local = -1; 1081157019Sdes options->tun_remote = -1; 1082157019Sdes options->local_command = NULL; 1083157019Sdes options->permit_local_command = -1; 1084181111Sdes options->visual_host_key = -1; 108557429Smarkm} 108657429Smarkm 108757429Smarkm/* 108857429Smarkm * Called after processing other sources of option data, this fills those 108957429Smarkm * options for which no value has been specified with their default values. 109057429Smarkm */ 109157429Smarkm 109260576Skrisvoid 109357429Smarkmfill_default_options(Options * options) 109457429Smarkm{ 109576262Sgreen int len; 109676262Sgreen 109757429Smarkm if (options->forward_agent == -1) 109861203Skris options->forward_agent = 0; 109957429Smarkm if (options->forward_x11 == -1) 110057708Sgreen options->forward_x11 = 0; 1101126277Sdes if (options->forward_x11_trusted == -1) 1102126277Sdes options->forward_x11_trusted = 0; 1103162856Sdes if (options->exit_on_forward_failure == -1) 1104162856Sdes options->exit_on_forward_failure = 0; 110565674Skris if (options->xauth_location == NULL) 110692559Sdes options->xauth_location = _PATH_XAUTH; 110757429Smarkm if (options->gateway_ports == -1) 110857429Smarkm options->gateway_ports = 0; 110957429Smarkm if (options->use_privileged_port == -1) 111076262Sgreen options->use_privileged_port = 0; 111157429Smarkm if (options->rsa_authentication == -1) 111257429Smarkm options->rsa_authentication = 1; 111376262Sgreen if (options->pubkey_authentication == -1) 111476262Sgreen options->pubkey_authentication = 1; 111592559Sdes if (options->challenge_response_authentication == -1) 111692559Sdes options->challenge_response_authentication = 1; 1117124211Sdes if (options->gss_authentication == -1) 1118126277Sdes options->gss_authentication = 0; 1119124211Sdes if (options->gss_deleg_creds == -1) 1120124211Sdes options->gss_deleg_creds = 0; 112157429Smarkm if (options->password_authentication == -1) 112257429Smarkm options->password_authentication = 1; 112369591Sgreen if (options->kbd_interactive_authentication == -1) 112476262Sgreen options->kbd_interactive_authentication = 1; 112557429Smarkm if (options->rhosts_rsa_authentication == -1) 112698684Sdes options->rhosts_rsa_authentication = 0; 112776262Sgreen if (options->hostbased_authentication == -1) 112876262Sgreen options->hostbased_authentication = 0; 112957429Smarkm if (options->batch_mode == -1) 113057429Smarkm options->batch_mode = 0; 113157429Smarkm if (options->check_host_ip == -1) 113299048Sdes options->check_host_ip = 0; 113357429Smarkm if (options->strict_host_key_checking == -1) 113457429Smarkm options->strict_host_key_checking = 2; /* 2 is default */ 113557429Smarkm if (options->compression == -1) 113657429Smarkm options->compression = 0; 1137126277Sdes if (options->tcp_keep_alive == -1) 1138126277Sdes options->tcp_keep_alive = 1; 113957429Smarkm if (options->compression_level == -1) 114057429Smarkm options->compression_level = 6; 114157429Smarkm if (options->port == -1) 114257429Smarkm options->port = 0; /* Filled in ssh_connect. */ 1143124211Sdes if (options->address_family == -1) 1144124211Sdes options->address_family = AF_UNSPEC; 114557429Smarkm if (options->connection_attempts == -1) 114692559Sdes options->connection_attempts = 1; 114757429Smarkm if (options->number_of_password_prompts == -1) 114857429Smarkm options->number_of_password_prompts = 3; 114957429Smarkm /* Selected in ssh_login(). */ 115057429Smarkm if (options->cipher == -1) 115157429Smarkm options->cipher = SSH_CIPHER_NOT_SET; 115260576Skris /* options->ciphers, default set in myproposals.h */ 115376262Sgreen /* options->macs, default set in myproposals.h */ 115476262Sgreen /* options->hostkeyalgorithms, default set in myproposals.h */ 115560576Skris if (options->protocol == SSH_PROTO_UNKNOWN) 115676262Sgreen options->protocol = SSH_PROTO_1|SSH_PROTO_2; 115757429Smarkm if (options->num_identity_files == 0) { 115876262Sgreen if (options->protocol & SSH_PROTO_1) { 115976262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 116076262Sgreen options->identity_files[options->num_identity_files] = 116176262Sgreen xmalloc(len); 116276262Sgreen snprintf(options->identity_files[options->num_identity_files++], 116376262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 116476262Sgreen } 116576262Sgreen if (options->protocol & SSH_PROTO_2) { 116676262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 116776262Sgreen options->identity_files[options->num_identity_files] = 116876262Sgreen xmalloc(len); 116976262Sgreen snprintf(options->identity_files[options->num_identity_files++], 117076262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 117176262Sgreen 117276262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 117376262Sgreen options->identity_files[options->num_identity_files] = 117476262Sgreen xmalloc(len); 117576262Sgreen snprintf(options->identity_files[options->num_identity_files++], 117676262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 117776262Sgreen } 117857429Smarkm } 117957429Smarkm if (options->escape_char == -1) 118057429Smarkm options->escape_char = '~'; 118157429Smarkm if (options->system_hostfile == NULL) 118276262Sgreen options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 118357429Smarkm if (options->user_hostfile == NULL) 118476262Sgreen options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 118560576Skris if (options->system_hostfile2 == NULL) 118676262Sgreen options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 118760576Skris if (options->user_hostfile2 == NULL) 118876262Sgreen options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 118992559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 119057429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 119192559Sdes if (options->clear_forwardings == 1) 119292559Sdes clear_forwardings(options); 119392559Sdes if (options->no_host_authentication_for_localhost == - 1) 119492559Sdes options->no_host_authentication_for_localhost = 0; 1195128460Sdes if (options->identities_only == -1) 1196128460Sdes options->identities_only = 0; 1197113911Sdes if (options->enable_ssh_keysign == -1) 1198113911Sdes options->enable_ssh_keysign = 0; 1199124211Sdes if (options->rekey_limit == -1) 1200124211Sdes options->rekey_limit = 0; 1201124211Sdes if (options->verify_host_key_dns == -1) 1202124211Sdes options->verify_host_key_dns = 0; 1203126277Sdes if (options->server_alive_interval == -1) 1204126277Sdes options->server_alive_interval = 0; 1205126277Sdes if (options->server_alive_count_max == -1) 1206126277Sdes options->server_alive_count_max = 3; 1207137019Sdes if (options->control_master == -1) 1208137019Sdes options->control_master = 0; 1209147005Sdes if (options->hash_known_hosts == -1) 1210147005Sdes options->hash_known_hosts = 0; 1211157019Sdes if (options->tun_open == -1) 1212157019Sdes options->tun_open = SSH_TUNMODE_NO; 1213157019Sdes if (options->tun_local == -1) 1214157019Sdes options->tun_local = SSH_TUNID_ANY; 1215157019Sdes if (options->tun_remote == -1) 1216157019Sdes options->tun_remote = SSH_TUNID_ANY; 1217157019Sdes if (options->permit_local_command == -1) 1218157019Sdes options->permit_local_command = 0; 1219181111Sdes if (options->visual_host_key == -1) 1220181111Sdes options->visual_host_key = 0; 1221157019Sdes /* options->local_command should not be set by default */ 122257429Smarkm /* options->proxy_command should not be set by default */ 122357429Smarkm /* options->user will be set in the main program if appropriate */ 122457429Smarkm /* options->hostname will be set in the main program if appropriate */ 122576262Sgreen /* options->host_key_alias should not be set by default */ 122676262Sgreen /* options->preferred_authentications will be set in ssh */ 122757429Smarkm} 1228147005Sdes 1229147005Sdes/* 1230147005Sdes * parse_forward 1231147005Sdes * parses a string containing a port forwarding specification of the form: 1232147005Sdes * [listenhost:]listenport:connecthost:connectport 1233147005Sdes * returns number of arguments parsed or zero on error 1234147005Sdes */ 1235147005Sdesint 1236147005Sdesparse_forward(Forward *fwd, const char *fwdspec) 1237147005Sdes{ 1238147005Sdes int i; 1239147005Sdes char *p, *cp, *fwdarg[4]; 1240147005Sdes 1241147005Sdes memset(fwd, '\0', sizeof(*fwd)); 1242147005Sdes 1243147005Sdes cp = p = xstrdup(fwdspec); 1244147005Sdes 1245147005Sdes /* skip leading spaces */ 1246181111Sdes while (isspace(*cp)) 1247147005Sdes cp++; 1248147005Sdes 1249147005Sdes for (i = 0; i < 4; ++i) 1250147005Sdes if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1251147005Sdes break; 1252147005Sdes 1253147005Sdes /* Check for trailing garbage in 4-arg case*/ 1254147005Sdes if (cp != NULL) 1255147005Sdes i = 0; /* failure */ 1256147005Sdes 1257147005Sdes switch (i) { 1258147005Sdes case 3: 1259147005Sdes fwd->listen_host = NULL; 1260147005Sdes fwd->listen_port = a2port(fwdarg[0]); 1261147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1262147005Sdes fwd->connect_port = a2port(fwdarg[2]); 1263147005Sdes break; 1264147005Sdes 1265147005Sdes case 4: 1266147005Sdes fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1267147005Sdes fwd->listen_port = a2port(fwdarg[1]); 1268147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1269147005Sdes fwd->connect_port = a2port(fwdarg[3]); 1270147005Sdes break; 1271147005Sdes default: 1272147005Sdes i = 0; /* failure */ 1273147005Sdes } 1274147005Sdes 1275147005Sdes xfree(p); 1276147005Sdes 1277181111Sdes if (fwd->listen_port == 0 || fwd->connect_port == 0) 1278147005Sdes goto fail_free; 1279147005Sdes 1280147005Sdes if (fwd->connect_host != NULL && 1281147005Sdes strlen(fwd->connect_host) >= NI_MAXHOST) 1282147005Sdes goto fail_free; 1283147005Sdes 1284147005Sdes return (i); 1285147005Sdes 1286147005Sdes fail_free: 1287147005Sdes if (fwd->connect_host != NULL) 1288147005Sdes xfree(fwd->connect_host); 1289147005Sdes if (fwd->listen_host != NULL) 1290147005Sdes xfree(fwd->listen_host); 1291147005Sdes return (0); 1292147005Sdes} 1293