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
Parsing a cert containing a raw IPv6 address as DNS SAN fails #3943
Comments
Looks like this simple patch would work for me, avoiding calling a deprecated function or so it claims. Sadly next thing to happen is
|
Patch v2:
|
Right now Our original plan was to deprecate the I'm frankly not entirely sure what to do here. Do we need a |
According to RFC 5280, it's not legal to have subjectAltName entries of type dNSName which contain IP addresses. Things of type dNSName should be valid DNS labels and the name MUST be in the "preferred name syntax", as specified by Section 3.5 of [RFC1034] and as modified by Section 2.1 of [RFC1123]. Even with the changes in RFC 1123 to allow DNS label components beginning with a number, a DNS label which exactly matches an IPv4 dotted decimal address is not allowed, and an IPv6 address would also not be allowed due to the presence of colons. So, I'm not sure we should be trying to support literal IP addresses appearing in dNSName GeneralNames. |
Being RFC compliant is one thing, having software that works with the rest of the world may be a different one. IPv4 dotted decimal address as DNS label is supported currently and is being used in many locations as a workaround for issues like the one I mentioned above. So it seems inconsistent to deny feature parity for IPv6 with the argument being "now that violates RFC". Denying both and forcing people to fix their real issues might be a good approach, but you'd better get some asbestos suits ready before that. @reaperhulk I do agree that conserving compatibility is a valid point, maybe adding |
Yeah RFC compliance isn’t relevant here (sadly) because there are certs in the wild that do this as a workaround for bugs in various software. requests will need to make changes no matter what due to its own idna functions (which are still cryptography's fault), but I suspect @Lukasa would appreciate a method that gives A-label bytes that require no encoding. |
I'll admit I haven't looked closely at the cryptography code in question here, but I'm still a bit lost about the discussion of returning these values as bytes. If we were to allow a literal IPv4 or IPv6 address to be associated with a GeneralName of type dNSName, I would still expect the return value to be a str value, not a bytes value. It would happen to be all ASCII in this case, but many non-IP-address DNS names would already return str values that were all ASCII, if they happened not to contain any Punycode sequences. As for wanting to return an encoded Punycode string instead of converting that to its Unicode equivalent, I guess I could see a function that returned a bytes value instead of a str making sense in that case, but why would that be the right thing to do for this case of IP addresses encoded as DNS names? Also, how would a caller know in advance whether the name they are getting the value of is going to be an actual DNS name that they should request as a str vs. an IP address they should request as bytes? Wouldn't it be simpler to just always return a string in both of these cases? After getting it back, they could always try and convert that string to an IP address to see if it was a DNS name or an IP address, and then from there convert it to whatever form they needed. |
@ronf we've chosen to deprecate the U-label behavior entirely (which is what The complexity here is that we have a bug in our IDNA decoding that causes raw IPv6 (and IPv4) to raise an exception when it attempts to generate the U-label string. Since So, we could fix the problem in cryptography by resolving the bug in the IDNA decode such that
I am still not happy with any of the solutions I've come up with for this issue. A new method seems foolish since it's just new return types... What about an optional arg |
Thanks for the extra info, @reaperhulk. If the long term plan is to switch from str to bytes and not do the Unicode conversions, I agree it would make sense to also return a bytes value which is an ASCII representation of the IPv4/IPv6 address exactly matching how it was encoded in the GeneralName. If both "value" and "bytes_value" will be available for some time, though, I think it could also make sense to set "value" to a string version of that same ASCII value. If the IDNA encoder fails here, perhaps you could have fallback code that would just do a decode() of the bytes value with encoding 'ascii' to cover that. That may fail if there's non-ASCII data in the bytes, but that would be illegal for a dNSName, so breaking in that case seems like it might be ok. As for get_values_for_type, I agree there isn't a great answer. You can't easily add a get_bytes_value_for_type() that parallels the existing function because some of the types don't have a bytes_value property. A defaulted a_label argument is an interesting alternative, but I agree it would be hard to ever get rid of that if it defaults to the behavior you want to eventually disallow. You'd have to deprecate it in phases where you first default it to False but make it a warning after a while if you don't set the argument to True, and then eventually only support the new behavior, still allowing the argument but only if set to True and warning whenever it was present that it is a no-op and should be removed. It would also bit a bit awkward if someone specified the a_label argument when asking to get values for a type like iPAddress. |
I put up a potential If we do that then calling That's still not great, but I haven't come up with an idea that isn't bad in some dimension so far... |
Keeping get_values_for_type as returning strings would definitely be better from a backward compatibility standpoint, and it's a lot cleaner than having an extra argument to choose between A-labels and U-labels. Since it's fairly easy for a caller to do their own conversion back to a full Unicode string, perhaps that's the better option for now. If a caller passed in something that was actual Unicode and not already an A-label string, would you still do the automatic conversion for them in the process of converting the value to bytes? |
The scenario is that I'm trying to access a server at e.g.
https://[2001:db8::17]/
running with a certificate that contains bothDNS:2001:db8::17
andIP:2001:db8::17
via urllib3, which in turn uses thecryptography
module in order to parse the certificate.With released version 2.0.3, there is an error already in
cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
, if I install the current git master, the error moves to a later stage whenext.get_values_for_type(x509.DNSName)
is called.After asking in
#cryptography-dev
I used the workarounf of dropping theDNS:...
part from the certificate, but in that case the certificate is no longer accepted by the standardhttplib
module, see https://bugs.python.org/issue23239, so we really need a fix to accept that part here.The text was updated successfully, but these errors were encountered: