Add `X509_STORE_CTX_get0_cert` interface
This method reliably retrieves the certificate the `X509_STORE_CTX` is verifying, unlike `X509_STORE_CTX_get_current_cert`, which may return the "problematic" cert when verification fails.
This commit is contained in:
parent
6e35abb2cd
commit
eefc7b7265
|
|
@ -56,17 +56,29 @@ fn no_error_when_trusted_and_callback_returns_true() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn callback_receives_correct_certificate() {
|
fn callback_receives_correct_certificate() {
|
||||||
let server = Server::builder().build();
|
// Server sends the full chain (leaf + root)...
|
||||||
|
let server = Server::builder_full_chain().build();
|
||||||
|
// but client doesn't load the root as trusted.
|
||||||
|
// So we expect an error.
|
||||||
let mut client = server.client();
|
let mut client = server.client();
|
||||||
let expected = "59172d9313e84459bcff27f967e79e6e9217e584";
|
let leaf_sha1 = "59172d9313e84459bcff27f967e79e6e9217e584";
|
||||||
|
let root_sha1 = "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875";
|
||||||
client.ctx().set_verify(SslVerifyMode::PEER);
|
client.ctx().set_verify(SslVerifyMode::PEER);
|
||||||
client.ctx().set_cert_verify_callback(move |x509| {
|
client.ctx().set_cert_verify_callback(move |x509| {
|
||||||
assert!(!x509.verify_cert().unwrap());
|
assert!(!x509.verify_cert().unwrap());
|
||||||
|
// This is set to the root, since that's the problematic cert.
|
||||||
assert!(x509.current_cert().is_some());
|
assert!(x509.current_cert().is_some());
|
||||||
|
// This is set to the leaf, since that's the cert we're verifying.
|
||||||
|
assert!(x509.cert().is_some());
|
||||||
assert!(x509.verify_result().is_err());
|
assert!(x509.verify_result().is_err());
|
||||||
let cert = x509.current_cert().unwrap();
|
|
||||||
let digest = cert.digest(MessageDigest::sha1()).unwrap();
|
let root = x509.current_cert().unwrap();
|
||||||
assert_eq!(hex::encode(digest), expected);
|
let digest = root.digest(MessageDigest::sha1()).unwrap();
|
||||||
|
assert_eq!(hex::encode(digest), root_sha1);
|
||||||
|
|
||||||
|
let leaf = x509.cert().unwrap();
|
||||||
|
let digest = leaf.digest(MessageDigest::sha1()).unwrap();
|
||||||
|
assert_eq!(hex::encode(digest), leaf_sha1);
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,24 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serves the leaf and the root together.
|
||||||
|
pub fn builder_full_chain() -> Builder {
|
||||||
|
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||||
|
// Uses certs.pem instead of cert.pem.
|
||||||
|
ctx.set_certificate_chain_file("test/certs.pem").unwrap();
|
||||||
|
ctx.set_private_key_file("test/key.pem", SslFiletype::PEM)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Builder {
|
||||||
|
ctx,
|
||||||
|
ssl_cb: Box::new(|_| {}),
|
||||||
|
io_cb: Box::new(|_| {}),
|
||||||
|
err_cb: Box::new(|_| {}),
|
||||||
|
should_error: false,
|
||||||
|
expected_connections_count: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn client(&self) -> ClientBuilder {
|
pub fn client(&self) -> ClientBuilder {
|
||||||
ClientBuilder {
|
ClientBuilder {
|
||||||
ctx: SslContext::builder(SslMethod::tls()).unwrap(),
|
ctx: SslContext::builder(SslMethod::tls()).unwrap(),
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,20 @@ impl X509StoreContextRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the certificate being verified.
|
||||||
|
/// May return None if a raw public key is being verified.
|
||||||
|
#[corresponds(X509_STORE_CTX_get0_cert)]
|
||||||
|
pub fn cert(&self) -> Option<&X509Ref> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = ffi::X509_STORE_CTX_get0_cert(self.as_ptr());
|
||||||
|
if ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(X509Ref::from_ptr(ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder used to construct an `X509`.
|
/// A builder used to construct an `X509`.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue