summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/ssh.c')
-rw-r--r--crypto/openssh/ssh.c403
1 files changed, 296 insertions, 107 deletions
diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c
index eaeb5c7..046dc9d 100644
--- a/crypto/openssh/ssh.c
+++ b/crypto/openssh/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.420 2015/07/30 00:01:34 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -49,7 +49,6 @@ __RCSID("$FreeBSD$");
#endif
#include <sys/resource.h>
#include <sys/ioctl.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -68,12 +67,15 @@ __RCSID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/err.h>
+#endif
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -84,6 +86,7 @@ __RCSID("$FreeBSD$");
#include "canohost.h"
#include "compat.h"
#include "cipher.h"
+#include "digest.h"
#include "packet.h"
#include "buffer.h"
#include "channels.h"
@@ -94,9 +97,9 @@ __RCSID("$FreeBSD$");
#include "dispatch.h"
#include "clientloop.h"
#include "log.h"
+#include "misc.h"
#include "readconf.h"
#include "sshconnect.h"
-#include "misc.h"
#include "kex.h"
#include "mac.h"
#include "sshpty.h"
@@ -105,6 +108,8 @@ __RCSID("$FreeBSD$");
#include "uidswap.h"
#include "roaming.h"
#include "version.h"
+#include "ssherr.h"
+#include "myproposal.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@@ -197,13 +202,13 @@ static void
usage(void)
{
fprintf(stderr,
-"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
+"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n"
" [-F configfile] [-I pkcs11] [-i identity_file]\n"
-" [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]\n"
+" [-L address] [-l login_name] [-m mac_spec]\n"
" [-O ctl_cmd] [-o option] [-p port]\n"
" [-Q cipher | cipher-auth | mac | kex | key]\n"
-" [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n"
+" [-R address] [-S ctl_path] [-W host:port]\n"
" [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
);
exit(255);
@@ -274,6 +279,60 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
}
/*
+ * Attempt to resolve a numeric host address / port to a single address.
+ * Returns a canonical address string.
+ * Returns NULL on failure.
+ * NB. this function must operate with a options having undefined members.
+ */
+static struct addrinfo *
+resolve_addr(const char *name, int port, char *caddr, size_t clen)
+{
+ char addr[NI_MAXHOST], strport[NI_MAXSERV];
+ struct addrinfo hints, *res;
+ int gaierr;
+
+ if (port <= 0)
+ port = default_ssh_port();
+ snprintf(strport, sizeof strport, "%u", port);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = options.address_family == -1 ?
+ AF_UNSPEC : options.address_family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
+ if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
+ debug2("%s: could not resolve name %.100s as address: %s",
+ __func__, name, ssh_gai_strerror(gaierr));
+ return NULL;
+ }
+ if (res == NULL) {
+ debug("%s: getaddrinfo %.100s returned no addresses",
+ __func__, name);
+ return NULL;
+ }
+ if (res->ai_next != NULL) {
+ debug("%s: getaddrinfo %.100s returned multiple addresses",
+ __func__, name);
+ goto fail;
+ }
+ if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen,
+ addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) {
+ debug("%s: Could not format address for name %.100s: %s",
+ __func__, name, ssh_gai_strerror(gaierr));
+ goto fail;
+ }
+ if (strlcpy(caddr, addr, clen) >= clen) {
+ error("%s: host \"%s\" addr \"%s\" too long (max %lu)",
+ __func__, name, addr, (u_long)clen);
+ if (clen > 0)
+ *caddr = '\0';
+ fail:
+ freeaddrinfo(res);
+ return NULL;
+ }
+ return res;
+}
+
+/*
* Check whether the cname is a permitted replacement for the hostname
* and perform the replacement if it is.
* NB. this function must operate with a options having undefined members.
@@ -299,10 +358,8 @@ check_follow_cname(char **namep, const char *cname)
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)
+ if (match_pattern_list(*namep, rule->source_list, 1) != 1 ||
+ match_pattern_list(cname, rule->target_list, 1) != 1)
continue;
verbose("Canonicalized DNS aliased hostname "
"\"%s\" => \"%s\"", *namep, cname);
@@ -323,7 +380,7 @@ static struct addrinfo *
resolve_canonicalize(char **hostp, int port)
{
int i, ndots;
- char *cp, *fullhost, cname_target[NI_MAXHOST];
+ char *cp, *fullhost, newname[NI_MAXHOST];
struct addrinfo *addrs;
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
@@ -337,6 +394,19 @@ resolve_canonicalize(char **hostp, int port)
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
return NULL;
+ /* Try numeric hostnames first */
+ if ((addrs = resolve_addr(*hostp, port,
+ newname, sizeof(newname))) != NULL) {
+ debug2("%s: hostname %.100s is address", __func__, *hostp);
+ if (strcasecmp(*hostp, newname) != 0) {
+ debug2("%s: canonicalised address \"%s\" => \"%s\"",
+ __func__, *hostp, newname);
+ free(*hostp);
+ *hostp = xstrdup(newname);
+ }
+ return addrs;
+ }
+
/* Don't apply canonicalization to sufficiently-qualified hostnames */
ndots = 0;
for (cp = *hostp; *cp != '\0'; cp++) {
@@ -350,20 +420,20 @@ resolve_canonicalize(char **hostp, int port)
}
/* Attempt each supplied suffix */
for (i = 0; i < options.num_canonical_domains; i++) {
- *cname_target = '\0';
+ *newname = '\0';
xasprintf(&fullhost, "%s.%s.", *hostp,
options.canonical_domains[i]);
debug3("%s: attempting \"%s\" => \"%s\"", __func__,
*hostp, fullhost);
if ((addrs = resolve_host(fullhost, port, 0,
- cname_target, sizeof(cname_target))) == NULL) {
+ newname, sizeof(newname))) == NULL) {
free(fullhost);
continue;
}
/* Remove trailing '.' */
fullhost[strlen(fullhost) - 1] = '\0';
/* Follow CNAME if requested */
- if (!check_follow_cname(&fullhost, cname_target)) {
+ if (!check_follow_cname(&fullhost, newname)) {
debug("Canonicalized hostname \"%s\" => \"%s\"",
*hostp, fullhost);
}
@@ -382,27 +452,49 @@ resolve_canonicalize(char **hostp, int port)
* file if the user specifies a config file on the command line.
*/
static void
-process_config_files(struct passwd *pw)
+process_config_files(const char *host_arg, struct passwd *pw, int post_canon)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
int r;
if (config != NULL) {
if (strcasecmp(config, "none") != 0 &&
- !read_config_file(config, pw, host, &options,
- SSHCONF_USERCONF))
+ !read_config_file(config, pw, host, host_arg, &options,
+ SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno));
} else {
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE);
if (r > 0 && (size_t)r < sizeof(buf))
- (void)read_config_file(buf, pw, host, &options,
- SSHCONF_CHECKPERM|SSHCONF_USERCONF);
+ (void)read_config_file(buf, pw, host, host_arg,
+ &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
+ (post_canon ? SSHCONF_POSTCANON : 0));
/* Read systemwide configuration file after user config. */
- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host,
- &options, 0);
+ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
+ host, host_arg, &options,
+ post_canon ? SSHCONF_POSTCANON : 0);
+ }
+}
+
+/* Rewrite the port number in an addrinfo list of addresses */
+static void
+set_addrinfo_port(struct addrinfo *addrs, int port)
+{
+ struct addrinfo *addr;
+
+ for (addr = addrs; addr != NULL; addr = addr->ai_next) {
+ switch (addr->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)addr->ai_addr)->
+ sin_port = htons(port);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)addr->ai_addr)->
+ sin6_port = htons(port);
+ break;
+ }
}
}
@@ -412,8 +504,8 @@ process_config_files(struct passwd *pw)
int
main(int ac, char **av)
{
- int i, r, opt, exit_status, use_syslog;
- char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile;
+ int i, r, opt, exit_status, use_syslog, config_test = 0;
+ char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
char cname[NI_MAXHOST];
struct stat st;
@@ -421,8 +513,11 @@ main(int ac, char **av)
int timeout_ms;
extern int optind, optreset;
extern char *optarg;
- Forward fwd;
+ struct Forward fwd;
struct addrinfo *addrs = NULL;
+ struct ssh_digest_ctx *md;
+ u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
+ char *conn_hash_hex;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -502,7 +597,7 @@ main(int ac, char **av)
again:
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
- "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
+ "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
switch (opt) {
case '1':
options.protocol = SSH_PROTO_1;
@@ -535,12 +630,15 @@ main(int ac, char **av)
case 'E':
logfile = xstrdup(optarg);
break;
+ case 'G':
+ config_test = 1;
+ break;
case 'Y':
options.forward_x11 = 1;
options.forward_x11_trusted = 1;
break;
case 'g':
- options.gateway_ports = 1;
+ options.fwd_opts.gateway_ports = 1;
break;
case 'O':
if (stdio_forward_host != NULL)
@@ -580,6 +678,13 @@ main(int ac, char **av)
cp = key_alg_list(1, 0);
else if (strcmp(optarg, "key-plain") == 0)
cp = key_alg_list(0, 1);
+ else if (strcmp(optarg, "protocol-version") == 0) {
+#ifdef WITH_SSH1
+ cp = xstrdup("1\n2");
+#else
+ cp = xstrdup("2");
+#endif
+ }
if (cp == NULL)
fatal("Unsupported query \"%s\"", optarg);
printf("%s\n", cp);
@@ -635,10 +740,10 @@ main(int ac, char **av)
*options.version_addendum != '\0')
fprintf(stderr, "%s %s, %s\n", SSH_RELEASE,
options.version_addendum,
- SSLeay_version(SSLEAY_VERSION));
+ OPENSSL_VERSION);
else
fprintf(stderr, "%s, %s\n", SSH_RELEASE,
- SSLeay_version(SSLEAY_VERSION));
+ OPENSSL_VERSION);
if (opt == 'V')
exit(0);
break;
@@ -691,26 +796,26 @@ main(int ac, char **av)
}
break;
case 'c':
- if (ciphers_valid(optarg)) {
+ if (ciphers_valid(*optarg == '+' ?
+ optarg + 1 : optarg)) {
/* SSH2 only */
options.ciphers = xstrdup(optarg);
options.cipher = SSH_CIPHER_INVALID;
- } else {
- /* SSH1 only */
- options.cipher = cipher_number(optarg);
- if (options.cipher == -1) {
- fprintf(stderr,
- "Unknown cipher type '%s'\n",
- optarg);
- exit(255);
- }
- if (options.cipher == SSH_CIPHER_3DES)
- options.ciphers = "3des-cbc";
- else if (options.cipher == SSH_CIPHER_BLOWFISH)
- options.ciphers = "blowfish-cbc";
- else
- options.ciphers = (char *)-1;
+ break;
+ }
+ /* SSH1 only */
+ options.cipher = cipher_number(optarg);
+ if (options.cipher == -1) {
+ fprintf(stderr, "Unknown cipher type '%s'\n",
+ optarg);
+ exit(255);
}
+ if (options.cipher == SSH_CIPHER_3DES)
+ options.ciphers = xstrdup("3des-cbc");
+ else if (options.cipher == SSH_CIPHER_BLOWFISH)
+ options.ciphers = xstrdup("blowfish-cbc");
+ else
+ options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT);
break;
case 'm':
if (mac_valid(optarg))
@@ -783,9 +888,9 @@ main(int ac, char **av)
break;
case 'o':
line = xstrdup(optarg);
- if (process_config_line(&options, pw, host ? host : "",
- line, "command-line", 0, NULL, SSHCONF_USERCONF)
- != 0)
+ if (process_config_line(&options, pw,
+ host ? host : "", host ? host : "", line,
+ "command-line", 0, NULL, SSHCONF_USERCONF) != 0)
exit(255);
free(line);
break;
@@ -835,8 +940,10 @@ main(int ac, char **av)
host_arg = xstrdup(host);
+#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
+#endif
/* Initialize the command to execute on remote host. */
buffer_init(&command);
@@ -883,10 +990,11 @@ main(int ac, char **av)
SYSLOG_FACILITY_USER, !use_syslog);
if (debug_flag)
- logit("%s, %s", SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+ /* version_addendum is always NULL at this point */
+ logit("%s, %s", SSH_RELEASE, OPENSSL_VERSION);
/* Parse the configuration files */
- process_config_files(pw);
+ process_config_files(host_arg, pw, 0);
/* Hostname canonicalisation needs a few options filled. */
fill_default_options_for_canonicalization(&options);
@@ -898,6 +1006,8 @@ main(int ac, char **av)
"h", host, (char *)NULL);
free(host);
host = cp;
+ free(options.hostname);
+ options.hostname = xstrdup(host);
}
/* If canonicalization requested then try to apply it */
@@ -921,19 +1031,33 @@ main(int ac, char **av)
if (addrs == NULL && options.num_permitted_cnames != 0 &&
(option_clear_or_none(options.proxy_command) ||
options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
- 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 ((addrs = resolve_host(host, options.port,
+ option_clear_or_none(options.proxy_command),
+ cname, sizeof(cname))) == NULL) {
+ /* Don't fatal proxied host names not in the DNS */
+ if (option_clear_or_none(options.proxy_command))
+ cleanup_exit(255); /* logged in resolve_host */
+ } else
+ check_follow_cname(&host, cname);
}
/*
- * If the target hostname has changed as a result of canonicalisation
- * then re-parse the configuration files as new stanzas may match.
+ * If canonicalisation is enabled then re-parse the configuration
+ * files as new stanzas may match.
*/
- if (strcasecmp(host_arg, host) != 0) {
- debug("Hostname has changed; re-reading configuration");
- process_config_files(pw);
+ if (options.canonicalize_hostname != 0) {
+ debug("Re-reading configuration after hostname "
+ "canonicalisation");
+ free(options.hostname);
+ options.hostname = xstrdup(host);
+ process_config_files(host_arg, pw, 1);
+ /*
+ * Address resolution happens early with canonicalisation
+ * enabled and the port number may have changed since, so
+ * reset it in address list
+ */
+ if (addrs != NULL && options.port > 0)
+ set_addrinfo_port(addrs, options.port);
}
/* Fill configuration defaults. */
@@ -950,6 +1074,12 @@ main(int ac, char **av)
strcmp(options.proxy_command, "-") == 0 &&
options.proxy_use_fdpass)
fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
+ if (options.control_persist &&
+ options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
+ debug("UpdateHostKeys=ask is incompatible with ControlPersist; "
+ "disabling");
+ options.update_hostkeys = 0;
+ }
#ifndef HAVE_CYGWIN
if (original_effective_uid != 0)
options.use_privileged_port = 0;
@@ -1006,12 +1136,29 @@ main(int ac, char **av)
}
}
+ if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
+ ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
+ ssh_digest_update(md, host, strlen(host)) < 0 ||
+ ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
+ ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
+ ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
+ fatal("%s: mux digest failed", __func__);
+ ssh_digest_free(md);
+ conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
+
if (options.local_command != NULL) {
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
- options.local_command = percent_expand(cp, "d", pw->pw_dir,
- "h", host, "l", thishost, "n", host_arg, "r", options.user,
- "p", portstr, "u", pw->pw_name, "L", shorthost,
+ options.local_command = percent_expand(cp,
+ "C", conn_hash_hex,
+ "L", shorthost,
+ "d", pw->pw_dir,
+ "h", host,
+ "l", thishost,
+ "n", host_arg,
+ "p", portstr,
+ "r", options.user,
+ "u", pw->pw_name,
(char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
free(cp);
@@ -1021,12 +1168,25 @@ main(int ac, char **av)
cp = tilde_expand_filename(options.control_path,
original_real_uid);
free(options.control_path);
- options.control_path = percent_expand(cp, "h", host,
- "l", thishost, "n", host_arg, "r", options.user,
- "p", portstr, "u", pw->pw_name, "L", shorthost,
+ options.control_path = percent_expand(cp,
+ "C", conn_hash_hex,
+ "L", shorthost,
+ "h", host,
+ "l", thishost,
+ "n", host_arg,
+ "p", portstr,
+ "r", options.user,
+ "u", pw->pw_name,
(char *)NULL);
free(cp);
}
+ free(conn_hash_hex);
+
+ if (config_test) {
+ dump_client_config(&options, host);
+ exit(0);
+ }
+
if (muxclient_command != 0 && options.control_path == NULL)
fatal("No ControlPath specified for \"-O\" command");
if (options.control_path != NULL)
@@ -1082,26 +1242,26 @@ main(int ac, char **av)
PRIV_START;
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL, NULL);
- sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
- _PATH_HOST_DSA_KEY_FILE, "", NULL);
#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
+ sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA,
_PATH_HOST_ECDSA_KEY_FILE, "", NULL);
#endif
+ sensitive_data.keys[2] = key_load_private_cert(KEY_ED25519,
+ _PATH_HOST_ED25519_KEY_FILE, "", NULL);
sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL);
- sensitive_data.keys[4] = key_load_private_cert(KEY_ED25519,
- _PATH_HOST_ED25519_KEY_FILE, "", NULL);
- sensitive_data.keys[5] = key_load_private_type(KEY_DSA,
- _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
+ sensitive_data.keys[4] = key_load_private_cert(KEY_DSA,
+ _PATH_HOST_DSA_KEY_FILE, "", NULL);
#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[6] = key_load_private_type(KEY_ECDSA,
+ sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
_PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
#endif
+ sensitive_data.keys[6] = key_load_private_type(KEY_ED25519,
+ _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL);
sensitive_data.keys[7] = key_load_private_type(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
- sensitive_data.keys[8] = key_load_private_type(KEY_ED25519,
- _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL);
+ sensitive_data.keys[8] = key_load_private_type(KEY_DSA,
+ _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
PRIV_END;
if (options.hostbased_authentication == 1 &&
@@ -1110,26 +1270,26 @@ main(int ac, char **av)
sensitive_data.keys[6] == NULL &&
sensitive_data.keys[7] == NULL &&
sensitive_data.keys[8] == NULL) {
- sensitive_data.keys[1] = key_load_cert(
- _PATH_HOST_DSA_KEY_FILE);
#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[2] = key_load_cert(
+ sensitive_data.keys[1] = key_load_cert(
_PATH_HOST_ECDSA_KEY_FILE);
#endif
+ sensitive_data.keys[2] = key_load_cert(
+ _PATH_HOST_ED25519_KEY_FILE);
sensitive_data.keys[3] = key_load_cert(
_PATH_HOST_RSA_KEY_FILE);
sensitive_data.keys[4] = key_load_cert(
- _PATH_HOST_ED25519_KEY_FILE);
- sensitive_data.keys[5] = key_load_public(
- _PATH_HOST_DSA_KEY_FILE, NULL);
+ _PATH_HOST_DSA_KEY_FILE);
#ifdef OPENSSL_HAS_ECC
- sensitive_data.keys[6] = key_load_public(
+ sensitive_data.keys[5] = key_load_public(
_PATH_HOST_ECDSA_KEY_FILE, NULL);
#endif
+ sensitive_data.keys[6] = key_load_public(
+ _PATH_HOST_ED25519_KEY_FILE, NULL);
sensitive_data.keys[7] = key_load_public(
_PATH_HOST_RSA_KEY_FILE, NULL);
sensitive_data.keys[8] = key_load_public(
- _PATH_HOST_ED25519_KEY_FILE, NULL);
+ _PATH_HOST_DSA_KEY_FILE, NULL);
sensitive_data.external_keysign = 1;
}
}
@@ -1280,13 +1440,17 @@ fork_postauth(void)
static void
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
{
- Forward *rfwd = (Forward *)ctxt;
+ struct Forward *rfwd = (struct Forward *)ctxt;
/* XXX verbose() on failure? */
- debug("remote forward %s for: listen %d, connect %s:%d",
+ debug("remote forward %s for: listen %s%s%d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
- rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
- if (rfwd->listen_port == 0) {
+ rfwd->listen_path ? rfwd->listen_path :
+ rfwd->listen_host ? rfwd->listen_host : "",
+ (rfwd->listen_path || rfwd->listen_host) ? ":" : "",
+ rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
+ rfwd->connect_host, rfwd->connect_port);
+ if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) {
rfwd->allocated_port = packet_get_int();
logit("Allocated port %u for remote forward to %s:%d",
@@ -1300,12 +1464,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
}
if (type == SSH2_MSG_REQUEST_FAILURE) {
- if (options.exit_on_forward_failure)
- fatal("Error: remote port forwarding failed for "
- "listen port %d", rfwd->listen_port);
- else
- logit("Warning: remote port forwarding failed for "
- "listen port %d", rfwd->listen_port);
+ if (options.exit_on_forward_failure) {
+ if (rfwd->listen_path != NULL)
+ fatal("Error: remote port forwarding failed "
+ "for listen path %s", rfwd->listen_path);
+ else
+ fatal("Error: remote port forwarding failed "
+ "for listen port %d", rfwd->listen_port);
+ } else {
+ if (rfwd->listen_path != NULL)
+ logit("Warning: remote port forwarding failed "
+ "for listen path %s", rfwd->listen_path);
+ else
+ logit("Warning: remote port forwarding failed "
+ "for listen port %d", rfwd->listen_port);
+ }
}
if (++remote_forward_confirms_received == options.num_remote_forwards) {
debug("All remote forwarding requests processed");
@@ -1322,6 +1495,13 @@ client_cleanup_stdio_fwd(int id, void *arg)
}
static void
+ssh_stdio_confirm(int id, int success, void *arg)
+{
+ if (!success)
+ fatal("stdio forwarding failed");
+}
+
+static void
ssh_init_stdio_forwarding(void)
{
Channel *c;
@@ -1341,6 +1521,7 @@ ssh_init_stdio_forwarding(void)
stdio_forward_port, in, out)) == NULL)
fatal("%s: channel_connect_stdio_fwd failed", __func__);
channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
+ channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL);
}
static void
@@ -1353,18 +1534,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_local_forwards; i++) {
debug("Local connections to %.200s:%d forwarded to remote "
"address %.200s:%d",
+ (options.local_forwards[i].listen_path != NULL) ?
+ options.local_forwards[i].listen_path :
(options.local_forwards[i].listen_host == NULL) ?
- (options.gateway_ports ? "*" : "LOCALHOST") :
+ (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
options.local_forwards[i].listen_host,
options.local_forwards[i].listen_port,
+ (options.local_forwards[i].connect_path != NULL) ?
+ options.local_forwards[i].connect_path :
options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port);
success += channel_setup_local_fwd_listener(
- options.local_forwards[i].listen_host,
- options.local_forwards[i].listen_port,
- options.local_forwards[i].connect_host,
- options.local_forwards[i].connect_port,
- options.gateway_ports);
+ &options.local_forwards[i], &options.fwd_opts);
}
if (i > 0 && success != i && options.exit_on_forward_failure)
fatal("Could not request local forwarding.");
@@ -1375,17 +1556,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_remote_forwards; i++) {
debug("Remote connections from %.200s:%d forwarded to "
"local address %.200s:%d",
+ (options.remote_forwards[i].listen_path != NULL) ?
+ options.remote_forwards[i].listen_path :
(options.remote_forwards[i].listen_host == NULL) ?
"LOCALHOST" : options.remote_forwards[i].listen_host,
options.remote_forwards[i].listen_port,
+ (options.remote_forwards[i].connect_path != NULL) ?
+ options.remote_forwards[i].connect_path :
options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port);
options.remote_forwards[i].handle =
channel_request_remote_forwarding(
- options.remote_forwards[i].listen_host,
- options.remote_forwards[i].listen_port,
- options.remote_forwards[i].connect_host,
- options.remote_forwards[i].connect_port);
+ &options.remote_forwards[i]);
if (options.remote_forwards[i].handle < 0) {
if (options.exit_on_forward_failure)
fatal("Could not request remote forwarding.");
@@ -1413,10 +1595,16 @@ ssh_init_forwarding(void)
static void
check_agent_present(void)
{
+ int r;
+
if (options.forward_agent) {
/* Clear agent forwarding if we don't have an agent. */
- if (!ssh_agent_present())
+ if ((r = ssh_get_authentication_socket(NULL)) != 0) {
options.forward_agent = 0;
+ if (r != SSH_ERR_AGENT_NOT_PRESENT)
+ debug("ssh_get_authentication_socket: %s",
+ ssh_err(r));
+ }
}
}
@@ -1497,6 +1685,8 @@ ssh_session(void)
}
/* Request X11 forwarding if enabled and DISPLAY is set. */
display = getenv("DISPLAY");
+ if (display == NULL && options.forward_x11)
+ debug("X11 forwarding requested but DISPLAY not set");
if (options.forward_x11 && display != NULL) {
char *proto, *data;
/* Get reasonable local authentication information. */
@@ -1598,6 +1788,8 @@ ssh_session2_setup(int id, int success, void *arg)
return; /* No need for error message, channels code sens one */
display = getenv("DISPLAY");
+ if (display == NULL && options.forward_x11)
+ debug("X11 forwarding requested but DISPLAY not set");
if (options.forward_x11 && display != NULL) {
char *proto, *data;
/* Get reasonable local authentication information. */
@@ -1753,9 +1945,6 @@ ssh_session2(void)
fork_postauth();
}
- if (options.use_roaming)
- request_roaming();
-
return client_loop(tty_flag, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
OpenPOWER on IntegriCloud