Repository navigation
Conversation
An endpoint created by the S command has no remote fingerprint until
the A or P command supplies one, but rtpp_dtls_conn_dtls_recv() still
answered a ClientHello in that state and, once the handshake finished,
skipped the fingerprint check because pvt->fingerprint was empty. Any
host that reached the advertised port between S and A/P could complete
the handshake with a throwaway self-signed certificate: the SRTP
contexts were keyed with that peer, the A/P command that followed was
refused ("cannot change mode ... when in the 2 state") and relayed
media stayed encrypted to, and accepted from, that peer.
Drop DTLS packets while no peer fingerprint is configured, the peer
retransmits its ClientHello and the handshake completes once A/P has
arrived. The check after the handshake no longer has a no-fingerprint
case.
The dtls scenario used by tests/dtls_gw relied on this: in the second
gena's fingerprint (the A went to the geno-facing stream through L6).
Give it gena's fingerprint with U6 before gena starts the handshake.
Validated by driving the real rtpp_dtls_conn object with an OpenSSL
DTLS client: before the change a handshake made before A completes and
keys SRTP, after it the handshake only completes once A has supplied
the matching fingerprint, and a mismatching one still fails.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Repro:
U ... && M4:1 S, then, before theA/Pfor that leg arrives, send a DTLS ClientHello with any self-signed certificate to the returned port. The handshake completes and SRTP is keyed with that peer. The realAis then refused with "cannot change mode from 0 to 2 when in the 2 state", so relayed media keeps going to (and being accepted from) whoever got there first.Cause:
rtpp_dtls_conn_dtls_recv()answers the handshake inRDC_INITbefore any peer fingerprint is set, and the check after the handshake is skipped whenpvt->fingerprintis empty.Fix: drop DTLS packets until
A/Phas supplied the fingerprint (the peer retransmits its ClientHello), and make the comparison unconditional.The dtls scenario used by
tests/dtls_gwdepended on the old behaviour: in the second IPv6 round fwd's gena-facing endpoint is created withSand never gets gena's fingerprint, because theAgoes to the geno-facing stream viaL6. It now gets it withU6before gena starts the handshake.I validated the change by linking the real
rtpp_dtls_conn.c/rtpp_dtls.cagainst an OpenSSL DTLS client. Before the change, a handshake made beforeAcompletes andrtp_sendprotects with its keys. After it, the early ClientHello is ignored and the retransmit completes only onceAcarries the matching fingerprint; a mismatching fingerprint still fails as before. I could only do this on macOS, where rtpproxy itself doesn't build, sotests/dtls_gwwith the adjusted scenario has not been run locally.