diff options
author | Renato Botelho <renato@netgate.com> | 2016-03-14 07:56:21 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-03-14 07:56:21 -0300 |
commit | a26e4b3de35515ec3eaf2eb76b001a6a502bf56c (patch) | |
tree | 66dd86f3e16db9b45f07c989e95501b6456cf6a5 /crypto/openssh/ssh.c | |
parent | 7d66bf7f17e48798ec04b7a6d99daff1820e28f8 (diff) | |
parent | a64e8d254dc9ecd38594b71dcd7d53c6084c5abc (diff) | |
download | FreeBSD-src-a26e4b3de35515ec3eaf2eb76b001a6a502bf56c.zip FreeBSD-src-a26e4b3de35515ec3eaf2eb76b001a6a502bf56c.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'crypto/openssh/ssh.c')
-rw-r--r-- | crypto/openssh/ssh.c | 148 |
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)); |