Skip to content
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

Do not skip first subject alt name when validating hostname #255

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

gmalkas
Copy link

@gmalkas gmalkas commented Feb 16, 2023

Hi there!

Thank you for this library.

I have recently run into an issue while writing a client using this library. The test server provided by an OEM (i.e., I can't change the server) has a certificate which includes two subject alternate names: one DNS and one application URI. The DNS hostname matches the one used to connect to the server, meaning the certificate is valid, but it comes first, so it is rejected by the library is_hostname_valid function.

The specification does not seem to mandate any specific order for subject alternative names:
https://reference.opcfoundation.org/Core/Part6/v105/docs/6.2.2

Skipping the first alt name can cause some valid server certificate to be rejected if the DNS name is the first one in the list. I am unsure why the first subj alt name was skipped in the first place.

Thank you.

The specification does not seem to mandate any specific order for
subject alternative names:
https://reference.opcfoundation.org/Core/Part6/v105/docs/6.2.2

Skipping the first alt name can cause some valid server certificate to
be rejected if the DNS name is the first one in the list.
@locka99
Copy link
Owner

locka99 commented Feb 17, 2023

My interpretation of the spec is what it says - applicationUri, hostnames - i.e., the first entry is the application uri and there are one or more hostnames / ip addresses thereafter. It's probably problematic to switch the ordering anyway since a uri / urn could potentially resemble an IPV6 address or vice versa. So even if the code were loosened it would still have to look for exactly one uri/urn somewhere in the list and filter it out correctly

Do you know how the client created its certificate and if it works with other OPC libraries? If it's a case of client error, then it's probably not a good idea to loosen security in the code for the sake of it.

@gmalkas
Copy link
Author

gmalkas commented Feb 17, 2023

Thank you for taking a look.

In my case, I am writing the client, it is the server certificate that is problematic due to the order of subject alternative names.

The open62541 C library looks at all SAN and picks the first one of type URI: https://github.com/open62541/open62541/blob/10047d4757eb2b37ca8d93c7124dcd421ce2ddbf/plugins/crypto/openssl/ua_pki_openssl.c#L634

For whatever it's worth, this library claims to be certified by the OPC Foundation: https://www.open62541.org/certification/

I am not super familiar with x509v3 but my reading of the openssl manpage indicates the subject alternative names are typed, meaning the ambiguity between URI/URN and IP wouldn't happen:

Subject Alternative Name

This is a multi-valued extension that supports several types of name identifier, including email (an email address), URI (a uniform resource indicator), DNS (a DNS domain name), RID (a registered ID: OBJECT IDENTIFIER), IP (an IP address), dirName (a distinguished name), and otherName. The syntax of each is described in the following paragraphs.

(https://www.openssl.org/docs/manmaster/man5/x509v3_config.html)

Here is an example on a client certificate generated by UAExpert (https://www.unified-automation.com/products/development-tools/uaexpert.html):

X509v3 Subject Alternative Name:
                URI:urn:myhostname:UnifiedAutomation:UaExpert, DNS:myhostname

URI: and DNS: are indicating the type of the entry, so there is no ambiguity. If an IP was specified for the URI, it would still have a type of URI.

Note that UAExpert is able to connect to the server with the problematic certificate.

Does it make sense?

Thank you.

@gmalkas
Copy link
Author

gmalkas commented Feb 18, 2023

Hi,

I've looked into this further and checked the official OPC Foundation reference implementation in C#.

They do verify the application URI/URN and server domain name by looking at the certificate subject alternative names of the relevant type.

In particular, they check the server domain name against every name of type DNS: https://github.com/OPCFoundation/UA-.NETStandard/blob/6d675b8cd0107372240fc530a95c5d2f59228820/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs#L173

And the application URI against the first name of type URI:
https://github.com/OPCFoundation/UA-.NETStandard/blob/7d9be41cf5337e7832819ef76f150b8573c1ef12/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs#L636 and https://github.com/OPCFoundation/UA-.NETStandard/blob/6d675b8cd0107372240fc530a95c5d2f59228820/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs#L127

I will refactor my change to match that implementation. Let me know if that makes sense.

Thanks!

@locka99
Copy link
Owner

locka99 commented Feb 18, 2023

You might be able to replace the skip with a .filter(|n| n.dnsname().is_some() || n.ipaddress().is_some()) so it doesn't assume the application uri is first and will skip anything which is not a dnsname / ipaddress.

I think the code as-is is perhaps a little fragile and maybe needs work to enforce the spec more stringently. I don't have time to look at the other impls at the moment but think it could be changed to work with application uri(s) anywhere, favouring the first uri and filter out anything that is not a host/dnsnames from places that test that kind of thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants