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