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
Allow certificate claim checking to fall back to using CN #603
Conversation
We currently check only the Subject Alternative Name when looking at certificates In order to match RFC 2818, in the event there are no DNS values in the SAN field (or no SAN extension at all), fall back to using CN
@dotnet-bot test outerloop please |
LGTM |
@bartonjs could you also review please? |
Algorithmically, you've done the right thing here. The remaining problem is that GetDnsFromExtensions returns things that aren't dNSName values (and doesn't work on Unix). Lacking a SAN extension object to read from semantically (it's on my infinite TODO list), your best bet is to do something like:
Then, in GetDnsFromExtensions, skip over anything that doesn't match the dNSName prefix (for example, the ipAddress entries). |
@bartonjs - wondering if I could cheat here a bit. Basically we're looking at parsing the following: <separator(s)><separator(s)> is it sufficient to figure out that the identifier ("dnsName" or "DNS Name") is the string from the start of string to the first delimiter seen? I agree it's probably safer to move forward from the end of to the first non-whitespace, not-comma character though, just seeing if assuming we can assume identifier is Gist here with what I have for the moment: https://gist.github.com/iamjasonp/dbe3966aba99e8bc5d22; I ran this against Linux and it seems to parse out the various elements fine (In the gist, I stripped out a huge bunch of cruft around Console.WriteLine while I was playing around) |
(gee, brings me back to when I was mucking around with the various XmlReaders/Writers :) ) |
@iamjasonp Seems legit. I couldn't remember if there was a header on it (or not), but when I just looked at an example there wasn't. |
@iamjasonp And, to be pedantic to avoid confusion: |
Pedantic is good 😄 |
Update: things are looking good, seems like the OuterLoop test that broke in Linux are working again. I'll update this PR once it's in a state that's presentable, right now it's a big kludge. |
Previously, we blindly added all items contained in the SubjectAlternativeName, even though the SAN field could contain entries like iPAddress, eMail, URI, and we do not want to make claims for entries other than dNSName
…ridge * Allows bridge to specify the FriendlyName of the certificate for identification purposes * Changes created certs so that endpoints creating certs now also set the FriendlyName * Allow Subject Alternative Names to be specified separate from the Subject for testing purposes - e.g., when we only want to specify the CN and not the SAN
@dotnet-bot test outerloop please |
I came up with a really clunky way to test this functionality:
The reason we need to do this is because I haven't found a good way to allow BridgeClient to report to the Bridge what endpoint it believes it's hitting. So the Bridge is listening and doesn't care where the requests are coming in, but there's a difference to the client between hitting "localhost" or "testmachine" or "testmachine.example.com". I guess in this way, we test the positive and negative cases in one go, so that's a win, right? 😄 |
public static readonly char Delimiter; | ||
public static readonly string Separator; | ||
|
||
// static initializer runs only when one of the properties is accessed |
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.
I ran this through the debugger and noted that accessing X509SubjectAlternativeNameConstants.Oid
did not call the static initializer. It was called only when one of the readonly
fields was accessed.
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.
@iamjasonp Yep, const
values are embedded as literals at the callsite, the type isn't involved at runtime.
@bartonjs - arggh, semantics:
So... the current behaviour is that GetDnsFromExtensions will return an empty Thoughts on whether this is an important enough distinction? NINJA EDIT - looks like it's "subjectAltName extension of type dNSName is present", so I think the behaviour as implemented is correct. |
@iamjasonp I agree with the ninja edit, that you're doing the right thing in the case of SAN:Yes, DNS-SAN:No. |
Ideally we want functional tests to be deterministic. But I agree we should not block the checkin as the test does provide desired coverage and it will take some time to investigate a deterministic way. Please open an issue for the test improvement. From: Jason Pang [mailto:notifications@github.com] I came up with a really clunky way to test this functionality:
· Note that there are no Subject Alt Names for each of these
The reason we need to do this is because I haven't found a good way to allow BridgeClient to report to the Bridge what endpoint it believes it's hitting. So the Bridge is listening and doesn't care where the requests are coming in, but there's a difference to the client between hitting "localhost" or "testmachine" or "testmachine.example.com". I guess in this way, we test the positive and negative cases in one go, so that's a win, right? [:smile:] — |
4e74422
to
ecaa68f
Compare
One of the unfortunate parts about this particular test is that what is "correct" behaviour is only going to be defined at runtime, depending on what parameter you're passing into msbuild I have, however, modified the test to be a [Theory] test that is a bit better at compartmentalizing what a correct an incorrect variation is. |
7fb59ea
to
a9c251d
Compare
a9c251d
to
878c966
Compare
@dotnet-bot retest this please |
@dotnet-bot test outerloop please |
return list; | ||
} | ||
} | ||
} |
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.
Deterministic in the run time is sufficient. Thanks for being creative to solve the issue, Jason! LGTM from testing perspective.
LGTM, the only concern is the possibility of having an exception in the static block. I'm okay with a follow up PR to address that though. |
I'm trying to figure out why the outerloop build in CI will fail but the same failure doesn't repro locally for me, so there might be some light churn on the test. EDIT: got it. Retesting now, see #603 (comment) for explanation |
@dotnet-bot test outerloop please |
Verifies that when a Subject Alternative Name is not specified in an endpoint certificate, we are able to fall back to Subject CN to verify the endpoint
878c966
to
4c76923
Compare
@dotnet-bot test outerloop please |
FYI: the reason why outerloop tests were failing in CI is because when running a bridge as "localhost", the check for var domainNameEndpointUri = new Uri(Endpoints.Tcp_ClientCredentialType_Certificate_With_CanonicalName_DomainName_Address);
list.Add(new object[] {
domainNameEndpointUri,
domainNameEndpointUri.Host.IndexOf('.') == -1}); meant that the Bridge was always presenting URIs as "localhost - and thus the "should test pass" would still resolve as true, as we were only looking for "." in the hostname. Fixed this, and now it passes. (I usually run the bridge separately, and use the same Bridge instance across multiple runs, so I never ran into this issue. This issue will surface when running |
Allow certificate claim checking to fall back to using CN
We currently check only the Subject Alternative Name when looking at certificates. In order to match RFC 2818, in the event there are no DNS values in the SAN field (or no SAN extension at all), fall back to using CN (this is the behaviour that we use on Desktop pre-4.6)
Relates to #576