version 1.79.2.6, 2001/11/15 00:15:00 |
version 1.79.2.7, 2002/03/08 17:04:43 |
|
|
#include "readconf.h" |
#include "readconf.h" |
#include "atomicio.h" |
#include "atomicio.h" |
#include "misc.h" |
#include "misc.h" |
|
#include "readpass.h" |
|
|
char *client_version_string = NULL; |
char *client_version_string = NULL; |
char *server_version_string = NULL; |
char *server_version_string = NULL; |
|
|
static char addrbuf[INET6_ADDRSTRLEN]; |
static char addrbuf[INET6_ADDRSTRLEN]; |
|
|
switch (sa->sa_family) { |
switch (sa->sa_family) { |
case AF_INET: |
case AF_INET: |
addr = &((struct sockaddr_in *)sa)->sin_addr; |
addr = &((struct sockaddr_in *)sa)->sin_addr; |
break; |
break; |
case AF_INET6: |
case AF_INET6: |
addr = &((struct sockaddr_in6 *)sa)->sin6_addr; |
addr = &((struct sockaddr_in6 *)sa)->sin6_addr; |
break; |
break; |
default: |
default: |
/* This case should be protected against elsewhere */ |
/* This case should be protected against elsewhere */ |
abort(); |
abort(); /* XXX abort is bad -- do something else */ |
} |
} |
inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); |
inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); |
return addrbuf; |
return addrbuf; |
|
|
/* Create pipes for communicating with the proxy. */ |
/* Create pipes for communicating with the proxy. */ |
if (pipe(pin) < 0 || pipe(pout) < 0) |
if (pipe(pin) < 0 || pipe(pout) < 0) |
fatal("Could not create pipes to communicate with the proxy: %.100s", |
fatal("Could not create pipes to communicate with the proxy: %.100s", |
strerror(errno)); |
strerror(errno)); |
|
|
debug("Executing proxy command: %.500s", command_string); |
debug("Executing proxy command: %.500s", command_string); |
|
|
|
|
int full_failure = 1; |
int full_failure = 1; |
|
|
debug("ssh_connect: getuid %u geteuid %u anon %d", |
debug("ssh_connect: getuid %u geteuid %u anon %d", |
(u_int) getuid(), (u_int) geteuid(), anonymous); |
(u_int) getuid(), (u_int) geteuid(), anonymous); |
|
|
/* Get default port if port has not been set. */ |
/* Get default port if port has not been set. */ |
if (port == 0) { |
if (port == 0) { |
|
|
* which connect() has already returned an |
* which connect() has already returned an |
* error. |
* error. |
*/ |
*/ |
shutdown(sock, SHUT_RDWR); |
|
close(sock); |
close(sock); |
} |
} |
} |
} |
|
|
&remote_major, &remote_minor, remote_version) != 3) |
&remote_major, &remote_minor, remote_version) != 3) |
fatal("Bad remote protocol version identification: '%.100s'", buf); |
fatal("Bad remote protocol version identification: '%.100s'", buf); |
debug("Remote protocol version %d.%d, remote software version %.100s", |
debug("Remote protocol version %d.%d, remote software version %.100s", |
remote_major, remote_minor, remote_version); |
remote_major, remote_minor, remote_version); |
|
|
compat_datafellows(remote_version); |
compat_datafellows(remote_version); |
mismatch = 0; |
mismatch = 0; |
|
|
switch(remote_major) { |
switch (remote_major) { |
case 1: |
case 1: |
if (remote_minor == 99 && |
if (remote_minor == 99 && |
(options.protocol & SSH_PROTO_2) && |
(options.protocol & SSH_PROTO_2) && |
|
|
static int |
static int |
confirm(const char *prompt) |
confirm(const char *prompt) |
{ |
{ |
char buf[1024]; |
const char *msg, *again = "Please type 'yes' or 'no': "; |
FILE *f; |
char *p; |
int retval = -1; |
int ret = -1; |
|
|
if (options.batch_mode) |
if (options.batch_mode) |
return 0; |
return 0; |
if (isatty(STDIN_FILENO)) |
for (msg = prompt;;msg = again) { |
f = stdin; |
p = read_passphrase(msg, RP_ECHO); |
else |
if (p == NULL || |
f = fopen(_PATH_TTY, "rw"); |
(p[0] == '\0') || (p[0] == '\n') || |
if (f == NULL) |
strncasecmp(p, "no", 2) == 0) |
return 0; |
ret = 0; |
fflush(stdout); |
if (strncasecmp(p, "yes", 3) == 0) |
fprintf(stderr, "%s", prompt); |
ret = 1; |
while (1) { |
if (p) |
if (fgets(buf, sizeof(buf), f) == NULL) { |
xfree(p); |
fprintf(stderr, "\n"); |
if (ret != -1) |
strlcpy(buf, "no", sizeof buf); |
return ret; |
} |
|
/* Remove newline from response. */ |
|
if (strchr(buf, '\n')) |
|
*strchr(buf, '\n') = 0; |
|
if (strcmp(buf, "yes") == 0) |
|
retval = 1; |
|
else if (strcmp(buf, "no") == 0) |
|
retval = 0; |
|
else |
|
fprintf(stderr, "Please type 'yes' or 'no': "); |
|
|
|
if (retval != -1) { |
|
if (f != stdin) |
|
fclose(f); |
|
return retval; |
|
} |
|
} |
} |
} |
} |
|
|
|
|
HostStatus ip_status; |
HostStatus ip_status; |
int local = 0, host_ip_differ = 0; |
int local = 0, host_ip_differ = 0; |
char ntop[NI_MAXHOST]; |
char ntop[NI_MAXHOST]; |
int host_line, ip_line; |
char msg[1024]; |
|
int len, host_line, ip_line; |
const char *host_file = NULL, *ip_file = NULL; |
const char *host_file = NULL, *ip_file = NULL; |
|
|
/* |
/* |
|
|
*/ |
*/ |
host_file = user_hostfile; |
host_file = user_hostfile; |
host_status = check_host_in_hostfile(host_file, host, host_key, |
host_status = check_host_in_hostfile(host_file, host, host_key, |
file_key, &host_line); |
file_key, &host_line); |
if (host_status == HOST_NEW) { |
if (host_status == HOST_NEW) { |
host_file = system_hostfile; |
host_file = system_hostfile; |
host_status = check_host_in_hostfile(host_file, host, host_key, |
host_status = check_host_in_hostfile(host_file, host, host_key, |
|
|
"'%.128s' not in list of known hosts.", |
"'%.128s' not in list of known hosts.", |
type, ip); |
type, ip); |
else if (!add_host_to_hostfile(user_hostfile, ip, |
else if (!add_host_to_hostfile(user_hostfile, ip, |
host_key)) |
host_key)) |
log("Failed to add the %s host key for IP " |
log("Failed to add the %s host key for IP " |
"address '%.128s' to the list of known " |
"address '%.128s' to the list of known " |
"hosts (%.30s).", type, ip, user_hostfile); |
"hosts (%.30s).", type, ip, user_hostfile); |
|
|
goto fail; |
goto fail; |
} else if (options.strict_host_key_checking == 2) { |
} else if (options.strict_host_key_checking == 2) { |
/* The default */ |
/* The default */ |
char prompt[1024]; |
|
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); |
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); |
snprintf(prompt, sizeof(prompt), |
snprintf(msg, sizeof(msg), |
"The authenticity of host '%.200s (%s)' can't be " |
"The authenticity of host '%.200s (%s)' can't be " |
"established.\n" |
"established.\n" |
"%s key fingerprint is %s.\n" |
"%s key fingerprint is %s.\n" |
"Are you sure you want to continue connecting " |
"Are you sure you want to continue connecting " |
"(yes/no)? ", host, ip, type, fp); |
"(yes/no)? ", host, ip, type, fp); |
xfree(fp); |
xfree(fp); |
if (!confirm(prompt)) { |
if (!confirm(msg)) |
goto fail; |
goto fail; |
} |
|
} |
} |
if (options.check_host_ip && ip_status == HOST_NEW) { |
if (options.check_host_ip && ip_status == HOST_NEW) { |
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); |
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); |
|
|
error("Port forwarding is disabled to avoid " |
error("Port forwarding is disabled to avoid " |
"man-in-the-middle attacks."); |
"man-in-the-middle attacks."); |
options.num_local_forwards = |
options.num_local_forwards = |
options.num_remote_forwards = 0; |
options.num_remote_forwards = 0; |
} |
} |
/* |
/* |
* XXX Should permit the user to change to use the new id. |
* XXX Should permit the user to change to use the new id. |
|
|
|
|
if (options.check_host_ip && host_status != HOST_CHANGED && |
if (options.check_host_ip && host_status != HOST_CHANGED && |
ip_status == HOST_CHANGED) { |
ip_status == HOST_CHANGED) { |
log("Warning: the %s host key for '%.200s' " |
snprintf(msg, sizeof(msg), |
"differs from the key for the IP address '%.128s'", |
"Warning: the %s host key for '%.200s' " |
type, host, ip); |
"differs from the key for the IP address '%.128s'" |
if (host_status == HOST_OK) |
"\nOffending key for IP in %s:%d", |
log("Matching host key in %s:%d", host_file, host_line); |
type, host, ip, ip_file, ip_line); |
log("Offending key for IP in %s:%d", ip_file, ip_line); |
if (host_status == HOST_OK) { |
|
len = strlen(msg); |
|
snprintf(msg + len, sizeof(msg) - len, |
|
"\nMatching host key in %s:%d", |
|
host_file, host_line); |
|
} |
if (options.strict_host_key_checking == 1) { |
if (options.strict_host_key_checking == 1) { |
|
log(msg); |
error("Exiting, you have requested strict checking."); |
error("Exiting, you have requested strict checking."); |
goto fail; |
goto fail; |
} else if (options.strict_host_key_checking == 2) { |
} else if (options.strict_host_key_checking == 2) { |
if (!confirm("Are you sure you want " |
strlcat(msg, "\nAre you sure you want " |
"to continue connecting (yes/no)? ")) { |
"to continue connecting (yes/no)? ", sizeof(msg)); |
|
if (!confirm(msg)) |
goto fail; |
goto fail; |
} |
} else { |
|
log(msg); |
} |
} |
} |
} |
|
|