0

Fix rtmp secret validation to allow / (#1069) (#1070)

* Fix rtmp secret validation to allow `/` (#1069)

* add negative test cases for stuff before /live/

* simplify since Url.Path is already stripping the host

This means that we can simplify the code and make it much clearer.
Removes the tests that checked for the host and stuff between the host and /live/.
This commit is contained in:
Jannik 2021-06-05 05:09:43 +02:00 committed by GitHub
parent dc70642892
commit fae2c58259
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 4 deletions

View File

@ -5,7 +5,6 @@ import (
"io"
"net"
"os"
"strings"
"syscall"
"time"
@ -78,9 +77,7 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
return
}
streamingKeyComponents := strings.Split(c.URL.Path, "/")
streamingKey := streamingKeyComponents[len(streamingKeyComponents)-1]
if streamingKey != data.GetStreamKey() {
if !secretMatch(data.GetStreamKey(), c.URL.Path) {
log.Errorln("invalid streaming key; rejecting incoming stream")
nc.Close()
return

View File

@ -9,6 +9,7 @@ import (
"github.com/nareix/joy5/format/flv/flvio"
"github.com/owncast/owncast/models"
log "github.com/sirupsen/logrus"
)
const unknownString = "Unknown"
@ -76,3 +77,15 @@ func getVideoCodec(codec interface{}) string {
return unknownString
}
func secretMatch(configStreamKey string, path string) bool {
prefix := "/live/"
if !strings.HasPrefix(path, prefix) {
log.Debug("RTMP path does not start with " + prefix)
return false // We need the path to begin with $prefix
}
streamingKey := path[len(prefix):] // Remove $prefix
return streamingKey == configStreamKey
}

35
core/rtmp/utils_test.go Normal file
View File

@ -0,0 +1,35 @@
package rtmp
import "testing"
func Test_secretMatch(t *testing.T) {
tests := []struct {
name string
streamKey string
path string
want bool
}{
{"positive", "abc", "/live/abc", true},
{"negative", "abc", "/live/def", false},
{"positive with numbers", "abc123", "/live/abc123", true},
{"negative with numbers", "abc123", "/live/def456", false},
{"positive with url chars", "one/two/three", "/live/one/two/three", true},
{"negative with url chars", "one/two/three", "/live/four/five/six", false},
{"check the entire secret", "three", "/live/one/two/three", false},
{"with /live/ in secret", "one/live/three", "/live/one/live/three", true},
{"bad path", "anything", "nonsense", false},
{"missing secret", "abc", "/live/", false},
{"missing secret and missing last slash", "abc", "/live", false},
{"streamkey before /live/", "streamkey", "/streamkey/live", false},
{"missing /live/", "anything", "/something/else", false},
{"stuff before and after /live/", "after", "/before/live/after", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := secretMatch(tt.streamKey, tt.path); got != tt.want {
t.Errorf("secretMatch() = %v, want %v", got, tt.want)
}
})
}
}