View | Details | Raw Unified | Return to bug 910 | Differences between
and this patch

Collapse All | Expand All

(-)sshconnect.c (-27 / +56 lines)
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 621-626 check_host_key(char *host, struct sockad Link Here
621
	if (options.host_key_alias != NULL) {
624
	if (options.host_key_alias != NULL) {
622
		host = options.host_key_alias;
625
		host = options.host_key_alias;
623
		debug("using hostkeyalias: %s", host);
626
		debug("using hostkeyalias: %s", host);
627
		hoststr = xstrdup(host);
628
		ipstr = xstrdup(ip);
629
	} else {
630
		/* we have no HostKeyAlias */
631
		if (port == 0 || port == SSH_DEFAULT_PORT) {
632
			/* default or unspecified port */
633
			hoststr = xstrdup(host);
634
			ipstr = xstrdup(ip);
635
		} else {
636
			/* append port identifier */
637
			r = snprintf(msg, sizeof(msg), "%hu", port);
638
			len = r + strlen(host) + 2;
639
			hoststr = xmalloc(len);
640
			snprintf(hoststr, len, "%s@%hu", host, port);
641
			len = r + strlen(ip) + 2;
642
			ipstr = xmalloc(len);
643
			snprintf(ipstr, len, "%s@%hu", ip, port);
644
		}
624
	}
645
	}
625
646
626
	/*
647
	/*
Lines 634-646 check_host_key(char *host, struct sockad Link Here
634
	 * hosts or in the systemwide list.
655
	 * hosts or in the systemwide list.
635
	 */
656
	 */
636
	host_file = user_hostfile;
657
	host_file = user_hostfile;
637
	host_status = check_host_in_hostfile(host_file, host, host_key,
658
	host_status = check_host_in_hostfile(host_file, hoststr, host_key,
638
	    file_key, &host_line);
659
	    file_key, &host_line);
639
	if (host_status == HOST_NEW) {
660
	if (host_status == HOST_NEW) {
640
		host_file = system_hostfile;
661
		host_file = system_hostfile;
641
		host_status = check_host_in_hostfile(host_file, host, host_key,
662
		host_status = check_host_in_hostfile(host_file, hoststr,
642
		    file_key, &host_line);
663
		    host_key, file_key, &host_line);
643
	}
664
	}
665
644
	/*
666
	/*
645
	 * Also perform check for the ip address, skip the check if we are
667
	 * 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
668
	 * 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);
671
		Key *ip_key = key_new(host_key->type);
650
672
651
		ip_file = user_hostfile;
673
		ip_file = user_hostfile;
652
		ip_status = check_host_in_hostfile(ip_file, ip, host_key,
674
		ip_status = check_host_in_hostfile(ip_file, ipstr, host_key,
653
		    ip_key, &ip_line);
675
		    ip_key, &ip_line);
654
		if (ip_status == HOST_NEW) {
676
		if (ip_status == HOST_NEW) {
655
			ip_file = system_hostfile;
677
			ip_file = system_hostfile;
656
			ip_status = check_host_in_hostfile(ip_file, ip,
678
			ip_status = check_host_in_hostfile(ip_file, ipstr,
657
			    host_key, ip_key, &ip_line);
679
			    host_key, ip_key, &ip_line);
658
		}
680
		}
659
		if (host_status == HOST_CHANGED &&
681
		if (host_status == HOST_CHANGED &&
Lines 670-691 check_host_key(char *host, struct sockad Link Here
670
	case HOST_OK:
692
	case HOST_OK:
671
		/* The host is known and the key matches. */
693
		/* The host is known and the key matches. */
672
		debug("Host '%.200s' is known and matches the %s host key.",
694
		debug("Host '%.200s' is known and matches the %s host key.",
673
		    host, type);
695
		    hoststr, type);
674
		debug("Found key in %s:%d", host_file, host_line);
696
		debug("Found key in %s:%d", host_file, host_line);
675
		if (options.check_host_ip && ip_status == HOST_NEW) {
697
		if (options.check_host_ip && ip_status == HOST_NEW) {
676
			if (readonly)
698
			if (readonly)
677
				logit("%s host key for IP address "
699
				logit("%s host key for IP address "
678
				    "'%.128s' not in list of known hosts.",
700
				    "'%.128s' not in list of known hosts.",
679
				    type, ip);
701
				    type, ipstr);
680
			else if (!add_host_to_hostfile(user_hostfile, ip,
702
			else if (!add_host_to_hostfile(user_hostfile, ip,
681
			    host_key, options.hash_known_hosts))
703
			    host_key, options.hash_known_hosts))
682
				logit("Failed to add the %s host key for IP "
704
				logit("Failed to add the %s host key for IP "
683
				    "address '%.128s' to the list of known "
705
				    "address '%.128s' to the list of known "
684
				    "hosts (%.30s).", type, ip, user_hostfile);
706
				    "hosts (%.30s).", type, ipstr,
707
				    user_hostfile);
685
			else
708
			else
686
				logit("Warning: Permanently added the %s host "
709
				logit("Warning: Permanently added the %s host "
687
				    "key for IP address '%.128s' to the list "
710
				    "key for IP address '%.128s' to the list "
688
				    "of known hosts.", type, ip);
711
				    "of known hosts.", type, ipstr);
689
		}
712
		}
690
		break;
713
		break;
691
	case HOST_NEW:
714
	case HOST_NEW:
Lines 699-710 check_host_key(char *host, struct sockad Link Here
699
			 * alternative left is to abort.
722
			 * alternative left is to abort.
700
			 */
723
			 */
701
			error("No %s host key is known for %.200s and you "
724
			error("No %s host key is known for %.200s and you "
702
			    "have requested strict checking.", type, host);
725
			    "have requested strict checking.", type, hoststr);
703
			goto fail;
726
			goto fail;
704
		} else if (options.strict_host_key_checking == 2) {
727
		} else if (options.strict_host_key_checking == 2) {
705
			char msg1[1024], msg2[1024];
728
			char msg1[1024], msg2[1024];
706
729
707
			if (show_other_keys(host, host_key))
730
			if (show_other_keys(hoststr, host_key))
708
				snprintf(msg1, sizeof(msg1),
731
				snprintf(msg1, sizeof(msg1),
709
				   "\nbut keys of different type are already"
732
				   "\nbut keys of different type are already"
710
				   " known for this host.");
733
				   " known for this host.");
Lines 729-735 check_host_key(char *host, struct sockad Link Here
729
			    "%s key fingerprint is %s.\n%s"
752
			    "%s key fingerprint is %s.\n%s"
730
			    "Are you sure you want to continue connecting "
753
			    "Are you sure you want to continue connecting "
731
			    "(yes/no)? ",
754
			    "(yes/no)? ",
732
			    host, ip, msg1, type, fp, msg2);
755
			    hoststr, ipstr, msg1, type, fp, msg2);
733
			xfree(fp);
756
			xfree(fp);
734
			if (!confirm(msg))
757
			if (!confirm(msg))
735
				goto fail;
758
				goto fail;
Lines 740-752 check_host_key(char *host, struct sockad Link Here
740
		 */
763
		 */
741
		if (options.check_host_ip && ip_status == HOST_NEW) {
764
		if (options.check_host_ip && ip_status == HOST_NEW) {
742
			snprintf(hostline, sizeof(hostline), "%s,%s",
765
			snprintf(hostline, sizeof(hostline), "%s,%s",
743
			    host, ip);
766
			    hoststr, ipstr);
744
			hostp = hostline;
767
			hostp = hostline;
745
			if (options.hash_known_hosts) {
768
			if (options.hash_known_hosts) {
746
				/* Add hash of host and IP separately */
769
				/* Add hash of host and IP separately */
747
				r = add_host_to_hostfile(user_hostfile, host,
770
				r = add_host_to_hostfile(user_hostfile, hoststr,
748
				    host_key, options.hash_known_hosts) &&
771
				    host_key, options.hash_known_hosts) &&
749
				    add_host_to_hostfile(user_hostfile, ip,
772
				    add_host_to_hostfile(user_hostfile, ipstr,
750
				    host_key, options.hash_known_hosts);
773
				    host_key, options.hash_known_hosts);
751
			} else {
774
			} else {
752
				/* Add unhashed "host,ip" */
775
				/* Add unhashed "host,ip" */
Lines 757-763 check_host_key(char *host, struct sockad Link Here
757
		} else {
780
		} else {
758
			r = add_host_to_hostfile(user_hostfile, host, host_key,
781
			r = add_host_to_hostfile(user_hostfile, host, host_key,
759
			    options.hash_known_hosts);
782
			    options.hash_known_hosts);
760
			hostp = host;
783
			hostp = hoststr;
761
		}
784
		}
762
785
763
		if (!r)
786
		if (!r)
Lines 779-786 check_host_key(char *host, struct sockad Link Here
779
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
802
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
780
			error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
803
			error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
781
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
804
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
782
			error("The %s host key for %s has changed,", type, host);
805
			error("The %s host key for %s has changed,", type, hoststr);
783
			error("and the key for the according IP address %s", ip);
806
			error("and the key for the according IP address %s", ipstr);
784
			error("%s. This could either mean that", key_msg);
807
			error("%s. This could either mean that", key_msg);
785
			error("DNS SPOOFING is happening or the IP address for the host");
808
			error("DNS SPOOFING is happening or the IP address for the host");
786
			error("and its host key have changed at the same time.");
809
			error("and its host key have changed at the same time.");
Lines 799-805 check_host_key(char *host, struct sockad Link Here
799
		 */
822
		 */
800
		if (options.strict_host_key_checking) {
823
		if (options.strict_host_key_checking) {
801
			error("%s host key for %.200s has changed and you have "
824
			error("%s host key for %.200s has changed and you have "
802
			    "requested strict checking.", type, host);
825
			    "requested strict checking.", type, hoststr);
803
			goto fail;
826
			goto fail;
804
		}
827
		}
805
828
Lines 860-866 check_host_key(char *host, struct sockad Link Here
860
		    "Warning: the %s host key for '%.200s' "
883
		    "Warning: the %s host key for '%.200s' "
861
		    "differs from the key for the IP address '%.128s'"
884
		    "differs from the key for the IP address '%.128s'"
862
		    "\nOffending key for IP in %s:%d",
885
		    "\nOffending key for IP in %s:%d",
863
		    type, host, ip, ip_file, ip_line);
886
		    type, hoststr, ipstr, ip_file, ip_line);
864
		if (host_status == HOST_OK) {
887
		if (host_status == HOST_OK) {
865
			len = strlen(msg);
888
			len = strlen(msg);
866
			snprintf(msg + len, sizeof(msg) - len,
889
			snprintf(msg + len, sizeof(msg) - len,
Lines 882-897 check_host_key(char *host, struct sockad Link Here
882
	}
905
	}
883
906
884
	xfree(ip);
907
	xfree(ip);
908
	xfree(hoststr);
909
	xfree(ipstr);
885
	return 0;
910
	return 0;
886
911
887
fail:
912
fail:
888
	xfree(ip);
913
	xfree(ip);
914
	xfree(hoststr);
915
	xfree(ipstr);
889
	return -1;
916
	return -1;
890
}
917
}
891
918
892
/* returns 0 if key verifies or -1 if key does NOT verify */
919
/* returns 0 if key verifies or -1 if key does NOT verify */
893
int
920
int
894
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
921
verify_host_key(char *host, u_short port, struct sockaddr *hostaddr,
922
    Key *host_key)
895
{
923
{
896
	struct stat st;
924
	struct stat st;
897
	int flags = 0;
925
	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 */
947
	/* return ok if the key can be found in an old keyfile */
920
	if (stat(options.system_hostfile2, &st) == 0 ||
948
	if (stat(options.system_hostfile2, &st) == 0 ||
921
	    stat(options.user_hostfile2, &st) == 0) {
949
	    stat(options.user_hostfile2, &st) == 0) {
922
		if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,
950
		if (check_host_key(host, port, hostaddr, host_key, /*readonly*/ 1,
923
		    options.user_hostfile2, options.system_hostfile2) == 0)
951
		    options.user_hostfile2, options.system_hostfile2) == 0)
924
			return 0;
952
			return 0;
925
	}
953
	}
926
	return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,
954
	return check_host_key(host, port, hostaddr, host_key, /*readonly*/ 0,
927
	    options.user_hostfile, options.system_hostfile);
955
	    options.user_hostfile, options.system_hostfile);
928
}
956
}
929
957
Lines 940-945 ssh_login(Sensitive *sensitive, const ch Link Here
940
{
968
{
941
	char *host, *cp;
969
	char *host, *cp;
942
	char *server_user, *local_user;
970
	char *server_user, *local_user;
971
	u_short port = options.port ? options.port : SSH_DEFAULT_PORT;
943
972
944
	local_user = xstrdup(pw->pw_name);
973
	local_user = xstrdup(pw->pw_name);
945
	server_user = options.user ? options.user : local_user;
974
	server_user = options.user ? options.user : local_user;
Lines 959-968 ssh_login(Sensitive *sensitive, const ch Link Here
959
	/* key exchange */
988
	/* key exchange */
960
	/* authenticate user */
989
	/* authenticate user */
961
	if (compat20) {
990
	if (compat20) {
962
		ssh_kex2(host, hostaddr);
991
		ssh_kex2(host, port, hostaddr);
963
		ssh_userauth2(local_user, server_user, host, sensitive);
992
		ssh_userauth2(local_user, server_user, host, sensitive);
964
	} else {
993
	} else {
965
		ssh_kex(host, hostaddr);
994
		ssh_kex(host, port, hostaddr);
966
		ssh_userauth1(local_user, server_user, host, sensitive);
995
		ssh_userauth1(local_user, server_user, host, sensitive);
967
	}
996
	}
968
}
997
}
(-)sshconnect.h (-3 / +3 lines)
Lines 40-49 ssh_connect(const char *, struct sockadd Link Here
40
void
40
void
41
ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *);
41
ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *);
42
42
43
int	 verify_host_key(char *, struct sockaddr *, Key *);
43
int	 verify_host_key(char *, u_short, struct sockaddr *, Key *);
44
44
45
void	 ssh_kex(char *, struct sockaddr *);
45
void	 ssh_kex(char *, u_short, struct sockaddr *);
46
void	 ssh_kex2(char *, struct sockaddr *);
46
void	 ssh_kex2(char *, u_short, struct sockaddr *);
47
47
48
void	 ssh_userauth1(const char *, const char *, char *, Sensitive *);
48
void	 ssh_userauth1(const char *, const char *, char *, Sensitive *);
49
void	 ssh_userauth2(const char *, const char *, char *, Sensitive *);
49
void	 ssh_userauth2(const char *, const char *, char *, Sensitive *);
(-)sshconnect1.c (-2 / +2 lines)
Lines 465-471 try_password_authentication(char *prompt Link Here
465
 * SSH1 key exchange
465
 * SSH1 key exchange
466
 */
466
 */
467
void
467
void
468
ssh_kex(char *host, struct sockaddr *hostaddr)
468
ssh_kex(char *host, u_short port, struct sockaddr *hostaddr)
469
{
469
{
470
	int i;
470
	int i;
471
	BIGNUM *key;
471
	BIGNUM *key;
Lines 523-529 ssh_kex(char *host, struct sockaddr *hos Link Here
523
	debug("Received server public key (%d bits) and host key (%d bits).",
523
	debug("Received server public key (%d bits) and host key (%d bits).",
524
	    BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n));
524
	    BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n));
525
525
526
	if (verify_host_key(host, hostaddr, host_key) == -1)
526
	if (verify_host_key(host, port, hostaddr, host_key) == -1)
527
		fatal("Host key verification failed.");
527
		fatal("Host key verification failed.");
528
528
529
	client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
529
	client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
(-)sshconnect2.c (-2 / +4 lines)
Lines 67-72 u_char *session_id2 = NULL; Link Here
67
u_int session_id2_len = 0;
67
u_int session_id2_len = 0;
68
68
69
char *xxx_host;
69
char *xxx_host;
70
u_short xxx_port;
70
struct sockaddr *xxx_hostaddr;
71
struct sockaddr *xxx_hostaddr;
71
72
72
Kex *xxx_kex = NULL;
73
Kex *xxx_kex = NULL;
Lines 74-90 Kex *xxx_kex = NULL; Link Here
74
static int
75
static int
75
verify_host_key_callback(Key *hostkey)
76
verify_host_key_callback(Key *hostkey)
76
{
77
{
77
	if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
78
	if (verify_host_key(xxx_host, xxx_port, xxx_hostaddr, hostkey) == -1)
78
		fatal("Host key verification failed.");
79
		fatal("Host key verification failed.");
79
	return 0;
80
	return 0;
80
}
81
}
81
82
82
void
83
void
83
ssh_kex2(char *host, struct sockaddr *hostaddr)
84
ssh_kex2(char *host, u_short port, struct sockaddr *hostaddr)
84
{
85
{
85
	Kex *kex;
86
	Kex *kex;
86
87
87
	xxx_host = host;
88
	xxx_host = host;
89
	xxx_port = port;
88
	xxx_hostaddr = hostaddr;
90
	xxx_hostaddr = hostaddr;
89
91
90
	if (options.ciphers == (char *)-1) {
92
	if (options.ciphers == (char *)-1) {

Return to bug 910