quinn-rs / quinn

Async-friendly QUIC implementation in Rust
Apache License 2.0
3.84k stars 394 forks source link

Allow certificate access on Connecting #1922

Open n-lebel opened 4 months ago

n-lebel commented 4 months ago

I'm writing an application that needs to run some custom checks on a peer's TLS certificate (more specifically on its public key) before accepting a connection. In the current implementation, it seems this data is not available through the Connecting struct, only through Connection which necessitates accepting the connection beforehand. It seems like this should be doable given that Connecting does have access to handshake_data, which sources its info from the Session just like peer_identity does.

I'll look into implementing this, happy to hear any suggestions or other ways to go about this if any. Thanks!

djc commented 4 months ago

The HandshakeData currently only exposes server name and application protocol, which are submitted in the ClientHello message and are thus available as soon as connection is initiated. The peer's TLS certificate is transmitted later in this TLS handshake and thus will not be available as soon as Connecting is made available. I guess it will become available over the lifetime of the Connecting, but for this reason I don't think it will slot in as easily as you're suggesting it will in your OP.

Ralith commented 4 months ago

I am interested in having this. I think the implementation should be similar to handshake_data. The simplest approach would probably be to build similar infrastructure as used for handshake_data and expose a separate async peer_identity getter. One caveat is that we should use a tokio::sync::Notify rather than a oneshot channel so that the method can be &self and have multiple waiters; handshake_data predates this pattern and we haven't gotten around to updating it.

In an ideal world I'd like to be able to access both handshake data and the peer identity on the server before committing to a ServerConfig, similarly to how you can currently inspect information from the first packet via Incoming, but that's probably a larger change than necessary to achieve your goals here.

djc commented 4 months ago

@Ralith I don't think you can get to the peer identity before committing to config in rustls, and even at the protocol level you'll need to commit to a bunch of configuration values before you get the peer identity, AFAIK?

Ralith commented 4 months ago

Ah, okay. We could still probably do the ClientHello stuff (in particular dispatching config based on server name is interesting) but I guess that's completely off topic for this issue then.

djc commented 4 months ago

Right, doing an Acceptor thing for the server would be interesting, but that's separate from the client identity.