Skip to content

Commit b9ae943

Browse files
authored
TEL-792: Tolerate, but ignore RFC 4568 session parameters (#73)
1 parent 40d3338 commit b9ae943

2 files changed

Lines changed: 54 additions & 0 deletions

File tree

sdp/offer.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ func parseSRTPProfile(val string) (*srtp.Profile, error) {
586586
return nil, nil // ignore
587587
}
588588

589+
if strings.ContainsAny(skey, " \t") {
590+
return nil, nil // RFC 4568 session-parameter list not supported; ignore
591+
}
592+
589593
// Split by '|' per RFC 4568 6.1
590594
parts := strings.Split(skey, "|")
591595
keyMaterial := parts[0] // First part is always the base64-encoded key+salt

sdp/offer_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,56 @@ a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:pMIPxjzYIG5TQuIWfkjTnaACVrzohhFfOGhSMg
612612
require.Equal(t, 4, len(profile.MKI), "MKI length should be 4 bytes")
613613
}
614614

615+
// TestParseOfferSRTPSessionParams verifies that crypto lines carrying RFC 4568
616+
// session parameters (which we don't support, e.g. UNENCRYPTED_SRTCP) are
617+
// skipped rather than misparsed, while other offered ciphers are still
618+
// accepted.
619+
func TestParseOfferSRTPSessionParams(t *testing.T) {
620+
g := media.GlobalCodecs()
621+
622+
const header = `v=0
623+
o=Test 1 1 IN IP4 127.0.0.1
624+
s=Stream1
625+
t=0 0
626+
m=audio 5000 RTP/SAVP 0 101
627+
c=IN IP4 127.0.0.1
628+
a=rtpmap:0 PCMU/8000
629+
a=rtpmap:101 telephone-event/8000
630+
a=sendrecv
631+
a=ptime:20
632+
`
633+
634+
t.Run("AcceptsOther", func(t *testing.T) {
635+
sdpData := header +
636+
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:pMIPxjzYIG5TQuIWfkjTnaACVrzohhFfOGhSMgV1|2^48 UNENCRYPTED_SRTCP \n" +
637+
"a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:ZKkTQfuCsliegVZtFSya3Z6oEVUtSwjGCfHlbrMf \n"
638+
639+
offer, err := ParseOfferWith(g, []byte(sdpData))
640+
require.NoError(t, err)
641+
require.Len(t, offer.CryptoProfiles, 1, "only the plain crypto line should be accepted")
642+
require.Equal(t, 2, offer.CryptoProfiles[0].Index)
643+
require.Equal(t, srtp.ProtectionProfile("AES_CM_128_HMAC_SHA1_32"), offer.CryptoProfiles[0].Profile)
644+
645+
// The surviving cipher is usable for a required-encryption answer.
646+
_, conf, err := offer.Answer(netip.MustParseAddr("127.0.0.1"), 5001, EncryptionRequire)
647+
require.NoError(t, err)
648+
require.NotNil(t, conf.Crypto)
649+
})
650+
651+
t.Run("RejectAll", func(t *testing.T) {
652+
sdpData := header +
653+
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:pMIPxjzYIG5TQuIWfkjTnaACVrzohhFfOGhSMgV1|2^48 UNENCRYPTED_SRTCP \n" +
654+
"a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:ZKkTQfuCsliegVZtFSya3Z6oEVUtSwjGCfHlbrMf KDR=1 \n"
655+
656+
offer, err := ParseOfferWith(g, []byte(sdpData))
657+
require.NoError(t, err)
658+
require.Empty(t, offer.CryptoProfiles, "no cipher should survive session-param filtering")
659+
660+
_, _, err = offer.Answer(netip.MustParseAddr("127.0.0.1"), 5001, EncryptionRequire)
661+
require.Error(t, err)
662+
})
663+
}
664+
615665
// TestSelectCryptoSuiteTag ensures that when selecting a crypto suite from an offer/answer pair,
616666
// the answer uses the same crypto suite tag as the offer, per RFC 4568 section 5.1.2 and 5.1.3.
617667
func TestSelectCryptoSuiteTag(t *testing.T) {

0 commit comments

Comments
 (0)