- djm@cvs.openbsd.org 2013/10/16 02:31:47

[readconf.c readconf.h roaming_client.c ssh.1 ssh.c ssh_config.5]
     [sshconnect.c sshconnect.h]
     Implement client-side hostname canonicalisation to allow an explicit
     search path of domain suffixes to use to convert unqualified host names
     to fully-qualified ones for host key matching.
     This is particularly useful for host certificates, which would otherwise
     need to list unqualified names alongside fully-qualified ones (and this
     causes a number of problems).
     "looks fine" markus@
This commit is contained in:
Damien Miller 2013-10-17 11:47:23 +11:00
parent d77b81f856
commit 0faf747e2f
9 changed files with 426 additions and 76 deletions

View File

@ -3,6 +3,16 @@
- jmc@cvs.openbsd.org 2013/10/15 14:10:25
[ssh.1 ssh_config.5]
tweak previous;
- djm@cvs.openbsd.org 2013/10/16 02:31:47
[readconf.c readconf.h roaming_client.c ssh.1 ssh.c ssh_config.5]
[sshconnect.c sshconnect.h]
Implement client-side hostname canonicalisation to allow an explicit
search path of domain suffixes to use to convert unqualified host names
to fully-qualified ones for host key matching.
This is particularly useful for host certificates, which would otherwise
need to list unqualified names alongside fully-qualified ones (and this
causes a number of problems).
"looks fine" markus@
20131015
- (djm) OpenBSD CVS Sync

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.207 2013/10/14 23:28:23 djm Exp $ */
/* $OpenBSD: readconf.c,v 1.208 2013/10/16 02:31:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -144,6 +144,8 @@ typedef enum {
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicaliseHostname, oCanonicaliseMaxDots,
oCanonicaliseFallbackLocal, oCanonicalisePermittedCNAMEs,
oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@ -257,6 +259,11 @@ static struct {
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
{ "proxyusefdpass", oProxyUseFdpass },
{ "canonicaldomains", oCanonicalDomains },
{ "canonicalisefallbacklocal", oCanonicaliseFallbackLocal },
{ "canonicalisehostname", oCanonicaliseHostname },
{ "canonicalisemaxdots", oCanonicaliseMaxDots },
{ "canonicalisepermittedcnames", oCanonicalisePermittedCNAMEs },
{ "ignoreunknown", oIgnoreUnknown },
{ NULL, oBadOption }
@ -535,6 +542,34 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
return result;
}
/* Check and prepare a domain name: removes trailing '.' and lowercases */
static void
valid_domain(char *name, const char *filename, int linenum)
{
size_t i, l = strlen(name);
u_char c, last = '\0';
if (l == 0)
fatal("%s line %d: empty hostname suffix", filename, linenum);
if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0]))
fatal("%s line %d: hostname suffix \"%.100s\" "
"starts with invalid character", filename, linenum, name);
for (i = 0; i < l; i++) {
c = tolower((u_char)name[i]);
name[i] = (char)c;
if (last == '.' && c == '.')
fatal("%s line %d: hostname suffix \"%.100s\" contains "
"consecutive separators", filename, linenum, name);
if (c != '.' && c != '-' && !isalnum(c) &&
c != '_') /* technically invalid, but common */
fatal("%s line %d: hostname suffix \"%.100s\" contains "
"invalid characters", filename, linenum, name);
last = c;
}
if (name[l - 1] == '.')
name[l - 1] = '\0';
}
/*
* Returns the number of the token pointed to by cp or oBadOption.
*/
@ -609,6 +644,14 @@ static const struct multistate multistate_requesttty[] = {
{ "auto", REQUEST_TTY_AUTO },
{ NULL, -1 }
};
static const struct multistate multistate_canonicalisehostname[] = {
{ "true", SSH_CANONICALISE_YES },
{ "false", SSH_CANONICALISE_NO },
{ "yes", SSH_CANONICALISE_YES },
{ "no", SSH_CANONICALISE_NO },
{ "always", SSH_CANONICALISE_ALWAYS },
{ NULL, -1 }
};
/*
* Processes a single option line as used in the configuration files. This
@ -628,6 +671,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
size_t len;
Forward fwd;
const struct multistate *multistate_ptr;
struct allowed_cname *cname;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
@ -1263,6 +1307,62 @@ parse_int:
intptr = &options->proxy_use_fdpass;
goto parse_flag;
case oCanonicalDomains:
value = options->num_canonical_domains != 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
valid_domain(arg, filename, linenum);
if (!*activep || value)
continue;
if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
fatal("%s line %d: too many hostname suffixes.",
filename, linenum);
options->canonical_domains[
options->num_canonical_domains++] = xstrdup(arg);
}
break;
case oCanonicalisePermittedCNAMEs:
value = options->num_permitted_cnames != 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
/* Either '*' for everything or 'list:list' */
if (strcmp(arg, "*") == 0)
arg2 = arg;
else {
lowercase(arg);
if ((arg2 = strchr(arg, ':')) == NULL ||
arg2[1] == '\0') {
fatal("%s line %d: "
"Invalid permitted CNAME \"%s\"",
filename, linenum, arg);
}
*arg2 = '\0';
arg2++;
}
if (!*activep || value)
continue;
if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
fatal("%s line %d: too many permitted CNAMEs.",
filename, linenum);
cname = options->permitted_cnames +
options->num_permitted_cnames++;
cname->source_list = xstrdup(arg);
cname->target_list = xstrdup(arg2);
}
break;
case oCanonicaliseHostname:
intptr = &options->canonicalise_hostname;
multistate_ptr = multistate_canonicalisehostname;
goto parse_multistate;
case oCanonicaliseMaxDots:
intptr = &options->canonicalise_max_dots;
goto parse_int;
case oCanonicaliseFallbackLocal:
intptr = &options->canonicalise_fallback_local;
goto parse_flag;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@ -1426,6 +1526,11 @@ initialize_options(Options * options)
options->request_tty = -1;
options->proxy_use_fdpass = -1;
options->ignored_unknown = NULL;
options->num_canonical_domains = 0;
options->num_permitted_cnames = 0;
options->canonicalise_max_dots = -1;
options->canonicalise_fallback_local = -1;
options->canonicalise_hostname = -1;
}
/*
@ -1579,6 +1684,12 @@ fill_default_options(Options * options)
options->request_tty = REQUEST_TTY_AUTO;
if (options->proxy_use_fdpass == -1)
options->proxy_use_fdpass = 0;
if (options->canonicalise_max_dots == -1)
options->canonicalise_max_dots = 1;
if (options->canonicalise_fallback_local == -1)
options->canonicalise_fallback_local = 1;
if (options->canonicalise_hostname == -1)
options->canonicalise_hostname = SSH_CANONICALISE_NO;
#define CLEAR_ON_NONE(v) \
do { \
if (v != NULL && strcasecmp(v, "none") == 0) { \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.97 2013/10/14 22:22:03 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.98 2013/10/16 02:31:46 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -29,7 +29,13 @@ typedef struct {
/* Data structure for representing option data. */
#define MAX_SEND_ENV 256
#define SSH_MAX_HOSTS_FILES 256
#define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32
struct allowed_cname {
char *source_list;
char *target_list;
};
typedef struct {
int forward_agent; /* Forward authentication agent. */
@ -140,9 +146,21 @@ typedef struct {
int proxy_use_fdpass;
int num_canonical_domains;
char *canonical_domains[MAX_CANON_DOMAINS];
int canonicalise_hostname;
int canonicalise_max_dots;
int canonicalise_fallback_local;
int num_permitted_cnames;
struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
#define SSH_CANONICALISE_NO 0
#define SSH_CANONICALISE_YES 1
#define SSH_CANONICALISE_ALWAYS 2
#define SSHCTL_MASTER_NO 0
#define SSHCTL_MASTER_YES 1
#define SSHCTL_MASTER_AUTO 2

View File

@ -1,4 +1,4 @@
/* $OpenBSD: roaming_client.c,v 1.5 2013/05/17 00:13:14 djm Exp $ */
/* $OpenBSD: roaming_client.c,v 1.6 2013/10/16 02:31:46 djm Exp $ */
/*
* Copyright (c) 2004-2009 AppGate Network Security AB
*
@ -259,10 +259,10 @@ wait_for_roaming_reconnect(void)
if (c != '\n' && c != '\r')
continue;
if (ssh_connect(host, &hostaddr, options.port,
if (ssh_connect(host, NULL, &hostaddr, options.port,
options.address_family, 1, &timeout_ms,
options.tcp_keep_alive, options.use_privileged_port,
options.proxy_command) == 0 && roaming_resume() == 0) {
options.tcp_keep_alive, options.use_privileged_port) == 0 &&
roaming_resume() == 0) {
packet_restore_state();
reenter_guard = 0;
fprintf(stderr, "[connection resumed]\n");

9
ssh.1
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh.1,v 1.337 2013/10/15 14:10:25 jmc Exp $
.Dd $Mdocdate: October 15 2013 $
.\" $OpenBSD: ssh.1,v 1.338 2013/10/16 02:31:46 djm Exp $
.Dd $Mdocdate: October 16 2013 $
.Dt SSH 1
.Os
.Sh NAME
@ -417,6 +417,11 @@ For full details of the options listed below, and their possible values, see
.It AddressFamily
.It BatchMode
.It BindAddress
.It CanonicalDomains
.It CanonicaliseFallbackLocal
.It CanonicaliseHostname
.It CanonicaliseMaxDots
.It CanonicalisePermittedCNAMEs
.It ChallengeResponseAuthentication
.It CheckHostIP
.It Cipher

183
ssh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.384 2013/10/14 23:31:01 djm Exp $ */
/* $OpenBSD: ssh.c,v 1.385 2013/10/16 02:31:46 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -231,6 +231,134 @@ tilde_expand_paths(char **paths, u_int num_paths)
}
}
static struct addrinfo *
resolve_host(const char *name, u_int port, int logerr, char *cname, size_t clen)
{
char strport[NI_MAXSERV];
struct addrinfo hints, *res;
int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
snprintf(strport, sizeof strport, "%u", port);
bzero(&hints, sizeof(hints));
hints.ai_family = options.address_family;
hints.ai_socktype = SOCK_STREAM;
if (cname != NULL)
hints.ai_flags = AI_CANONNAME;
if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA))
loglevel = SYSLOG_LEVEL_ERROR;
do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s",
__progname, name, ssh_gai_strerror(gaierr));
return NULL;
}
if (cname != NULL && res->ai_canonname != NULL) {
if (strlcpy(cname, res->ai_canonname, clen) >= clen) {
error("%s: host \"%s\" cname \"%s\" too long (max %lu)",
__func__, name, res->ai_canonname, (u_long)clen);
if (clen > 0)
*cname = '\0';
}
}
return res;
}
/*
* Check whether the cname is a permitted replacement for the hostname
* and perform the replacement if it is.
*/
static int
check_follow_cname(char **namep, const char *cname)
{
int i;
struct allowed_cname *rule;
if (*cname == '\0' || options.num_permitted_cnames == 0 ||
strcmp(*namep, cname) == 0)
return 0;
if (options.canonicalise_hostname == SSH_CANONICALISE_NO)
return 0;
/*
* Don't attempt to canonicalise names that will be interpreted by
* a proxy unless the user specifically requests so.
*/
if (options.proxy_command != NULL &&
options.canonicalise_hostname != SSH_CANONICALISE_ALWAYS)
return 0;
debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
for (i = 0; i < options.num_permitted_cnames; i++) {
rule = options.permitted_cnames + i;
if (match_pattern_list(*namep, rule->source_list,
strlen(rule->source_list), 1) != 1 ||
match_pattern_list(cname, rule->target_list,
strlen(rule->target_list), 1) != 1)
continue;
verbose("Canonicalised DNS aliased hostname "
"\"%s\" => \"%s\"", *namep, cname);
free(*namep);
*namep = xstrdup(cname);
return 1;
}
return 0;
}
/*
* Attempt to resolve the supplied hostname after applying the user's
* canonicalisation rules. Returns the address list for the host or NULL
* if no name was found after canonicalisation.
*/
static struct addrinfo *
resolve_canonicalise(char **hostp, u_int port)
{
int i, ndots;
char *cp, *fullhost, cname_target[NI_MAXHOST];
struct addrinfo *addrs;
if (options.canonicalise_hostname == SSH_CANONICALISE_NO)
return NULL;
/*
* Don't attempt to canonicalise names that will be interpreted by
* a proxy unless the user specifically requests so.
*/
if (options.proxy_command != NULL &&
options.canonicalise_hostname != SSH_CANONICALISE_ALWAYS)
return NULL;
/* Don't apply canonicalisation to sufficiently-qualified hostnames */
ndots = 0;
for (cp = *hostp; *cp != '\0'; cp++) {
if (*cp == '.')
ndots++;
}
if (ndots > options.canonicalise_max_dots) {
debug3("%s: not canonicalising hostname \"%s\" (max dots %d)",
__func__, *hostp, options.canonicalise_max_dots);
return NULL;
}
/* Attempt each supplied suffix */
for (i = 0; i < options.num_canonical_domains; i++) {
*cname_target = '\0';
xasprintf(&fullhost, "%s.%s.", *hostp,
options.canonical_domains[i]);
if ((addrs = resolve_host(fullhost, options.port, 0,
cname_target, sizeof(cname_target))) == NULL) {
free(fullhost);
continue;
}
/* Remove trailing '.' */
fullhost[strlen(fullhost) - 1] = '\0';
/* Follow CNAME if requested */
if (!check_follow_cname(&fullhost, cname_target)) {
debug("Canonicalised hostname \"%s\" => \"%s\"",
*hostp, fullhost);
}
free(*hostp);
*hostp = fullhost;
return addrs;
}
if (!options.canonicalise_fallback_local)
fatal("%s: Could not resolve host \"%s\"", __progname, host);
return NULL;
}
/*
* Main program for the ssh client.
*/
@ -240,12 +368,14 @@ main(int ac, char **av)
int i, r, opt, exit_status, use_syslog;
char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
char cname[NI_MAXHOST];
struct stat st;
struct passwd *pw;
int timeout_ms;
extern int optind, optreset;
extern char *optarg;
Forward fwd;
struct addrinfo *addrs = NULL;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@ -630,9 +760,9 @@ main(int ac, char **av)
usage();
options.user = p;
*cp = '\0';
host = ++cp;
host = xstrdup(++cp);
} else
host = *av;
host = xstrdup(*av);
if (ac > 1) {
optind = optreset = 1;
goto again;
@ -644,6 +774,9 @@ main(int ac, char **av)
if (!host)
usage();
lowercase(host);
host_arg = xstrdup(host);
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
@ -728,6 +861,10 @@ main(int ac, char **av)
strcmp(options.proxy_command, "-") == 0 &&
options.proxy_use_fdpass)
fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
#ifndef HAVE_CYGWIN
if (original_effective_uid != 0)
options.use_privileged_port = 0;
#endif
/* reinit */
log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);
@ -762,10 +899,26 @@ main(int ac, char **av)
options.port = default_ssh_port();
/* preserve host name given on command line for %n expansion */
host_arg = host;
if (options.hostname != NULL) {
host = percent_expand(options.hostname,
cp = percent_expand(options.hostname,
"h", host, (char *)NULL);
free(host);
host = cp;
}
/* If canonicalisation requested then try to apply it */
if (options.canonicalise_hostname != SSH_CANONICALISE_NO)
addrs = resolve_canonicalise(&host, options.port);
/*
* If canonicalisation not requested, or if it failed then try to
* resolve the bare hostname name using the system resolver's usual
* search rules.
*/
if (addrs == NULL) {
if ((addrs = resolve_host(host, options.port, 1,
cname, sizeof(cname))) == NULL)
cleanup_exit(255); /* resolve_host logs the error */
check_follow_cname(&host, cname);
}
if (gethostname(thishost, sizeof(thishost)) == -1)
@ -803,16 +956,15 @@ main(int ac, char **av)
timeout_ms = options.connection_timeout * 1000;
/* Open a connection to the remote host. */
if (ssh_connect(host, &hostaddr, options.port,
options.address_family, options.connection_attempts, &timeout_ms,
options.tcp_keep_alive,
#ifdef HAVE_CYGWIN
options.use_privileged_port,
#else
original_effective_uid == 0 && options.use_privileged_port,
#endif
options.proxy_command) != 0)
exit(255);
if (ssh_connect(host, addrs, &hostaddr, options.port,
options.address_family, options.connection_attempts,
&timeout_ms, options.tcp_keep_alive,
options.use_privileged_port) != 0)
exit(255);
freeaddrinfo(addrs);
packet_set_timeout(options.server_alive_interval,
options.server_alive_count_max);
if (timeout_ms > 0)
debug3("timeout: %d ms remain after connect", timeout_ms);
@ -1621,4 +1773,3 @@ main_sigchld_handler(int sig)
signal(sig, main_sigchld_handler);
errno = save_errno;
}

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh_config.5,v 1.170 2013/10/15 14:10:25 jmc Exp $
.Dd $Mdocdate: October 15 2013 $
.\" $OpenBSD: ssh_config.5,v 1.171 2013/10/16 02:31:46 djm Exp $
.Dd $Mdocdate: October 16 2013 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -200,6 +200,77 @@ Note that this option does not work if
.Cm UsePrivilegedPort
is set to
.Dq yes .
.It Cm CanonicalDomains
when
.Cm CanonicaliseHostname
is enabled, this option specifies the list of domain suffixes in which to
search for the specified destination host.
.It Cm CanonicaliseFallbackLocal
specified whether to fail with an error when hostname canonicalisation fails.
The default of
.Dq no
will attempt to lookup the unqualified hostname using the system resolver's
search rules.
A value of
.Dq yes
will cause
.Xr ssh 1
to fail instantly if
.Cm CanonicaliseHostname
is enabled and the target hostname cannot be found in any of the domains
specified by
.Cm CanonicalDomains .
.It Cm CanonicaliseHostname
controls whether explicit hostname canonicalisation is performed.
The default
.Dq no
is not to perform any name rewriting and let the system resolver handle all
hostname lookups.
If set to
.Dq yes
then, for connections that do not use a
.Cm ProxyCommand ,
.Xr ssh 1
will attempt to canonicalise the hostname specified on the command line
using the
.Cm CanonicalDomains
suffixes and
.Cm CanonicalisePermittedCNAMEs
rules.
If
.Cm CanonicaliseHostname
is set to
.Dq always ,
then canonicalisation is applied to proxied connections to.
.It Cm CanonicaliseMaxDots
specifies the maximum number of dot characters in a hostname name before
canonicalisation is disabled.
The default of
.Dq 1
allows a single dot (i.e. hostname.subdomain)
.It Cm CanonicalisePermittedCNAMEs
specifies rules to determine whether CNAMEs should be followed when
canonicalising hostnames.
The rules consist of one or more arguments of
.Sm off
.Ar source_domain_list : Ar target_domain_list
.Sm on
where
.Ar source_domain_list
is a pattern-list of domains that are may follow CNAMEs in canonicalisation
and
.Ar target_domain_list
is a pattern-list of domains that they may resove to.
.Pp
For example,
.Dq *.a.example.com:*.b.example.com,*.c.example.com
will allow hostnames matching
.Dq *.a.example.com
to be canonicalised to names in the
.Dq *.b.example.com
or
.Dq *.c.example.com
domains.
.It Cm ChallengeResponseAuthentication
Specifies whether to use challenge-response authentication.
The argument to this keyword must be

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.240 2013/09/19 01:26:29 djm Exp $ */
/* $OpenBSD: sshconnect.c,v 1.241 2013/10/16 02:31:46 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -86,7 +86,7 @@ expand_proxy_command(const char *proxy_command, const char *user,
{
char *tmp, *ret, strport[NI_MAXSERV];
snprintf(strport, sizeof strport, "%hu", port);
snprintf(strport, sizeof strport, "%d", port);
xasprintf(&tmp, "exec %s", proxy_command);
ret = percent_expand(tmp, "h", host, "p", strport,
"r", options.user, (char *)NULL);
@ -170,8 +170,6 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
/* Set the connection file descriptors. */
packet_set_connection(sock, sock);
packet_set_timeout(options.server_alive_interval,
options.server_alive_count_max);
return 0;
}
@ -187,16 +185,6 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
pid_t pid;
char *shell;
if (!strcmp(proxy_command, "-")) {
packet_set_connection(STDIN_FILENO, STDOUT_FILENO);
packet_set_timeout(options.server_alive_interval,
options.server_alive_count_max);
return 0;
}
if (options.proxy_use_fdpass)
return ssh_proxy_fdpass_connect(host, port, proxy_command);
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
@ -258,8 +246,6 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
/* Set the connection file descriptors. */
packet_set_connection(pout[0], pin[1]);
packet_set_timeout(options.server_alive_interval,
options.server_alive_count_max);
/* Indicate OK return */
return 0;
@ -429,33 +415,18 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
* and %p substituted for host and port, respectively) to use to contact
* the daemon.
*/
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int family, int connection_attempts, int *timeout_ms,
int want_keepalive, int needpriv, const char *proxy_command)
static int
ssh_connect_direct(const char *host, struct addrinfo *aitop,
struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
{
int gaierr;
int on = 1;
int sock = -1, attempt;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
struct addrinfo hints, *ai, *aitop;
struct addrinfo *ai;
debug2("ssh_connect: needpriv %d", needpriv);
/* If a proxy command is given, connect using it. */
if (proxy_command != NULL)
return ssh_proxy_connect(host, port, proxy_command);
/* No proxy command. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%u", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
fatal("%s: Could not resolve hostname %.100s: %s", __progname,
host, ssh_gai_strerror(gaierr));
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0) {
/* Sleep a moment before retrying. */
@ -467,7 +438,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
* sequence until the connection succeeds.
*/
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
if (ai->ai_family != AF_INET &&
ai->ai_family != AF_INET6)
continue;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
@ -500,8 +472,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
break; /* Successful connection. */
}
freeaddrinfo(aitop);
/* Return failure if we didn't get a successful connection. */
if (sock == -1) {
error("ssh: connect to host %s port %s: %s",
@ -519,12 +489,28 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
/* Set the connection. */
packet_set_connection(sock, sock);
packet_set_timeout(options.server_alive_interval,
options.server_alive_count_max);
return 0;
}
int
ssh_connect(const char *host, struct addrinfo *addrs,
struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
{
if (options.proxy_command == NULL) {
return ssh_connect_direct(host, addrs, hostaddr, port, family,
connection_attempts, timeout_ms, want_keepalive, needpriv);
} else if (strcmp(options.proxy_command, "-") == 0) {
packet_set_connection(STDIN_FILENO, STDOUT_FILENO);
return 0; /* Always succeeds */
} else if (options.proxy_use_fdpass) {
return ssh_proxy_fdpass_connect(host, port,
options.proxy_command);
}
return ssh_proxy_connect(host, port, options.proxy_command);
}
static void
send_client_banner(int connection_out, int minor1)
{
@ -1265,7 +1251,7 @@ void
ssh_login(Sensitive *sensitive, const char *orighost,
struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
{
char *host, *cp;
char *host;
char *server_user, *local_user;
local_user = xstrdup(pw->pw_name);
@ -1273,9 +1259,7 @@ ssh_login(Sensitive *sensitive, const char *orighost,
/* Convert the user-supplied hostname into all lowercase. */
host = xstrdup(orighost);
for (cp = host; *cp; cp++)
if (isupper(*cp))
*cp = (char)tolower(*cp);
lowercase(host);
/* Exchange protocol version identification strings with the server. */
ssh_exchange_identification(timeout_ms);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.h,v 1.27 2010/11/29 23:45:51 djm Exp $ */
/* $OpenBSD: sshconnect.h,v 1.28 2013/10/16 02:31:47 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -31,9 +31,9 @@ struct Sensitive {
int external_keysign;
};
int
ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int,
int *, int, int, const char *);
struct addrinfo;
int ssh_connect(const char *, struct addrinfo *, struct sockaddr_storage *,
u_short, int, int, int *, int, int);
void ssh_kill_proxy_command(void);
void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short,