diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 55e5c75d..146a77b0 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -108,21 +108,39 @@ impl X509StoreContextRef { } /// Initializes this context with the given certificate, certificates chain and certificate - /// store. - /// For successive calls to this function, it is required to call `cleanup` in beforehand. + /// store. After initializing the context, the `with_context` closure is called with the prepared + /// context. As long as the closure is running, the context stays initialized and can be used + /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished. /// /// * `trust` - The certificate store with the trusted certificates. /// * `cert` - The certificate that should be verified. /// * `cert_chain` - The certificates chain. + /// * `with_context` - The closure that is called with the initialized context. /// - /// This corresponds to [`X509_STORE_CTX_init`]. + /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to + /// [`X509_STORE_CTX_cleanup`] after calling `with_context`. /// /// [`X509_STORE_CTX_init`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html - pub fn init(&mut self, trust: &store::X509StoreRef, cert: &X509Ref, - cert_chain: &StackRef) -> Result<(), ErrorStack> { + /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html + pub fn init(&mut self, trust: &store::X509StoreRef, cert: &X509Ref, + cert_chain: &StackRef, with_context: F) -> Result + where + F: FnOnce(&mut X509StoreContextRef) -> Result + { + struct Cleanup<'a>(&'a mut X509StoreContextRef); + + impl<'a> Drop for Cleanup<'a> { + fn drop(&mut self) { + self.0.cleanup(); + } + } + unsafe { cvt(ffi::X509_STORE_CTX_init(self.as_ptr(), trust.as_ptr(), - cert.as_ptr(), cert_chain.as_ptr())).map(|_| ()) + cert.as_ptr(), cert_chain.as_ptr()))?; + + let cleanup = Cleanup(self); + with_context(cleanup.0) } } @@ -147,7 +165,7 @@ impl X509StoreContextRef { /// This corresponds to [`X509_STORE_CTX_cleanup`]. /// /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html - pub fn cleanup(&mut self) { + fn cleanup(&mut self) { unsafe { ffi::X509_STORE_CTX_cleanup(self.as_ptr()); } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 9b630d0e..e3c726ae 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -306,11 +306,8 @@ fn test_verify_cert() { let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); - assert!(context.init(&store, &cert, &chain).is_ok()); - assert!(context.verify_cert().is_ok()); - context.cleanup(); - assert!(context.init(&store, &cert, &chain).is_ok()); - assert!(context.verify_cert().is_ok()); + assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); + assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); } #[test] @@ -326,6 +323,5 @@ fn test_verify_fails() { let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); - assert!(context.init(&store, &cert, &chain).is_ok()); - assert!(context.verify_cert().is_err()); + assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_err()); }