X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/21289cd03008ed8387b9cc1111f17e691cd91ea1..7caca6d44d365220a637081df8cce38c5d26c588:/sshconnect.c diff --git a/sshconnect.c b/sshconnect.c index 32bef7d0..40d22800 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.140 2003/05/14 18:16:21 jakob Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.147 2003/06/29 12:44:38 markus Exp $"); #include @@ -40,6 +40,10 @@ RCSID("$OpenBSD: sshconnect.c,v 1.140 2003/05/14 18:16:21 jakob Exp $"); char *client_version_string = NULL; char *server_version_string = NULL; +#ifdef DNS +int verified_host_key_dns = 0; +#endif + /* import */ extern Options options; extern char *__progname; @@ -218,6 +222,73 @@ ssh_create_socket(int privileged, struct addrinfo *ai) return sock; } +static int +timeout_connect(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen, int timeout) +{ + fd_set *fdset; + struct timeval tv; + socklen_t optlen; + int fdsetsz, optval, rc, result = -1; + + if (timeout <= 0) + return (connect(sockfd, serv_addr, addrlen)); + + if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) + return (-1); + + rc = connect(sockfd, serv_addr, addrlen); + if (rc == 0) + return (0); + if (errno != EINPROGRESS) + return (-1); + + 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; + + for(;;) { + rc = select(sockfd + 1, NULL, fdset, NULL, &tv); + if (rc != -1 || errno != EINTR) + break; + } + + switch(rc) { + case 0: + /* Timed out */ + errno = ETIMEDOUT; + break; + case -1: + /* Select error */ + debug("select: %s", strerror(errno)); + break; + case 1: + /* Completed or failed */ + optval = 0; + optlen = sizeof(optval); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, + &optlen) == -1) + debug("getsockopt: %s", strerror(errno)); + break; + if (optval != 0) { + errno = optval; + break; + } + result = 0; + break; + default: + /* Should not occur */ + fatal("Bogus return (%d) from select()", rc); + } + + xfree(fdset); + return (result); +} + /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. @@ -306,7 +377,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, /* Any error is already output */ continue; - if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { + if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, + options.connection_timeout) >= 0) { /* Successful connection. */ memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); break; @@ -451,7 +523,7 @@ ssh_exchange_identification(void) compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, compat20 ? PROTOCOL_MINOR_2 : minor1, SSH_VERSION); - if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) + if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) fatal("write: %.100s", strerror(errno)); client_version_string = xstrdup(buf); chop(client_version_string); @@ -502,7 +574,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, int salen; char ntop[NI_MAXHOST]; char msg[1024]; - int len, host_line, ip_line, has_keys; + int len, host_line, ip_line; const char *host_file = NULL, *ip_file = NULL; /* @@ -646,19 +718,36 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, "have requested strict checking.", type, host); goto fail; } else if (options.strict_host_key_checking == 2) { - has_keys = show_other_keys(host, host_key); + char msg1[1024], msg2[1024]; + + if (show_other_keys(host, host_key)) + snprintf(msg1, sizeof(msg1), + "\nbut keys of different type are already" + " known for this host."); + else + snprintf(msg1, sizeof(msg1), "."); /* The default */ fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + msg2[0] = '\0'; +#ifdef DNS + if (options.verify_host_key_dns) { + if (verified_host_key_dns) + snprintf(msg2, sizeof(msg2), + "Matching host key fingerprint" + " found in DNS.\n"); + else + snprintf(msg2, sizeof(msg2), + "No matching host key fingerprint" + " found in DNS.\n"); + } +#endif snprintf(msg, sizeof(msg), "The authenticity of host '%.200s (%s)' can't be " "established%s\n" - "%s key fingerprint is %s.\n" + "%s key fingerprint is %s.\n%s" "Are you sure you want to continue connecting " "(yes/no)? ", - host, ip, - has_keys ? ",\nbut keys of different type are already " - "known for this host." : ".", - type, fp); + host, ip, msg1, type, fp, msg2); xfree(fp); if (!confirm(msg)) goto fail; @@ -728,7 +817,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 password authentication or + * the connection but without MITM-able authentication or * agent forwarding. */ if (options.password_authentication) { @@ -736,6 +825,17 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, "man-in-the-middle attacks."); options.password_authentication = 0; } + if (options.kbd_interactive_authentication) { + error("Keyboard-interactive authentication is disabled" + " to avoid man-in-the-middle attacks."); + options.kbd_interactive_authentication = 0; + options.challenge_response_authentication = 0; + } + if (options.challenge_response_authentication) { + error("Challenge/response authentication is disabled" + " to avoid man-in-the-middle attacks."); + options.challenge_response_authentication = 0; + } if (options.forward_agent) { error("Agent forwarding is disabled to avoid " "man-in-the-middle attacks."); @@ -780,7 +880,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, host_file, host_line); } if (options.strict_host_key_checking == 1) { - logit(msg); + logit("%s", msg); error("Exiting, you have requested strict checking."); goto fail; } else if (options.strict_host_key_checking == 2) { @@ -789,7 +889,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, if (!confirm(msg)) goto fail; } else { - logit(msg); + logit("%s", msg); } } @@ -811,7 +911,12 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) if (options.verify_host_key_dns) { switch(verify_host_key_dns(host, hostaddr, host_key)) { case DNS_VERIFY_OK: +#ifdef DNSSEC return 0; +#else + verified_host_key_dns = 1; + break; +#endif case DNS_VERIFY_FAILED: return -1; case DNS_VERIFY_ERROR: