client: prevent downgrading from RTSPS to RTSP during redirect (#816)

This commit is contained in:
Alessandro Ros
2025-06-30 16:03:05 +02:00
committed by GitHub
parent 6cf27aac05
commit bf3ce11479
3 changed files with 93 additions and 20 deletions

View File

@@ -1256,6 +1256,10 @@ func (c *Client) doDescribe(u *base.URL) (*description.Session, *base.Response,
return nil, nil, err
}
if c.connURL.Scheme == "rtsps" && ru.Scheme != "rtsps" {
return nil, nil, fmt.Errorf("connection cannot be downgraded from RTSPS to RTSP")
}
if u.User != nil {
ru.User = u.User
}

View File

@@ -252,9 +252,8 @@ func TestClientPlay(t *testing.T) {
packetRecv := make(chan struct{})
listenIP := multicastCapableIP(t)
l, err := net.Listen("tcp", listenIP+":8554")
require.NoError(t, err)
defer l.Close()
var l net.Listener
var err error
var scheme string
if transport == "tls" {
@@ -264,9 +263,15 @@ func TestClientPlay(t *testing.T) {
cert, err = tls.X509KeyPair(serverCert, serverKey)
require.NoError(t, err)
l = tls.NewListener(l, &tls.Config{Certificates: []tls.Certificate{cert}})
l, err = tls.Listen("tcp", listenIP+":8554", &tls.Config{Certificates: []tls.Certificate{cert}})
require.NoError(t, err)
defer l.Close()
} else {
scheme = "rtsp"
l, err = net.Listen("tcp", listenIP+":8554")
require.NoError(t, err)
defer l.Close()
}
serverDone := make(chan struct{})
@@ -1650,12 +1655,11 @@ func TestClientPlayDifferentInterleavedIDs(t *testing.T) {
}
func TestClientPlayRedirect(t *testing.T) {
for _, withCredentials := range []bool{false, true} {
runName := "WithoutCredentials"
if withCredentials {
runName = "WithCredentials"
}
t.Run(runName, func(t *testing.T) {
for _, ca := range []string{
"without credentials",
"with credentials",
} {
t.Run(ca, func(t *testing.T) {
l, err := net.Listen("tcp", "localhost:8554")
require.NoError(t, err)
defer l.Close()
@@ -1728,7 +1732,7 @@ func TestClientPlayRedirect(t *testing.T) {
require.NoError(t, err2)
require.Equal(t, base.Describe, req.Method)
if withCredentials {
if ca == "with credentials" {
if _, exists := req.Header["Authorization"]; !exists {
authRealm := "example@localhost"
authNonce := "exampleNonce"
@@ -1823,7 +1827,7 @@ func TestClientPlayRedirect(t *testing.T) {
c := Client{}
ru := "rtsp://localhost:8554/path1"
if withCredentials {
if ca == "with credentials" {
ru = "rtsp://testusr:testpwd@localhost:8554/path1"
}
err = readAll(&c, ru,
@@ -1838,6 +1842,61 @@ func TestClientPlayRedirect(t *testing.T) {
}
}
func TestClientPlayRedirectPreventDecrypt(t *testing.T) {
cert, err := tls.X509KeyPair(serverCert, serverKey)
require.NoError(t, err)
l, err := tls.Listen("tcp", "localhost:8554", &tls.Config{Certificates: []tls.Certificate{cert}})
require.NoError(t, err)
defer l.Close()
serverDone := make(chan struct{})
defer func() { <-serverDone }()
go func() {
defer close(serverDone)
var nconn net.Conn
nconn, err = l.Accept()
require.NoError(t, err)
defer nconn.Close()
conn := conn.NewConn(nconn)
req, err2 := conn.ReadRequest()
require.NoError(t, err2)
require.Equal(t, base.Options, req.Method)
err2 = conn.WriteResponse(&base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
string(base.Describe),
string(base.Setup),
string(base.Play),
}, ", ")},
},
})
require.NoError(t, err2)
req, err2 = conn.ReadRequest()
require.NoError(t, err2)
require.Equal(t, base.Describe, req.Method)
err2 = conn.WriteResponse(&base.Response{
StatusCode: base.StatusMovedPermanently,
Header: base.Header{
"Location": base.HeaderValue{"rtsp://localhost:8554/test"},
},
})
require.NoError(t, err2)
}()
c := Client{TLSConfig: &tls.Config{InsecureSkipVerify: true}}
err = readAll(&c, "rtsps://localhost:8554/test", nil)
require.EqualError(t, err, "connection cannot be downgraded from RTSPS to RTSP")
defer c.Close()
}
func TestClientPlayPausePlay(t *testing.T) {
writeFrames := func(inTH *headers.Transport, conn *conn.Conn) (chan struct{}, chan struct{}) {
writerTerminate := make(chan struct{})

View File

@@ -132,9 +132,8 @@ func TestClientRecord(t *testing.T) {
"tls",
} {
t.Run(transport, func(t *testing.T) {
l, err := net.Listen("tcp", "localhost:8554")
require.NoError(t, err)
defer l.Close()
var l net.Listener
var err error
var scheme string
if transport == "tls" {
@@ -144,9 +143,15 @@ func TestClientRecord(t *testing.T) {
cert, err = tls.X509KeyPair(serverCert, serverKey)
require.NoError(t, err)
l = tls.NewListener(l, &tls.Config{Certificates: []tls.Certificate{cert}})
l, err = tls.Listen("tcp", "localhost:8554", &tls.Config{Certificates: []tls.Certificate{cert}})
require.NoError(t, err)
defer l.Close()
} else {
scheme = "rtsp"
l, err = net.Listen("tcp", "localhost:8554")
require.NoError(t, err)
defer l.Close()
}
serverDone := make(chan struct{})
@@ -380,9 +385,8 @@ func TestClientRecordSocketError(t *testing.T) {
"tls",
} {
t.Run(transport, func(t *testing.T) {
l, err := net.Listen("tcp", "localhost:8554")
require.NoError(t, err)
defer l.Close()
var l net.Listener
var err error
var scheme string
if transport == "tls" {
@@ -392,9 +396,15 @@ func TestClientRecordSocketError(t *testing.T) {
cert, err = tls.X509KeyPair(serverCert, serverKey)
require.NoError(t, err)
l = tls.NewListener(l, &tls.Config{Certificates: []tls.Certificate{cert}})
l, err = tls.Listen("tcp", "localhost:8554", &tls.Config{Certificates: []tls.Certificate{cert}})
require.NoError(t, err)
defer l.Close()
} else {
scheme = "rtsp"
l, err = net.Listen("tcp", "localhost:8554")
require.NoError(t, err)
defer l.Close()
}
serverDone := make(chan struct{})