=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sshconnect.c,v retrieving revision 1.176.2.2 retrieving revision 1.177 diff -u -r1.176.2.2 -r1.177 --- src/usr.bin/ssh/sshconnect.c 2006/11/08 00:17:14 1.176.2.2 +++ src/usr.bin/ssh/sshconnect.c 2006/03/19 18:51:19 1.177 @@ -1,4 +1,3 @@ -/* $OpenBSD: sshconnect.c,v 1.176.2.2 2006/11/08 00:17:14 brad Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,27 +12,17 @@ * called by a name other than "ssh" or "Secure Shell". */ +#include "includes.h" + #include #include #include -#include -#include -#include - #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include "xmalloc.h" #include "ssh.h" +#include "xmalloc.h" #include "rsa.h" #include "buffer.h" #include "packet.h" @@ -47,7 +36,6 @@ #include "atomicio.h" #include "misc.h" #include "dns.h" -#include "version.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -74,6 +62,7 @@ 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); @@ -85,7 +74,10 @@ * Use "exec" to avoid "sh -c" processes on some platforms * (e.g. Solaris) */ - xasprintf(&tmp, "exec %s", proxy_command); + len = strlen(proxy_command) + 6; + tmp = xmalloc(len); + strlcpy(tmp, "exec ", len); + strlcat(tmp, proxy_command, len); command_string = percent_expand(tmp, "h", host, "p", strport, (char *)NULL); xfree(tmp); @@ -102,7 +94,8 @@ char *argv[10]; /* Child. Permanently give up superuser privileges. */ - permanently_drop_suid(original_real_uid); + seteuid(original_real_uid); + setuid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); @@ -212,7 +205,7 @@ fd_set *fdset; struct timeval tv; socklen_t optlen; - int optval, rc, result = -1; + int fdsetsz, optval, rc, result = -1; if (timeout <= 0) return (connect(sockfd, serv_addr, addrlen)); @@ -226,8 +219,10 @@ if (errno != EINPROGRESS) return (-1); - fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), - sizeof(fd_mask)); + fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask); + fdset = (fd_set *)xmalloc(fdsetsz); + + memset(fdset, 0, fdsetsz); FD_SET(sockfd, fdset); tv.tv_sec = timeout; tv.tv_usec = 0; @@ -310,16 +305,17 @@ fatal("%s: %.100s: %s", __progname, host, gai_strerror(gaierr)); - for (attempt = 0; attempt < connection_attempts; attempt++) { - if (attempt > 0) { - /* Sleep a moment before retrying. */ - sleep(1); - debug("Trying again..."); - } - /* - * Loop through addresses for this host, and try each one in - * sequence until the connection succeeds. + /* + * 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; ;) { + if (attempt > 0) + debug("Trying again..."); + + /* 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; @@ -346,18 +342,29 @@ } 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 (sock != -1) + if (ai) break; /* Successful connection. */ + + attempt++; + if (attempt >= connection_attempts) + break; + /* Sleep a moment before retrying. */ + sleep(1); } freeaddrinfo(aitop); /* Return failure if we didn't get a successful connection. */ - if (sock == -1) { + if (attempt >= connection_attempts) { error("ssh: connect to host %s port %s: %s", host, strport, strerror(errno)); return (-1); @@ -389,10 +396,10 @@ int connection_in = packet_get_connection_in(); int connection_out = packet_get_connection_out(); int minor1 = PROTOCOL_MINOR_1; - u_int i, n; + u_int i; /* Read other side's version identification. */ - for (n = 0;;) { + for (;;) { for (i = 0; i < sizeof(buf) - 1; i++) { size_t len = atomicio(read, connection_in, &buf[i], 1); @@ -409,8 +416,6 @@ 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) @@ -512,17 +517,13 @@ * 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 *hostname, struct sockaddr *hostaddr, u_short port, - Key *host_key, int readonly, const char *user_hostfile, - const char *system_hostfile) +check_host_key(char *host, struct sockaddr *hostaddr, 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, *host = NULL; + char *ip = NULL; char hostline[1000], *hostp, *fp; HostStatus host_status; HostStatus ip_status; @@ -569,7 +570,7 @@ if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal("check_host_key: getnameinfo failed"); - ip = put_host_port(ntop, port); + ip = xstrdup(ntop); } else { ip = xstrdup(""); } @@ -577,21 +578,18 @@ * 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(hostname, ip) == 0 || options.proxy_command != NULL)) + if (options.check_host_ip && + (local || strcmp(host, ip) == 0 || options.proxy_command != NULL)) options.check_host_ip = 0; /* - * 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. + * 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. */ if (options.host_key_alias != NULL) { - host = xstrdup(options.host_key_alias); + host = options.host_key_alias; debug("using hostkeyalias: %s", host); - } else { - host = put_host_port(hostname, port); } /* @@ -660,15 +658,6 @@ } 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. */ @@ -748,8 +737,6 @@ "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) @@ -788,7 +775,7 @@ /* * If strict host key checking has not been requested, allow * the connection but without MITM-able authentication or - * forwarding. + * agent forwarding. */ if (options.password_authentication) { error("Password authentication is disabled to avoid " @@ -823,11 +810,6 @@ 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 @@ -869,12 +851,10 @@ } xfree(ip); - xfree(host); return 0; fail: xfree(ip); - xfree(host); return -1; } @@ -908,13 +888,12 @@ /* 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, options.port, host_key, - RDONLY, options.user_hostfile2, - options.system_hostfile2) == 0) + if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, + options.user_hostfile2, options.system_hostfile2) == 0) return 0; } - return check_host_key(host, hostaddr, options.port, host_key, - RDRW, options.user_hostfile, options.system_hostfile); + return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, + options.user_hostfile, options.system_hostfile); } /* @@ -938,7 +917,7 @@ host = xstrdup(orighost); for (cp = host; *cp; cp++) if (isupper(*cp)) - *cp = (char)tolower(*cp); + *cp = tolower(*cp); /* Exchange protocol version identification strings with the server. */ ssh_exchange_identification(); @@ -955,7 +934,6 @@ ssh_kex(host, hostaddr); ssh_userauth1(local_user, server_user, host, sensitive); } - xfree(local_user); } void @@ -969,7 +947,8 @@ return; } size = roundup(strlen(password) + 1, 32); - padded = xcalloc(1, size); + padded = xmalloc(size); + memset(padded, 0, size); strlcpy(padded, password, size); packet_put_string(padded, size); memset(padded, 0, size);