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.c148
1 files changed, 106 insertions, 42 deletions
diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c
index 046dc9d..7e254f4 100644
--- a/crypto/openssh/ssh.c
+++ b/crypto/openssh/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.420 2015/07/30 00:01:34 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.436 2016/02/15 09:47:49 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -106,7 +106,6 @@ __RCSID("$FreeBSD$");
#include "match.h"
#include "msg.h"
#include "uidswap.h"
-#include "roaming.h"
#include "version.h"
#include "ssherr.h"
#include "myproposal.h"
@@ -204,11 +203,9 @@ usage(void)
fprintf(stderr,
"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 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 address] [-S ctl_path] [-W host:port]\n"
+" [-F configfile] [-I pkcs11] [-i identity_file] [-L address]\n"
+" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
+" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
" [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
);
exit(255);
@@ -253,7 +250,7 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
if (port <= 0)
port = default_ssh_port();
- snprintf(strport, sizeof strport, "%u", port);
+ snprintf(strport, sizeof strport, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = options.address_family == -1 ?
AF_UNSPEC : options.address_family;
@@ -407,6 +404,17 @@ resolve_canonicalize(char **hostp, int port)
return addrs;
}
+ /* If domain name is anchored, then resolve it now */
+ if ((*hostp)[strlen(*hostp) - 1] == '.') {
+ debug3("%s: name is fully qualified", __func__);
+ fullhost = xstrdup(*hostp);
+ if ((addrs = resolve_host(fullhost, port, 0,
+ newname, sizeof(newname))) != NULL)
+ goto found;
+ free(fullhost);
+ goto notfound;
+ }
+
/* Don't apply canonicalization to sufficiently-qualified hostnames */
ndots = 0;
for (cp = *hostp; *cp != '\0'; cp++) {
@@ -430,6 +438,7 @@ resolve_canonicalize(char **hostp, int port)
free(fullhost);
continue;
}
+ found:
/* Remove trailing '.' */
fullhost[strlen(fullhost) - 1] = '\0';
/* Follow CNAME if requested */
@@ -441,6 +450,7 @@ resolve_canonicalize(char **hostp, int port)
*hostp = fullhost;
return addrs;
}
+ notfound:
if (!options.canonicalize_fallback_local)
fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
debug2("%s: host %s not found in any suffix", __func__, *hostp);
@@ -507,7 +517,7 @@ main(int ac, char **av)
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];
+ char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex;
struct stat st;
struct passwd *pw;
int timeout_ms;
@@ -517,8 +527,8 @@ main(int ac, char **av)
struct addrinfo *addrs = NULL;
struct ssh_digest_ctx *md;
u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
- char *conn_hash_hex;
+ ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -628,7 +638,7 @@ main(int ac, char **av)
use_syslog = 1;
break;
case 'E':
- logfile = xstrdup(optarg);
+ logfile = optarg;
break;
case 'G':
config_test = 1;
@@ -705,16 +715,18 @@ main(int ac, char **av)
options.gss_deleg_creds = 1;
break;
case 'i':
- if (stat(optarg, &st) < 0) {
+ p = tilde_expand_filename(optarg, original_real_uid);
+ if (stat(p, &st) < 0)
fprintf(stderr, "Warning: Identity file %s "
- "not accessible: %s.\n", optarg,
+ "not accessible: %s.\n", p,
strerror(errno));
- break;
- }
- add_identity_file(&options, NULL, optarg, 1);
+ else
+ add_identity_file(&options, NULL, p, 1);
+ free(p);
break;
case 'I':
#ifdef ENABLE_PKCS11
+ free(options.pkcs11_provider);
options.pkcs11_provider = xstrdup(optarg);
#else
fprintf(stderr, "no support for PKCS#11.\n");
@@ -799,6 +811,7 @@ main(int ac, char **av)
if (ciphers_valid(*optarg == '+' ?
optarg + 1 : optarg)) {
/* SSH2 only */
+ free(options.ciphers);
options.ciphers = xstrdup(optarg);
options.cipher = SSH_CIPHER_INVALID;
break;
@@ -818,9 +831,10 @@ main(int ac, char **av)
options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT);
break;
case 'm':
- if (mac_valid(optarg))
+ if (mac_valid(optarg)) {
+ free(options.macs);
options.macs = xstrdup(optarg);
- else {
+ } else {
fprintf(stderr, "Unknown mac type '%s'\n",
optarg);
exit(255);
@@ -898,8 +912,7 @@ main(int ac, char **av)
subsystem_flag = 1;
break;
case 'S':
- if (options.control_path != NULL)
- free(options.control_path);
+ free(options.control_path);
options.control_path = xstrdup(optarg);
break;
case 'b':
@@ -981,10 +994,8 @@ main(int ac, char **av)
*/
if (use_syslog && logfile != NULL)
fatal("Can't specify both -y and -E");
- if (logfile != NULL) {
+ if (logfile != NULL)
log_redirect_stderr_to(logfile);
- free(logfile);
- }
log_init(argv0,
options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
SYSLOG_FACILITY_USER, !use_syslog);
@@ -1080,6 +1091,8 @@ main(int ac, char **av)
"disabling");
options.update_hostkeys = 0;
}
+ if (options.connection_attempts <= 0)
+ fatal("Invalid number of ConnectionAttempts");
#ifndef HAVE_CYGWIN
if (original_effective_uid != 0)
options.use_privileged_port = 0;
@@ -1118,6 +1131,7 @@ main(int ac, char **av)
strlcpy(shorthost, thishost, sizeof(shorthost));
shorthost[strcspn(thishost, ".")] = '\0';
snprintf(portstr, sizeof(portstr), "%d", options.port);
+ snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
/* Find canonic host name. */
if (strchr(host, '.') == 0) {
@@ -1177,6 +1191,7 @@ main(int ac, char **av)
"p", portstr,
"r", options.user,
"u", pw->pw_name,
+ "i", uidstr,
(char *)NULL);
free(cp);
}
@@ -1197,6 +1212,7 @@ main(int ac, char **av)
* have yet resolved the hostname. Do so now.
*/
if (addrs == NULL && options.proxy_command == NULL) {
+ debug2("resolving \"%s\" port %d", host, options.port);
if ((addrs = resolve_host(host, options.port, 1,
cname, sizeof(cname))) == NULL)
cleanup_exit(255); /* resolve_host logs the error */
@@ -1240,8 +1256,10 @@ main(int ac, char **av)
sensitive_data.keys[i] = NULL;
PRIV_START;
+#if WITH_SSH1
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL, NULL);
+#endif
#ifdef OPENSSL_HAS_ECC
sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA,
_PATH_HOST_ECDSA_KEY_FILE, "", NULL);
@@ -1366,6 +1384,10 @@ main(int ac, char **av)
options.identity_keys[i] = NULL;
}
}
+ for (i = 0; i < options.num_certificate_files; i++) {
+ free(options.certificate_files[i]);
+ options.certificate_files[i] = NULL;
+ }
exit_status = compat20 ? ssh_session2() : ssh_session();
packet_close();
@@ -1617,6 +1639,7 @@ ssh_session(void)
struct winsize ws;
char *cp;
const char *display;
+ char *proto = NULL, *data = NULL;
/* Enable compression if requested. */
if (options.compression) {
@@ -1687,13 +1710,9 @@ ssh_session(void)
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. */
- client_x11_get_proto(display, options.xauth_location,
- options.forward_x11_trusted,
- options.forward_x11_timeout,
- &proto, &data);
+ if (options.forward_x11 && client_x11_get_proto(display,
+ options.xauth_location, options.forward_x11_trusted,
+ options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
@@ -1783,6 +1802,7 @@ ssh_session2_setup(int id, int success, void *arg)
extern char **environ;
const char *display;
int interactive = tty_flag;
+ char *proto = NULL, *data = NULL;
if (!success)
return; /* No need for error message, channels code sens one */
@@ -1790,12 +1810,9 @@ ssh_session2_setup(int id, int success, void *arg)
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. */
- client_x11_get_proto(display, options.xauth_location,
- options.forward_x11_trusted,
- options.forward_x11_timeout, &proto, &data);
+ if (options.forward_x11 && client_x11_get_proto(display,
+ options.xauth_location, options.forward_x11_trusted,
+ options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
@@ -1949,25 +1966,30 @@ ssh_session2(void)
options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
+/* Loads all IdentityFile and CertificateFile keys */
static void
load_public_identity_files(void)
{
char *filename, *cp, thishost[NI_MAXHOST];
char *pwdir = NULL, *pwname = NULL;
- int i = 0;
Key *public;
struct passwd *pw;
- u_int n_ids;
+ int i;
+ u_int n_ids, n_certs;
char *identity_files[SSH_MAX_IDENTITY_FILES];
Key *identity_keys[SSH_MAX_IDENTITY_FILES];
+ char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
+ struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
#ifdef ENABLE_PKCS11
Key **keys;
int nkeys;
#endif /* PKCS11 */
- n_ids = 0;
+ n_ids = n_certs = 0;
memset(identity_files, 0, sizeof(identity_files));
memset(identity_keys, 0, sizeof(identity_keys));
+ memset(certificate_files, 0, sizeof(certificate_files));
+ memset(certificates, 0, sizeof(certificates));
#ifdef ENABLE_PKCS11
if (options.pkcs11_provider != NULL &&
@@ -1999,6 +2021,7 @@ load_public_identity_files(void)
if (n_ids >= SSH_MAX_IDENTITY_FILES ||
strcasecmp(options.identity_files[i], "none") == 0) {
free(options.identity_files[i]);
+ options.identity_files[i] = NULL;
continue;
}
cp = tilde_expand_filename(options.identity_files[i],
@@ -2017,7 +2040,12 @@ load_public_identity_files(void)
if (++n_ids >= SSH_MAX_IDENTITY_FILES)
continue;
- /* Try to add the certificate variant too */
+ /*
+ * If no certificates have been explicitly listed then try
+ * to add the default certificate variant too.
+ */
+ if (options.num_certificate_files != 0)
+ continue;
xasprintf(&cp, "%s-cert", filename);
public = key_load_public(cp, NULL);
debug("identity file %s type %d", cp,
@@ -2034,14 +2062,50 @@ load_public_identity_files(void)
continue;
}
identity_keys[n_ids] = public;
- /* point to the original path, most likely the private key */
- identity_files[n_ids] = xstrdup(filename);
+ identity_files[n_ids] = cp;
n_ids++;
}
+
+ if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
+ fatal("%s: too many certificates", __func__);
+ for (i = 0; i < options.num_certificate_files; i++) {
+ cp = tilde_expand_filename(options.certificate_files[i],
+ original_real_uid);
+ filename = percent_expand(cp, "d", pwdir,
+ "u", pwname, "l", thishost, "h", host,
+ "r", options.user, (char *)NULL);
+ free(cp);
+
+ public = key_load_public(filename, NULL);
+ debug("certificate file %s type %d", filename,
+ public ? public->type : -1);
+ free(options.certificate_files[i]);
+ options.certificate_files[i] = NULL;
+ if (public == NULL) {
+ free(filename);
+ continue;
+ }
+ if (!key_is_cert(public)) {
+ debug("%s: key %s type %s is not a certificate",
+ __func__, filename, key_type(public));
+ key_free(public);
+ free(filename);
+ continue;
+ }
+ certificate_files[n_certs] = filename;
+ certificates[n_certs] = public;
+ ++n_certs;
+ }
+
options.num_identity_files = n_ids;
memcpy(options.identity_files, identity_files, sizeof(identity_files));
memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
+ options.num_certificate_files = n_certs;
+ memcpy(options.certificate_files,
+ certificate_files, sizeof(certificate_files));
+ memcpy(options.certificates, certificates, sizeof(certificates));
+
explicit_bzero(pwname, strlen(pwname));
free(pwname);
explicit_bzero(pwdir, strlen(pwdir));
OpenPOWER on IntegriCloud