Index: readconf.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readconf.c,v retrieving revision 1.12 diff -u -r1.12 readconf.c --- readconf.c 2001/05/04 04:14:22 1.12 +++ readconf.c 2001/07/05 15:56:11 @@ -108,7 +108,7 @@ #endif oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, - oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, + oGlobalKnownHostsFile, oUserKnownHostsFile, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, @@ -172,7 +172,6 @@ { "userknownhostsfile", oUserKnownHostsFile }, { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, { "userknownhostsfile2", oUserKnownHostsFile2 }, - { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, { "checkhostip", oCheckHostIP }, { "stricthostkeychecking", oStrictHostKeyChecking }, @@ -501,10 +500,6 @@ *intptr = value; break; - case oConnectionAttempts: - intptr = &options->connection_attempts; - goto parse_int; - case oCipher: intptr = &options->cipher; arg = strdelim(&s); @@ -754,7 +749,6 @@ options->keepalives = -1; options->compression_level = -1; options->port = -1; - options->connection_attempts = -1; options->number_of_password_prompts = -1; options->cipher = -1; options->ciphers = NULL; @@ -847,8 +841,6 @@ options->compression_level = 6; if (options->port == -1) options->port = 0; /* Filled in ssh_connect. */ - if (options->connection_attempts == -1) - options->connection_attempts = 4; if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; /* Selected in ssh_login(). */ Index: readconf.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readconf.h,v retrieving revision 1.8 diff -u -r1.8 readconf.h --- readconf.h 2001/05/04 04:14:22 1.8 +++ readconf.h 2001/07/05 15:55:40 @@ -71,8 +71,6 @@ LogLevel log_level; /* Level for logging. */ int port; /* Port to connect. */ - int connection_attempts; /* Max attempts (seconds) before - * giving up */ int number_of_password_prompts; /* Max number of password * prompts. */ int cipher; /* Cipher to use. */ Index: ssh.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh.1,v retrieving revision 1.19 diff -u -r1.19 ssh.1 --- ssh.1 2001/05/14 18:13:34 1.19 +++ ssh.1 2001/07/05 15:56:55 @@ -717,12 +717,6 @@ The meaning of the values is the same as in .Xr gzip 1 . Note that this option applies to protocol version 1 only. -.It Cm ConnectionAttempts -Specifies the number of tries (one per second) to make before falling -back to rsh or exiting. -The argument must be an integer. -This may be useful in scripts if the connection sometimes fails. -The default is 4. .It Cm EscapeChar Sets the escape character (default: .Ql ~ ) . Index: ssh.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh.c,v retrieving revision 1.14 diff -u -r1.14 ssh.c --- ssh.c 2001/05/04 04:14:23 1.14 +++ ssh.c 2001/07/05 15:59:24 @@ -238,7 +238,7 @@ int main(int ac, char **av) { - int i, opt, optind, exit_status, ok; + int i, opt, optind, exit_status, cerr; u_short fwd_port, fwd_host_port; char *optarg, *cp, buf[256]; struct stat st; @@ -635,8 +635,7 @@ /* Open a connection to the remote host. */ - ok = ssh_connect(host, &hostaddr, options.port, - options.connection_attempts, + cerr = ssh_connect(host, &hostaddr, options.port, original_effective_uid != 0 || !options.use_privileged_port, pw, options.proxy_command); @@ -648,7 +647,7 @@ */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; - if (ok && (options.rhosts_rsa_authentication || + if (!cerr && (options.rhosts_rsa_authentication || options.hostbased_authentication)) { sensitive_data.nkeys = 3; sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); @@ -686,20 +685,19 @@ error("Could not create directory '%.200s'.", buf); /* Check if the connection failed, and try "rsh" if appropriate. */ - if (!ok) { + if (cerr) { + if (!options.fallback_to_rsh) + exit(1); if (options.port != 0) - log("Secure connection to %.100s on port %hu refused%.100s.", - host, options.port, - options.fallback_to_rsh ? "; reverting to insecure method" : ""); + log( +"Secure connection to %.100s on port %hu refused; reverting to insecure method", + host, options.port); else - log("Secure connection to %.100s refused%.100s.", host, - options.fallback_to_rsh ? "; reverting to insecure method" : ""); + log( +"Secure connection to %.100s refused; reverting to insecure method.", host); - if (options.fallback_to_rsh) { - rsh_connect(host, options.user, &command); - fatal("rsh_connect returned"); - } - exit(1); + rsh_connect(host, options.user, &command); + fatal("rsh_connect returned"); } /* load options.identity_files */ load_public_identity_files(); Index: sshconnect.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect.c,v retrieving revision 1.17 diff -u -r1.17 sshconnect.c --- sshconnect.c 2001/05/04 04:37:49 1.17 +++ sshconnect.c 2001/07/05 16:03:31 @@ -45,6 +45,29 @@ /* AF_UNSPEC or AF_INET or AF_INET6 */ extern int IPv4or6; +static const char * +sockaddr_ntop(sa) + struct sockaddr *sa; +{ + void *addr; + static char addrbuf[INET6_ADDRSTRLEN]; + + switch (sa->sa_family) { + case AF_INET: + addr = &((struct sockaddr_in *)sa)->sin_addr; + break; + case AF_INET6: + addr = &((struct sockaddr_in6 *)sa)->sin6_addr; + break; + default: + /* This case should be protected against elsewhere */ + abort(); + } + inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); + return addrbuf; +} + + /* * Connect to the given ssh server using a proxy command. */ @@ -142,7 +165,8 @@ /* Set the connection file descriptors. */ packet_set_connection(pout[0], pin[1]); - return 1; + /* Indicate OK return */ + return 0; } /* @@ -184,15 +208,19 @@ * If port is 0, the default port will be used. If anonymous is zero, * a privileged port will be allocated to make the connection. * This requires super-user privileges if anonymous is false. - * Connection_attempts specifies the maximum number of tries (one per - * second). If proxy_command is non-NULL, it specifies the command (with %h + * If proxy_command is non-NULL, it specifies the command (with %h * and %p substituted for host and port, respectively) to use to contact * the daemon. + * Return values: + * 0 for OK + * ECONNREFUSED if we got a "Connection Refused" by the peer on any address + * ECONNABORTED if we failed without a "Connection refused" + * Suitable error messages for the connection failure will already have been + * printed. */ int ssh_connect(const char *host, struct sockaddr_storage * hostaddr, - u_short port, int connection_attempts, - int anonymous, struct passwd *pw, + u_short port, int anonymous, struct passwd *pw, const char *proxy_command) { int gaierr; @@ -202,6 +230,14 @@ struct addrinfo hints, *ai, *aitop; struct linger linger; struct servent *sp; + int got_connection; + int port_set_locally; + /* + * Did we get only other errors than "Connection refused" (which + * should block fallback to rsh and similar), or did we get at least + * one "Connection refused"? + */ + int full_failure = 1; debug("ssh_connect: getuid %u geteuid %u anon %d", (u_int) getuid(), (u_int) geteuid(), anonymous); @@ -213,7 +249,9 @@ port = ntohs(sp->s_port); else port = SSH_DEFAULT_PORT; - } + port_set_locally = 1; + } else + port_set_locally = 0; /* If a proxy command is given, connect using it. */ if (proxy_command != NULL) return ssh_proxy_connect(host, port, pw, proxy_command); @@ -227,72 +265,69 @@ if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) fatal("%s: %.100s: %s", __progname, host, gai_strerror(gaierr)); + got_connection = 0; - /* - * 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; 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. */ - for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) - continue; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, - ntop, sizeof(ntop), strport, sizeof(strport), - NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("ssh_connect: getnameinfo failed"); - continue; - } - debug("Connecting to %.200s [%.100s] port %s.", - host, ntop, strport); - - /* Create a socket for connecting. */ - sock = ssh_create_socket(pw, - !anonymous && geteuid() == 0, - ai->ai_family); - if (sock < 0) - continue; - - /* Connect to the host. We use the user's uid in the - * hope that it will help with tcp_wrappers showing - * the remote uid as root. - */ - temporarily_use_uid(pw); - if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { - /* Successful connection. */ - memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); - restore_uid(); - break; - } else { - debug("connect: %.100s", strerror(errno)); - restore_uid(); - /* - * Close the failed socket; there appear to - * be some problems when reusing a socket for - * which connect() has already returned an - * error. - */ - shutdown(sock, SHUT_RDWR); - close(sock); - } + /* 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; + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, + ntop, sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV) != 0) { + error("ssh_connect: getnameinfo failed"); + continue; } - if (ai) - break; /* Successful connection. */ + debug("Connecting to %.200s [%.100s] port %s.", + host, ntop, strport); + + /* Create a socket for connecting. */ + sock = ssh_create_socket(pw, + !anonymous && geteuid() == 0, + ai->ai_family); + if (sock < 0) + /* Any error is already output */ + continue; - /* Sleep a moment before retrying. */ - sleep(1); + /* Connect to the host. We use the user's uid in the + * hope that it will help with tcp_wrappers showing + * the remote uid as root. + */ + temporarily_use_uid(pw); + if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { + /* Successful connection. */ + memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); + restore_uid(); + got_connection = 1; + break; + } else { + if (errno == ECONNREFUSED) + full_failure = 0; + if (port_set_locally) + log("ssh: connect to address %s: %s", + sockaddr_ntop(ai->ai_addr), + strerror(errno)); + else + log("ssh: connect to address %s port %s: %s", + sockaddr_ntop(ai->ai_addr), strport, + strerror(errno)); + restore_uid(); + /* + * Close the failed socket; there appear to + * be some problems when reusing a socket for + * which connect() has already returned an + * error. + */ + shutdown(sock, SHUT_RDWR); + close(sock); + } } freeaddrinfo(aitop); /* Return failure if we didn't get a successful connection. */ - if (attempt >= connection_attempts) - return 0; + if (!got_connection) + return full_failure ? ECONNABORTED : ECONNREFUSED; debug("Connection established."); @@ -314,7 +349,7 @@ /* Set the connection. */ packet_set_connection(sock, sock); - return 1; + return 0; } /* Index: sshconnect.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect.h,v retrieving revision 1.4 diff -u -r1.4 sshconnect.h --- sshconnect.h 2001/05/04 04:14:23 1.4 +++ sshconnect.h 2001/07/05 15:58:53 @@ -29,8 +29,7 @@ int ssh_connect(const char *host, struct sockaddr_storage * hostaddr, - u_short port, int connection_attempts, - int anonymous, struct passwd *pw, + u_short port, int anonymous, struct passwd *pw, const char *proxy_command); void