w3c / openscreenprotocol

Open Screen Protocol
https://www.w3.org/TR/openscreenprotocol/
Other
93 stars 22 forks source link

TLS SNI requirement is incompatible with TLS SNI definition #275

Closed sleevi closed 1 month ago

sleevi commented 3 years ago

Section 4.1 contains the following language: https://github.com/w3c/openscreenprotocol/blob/5488c7b7cce9c9c64ba97348a8deb0c6c50eb9bb/index.bs#L343-L345

This may be incompatible with the definition of SNI from RFC 6066, Section 3, which normatively references RFC 5890, which has LDH labels (of which A-Labels are a subset), expanded on in Section 2.3.1

The issue here is that underscore, as used by these records, is not part of the Preferred Name Syntax (which only allows Letters, Digits, and Hyphens). This is also called out within RFC 8499, which states:

 This term and its equivalent, "hostname", have been
  widely used but are not defined in [RFC1034], [RFC1035],
  [RFC1123], or [RFC2181].  The DNS was originally deployed into the
  Host Tables environment as outlined in [RFC952], and it is likely
  that the term followed informally from the definition there.  Over
  time, the definition seems to have shifted.  "Host name" is often
  meant to be a domain name that follows the rules in Section 3.5 of
  [RFC1034], which is also called the "preferred name syntax".  (In
  that syntax, every character in each label is a letter, a digit,
  or a hyphen).  Note that any label in a domain name can contain
  any octet value; hostnames are generally considered to be domain
  names where every label follows the rules in the "preferred name
  syntax", with the amendment that labels can start with ASCII
  digits (this amendment comes from Section 2.1 of [RFC1123]).

It's not obvious why SNI needs to be supported for this use case, so I'm not sure where to offer productive suggestions (e.g. as an Errata/attempt to redefine SNI to unambiguously allow arbitrary domain names, and not just host names, or some other TLS approach).

Could you clarify why the server needs to know the expected fingerprint, given that it will have advertised that via mDNS? If a certificate rotation event occurs, presumably, the mDNS update flow can handle this?

markafoltz commented 3 years ago

Tagging @GrumpyOldTroll, who mentioned they have a contact who could comment on whether an SNI was required by current TLS implementations.

enygren commented 3 years ago

(Note that this comment quickly ratholes goes well past the scope of openscreenprotocol so likely belongs as a discussion on the TLS WG mailing list.)

What really matters here is making sure that servers always have a way to demux incoming requests and determine which certificate to return to a client without requiring the server to have a separate IP address or port per certificate. For the cert rotation case, or for the case where there are multiple active services on the network, or in cases where a service wants to have multiple internal instances for various reasons it seems cleaner for this to be explicit in the SNI.

For the specific case of openscreenprotocol, perhaps this would be a good case to define a new NameType? It seems like what is being desired is for the SNI value to select authentication based on a particular {fingerprint,service}. This could be a common pattern for peer-wise authentication like this, so having a new NameType that is a struct that includes a service name (a DNS name including underscores) and an instance_fingerprint (variable length octet string) would work well for this use-case and might also work well for similar use-cases. It's possible that this might also be usable for some other services discovered through the local network following this mDNS pattern.

One challenge is that per https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 the allowed SAN values are supersets of allowed SNI values. There are other cases where this is also an issue. If looking at this for the openscreenprotocol case it might also be worth the broader community exploring whether it is a good time to look at other use-cases.

For example, another use-case that has come up in some IETF WGs recently is that literal IP addresses aren't technically allowed as SNI values but are allowed as certificate SANs. One approach might be a draft that specifies one or more new SNI NameTypes (rfc6066 section 3), although that might introduce compatibility issues as there are likely clients today that send IPv4 and IPv6 address strings (to select certs with IPv4/IPv6 address SANs) in-violation of the current spec. That might also be a good opportunity to revisit whether IP addresses should get a new NameType or whether so many clients already misbehave that we should update how they fit into the spec.

sleevi commented 3 years ago

@enygren In like with the updates happening to RFC 6125, it seems tackling this such that there’s a relationship between SAN type and ServerName type, allowing a client to express all of their acceptable reference identifiers, would tackle this? For OSP, it seems SRVName is what is intended, while for the iPAddress issue you highlight, that could also be tackled?

kaduk commented 3 years ago

There's a pretty complicated set of issues surrouding TLS SNI usage and what's deployable, and we haven't quite covered all of it yet, here.

As @enygren notes, SNI is vital for a server to be able to demux incoming connections and select the proper certificate+configuration.

