version 1.57, 2000/03/16 20:56:14 |
version 1.58, 2000/03/23 22:15:33 |
|
|
#include "uidswap.h" |
#include "uidswap.h" |
#include "compat.h" |
#include "compat.h" |
#include "readconf.h" |
#include "readconf.h" |
#include "fingerprint.h" |
|
|
|
|
#include <ssl/rsa.h> |
|
#include <ssl/dsa.h> |
#include <ssl/md5.h> |
#include <ssl/md5.h> |
|
#include "key.h" |
|
#include "hostfile.h" |
|
|
/* Session id for the current session. */ |
/* Session id for the current session. */ |
unsigned char session_id[16]; |
unsigned char session_id[16]; |
|
|
*/ |
*/ |
|
|
void |
void |
check_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key) |
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
{ |
{ |
RSA *file_key; |
Key *file_key; |
char *ip = NULL; |
char *ip = NULL; |
char hostline[1000], *hostp; |
char hostline[1000], *hostp; |
HostStatus host_status; |
HostStatus host_status; |
|
|
* Store the host key from the known host file in here so that we can |
* Store the host key from the known host file in here so that we can |
* compare it with the key for the IP address. |
* compare it with the key for the IP address. |
*/ |
*/ |
file_key = RSA_new(); |
file_key = key_new(host_key->type); |
file_key->n = BN_new(); |
|
file_key->e = BN_new(); |
|
|
|
/* |
/* |
* Check if the host key is present in the user\'s list of known |
* Check if the host key is present in the user\'s list of known |
* hosts or in the systemwide list. |
* hosts or in the systemwide list. |
*/ |
*/ |
host_status = check_host_in_hostfile(options.user_hostfile, host, |
host_status = check_host_in_hostfile(options.user_hostfile, host, host_key, file_key); |
host_key->e, host_key->n, |
|
file_key->e, file_key->n); |
|
if (host_status == HOST_NEW) |
if (host_status == HOST_NEW) |
host_status = check_host_in_hostfile(options.system_hostfile, host, |
host_status = check_host_in_hostfile(options.system_hostfile, host, host_key, file_key); |
host_key->e, host_key->n, |
|
file_key->e, file_key->n); |
|
/* |
/* |
* Also perform check for the ip address, skip the check if we are |
* Also perform check for the ip address, skip the check if we are |
* localhost or the hostname was an ip address to begin with |
* 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 && !local && strcmp(host, ip)) { |
RSA *ip_key = RSA_new(); |
Key *ip_key = key_new(host_key->type); |
ip_key->n = BN_new(); |
ip_status = check_host_in_hostfile(options.user_hostfile, ip, host_key, ip_key); |
ip_key->e = BN_new(); |
|
ip_status = check_host_in_hostfile(options.user_hostfile, ip, |
|
host_key->e, host_key->n, |
|
ip_key->e, ip_key->n); |
|
|
|
if (ip_status == HOST_NEW) |
if (ip_status == HOST_NEW) |
ip_status = check_host_in_hostfile(options.system_hostfile, ip, |
ip_status = check_host_in_hostfile(options.system_hostfile, ip, host_key, ip_key); |
host_key->e, host_key->n, |
|
ip_key->e, ip_key->n); |
|
if (host_status == HOST_CHANGED && |
if (host_status == HOST_CHANGED && |
(ip_status != HOST_CHANGED || |
(ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) |
(BN_cmp(ip_key->e, file_key->e) || BN_cmp(ip_key->n, file_key->n)))) |
|
host_ip_differ = 1; |
host_ip_differ = 1; |
|
|
RSA_free(ip_key); |
key_free(ip_key); |
} else |
} else |
ip_status = host_status; |
ip_status = host_status; |
|
|
RSA_free(file_key); |
key_free(file_key); |
|
|
switch (host_status) { |
switch (host_status) { |
case HOST_OK: |
case HOST_OK: |
|
|
debug("Host '%.200s' is known and matches the host key.", host); |
debug("Host '%.200s' is known and matches the host key.", host); |
if (options.check_host_ip) { |
if (options.check_host_ip) { |
if (ip_status == HOST_NEW) { |
if (ip_status == HOST_NEW) { |
if (!add_host_to_hostfile(options.user_hostfile, ip, |
if (!add_host_to_hostfile(options.user_hostfile, ip, host_key)) |
host_key->e, host_key->n)) |
|
log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).", |
log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).", |
ip, options.user_hostfile); |
ip, options.user_hostfile); |
else |
else |
|
|
} else if (options.strict_host_key_checking == 2) { |
} else if (options.strict_host_key_checking == 2) { |
/* The default */ |
/* The default */ |
char prompt[1024]; |
char prompt[1024]; |
char *fp = fingerprint(host_key->e, host_key->n); |
char *fp = key_fingerprint(host_key); |
snprintf(prompt, sizeof(prompt), |
snprintf(prompt, sizeof(prompt), |
"The authenticity of host '%.200s' can't be established.\n" |
"The authenticity of host '%.200s' can't be established.\n" |
"Key fingerprint is %d %s.\n" |
"Key fingerprint is %s.\n" |
"Are you sure you want to continue connecting (yes/no)? ", |
"Are you sure you want to continue connecting (yes/no)? ", |
host, BN_num_bits(host_key->n), fp); |
host, fp); |
if (!read_yes_or_no(prompt, -1)) |
if (!read_yes_or_no(prompt, -1)) |
fatal("Aborted by user!\n"); |
fatal("Aborted by user!\n"); |
} |
} |
|
|
hostp = host; |
hostp = host; |
|
|
/* If not in strict mode, add the key automatically to the local known_hosts file. */ |
/* If not in strict mode, add the key automatically to the local known_hosts file. */ |
if (!add_host_to_hostfile(options.user_hostfile, hostp, |
if (!add_host_to_hostfile(options.user_hostfile, hostp, host_key)) |
host_key->e, host_key->n)) |
|
log("Failed to add the host to the list of known hosts (%.500s).", |
log("Failed to add the host to the list of known hosts (%.500s).", |
options.user_hostfile); |
options.user_hostfile); |
else |
else |
|
|
if (options.check_host_ip) |
if (options.check_host_ip) |
xfree(ip); |
xfree(ip); |
} |
} |
|
void |
|
check_rsa_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key) |
|
{ |
|
Key k; |
|
k.type = KEY_RSA; |
|
k.rsa = host_key; |
|
check_host_key(host, hostaddr, &k); |
|
} |
|
|
/* |
/* |
* SSH1 key exchange |
* SSH1 key exchange |
|
|
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, |
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, |
SSH_SMSG_PUBLIC_KEY); |
SSH_SMSG_PUBLIC_KEY); |
|
|
check_host_key(host, hostaddr, host_key); |
check_rsa_host_key(host, hostaddr, host_key); |
|
|
client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; |
client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; |
|
|
|
|
fatal("Permission denied."); |
fatal("Permission denied."); |
/* NOTREACHED */ |
/* NOTREACHED */ |
} |
} |
|
|
/* |
/* |
* Starts a dialog with the server, and authenticates the current user on the |
* Starts a dialog with the server, and authenticates the current user on the |
* server. This does not need any extra privileges. The basic connection |
* server. This does not need any extra privileges. The basic connection |
|
|
ssh_kex(host, hostaddr); |
ssh_kex(host, hostaddr); |
if (supported_authentications == 0) |
if (supported_authentications == 0) |
fatal("supported_authentications == 0."); |
fatal("supported_authentications == 0."); |
|
|
/* authenticate user */ |
/* authenticate user */ |
ssh_userauth(host_key_valid, own_host_key, original_real_uid, host); |
ssh_userauth(host_key_valid, own_host_key, original_real_uid, host); |
} |
} |