mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Reject multilayer certificates in check_cert.
Rejecting them in the CA config box reminded me that the main checking code also ought to do the same thing.
This commit is contained in:
parent
4b0e54c22a
commit
b753cf6e3b
@ -726,11 +726,40 @@ static bool opensshcert_check_cert(
|
|||||||
|
|
||||||
ptrlen signature = ptrlen_from_strbuf(ck->signature);
|
ptrlen signature = ptrlen_from_strbuf(ck->signature);
|
||||||
|
|
||||||
ca_key = opensshcert_ca_pub_key(ck, signature, NULL);
|
/*
|
||||||
|
* The OpenSSH certificate spec is one-layer only: it explicitly
|
||||||
|
* forbids using a certified key in turn as the CA.
|
||||||
|
*
|
||||||
|
* If it did not, then we'd also have to recursively verify
|
||||||
|
* everything up the CA chain until we reached the ultimate root,
|
||||||
|
* and then make sure _that_ was something we trusted. (Not to
|
||||||
|
* mention that there'd probably be an additional SSH_CERT_TYPE_CA
|
||||||
|
* or some such, and certificate options saying what kinds of
|
||||||
|
* certificate a CA was trusted to sign for, and ...)
|
||||||
|
*/
|
||||||
|
ca_key = opensshcert_ca_pub_key(ck, make_ptrlen(NULL, 0), NULL);
|
||||||
if (!ca_key) {
|
if (!ca_key) {
|
||||||
put_fmt(error, "Certificate's signing key is invalid");
|
put_fmt(error, "Certificate's signing key is invalid");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (ssh_key_alg(ca_key)->is_certificate) {
|
||||||
|
put_fmt(error, "Certificate is signed with a certified key "
|
||||||
|
"(forbidden by OpenSSH certificate specification)");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now re-instantiate the key in a way that matches the signature
|
||||||
|
* (i.e. so that if the key is an RSA one we get the right subtype
|
||||||
|
* of RSA).
|
||||||
|
*/
|
||||||
|
ssh_key_free(ca_key);
|
||||||
|
ca_key = opensshcert_ca_pub_key(ck, signature, NULL);
|
||||||
|
if (!ca_key) {
|
||||||
|
put_fmt(error, "Certificate's signing key does not match "
|
||||||
|
"signature type");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check which signature algorithm is actually in use, because
|
/* Check which signature algorithm is actually in use, because
|
||||||
* that might be a reason to reject the certificate (e.g. ssh-rsa
|
* that might be a reason to reject the certificate (e.g. ssh-rsa
|
||||||
|
@ -2715,6 +2715,43 @@ Private-MAC: 5b1f6f4cc43eb0060d2c3e181bc0129343adba2b
|
|||||||
False, b'username', 1000, '')
|
False, b'username', 1000, '')
|
||||||
self.assertEqual(result, True)
|
self.assertEqual(result, True)
|
||||||
|
|
||||||
|
# Make a certificate on the CA key, and re-sign the main
|
||||||
|
# key using that, to ensure that two-level certs are rejected
|
||||||
|
ca_self_certificate = sign_cert_via_testcrypt(
|
||||||
|
make_signature_preimage(
|
||||||
|
key_to_certify = ca_key.public_blob(),
|
||||||
|
ca_key = ca_key,
|
||||||
|
certtype = CertType.user,
|
||||||
|
keyid = b'id',
|
||||||
|
serial = 111,
|
||||||
|
principals = [b"doesn't matter"],
|
||||||
|
valid_after = 1000,
|
||||||
|
valid_before = 2000), ca_key, signflags=ca_signflags)
|
||||||
|
import base64
|
||||||
|
print(base64.b64encode(ca_self_certificate))
|
||||||
|
self_signed_ca_key = ssh_key_new_pub(
|
||||||
|
alg + '-cert', ca_self_certificate)
|
||||||
|
print(self_signed_ca_key)
|
||||||
|
cert_pub = sign_cert_via_testcrypt(
|
||||||
|
make_signature_preimage(
|
||||||
|
key_to_certify = base_key.public_blob(),
|
||||||
|
ca_key = self_signed_ca_key,
|
||||||
|
certtype = CertType.user,
|
||||||
|
keyid = b'id',
|
||||||
|
serial = 111,
|
||||||
|
principals = [b'username'],
|
||||||
|
valid_after = 1000,
|
||||||
|
valid_before = 2000), ca_key, signflags=ca_signflags)
|
||||||
|
print(base64.b64encode(cert_pub))
|
||||||
|
certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
|
||||||
|
base_key.private_blob())
|
||||||
|
result, err = certified_key.check_cert(
|
||||||
|
False, b'username', 1500, '')
|
||||||
|
self.assertEqual(result, False)
|
||||||
|
self.assertEqual(
|
||||||
|
err, b'Certificate is signed with a certified key '
|
||||||
|
b'(forbidden by OpenSSH certificate specification)')
|
||||||
|
|
||||||
# Now try a host certificate. We don't need to do _all_ the
|
# Now try a host certificate. We don't need to do _all_ the
|
||||||
# checks over again, but at least make sure that setting
|
# checks over again, but at least make sure that setting
|
||||||
# CertType.host leads to the certificate validating with
|
# CertType.host leads to the certificate validating with
|
||||||
|
Loading…
x
Reference in New Issue
Block a user