readconf.c revision 197679
1197679Sdes/* $OpenBSD: readconf.c,v 1.177 2009/06/27 09:35:06 andreas 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 197679 2009-10-01 17:12:52Z des $"); 1757429Smarkm 18162856Sdes#include <sys/types.h> 19162856Sdes#include <sys/stat.h> 20162856Sdes#include <sys/socket.h> 21181918Sdes#include <sys/sysctl.h> 22162856Sdes 23162856Sdes#include <netinet/in.h> 24162856Sdes 25162856Sdes#include <ctype.h> 26162856Sdes#include <errno.h> 27162856Sdes#include <netdb.h> 28162856Sdes#include <signal.h> 29162856Sdes#include <stdarg.h> 30162856Sdes#include <stdio.h> 31162856Sdes#include <string.h> 32162856Sdes#include <unistd.h> 33162856Sdes 34162856Sdes#include "xmalloc.h" 3557429Smarkm#include "ssh.h" 3676262Sgreen#include "compat.h" 3776262Sgreen#include "cipher.h" 3876262Sgreen#include "pathnames.h" 3976262Sgreen#include "log.h" 40162856Sdes#include "key.h" 4157429Smarkm#include "readconf.h" 4260576Skris#include "match.h" 4376262Sgreen#include "misc.h" 44162856Sdes#include "buffer.h" 4576262Sgreen#include "kex.h" 4676262Sgreen#include "mac.h" 47192595Sdes#include "version.h" 4857429Smarkm 4957429Smarkm/* Format of the configuration file: 5057429Smarkm 5157429Smarkm # Configuration data is parsed as follows: 5257429Smarkm # 1. command line options 5357429Smarkm # 2. user-specific file 5457429Smarkm # 3. system-wide file 5557429Smarkm # Any configuration value is only changed the first time it is set. 5657429Smarkm # Thus, host-specific definitions should be at the beginning of the 5757429Smarkm # configuration file, and defaults at the end. 5857429Smarkm 5957429Smarkm # Host-specific declarations. These may override anything above. A single 6057429Smarkm # host may match multiple declarations; these are processed in the order 6157429Smarkm # that they are given in. 6257429Smarkm 6357429Smarkm Host *.ngs.fi ngs.fi 6498684Sdes User foo 6557429Smarkm 6657429Smarkm Host fake.com 6757429Smarkm HostName another.host.name.real.org 6857429Smarkm User blaah 6957429Smarkm Port 34289 7057429Smarkm ForwardX11 no 7157429Smarkm ForwardAgent no 7257429Smarkm 7357429Smarkm Host books.com 7457429Smarkm RemoteForward 9999 shadows.cs.hut.fi:9999 7557429Smarkm Cipher 3des 7657429Smarkm 7757429Smarkm Host fascist.blob.com 7857429Smarkm Port 23123 7957429Smarkm User tylonen 8057429Smarkm PasswordAuthentication no 8157429Smarkm 8257429Smarkm Host puukko.hut.fi 8357429Smarkm User t35124p 8457429Smarkm ProxyCommand ssh-proxy %h %p 8557429Smarkm 8657429Smarkm Host *.fr 8798684Sdes PublicKeyAuthentication no 8857429Smarkm 8957429Smarkm Host *.su 9057429Smarkm Cipher none 9157429Smarkm PasswordAuthentication no 9257429Smarkm 93157019Sdes Host vpn.fake.com 94157019Sdes Tunnel yes 95157019Sdes TunnelDevice 3 96157019Sdes 9757429Smarkm # Defaults for various options 9857429Smarkm Host * 9957429Smarkm ForwardAgent no 10076262Sgreen ForwardX11 no 10157429Smarkm PasswordAuthentication yes 10257429Smarkm RSAAuthentication yes 10357429Smarkm RhostsRSAAuthentication yes 10457429Smarkm StrictHostKeyChecking yes 105126277Sdes TcpKeepAlive no 10657429Smarkm IdentityFile ~/.ssh/identity 10757429Smarkm Port 22 10857429Smarkm EscapeChar ~ 10957429Smarkm 11057429Smarkm*/ 11157429Smarkm 11257429Smarkm/* Keyword tokens. */ 11357429Smarkm 11457429Smarkmtypedef enum { 11557429Smarkm oBadOption, 116126277Sdes oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, 117162856Sdes oExitOnForwardFailure, 11898684Sdes oPasswordAuthentication, oRSAAuthentication, 11976262Sgreen oChallengeResponseAuthentication, oXAuthLocation, 12057429Smarkm oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 12157429Smarkm oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 12257429Smarkm oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 12357429Smarkm oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 124126277Sdes oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, 12576262Sgreen oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 12676262Sgreen oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 12776262Sgreen oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 12876262Sgreen oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 12992559Sdes oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 13093698Sdes oClearAllForwardings, oNoHostAuthenticationForLocalhost, 131124211Sdes oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 132124211Sdes oAddressFamily, oGssAuthentication, oGssDelegateCreds, 133128461Sdes oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 134147005Sdes oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, 135157019Sdes oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 136197679Sdes oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 13799048Sdes oVersionAddendum, 138124211Sdes oDeprecated, oUnsupported 13957429Smarkm} OpCodes; 14057429Smarkm 14157429Smarkm/* Textual representations of the tokens. */ 14257429Smarkm 14357429Smarkmstatic struct { 14457429Smarkm const char *name; 14557429Smarkm OpCodes opcode; 14657429Smarkm} keywords[] = { 14757429Smarkm { "forwardagent", oForwardAgent }, 14857429Smarkm { "forwardx11", oForwardX11 }, 149126277Sdes { "forwardx11trusted", oForwardX11Trusted }, 150162856Sdes { "exitonforwardfailure", oExitOnForwardFailure }, 15165674Skris { "xauthlocation", oXAuthLocation }, 15257429Smarkm { "gatewayports", oGatewayPorts }, 15357429Smarkm { "useprivilegedport", oUsePrivilegedPort }, 154124211Sdes { "rhostsauthentication", oDeprecated }, 15557429Smarkm { "passwordauthentication", oPasswordAuthentication }, 15669591Sgreen { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 15769591Sgreen { "kbdinteractivedevices", oKbdInteractiveDevices }, 15857429Smarkm { "rsaauthentication", oRSAAuthentication }, 15976262Sgreen { "pubkeyauthentication", oPubkeyAuthentication }, 16076262Sgreen { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 16176262Sgreen { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 16276262Sgreen { "hostbasedauthentication", oHostbasedAuthentication }, 16376262Sgreen { "challengeresponseauthentication", oChallengeResponseAuthentication }, 16476262Sgreen { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 16576262Sgreen { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 166124211Sdes { "kerberosauthentication", oUnsupported }, 167124211Sdes { "kerberostgtpassing", oUnsupported }, 168124211Sdes { "afstokenpassing", oUnsupported }, 169124211Sdes#if defined(GSSAPI) 170124211Sdes { "gssapiauthentication", oGssAuthentication }, 171124211Sdes { "gssapidelegatecredentials", oGssDelegateCreds }, 172124211Sdes#else 173124211Sdes { "gssapiauthentication", oUnsupported }, 174124211Sdes { "gssapidelegatecredentials", oUnsupported }, 17592559Sdes#endif 17698684Sdes { "fallbacktorsh", oDeprecated }, 17798684Sdes { "usersh", oDeprecated }, 17857429Smarkm { "identityfile", oIdentityFile }, 179192595Sdes { "identityfile2", oIdentityFile }, /* obsolete */ 180128460Sdes { "identitiesonly", oIdentitiesOnly }, 18157429Smarkm { "hostname", oHostName }, 18276262Sgreen { "hostkeyalias", oHostKeyAlias }, 18357429Smarkm { "proxycommand", oProxyCommand }, 18457429Smarkm { "port", oPort }, 18557429Smarkm { "cipher", oCipher }, 18660576Skris { "ciphers", oCiphers }, 18776262Sgreen { "macs", oMacs }, 18860576Skris { "protocol", oProtocol }, 18957429Smarkm { "remoteforward", oRemoteForward }, 19057429Smarkm { "localforward", oLocalForward }, 19157429Smarkm { "user", oUser }, 19257429Smarkm { "host", oHost }, 19357429Smarkm { "escapechar", oEscapeChar }, 19457429Smarkm { "globalknownhostsfile", oGlobalKnownHostsFile }, 195192595Sdes { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */ 196192595Sdes { "userknownhostsfile", oUserKnownHostsFile }, 19792559Sdes { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 19857429Smarkm { "connectionattempts", oConnectionAttempts }, 19957429Smarkm { "batchmode", oBatchMode }, 20057429Smarkm { "checkhostip", oCheckHostIP }, 20157429Smarkm { "stricthostkeychecking", oStrictHostKeyChecking }, 20257429Smarkm { "compression", oCompression }, 20357429Smarkm { "compressionlevel", oCompressionLevel }, 204126277Sdes { "tcpkeepalive", oTCPKeepAlive }, 205126277Sdes { "keepalive", oTCPKeepAlive }, /* obsolete */ 20657429Smarkm { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 20757429Smarkm { "loglevel", oLogLevel }, 20876262Sgreen { "dynamicforward", oDynamicForward }, 20976262Sgreen { "preferredauthentications", oPreferredAuthentications }, 21076262Sgreen { "hostkeyalgorithms", oHostKeyAlgorithms }, 21192559Sdes { "bindaddress", oBindAddress }, 212124211Sdes#ifdef SMARTCARD 21392559Sdes { "smartcarddevice", oSmartcardDevice }, 214124211Sdes#else 215124211Sdes { "smartcarddevice", oUnsupported }, 216124211Sdes#endif 21792559Sdes { "clearallforwardings", oClearAllForwardings }, 218113911Sdes { "enablesshkeysign", oEnableSSHKeysign }, 219124211Sdes { "verifyhostkeydns", oVerifyHostKeyDNS }, 22092559Sdes { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 221124211Sdes { "rekeylimit", oRekeyLimit }, 222124211Sdes { "connecttimeout", oConnectTimeout }, 223124211Sdes { "addressfamily", oAddressFamily }, 224126277Sdes { "serveraliveinterval", oServerAliveInterval }, 225126277Sdes { "serveralivecountmax", oServerAliveCountMax }, 226137019Sdes { "sendenv", oSendEnv }, 227137019Sdes { "controlpath", oControlPath }, 228137019Sdes { "controlmaster", oControlMaster }, 229147005Sdes { "hashknownhosts", oHashKnownHosts }, 230157019Sdes { "tunnel", oTunnel }, 231157019Sdes { "tunneldevice", oTunnelDevice }, 232157019Sdes { "localcommand", oLocalCommand }, 233157019Sdes { "permitlocalcommand", oPermitLocalCommand }, 234181111Sdes { "visualhostkey", oVisualHostKey }, 235197679Sdes { "useroaming", oUseRoaming }, 236192595Sdes#ifdef JPAKE 237192595Sdes { "zeroknowledgepasswordauthentication", 238192595Sdes oZeroKnowledgePasswordAuthentication }, 239192595Sdes#else 240192595Sdes { "zeroknowledgepasswordauthentication", oUnsupported }, 241192595Sdes#endif 242192595Sdes 24399048Sdes { "versionaddendum", oVersionAddendum }, 24492559Sdes { NULL, oBadOption } 24557429Smarkm}; 24657429Smarkm 24757429Smarkm/* 24857429Smarkm * Adds a local TCP/IP port forward to options. Never returns if there is an 24957429Smarkm * error. 25057429Smarkm */ 25157429Smarkm 25260576Skrisvoid 253147005Sdesadd_local_forward(Options *options, const Forward *newfwd) 25457429Smarkm{ 25557429Smarkm Forward *fwd; 256106130Sdes#ifndef NO_IPPORT_RESERVED_CONCEPT 25757429Smarkm extern uid_t original_real_uid; 258181918Sdes int ipport_reserved; 259181918Sdes#ifdef __FreeBSD__ 260181918Sdes size_t len_ipport_reserved = sizeof(ipport_reserved); 261181918Sdes 262181918Sdes if (sysctlbyname("net.inet.ip.portrange.reservedhigh", 263181918Sdes &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0) 264181918Sdes ipport_reserved = IPPORT_RESERVED; 265181918Sdes else 266181918Sdes ipport_reserved++; 267181918Sdes#else 268181918Sdes ipport_reserved = IPPORT_RESERVED; 269181918Sdes#endif 270181918Sdes if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) 27176262Sgreen fatal("Privileged ports can only be forwarded by root."); 27298941Sdes#endif 27357429Smarkm if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 27457429Smarkm fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 27557429Smarkm fwd = &options->local_forwards[options->num_local_forwards++]; 276147005Sdes 277192595Sdes fwd->listen_host = newfwd->listen_host; 278147005Sdes fwd->listen_port = newfwd->listen_port; 279192595Sdes fwd->connect_host = newfwd->connect_host; 280147005Sdes fwd->connect_port = newfwd->connect_port; 28157429Smarkm} 28257429Smarkm 28357429Smarkm/* 28457429Smarkm * Adds a remote TCP/IP port forward to options. Never returns if there is 28557429Smarkm * an error. 28657429Smarkm */ 28757429Smarkm 28860576Skrisvoid 289147005Sdesadd_remote_forward(Options *options, const Forward *newfwd) 29057429Smarkm{ 29157429Smarkm Forward *fwd; 29257429Smarkm if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 29357429Smarkm fatal("Too many remote forwards (max %d).", 29492559Sdes SSH_MAX_FORWARDS_PER_DIRECTION); 29557429Smarkm fwd = &options->remote_forwards[options->num_remote_forwards++]; 296147005Sdes 297192595Sdes fwd->listen_host = newfwd->listen_host; 298147005Sdes fwd->listen_port = newfwd->listen_port; 299192595Sdes fwd->connect_host = newfwd->connect_host; 300147005Sdes fwd->connect_port = newfwd->connect_port; 30157429Smarkm} 30257429Smarkm 30392559Sdesstatic void 30492559Sdesclear_forwardings(Options *options) 30592559Sdes{ 30692559Sdes int i; 30792559Sdes 308147005Sdes for (i = 0; i < options->num_local_forwards; i++) { 309147005Sdes if (options->local_forwards[i].listen_host != NULL) 310147005Sdes xfree(options->local_forwards[i].listen_host); 311147005Sdes xfree(options->local_forwards[i].connect_host); 312147005Sdes } 31392559Sdes options->num_local_forwards = 0; 314147005Sdes for (i = 0; i < options->num_remote_forwards; i++) { 315147005Sdes if (options->remote_forwards[i].listen_host != NULL) 316147005Sdes xfree(options->remote_forwards[i].listen_host); 317147005Sdes xfree(options->remote_forwards[i].connect_host); 318147005Sdes } 31992559Sdes options->num_remote_forwards = 0; 320157019Sdes options->tun_open = SSH_TUNMODE_NO; 32192559Sdes} 32292559Sdes 32357429Smarkm/* 32476262Sgreen * Returns the number of the token pointed to by cp or oBadOption. 32557429Smarkm */ 32657429Smarkm 32760576Skrisstatic OpCodes 32857429Smarkmparse_token(const char *cp, const char *filename, int linenum) 32957429Smarkm{ 33076262Sgreen u_int i; 33157429Smarkm 33257429Smarkm for (i = 0; keywords[i].name; i++) 33357429Smarkm if (strcasecmp(cp, keywords[i].name) == 0) 33457429Smarkm return keywords[i].opcode; 33557429Smarkm 33676262Sgreen error("%s: line %d: Bad configuration option: %s", 33776262Sgreen filename, linenum, cp); 33857429Smarkm return oBadOption; 33957429Smarkm} 34057429Smarkm 34157429Smarkm/* 34257429Smarkm * Processes a single option line as used in the configuration files. This 34357429Smarkm * only sets those values that have not already been set. 34457429Smarkm */ 345113911Sdes#define WHITESPACE " \t\r\n" 34657429Smarkm 34757429Smarkmint 34857429Smarkmprocess_config_line(Options *options, const char *host, 34957429Smarkm char *line, const char *filename, int linenum, 35057429Smarkm int *activep) 35157429Smarkm{ 352147005Sdes char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; 353162856Sdes int opcode, *intptr, value, value2, scale; 354181111Sdes LogLevel *log_level_ptr; 355162856Sdes long long orig, val64; 356113911Sdes size_t len; 357147005Sdes Forward fwd; 35857429Smarkm 359124211Sdes /* Strip trailing whitespace */ 360147005Sdes for (len = strlen(line) - 1; len > 0; len--) { 361124211Sdes if (strchr(WHITESPACE, line[len]) == NULL) 362124211Sdes break; 363124211Sdes line[len] = '\0'; 364124211Sdes } 365124211Sdes 36665674Skris s = line; 36765674Skris /* Get the keyword. (Each line is supposed to begin with a keyword). */ 368162856Sdes if ((keyword = strdelim(&s)) == NULL) 369162856Sdes return 0; 37065674Skris /* Ignore leading whitespace. */ 37165674Skris if (*keyword == '\0') 37265674Skris keyword = strdelim(&s); 37376262Sgreen if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 37457429Smarkm return 0; 37557429Smarkm 37665674Skris opcode = parse_token(keyword, filename, linenum); 37757429Smarkm 37857429Smarkm switch (opcode) { 37957429Smarkm case oBadOption: 38057429Smarkm /* don't panic, but count bad options */ 38157429Smarkm return -1; 38257429Smarkm /* NOTREACHED */ 383124211Sdes case oConnectTimeout: 384124211Sdes intptr = &options->connection_timeout; 385126277Sdesparse_time: 386124211Sdes arg = strdelim(&s); 387124211Sdes if (!arg || *arg == '\0') 388124211Sdes fatal("%s line %d: missing time value.", 389124211Sdes filename, linenum); 390124211Sdes if ((value = convtime(arg)) == -1) 391124211Sdes fatal("%s line %d: invalid time value.", 392124211Sdes filename, linenum); 393181111Sdes if (*activep && *intptr == -1) 394124211Sdes *intptr = value; 395124211Sdes break; 396124211Sdes 39757429Smarkm case oForwardAgent: 39857429Smarkm intptr = &options->forward_agent; 39957429Smarkmparse_flag: 40065674Skris arg = strdelim(&s); 40165674Skris if (!arg || *arg == '\0') 40257429Smarkm fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 40357429Smarkm value = 0; /* To avoid compiler warning... */ 40465674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 40557429Smarkm value = 1; 40665674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 40757429Smarkm value = 0; 40857429Smarkm else 40957429Smarkm fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 41057429Smarkm if (*activep && *intptr == -1) 41157429Smarkm *intptr = value; 41257429Smarkm break; 41357429Smarkm 41457429Smarkm case oForwardX11: 41557429Smarkm intptr = &options->forward_x11; 41657429Smarkm goto parse_flag; 41757429Smarkm 418126277Sdes case oForwardX11Trusted: 419126277Sdes intptr = &options->forward_x11_trusted; 420126277Sdes goto parse_flag; 421126277Sdes 42257429Smarkm case oGatewayPorts: 42357429Smarkm intptr = &options->gateway_ports; 42457429Smarkm goto parse_flag; 42557429Smarkm 426162856Sdes case oExitOnForwardFailure: 427162856Sdes intptr = &options->exit_on_forward_failure; 428162856Sdes goto parse_flag; 429162856Sdes 43057429Smarkm case oUsePrivilegedPort: 43157429Smarkm intptr = &options->use_privileged_port; 43257429Smarkm goto parse_flag; 43357429Smarkm 43457429Smarkm case oPasswordAuthentication: 43557429Smarkm intptr = &options->password_authentication; 43657429Smarkm goto parse_flag; 43757429Smarkm 438192595Sdes case oZeroKnowledgePasswordAuthentication: 439192595Sdes intptr = &options->zero_knowledge_password_authentication; 440192595Sdes goto parse_flag; 441192595Sdes 44269591Sgreen case oKbdInteractiveAuthentication: 44369591Sgreen intptr = &options->kbd_interactive_authentication; 44469591Sgreen goto parse_flag; 44569591Sgreen 44669591Sgreen case oKbdInteractiveDevices: 44769591Sgreen charptr = &options->kbd_interactive_devices; 44869591Sgreen goto parse_string; 44969591Sgreen 45076262Sgreen case oPubkeyAuthentication: 45176262Sgreen intptr = &options->pubkey_authentication; 45260576Skris goto parse_flag; 45360576Skris 45457429Smarkm case oRSAAuthentication: 45557429Smarkm intptr = &options->rsa_authentication; 45657429Smarkm goto parse_flag; 45757429Smarkm 45857429Smarkm case oRhostsRSAAuthentication: 45957429Smarkm intptr = &options->rhosts_rsa_authentication; 46057429Smarkm goto parse_flag; 46157429Smarkm 46276262Sgreen case oHostbasedAuthentication: 46376262Sgreen intptr = &options->hostbased_authentication; 46457429Smarkm goto parse_flag; 46557429Smarkm 46692559Sdes case oChallengeResponseAuthentication: 46792559Sdes intptr = &options->challenge_response_authentication; 46892559Sdes goto parse_flag; 469124211Sdes 470124211Sdes case oGssAuthentication: 471124211Sdes intptr = &options->gss_authentication; 47257429Smarkm goto parse_flag; 473124211Sdes 474124211Sdes case oGssDelegateCreds: 475124211Sdes intptr = &options->gss_deleg_creds; 47676262Sgreen goto parse_flag; 477124211Sdes 47857429Smarkm case oBatchMode: 47957429Smarkm intptr = &options->batch_mode; 48057429Smarkm goto parse_flag; 48157429Smarkm 48257429Smarkm case oCheckHostIP: 48357429Smarkm intptr = &options->check_host_ip; 48457429Smarkm goto parse_flag; 48557429Smarkm 486124211Sdes case oVerifyHostKeyDNS: 487124211Sdes intptr = &options->verify_host_key_dns; 488126277Sdes goto parse_yesnoask; 489124211Sdes 49057429Smarkm case oStrictHostKeyChecking: 49157429Smarkm intptr = &options->strict_host_key_checking; 492126277Sdesparse_yesnoask: 49365674Skris arg = strdelim(&s); 49465674Skris if (!arg || *arg == '\0') 49576262Sgreen fatal("%.200s line %d: Missing yes/no/ask argument.", 49692559Sdes filename, linenum); 49757429Smarkm value = 0; /* To avoid compiler warning... */ 49865674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 49957429Smarkm value = 1; 50065674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 50157429Smarkm value = 0; 50265674Skris else if (strcmp(arg, "ask") == 0) 50357429Smarkm value = 2; 50457429Smarkm else 50557429Smarkm fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 50657429Smarkm if (*activep && *intptr == -1) 50757429Smarkm *intptr = value; 50857429Smarkm break; 50957429Smarkm 51057429Smarkm case oCompression: 51157429Smarkm intptr = &options->compression; 51257429Smarkm goto parse_flag; 51357429Smarkm 514126277Sdes case oTCPKeepAlive: 515126277Sdes intptr = &options->tcp_keep_alive; 51657429Smarkm goto parse_flag; 51757429Smarkm 51892559Sdes case oNoHostAuthenticationForLocalhost: 51992559Sdes intptr = &options->no_host_authentication_for_localhost; 52092559Sdes goto parse_flag; 52192559Sdes 52257429Smarkm case oNumberOfPasswordPrompts: 52357429Smarkm intptr = &options->number_of_password_prompts; 52457429Smarkm goto parse_int; 52557429Smarkm 52657429Smarkm case oCompressionLevel: 52757429Smarkm intptr = &options->compression_level; 52857429Smarkm goto parse_int; 52957429Smarkm 530124211Sdes case oRekeyLimit: 531124211Sdes arg = strdelim(&s); 532124211Sdes if (!arg || *arg == '\0') 533124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 534124211Sdes if (arg[0] < '0' || arg[0] > '9') 535124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 536162856Sdes orig = val64 = strtoll(arg, &endofnumber, 10); 537124211Sdes if (arg == endofnumber) 538124211Sdes fatal("%.200s line %d: Bad number.", filename, linenum); 539124211Sdes switch (toupper(*endofnumber)) { 540162856Sdes case '\0': 541162856Sdes scale = 1; 542162856Sdes break; 543124211Sdes case 'K': 544162856Sdes scale = 1<<10; 545124211Sdes break; 546124211Sdes case 'M': 547162856Sdes scale = 1<<20; 548124211Sdes break; 549124211Sdes case 'G': 550162856Sdes scale = 1<<30; 551124211Sdes break; 552162856Sdes default: 553162856Sdes fatal("%.200s line %d: Invalid RekeyLimit suffix", 554162856Sdes filename, linenum); 555124211Sdes } 556162856Sdes val64 *= scale; 557162856Sdes /* detect integer wrap and too-large limits */ 558181111Sdes if ((val64 / scale) != orig || val64 > UINT_MAX) 559162856Sdes fatal("%.200s line %d: RekeyLimit too large", 560162856Sdes filename, linenum); 561162856Sdes if (val64 < 16) 562162856Sdes fatal("%.200s line %d: RekeyLimit too small", 563162856Sdes filename, linenum); 564181111Sdes if (*activep && options->rekey_limit == -1) 565181111Sdes options->rekey_limit = (u_int32_t)val64; 566124211Sdes break; 567124211Sdes 56857429Smarkm case oIdentityFile: 56965674Skris arg = strdelim(&s); 57065674Skris if (!arg || *arg == '\0') 57157429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 57257429Smarkm if (*activep) { 57376262Sgreen intptr = &options->num_identity_files; 57460576Skris if (*intptr >= SSH_MAX_IDENTITY_FILES) 57557429Smarkm fatal("%.200s line %d: Too many identity files specified (max %d).", 57692559Sdes filename, linenum, SSH_MAX_IDENTITY_FILES); 577181111Sdes charptr = &options->identity_files[*intptr]; 57865674Skris *charptr = xstrdup(arg); 57960576Skris *intptr = *intptr + 1; 58057429Smarkm } 58157429Smarkm break; 58257429Smarkm 58365674Skris case oXAuthLocation: 58465674Skris charptr=&options->xauth_location; 58565674Skris goto parse_string; 58665674Skris 58757429Smarkm case oUser: 58857429Smarkm charptr = &options->user; 58957429Smarkmparse_string: 59065674Skris arg = strdelim(&s); 59165674Skris if (!arg || *arg == '\0') 59257429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 59357429Smarkm if (*activep && *charptr == NULL) 59465674Skris *charptr = xstrdup(arg); 59557429Smarkm break; 59657429Smarkm 59757429Smarkm case oGlobalKnownHostsFile: 59857429Smarkm charptr = &options->system_hostfile; 59957429Smarkm goto parse_string; 60057429Smarkm 60157429Smarkm case oUserKnownHostsFile: 60257429Smarkm charptr = &options->user_hostfile; 60357429Smarkm goto parse_string; 60457429Smarkm 60560576Skris case oGlobalKnownHostsFile2: 60660576Skris charptr = &options->system_hostfile2; 60760576Skris goto parse_string; 60860576Skris 60960576Skris case oUserKnownHostsFile2: 61060576Skris charptr = &options->user_hostfile2; 61160576Skris goto parse_string; 61260576Skris 61357429Smarkm case oHostName: 61457429Smarkm charptr = &options->hostname; 61557429Smarkm goto parse_string; 61657429Smarkm 61776262Sgreen case oHostKeyAlias: 61876262Sgreen charptr = &options->host_key_alias; 61976262Sgreen goto parse_string; 62076262Sgreen 62176262Sgreen case oPreferredAuthentications: 62276262Sgreen charptr = &options->preferred_authentications; 62376262Sgreen goto parse_string; 62476262Sgreen 62592559Sdes case oBindAddress: 62692559Sdes charptr = &options->bind_address; 62792559Sdes goto parse_string; 62892559Sdes 62992559Sdes case oSmartcardDevice: 63092559Sdes charptr = &options->smartcard_device; 63192559Sdes goto parse_string; 63292559Sdes 63357429Smarkm case oProxyCommand: 634157019Sdes charptr = &options->proxy_command; 635157019Sdesparse_command: 636124211Sdes if (s == NULL) 637124211Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 638113911Sdes len = strspn(s, WHITESPACE "="); 63957429Smarkm if (*activep && *charptr == NULL) 640113911Sdes *charptr = xstrdup(s + len); 64157429Smarkm return 0; 64257429Smarkm 64357429Smarkm case oPort: 64457429Smarkm intptr = &options->port; 64557429Smarkmparse_int: 64665674Skris arg = strdelim(&s); 64765674Skris if (!arg || *arg == '\0') 64857429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 64965674Skris if (arg[0] < '0' || arg[0] > '9') 65057429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 65157429Smarkm 65257429Smarkm /* Octal, decimal, or hex format? */ 65365674Skris value = strtol(arg, &endofnumber, 0); 65465674Skris if (arg == endofnumber) 65557429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 65657429Smarkm if (*activep && *intptr == -1) 65757429Smarkm *intptr = value; 65857429Smarkm break; 65957429Smarkm 66057429Smarkm case oConnectionAttempts: 66157429Smarkm intptr = &options->connection_attempts; 66257429Smarkm goto parse_int; 66357429Smarkm 66457429Smarkm case oCipher: 66557429Smarkm intptr = &options->cipher; 66665674Skris arg = strdelim(&s); 66765674Skris if (!arg || *arg == '\0') 66861203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 66965674Skris value = cipher_number(arg); 67057429Smarkm if (value == -1) 67157429Smarkm fatal("%.200s line %d: Bad cipher '%s'.", 67292559Sdes filename, linenum, arg ? arg : "<NONE>"); 67357429Smarkm if (*activep && *intptr == -1) 67457429Smarkm *intptr = value; 67557429Smarkm break; 67657429Smarkm 67760576Skris case oCiphers: 67865674Skris arg = strdelim(&s); 67965674Skris if (!arg || *arg == '\0') 68061203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 68165674Skris if (!ciphers_valid(arg)) 68260576Skris fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 68392559Sdes filename, linenum, arg ? arg : "<NONE>"); 68460576Skris if (*activep && options->ciphers == NULL) 68565674Skris options->ciphers = xstrdup(arg); 68660576Skris break; 68760576Skris 68876262Sgreen case oMacs: 68976262Sgreen arg = strdelim(&s); 69076262Sgreen if (!arg || *arg == '\0') 69176262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 69276262Sgreen if (!mac_valid(arg)) 69376262Sgreen fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 69492559Sdes filename, linenum, arg ? arg : "<NONE>"); 69576262Sgreen if (*activep && options->macs == NULL) 69676262Sgreen options->macs = xstrdup(arg); 69776262Sgreen break; 69876262Sgreen 69976262Sgreen case oHostKeyAlgorithms: 70076262Sgreen arg = strdelim(&s); 70176262Sgreen if (!arg || *arg == '\0') 70276262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 70376262Sgreen if (!key_names_valid2(arg)) 70476262Sgreen fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 70592559Sdes filename, linenum, arg ? arg : "<NONE>"); 70676262Sgreen if (*activep && options->hostkeyalgorithms == NULL) 70776262Sgreen options->hostkeyalgorithms = xstrdup(arg); 70876262Sgreen break; 70976262Sgreen 71060576Skris case oProtocol: 71160576Skris intptr = &options->protocol; 71265674Skris arg = strdelim(&s); 71365674Skris if (!arg || *arg == '\0') 71461203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 71565674Skris value = proto_spec(arg); 71660576Skris if (value == SSH_PROTO_UNKNOWN) 71760576Skris fatal("%.200s line %d: Bad protocol spec '%s'.", 71892559Sdes filename, linenum, arg ? arg : "<NONE>"); 71960576Skris if (*activep && *intptr == SSH_PROTO_UNKNOWN) 72060576Skris *intptr = value; 72160576Skris break; 72260576Skris 72357429Smarkm case oLogLevel: 724181111Sdes log_level_ptr = &options->log_level; 72565674Skris arg = strdelim(&s); 72665674Skris value = log_level_number(arg); 72792559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 72876262Sgreen fatal("%.200s line %d: unsupported log level '%s'", 72992559Sdes filename, linenum, arg ? arg : "<NONE>"); 730181111Sdes if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) 731181111Sdes *log_level_ptr = (LogLevel) value; 73257429Smarkm break; 73357429Smarkm 73492559Sdes case oLocalForward: 73557429Smarkm case oRemoteForward: 736192595Sdes case oDynamicForward: 73765674Skris arg = strdelim(&s); 738147005Sdes if (arg == NULL || *arg == '\0') 73992559Sdes fatal("%.200s line %d: Missing port argument.", 74092559Sdes filename, linenum); 741147005Sdes 742192595Sdes if (opcode == oLocalForward || 743192595Sdes opcode == oRemoteForward) { 744192595Sdes arg2 = strdelim(&s); 745192595Sdes if (arg2 == NULL || *arg2 == '\0') 746192595Sdes fatal("%.200s line %d: Missing target argument.", 747192595Sdes filename, linenum); 748147005Sdes 749192595Sdes /* construct a string for parse_forward */ 750192595Sdes snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); 751192595Sdes } else if (opcode == oDynamicForward) { 752192595Sdes strlcpy(fwdarg, arg, sizeof(fwdarg)); 753192595Sdes } 754192595Sdes 755192595Sdes if (parse_forward(&fwd, fwdarg, 756192595Sdes opcode == oDynamicForward ? 1 : 0, 757192595Sdes opcode == oRemoteForward ? 1 : 0) == 0) 75892559Sdes fatal("%.200s line %d: Bad forwarding specification.", 75992559Sdes filename, linenum); 760147005Sdes 76192559Sdes if (*activep) { 762192595Sdes if (opcode == oLocalForward || 763192595Sdes opcode == oDynamicForward) 764147005Sdes add_local_forward(options, &fwd); 76592559Sdes else if (opcode == oRemoteForward) 766147005Sdes add_remote_forward(options, &fwd); 76792559Sdes } 76857429Smarkm break; 76957429Smarkm 77092559Sdes case oClearAllForwardings: 77192559Sdes intptr = &options->clear_forwardings; 77292559Sdes goto parse_flag; 77392559Sdes 77457429Smarkm case oHost: 77557429Smarkm *activep = 0; 77665674Skris while ((arg = strdelim(&s)) != NULL && *arg != '\0') 77765674Skris if (match_pattern(host, arg)) { 77865674Skris debug("Applying options for %.100s", arg); 77957429Smarkm *activep = 1; 78057429Smarkm break; 78157429Smarkm } 78265674Skris /* Avoid garbage check below, as strdelim is done. */ 78357429Smarkm return 0; 78457429Smarkm 78557429Smarkm case oEscapeChar: 78657429Smarkm intptr = &options->escape_char; 78765674Skris arg = strdelim(&s); 78865674Skris if (!arg || *arg == '\0') 78957429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 79065674Skris if (arg[0] == '^' && arg[2] == 0 && 79176262Sgreen (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 79276262Sgreen value = (u_char) arg[1] & 31; 79365674Skris else if (strlen(arg) == 1) 79476262Sgreen value = (u_char) arg[0]; 79565674Skris else if (strcmp(arg, "none") == 0) 79692559Sdes value = SSH_ESCAPECHAR_NONE; 79757429Smarkm else { 79857429Smarkm fatal("%.200s line %d: Bad escape character.", 79992559Sdes filename, linenum); 80057429Smarkm /* NOTREACHED */ 80157429Smarkm value = 0; /* Avoid compiler warning. */ 80257429Smarkm } 80357429Smarkm if (*activep && *intptr == -1) 80457429Smarkm *intptr = value; 80557429Smarkm break; 80657429Smarkm 807124211Sdes case oAddressFamily: 808124211Sdes arg = strdelim(&s); 809149753Sdes if (!arg || *arg == '\0') 810149753Sdes fatal("%s line %d: missing address family.", 811149753Sdes filename, linenum); 812124211Sdes intptr = &options->address_family; 813124211Sdes if (strcasecmp(arg, "inet") == 0) 814124211Sdes value = AF_INET; 815124211Sdes else if (strcasecmp(arg, "inet6") == 0) 816124211Sdes value = AF_INET6; 817124211Sdes else if (strcasecmp(arg, "any") == 0) 818124211Sdes value = AF_UNSPEC; 819124211Sdes else 820124211Sdes fatal("Unsupported AddressFamily \"%s\"", arg); 821124211Sdes if (*activep && *intptr == -1) 822124211Sdes *intptr = value; 823124211Sdes break; 824124211Sdes 825113911Sdes case oEnableSSHKeysign: 826113911Sdes intptr = &options->enable_ssh_keysign; 827113911Sdes goto parse_flag; 828113911Sdes 829128460Sdes case oIdentitiesOnly: 830128460Sdes intptr = &options->identities_only; 831128460Sdes goto parse_flag; 832128460Sdes 833126277Sdes case oServerAliveInterval: 834126277Sdes intptr = &options->server_alive_interval; 835126277Sdes goto parse_time; 836126277Sdes 837126277Sdes case oServerAliveCountMax: 838126277Sdes intptr = &options->server_alive_count_max; 839126277Sdes goto parse_int; 840126277Sdes 841137019Sdes case oSendEnv: 842137019Sdes while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 843137019Sdes if (strchr(arg, '=') != NULL) 844137019Sdes fatal("%s line %d: Invalid environment name.", 845137019Sdes filename, linenum); 846147005Sdes if (!*activep) 847147005Sdes continue; 848137019Sdes if (options->num_send_env >= MAX_SEND_ENV) 849137019Sdes fatal("%s line %d: too many send env.", 850137019Sdes filename, linenum); 851137019Sdes options->send_env[options->num_send_env++] = 852137019Sdes xstrdup(arg); 853137019Sdes } 854137019Sdes break; 855137019Sdes 856137019Sdes case oControlPath: 857137019Sdes charptr = &options->control_path; 858137019Sdes goto parse_string; 859137019Sdes 860137019Sdes case oControlMaster: 861137019Sdes intptr = &options->control_master; 862149753Sdes arg = strdelim(&s); 863149753Sdes if (!arg || *arg == '\0') 864149753Sdes fatal("%.200s line %d: Missing ControlMaster argument.", 865149753Sdes filename, linenum); 866149753Sdes value = 0; /* To avoid compiler warning... */ 867149753Sdes if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 868149753Sdes value = SSHCTL_MASTER_YES; 869149753Sdes else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 870149753Sdes value = SSHCTL_MASTER_NO; 871149753Sdes else if (strcmp(arg, "auto") == 0) 872149753Sdes value = SSHCTL_MASTER_AUTO; 873149753Sdes else if (strcmp(arg, "ask") == 0) 874149753Sdes value = SSHCTL_MASTER_ASK; 875149753Sdes else if (strcmp(arg, "autoask") == 0) 876149753Sdes value = SSHCTL_MASTER_AUTO_ASK; 877149753Sdes else 878149753Sdes fatal("%.200s line %d: Bad ControlMaster argument.", 879149753Sdes filename, linenum); 880149753Sdes if (*activep && *intptr == -1) 881149753Sdes *intptr = value; 882149753Sdes break; 883137019Sdes 884147005Sdes case oHashKnownHosts: 885147005Sdes intptr = &options->hash_known_hosts; 886147005Sdes goto parse_flag; 887147005Sdes 888157019Sdes case oTunnel: 889157019Sdes intptr = &options->tun_open; 890157019Sdes arg = strdelim(&s); 891157019Sdes if (!arg || *arg == '\0') 892157019Sdes fatal("%s line %d: Missing yes/point-to-point/" 893157019Sdes "ethernet/no argument.", filename, linenum); 894157019Sdes value = 0; /* silence compiler */ 895157019Sdes if (strcasecmp(arg, "ethernet") == 0) 896157019Sdes value = SSH_TUNMODE_ETHERNET; 897157019Sdes else if (strcasecmp(arg, "point-to-point") == 0) 898157019Sdes value = SSH_TUNMODE_POINTOPOINT; 899157019Sdes else if (strcasecmp(arg, "yes") == 0) 900157019Sdes value = SSH_TUNMODE_DEFAULT; 901157019Sdes else if (strcasecmp(arg, "no") == 0) 902157019Sdes value = SSH_TUNMODE_NO; 903157019Sdes else 904157019Sdes fatal("%s line %d: Bad yes/point-to-point/ethernet/" 905157019Sdes "no argument: %s", filename, linenum, arg); 906157019Sdes if (*activep) 907157019Sdes *intptr = value; 908157019Sdes break; 909157019Sdes 910157019Sdes case oTunnelDevice: 911157019Sdes arg = strdelim(&s); 912157019Sdes if (!arg || *arg == '\0') 913157019Sdes fatal("%.200s line %d: Missing argument.", filename, linenum); 914157019Sdes value = a2tun(arg, &value2); 915157019Sdes if (value == SSH_TUNID_ERR) 916157019Sdes fatal("%.200s line %d: Bad tun device.", filename, linenum); 917157019Sdes if (*activep) { 918157019Sdes options->tun_local = value; 919157019Sdes options->tun_remote = value2; 920157019Sdes } 921157019Sdes break; 922157019Sdes 923157019Sdes case oLocalCommand: 924157019Sdes charptr = &options->local_command; 925157019Sdes goto parse_command; 926157019Sdes 927157019Sdes case oPermitLocalCommand: 928157019Sdes intptr = &options->permit_local_command; 929157019Sdes goto parse_flag; 930157019Sdes 931181111Sdes case oVisualHostKey: 932181111Sdes intptr = &options->visual_host_key; 933181111Sdes goto parse_flag; 934181111Sdes 935197679Sdes case oUseRoaming: 936197679Sdes intptr = &options->use_roaming; 937197679Sdes goto parse_flag; 938197679Sdes 93999048Sdes case oVersionAddendum: 94099048Sdes ssh_version_set_addendum(strtok(s, "\n")); 94199048Sdes do { 94299048Sdes arg = strdelim(&s); 94399048Sdes } while (arg != NULL && *arg != '\0'); 94499048Sdes break; 94599048Sdes 94698684Sdes case oDeprecated: 94798684Sdes debug("%s line %d: Deprecated option \"%s\"", 94898684Sdes filename, linenum, keyword); 94998684Sdes return 0; 95098684Sdes 951124211Sdes case oUnsupported: 952124211Sdes error("%s line %d: Unsupported option \"%s\"", 953124211Sdes filename, linenum, keyword); 954124211Sdes return 0; 955124211Sdes 95657429Smarkm default: 95757429Smarkm fatal("process_config_line: Unimplemented opcode %d", opcode); 95857429Smarkm } 95957429Smarkm 96057429Smarkm /* Check that there is no garbage at end of line. */ 96176262Sgreen if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 96265674Skris fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 963149753Sdes filename, linenum, arg); 96465674Skris } 96557429Smarkm return 0; 96657429Smarkm} 96757429Smarkm 96857429Smarkm 96957429Smarkm/* 97057429Smarkm * Reads the config file and modifies the options accordingly. Options 97157429Smarkm * should already be initialized before this call. This never returns if 97292559Sdes * there is an error. If the file does not exist, this returns 0. 97357429Smarkm */ 97457429Smarkm 97592559Sdesint 976137019Sdesread_config_file(const char *filename, const char *host, Options *options, 977137019Sdes int checkperm) 97857429Smarkm{ 97957429Smarkm FILE *f; 98057429Smarkm char line[1024]; 98157429Smarkm int active, linenum; 98257429Smarkm int bad_options = 0; 98357429Smarkm 984137019Sdes if ((f = fopen(filename, "r")) == NULL) 98592559Sdes return 0; 98657429Smarkm 987137019Sdes if (checkperm) { 988137019Sdes struct stat sb; 989137019Sdes 990137019Sdes if (fstat(fileno(f), &sb) == -1) 991137019Sdes fatal("fstat %s: %s", filename, strerror(errno)); 992137019Sdes if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 993137019Sdes (sb.st_mode & 022) != 0)) 994137019Sdes fatal("Bad owner or permissions on %s", filename); 995137019Sdes } 996137019Sdes 99757429Smarkm debug("Reading configuration data %.200s", filename); 99857429Smarkm 99957429Smarkm /* 100057429Smarkm * Mark that we are now processing the options. This flag is turned 100157429Smarkm * on/off by Host specifications. 100257429Smarkm */ 100357429Smarkm active = 1; 100457429Smarkm linenum = 0; 100557429Smarkm while (fgets(line, sizeof(line), f)) { 100657429Smarkm /* Update line number counter. */ 100757429Smarkm linenum++; 100857429Smarkm if (process_config_line(options, host, line, filename, linenum, &active) != 0) 100957429Smarkm bad_options++; 101057429Smarkm } 101157429Smarkm fclose(f); 101257429Smarkm if (bad_options > 0) 101376262Sgreen fatal("%s: terminating, %d bad configuration options", 101492559Sdes filename, bad_options); 101592559Sdes return 1; 101657429Smarkm} 101757429Smarkm 101857429Smarkm/* 101957429Smarkm * Initializes options to special values that indicate that they have not yet 102057429Smarkm * been set. Read_config_file will only set options with this value. Options 102157429Smarkm * are processed in the following order: command line, user config file, 102257429Smarkm * system config file. Last, fill_default_options is called. 102357429Smarkm */ 102457429Smarkm 102560576Skrisvoid 102657429Smarkminitialize_options(Options * options) 102757429Smarkm{ 102857429Smarkm memset(options, 'X', sizeof(*options)); 102957429Smarkm options->forward_agent = -1; 103057429Smarkm options->forward_x11 = -1; 1031126277Sdes options->forward_x11_trusted = -1; 1032162856Sdes options->exit_on_forward_failure = -1; 103365674Skris options->xauth_location = NULL; 103457429Smarkm options->gateway_ports = -1; 103557429Smarkm options->use_privileged_port = -1; 103657429Smarkm options->rsa_authentication = -1; 103776262Sgreen options->pubkey_authentication = -1; 103892559Sdes options->challenge_response_authentication = -1; 1039124211Sdes options->gss_authentication = -1; 1040124211Sdes options->gss_deleg_creds = -1; 104157429Smarkm options->password_authentication = -1; 104269591Sgreen options->kbd_interactive_authentication = -1; 104369591Sgreen options->kbd_interactive_devices = NULL; 104457429Smarkm options->rhosts_rsa_authentication = -1; 104576262Sgreen options->hostbased_authentication = -1; 104657429Smarkm options->batch_mode = -1; 104757429Smarkm options->check_host_ip = -1; 104857429Smarkm options->strict_host_key_checking = -1; 104957429Smarkm options->compression = -1; 1050126277Sdes options->tcp_keep_alive = -1; 105157429Smarkm options->compression_level = -1; 105257429Smarkm options->port = -1; 1053124211Sdes options->address_family = -1; 105457429Smarkm options->connection_attempts = -1; 1055124211Sdes options->connection_timeout = -1; 105657429Smarkm options->number_of_password_prompts = -1; 105757429Smarkm options->cipher = -1; 105860576Skris options->ciphers = NULL; 105976262Sgreen options->macs = NULL; 106076262Sgreen options->hostkeyalgorithms = NULL; 106160576Skris options->protocol = SSH_PROTO_UNKNOWN; 106257429Smarkm options->num_identity_files = 0; 106357429Smarkm options->hostname = NULL; 106476262Sgreen options->host_key_alias = NULL; 106557429Smarkm options->proxy_command = NULL; 106657429Smarkm options->user = NULL; 106757429Smarkm options->escape_char = -1; 106857429Smarkm options->system_hostfile = NULL; 106957429Smarkm options->user_hostfile = NULL; 107060576Skris options->system_hostfile2 = NULL; 107160576Skris options->user_hostfile2 = NULL; 107257429Smarkm options->num_local_forwards = 0; 107357429Smarkm options->num_remote_forwards = 0; 107492559Sdes options->clear_forwardings = -1; 107592559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 107676262Sgreen options->preferred_authentications = NULL; 107792559Sdes options->bind_address = NULL; 107892559Sdes options->smartcard_device = NULL; 1079113911Sdes options->enable_ssh_keysign = - 1; 108092559Sdes options->no_host_authentication_for_localhost = - 1; 1081128460Sdes options->identities_only = - 1; 1082124211Sdes options->rekey_limit = - 1; 1083124211Sdes options->verify_host_key_dns = -1; 1084126277Sdes options->server_alive_interval = -1; 1085126277Sdes options->server_alive_count_max = -1; 1086137019Sdes options->num_send_env = 0; 1087137019Sdes options->control_path = NULL; 1088137019Sdes options->control_master = -1; 1089147005Sdes options->hash_known_hosts = -1; 1090157019Sdes options->tun_open = -1; 1091157019Sdes options->tun_local = -1; 1092157019Sdes options->tun_remote = -1; 1093157019Sdes options->local_command = NULL; 1094157019Sdes options->permit_local_command = -1; 1095197679Sdes options->use_roaming = -1; 1096181111Sdes options->visual_host_key = -1; 1097192595Sdes options->zero_knowledge_password_authentication = -1; 109857429Smarkm} 109957429Smarkm 110057429Smarkm/* 110157429Smarkm * Called after processing other sources of option data, this fills those 110257429Smarkm * options for which no value has been specified with their default values. 110357429Smarkm */ 110457429Smarkm 110560576Skrisvoid 110657429Smarkmfill_default_options(Options * options) 110757429Smarkm{ 110876262Sgreen int len; 110976262Sgreen 111057429Smarkm if (options->forward_agent == -1) 111161203Skris options->forward_agent = 0; 111257429Smarkm if (options->forward_x11 == -1) 111357708Sgreen options->forward_x11 = 0; 1114126277Sdes if (options->forward_x11_trusted == -1) 1115126277Sdes options->forward_x11_trusted = 0; 1116162856Sdes if (options->exit_on_forward_failure == -1) 1117162856Sdes options->exit_on_forward_failure = 0; 111865674Skris if (options->xauth_location == NULL) 111992559Sdes options->xauth_location = _PATH_XAUTH; 112057429Smarkm if (options->gateway_ports == -1) 112157429Smarkm options->gateway_ports = 0; 112257429Smarkm if (options->use_privileged_port == -1) 112376262Sgreen options->use_privileged_port = 0; 112457429Smarkm if (options->rsa_authentication == -1) 112557429Smarkm options->rsa_authentication = 1; 112676262Sgreen if (options->pubkey_authentication == -1) 112776262Sgreen options->pubkey_authentication = 1; 112892559Sdes if (options->challenge_response_authentication == -1) 112992559Sdes options->challenge_response_authentication = 1; 1130124211Sdes if (options->gss_authentication == -1) 1131126277Sdes options->gss_authentication = 0; 1132124211Sdes if (options->gss_deleg_creds == -1) 1133124211Sdes options->gss_deleg_creds = 0; 113457429Smarkm if (options->password_authentication == -1) 113557429Smarkm options->password_authentication = 1; 113669591Sgreen if (options->kbd_interactive_authentication == -1) 113776262Sgreen options->kbd_interactive_authentication = 1; 113857429Smarkm if (options->rhosts_rsa_authentication == -1) 113998684Sdes options->rhosts_rsa_authentication = 0; 114076262Sgreen if (options->hostbased_authentication == -1) 114176262Sgreen options->hostbased_authentication = 0; 114257429Smarkm if (options->batch_mode == -1) 114357429Smarkm options->batch_mode = 0; 114457429Smarkm if (options->check_host_ip == -1) 114599048Sdes options->check_host_ip = 0; 114657429Smarkm if (options->strict_host_key_checking == -1) 114757429Smarkm options->strict_host_key_checking = 2; /* 2 is default */ 114857429Smarkm if (options->compression == -1) 114957429Smarkm options->compression = 0; 1150126277Sdes if (options->tcp_keep_alive == -1) 1151126277Sdes options->tcp_keep_alive = 1; 115257429Smarkm if (options->compression_level == -1) 115357429Smarkm options->compression_level = 6; 115457429Smarkm if (options->port == -1) 115557429Smarkm options->port = 0; /* Filled in ssh_connect. */ 1156124211Sdes if (options->address_family == -1) 1157124211Sdes options->address_family = AF_UNSPEC; 115857429Smarkm if (options->connection_attempts == -1) 115992559Sdes options->connection_attempts = 1; 116057429Smarkm if (options->number_of_password_prompts == -1) 116157429Smarkm options->number_of_password_prompts = 3; 116257429Smarkm /* Selected in ssh_login(). */ 116357429Smarkm if (options->cipher == -1) 116457429Smarkm options->cipher = SSH_CIPHER_NOT_SET; 116560576Skris /* options->ciphers, default set in myproposals.h */ 116676262Sgreen /* options->macs, default set in myproposals.h */ 116776262Sgreen /* options->hostkeyalgorithms, default set in myproposals.h */ 116860576Skris if (options->protocol == SSH_PROTO_UNKNOWN) 116976262Sgreen options->protocol = SSH_PROTO_1|SSH_PROTO_2; 117057429Smarkm if (options->num_identity_files == 0) { 117176262Sgreen if (options->protocol & SSH_PROTO_1) { 117276262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 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_IDENTITY); 117776262Sgreen } 117876262Sgreen if (options->protocol & SSH_PROTO_2) { 117976262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 118076262Sgreen options->identity_files[options->num_identity_files] = 118176262Sgreen xmalloc(len); 118276262Sgreen snprintf(options->identity_files[options->num_identity_files++], 118376262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 118476262Sgreen 118576262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 118676262Sgreen options->identity_files[options->num_identity_files] = 118776262Sgreen xmalloc(len); 118876262Sgreen snprintf(options->identity_files[options->num_identity_files++], 118976262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 119076262Sgreen } 119157429Smarkm } 119257429Smarkm if (options->escape_char == -1) 119357429Smarkm options->escape_char = '~'; 119457429Smarkm if (options->system_hostfile == NULL) 119576262Sgreen options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 119657429Smarkm if (options->user_hostfile == NULL) 119776262Sgreen options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 119860576Skris if (options->system_hostfile2 == NULL) 119976262Sgreen options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 120060576Skris if (options->user_hostfile2 == NULL) 120176262Sgreen options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 120292559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 120357429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 120492559Sdes if (options->clear_forwardings == 1) 120592559Sdes clear_forwardings(options); 120692559Sdes if (options->no_host_authentication_for_localhost == - 1) 120792559Sdes options->no_host_authentication_for_localhost = 0; 1208128460Sdes if (options->identities_only == -1) 1209128460Sdes options->identities_only = 0; 1210113911Sdes if (options->enable_ssh_keysign == -1) 1211113911Sdes options->enable_ssh_keysign = 0; 1212124211Sdes if (options->rekey_limit == -1) 1213124211Sdes options->rekey_limit = 0; 1214124211Sdes if (options->verify_host_key_dns == -1) 1215124211Sdes options->verify_host_key_dns = 0; 1216126277Sdes if (options->server_alive_interval == -1) 1217126277Sdes options->server_alive_interval = 0; 1218126277Sdes if (options->server_alive_count_max == -1) 1219126277Sdes options->server_alive_count_max = 3; 1220137019Sdes if (options->control_master == -1) 1221137019Sdes options->control_master = 0; 1222147005Sdes if (options->hash_known_hosts == -1) 1223147005Sdes options->hash_known_hosts = 0; 1224157019Sdes if (options->tun_open == -1) 1225157019Sdes options->tun_open = SSH_TUNMODE_NO; 1226157019Sdes if (options->tun_local == -1) 1227157019Sdes options->tun_local = SSH_TUNID_ANY; 1228157019Sdes if (options->tun_remote == -1) 1229157019Sdes options->tun_remote = SSH_TUNID_ANY; 1230157019Sdes if (options->permit_local_command == -1) 1231157019Sdes options->permit_local_command = 0; 1232197679Sdes if (options->use_roaming == -1) 1233197679Sdes options->use_roaming = 1; 1234181111Sdes if (options->visual_host_key == -1) 1235181111Sdes options->visual_host_key = 0; 1236192595Sdes if (options->zero_knowledge_password_authentication == -1) 1237192595Sdes options->zero_knowledge_password_authentication = 0; 1238157019Sdes /* options->local_command should not be set by default */ 123957429Smarkm /* options->proxy_command should not be set by default */ 124057429Smarkm /* options->user will be set in the main program if appropriate */ 124157429Smarkm /* options->hostname will be set in the main program if appropriate */ 124276262Sgreen /* options->host_key_alias should not be set by default */ 124376262Sgreen /* options->preferred_authentications will be set in ssh */ 124457429Smarkm} 1245147005Sdes 1246147005Sdes/* 1247147005Sdes * parse_forward 1248147005Sdes * parses a string containing a port forwarding specification of the form: 1249192595Sdes * dynamicfwd == 0 1250147005Sdes * [listenhost:]listenport:connecthost:connectport 1251192595Sdes * dynamicfwd == 1 1252192595Sdes * [listenhost:]listenport 1253147005Sdes * returns number of arguments parsed or zero on error 1254147005Sdes */ 1255147005Sdesint 1256192595Sdesparse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 1257147005Sdes{ 1258147005Sdes int i; 1259147005Sdes char *p, *cp, *fwdarg[4]; 1260147005Sdes 1261147005Sdes memset(fwd, '\0', sizeof(*fwd)); 1262147005Sdes 1263147005Sdes cp = p = xstrdup(fwdspec); 1264147005Sdes 1265147005Sdes /* skip leading spaces */ 1266181111Sdes while (isspace(*cp)) 1267147005Sdes cp++; 1268147005Sdes 1269147005Sdes for (i = 0; i < 4; ++i) 1270147005Sdes if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1271147005Sdes break; 1272147005Sdes 1273192595Sdes /* Check for trailing garbage */ 1274147005Sdes if (cp != NULL) 1275147005Sdes i = 0; /* failure */ 1276147005Sdes 1277147005Sdes switch (i) { 1278192595Sdes case 1: 1279192595Sdes fwd->listen_host = NULL; 1280192595Sdes fwd->listen_port = a2port(fwdarg[0]); 1281192595Sdes fwd->connect_host = xstrdup("socks"); 1282192595Sdes break; 1283192595Sdes 1284192595Sdes case 2: 1285192595Sdes fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1286192595Sdes fwd->listen_port = a2port(fwdarg[1]); 1287192595Sdes fwd->connect_host = xstrdup("socks"); 1288192595Sdes break; 1289192595Sdes 1290147005Sdes case 3: 1291147005Sdes fwd->listen_host = NULL; 1292147005Sdes fwd->listen_port = a2port(fwdarg[0]); 1293147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1294147005Sdes fwd->connect_port = a2port(fwdarg[2]); 1295147005Sdes break; 1296147005Sdes 1297147005Sdes case 4: 1298147005Sdes fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1299147005Sdes fwd->listen_port = a2port(fwdarg[1]); 1300147005Sdes fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1301147005Sdes fwd->connect_port = a2port(fwdarg[3]); 1302147005Sdes break; 1303147005Sdes default: 1304147005Sdes i = 0; /* failure */ 1305147005Sdes } 1306147005Sdes 1307147005Sdes xfree(p); 1308147005Sdes 1309192595Sdes if (dynamicfwd) { 1310192595Sdes if (!(i == 1 || i == 2)) 1311192595Sdes goto fail_free; 1312192595Sdes } else { 1313192595Sdes if (!(i == 3 || i == 4)) 1314192595Sdes goto fail_free; 1315192595Sdes if (fwd->connect_port <= 0) 1316192595Sdes goto fail_free; 1317192595Sdes } 1318192595Sdes 1319192595Sdes if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 1320147005Sdes goto fail_free; 1321147005Sdes 1322147005Sdes if (fwd->connect_host != NULL && 1323147005Sdes strlen(fwd->connect_host) >= NI_MAXHOST) 1324147005Sdes goto fail_free; 1325192595Sdes if (fwd->listen_host != NULL && 1326192595Sdes strlen(fwd->listen_host) >= NI_MAXHOST) 1327192595Sdes goto fail_free; 1328147005Sdes 1329192595Sdes 1330147005Sdes return (i); 1331147005Sdes 1332147005Sdes fail_free: 1333192595Sdes if (fwd->connect_host != NULL) { 1334147005Sdes xfree(fwd->connect_host); 1335192595Sdes fwd->connect_host = NULL; 1336192595Sdes } 1337192595Sdes if (fwd->listen_host != NULL) { 1338147005Sdes xfree(fwd->listen_host); 1339192595Sdes fwd->listen_host = NULL; 1340192595Sdes } 1341147005Sdes return (0); 1342147005Sdes} 1343