-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new with extra roots on windows #135
Add new with extra roots on windows #135
Conversation
6b1ec76
to
e3bd04e
Compare
After experimenting using So we can't use I've come up with 3 possible solutions:
Click to expand the code fn new_with_extra_roots(
roots: &[pki_types::CertificateDer<'static>],
) -> Result<Self, TlsError> {
let mut inner = Self::new()?;
// In memory store for the extra roots
let mut additional_store = CertificateStore::new()?;
for root in roots {
additional_store.add_cert(root)?;
}
// System store
let mut pvpara: Vec<_> = "root".encode_utf16().collect();
pvpara.push(0);
let system_store = unsafe { CertOpenSystemStoreW(0, pvpara.as_ptr()) };
// We create a collection, and we add the two previous created stores.
let collection = unsafe {
CertOpenStore(
CERT_STORE_PROV_COLLECTION,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
ptr::null(), //must be null in that case
)
};
unsafe {
CertAddStoreToCollection(
collection,
system_store,
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
0,
)
};
unsafe {
CertAddStoreToCollection(
collection,
additional_store.inner.as_ptr(),
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
0,
)
};
let mut config = CERT_CHAIN_ENGINE_CONFIG::zeroed_with_size();
config.hExclusiveRoot = collection;
//.. However, this seems fragile as in Windows they are Root stores in various places. It will be hard to cover and maintain the roots that match the ones that are naturally looked by
Other referencesIn the source code of curl and Dotnet, we can see that they only support using extra roots exclusively, not in combination with the system root store like we plan to support. |
e3bd04e
to
70f4c28
Compare
This MR is ready to review, I've opted for the golang approach that I discussed on discord. The Android job failure seems unrelated, as it's already on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, I think this approach is the most reasonable we have, and the code looks good for the most part.
One open question I have is about the infallibility of new_with_extra_roots
. After seeing how we need to implement this on Windows, I'm wondering if we want to return Result<Self, TlsError>
instead so that we can do OS-level logic in the constructor instead of being restricted to infallible operations.
The reason I mention this is because I think the re-build logic in this is not great for efficiency if we assume that the case where extra roots are provided is required for most, if not all, chain building operations to succeed. Instead we are allocating a new CertificateStore
, parsing all the DER provided by the user again, etc. Instead, you could envision that we keep an Option<CertificateStore>
on the Verifier
structure instead of Vec<CertificateDer<'static>
and reuse that when encountering partial chain errors.
Apologies I had queued review comments I hadn't submitted from a few days ago. I think Complexspaces and I overlapped in some feedback as a result.
I would be in favour of this 👍 |
|
70f4c28
to
cf4ceb6
Compare
cf4ceb6
to
db872b0
Compare
db872b0
to
64c0328
Compare
Thank you both for the thorough review!
I also totally agree this could be better this way. I've implemented a new constructor where I parse the certificates right away. I now store the certificate engine in the verifier to avoid creating a store each time for the extra roots. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me within my limited understanding of the windows_sys
APIs. Thank you @stormshield-gt !
} | ||
|
||
// SAFETY: We know no other threads is mutating the `CertEngine`, because it would require `unsafe`. | ||
// Across the FFI, `CertGetCertificateChain` don't mutate it either. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No action needed: I'm not 100% certain of this assertion FWIW, but I think there's enough supporting evidence to go with it. Windows handles are generally thread safe, the CertFreeCertificateChainEngine
function doesn't say it invalidates the handle, and an engine is really just a set of parameters Windows needs to read.
64c0328
to
ddcaa3e
Compare
No need to block on me; I looked at it but didn't have time to dig into the details of the Windows API. |
Thanks again for your work on this @stormshield-gt 🎉 |
Windows implementation of
new_with_extra_roots
, which have some problems for now as mentioned in #133 (comment).Note that it's based on top of #133 to benefit the tests defined here.
Partially Fix #58