-
Notifications
You must be signed in to change notification settings - Fork 876
Add support for multiple client certificates #6162
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next
Next commit
Add support for multiple client certificates
- Loading branch information
commit 97b9c4b88f884ea77e15ad6b41a5810cb93a7dd2
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
So there's no way to read multiple certificates (as above with
X509Certificate2Collection.ImportFromPemFile()) if the PEM file happens to be encrypted with a password or key? While with PKCS12 it's possible (below we doX509CertificateLoader.LoadPkcs12CollectionFromFile)?Is this a weird/arbitrary .NET limitation, is it tracked somewhere?
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.
Seems to be intentional dotnet/runtime#31944 (comment)
To quote:
I'm still investigating a few things in regards to how pg actually behaves so there might be some other changes in this pr.
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.
OK, it's a mess.
A bit of context: you can send certificates from a client to the server which then can validate them either for auth or just in general. That's so called client certificates.
One requirement for them is that client certificate has to have private key. Just having a certificate with public key would not do.
The basic validation pg can do is that that certificate is signed by some other trusted certificate (CA). Here there is no issue, we already support this from our side.
The problem is when there are multiple certificates in between the trusted (CA) and the client (leaf). Let's say we have a CA->intermediate->leaf chain. PG only has CA while we have both intermediate and leaf certificates. In this case we have to send both of them, as otherwise PG can't establish the whole chain and rejects our connection. That's the original issue this pr is fixing.
Now, here's the fun part.
X509Certificate2.CreateFromPemFilehas: it loads only the first certificate, ignoring everything else. This way we can load the first certificate with both key and password and then load all other certificates viaX509Certificate2Collection.ImportFromPemFile. This still makes it so we have a duplicate of the first certificate, but it's easy to remove it since we know it's the first one.SslClientAuthenticationOptionshas a propertyClientCertificateswhich we're using to send client certificates. The problem is, it doesn't work for intermediate certificates. If they're not trusted or they don't have a private key,SslStreamseems to completely ignore them, making the chain incomplete. From my understanding, that's due to the way SChannel works (and this behavior was copied to other platforms). Which means that we have to useSslStreamCertificateContext.Createand explicitly specify which certificate is leaf and which are additional. The main issue is thatSslStreamCertificateContextdoesn't exist for .NET Framework, so that means we can't backport that fix to npgsql 8, but I'm personally OK with leaving it to 9 and 10.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.
OK. I just want to confirm that the thing we're supporting here (loading first certificate with key/password, the rest of the certificates with public key only) is "standard" - or just supported by libpq (if libpq supports it ideally so should we). If so, seems quite smelly that we need to hack around like this in .NET rather than having a more 1st-class API (is it worth raising the problem more explicitly?).
Otherwise at this point doing something that can't be backported to netfx seems completely fine to me.