In theory it can also serve to provide an authenticated mechanism that ensures that both parties agree on the server identity (since the extension is part of the handshake transcript that's digested into the key schedule in TLS 1.3 and when extended-master-secret is used with earlier TLS versions). However, in order for that to occur, the server has to send a response extension to confirm that it used the SNI data from the client; many servers in practice will use the SNI information from the client but not send this response extension.

The ecosystem for SNI name types other than host_name is pretty defunct. Some TLS implementations don't even provide a usable API to handle other name types. While it's an attractive option just from looking at the protocol specification, it would be challenging at best to actually make use of that flexibility in practice. Not least, the values do not appear to be managed by an IANA registry, and so producing a new one would likely require some action by the IETF TLS working group.


It remains somewhat unclear to me just based on the discussion on this issue and the immediate context of the linked part of the openscreenprotocol spec exactly what role the SNI usage is intended to play for this protocol.

In some ways it seems analogous to the WebRTC case, where participants often end up using self-signed certificates and exchanging the fingerprints of those certificates over an external (authenticated) channel, e.g., an SDP signalling channel. I believe the state of the art in that case involves using the external_session_id TLS extension from RFC 8844 to get agreement between parties, spanning both the TLS channel and the external signaling channel, about which identities (e.g., fingerprints) are in use for the TLS channel. That RFC also defines an external_id_hash extension that can be useful in similar scenarios as well.

The discussion in RFC 8844 about the unknown key-share attack in general also seems of some applicability here. What technical mechanisms are needed to prevent attacks will depend on the scope in which a given certificate/fingerprint is used, in particular if it's used for more than one "call". In particular, if there is external signaling about what the expected fingerprint is, and the server will not need to select amongst multiple potential certificates based on the information in the TLS ClientHello (since that knowledge comes from an external channel), the TLS SNI extension may not be necessary in this scenario. But again, I don't understand the use case well enough to be able to make statements with any kind of certainty here.

Finally, I note that there is a lot of flexibility about how to construct hostnames that would go in the SNI extension, if such a name is needed. Using underscored "SRV-like" names is one option (and admittedly attractive due to the mDNS usage), but does not seem to be the only option. For example, the Home Networking Control Protocol uses names under home.arpa.(RFC 8375), and the control and usage of such names is specified in the corresponding RFCs. There is admittedly some significant administrative and specification overhead involved in getting a special-use name under .arpa, but given that this is a W3C activity it does not seem worth dismissing entirely.

markafoltz commented 6 months ago

Proposal by David Schinazi in code review:

It sounds like the OpenScreenProtocol specification is using SNI incorrectly. The host name in the SNI should be the "Service Instance Name" as defined in RFC 6763. I'd recommend fixing the OSP spec to pass in the correct hostname to TLS instead of making QUICHE allow invalid hostnames.

DavidSchinazi commented 6 months ago

From skimming this issue, your best bet is most likely to drop SNI usage entirely. The purpose of SNI is to allow the client to give the server a hint as to what certificate it should use. Unless I'm misunderstanding things, that's not useful here.

markafoltz commented 6 months ago

It could be useful in situations where multiple agents are sharing a IP:port, because of proxies, or firewall rules preventing binding of multiple ports. However it's not strictly necessary.

DavidSchinazi commented 6 months ago

That makes sense, thanks. In that scenario, would the agents have distinct Instance Names? If they do, then we could have the SNI match the actual mDNS hostname of the agent. We'd still need to figure out the underscores, but we'd be closer.

DavidSchinazi commented 6 months ago

Actually, the underscore wouldn't be a problem. With mDNS, you browse for _openscreen._udp.local and that allows you to find BigTV.local, which you can then put in the SNI. Any reason not to do that?

kaduk commented 6 months ago

Actually, the underscore wouldn't be a problem. With mDNS, you browse for _openscreen._udp.local and that allows you to find BigTV.local, which you can then put in the SNI. Any reason not to do that?

When RFC 6066 says ""HostName" contains the fully qualified DNS hostname of the server, as understood by the client", that is usually taken to mean before doing any CNAME chasing or lookup. That said, if you're going to specify special behavior for a given application protocol (like dropping underscores) that doesn't seem especially different from specifying that the mDNS resolution of the provided name is ok, provided that the resulting security considerations are accurately documented.

DavidSchinazi commented 6 months ago

mDNS/DNS-SD doesn't involve CNAMEs. First you browse (by querying for PTR records), in this case with service type set to _openscreen._udp. That'll provide a list of instances, which are represented as tuples (instance name, service type, domain) where the service type will always be _openscreen._udp, and for mDNS the domain will be local. Then for each of those, you lookup its SRV record to get the corresponding hostname and port. In this scenario, the hostname will be something like BigTV.local, it won't contain the service name (the service name is only used when querying PTR and SRV records, not A or AAAA). So if the application protocol uses TLS/QUIC, then normally the TLS SNI would be set to BigTV.local.

wangw-1991 commented 6 months ago

mDNS/DNS-SD doesn't involve CNAMEs. First you browse (by querying for PTR records), in this case with service type set to _openscreen._udp. That'll provide a list of instances, which are represented as tuples (instance name, service type, domain) where the service type will always be _openscreen._udp, and for mDNS the domain will be local. Then for each of those, you lookup its SRV record to get the corresponding hostname and port. In this scenario, the hostname will be something like BigTV.local, it won't contain the service name (the service name is only used when querying PTR and SRV records, not A or AAAA). So if the application protocol uses TLS/QUIC, then normally the TLS SNI would be set to BigTV.local.

It seems reasonable to me to set TLS SNI to instance name + domain, like BigTV.local, because the instance name is unique and can be used to identify a specific server. Can we change the spec to use instance name + domain as SNI?

enygren commented 6 months ago

I think a desired approach might be something like Martin Thomson's HTTPS for Local Domains, but it would need to be defined in some other context. See https://docs.google.com/document/d/170rFC91jqvpFrKIqG4K8Vox8AL4LeQXzfikBQXYPmzU/edit#heading=h.cp9yfs7gg5p7 for an example proposal.

This same thing was coming up as a problem for ADD and there was talk about having an IETF BOF on this topic.

But in that context, the mDNS responder would include a public key fingerprint as part of its response, and the public key fingerprint would be part of the HTTP Origin as well. There'd be a cryptographic binding between the mDNS response and the TLS connection, and any state would be scoped solidly to the key (eg, so if the key changed there wouldn't be leakage).

In that case the TLS SNI would be something like _NPNE4IG2GJ4VAL4DCHL64YSM5BII4A2X.BigTV.local

DavidSchinazi commented 6 months ago

@enygren while I absolutely agree that solving the problem of insecure local connectivity is important and worth spending time on, this issue is about the Open Screen Protocol. And OSP is definitely not the right place to solve this large complex security issue. OSP has its own security model for exchanging keys. If binding those to the TLS handshake is worthwhile, the SNI is not the right place to do it.

markafoltz commented 1 month ago

Closed by the PR landed for #276.