diff options
author | des <des@FreeBSD.org> | 2006-09-30 13:29:51 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2006-09-30 13:29:51 +0000 |
commit | 2f35ce4773442329d7798ccfecd8db9dcdce89bf (patch) | |
tree | bba6f2fe7855d7b0095f9dc7720dc27bea4d1fdf /crypto/openssh/sshconnect.c | |
parent | 03ef9d989bf2619956d8c703362439e9be9257ca (diff) | |
download | FreeBSD-src-2f35ce4773442329d7798ccfecd8db9dcdce89bf.zip FreeBSD-src-2f35ce4773442329d7798ccfecd8db9dcdce89bf.tar.gz |
Vendor import of OpenSSH 4.4p1.
Diffstat (limited to 'crypto/openssh/sshconnect.c')
-rw-r--r-- | crypto/openssh/sshconnect.c | 143 |
1 files changed, 89 insertions, 54 deletions
diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c index 64ffec2..a7a4e8a 100644 --- a/crypto/openssh/sshconnect.c +++ b/crypto/openssh/sshconnect.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sshconnect.c,v 1.199 2006/08/03 03:34:42 deraadt Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -13,12 +14,35 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.171 2005/12/06 22:38:27 reyk Exp $"); -#include <openssl/bn.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/socket.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif +#include <pwd.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> -#include "ssh.h" #include "xmalloc.h" +#include "key.h" +#include "hostfile.h" +#include "ssh.h" #include "rsa.h" #include "buffer.h" #include "packet.h" @@ -32,6 +56,7 @@ RCSID("$OpenBSD: sshconnect.c,v 1.171 2005/12/06 22:38:27 reyk Exp $"); #include "atomicio.h" #include "misc.h" #include "dns.h" +#include "version.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -62,7 +87,6 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) int pin[2], pout[2]; pid_t pid; char strport[NI_MAXSERV]; - size_t len; /* Convert the port number into a string. */ snprintf(strport, sizeof strport, "%hu", port); @@ -74,10 +98,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) * Use "exec" to avoid "sh -c" processes on some platforms * (e.g. Solaris) */ - len = strlen(proxy_command) + 6; - tmp = xmalloc(len); - strlcpy(tmp, "exec ", len); - strlcat(tmp, proxy_command, len); + xasprintf(&tmp, "exec %s", proxy_command); command_string = percent_expand(tmp, "h", host, "p", strport, (char *)NULL); xfree(tmp); @@ -94,8 +115,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) char *argv[10]; /* Child. Permanently give up superuser privileges. */ - seteuid(original_real_uid); - setuid(original_real_uid); + permanently_drop_suid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); @@ -205,7 +225,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, fd_set *fdset; struct timeval tv; socklen_t optlen; - int fdsetsz, optval, rc, result = -1; + int optval, rc, result = -1; if (timeout <= 0) return (connect(sockfd, serv_addr, addrlen)); @@ -219,10 +239,8 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, if (errno != EINPROGRESS) return (-1); - fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask); - fdset = (fd_set *)xmalloc(fdsetsz); - - memset(fdset, 0, fdsetsz); + fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), + sizeof(fd_mask)); FD_SET(sockfd, fdset); tv.tv_sec = timeout; tv.tv_usec = 0; @@ -305,17 +323,14 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, fatal("%s: %.100s: %s", __progname, host, gai_strerror(gaierr)); - /* - * Try to connect several times. On some machines, the first time - * will sometimes fail. In general socket code appears to behave - * quite magically on many machines. - */ - for (attempt = 0; ;) { + for (attempt = 0; attempt < connection_attempts; attempt++) { if (attempt > 0) debug("Trying again..."); - /* Loop through addresses for this host, and try each one in - sequence until the connection succeeds. */ + /* + * Loop through addresses for this host, and try each one in + * sequence until the connection succeeds. + */ for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; @@ -342,21 +357,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, } else { debug("connect to address %s port %s: %s", ntop, strport, strerror(errno)); - /* - * Close the failed socket; there appear to - * be some problems when reusing a socket for - * which connect() has already returned an - * error. - */ close(sock); + sock = -1; } } - if (ai) + if (sock != -1) break; /* Successful connection. */ - attempt++; - if (attempt >= connection_attempts) - break; /* Sleep a moment before retrying. */ sleep(1); } @@ -364,7 +371,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, freeaddrinfo(aitop); /* Return failure if we didn't get a successful connection. */ - if (attempt >= connection_attempts) { + if (sock == -1) { error("ssh: connect to host %s port %s: %s", host, strport, strerror(errno)); return (-1); @@ -396,10 +403,10 @@ ssh_exchange_identification(void) int connection_in = packet_get_connection_in(); int connection_out = packet_get_connection_out(); int minor1 = PROTOCOL_MINOR_1; - u_int i; + u_int i, n; /* Read other side's version identification. */ - for (;;) { + for (n = 0;;) { for (i = 0; i < sizeof(buf) - 1; i++) { size_t len = atomicio(read, connection_in, &buf[i], 1); @@ -416,6 +423,8 @@ ssh_exchange_identification(void) buf[i + 1] = 0; break; } + if (++n > 65536) + fatal("ssh_exchange_identification: No banner received"); } buf[sizeof(buf) - 1] = 0; if (strncmp(buf, "SSH-", 4) == 0) @@ -517,13 +526,17 @@ confirm(const char *prompt) * check whether the supplied host key is valid, return -1 if the key * is not valid. the user_hostfile will not be updated if 'readonly' is true. */ +#define RDRW 0 +#define RDONLY 1 +#define ROQUIET 2 static int -check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, - int readonly, const char *user_hostfile, const char *system_hostfile) +check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, + Key *host_key, int readonly, const char *user_hostfile, + const char *system_hostfile) { Key *file_key; const char *type = key_type(host_key); - char *ip = NULL; + char *ip = NULL, *host = NULL; char hostline[1000], *hostp, *fp; HostStatus host_status; HostStatus ip_status; @@ -574,7 +587,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal("check_host_key: getnameinfo failed"); - ip = xstrdup(ntop); + ip = put_host_port(ntop, port); } else { ip = xstrdup("<no hostip for proxy command>"); } @@ -582,18 +595,21 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, * Turn off check_host_ip if the connection is to localhost, via proxy * command or if we don't have a hostname to compare with */ - if (options.check_host_ip && - (local || strcmp(host, ip) == 0 || options.proxy_command != NULL)) + if (options.check_host_ip && (local || + strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) options.check_host_ip = 0; /* - * Allow the user to record the key under a different name. This is - * useful for ssh tunneling over forwarded connections or if you run - * multiple sshd's on different ports on the same machine. + * Allow the user to record the key under a different name or + * differentiate a non-standard port. This is useful for ssh + * tunneling over forwarded connections or if you run multiple + * sshd's on different ports on the same machine. */ if (options.host_key_alias != NULL) { - host = options.host_key_alias; + host = xstrdup(options.host_key_alias); debug("using hostkeyalias: %s", host); + } else { + host = put_host_port(hostname, port); } /* @@ -662,6 +678,15 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, } break; case HOST_NEW: + if (options.host_key_alias == NULL && port != 0 && + port != SSH_DEFAULT_PORT) { + debug("checking without port identifier"); + if (check_host_key(hostname, hostaddr, 0, host_key, 2, + user_hostfile, system_hostfile) == 0) { + debug("found matching key w/out port"); + break; + } + } if (readonly) goto fail; /* The host is new. */ @@ -741,6 +766,8 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, "list of known hosts.", hostp, type); break; case HOST_CHANGED: + if (readonly == ROQUIET) + goto fail; if (options.check_host_ip && host_ip_differ) { char *key_msg; if (ip_status == HOST_NEW) @@ -779,7 +806,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, /* * If strict host key checking has not been requested, allow * the connection but without MITM-able authentication or - * agent forwarding. + * forwarding. */ if (options.password_authentication) { error("Password authentication is disabled to avoid " @@ -814,6 +841,11 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, options.num_local_forwards = options.num_remote_forwards = 0; } + if (options.tun_open != SSH_TUNMODE_NO) { + error("Tunnel forwarding is disabled to avoid " + "man-in-the-middle attacks."); + options.tun_open = SSH_TUNMODE_NO; + } /* * XXX Should permit the user to change to use the new id. * This could be done by converting the host key to an @@ -855,10 +887,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, } xfree(ip); + xfree(host); return 0; fail: xfree(ip); + xfree(host); return -1; } @@ -892,12 +926,13 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) /* return ok if the key can be found in an old keyfile */ if (stat(options.system_hostfile2, &st) == 0 || stat(options.user_hostfile2, &st) == 0) { - if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, - options.user_hostfile2, options.system_hostfile2) == 0) + if (check_host_key(host, hostaddr, options.port, host_key, + RDONLY, options.user_hostfile2, + options.system_hostfile2) == 0) return 0; } - return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, - options.user_hostfile, options.system_hostfile); + return check_host_key(host, hostaddr, options.port, host_key, + RDRW, options.user_hostfile, options.system_hostfile); } /* @@ -921,7 +956,7 @@ ssh_login(Sensitive *sensitive, const char *orighost, host = xstrdup(orighost); for (cp = host; *cp; cp++) if (isupper(*cp)) - *cp = tolower(*cp); + *cp = (char)tolower(*cp); /* Exchange protocol version identification strings with the server. */ ssh_exchange_identification(); @@ -938,6 +973,7 @@ ssh_login(Sensitive *sensitive, const char *orighost, ssh_kex(host, hostaddr); ssh_userauth1(local_user, server_user, host, sensitive); } + xfree(local_user); } void @@ -951,8 +987,7 @@ ssh_put_password(char *password) return; } size = roundup(strlen(password) + 1, 32); - padded = xmalloc(size); - memset(padded, 0, size); + padded = xcalloc(1, size); strlcpy(padded, password, size); packet_put_string(padded, size); memset(padded, 0, size); |