readconf.c revision 99048
157429Smarkm/* 257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 457429Smarkm * All rights reserved 557429Smarkm * Functions for reading the configuration files. 660576Skris * 765674Skris * As far as I am concerned, the code I have written for this software 865674Skris * can be used freely for any purpose. Any derived versions of this 965674Skris * software must be clearly marked as such, and if the derived work is 1065674Skris * incompatible with the protocol description in the RFC file, it must be 1165674Skris * called by a name other than "ssh" or "Secure Shell". 1257429Smarkm */ 1357429Smarkm 1457429Smarkm#include "includes.h" 1598684SdesRCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); 1699048SdesRCSID("$FreeBSD: head/crypto/openssh/readconf.c 99048 2002-06-29 10:51:56Z des $"); 1757429Smarkm 1857429Smarkm#include "ssh.h" 1976262Sgreen#include "xmalloc.h" 2076262Sgreen#include "compat.h" 2176262Sgreen#include "cipher.h" 2276262Sgreen#include "pathnames.h" 2376262Sgreen#include "log.h" 2457429Smarkm#include "readconf.h" 2560576Skris#include "match.h" 2676262Sgreen#include "misc.h" 2776262Sgreen#include "kex.h" 2876262Sgreen#include "mac.h" 2957429Smarkm 3057429Smarkm/* Format of the configuration file: 3157429Smarkm 3257429Smarkm # Configuration data is parsed as follows: 3357429Smarkm # 1. command line options 3457429Smarkm # 2. user-specific file 3557429Smarkm # 3. system-wide file 3657429Smarkm # Any configuration value is only changed the first time it is set. 3757429Smarkm # Thus, host-specific definitions should be at the beginning of the 3857429Smarkm # configuration file, and defaults at the end. 3957429Smarkm 4057429Smarkm # Host-specific declarations. These may override anything above. A single 4157429Smarkm # host may match multiple declarations; these are processed in the order 4257429Smarkm # that they are given in. 4357429Smarkm 4457429Smarkm Host *.ngs.fi ngs.fi 4598684Sdes User foo 4657429Smarkm 4757429Smarkm Host fake.com 4857429Smarkm HostName another.host.name.real.org 4957429Smarkm User blaah 5057429Smarkm Port 34289 5157429Smarkm ForwardX11 no 5257429Smarkm ForwardAgent no 5357429Smarkm 5457429Smarkm Host books.com 5557429Smarkm RemoteForward 9999 shadows.cs.hut.fi:9999 5657429Smarkm Cipher 3des 5757429Smarkm 5857429Smarkm Host fascist.blob.com 5957429Smarkm Port 23123 6057429Smarkm User tylonen 6157429Smarkm RhostsAuthentication no 6257429Smarkm PasswordAuthentication no 6357429Smarkm 6457429Smarkm Host puukko.hut.fi 6557429Smarkm User t35124p 6657429Smarkm ProxyCommand ssh-proxy %h %p 6757429Smarkm 6857429Smarkm Host *.fr 6998684Sdes PublicKeyAuthentication no 7057429Smarkm 7157429Smarkm Host *.su 7257429Smarkm Cipher none 7357429Smarkm PasswordAuthentication no 7457429Smarkm 7557429Smarkm # Defaults for various options 7657429Smarkm Host * 7757429Smarkm ForwardAgent no 7876262Sgreen ForwardX11 no 7957429Smarkm RhostsAuthentication yes 8057429Smarkm PasswordAuthentication yes 8157429Smarkm RSAAuthentication yes 8257429Smarkm RhostsRSAAuthentication yes 8357429Smarkm StrictHostKeyChecking yes 8457429Smarkm KeepAlives no 8557429Smarkm IdentityFile ~/.ssh/identity 8657429Smarkm Port 22 8757429Smarkm EscapeChar ~ 8857429Smarkm 8957429Smarkm*/ 9057429Smarkm 9157429Smarkm/* Keyword tokens. */ 9257429Smarkm 9357429Smarkmtypedef enum { 9457429Smarkm oBadOption, 9557429Smarkm oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication, 9698684Sdes oPasswordAuthentication, oRSAAuthentication, 9776262Sgreen oChallengeResponseAuthentication, oXAuthLocation, 9873400Sassar#if defined(KRB4) || defined(KRB5) 9973400Sassar oKerberosAuthentication, 10092559Sdes#endif 10192559Sdes#if defined(AFS) || defined(KRB5) 10292559Sdes oKerberosTgtPassing, 10392559Sdes#endif 10457429Smarkm#ifdef AFS 10592559Sdes oAFSTokenPassing, 10657429Smarkm#endif 10757429Smarkm oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, 10857429Smarkm oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, 10957429Smarkm oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 11057429Smarkm oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 11176262Sgreen oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, 11276262Sgreen oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, 11376262Sgreen oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, 11476262Sgreen oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, 11576262Sgreen oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, 11692559Sdes oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, 11793698Sdes oClearAllForwardings, oNoHostAuthenticationForLocalhost, 11899048Sdes oVersionAddendum, 11998684Sdes oDeprecated 12057429Smarkm} OpCodes; 12157429Smarkm 12257429Smarkm/* Textual representations of the tokens. */ 12357429Smarkm 12457429Smarkmstatic struct { 12557429Smarkm const char *name; 12657429Smarkm OpCodes opcode; 12757429Smarkm} keywords[] = { 12857429Smarkm { "forwardagent", oForwardAgent }, 12957429Smarkm { "forwardx11", oForwardX11 }, 13065674Skris { "xauthlocation", oXAuthLocation }, 13157429Smarkm { "gatewayports", oGatewayPorts }, 13257429Smarkm { "useprivilegedport", oUsePrivilegedPort }, 13357429Smarkm { "rhostsauthentication", oRhostsAuthentication }, 13457429Smarkm { "passwordauthentication", oPasswordAuthentication }, 13569591Sgreen { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 13669591Sgreen { "kbdinteractivedevices", oKbdInteractiveDevices }, 13757429Smarkm { "rsaauthentication", oRSAAuthentication }, 13876262Sgreen { "pubkeyauthentication", oPubkeyAuthentication }, 13976262Sgreen { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 14076262Sgreen { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 14176262Sgreen { "hostbasedauthentication", oHostbasedAuthentication }, 14276262Sgreen { "challengeresponseauthentication", oChallengeResponseAuthentication }, 14376262Sgreen { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ 14476262Sgreen { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ 14573400Sassar#if defined(KRB4) || defined(KRB5) 14673400Sassar { "kerberosauthentication", oKerberosAuthentication }, 14792559Sdes#endif 14892559Sdes#if defined(AFS) || defined(KRB5) 14992559Sdes { "kerberostgtpassing", oKerberosTgtPassing }, 15092559Sdes#endif 15157429Smarkm#ifdef AFS 15257429Smarkm { "afstokenpassing", oAFSTokenPassing }, 15357429Smarkm#endif 15498684Sdes { "fallbacktorsh", oDeprecated }, 15598684Sdes { "usersh", oDeprecated }, 15657429Smarkm { "identityfile", oIdentityFile }, 15776262Sgreen { "identityfile2", oIdentityFile }, /* alias */ 15857429Smarkm { "hostname", oHostName }, 15976262Sgreen { "hostkeyalias", oHostKeyAlias }, 16057429Smarkm { "proxycommand", oProxyCommand }, 16157429Smarkm { "port", oPort }, 16257429Smarkm { "cipher", oCipher }, 16360576Skris { "ciphers", oCiphers }, 16476262Sgreen { "macs", oMacs }, 16560576Skris { "protocol", oProtocol }, 16657429Smarkm { "remoteforward", oRemoteForward }, 16757429Smarkm { "localforward", oLocalForward }, 16857429Smarkm { "user", oUser }, 16957429Smarkm { "host", oHost }, 17057429Smarkm { "escapechar", oEscapeChar }, 17157429Smarkm { "globalknownhostsfile", oGlobalKnownHostsFile }, 17292559Sdes { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ 17360576Skris { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, 17492559Sdes { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ 17557429Smarkm { "connectionattempts", oConnectionAttempts }, 17657429Smarkm { "batchmode", oBatchMode }, 17757429Smarkm { "checkhostip", oCheckHostIP }, 17857429Smarkm { "stricthostkeychecking", oStrictHostKeyChecking }, 17957429Smarkm { "compression", oCompression }, 18057429Smarkm { "compressionlevel", oCompressionLevel }, 18157429Smarkm { "keepalive", oKeepAlives }, 18257429Smarkm { "numberofpasswordprompts", oNumberOfPasswordPrompts }, 18357429Smarkm { "loglevel", oLogLevel }, 18476262Sgreen { "dynamicforward", oDynamicForward }, 18576262Sgreen { "preferredauthentications", oPreferredAuthentications }, 18676262Sgreen { "hostkeyalgorithms", oHostKeyAlgorithms }, 18792559Sdes { "bindaddress", oBindAddress }, 18892559Sdes { "smartcarddevice", oSmartcardDevice }, 18992559Sdes { "clearallforwardings", oClearAllForwardings }, 19092559Sdes { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 19199048Sdes { "versionaddendum", oVersionAddendum }, 19292559Sdes { NULL, oBadOption } 19357429Smarkm}; 19457429Smarkm 19557429Smarkm/* 19657429Smarkm * Adds a local TCP/IP port forward to options. Never returns if there is an 19757429Smarkm * error. 19857429Smarkm */ 19957429Smarkm 20060576Skrisvoid 20157429Smarkmadd_local_forward(Options *options, u_short port, const char *host, 20257429Smarkm u_short host_port) 20357429Smarkm{ 20457429Smarkm Forward *fwd; 20598941Sdes#ifndef HAVE_CYGWIN 20657429Smarkm extern uid_t original_real_uid; 20757429Smarkm if (port < IPPORT_RESERVED && original_real_uid != 0) 20876262Sgreen fatal("Privileged ports can only be forwarded by root."); 20998941Sdes#endif 21057429Smarkm if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 21157429Smarkm fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); 21257429Smarkm fwd = &options->local_forwards[options->num_local_forwards++]; 21357429Smarkm fwd->port = port; 21457429Smarkm fwd->host = xstrdup(host); 21557429Smarkm fwd->host_port = host_port; 21657429Smarkm} 21757429Smarkm 21857429Smarkm/* 21957429Smarkm * Adds a remote TCP/IP port forward to options. Never returns if there is 22057429Smarkm * an error. 22157429Smarkm */ 22257429Smarkm 22360576Skrisvoid 22457429Smarkmadd_remote_forward(Options *options, u_short port, const char *host, 22557429Smarkm u_short host_port) 22657429Smarkm{ 22757429Smarkm Forward *fwd; 22857429Smarkm if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) 22957429Smarkm fatal("Too many remote forwards (max %d).", 23092559Sdes SSH_MAX_FORWARDS_PER_DIRECTION); 23157429Smarkm fwd = &options->remote_forwards[options->num_remote_forwards++]; 23257429Smarkm fwd->port = port; 23357429Smarkm fwd->host = xstrdup(host); 23457429Smarkm fwd->host_port = host_port; 23557429Smarkm} 23657429Smarkm 23792559Sdesstatic void 23892559Sdesclear_forwardings(Options *options) 23992559Sdes{ 24092559Sdes int i; 24192559Sdes 24292559Sdes for (i = 0; i < options->num_local_forwards; i++) 24392559Sdes xfree(options->local_forwards[i].host); 24492559Sdes options->num_local_forwards = 0; 24592559Sdes for (i = 0; i < options->num_remote_forwards; i++) 24692559Sdes xfree(options->remote_forwards[i].host); 24792559Sdes options->num_remote_forwards = 0; 24892559Sdes} 24992559Sdes 25057429Smarkm/* 25176262Sgreen * Returns the number of the token pointed to by cp or oBadOption. 25257429Smarkm */ 25357429Smarkm 25460576Skrisstatic OpCodes 25557429Smarkmparse_token(const char *cp, const char *filename, int linenum) 25657429Smarkm{ 25776262Sgreen u_int i; 25857429Smarkm 25957429Smarkm for (i = 0; keywords[i].name; i++) 26057429Smarkm if (strcasecmp(cp, keywords[i].name) == 0) 26157429Smarkm return keywords[i].opcode; 26257429Smarkm 26376262Sgreen error("%s: line %d: Bad configuration option: %s", 26476262Sgreen filename, linenum, cp); 26557429Smarkm return oBadOption; 26657429Smarkm} 26757429Smarkm 26857429Smarkm/* 26957429Smarkm * Processes a single option line as used in the configuration files. This 27057429Smarkm * only sets those values that have not already been set. 27157429Smarkm */ 27257429Smarkm 27357429Smarkmint 27457429Smarkmprocess_config_line(Options *options, const char *host, 27557429Smarkm char *line, const char *filename, int linenum, 27657429Smarkm int *activep) 27757429Smarkm{ 27865674Skris char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg; 27957429Smarkm int opcode, *intptr, value; 28057429Smarkm u_short fwd_port, fwd_host_port; 28192559Sdes char sfwd_host_port[6]; 28257429Smarkm 28365674Skris s = line; 28465674Skris /* Get the keyword. (Each line is supposed to begin with a keyword). */ 28565674Skris keyword = strdelim(&s); 28665674Skris /* Ignore leading whitespace. */ 28765674Skris if (*keyword == '\0') 28865674Skris keyword = strdelim(&s); 28976262Sgreen if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') 29057429Smarkm return 0; 29157429Smarkm 29265674Skris opcode = parse_token(keyword, filename, linenum); 29357429Smarkm 29457429Smarkm switch (opcode) { 29557429Smarkm case oBadOption: 29657429Smarkm /* don't panic, but count bad options */ 29757429Smarkm return -1; 29857429Smarkm /* NOTREACHED */ 29957429Smarkm case oForwardAgent: 30057429Smarkm intptr = &options->forward_agent; 30157429Smarkmparse_flag: 30265674Skris arg = strdelim(&s); 30365674Skris if (!arg || *arg == '\0') 30457429Smarkm fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); 30557429Smarkm value = 0; /* To avoid compiler warning... */ 30665674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 30757429Smarkm value = 1; 30865674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 30957429Smarkm value = 0; 31057429Smarkm else 31157429Smarkm fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); 31257429Smarkm if (*activep && *intptr == -1) 31357429Smarkm *intptr = value; 31457429Smarkm break; 31557429Smarkm 31657429Smarkm case oForwardX11: 31757429Smarkm intptr = &options->forward_x11; 31857429Smarkm goto parse_flag; 31957429Smarkm 32057429Smarkm case oGatewayPorts: 32157429Smarkm intptr = &options->gateway_ports; 32257429Smarkm goto parse_flag; 32357429Smarkm 32457429Smarkm case oUsePrivilegedPort: 32557429Smarkm intptr = &options->use_privileged_port; 32657429Smarkm goto parse_flag; 32757429Smarkm 32857429Smarkm case oRhostsAuthentication: 32957429Smarkm intptr = &options->rhosts_authentication; 33057429Smarkm goto parse_flag; 33157429Smarkm 33257429Smarkm case oPasswordAuthentication: 33357429Smarkm intptr = &options->password_authentication; 33457429Smarkm goto parse_flag; 33557429Smarkm 33669591Sgreen case oKbdInteractiveAuthentication: 33769591Sgreen intptr = &options->kbd_interactive_authentication; 33869591Sgreen goto parse_flag; 33969591Sgreen 34069591Sgreen case oKbdInteractiveDevices: 34169591Sgreen charptr = &options->kbd_interactive_devices; 34269591Sgreen goto parse_string; 34369591Sgreen 34476262Sgreen case oPubkeyAuthentication: 34576262Sgreen intptr = &options->pubkey_authentication; 34660576Skris goto parse_flag; 34760576Skris 34857429Smarkm case oRSAAuthentication: 34957429Smarkm intptr = &options->rsa_authentication; 35057429Smarkm goto parse_flag; 35157429Smarkm 35257429Smarkm case oRhostsRSAAuthentication: 35357429Smarkm intptr = &options->rhosts_rsa_authentication; 35457429Smarkm goto parse_flag; 35557429Smarkm 35676262Sgreen case oHostbasedAuthentication: 35776262Sgreen intptr = &options->hostbased_authentication; 35857429Smarkm goto parse_flag; 35957429Smarkm 36092559Sdes case oChallengeResponseAuthentication: 36192559Sdes intptr = &options->challenge_response_authentication; 36292559Sdes goto parse_flag; 36373400Sassar#if defined(KRB4) || defined(KRB5) 36473400Sassar case oKerberosAuthentication: 36573400Sassar intptr = &options->kerberos_authentication; 36657429Smarkm goto parse_flag; 36792559Sdes#endif 36892559Sdes#if defined(AFS) || defined(KRB5) 36992559Sdes case oKerberosTgtPassing: 37092559Sdes intptr = &options->kerberos_tgt_passing; 37176262Sgreen goto parse_flag; 37292559Sdes#endif 37357429Smarkm#ifdef AFS 37457429Smarkm case oAFSTokenPassing: 37557429Smarkm intptr = &options->afs_token_passing; 37657429Smarkm goto parse_flag; 37757429Smarkm#endif 37857429Smarkm case oBatchMode: 37957429Smarkm intptr = &options->batch_mode; 38057429Smarkm goto parse_flag; 38157429Smarkm 38257429Smarkm case oCheckHostIP: 38357429Smarkm intptr = &options->check_host_ip; 38457429Smarkm goto parse_flag; 38557429Smarkm 38657429Smarkm case oStrictHostKeyChecking: 38757429Smarkm intptr = &options->strict_host_key_checking; 38865674Skris arg = strdelim(&s); 38965674Skris if (!arg || *arg == '\0') 39076262Sgreen fatal("%.200s line %d: Missing yes/no/ask argument.", 39192559Sdes filename, linenum); 39257429Smarkm value = 0; /* To avoid compiler warning... */ 39365674Skris if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) 39457429Smarkm value = 1; 39565674Skris else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) 39657429Smarkm value = 0; 39765674Skris else if (strcmp(arg, "ask") == 0) 39857429Smarkm value = 2; 39957429Smarkm else 40057429Smarkm fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); 40157429Smarkm if (*activep && *intptr == -1) 40257429Smarkm *intptr = value; 40357429Smarkm break; 40457429Smarkm 40557429Smarkm case oCompression: 40657429Smarkm intptr = &options->compression; 40757429Smarkm goto parse_flag; 40857429Smarkm 40957429Smarkm case oKeepAlives: 41057429Smarkm intptr = &options->keepalives; 41157429Smarkm goto parse_flag; 41257429Smarkm 41392559Sdes case oNoHostAuthenticationForLocalhost: 41492559Sdes intptr = &options->no_host_authentication_for_localhost; 41592559Sdes goto parse_flag; 41692559Sdes 41757429Smarkm case oNumberOfPasswordPrompts: 41857429Smarkm intptr = &options->number_of_password_prompts; 41957429Smarkm goto parse_int; 42057429Smarkm 42157429Smarkm case oCompressionLevel: 42257429Smarkm intptr = &options->compression_level; 42357429Smarkm goto parse_int; 42457429Smarkm 42557429Smarkm case oIdentityFile: 42665674Skris arg = strdelim(&s); 42765674Skris if (!arg || *arg == '\0') 42857429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 42957429Smarkm if (*activep) { 43076262Sgreen intptr = &options->num_identity_files; 43160576Skris if (*intptr >= SSH_MAX_IDENTITY_FILES) 43257429Smarkm fatal("%.200s line %d: Too many identity files specified (max %d).", 43392559Sdes filename, linenum, SSH_MAX_IDENTITY_FILES); 43476262Sgreen charptr = &options->identity_files[*intptr]; 43565674Skris *charptr = xstrdup(arg); 43660576Skris *intptr = *intptr + 1; 43757429Smarkm } 43857429Smarkm break; 43957429Smarkm 44065674Skris case oXAuthLocation: 44165674Skris charptr=&options->xauth_location; 44265674Skris goto parse_string; 44365674Skris 44457429Smarkm case oUser: 44557429Smarkm charptr = &options->user; 44657429Smarkmparse_string: 44765674Skris arg = strdelim(&s); 44865674Skris if (!arg || *arg == '\0') 44957429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 45057429Smarkm if (*activep && *charptr == NULL) 45165674Skris *charptr = xstrdup(arg); 45257429Smarkm break; 45357429Smarkm 45457429Smarkm case oGlobalKnownHostsFile: 45557429Smarkm charptr = &options->system_hostfile; 45657429Smarkm goto parse_string; 45757429Smarkm 45857429Smarkm case oUserKnownHostsFile: 45957429Smarkm charptr = &options->user_hostfile; 46057429Smarkm goto parse_string; 46157429Smarkm 46260576Skris case oGlobalKnownHostsFile2: 46360576Skris charptr = &options->system_hostfile2; 46460576Skris goto parse_string; 46560576Skris 46660576Skris case oUserKnownHostsFile2: 46760576Skris charptr = &options->user_hostfile2; 46860576Skris goto parse_string; 46960576Skris 47057429Smarkm case oHostName: 47157429Smarkm charptr = &options->hostname; 47257429Smarkm goto parse_string; 47357429Smarkm 47476262Sgreen case oHostKeyAlias: 47576262Sgreen charptr = &options->host_key_alias; 47676262Sgreen goto parse_string; 47776262Sgreen 47876262Sgreen case oPreferredAuthentications: 47976262Sgreen charptr = &options->preferred_authentications; 48076262Sgreen goto parse_string; 48176262Sgreen 48292559Sdes case oBindAddress: 48392559Sdes charptr = &options->bind_address; 48492559Sdes goto parse_string; 48592559Sdes 48692559Sdes case oSmartcardDevice: 48792559Sdes charptr = &options->smartcard_device; 48892559Sdes goto parse_string; 48992559Sdes 49057429Smarkm case oProxyCommand: 49157429Smarkm charptr = &options->proxy_command; 49257429Smarkm string = xstrdup(""); 49365674Skris while ((arg = strdelim(&s)) != NULL && *arg != '\0') { 49465674Skris string = xrealloc(string, strlen(string) + strlen(arg) + 2); 49557429Smarkm strcat(string, " "); 49665674Skris strcat(string, arg); 49757429Smarkm } 49857429Smarkm if (*activep && *charptr == NULL) 49957429Smarkm *charptr = string; 50057429Smarkm else 50157429Smarkm xfree(string); 50257429Smarkm return 0; 50357429Smarkm 50457429Smarkm case oPort: 50557429Smarkm intptr = &options->port; 50657429Smarkmparse_int: 50765674Skris arg = strdelim(&s); 50865674Skris if (!arg || *arg == '\0') 50957429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 51065674Skris if (arg[0] < '0' || arg[0] > '9') 51157429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 51257429Smarkm 51357429Smarkm /* Octal, decimal, or hex format? */ 51465674Skris value = strtol(arg, &endofnumber, 0); 51565674Skris if (arg == endofnumber) 51657429Smarkm fatal("%.200s line %d: Bad number.", filename, linenum); 51757429Smarkm if (*activep && *intptr == -1) 51857429Smarkm *intptr = value; 51957429Smarkm break; 52057429Smarkm 52157429Smarkm case oConnectionAttempts: 52257429Smarkm intptr = &options->connection_attempts; 52357429Smarkm goto parse_int; 52457429Smarkm 52557429Smarkm case oCipher: 52657429Smarkm intptr = &options->cipher; 52765674Skris arg = strdelim(&s); 52865674Skris if (!arg || *arg == '\0') 52961203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 53065674Skris value = cipher_number(arg); 53157429Smarkm if (value == -1) 53257429Smarkm fatal("%.200s line %d: Bad cipher '%s'.", 53392559Sdes filename, linenum, arg ? arg : "<NONE>"); 53457429Smarkm if (*activep && *intptr == -1) 53557429Smarkm *intptr = value; 53657429Smarkm break; 53757429Smarkm 53860576Skris case oCiphers: 53965674Skris arg = strdelim(&s); 54065674Skris if (!arg || *arg == '\0') 54161203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 54265674Skris if (!ciphers_valid(arg)) 54360576Skris fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", 54492559Sdes filename, linenum, arg ? arg : "<NONE>"); 54560576Skris if (*activep && options->ciphers == NULL) 54665674Skris options->ciphers = xstrdup(arg); 54760576Skris break; 54860576Skris 54976262Sgreen case oMacs: 55076262Sgreen arg = strdelim(&s); 55176262Sgreen if (!arg || *arg == '\0') 55276262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 55376262Sgreen if (!mac_valid(arg)) 55476262Sgreen fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", 55592559Sdes filename, linenum, arg ? arg : "<NONE>"); 55676262Sgreen if (*activep && options->macs == NULL) 55776262Sgreen options->macs = xstrdup(arg); 55876262Sgreen break; 55976262Sgreen 56076262Sgreen case oHostKeyAlgorithms: 56176262Sgreen arg = strdelim(&s); 56276262Sgreen if (!arg || *arg == '\0') 56376262Sgreen fatal("%.200s line %d: Missing argument.", filename, linenum); 56476262Sgreen if (!key_names_valid2(arg)) 56576262Sgreen fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", 56692559Sdes filename, linenum, arg ? arg : "<NONE>"); 56776262Sgreen if (*activep && options->hostkeyalgorithms == NULL) 56876262Sgreen options->hostkeyalgorithms = xstrdup(arg); 56976262Sgreen break; 57076262Sgreen 57160576Skris case oProtocol: 57260576Skris intptr = &options->protocol; 57365674Skris arg = strdelim(&s); 57465674Skris if (!arg || *arg == '\0') 57561203Skris fatal("%.200s line %d: Missing argument.", filename, linenum); 57665674Skris value = proto_spec(arg); 57760576Skris if (value == SSH_PROTO_UNKNOWN) 57860576Skris fatal("%.200s line %d: Bad protocol spec '%s'.", 57992559Sdes filename, linenum, arg ? arg : "<NONE>"); 58060576Skris if (*activep && *intptr == SSH_PROTO_UNKNOWN) 58160576Skris *intptr = value; 58260576Skris break; 58360576Skris 58457429Smarkm case oLogLevel: 58557429Smarkm intptr = (int *) &options->log_level; 58665674Skris arg = strdelim(&s); 58765674Skris value = log_level_number(arg); 58892559Sdes if (value == SYSLOG_LEVEL_NOT_SET) 58976262Sgreen fatal("%.200s line %d: unsupported log level '%s'", 59092559Sdes filename, linenum, arg ? arg : "<NONE>"); 59192559Sdes if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) 59257429Smarkm *intptr = (LogLevel) value; 59357429Smarkm break; 59457429Smarkm 59592559Sdes case oLocalForward: 59657429Smarkm case oRemoteForward: 59765674Skris arg = strdelim(&s); 59865674Skris if (!arg || *arg == '\0') 59992559Sdes fatal("%.200s line %d: Missing port argument.", 60092559Sdes filename, linenum); 60192559Sdes if ((fwd_port = a2port(arg)) == 0) 60292559Sdes fatal("%.200s line %d: Bad listen port.", 60392559Sdes filename, linenum); 60465674Skris arg = strdelim(&s); 60565674Skris if (!arg || *arg == '\0') 60657429Smarkm fatal("%.200s line %d: Missing second argument.", 60792559Sdes filename, linenum); 60892559Sdes if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && 60992559Sdes sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) 61092559Sdes fatal("%.200s line %d: Bad forwarding specification.", 61192559Sdes filename, linenum); 61292559Sdes if ((fwd_host_port = a2port(sfwd_host_port)) == 0) 61392559Sdes fatal("%.200s line %d: Bad forwarding port.", 61492559Sdes filename, linenum); 61592559Sdes if (*activep) { 61692559Sdes if (opcode == oLocalForward) 61792559Sdes add_local_forward(options, fwd_port, buf, 61892559Sdes fwd_host_port); 61992559Sdes else if (opcode == oRemoteForward) 62092559Sdes add_remote_forward(options, fwd_port, buf, 62192559Sdes fwd_host_port); 62292559Sdes } 62357429Smarkm break; 62457429Smarkm 62576262Sgreen case oDynamicForward: 62676262Sgreen arg = strdelim(&s); 62776262Sgreen if (!arg || *arg == '\0') 62876262Sgreen fatal("%.200s line %d: Missing port argument.", 62976262Sgreen filename, linenum); 63076262Sgreen fwd_port = a2port(arg); 63176262Sgreen if (fwd_port == 0) 63276262Sgreen fatal("%.200s line %d: Badly formatted port number.", 63376262Sgreen filename, linenum); 63492559Sdes if (*activep) 63592559Sdes add_local_forward(options, fwd_port, "socks4", 0); 63676262Sgreen break; 63776262Sgreen 63892559Sdes case oClearAllForwardings: 63992559Sdes intptr = &options->clear_forwardings; 64092559Sdes goto parse_flag; 64192559Sdes 64257429Smarkm case oHost: 64357429Smarkm *activep = 0; 64465674Skris while ((arg = strdelim(&s)) != NULL && *arg != '\0') 64565674Skris if (match_pattern(host, arg)) { 64665674Skris debug("Applying options for %.100s", arg); 64757429Smarkm *activep = 1; 64857429Smarkm break; 64957429Smarkm } 65065674Skris /* Avoid garbage check below, as strdelim is done. */ 65157429Smarkm return 0; 65257429Smarkm 65357429Smarkm case oEscapeChar: 65457429Smarkm intptr = &options->escape_char; 65565674Skris arg = strdelim(&s); 65665674Skris if (!arg || *arg == '\0') 65757429Smarkm fatal("%.200s line %d: Missing argument.", filename, linenum); 65865674Skris if (arg[0] == '^' && arg[2] == 0 && 65976262Sgreen (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) 66076262Sgreen value = (u_char) arg[1] & 31; 66165674Skris else if (strlen(arg) == 1) 66276262Sgreen value = (u_char) arg[0]; 66365674Skris else if (strcmp(arg, "none") == 0) 66492559Sdes value = SSH_ESCAPECHAR_NONE; 66557429Smarkm else { 66657429Smarkm fatal("%.200s line %d: Bad escape character.", 66792559Sdes filename, linenum); 66857429Smarkm /* NOTREACHED */ 66957429Smarkm value = 0; /* Avoid compiler warning. */ 67057429Smarkm } 67157429Smarkm if (*activep && *intptr == -1) 67257429Smarkm *intptr = value; 67357429Smarkm break; 67457429Smarkm 67599048Sdes case oVersionAddendum: 67699048Sdes ssh_version_set_addendum(strtok(s, "\n")); 67799048Sdes do { 67899048Sdes arg = strdelim(&s); 67999048Sdes } while (arg != NULL && *arg != '\0'); 68099048Sdes break; 68199048Sdes 68298684Sdes case oDeprecated: 68398684Sdes debug("%s line %d: Deprecated option \"%s\"", 68498684Sdes filename, linenum, keyword); 68598684Sdes return 0; 68698684Sdes 68757429Smarkm default: 68857429Smarkm fatal("process_config_line: Unimplemented opcode %d", opcode); 68957429Smarkm } 69057429Smarkm 69157429Smarkm /* Check that there is no garbage at end of line. */ 69276262Sgreen if ((arg = strdelim(&s)) != NULL && *arg != '\0') { 69365674Skris fatal("%.200s line %d: garbage at end of line; \"%.200s\".", 69492559Sdes filename, linenum, arg); 69565674Skris } 69657429Smarkm return 0; 69757429Smarkm} 69857429Smarkm 69957429Smarkm 70057429Smarkm/* 70157429Smarkm * Reads the config file and modifies the options accordingly. Options 70257429Smarkm * should already be initialized before this call. This never returns if 70392559Sdes * there is an error. If the file does not exist, this returns 0. 70457429Smarkm */ 70557429Smarkm 70692559Sdesint 70757429Smarkmread_config_file(const char *filename, const char *host, Options *options) 70857429Smarkm{ 70957429Smarkm FILE *f; 71057429Smarkm char line[1024]; 71157429Smarkm int active, linenum; 71257429Smarkm int bad_options = 0; 71357429Smarkm 71457429Smarkm /* Open the file. */ 71557429Smarkm f = fopen(filename, "r"); 71657429Smarkm if (!f) 71792559Sdes return 0; 71857429Smarkm 71957429Smarkm debug("Reading configuration data %.200s", filename); 72057429Smarkm 72157429Smarkm /* 72257429Smarkm * Mark that we are now processing the options. This flag is turned 72357429Smarkm * on/off by Host specifications. 72457429Smarkm */ 72557429Smarkm active = 1; 72657429Smarkm linenum = 0; 72757429Smarkm while (fgets(line, sizeof(line), f)) { 72857429Smarkm /* Update line number counter. */ 72957429Smarkm linenum++; 73057429Smarkm if (process_config_line(options, host, line, filename, linenum, &active) != 0) 73157429Smarkm bad_options++; 73257429Smarkm } 73357429Smarkm fclose(f); 73457429Smarkm if (bad_options > 0) 73576262Sgreen fatal("%s: terminating, %d bad configuration options", 73692559Sdes filename, bad_options); 73792559Sdes return 1; 73857429Smarkm} 73957429Smarkm 74057429Smarkm/* 74157429Smarkm * Initializes options to special values that indicate that they have not yet 74257429Smarkm * been set. Read_config_file will only set options with this value. Options 74357429Smarkm * are processed in the following order: command line, user config file, 74457429Smarkm * system config file. Last, fill_default_options is called. 74557429Smarkm */ 74657429Smarkm 74760576Skrisvoid 74857429Smarkminitialize_options(Options * options) 74957429Smarkm{ 75057429Smarkm memset(options, 'X', sizeof(*options)); 75157429Smarkm options->forward_agent = -1; 75257429Smarkm options->forward_x11 = -1; 75365674Skris options->xauth_location = NULL; 75457429Smarkm options->gateway_ports = -1; 75557429Smarkm options->use_privileged_port = -1; 75657429Smarkm options->rhosts_authentication = -1; 75757429Smarkm options->rsa_authentication = -1; 75876262Sgreen options->pubkey_authentication = -1; 75992559Sdes options->challenge_response_authentication = -1; 76073400Sassar#if defined(KRB4) || defined(KRB5) 76173400Sassar options->kerberos_authentication = -1; 76257429Smarkm#endif 76392559Sdes#if defined(AFS) || defined(KRB5) 76492559Sdes options->kerberos_tgt_passing = -1; 76592559Sdes#endif 76657429Smarkm#ifdef AFS 76757429Smarkm options->afs_token_passing = -1; 76857429Smarkm#endif 76957429Smarkm options->password_authentication = -1; 77069591Sgreen options->kbd_interactive_authentication = -1; 77169591Sgreen options->kbd_interactive_devices = NULL; 77257429Smarkm options->rhosts_rsa_authentication = -1; 77376262Sgreen options->hostbased_authentication = -1; 77457429Smarkm options->batch_mode = -1; 77557429Smarkm options->check_host_ip = -1; 77657429Smarkm options->strict_host_key_checking = -1; 77757429Smarkm options->compression = -1; 77857429Smarkm options->keepalives = -1; 77957429Smarkm options->compression_level = -1; 78057429Smarkm options->port = -1; 78157429Smarkm options->connection_attempts = -1; 78257429Smarkm options->number_of_password_prompts = -1; 78357429Smarkm options->cipher = -1; 78460576Skris options->ciphers = NULL; 78576262Sgreen options->macs = NULL; 78676262Sgreen options->hostkeyalgorithms = NULL; 78760576Skris options->protocol = SSH_PROTO_UNKNOWN; 78857429Smarkm options->num_identity_files = 0; 78957429Smarkm options->hostname = NULL; 79076262Sgreen options->host_key_alias = NULL; 79157429Smarkm options->proxy_command = NULL; 79257429Smarkm options->user = NULL; 79357429Smarkm options->escape_char = -1; 79457429Smarkm options->system_hostfile = NULL; 79557429Smarkm options->user_hostfile = NULL; 79660576Skris options->system_hostfile2 = NULL; 79760576Skris options->user_hostfile2 = NULL; 79857429Smarkm options->num_local_forwards = 0; 79957429Smarkm options->num_remote_forwards = 0; 80092559Sdes options->clear_forwardings = -1; 80192559Sdes options->log_level = SYSLOG_LEVEL_NOT_SET; 80276262Sgreen options->preferred_authentications = NULL; 80392559Sdes options->bind_address = NULL; 80492559Sdes options->smartcard_device = NULL; 80592559Sdes options->no_host_authentication_for_localhost = - 1; 80657429Smarkm} 80757429Smarkm 80857429Smarkm/* 80957429Smarkm * Called after processing other sources of option data, this fills those 81057429Smarkm * options for which no value has been specified with their default values. 81157429Smarkm */ 81257429Smarkm 81360576Skrisvoid 81457429Smarkmfill_default_options(Options * options) 81557429Smarkm{ 81676262Sgreen int len; 81776262Sgreen 81857429Smarkm if (options->forward_agent == -1) 81961203Skris options->forward_agent = 0; 82057429Smarkm if (options->forward_x11 == -1) 82157708Sgreen options->forward_x11 = 0; 82265674Skris if (options->xauth_location == NULL) 82392559Sdes options->xauth_location = _PATH_XAUTH; 82457429Smarkm if (options->gateway_ports == -1) 82557429Smarkm options->gateway_ports = 0; 82657429Smarkm if (options->use_privileged_port == -1) 82776262Sgreen options->use_privileged_port = 0; 82857429Smarkm if (options->rhosts_authentication == -1) 82998684Sdes options->rhosts_authentication = 0; 83057429Smarkm if (options->rsa_authentication == -1) 83157429Smarkm options->rsa_authentication = 1; 83276262Sgreen if (options->pubkey_authentication == -1) 83376262Sgreen options->pubkey_authentication = 1; 83492559Sdes if (options->challenge_response_authentication == -1) 83592559Sdes options->challenge_response_authentication = 1; 83673400Sassar#if defined(KRB4) || defined(KRB5) 83773400Sassar if (options->kerberos_authentication == -1) 83873400Sassar options->kerberos_authentication = 1; 83992559Sdes#endif 84092559Sdes#if defined(AFS) || defined(KRB5) 84192559Sdes if (options->kerberos_tgt_passing == -1) 84292559Sdes options->kerberos_tgt_passing = 1; 84392559Sdes#endif 84457429Smarkm#ifdef AFS 84557429Smarkm if (options->afs_token_passing == -1) 84657429Smarkm options->afs_token_passing = 1; 84792559Sdes#endif 84857429Smarkm if (options->password_authentication == -1) 84957429Smarkm options->password_authentication = 1; 85069591Sgreen if (options->kbd_interactive_authentication == -1) 85176262Sgreen options->kbd_interactive_authentication = 1; 85257429Smarkm if (options->rhosts_rsa_authentication == -1) 85398684Sdes options->rhosts_rsa_authentication = 0; 85476262Sgreen if (options->hostbased_authentication == -1) 85576262Sgreen options->hostbased_authentication = 0; 85657429Smarkm if (options->batch_mode == -1) 85757429Smarkm options->batch_mode = 0; 85857429Smarkm if (options->check_host_ip == -1) 85999048Sdes options->check_host_ip = 0; 86057429Smarkm if (options->strict_host_key_checking == -1) 86157429Smarkm options->strict_host_key_checking = 2; /* 2 is default */ 86257429Smarkm if (options->compression == -1) 86357429Smarkm options->compression = 0; 86457429Smarkm if (options->keepalives == -1) 86557429Smarkm options->keepalives = 1; 86657429Smarkm if (options->compression_level == -1) 86757429Smarkm options->compression_level = 6; 86857429Smarkm if (options->port == -1) 86957429Smarkm options->port = 0; /* Filled in ssh_connect. */ 87057429Smarkm if (options->connection_attempts == -1) 87192559Sdes options->connection_attempts = 1; 87257429Smarkm if (options->number_of_password_prompts == -1) 87357429Smarkm options->number_of_password_prompts = 3; 87457429Smarkm /* Selected in ssh_login(). */ 87557429Smarkm if (options->cipher == -1) 87657429Smarkm options->cipher = SSH_CIPHER_NOT_SET; 87760576Skris /* options->ciphers, default set in myproposals.h */ 87876262Sgreen /* options->macs, default set in myproposals.h */ 87976262Sgreen /* options->hostkeyalgorithms, default set in myproposals.h */ 88060576Skris if (options->protocol == SSH_PROTO_UNKNOWN) 88176262Sgreen options->protocol = SSH_PROTO_1|SSH_PROTO_2; 88257429Smarkm if (options->num_identity_files == 0) { 88376262Sgreen if (options->protocol & SSH_PROTO_1) { 88476262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; 88576262Sgreen options->identity_files[options->num_identity_files] = 88676262Sgreen xmalloc(len); 88776262Sgreen snprintf(options->identity_files[options->num_identity_files++], 88876262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); 88976262Sgreen } 89076262Sgreen if (options->protocol & SSH_PROTO_2) { 89176262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; 89276262Sgreen options->identity_files[options->num_identity_files] = 89376262Sgreen xmalloc(len); 89476262Sgreen snprintf(options->identity_files[options->num_identity_files++], 89576262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); 89676262Sgreen 89776262Sgreen len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; 89876262Sgreen options->identity_files[options->num_identity_files] = 89976262Sgreen xmalloc(len); 90076262Sgreen snprintf(options->identity_files[options->num_identity_files++], 90176262Sgreen len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); 90276262Sgreen } 90357429Smarkm } 90457429Smarkm if (options->escape_char == -1) 90557429Smarkm options->escape_char = '~'; 90657429Smarkm if (options->system_hostfile == NULL) 90776262Sgreen options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; 90857429Smarkm if (options->user_hostfile == NULL) 90976262Sgreen options->user_hostfile = _PATH_SSH_USER_HOSTFILE; 91060576Skris if (options->system_hostfile2 == NULL) 91176262Sgreen options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; 91260576Skris if (options->user_hostfile2 == NULL) 91376262Sgreen options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; 91492559Sdes if (options->log_level == SYSLOG_LEVEL_NOT_SET) 91557429Smarkm options->log_level = SYSLOG_LEVEL_INFO; 91692559Sdes if (options->clear_forwardings == 1) 91792559Sdes clear_forwardings(options); 91892559Sdes if (options->no_host_authentication_for_localhost == - 1) 91992559Sdes options->no_host_authentication_for_localhost = 0; 92057429Smarkm /* options->proxy_command should not be set by default */ 92157429Smarkm /* options->user will be set in the main program if appropriate */ 92257429Smarkm /* options->hostname will be set in the main program if appropriate */ 92376262Sgreen /* options->host_key_alias should not be set by default */ 92476262Sgreen /* options->preferred_authentications will be set in ssh */ 92557429Smarkm} 926