]> andersk Git - openssh.git/blobdiff - sshconnect.c
- djm@cvs.openbsd.org 2001/03/13 22:42:54
[openssh.git] / sshconnect.c
index 647aec79761e70535bb806fd33df21563ad358db..d82be89e9512f28e1aca3c0554f843078f0cfadd 100644 (file)
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.85 2000/12/21 15:10:17 markus Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.100 2001/03/12 22:02:02 markus Exp $");
 
 #include <openssl/bn.h>
-#include <openssl/dsa.h>
-#include <openssl/rsa.h>
 
+#include "ssh.h"
 #include "xmalloc.h"
 #include "rsa.h"
-#include "ssh.h"
 #include "buffer.h"
 #include "packet.h"
 #include "uidswap.h"
 #include "compat.h"
-#include "readconf.h"
 #include "key.h"
 #include "sshconnect.h"
 #include "hostfile.h"
+#include "log.h"
+#include "readconf.h"
+#include "atomicio.h"
+#include "misc.h"
 
 char *client_version_string = NULL;
 char *server_version_string = NULL;
@@ -37,6 +38,9 @@ char *server_version_string = NULL;
 extern Options options;
 extern char *__progname;
 
+/* AF_UNSPEC or AF_INET or AF_INET6 */
+extern int IPv4or6;
+
 /*
  * Connect to the given ssh server using a proxy command.
  */
@@ -116,8 +120,8 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
 
                /* Execute the proxy command.  Note that we gave up any
                   extra privileges above. */
-               execv(_PATH_BSHELL, argv);
-               perror(_PATH_BSHELL);
+               execv(argv[0], argv);
+               perror(argv[0]);
                exit(1);
        }
        /* Parent. */
@@ -187,12 +191,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
            int anonymous, uid_t original_real_uid,
            const char *proxy_command)
 {
+       int gaierr;
+       int on = 1;
        int sock = -1, attempt;
-       struct servent *sp;
-       struct addrinfo hints, *ai, *aitop;
        char ntop[NI_MAXHOST], strport[NI_MAXSERV];
-       int gaierr;
+       struct addrinfo hints, *ai, *aitop;
        struct linger linger;
+       struct servent *sp;
 
        debug("ssh_connect: getuid %u geteuid %u anon %d",
              (u_int) getuid(), (u_int) geteuid(), anonymous);
@@ -260,7 +265,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
                        temporarily_use_uid(original_real_uid);
                        if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
                                /* Successful connection. */
-                               memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
+                               memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 
                                restore_uid();
                                break;
                        } else {
@@ -298,7 +303,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
        /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
        linger.l_onoff = 1;
        linger.l_linger = 5;
-       setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
+       setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
+
+       /* Set keepalives if requested. */
+       if (options.keepalives &&
+           setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+           sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
 
        /* Set the connection. */
        packet_set_connection(sock, sock);
@@ -311,13 +322,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
  * identification string.
  */
 void
-ssh_exchange_identification()
+ssh_exchange_identification(void)
 {
        char buf[256], remote_version[256];     /* must be same size! */
        int remote_major, remote_minor, i, mismatch;
        int connection_in = packet_get_connection_in();
        int connection_out = packet_get_connection_out();
-       int minor1 = PROTOCOL_MINOR_1; 
+       int minor1 = PROTOCOL_MINOR_1;
 
        /* Read other side\'s version identification. */
        for (;;) {
@@ -410,6 +421,7 @@ ssh_exchange_identification()
        debug("Local version string %.100s", client_version_string);
 }
 
+/* defaults to 'no' */
 int
 read_yes_or_no(const char *prompt, int defval)
 {
@@ -417,10 +429,13 @@ read_yes_or_no(const char *prompt, int defval)
        FILE *f;
        int retval = -1;
 
-       if (isatty(0))
+       if (options.batch_mode)
+               return 0;
+
+       if (isatty(STDIN_FILENO))
                f = stdin;
        else
-               f = fopen("/dev/tty", "rw");
+               f = fopen(_PATH_TTY, "rw");
 
        if (f == NULL)
                return 0;
@@ -466,13 +481,13 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
        Key *file_key;
        char *type = key_type(host_key);
        char *ip = NULL;
-       char hostline[1000], *hostp;
+       char hostline[1000], *hostp, *fp;
        HostStatus host_status;
        HostStatus ip_status;
        int local = 0, host_ip_differ = 0;
        int salen;
        char ntop[NI_MAXHOST];
-       int host_line = -1, ip_line = -1;
+       int host_line, ip_line;
        const char *host_file = NULL, *ip_file = NULL;
 
        /*
@@ -498,28 +513,41 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                salen = sizeof(struct sockaddr_storage);
                break;
        }
-       if (local) {
-               debug("Forcing accepting of host key for loopback/localhost.");
+       if (local && options.host_key_alias == NULL) {
+               debug("Forcing accepting of host key for "
+                   "loopback/localhost.");
                return;
        }
 
        /*
-        * Turn off check_host_ip for proxy connects, since
-        * we don't have the remote ip-address
+        * We don't have the remote ip-address for connections
+        * using a proxy command
         */
-       if (options.proxy_command != NULL && options.check_host_ip)
+       if (options.proxy_command == NULL) {
+               if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
+                   NULL, 0, NI_NUMERICHOST) != 0)
+                       fatal("check_host_key: getnameinfo failed");
+               ip = xstrdup(ntop);
+       } else {
+               ip = xstrdup("<no hostip for proxy command>");
+       }
+       /*
+        * 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))
                options.check_host_ip = 0;
 
-
-
-       if (options.proxy_command == NULL) {
-               if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
-                               NULL, 0, NI_NUMERICHOST) != 0)
-                       fatal("check_host_key: getnameinfo failed");
-               ip = xstrdup(ntop);
-       } else {
-               ip = xstrdup("<no hostip for proxy command>");
-       }
+       /*
+        * 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 = options.host_key_alias;
+               debug("using hostkeyalias: %s", host);
+       }
 
        /*
         * Store the host key from the known host file in here so that we can
@@ -541,7 +569,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
         * Also perform check for the ip address, skip the check if we are
         * localhost or the hostname was an ip address to begin with
         */
-       if (options.check_host_ip && !local && strcmp(host, ip)) {
+       if (options.check_host_ip) {
                Key *ip_key = key_new(host_key->type);
 
                ip_file = user_hostfile;
@@ -566,21 +594,13 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                debug("Host '%.200s' is known and matches the %s host key.",
                    host, type);
                debug("Found key in %s:%d", host_file, host_line);
-               if (options.check_host_ip) {
-                       if (ip_status == HOST_NEW) {
-                               if (!add_host_to_hostfile(user_hostfile, ip, host_key))
-                                       log("Failed to add the %s host key for IP address '%.30s' to the list of known hosts (%.30s).",
-                                           type, ip, user_hostfile);
-                               else
-                                       log("Warning: Permanently added the %s host key for IP address '%.30s' to the list of known hosts.",
-                                           type, ip);
-                       } else if (ip_status != HOST_OK) {
-                               log("Warning: the %s host key for '%.200s' differs from the key for the IP address '%.30s'",
-                                   type, host, ip);
-                               log("Found key in %s:%d", host_file, host_line);
-                               if (ip_line != -1)
-                                       log("Offending key for IP in %s:%d", ip_file, ip_line);
-                       }
+               if (options.check_host_ip && ip_status == HOST_NEW) {
+                       if (!add_host_to_hostfile(user_hostfile, ip, host_key))
+                               log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).",
+                                   type, ip, user_hostfile);
+                       else
+                               log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.",
+                                   type, ip);
                }
                break;
        case HOST_NEW:
@@ -592,16 +612,17 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                } else if (options.strict_host_key_checking == 2) {
                        /* The default */
                        char prompt[1024];
-                       char *fp = key_fingerprint(host_key);
+                       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                        snprintf(prompt, sizeof(prompt),
                            "The authenticity of host '%.200s (%s)' can't be established.\n"
                            "%s key fingerprint is %s.\n"
                            "Are you sure you want to continue connecting (yes/no)? ",
                            host, ip, type, fp);
+                       xfree(fp);
                        if (!read_yes_or_no(prompt, -1))
-                               fatal("Aborted by user!\n");
+                               fatal("Aborted by user!");
                }
-               if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
+               if (options.check_host_ip && ip_status == HOST_NEW) {
                        snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
                        hostp = hostline;
                } else
@@ -632,20 +653,24 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                        error("%s. This could either mean that", msg);
                        error("DNS SPOOFING is happening or the IP address for the host");
                        error("and its host key have changed at the same time.");
-                       if (ip_line != -1)
+                       if (ip_status != HOST_NEW)
                                error("Offending key for IP in %s:%d", ip_file, ip_line);
                }
                /* The host key has changed. */
