|
Lines 545-556
confirm(const char *prompt)
Link Here
|
| 545 |
* is not valid. the user_hostfile will not be updated if 'readonly' is true. |
545 |
* is not valid. the user_hostfile will not be updated if 'readonly' is true. |
| 546 |
*/ |
546 |
*/ |
| 547 |
static int |
547 |
static int |
| 548 |
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, |
548 |
check_host_key(char *host, u_short port, struct sockaddr *hostaddr, |
| 549 |
int readonly, const char *user_hostfile, const char *system_hostfile) |
549 |
Key *host_key, int readonly, const char *user_hostfile, |
|
|
550 |
const char *system_hostfile) |
| 550 |
{ |
551 |
{ |
| 551 |
Key *file_key; |
552 |
Key *file_key; |
| 552 |
const char *type = key_type(host_key); |
553 |
const char *type = key_type(host_key); |
| 553 |
char *ip = NULL; |
554 |
char *ip = NULL; |
|
|
555 |
char *hoststr = NULL; |
| 556 |
char *ipstr = NULL; |
| 554 |
char hostline[1000], *hostp, *fp; |
557 |
char hostline[1000], *hostp, *fp; |
| 555 |
HostStatus host_status; |
558 |
HostStatus host_status; |
| 556 |
HostStatus ip_status; |
559 |
HostStatus ip_status; |
|
Lines 614-626
check_host_key(char *host, struct sockad
Link Here
|
| 614 |
options.check_host_ip = 0; |
617 |
options.check_host_ip = 0; |
| 615 |
|
618 |
|
| 616 |
/* |
619 |
/* |
| 617 |
* Allow the user to record the key under a different name. This is |
620 |
* Allow the user to record the key under a different name or |
| 618 |
* useful for ssh tunneling over forwarded connections or if you run |
621 |
* differentiate a non-standard port. This is useful for ssh |
| 619 |
* multiple sshd's on different ports on the same machine. |
622 |
* tunneling over forwarded connections or if you run multiple |
|
|
623 |
* sshd's on different ports on the same machine. |
| 620 |
*/ |
624 |
*/ |
| 621 |
if (options.host_key_alias != NULL) { |
625 |
if (options.host_key_alias != NULL) { |
| 622 |
host = options.host_key_alias; |
626 |
host = options.host_key_alias; |
| 623 |
debug("using hostkeyalias: %s", host); |
627 |
debug("using hostkeyalias: %s", host); |
|
|
628 |
hoststr = xstrdup(host); |
| 629 |
ipstr = xstrdup(ip); |
| 630 |
} else if (port == 0 || port == SSH_DEFAULT_PORT) { |
| 631 |
/* unspecified or default port */ |
| 632 |
hoststr = xstrdup(host); |
| 633 |
ipstr = xstrdup(ip); |
| 634 |
} else { |
| 635 |
/* non-standard port, append port identifier */ |
| 636 |
len = strlen(host) + sizeof(port) * 4 + 2; |
| 637 |
hoststr = xmalloc(len); |
| 638 |
if (snprintf(hoststr, len, "%s@%hu", host, port) >= len) |
| 639 |
fatal("check_host_key: snprintf failed"); |
| 640 |
len = strlen(ip) + sizeof(port) * 4 + 2; |
| 641 |
ipstr = xmalloc(len); |
| 642 |
if (snprintf(ipstr, len, "%s@%hu", ip, port) >= len) |
| 643 |
fatal("check_host_key: snprintf failed"); |
| 624 |
} |
644 |
} |
| 625 |
|
645 |
|
| 626 |
/* |
646 |
/* |
|
Lines 634-646
check_host_key(char *host, struct sockad
Link Here
|
| 634 |
* hosts or in the systemwide list. |
654 |
* hosts or in the systemwide list. |
| 635 |
*/ |
655 |
*/ |
| 636 |
host_file = user_hostfile; |
656 |
host_file = user_hostfile; |
| 637 |
host_status = check_host_in_hostfile(host_file, host, host_key, |
657 |
host_status = check_host_in_hostfile(host_file, hoststr, host_key, |
| 638 |
file_key, &host_line); |
658 |
file_key, &host_line); |
| 639 |
if (host_status == HOST_NEW) { |
659 |
if (host_status == HOST_NEW) { |
| 640 |
host_file = system_hostfile; |
660 |
host_file = system_hostfile; |
| 641 |
host_status = check_host_in_hostfile(host_file, host, host_key, |
661 |
host_status = check_host_in_hostfile(host_file, hoststr, |
| 642 |
file_key, &host_line); |
662 |
host_key, file_key, &host_line); |
| 643 |
} |
663 |
} |
|
|
664 |
|
| 644 |
/* |
665 |
/* |
| 645 |
* Also perform check for the ip address, skip the check if we are |
666 |
* Also perform check for the ip address, skip the check if we are |
| 646 |
* localhost or the hostname was an ip address to begin with |
667 |
* localhost or the hostname was an ip address to begin with |
|
Lines 649-659
check_host_key(char *host, struct sockad
Link Here
|
| 649 |
Key *ip_key = key_new(host_key->type); |
670 |
Key *ip_key = key_new(host_key->type); |
| 650 |
|
671 |
|
| 651 |
ip_file = user_hostfile; |
672 |
ip_file = user_hostfile; |
| 652 |
ip_status = check_host_in_hostfile(ip_file, ip, host_key, |
673 |
ip_status = check_host_in_hostfile(ip_file, ipstr, host_key, |
| 653 |
ip_key, &ip_line); |
674 |
ip_key, &ip_line); |
| 654 |
if (ip_status == HOST_NEW) { |
675 |
if (ip_status == HOST_NEW) { |
| 655 |
ip_file = system_hostfile; |
676 |
ip_file = system_hostfile; |
| 656 |
ip_status = check_host_in_hostfile(ip_file, ip, |
677 |
ip_status = check_host_in_hostfile(ip_file, ipstr, |
| 657 |
host_key, ip_key, &ip_line); |
678 |
host_key, ip_key, &ip_line); |
| 658 |
} |
679 |
} |
| 659 |
if (host_status == HOST_CHANGED && |
680 |
if (host_status == HOST_CHANGED && |
|
Lines 670-691
check_host_key(char *host, struct sockad
Link Here
|
| 670 |
case HOST_OK: |
691 |
case HOST_OK: |
| 671 |
/* The host is known and the key matches. */ |
692 |
/* The host is known and the key matches. */ |
| 672 |
debug("Host '%.200s' is known and matches the %s host key.", |
693 |
debug("Host '%.200s' is known and matches the %s host key.", |
| 673 |
host, type); |
694 |
hoststr, type); |
| 674 |
debug("Found key in %s:%d", host_file, host_line); |
695 |
debug("Found key in %s:%d", host_file, host_line); |
| 675 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
696 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
| 676 |
if (readonly) |
697 |
if (readonly) |
| 677 |
logit("%s host key for IP address " |
698 |
logit("%s host key for IP address " |
| 678 |
"'%.128s' not in list of known hosts.", |
699 |
"'%.128s' not in list of known hosts.", |
| 679 |
type, ip); |
700 |
type, ipstr); |
| 680 |
else if (!add_host_to_hostfile(user_hostfile, ip, |
701 |
else if (!add_host_to_hostfile(user_hostfile, ip, |
| 681 |
host_key, options.hash_known_hosts)) |
702 |
host_key, options.hash_known_hosts)) |
| 682 |
logit("Failed to add the %s host key for IP " |
703 |
logit("Failed to add the %s host key for IP " |
| 683 |
"address '%.128s' to the list of known " |
704 |
"address '%.128s' to the list of known " |
| 684 |
"hosts (%.30s).", type, ip, user_hostfile); |
705 |
"hosts (%.30s).", type, ipstr, |
|
|
706 |
user_hostfile); |
| 685 |
else |
707 |
else |
| 686 |
logit("Warning: Permanently added the %s host " |
708 |
logit("Warning: Permanently added the %s host " |
| 687 |
"key for IP address '%.128s' to the list " |
709 |
"key for IP address '%.128s' to the list " |
| 688 |
"of known hosts.", type, ip); |
710 |
"of known hosts.", type, ipstr); |
| 689 |
} |
711 |
} |
| 690 |
break; |
712 |
break; |
| 691 |
case HOST_NEW: |
713 |
case HOST_NEW: |
|
Lines 699-710
check_host_key(char *host, struct sockad
Link Here
|
| 699 |
* alternative left is to abort. |
721 |
* alternative left is to abort. |
| 700 |
*/ |
722 |
*/ |
| 701 |
error("No %s host key is known for %.200s and you " |
723 |
error("No %s host key is known for %.200s and you " |
| 702 |
"have requested strict checking.", type, host); |
724 |
"have requested strict checking.", type, hoststr); |
| 703 |
goto fail; |
725 |
goto fail; |
| 704 |
} else if (options.strict_host_key_checking == 2) { |
726 |
} else if (options.strict_host_key_checking == 2) { |
| 705 |
char msg1[1024], msg2[1024]; |
727 |
char msg1[1024], msg2[1024]; |
| 706 |
|
728 |
|
| 707 |
if (show_other_keys(host, host_key)) |
729 |
if (show_other_keys(hoststr, host_key)) |
| 708 |
snprintf(msg1, sizeof(msg1), |
730 |
snprintf(msg1, sizeof(msg1), |
| 709 |
"\nbut keys of different type are already" |
731 |
"\nbut keys of different type are already" |
| 710 |
" known for this host."); |
732 |
" known for this host."); |
|
Lines 729-735
check_host_key(char *host, struct sockad
Link Here
|
| 729 |
"%s key fingerprint is %s.\n%s" |
751 |
"%s key fingerprint is %s.\n%s" |
| 730 |
"Are you sure you want to continue connecting " |
752 |
"Are you sure you want to continue connecting " |
| 731 |
"(yes/no)? ", |
753 |
"(yes/no)? ", |
| 732 |
host, ip, msg1, type, fp, msg2); |
754 |
hoststr, ipstr, msg1, type, fp, msg2); |
| 733 |
xfree(fp); |
755 |
xfree(fp); |
| 734 |
if (!confirm(msg)) |
756 |
if (!confirm(msg)) |
| 735 |
goto fail; |
757 |
goto fail; |
|
Lines 740-752
check_host_key(char *host, struct sockad
Link Here
|
| 740 |
*/ |
762 |
*/ |
| 741 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
763 |
if (options.check_host_ip && ip_status == HOST_NEW) { |
| 742 |
snprintf(hostline, sizeof(hostline), "%s,%s", |
764 |
snprintf(hostline, sizeof(hostline), "%s,%s", |
| 743 |
host, ip); |
765 |
hoststr, ipstr); |
| 744 |
hostp = hostline; |
766 |
hostp = hostline; |
| 745 |
if (options.hash_known_hosts) { |
767 |
if (options.hash_known_hosts) { |
| 746 |
/* Add hash of host and IP separately */ |
768 |
/* Add hash of host and IP separately */ |
| 747 |
r = add_host_to_hostfile(user_hostfile, host, |
769 |
r = add_host_to_hostfile(user_hostfile, hoststr, |
| 748 |
host_key, options.hash_known_hosts) && |
770 |
host_key, options.hash_known_hosts) && |
| 749 |
add_host_to_hostfile(user_hostfile, ip, |
771 |
add_host_to_hostfile(user_hostfile, ipstr, |
| 750 |
host_key, options.hash_known_hosts); |
772 |
host_key, options.hash_known_hosts); |
| 751 |
} else { |
773 |
} else { |
| 752 |
/* Add unhashed "host,ip" */ |
774 |
/* Add unhashed "host,ip" */ |
|
Lines 757-763
check_host_key(char *host, struct sockad
Link Here
|
| 757 |
} else { |
779 |
} else { |
| 758 |
r = add_host_to_hostfile(user_hostfile, host, host_key, |
780 |
r = add_host_to_hostfile(user_hostfile, host, host_key, |
| 759 |
options.hash_known_hosts); |
781 |
options.hash_known_hosts); |
| 760 |
hostp = host; |
782 |
hostp = hoststr; |
| 761 |
} |
783 |
} |
| 762 |
|
784 |
|
| 763 |
if (!r) |
785 |
if (!r) |
|
Lines 779-786
check_host_key(char *host, struct sockad
Link Here
|
| 779 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
801 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
| 780 |
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); |
802 |
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); |
| 781 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
803 |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
| 782 |
error("The %s host key for %s has changed,", type, host); |
804 |
error("The %s host key for %s has changed,", type, hoststr); |
| 783 |
error("and the key for the according IP address %s", ip); |
805 |
error("and the key for the according IP address %s", ipstr); |
| 784 |
error("%s. This could either mean that", key_msg); |
806 |
error("%s. This could either mean that", key_msg); |
| 785 |
error("DNS SPOOFING is happening or the IP address for the host"); |
807 |
error("DNS SPOOFING is happening or the IP address for the host"); |
| 786 |
error("and its host key have changed at the same time."); |
808 |
error("and its host key have changed at the same time."); |
|
Lines 799-805
check_host_key(char *host, struct sockad
Link Here
|
| 799 |
*/ |
821 |
*/ |
| 800 |
if (options.strict_host_key_checking) { |
822 |
if (options.strict_host_key_checking) { |
| 801 |
error("%s host key for %.200s has changed and you have " |
823 |
error("%s host key for %.200s has changed and you have " |
| 802 |
"requested strict checking.", type, host); |
824 |
"requested strict checking.", type, hoststr); |
| 803 |
goto fail; |
825 |
goto fail; |
| 804 |
} |
826 |
} |
| 805 |
|
827 |
|
|
Lines 860-866
check_host_key(char *host, struct sockad
Link Here
|
| 860 |
"Warning: the %s host key for '%.200s' " |
882 |
"Warning: the %s host key for '%.200s' " |
| 861 |
"differs from the key for the IP address '%.128s'" |
883 |
"differs from the key for the IP address '%.128s'" |
| 862 |
"\nOffending key for IP in %s:%d", |
884 |
"\nOffending key for IP in %s:%d", |
| 863 |
type, host, ip, ip_file, ip_line); |
885 |
type, hoststr, ipstr, ip_file, ip_line); |
| 864 |
if (host_status == HOST_OK) { |
886 |
if (host_status == HOST_OK) { |
| 865 |
len = strlen(msg); |
887 |
len = strlen(msg); |
| 866 |
snprintf(msg + len, sizeof(msg) - len, |
888 |
snprintf(msg + len, sizeof(msg) - len, |
|
Lines 882-897
check_host_key(char *host, struct sockad
Link Here
|
| 882 |
} |
904 |
} |
| 883 |
|
905 |
|
| 884 |
xfree(ip); |
906 |
xfree(ip); |
|
|
907 |
xfree(hoststr); |
| 908 |
xfree(ipstr); |
| 885 |
return 0; |
909 |
return 0; |
| 886 |
|
910 |
|
| 887 |
fail: |
911 |
fail: |
| 888 |
xfree(ip); |
912 |
xfree(ip); |
|
|
913 |
xfree(hoststr); |
| 914 |
xfree(ipstr); |
| 889 |
return -1; |
915 |
return -1; |
| 890 |
} |
916 |
} |
| 891 |
|
917 |
|
| 892 |
/* returns 0 if key verifies or -1 if key does NOT verify */ |
918 |
/* returns 0 if key verifies or -1 if key does NOT verify */ |
| 893 |
int |
919 |
int |
| 894 |
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
920 |
verify_host_key(char *host, u_short port, struct sockaddr *hostaddr, |
|
|
921 |
Key *host_key) |
| 895 |
{ |
922 |
{ |
| 896 |
struct stat st; |
923 |
struct stat st; |
| 897 |
int flags = 0; |
924 |
int flags = 0; |
|
Lines 919-929
verify_host_key(char *host, struct socka
Link Here
|
| 919 |
/* return ok if the key can be found in an old keyfile */ |
946 |
/* return ok if the key can be found in an old keyfile */ |
| 920 |
if (stat(options.system_hostfile2, &st) == 0 || |
947 |
if (stat(options.system_hostfile2, &st) == 0 || |
| 921 |
stat(options.user_hostfile2, &st) == 0) { |
948 |
stat(options.user_hostfile2, &st) == 0) { |
| 922 |
if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, |
949 |
if (check_host_key(host, port, hostaddr, host_key, /*readonly*/ 1, |
| 923 |
options.user_hostfile2, options.system_hostfile2) == 0) |
950 |
options.user_hostfile2, options.system_hostfile2) == 0) |
| 924 |
return 0; |
951 |
return 0; |
| 925 |
} |
952 |
} |
| 926 |
return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, |
953 |
return check_host_key(host, port, hostaddr, host_key, /*readonly*/ 0, |
| 927 |
options.user_hostfile, options.system_hostfile); |
954 |
options.user_hostfile, options.system_hostfile); |
| 928 |
} |
955 |
} |
| 929 |
|
956 |
|
|
Lines 940-945
ssh_login(Sensitive *sensitive, const ch
Link Here
|
| 940 |
{ |
967 |
{ |
| 941 |
char *host, *cp; |
968 |
char *host, *cp; |
| 942 |
char *server_user, *local_user; |
969 |
char *server_user, *local_user; |
|
|
970 |
u_short port = options.port ? options.port : SSH_DEFAULT_PORT; |
| 943 |
|
971 |
|
| 944 |
local_user = xstrdup(pw->pw_name); |
972 |
local_user = xstrdup(pw->pw_name); |
| 945 |
server_user = options.user ? options.user : local_user; |
973 |
server_user = options.user ? options.user : local_user; |
|
Lines 959-968
ssh_login(Sensitive *sensitive, const ch
Link Here
|
| 959 |
/* key exchange */ |
987 |
/* key exchange */ |
| 960 |
/* authenticate user */ |
988 |
/* authenticate user */ |
| 961 |
if (compat20) { |
989 |
if (compat20) { |
| 962 |
ssh_kex2(host, hostaddr); |
990 |
ssh_kex2(host, port, hostaddr); |
| 963 |
ssh_userauth2(local_user, server_user, host, sensitive); |
991 |
ssh_userauth2(local_user, server_user, host, sensitive); |
| 964 |
} else { |
992 |
} else { |
| 965 |
ssh_kex(host, hostaddr); |
993 |
ssh_kex(host, port, hostaddr); |
| 966 |
ssh_userauth1(local_user, server_user, host, sensitive); |
994 |
ssh_userauth1(local_user, server_user, host, sensitive); |
| 967 |
} |
995 |
} |
| 968 |
} |
996 |
} |