@@ -24,6 +24,8 @@ import (
2424
2525 "github.com/pion/dtls/v2"
2626 "github.com/pion/dtls/v2/pkg/crypto/selfsign"
27+ "github.com/pion/dtls/v2/pkg/protocol/extension"
28+ "github.com/pion/dtls/v2/pkg/protocol/handshake"
2729 "github.com/pion/transport/v3/test"
2830)
2931
@@ -33,7 +35,11 @@ const (
3335 messageRetry = 200 * time .Millisecond
3436)
3537
36- var errServerTimeout = errors .New ("waiting on serverReady err: timeout" )
38+ var (
39+ errServerTimeout = errors .New ("waiting on serverReady err: timeout" )
40+ errHookCiphersFailed = errors .New ("hook failed to modify cipherlist" )
41+ errHookAPLNFailed = errors .New ("hook failed to modify APLN extension" )
42+ )
3743
3844func randomPort (t testing.TB ) int {
3945 t .Helper ()
@@ -569,6 +575,116 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), op
569575 comm .assert (t )
570576}
571577
578+ func testPionE2ESimpleClientHelloHook (t * testing.T , server , client func (* comm ), opts ... dtlsConfOpts ) {
579+ lim := test .TimeOut (time .Second * 30 )
580+ defer lim .Stop ()
581+
582+ report := test .CheckRoutines (t )
583+ defer report ()
584+
585+ t .Run ("ClientHello hook" , func (t * testing.T ) {
586+ ctx , cancel := context .WithTimeout (context .Background (), 2 * time .Second )
587+ defer cancel ()
588+
589+ cert , err := selfsign .GenerateSelfSignedWithDNS ("localhost" )
590+ if err != nil {
591+ t .Fatal (err )
592+ }
593+
594+ modifiedCipher := dtls .TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
595+ supportedList := []dtls.CipherSuiteID {
596+ dtls .TLS_ECDHE_ECDSA_WITH_AES_128_CCM ,
597+ modifiedCipher ,
598+ }
599+
600+ ccfg := & dtls.Config {
601+ Certificates : []tls.Certificate {cert },
602+ VerifyConnection : func (s * dtls.State ) error {
603+ if s .CipherSuiteID != modifiedCipher {
604+ return errHookCiphersFailed
605+ }
606+ return nil
607+ },
608+ CipherSuites : supportedList ,
609+ ClientHelloMessageHook : func (ch handshake.MessageClientHello ) handshake.Message {
610+ ch .CipherSuiteIDs = []uint16 {uint16 (modifiedCipher )}
611+ return & ch
612+ },
613+ InsecureSkipVerify : true ,
614+ }
615+
616+ scfg := & dtls.Config {
617+ Certificates : []tls.Certificate {cert },
618+ CipherSuites : supportedList ,
619+ InsecureSkipVerify : true ,
620+ }
621+
622+ for _ , o := range opts {
623+ o (ccfg )
624+ o (scfg )
625+ }
626+ serverPort := randomPort (t )
627+ comm := newComm (ctx , ccfg , scfg , serverPort , server , client )
628+ defer comm .cleanup (t )
629+ comm .assert (t )
630+ })
631+ }
632+
633+ func testPionE2ESimpleServerHelloHook (t * testing.T , server , client func (* comm ), opts ... dtlsConfOpts ) {
634+ lim := test .TimeOut (time .Second * 30 )
635+ defer lim .Stop ()
636+
637+ report := test .CheckRoutines (t )
638+ defer report ()
639+
640+ t .Run ("ServerHello hook" , func (t * testing.T ) {
641+ ctx , cancel := context .WithTimeout (context .Background (), 2 * time .Second )
642+ defer cancel ()
643+
644+ cert , err := selfsign .GenerateSelfSignedWithDNS ("localhost" )
645+ if err != nil {
646+ t .Fatal (err )
647+ }
648+
649+ supportedList := []dtls.CipherSuiteID {dtls .TLS_ECDHE_ECDSA_WITH_AES_128_CCM }
650+
651+ apln := "APLN"
652+
653+ ccfg := & dtls.Config {
654+ Certificates : []tls.Certificate {cert },
655+ VerifyConnection : func (s * dtls.State ) error {
656+ if s .NegotiatedProtocol != apln {
657+ return errHookAPLNFailed
658+ }
659+ return nil
660+ },
661+ CipherSuites : supportedList ,
662+ InsecureSkipVerify : true ,
663+ }
664+
665+ scfg := & dtls.Config {
666+ Certificates : []tls.Certificate {cert },
667+ CipherSuites : supportedList ,
668+ ServerHelloMessageHook : func (sh handshake.MessageServerHello ) handshake.Message {
669+ sh .Extensions = append (sh .Extensions , & extension.ALPN {
670+ ProtocolNameList : []string {apln },
671+ })
672+ return & sh
673+ },
674+ InsecureSkipVerify : true ,
675+ }
676+
677+ for _ , o := range opts {
678+ o (ccfg )
679+ o (scfg )
680+ }
681+ serverPort := randomPort (t )
682+ comm := newComm (ctx , ccfg , scfg , serverPort , server , client )
683+ defer comm .cleanup (t )
684+ comm .assert (t )
685+ })
686+ }
687+
572688func TestPionE2ESimple (t * testing.T ) {
573689 testPionE2ESimple (t , serverPion , clientPion )
574690}
@@ -624,3 +740,11 @@ func TestPionE2ESimpleECDSAClientCertCID(t *testing.T) {
624740func TestPionE2ESimpleRSAClientCertCID (t * testing.T ) {
625741 testPionE2ESimpleRSAClientCert (t , serverPion , clientPion , withConnectionIDGenerator (dtls .RandomCIDGenerator (8 )))
626742}
743+
744+ func TestPionE2ESimpleClientHelloHook (t * testing.T ) {
745+ testPionE2ESimpleClientHelloHook (t , serverPion , clientPion )
746+ }
747+
748+ func TestPionE2ESimpleServerHelloHook (t * testing.T ) {
749+ testPionE2ESimpleServerHelloHook (t , serverPion , clientPion )
750+ }
0 commit comments