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

Collapse All | Expand All

(-)usr.bin/ssh/sshconnect2.c (-14 / +51 lines)
Lines 988-998 input_userauth_passwd_changereq(int type Link Here
988
}
988
}
989
989
990
static const char *
990
static const char *
991
identity_sign_encode(struct identity *id)
991
key_sign_encode(const struct sshkey *key)
992
{
992
{
993
	struct ssh *ssh = active_state;
993
	struct ssh *ssh = active_state;
994
994
995
	if (id->key->type == KEY_RSA) {
995
	if (key->type == KEY_RSA) {
996
		switch (ssh->kex->rsa_sha2) {
996
		switch (ssh->kex->rsa_sha2) {
997
		case 256:
997
		case 256:
998
			return "rsa-sha2-256";
998
			return "rsa-sha2-256";
Lines 1000-1006 identity_sign_encode(struct identity *id Link Here
1000
			return "rsa-sha2-512";
1000
			return "rsa-sha2-512";
1001
		}
1001
		}
1002
	}
1002
	}
1003
	return key_ssh_name(id->key);
1003
	return key_ssh_name(key);
1004
}
1004
}
1005
1005
1006
static int
1006
static int
Lines 1009-1039 identity_sign(struct identity *id, u_cha Link Here
1009
{
1009
{
1010
	Key *prv;
1010
	Key *prv;
1011
	int ret;
1011
	int ret;
1012
	const char *alg;
1013
1014
	alg = identity_sign_encode(id);
1015
1012
1016
	/* the agent supports this key */
1013
	/* the agent supports this key */
1017
	if (id->agent_fd != -1)
1014
	if (id->key != NULL && id->agent_fd != -1)
1018
		return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
1015
		return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
1019
		    data, datalen, alg, compat);
1016
		    data, datalen, key_sign_encode(id->key), compat);
1020
1017
1021
	/*
1018
	/*
1022
	 * we have already loaded the private key or
1019
	 * we have already loaded the private key or
1023
	 * the private key is stored in external hardware
1020
	 * the private key is stored in external hardware
1024
	 */
1021
	 */
1025
	if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
1022
	if (id->key != NULL &&
1026
		return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg,
1023
	    (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)))
1027
		    compat));
1024
		return (sshkey_sign(id->key, sigp, lenp, data, datalen,
1025
		    key_sign_encode(id->key), compat));
1026
1028
	/* load the private key from the file */
1027
	/* load the private key from the file */
1029
	if ((prv = load_identity_file(id)) == NULL)
1028
	if ((prv = load_identity_file(id)) == NULL)
1030
		return SSH_ERR_KEY_NOT_FOUND;
1029
		return SSH_ERR_KEY_NOT_FOUND;
1031
	ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
1030
	ret = sshkey_sign(prv, sigp, lenp, data, datalen,
1031
	    key_sign_encode(prv), compat);
1032
	sshkey_free(prv);
1032
	sshkey_free(prv);
1033
	return (ret);
1033
	return (ret);
1034
}
1034
}
1035
1035
1036
static int
1036
static int
1037
id_filename_matches(Identity *id, Identity *private_id)
1038
{
1039
	const char *suffixes[] = { ".pub", "-cert.pub", NULL };
1040
	size_t len = strlen(id->filename), plen = strlen(private_id->filename);
1041
	size_t i, slen;
1042
1043
	if (strcmp(id->filename, private_id->filename) == 0)
1044
		return 1;
1045
	for (i = 0; suffixes[i]; i++) {
1046
		slen = strlen(suffixes[i]);
1047
		if (len > slen && plen == len - slen &&
1048
		    strcmp(id->filename + (len - slen), suffixes[i]) == 0 &&
1049
		    memcmp(id->filename, private_id->filename, plen) == 0)
1050
			return 1;
1051
	}
1052
	return 0;
1053
}
1054
1055
static int
1037
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1056
sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1038
{
1057
{
1039
	Buffer b;
1058
	Buffer b;
Lines 1075-1081 sign_and_send_pubkey(Authctxt *authctxt, Link Here
1075
	} else {
1094
	} else {
1076
		buffer_put_cstring(&b, authctxt->method->name);
1095
		buffer_put_cstring(&b, authctxt->method->name);
1077
		buffer_put_char(&b, have_sig);
1096
		buffer_put_char(&b, have_sig);
1078
		buffer_put_cstring(&b, identity_sign_encode(id));
1097
		buffer_put_cstring(&b, key_sign_encode(id->key));
1079
	}
1098
	}
1080
	buffer_put_string(&b, blob, bloblen);
1099
	buffer_put_string(&b, blob, bloblen);
1081
1100
Lines 1095-1100 sign_and_send_pubkey(Authctxt *authctxt, Link Here
1095
				break;
1114
				break;
1096
			}
1115
			}