+               fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
                error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
                error("It is also possible that the %s host key has just been changed.", type);
+               error("The fingerprint for the %s key sent by the remote host is\n%s.",
+                   type, fp);
                error("Please contact your system administrator.");
                error("Add correct host key in %.100s to get rid of this message.",
-                     user_hostfile);
+                   user_hostfile);
                error("Offending key in %s:%d", host_file, host_line);
+               xfree(fp);
 
                /*
                 * If strict host key checking is in use, the user will have
@@ -671,7 +696,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                        error("X11 forwarding is disabled to avoid trojan horses.");
                        options.forward_x11 = 0;
                }
-               if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) {
+               if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) {
                        error("Port forwarding is disabled to avoid trojan horses.");
                        options.num_local_forwards = options.num_remote_forwards = 0;
                }
@@ -685,6 +710,23 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
                break;
        }
 
+       if (options.check_host_ip && host_status != HOST_CHANGED &&
+           ip_status == HOST_CHANGED) {
+               log("Warning: the %s host key for '%.200s' "
+                   "differs from the key for the IP address '%.128s'",
+                   type, host, ip);
+               if (host_status == HOST_OK)
+                       log("Matching host key in %s:%d", host_file, host_line);
+               log("Offending key for IP in %s:%d", ip_file, ip_line);
+               if (options.strict_host_key_checking == 1) {
+                       fatal("Exiting, you have requested strict checking.");
+               } else if (options.strict_host_key_checking == 2) {
+                       if (!read_yes_or_no("Are you sure you want " \
+                           "to continue connecting (yes/no)? ", -1))
+                               fatal("Aborted by user!");
+               }
+       }
+
        xfree(ip);
 }
 
@@ -732,3 +774,22 @@ ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
                ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
        }
 }
+
+void
+ssh_put_password(char *password)
+{
+       int size;
+       char *padded;
+
+       if (datafellows & SSH_BUG_PASSWORDPAD) {
+               packet_put_string(password, strlen(password));
+               return;
+       }
+       size = roundup(strlen(password) + 1, 32);
+       padded = xmalloc(size);
+       memset(padded, 0, size);
+       strlcpy(padded, password, size);
+       packet_put_string(padded, size);
+       memset(padded, 0, size);
+       xfree(padded);
+}
This page took 0.055881 seconds and 4 git commands to generate.