=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sshconnect.c,v retrieving revision 1.72.2.5 retrieving revision 1.73 diff -u -r1.72.2.5 -r1.73 --- src/usr.bin/ssh/sshconnect.c 2001/03/21 18:53:14 1.72.2.5 +++ src/usr.bin/ssh/sshconnect.c 2000/05/17 08:20:15 1.73 @@ -2,35 +2,29 @@ * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved + * Created: Sat Mar 18 22:15:47 1995 ylo * Code to connect to a remote host, and to perform the client side of the * login (authentication) dialog. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.72.2.5 2001/03/21 18:53:14 jason Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.73 2000/05/17 08:20:15 markus Exp $"); #include +#include +#include -#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; @@ -38,9 +32,6 @@ 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. */ @@ -113,15 +104,15 @@ /* Stderr is left as it is so that error messages get printed on the user's terminal. */ - argv[0] = _PATH_BSHELL; + argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* Execute the proxy command. Note that we gave up any extra privileges above. */ - execv(argv[0], argv); - perror(argv[0]); + execv("/bin/sh", argv); + perror("/bin/sh"); exit(1); } /* Parent. */ @@ -191,16 +182,15 @@ int anonymous, uid_t original_real_uid, const char *proxy_command) { - int gaierr; - int on = 1; int sock = -1, attempt; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + struct servent *sp; struct addrinfo hints, *ai, *aitop; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + int gaierr; struct linger linger; - struct servent *sp; - debug("ssh_connect: getuid %u geteuid %u anon %d", - (u_int) getuid(), (u_int) geteuid(), anonymous); + debug("ssh_connect: getuid %d geteuid %d anon %d", + (int) getuid(), (int) geteuid(), anonymous); /* Get default port if port has not been set. */ if (port == 0) { @@ -249,7 +239,7 @@ /* Create a socket for connecting. */ sock = ssh_create_socket(original_real_uid, - !anonymous && geteuid() == 0, + !anonymous && geteuid() == 0 && port < IPPORT_RESERVED, ai->ai_family); if (sock < 0) continue; @@ -261,7 +251,7 @@ 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, sizeof(*hostaddr)); restore_uid(); break; } else { @@ -299,14 +289,8 @@ /* 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); @@ -318,37 +302,31 @@ * identification string. */ void -ssh_exchange_identification(void) +ssh_exchange_identification() { 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; /* Read other side\'s version identification. */ - for (;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - int len = atomicio(read, connection_in, &buf[i], 1); - if (len < 0) - fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); - if (len != 1) - fatal("ssh_exchange_identification: Connection closed by remote host"); - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ - } - if (buf[i] == '\n') { - buf[i + 1] = 0; - break; - } + for (i = 0; i < sizeof(buf) - 1; i++) { + int len = read(connection_in, &buf[i], 1); + if (len < 0) + fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); + if (len != 1) + fatal("ssh_exchange_identification: Connection closed by remote host"); + if (buf[i] == '\r') { + buf[i] = '\n'; + buf[i + 1] = 0; + continue; /**XXX wait for \n */ } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) + if (buf[i] == '\n') { + buf[i + 1] = 0; break; - debug("ssh_exchange_identification: %s", buf); + } } + buf[sizeof(buf) - 1] = 0; server_version_string = xstrdup(buf); /* @@ -378,10 +356,9 @@ } if (remote_minor < 3) { fatal("Remote machine has too old SSH software version."); - } else if (remote_minor == 3 || remote_minor == 4) { + } else if (remote_minor == 3) { /* We speak 1.3, too. */ enable_compat13(); - minor1 = 3; if (options.forward_agent) { log("Agent forwarding disabled for protocol 1.3"); options.forward_agent = 0; @@ -407,7 +384,7 @@ /* Send our own protocol version identification. */ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, - compat20 ? PROTOCOL_MINOR_2 : minor1, + compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1, SSH_VERSION); if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) fatal("write: %.100s", strerror(errno)); @@ -417,7 +394,6 @@ debug("Local version string %.100s", client_version_string); } -/* defaults to 'no' */ int read_yes_or_no(const char *prompt, int defval) { @@ -425,13 +401,10 @@ FILE *f; int retval = -1; - if (options.batch_mode) - return 0; - - if (isatty(STDIN_FILENO)) + if (isatty(0)) f = stdin; else - f = fopen(_PATH_TTY, "rw"); + f = fopen("/dev/tty", "rw"); if (f == NULL) return 0; @@ -453,10 +426,8 @@ retval = defval; if (strcmp(buf, "yes") == 0) retval = 1; - else if (strcmp(buf, "no") == 0) + if (strcmp(buf, "no") == 0) retval = 0; - else - fprintf(stderr, "Please type 'yes' or 'no'.\n"); if (retval != -1) { if (f != stdin) @@ -477,13 +448,11 @@ Key *file_key; char *type = key_type(host_key); char *ip = NULL; - char hostline[1000], *hostp, *fp; + char hostline[1000], *hostp; HostStatus host_status; HostStatus ip_status; int local = 0, host_ip_differ = 0; char ntop[NI_MAXHOST]; - int host_line, ip_line; - const char *host_file = NULL, *ip_file = NULL; /* * Force accepting of the host key for loopback/localhost. The @@ -505,43 +474,26 @@ local = 0; break; } - if (local && options.host_key_alias == NULL) { - debug("Forcing accepting of host key for " - "loopback/localhost."); + if (local) { + debug("Forcing accepting of host key for loopback/localhost."); return; } /* - * We don't have the remote ip-address for connections - * using a proxy command + * Turn off check_host_ip for proxy connects, since + * we don't have the remote ip-address */ - if (options.proxy_command == NULL) { + if (options.proxy_command != NULL && options.check_host_ip) + options.check_host_ip = 0; + + if (options.check_host_ip) { if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal("check_host_key: getnameinfo failed"); ip = xstrdup(ntop); - } else { - ip = xstrdup(""); } - /* - * 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; /* - * 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 * compare it with the key for the IP address. */ @@ -551,25 +503,19 @@ * Check if the host key is present in the user\'s list of known * hosts or in the systemwide list. */ - host_file = user_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); - if (host_status == HOST_NEW) { - host_file = system_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); - } + host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key); + if (host_status == HOST_NEW) + host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_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) { + if (options.check_host_ip && !local && strcmp(host, ip)) { Key *ip_key = key_new(host_key->type); + ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key); - ip_file = user_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); - if (ip_status == HOST_NEW) { - ip_file = system_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); - } + if (ip_status == HOST_NEW) + ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key); if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) host_ip_differ = 1; @@ -585,14 +531,17 @@ /* The host is known and the key matches. */ 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 && 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); + 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); } break; case HOST_NEW: @@ -604,17 +553,16 @@ } else if (options.strict_host_key_checking == 2) { /* The default */ char prompt[1024]; - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + char *fp = key_fingerprint(host_key); snprintf(prompt, sizeof(prompt), - "The authenticity of host '%.200s (%s)' can't be established.\n" + "The authenticity of host '%.200s' 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); + host, type, fp); if (!read_yes_or_no(prompt, -1)) - fatal("Aborted by user!"); + fatal("Aborted by user!\n"); } - if (options.check_host_ip && ip_status == HOST_NEW) { + if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); hostp = hostline; } else @@ -644,25 +592,18 @@ error("and the key for the according IP address %s", ip); 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_status != HOST_NEW) - error("Offending key for IP in %s:%d", ip_file, ip_line); + error("and its host key have changed at the same time"); } /* 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); - error("Offending key in %s:%d", host_file, host_line); - xfree(fp); + user_hostfile); /* * If strict host key checking is in use, the user will have @@ -684,14 +625,6 @@ error("Agent forwarding is disabled to avoid trojan horses."); options.forward_agent = 0; } - if (options.forward_x11) { - error("X11 forwarding is disabled to avoid trojan horses."); - options.forward_x11 = 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; - } /* * XXX Should permit the user to change to use the new id. * This could be done by converting the host key to an @@ -701,25 +634,8 @@ */ 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); + if (options.check_host_ip) + xfree(ip); } /* @@ -740,7 +656,7 @@ /* Get local user name. Use it as server user if no user name was given. */ pw = getpwuid(original_real_uid); if (!pw) - fatal("User id %u not found from user database.", original_real_uid); + fatal("User id %d not found from user database.", original_real_uid); local_user = xstrdup(pw->pw_name); server_user = options.user ? options.user : local_user; @@ -765,23 +681,4 @@ ssh_kex(host, hostaddr); 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); }