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

Collapse All | Expand All

(-)sshconnect.c (-30 / +58 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 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
}
(-)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) {
(-)sshd.8 (+3 lines)
Lines 552-557 A pattern may also be preceded by Link Here
552
to indicate negation: if the host name matches a negated
552
to indicate negation: if the host name matches a negated
553
pattern, it is not accepted (by that line) even if it matched another
553
pattern, it is not accepted (by that line) even if it matched another
554
pattern on the line.
554
pattern on the line.
555
A hostname may optionally be followed by a
556
.Ql @
557
and then a non-standard port number.
555
.Pp
558
.Pp
556
Alternately, hostnames may be stored in a hashed form which hides host names
559
Alternately, hostnames may be stored in a hashed form which hides host names
557
and addresses should the file's contents be disclosed.
560
and addresses should the file's contents be disclosed.

Return to bug 910