*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.112 2003/05/16 03:27:12 djm Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.140 2005/05/16 15:30:51 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"
Host fascist.blob.com
Port 23123
User tylonen
- RhostsAuthentication no
PasswordAuthentication no
Host puukko.hut.fi
Host *
ForwardAgent no
ForwardX11 no
- RhostsAuthentication yes
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
StrictHostKeyChecking yes
- KeepAlives no
+ TcpKeepAlive no
IdentityFile ~/.ssh/identity
Port 22
EscapeChar ~
typedef enum {
oBadOption,
- oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
+ oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
- oKerberosAuthentication, oKerberosTgtPassing, oAFSTokenPassing,
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
- oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
+ oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
- oAddressFamily,
+ oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+ oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+ oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
oDeprecated, oUnsupported
} OpCodes;
} keywords[] = {
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
+ { "forwardx11trusted", oForwardX11Trusted },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
{ "useprivilegedport", oUsePrivilegedPort },
- { "rhostsauthentication", oRhostsAuthentication },
+ { "rhostsauthentication", oDeprecated },
{ "passwordauthentication", oPasswordAuthentication },
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
-#if defined(KRB4) || defined(KRB5)
- { "kerberosauthentication", oKerberosAuthentication },
- { "kerberostgtpassing", oKerberosTgtPassing },
-#else
{ "kerberosauthentication", oUnsupported },
{ "kerberostgtpassing", oUnsupported },
-#endif
-#if defined(AFS)
- { "afstokenpassing", oAFSTokenPassing },
-#else
{ "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+ { "gssapiauthentication", oGssAuthentication },
+ { "gssapidelegatecredentials", oGssDelegateCreds },
+#else
+ { "gssapiauthentication", oUnsupported },
+ { "gssapidelegatecredentials", oUnsupported },
#endif
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* alias */
+ { "identitiesonly", oIdentitiesOnly },
{ "hostname", oHostName },
{ "hostkeyalias", oHostKeyAlias },
{ "proxycommand", oProxyCommand },
{ "stricthostkeychecking", oStrictHostKeyChecking },
{ "compression", oCompression },
{ "compressionlevel", oCompressionLevel },
- { "keepalive", oKeepAlives },
+ { "tcpkeepalive", oTCPKeepAlive },
+ { "keepalive", oTCPKeepAlive }, /* obsolete */
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "loglevel", oLogLevel },
{ "dynamicforward", oDynamicForward },
#endif
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
-#ifdef DNS
{ "verifyhostkeydns", oVerifyHostKeyDNS },
-#else
- { "verifyhostkeydns", oUnsupported },
-#endif
{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
{ "rekeylimit", oRekeyLimit },
{ "connecttimeout", oConnectTimeout },
{ "addressfamily", oAddressFamily },
+ { "serveraliveinterval", oServerAliveInterval },
+ { "serveralivecountmax", oServerAliveCountMax },
+ { "sendenv", oSendEnv },
+ { "controlpath", oControlPath },
+ { "controlmaster", oControlMaster },
+ { "hashknownhosts", oHashKnownHosts },
{ NULL, oBadOption }
};
*/
void
-add_local_forward(Options *options, u_short port, const char *host,
- u_short host_port)
+add_local_forward(Options *options, const Forward *newfwd)
{
Forward *fwd;
#ifndef NO_IPPORT_RESERVED_CONCEPT
extern uid_t original_real_uid;
- if (port < IPPORT_RESERVED && original_real_uid != 0)
+ if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
fatal("Privileged ports can only be forwarded by root.");
#endif
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
fwd = &options->local_forwards[options->num_local_forwards++];
- fwd->port = port;
- fwd->host = xstrdup(host);
- fwd->host_port = host_port;
+
+ fwd->listen_host = (newfwd->listen_host == NULL) ?
+ NULL : xstrdup(newfwd->listen_host);
+ fwd->listen_port = newfwd->listen_port;
+ fwd->connect_host = xstrdup(newfwd->connect_host);
+ fwd->connect_port = newfwd->connect_port;
}
/*
*/
void
-add_remote_forward(Options *options, u_short port, const char *host,
- u_short host_port)
+add_remote_forward(Options *options, const Forward *newfwd)
{
Forward *fwd;
if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many remote forwards (max %d).",
SSH_MAX_FORWARDS_PER_DIRECTION);
fwd = &options->remote_forwards[options->num_remote_forwards++];
- fwd->port = port;
- fwd->host = xstrdup(host);
- fwd->host_port = host_port;
+
+ fwd->listen_host = (newfwd->listen_host == NULL) ?
+ NULL : xstrdup(newfwd->listen_host);
+ fwd->listen_port = newfwd->listen_port;
+ fwd->connect_host = xstrdup(newfwd->connect_host);
+ fwd->connect_port = newfwd->connect_port;
}
static void
{
int i;
- for (i = 0; i < options->num_local_forwards; i++)
- xfree(options->local_forwards[i].host);
+ for (i = 0; i < options->num_local_forwards; i++) {
+ if (options->local_forwards[i].listen_host != NULL)
+ xfree(options->local_forwards[i].listen_host);
+ xfree(options->local_forwards[i].connect_host);
+ }
options->num_local_forwards = 0;
- for (i = 0; i < options->num_remote_forwards; i++)
- xfree(options->remote_forwards[i].host);
+ for (i = 0; i < options->num_remote_forwards; i++) {
+ if (options->remote_forwards[i].listen_host != NULL)
+ xfree(options->remote_forwards[i].listen_host);
+ xfree(options->remote_forwards[i].connect_host);
+ }
options->num_remote_forwards = 0;
}
char *line, const char *filename, int linenum,
int *activep)
{
- char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
+ char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
int opcode, *intptr, value;
size_t len;
- u_short fwd_port, fwd_host_port;
- char sfwd_host_port[6];
- extern int IPv4or6;
+ Forward fwd;
/* Strip trailing whitespace */
- for(len = strlen(line) - 1; len > 0; len--) {
+ for (len = strlen(line) - 1; len > 0; len--) {
if (strchr(WHITESPACE, line[len]) == NULL)
break;
line[len] = '\0';
/* NOTREACHED */
case oConnectTimeout:
intptr = &options->connection_timeout;
-/* parse_time: */
+parse_time:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
intptr = &options->forward_x11;
goto parse_flag;
+ case oForwardX11Trusted:
+ intptr = &options->forward_x11_trusted;
+ goto parse_flag;
+
case oGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
intptr = &options->use_privileged_port;
goto parse_flag;
- case oRhostsAuthentication:
- intptr = &options->rhosts_authentication;
- goto parse_flag;
-
case oPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
intptr = &options->challenge_response_authentication;
goto parse_flag;
- case oKerberosAuthentication:
- intptr = &options->kerberos_authentication;
+ case oGssAuthentication:
+ intptr = &options->gss_authentication;
goto parse_flag;
- case oKerberosTgtPassing:
- intptr = &options->kerberos_tgt_passing;
- goto parse_flag;
-
- case oAFSTokenPassing:
- intptr = &options->afs_token_passing;
+ case oGssDelegateCreds:
+ intptr = &options->gss_deleg_creds;
goto parse_flag;
case oBatchMode:
case oVerifyHostKeyDNS:
intptr = &options->verify_host_key_dns;
- goto parse_flag;
+ goto parse_yesnoask;
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
+parse_yesnoask:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no/ask argument.",
intptr = &options->compression;
goto parse_flag;
- case oKeepAlives:
- intptr = &options->keepalives;
+ case oTCPKeepAlive:
+ intptr = &options->tcp_keep_alive;
goto parse_flag;
case oNoHostAuthenticationForLocalhost:
goto parse_string;
case oProxyCommand:
+ if (s == NULL)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
charptr = &options->proxy_command;
len = strspn(s, WHITESPACE "=");
if (*activep && *charptr == NULL)
case oLocalForward:
case oRemoteForward:
arg = strdelim(&s);
- if (!arg || *arg == '\0')
+ if (arg == NULL || *arg == '\0')
fatal("%.200s line %d: Missing port argument.",
filename, linenum);
- if ((fwd_port = a2port(arg)) == 0)
- fatal("%.200s line %d: Bad listen port.",
+ arg2 = strdelim(&s);
+ if (arg2 == NULL || *arg2 == '\0')
+ fatal("%.200s line %d: Missing target argument.",
filename, linenum);
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing second argument.",
- filename, linenum);
- if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
- sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
+
+ /* construct a string for parse_forward */
+ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+
+ if (parse_forward(&fwd, fwdarg) == 0)
fatal("%.200s line %d: Bad forwarding specification.",
filename, linenum);
- if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
- fatal("%.200s line %d: Bad forwarding port.",
- filename, linenum);
+
if (*activep) {
if (opcode == oLocalForward)
- add_local_forward(options, fwd_port, buf,
- fwd_host_port);
+ add_local_forward(options, &fwd);
else if (opcode == oRemoteForward)
- add_remote_forward(options, fwd_port, buf,
- fwd_host_port);
+ add_remote_forward(options, &fwd);
}
break;
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing port argument.",
filename, linenum);
- fwd_port = a2port(arg);
- if (fwd_port == 0)
+ memset(&fwd, '\0', sizeof(fwd));
+ fwd.connect_host = "socks";
+ fwd.listen_host = hpdelim(&arg);
+ if (fwd.listen_host == NULL ||
+ strlen(fwd.listen_host) >= NI_MAXHOST)
+ fatal("%.200s line %d: Bad forwarding specification.",
+ filename, linenum);
+ if (arg) {
+ fwd.listen_port = a2port(arg);
+ fwd.listen_host = cleanhostname(fwd.listen_host);
+ } else {
+ fwd.listen_port = a2port(fwd.listen_host);
+ fwd.listen_host = "";
+ }
+ if (fwd.listen_port == 0)
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
if (*activep)
- add_local_forward(options, fwd_port, "socks4", 0);
+ add_local_forward(options, &fwd);
break;
case oClearAllForwardings:
case oAddressFamily:
arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing address family.",
+ filename, linenum);
+ intptr = &options->address_family;
if (strcasecmp(arg, "inet") == 0)
- IPv4or6 = AF_INET;
+ value = AF_INET;
else if (strcasecmp(arg, "inet6") == 0)
- IPv4or6 = AF_INET6;
+ value = AF_INET6;
else if (strcasecmp(arg, "any") == 0)
- IPv4or6 = AF_UNSPEC;
+ value = AF_UNSPEC;
else
fatal("Unsupported AddressFamily \"%s\"", arg);
+ if (*activep && *intptr == -1)
+ *intptr = value;
break;
case oEnableSSHKeysign:
intptr = &options->enable_ssh_keysign;
goto parse_flag;
+ case oIdentitiesOnly:
+ intptr = &options->identities_only;
+ goto parse_flag;
+
+ case oServerAliveInterval:
+ intptr = &options->server_alive_interval;
+ goto parse_time;
+
+ case oServerAliveCountMax:
+ intptr = &options->server_alive_count_max;
+ goto parse_int;
+
+ case oSendEnv:
+ while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ if (strchr(arg, '=') != NULL)
+ fatal("%s line %d: Invalid environment name.",
+ filename, linenum);
+ if (!*activep)
+ continue;
+ if (options->num_send_env >= MAX_SEND_ENV)
+ fatal("%s line %d: too many send env.",
+ filename, linenum);
+ options->send_env[options->num_send_env++] =
+ xstrdup(arg);
+ }
+ break;
+
+ case oControlPath:
+ charptr = &options->control_path;
+ goto parse_string;
+
+ case oControlMaster:
+ intptr = &options->control_master;
+ goto parse_yesnoask;
+
+ case oHashKnownHosts:
+ intptr = &options->hash_known_hosts;
+ goto parse_flag;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
*/
int
-read_config_file(const char *filename, const char *host, Options *options)
+read_config_file(const char *filename, const char *host, Options *options,
+ int checkperm)
{
FILE *f;
char line[1024];
int bad_options = 0;
/* Open the file. */
- f = fopen(filename, "r");
- if (!f)
+ if ((f = fopen(filename, "r")) == NULL)
return 0;
+ if (checkperm) {
+ struct stat sb;
+
+ if (fstat(fileno(f), &sb) == -1)
+ fatal("fstat %s: %s", filename, strerror(errno));
+ if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+ (sb.st_mode & 022) != 0))
+ fatal("Bad owner or permissions on %s", filename);
+ }
+
debug("Reading configuration data %.200s", filename);
/*
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
options->forward_x11 = -1;
+ options->forward_x11_trusted = -1;
options->xauth_location = NULL;
options->gateway_ports = -1;
options->use_privileged_port = -1;
- options->rhosts_authentication = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
options->challenge_response_authentication = -1;
- options->kerberos_authentication = -1;
- options->kerberos_tgt_passing = -1;
- options->afs_token_passing = -1;
+ options->gss_authentication = -1;
+ options->gss_deleg_creds = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
options->compression = -1;
- options->keepalives = -1;
+ options->tcp_keep_alive = -1;
options->compression_level = -1;
options->port = -1;
+ options->address_family = -1;
options->connection_attempts = -1;
options->connection_timeout = -1;
options->number_of_password_prompts = -1;
options->smartcard_device = NULL;
options->enable_ssh_keysign = - 1;
options->no_host_authentication_for_localhost = - 1;
+ options->identities_only = - 1;
options->rekey_limit = - 1;
options->verify_host_key_dns = -1;
+ options->server_alive_interval = -1;
+ options->server_alive_count_max = -1;
+ options->num_send_env = 0;
+ options->control_path = NULL;
+ options->control_master = -1;
+ options->hash_known_hosts = -1;
}
/*
options->forward_agent = 0;
if (options->forward_x11 == -1)
options->forward_x11 = 0;
+ if (options->forward_x11_trusted == -1)
+ options->forward_x11_trusted = 0;
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->use_privileged_port == -1)
options->use_privileged_port = 0;
- if (options->rhosts_authentication == -1)
- options->rhosts_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
- if (options->kerberos_authentication == -1)
- options->kerberos_authentication = 1;
- if (options->kerberos_tgt_passing == -1)
- options->kerberos_tgt_passing = 1;
- if (options->afs_token_passing == -1)
- options->afs_token_passing = 1;
+ if (options->gss_authentication == -1)
+ options->gss_authentication = 0;
+ if (options->gss_deleg_creds == -1)
+ options->gss_deleg_creds = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
options->strict_host_key_checking = 2; /* 2 is default */
if (options->compression == -1)
options->compression = 0;
- if (options->keepalives == -1)
- options->keepalives = 1;
+ if (options->tcp_keep_alive == -1)
+ options->tcp_keep_alive = 1;
if (options->compression_level == -1)
options->compression_level = 6;
if (options->port == -1)
options->port = 0; /* Filled in ssh_connect. */
+ if (options->address_family == -1)
+ options->address_family = AF_UNSPEC;
if (options->connection_attempts == -1)
options->connection_attempts = 1;
if (options->number_of_password_prompts == -1)
clear_forwardings(options);
if (options->no_host_authentication_for_localhost == - 1)
options->no_host_authentication_for_localhost = 0;
+ if (options->identities_only == -1)
+ options->identities_only = 0;
if (options->enable_ssh_keysign == -1)
options->enable_ssh_keysign = 0;
if (options->rekey_limit == -1)
options->rekey_limit = 0;
if (options->verify_host_key_dns == -1)
options->verify_host_key_dns = 0;
+ if (options->server_alive_interval == -1)
+ options->server_alive_interval = 0;
+ if (options->server_alive_count_max == -1)
+ options->server_alive_count_max = 3;
+ if (options->control_master == -1)
+ options->control_master = 0;
+ if (options->hash_known_hosts == -1)
+ options->hash_known_hosts = 0;
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
/* options->preferred_authentications will be set in ssh */
}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ * [listenhost:]listenport:connecthost:connectport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec)
+{
+ int i;
+ char *p, *cp, *fwdarg[4];
+
+ memset(fwd, '\0', sizeof(*fwd));
+
+ cp = p = xstrdup(fwdspec);
+
+ /* skip leading spaces */
+ while (*cp && isspace(*cp))
+ cp++;
+
+ for (i = 0; i < 4; ++i)
+ if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+ break;
+
+ /* Check for trailing garbage in 4-arg case*/
+ if (cp != NULL)
+ i = 0; /* failure */
+
+ switch (i) {
+ case 3:
+ fwd->listen_host = NULL;
+ fwd->listen_port = a2port(fwdarg[0]);
+ fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+ fwd->connect_port = a2port(fwdarg[2]);
+ break;
+
+ case 4:
+ fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+ fwd->listen_port = a2port(fwdarg[1]);
+ fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+ fwd->connect_port = a2port(fwdarg[3]);
+ break;
+ default:
+ i = 0; /* failure */
+ }
+
+ xfree(p);
+
+ if (fwd->listen_port == 0 && fwd->connect_port == 0)
+ goto fail_free;
+
+ if (fwd->connect_host != NULL &&
+ strlen(fwd->connect_host) >= NI_MAXHOST)
+ goto fail_free;
+
+ return (i);
+
+ fail_free:
+ if (fwd->connect_host != NULL)
+ xfree(fwd->connect_host);
+ if (fwd->listen_host != NULL)
+ xfree(fwd->listen_host);
+ return (0);
+}