|
Lines 559-570
Link Here
|
| 559 |
* is not valid. the user_hostfile will not be updated if 'readonly' is true. |
559 |
* is not valid. the user_hostfile will not be updated if 'readonly' is true. |
| 560 |
*/ |
560 |
*/ |
| 561 |
static int |
561 |
static int |
| 562 |
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, |
562 |
check_host_key(char *host, char *port, struct sockaddr *hostaddr, Key *host_key, |
| 563 |
int readonly, const char *user_hostfile, const char *system_hostfile) |
563 |
int readonly, const char *user_hostfile, const char *system_hostfile) |
| 564 |
{ |
564 |
{ |
| 565 |
Key *file_key; |
565 |
Key *file_key; |
| 566 |
const char *type = key_type(host_key); |
566 |
const char *type = key_type(host_key); |
|
|
567 |
char *hoststr = NULL; |
| 568 |
int hostlen = 0; |
| 567 |
char *ip = NULL; |
569 |
char *ip = NULL; |
|
|
570 |
char *ipstr = NULL; |
| 571 |
int iplen = 0; |
| 568 |
char hostline[1000], *hostp, *fp; |
572 |
char hostline[1000], *hostp, *fp; |
| 569 |
HostStatus host_status; |
573 |
HostStatus host_status; |
| 570 |
HostStatus ip_status; |
574 |
HostStatus ip_status; |
|
Lines 644-660
Link Here
|
| 644 |
file_key = key_new(host_key->type); |
648 |
file_key = key_new(host_key->type); |
| 645 |
|
649 |
|
| 646 |
/* |
650 |
/* |
|
|
651 |
* Setup hoststr as host:port for hostfile functions |
| 652 |
*/ |
| 653 |
hostlen = strlen(host) + strlen(port) + 2; |
| 654 |
hoststr = xmalloc(hostlen); |
| 655 |
snprintf(hoststr, hostlen, "%s:%s", host, port); |
| 656 |
|
| 657 |
/* |
| 647 |
* Check if the host key is present in the user\'s list of known |
658 |
* Check if the host key is present in the user\'s list of known |
| 648 |
* hosts or in the systemwide list. |
659 |
* hosts or in the systemwide list. |
| 649 |
*/ |
660 |
*/ |
| 650 |
host_file = user_hostfile; |
661 |
host_file = user_hostfile; |
| 651 |
host_status = check_host_in_hostfile(host_file, host, host_key, |
662 |
host_status = check_host_in_hostfile(host_file, hoststr, host_key, |
| 652 |
file_key, &host_line); |
663 |
file_key, &host_line); |
| 653 |
if (host_status == HOST_NEW) { |
664 |
if (host_status == HOST_NEW) { |
| 654 |
host_file = system_hostfile; |
665 |
host_file = system_hostfile; |
| 655 |
host_status = check_host_in_hostfile(host_file, host, host_key, |
666 |
host_status = check_host_in_hostfile(host_file, hoststr, host_key, |
| 656 |
file_key, &host_line); |
667 |
file_key, &host_line); |
| 657 |
} |
668 |
} |
|
|
669 |
|
| 670 |
/* |
| 671 |
* Setup ipstr as ip:port for hostfile functions |
| 672 |
*/ |
| 673 |
iplen = strlen(ip) + strlen(port) + 2; |
| 674 |
ipstr = xmalloc(iplen); |
| 675 |
snprintf(ipstr, iplen, "%s:%s", ip, port); |
| 676 |
|
| 658 |
/* |
677 |
/* |
| 659 |
* Also perform check for the ip address, skip the check if we are |
678 |
* Also perform check for the ip address, skip the check if we are |
| 660 |
* localhost or the hostname was an ip address to begin with |
679 |
* localhost or the hostname was an ip address to begin with |
|
Lines 663-673
Link Here
|
| 663 |
Key *ip_key = key_new(host_key->type); |
682 |
Key *ip_key = key_new(host_key->type); |
| 664 |
|
683 |
|
| 665 |
ip_file = user_hostfile; |
684 |
ip_file = user_hostfile; |
| 666 |
ip_status = check_host_in_hostfile(ip_file, ip, host_key, |
685 |
ip_status = check_host_in_hostfile(ip_file, ipstr, host_key, |
| 667 |
ip_key, &ip_line); |
686 |
ip_key, &ip_line); |
| 668 |
if (ip_status == HOST_NEW) { |
687 |
if (ip_status == HOST_NEW) { |
| 669 |
ip_file = system_hostfile; |
688 |
ip_file = system_hostfile; |
| 670 |
ip_status = check_host_in_hostfile(ip_file, ip, |
689 |
ip_status = check_host_in_hostfile(ip_file, ipstr, |
| 671 |
host_key, ip_key, &ip_line); |
690 |
host_key, ip_key, &ip_line); |
| 672 |
} |
691 |
} |
| 673 |
if (host_status == HOST_CHANGED && |
692 |
if (host_status == HOST_CHANGED && |
|
Lines 684-705
Link Here
|
| 684 |
case HOST_OK: |
703 |
case HOST_OK: |
| 685 |
/* The host is known and the key matches. */ |
704 |
/* The host is known and the key matches. */ |
| 686 |
debug("Host '%.200s' is known and matches the %s host key.", |
705 |
debug("Host '%.200s' is known and matches the %s host key.", |
| 687 |
host, type); |
706 |
hoststr, type); |
| 688 |
debug("Found key in %s:%d", host_file, host_line); |
707 |
debug("Found key in %s:%d", host_file, host_line); |
| 689 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
708 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
| 690 |
if (readonly) |
709 |
if (readonly) |
| 691 |
logit("%s host key for IP address " |
710 |
logit("%s host key for IP address " |
| 692 |
"'%.128s' not in list of known hosts.", |
711 |
"'%.128s' not in list of known hosts.", |
| 693 |
type, ip); |
712 |
type, ipstr); |
| 694 |
else if (!add_host_to_hostfile(user_hostfile, ip, |
713 |
else if (!add_host_to_hostfile(user_hostfile, ipstr, |
| 695 |
host_key)) |
714 |
host_key)) |
| 696 |
logit("Failed to add the %s host key for IP " |
715 |
logit("Failed to add the %s host key for IP " |
| 697 |
"address '%.128s' to the list of known " |
716 |
"address '%.128s' to the list of known " |
| 698 |
"hosts (%.30s).", type, ip, user_hostfile); |
717 |
"hosts (%.30s).", type, ipstr, user_hostfile); |
| 699 |
else |
718 |
else |
| 700 |
logit("Warning: Permanently added the %s host " |
719 |
logit("Warning: Permanently added the %s host " |
| 701 |
"key for IP address '%.128s' to the list " |
720 |
"key for IP address '%.128s' to the list " |
| 702 |
"of known hosts.", type, ip); |
721 |
"of known hosts.", type, ipstr); |
| 703 |
} |
722 |
} |
| 704 |
break; |
723 |
break; |
| 705 |
case HOST_NEW: |
724 |
case HOST_NEW: |
|
Lines 713-724
Link Here
|
| 713 |
* alternative left is to abort. |
732 |
* alternative left is to abort. |
| 714 |
*/ |
733 |
*/ |
| 715 |
error("No %s host key is known for %.200s and you " |
734 |
error("No %s host key is known for %.200s and you " |
| 716 |
"have requested strict checking.", type, host); |
735 |
"have requested strict checking.", type, hoststr); |
| 717 |
goto fail; |
736 |
goto fail; |
| 718 |
} else if (options.strict_host_key_checking == 2) { |
737 |
} else if (options.strict_host_key_checking == 2) { |
| 719 |
char msg1[1024], msg2[1024]; |
738 |
char msg1[1024], msg2[1024]; |
| 720 |
|
739 |
|
| 721 |
if (show_other_keys(host, host_key)) |
740 |
if (show_other_keys(hoststr, host_key)) |
| 722 |
snprintf(msg1, sizeof(msg1), |
741 |
snprintf(msg1, sizeof(msg1), |
| 723 |
"\nbut keys of different type are already" |
742 |
"\nbut keys of different type are already" |
| 724 |
" known for this host."); |
743 |
" known for this host."); |
|
Lines 743-758
Link Here
|
| 743 |
"%s key fingerprint is %s.\n%s" |
762 |
"%s key fingerprint is %s.\n%s" |
| 744 |
"Are you sure you want to continue connecting " |
763 |
"Are you sure you want to continue connecting " |
| 745 |
"(yes/no)? ", |
764 |
"(yes/no)? ", |
| 746 |
host, ip, msg1, type, fp, msg2); |
765 |
hoststr, ipstr, msg1, type, fp, msg2); |
| 747 |
xfree(fp); |
766 |
xfree(fp); |
| 748 |
if (!confirm(msg)) |
767 |
if (!confirm(msg)) |
| 749 |
goto fail; |
768 |
goto fail; |
| 750 |
} |
769 |
} |
| 751 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
770 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
| 752 |
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); |
771 |
snprintf(hostline, sizeof(hostline), "%s,%s", hoststr, ipstr); |
| 753 |
hostp = hostline; |
772 |
hostp = hostline; |
| 754 |
} else |
773 |
} else |
| 755 |
hostp = host; |
774 |
hostp = hoststr; |
| 756 |
|
775 |
|
| 757 |
/* |
776 |
/* |
| 758 |
* If not in strict mode, add the key automatically to the |
777 |
* If not in strict mode, add the key automatically to the |
|
Lines 777-784
Link Here
|
| 777 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
796 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
| 778 |
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); |
797 |
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); |
| 779 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
798 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
| 780 |
error("The %s host key for %s has changed,", type, host); |
799 |
error("The %s host key for %s has changed,", type, hoststr); |
| 781 |
error("and the key for the according IP address %s", ip); |
800 |
error("and the key for the according IP address %s", ipstr); |
| 782 |
error("%s. This could either mean that", key_msg); |
801 |
error("%s. This could either mean that", key_msg); |
| 783 |
error("DNS SPOOFING is happening or the IP address for the host"); |
802 |
error("DNS SPOOFING is happening or the IP address for the host"); |
| 784 |
error("and its host key have changed at the same time."); |
803 |
error("and its host key have changed at the same time."); |
|
Lines 797-803
Link Here
|
| 797 |
*/ |
816 |
*/ |
| 798 |
if (options.strict_host_key_checking) { |
817 |
if (options.strict_host_key_checking) { |
| 799 |
error("%s host key for %.200s has changed and you have " |
818 |
error("%s host key for %.200s has changed and you have " |
| 800 |
"requested strict checking.", type, host); |
819 |
"requested strict checking.", type, hoststr); |
| 801 |
goto fail; |
820 |
goto fail; |
| 802 |
} |
821 |
} |
| 803 |
|
822 |
|
|
Lines 858-864
Link Here
|
| 858 |
"Warning: the %s host key for '%.200s' " |
877 |
"Warning: the %s host key for '%.200s' " |
| 859 |
"differs from the key for the IP address '%.128s'" |
878 |
"differs from the key for the IP address '%.128s'" |
| 860 |
"\nOffending key for IP in %s:%d", |
879 |
"\nOffending key for IP in %s:%d", |
| 861 |
type, host, ip, ip_file, ip_line); |
880 |
type, hoststr, ipstr, ip_file, ip_line); |
| 862 |
if (host_status == HOST_OK) { |
881 |
if (host_status == HOST_OK) { |
| 863 |
len = strlen(msg); |
882 |
len = strlen(msg); |
| 864 |
snprintf(msg + len, sizeof(msg) - len, |
883 |
snprintf(msg + len, sizeof(msg) - len, |
|
Lines 880-895
Link Here
|
| 880 |
} |
899 |
} |
| 881 |
|
900 |
|
| 882 |
xfree(ip); |
901 |
xfree(ip); |
|
|
902 |
xfree(hoststr); |
| 903 |
xfree(ipstr); |
| 883 |
return 0; |
904 |
return 0; |
| 884 |
|
905 |
|
| 885 |
fail: |
906 |
fail: |
| 886 |
xfree(ip); |
907 |
xfree(ip); |
|
|
908 |
xfree(hoststr); |
| 909 |
xfree(ipstr); |
| 887 |
return -1; |
910 |
return -1; |
| 888 |
} |
911 |
} |
| 889 |
|
912 |
|
| 890 |
/* returns 0 if key verifies or -1 if key does NOT verify */ |
913 |
/* returns 0 if key verifies or -1 if key does NOT verify */ |
| 891 |
int |
914 |
int |
| 892 |
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
915 |
verify_host_key(char *host, char *port, struct sockaddr *hostaddr, Key *host_key) |
| 893 |
{ |
916 |
{ |
| 894 |
struct stat st; |
917 |
struct stat st; |
| 895 |
int flags = 0; |
918 |
int flags = 0; |
|
Lines 917-927
Link Here
|
| 917 |
/* return ok if the key can be found in an old keyfile */ |
940 |
/* return ok if the key can be found in an old keyfile */ |
| 918 |
if (stat(options.system_hostfile2, &st) == 0 || |
941 |
if (stat(options.system_hostfile2, &st) == 0 || |
| 919 |
stat(options.user_hostfile2, &st) == 0) { |
942 |
stat(options.user_hostfile2, &st) == 0) { |
| 920 |
if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, |
943 |
if (check_host_key(host, port, hostaddr, host_key, /*readonly*/ 1, |
| 921 |
options.user_hostfile2, options.system_hostfile2) == 0) |
944 |
options.user_hostfile2, options.system_hostfile2) == 0) |
| 922 |
return 0; |
945 |
return 0; |
| 923 |
} |
946 |
} |
| 924 |
return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, |
947 |
return check_host_key(host, port, hostaddr, host_key, /*readonly*/ 0, |
| 925 |
options.user_hostfile, options.system_hostfile); |
948 |
options.user_hostfile, options.system_hostfile); |
| 926 |
} |
949 |
} |
| 927 |
|
950 |
|
|
Lines 938-947
Link Here
|
| 938 |
{ |
961 |
{ |
| 939 |
char *host, *cp; |
962 |
char *host, *cp; |
| 940 |
char *server_user, *local_user; |
963 |
char *server_user, *local_user; |
|
|
964 |
u_short port; |
| 965 |
char strport[NI_MAXSERV]; |
| 941 |
|
966 |
|
| 942 |
local_user = xstrdup(pw->pw_name); |
967 |
local_user = xstrdup(pw->pw_name); |
| 943 |
server_user = options.user ? options.user : local_user; |
968 |
server_user = options.user ? options.user : local_user; |
| 944 |
|
969 |
|
|
|
970 |
/* Set default port */ |
| 971 |
port = options.port ? options.port : 22; |
| 972 |
snprintf(strport, sizeof strport, "%hu", port); |
| 973 |
|
| 945 |
/* Convert the user-supplied hostname into all lowercase. */ |
974 |
/* Convert the user-supplied hostname into all lowercase. */ |
| 946 |
host = xstrdup(orighost); |
975 |
host = xstrdup(orighost); |
| 947 |
for (cp = host; *cp; cp++) |
976 |
for (cp = host; *cp; cp++) |
|
Lines 957-966
Link Here
|
| 957 |
/* key exchange */ |
986 |
/* key exchange */ |
| 958 |
/* authenticate user */ |
987 |
/* authenticate user */ |
| 959 |
if (compat20) { |
988 |
if (compat20) { |
| 960 |
ssh_kex2(host, hostaddr); |
989 |
ssh_kex2(host, strport, hostaddr); |
| 961 |
ssh_userauth2(local_user, server_user, host, sensitive); |
990 |
ssh_userauth2(local_user, server_user, host, sensitive); |
| 962 |
} else { |
991 |
} else { |
| 963 |
ssh_kex(host, hostaddr); |
992 |
ssh_kex(host, strport, hostaddr); |
| 964 |
ssh_userauth1(local_user, server_user, host, sensitive); |
993 |
ssh_userauth1(local_user, server_user, host, sensitive); |
| 965 |
} |
994 |
} |
| 966 |
} |
995 |
} |