1097
		}
1116
		}
1117
		/*
1118
		 * Exact key matches are preferred, but also allow
1119
		 * filename matches for non-PKCS#11/agent keys that
1120
		 * didn't load public keys. This supports the case
1121
		 * of keeping just a private key file and public
1122
		 * certificate on disk.
1123
		 */
1124
		if (!matched && !id->isprivate && id->agent_fd == -1 &&
1125
		    (id->key->flags & SSHKEY_FLAG_EXT) == 0) {
1126
			TAILQ_FOREACH(private_id, &authctxt->keys, next) {
1127
				if (private_id->key == NULL &&
1128
				    id_filename_matches(id, private_id)) {
1129
					id = private_id;
1130
					matched = 1;
1131
					break;
1132
				}
1133
			}
1134
		}
1098
		if (matched) {
1135
		if (matched) {
1099
			debug2("%s: using private key \"%s\"%s for "
1136
			debug2("%s: using private key \"%s\"%s for "
1100
			    "certificate", __func__, id->filename,
1137
			    "certificate", __func__, id->filename,
Lines 1173-1179 send_pubkey_test(Authctxt *authctxt, Ide Link Here
1173
	packet_put_cstring(authctxt->method->name);
1210
	packet_put_cstring(authctxt->method->name);
1174
	packet_put_char(have_sig);
1211
	packet_put_char(have_sig);
1175
	if (!(datafellows & SSH_BUG_PKAUTH))
1212
	if (!(datafellows & SSH_BUG_PKAUTH))
1176
		packet_put_cstring(identity_sign_encode(id));
1213
		packet_put_cstring(key_sign_encode(id->key));
1177
	packet_put_string(blob, bloblen);
1214
	packet_put_string(blob, bloblen);
1178
	free(blob);
1215
	free(blob);
1179
	packet_send();
1216
	packet_send();
(-)regress/usr.bin/ssh/cert-file.sh (-10 / +41 lines)
Lines 17-40 ${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ Link Here
17
	fatal "ssh-keygen failed"
17
	fatal "ssh-keygen failed"
18
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
18
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
19
	fatal "ssh-keygen failed"
19
	fatal "ssh-keygen failed"
20
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key3 || \
21
	fatal "ssh-keygen failed"
22
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key4 || \
23
	fatal "ssh-keygen failed"
24
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key5 || \
25
	fatal "ssh-keygen failed"
26
20
# Move the certificate to a different address to better control
27
# Move the certificate to a different address to better control
21
# when it is offered.
28
# when it is offered.
22
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
29
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
23
	-z $$ -n ${USER} $OBJ/user_key1 ||
30
	-z $$ -n ${USER} $OBJ/user_key1 ||
24
		fail "couldn't sign user_key1 with user_ca_key1"
31
		fatal "couldn't sign user_key1 with user_ca_key1"
25
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_1.pub
32
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_1.pub
26
${SSHKEYGEN} -q -s $OBJ/user_ca_key2 -I "regress user key for $USER" \
33
${SSHKEYGEN} -q -s $OBJ/user_ca_key2 -I "regress user key for $USER" \
27
	-z $$ -n ${USER} $OBJ/user_key1 ||
34
	-z $$ -n ${USER} $OBJ/user_key1 ||
28
		fail "couldn't sign user_key1 with user_ca_key2"
35
		fatal "couldn't sign user_key1 with user_ca_key2"
29
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_2.pub
36
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1_2.pub
37
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
38
	-z $$ -n ${USER} $OBJ/user_key3 ||
39
		fatal "couldn't sign user_key3 with user_ca_key1"
40
rm $OBJ/user_key3.pub # to test use of private key w/o public half.
41
${SSHKEYGEN} -q -s $OBJ/user_ca_key1 -I "regress user key for $USER" \
42
	-z $$ -n ${USER} $OBJ/user_key4 ||
43
		fatal "couldn't sign user_key4 with user_ca_key1"
44
rm $OBJ/user_key4 $OBJ/user_key4.pub # to test no matching pub/private key case.
30
45
31
trace 'try with identity files'
46
trace 'try with identity files'
32
opts="-F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
47
opts="-F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
33
opts2="$opts -i $OBJ/user_key1 -i $OBJ/user_key2"
48
opts2="$opts -i $OBJ/user_key1 -i $OBJ/user_key2"
34
echo "cert-authority $(cat $OBJ/user_ca_key1.pub)" > $OBJ/authorized_keys_$USER
49
echo "cert-authority $(cat $OBJ/user_ca_key1.pub)" > $OBJ/authorized_keys_$USER
35
50
51
# Make a clean config that doesn't have any pre-added identities.
52
cat $OBJ/ssh_proxy | grep -v IdentityFile > $OBJ/no_identity_config
53
54
# XXX: verify that certificate used was what we expect. Needs exposure of
55
# keys via enviornment variable or similar.
56
36
for p in ${SSH_PROTOCOLS}; do
57
for p in ${SSH_PROTOCOLS}; do
58
	# Key with no .pub should work - finding the equivalent *-cert.pub.
59
	verbose "protocol $p: identity cert with no plain public file"
60
	${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
61
	    -i $OBJ/user_key3 somehost exit 5$p
62
	[ $? -ne 5$p ] && fail "ssh failed"
63
64
	# CertificateFile matching private key with no .pub file should work.
65
	verbose "protocol $p: CertificateFile with no plain public file"
66
	${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \
67
	    -oCertificateFile=$OBJ/user_key3-cert.pub \
68
	    -i $OBJ/user_key3 somehost exit 5$p
69
	[ $? -ne 5$p ] && fail "ssh failed"
70
37
	# Just keys should fail
71
	# Just keys should fail
72
	verbose "protocol $p: plain keys"
38
	${SSH} $opts2 somehost exit 5$p
73
	${SSH} $opts2 somehost exit 5$p
39
	r=$?
74
	r=$?
40
	if [ $r -eq 5$p ]; then
75
	if [ $r -eq 5$p ]; then
Lines 42-47 for p in ${SSH_PROTOCOLS}; do Link Here
42
	fi
77
	fi
43
78
44
	# Keys with untrusted cert should fail.
79
	# Keys with untrusted cert should fail.
80
	verbose "protocol $p: untrusted cert"
45
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
81
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
46
	${SSH} $opts3 somehost exit 5$p
82
	${SSH} $opts3 somehost exit 5$p
47
	r=$?
83
	r=$?
Lines 50-55 for p in ${SSH_PROTOCOLS}; do Link Here
50
	fi
86
	fi
51
87
52
	# Good cert with bad key should fail.
88
	# Good cert with bad key should fail.
89
	verbose "protocol $p: good cert, bad key"
53
	opts3="$opts -i $OBJ/user_key2"
90
	opts3="$opts -i $OBJ/user_key2"
54
	opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
91
	opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
55
	${SSH} $opts3 somehost exit 5$p
92
	${SSH} $opts3 somehost exit 5$p
Lines 59-64 for p in ${SSH_PROTOCOLS}; do Link Here
59
	fi
96
	fi
60
97
61
	# Keys with one trusted cert, should succeed.
98
	# Keys with one trusted cert, should succeed.
99
	verbose "protocol $p: single trusted"
62
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
100
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
63
	${SSH} $opts3 somehost exit 5$p
101
	${SSH} $opts3 somehost exit 5$p
64
	r=$?
102
	r=$?
Lines 67-86 for p in ${SSH_PROTOCOLS}; do Link Here
67
	fi
105
	fi
68
106
69
	# Multiple certs and keys, with one trusted cert, should succeed.
107
	# Multiple certs and keys, with one trusted cert, should succeed.
108
	verbose "protocol $p: multiple trusted"
70
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
109
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub"
71
	opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
110
	opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
72
	${SSH} $opts3 somehost exit 5$p
111
	${SSH} $opts3 somehost exit 5$p
73
	r=$?
112
	r=$?
74
	if [ $r -ne 5$p ]; then
113
	if [ $r -ne 5$p ]; then
75
		fail "ssh failed with multiple certs in protocol $p"
114
		fail "ssh failed with multiple certs in protocol $p"
76
	fi
77
78
	#Keys with trusted certificate specified in config options, should succeed.
79
	opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub"
80
	${SSH} $opts3 somehost exit 5$p
81
	r=$?
82
	if [ $r -ne 5$p ]; then
83
		fail "ssh failed with trusted cert in config in protocol $p"
84
	fi
115
	fi
85
done
116
done
86
117

Return to bug 2617