Fix input and output validation with tee outputs

This commit is contained in:
Ingo Oppermann 2022-07-07 15:45:24 +02:00
parent 2ecea4b3e2
commit 337e0040c2
No known key found for this signature in database
GPG key ID: 2AB32426E9DD229E
2 changed files with 110 additions and 28 deletions

View file

@ -585,11 +585,6 @@ func (r *restream) validateConfig(config *app.Config) (bool, error) {
if err != nil { if err != nil {
return false, fmt.Errorf("the address for input '#%s:%s' (%s) is invalid: %w", config.ID, io.ID, io.Address, err) return false, fmt.Errorf("the address for input '#%s:%s' (%s) is invalid: %w", config.ID, io.ID, io.Address, err)
} }
ok := r.ffmpeg.ValidateInputAddress(io.Address)
if !ok {
return false, fmt.Errorf("the address for input '#%s:%s' is not allowed (%s)", config.ID, io.ID, io.Address)
}
} }
if len(config.Output) == 0 { if len(config.Output) == 0 {
@ -628,11 +623,6 @@ func (r *restream) validateConfig(config *app.Config) (bool, error) {
if isFile { if isFile {
hasFiles = true hasFiles = true
} }
ok := r.ffmpeg.ValidateOutputAddress(io.Address)
if !ok {
return false, fmt.Errorf("the address for output '#%s:%s' is not allowed (%s)", config.ID, io.ID, io.Address)
}
} }
return hasFiles, nil return hasFiles, nil
@ -645,6 +635,10 @@ func (r *restream) validateInputAddress(address, basedir string) (string, error)
} }
} }
if !r.ffmpeg.ValidateInputAddress(address) {
return address, fmt.Errorf("address is not allowed")
}
return address, nil return address, nil
} }
@ -683,6 +677,11 @@ func (r *restream) validateOutputAddress(address, basedir string) (string, bool,
if err := url.Validate(address); err != nil { if err := url.Validate(address); err != nil {
return address, false, err return address, false, err
} }
if !r.ffmpeg.ValidateOutputAddress(address) {
return address, false, fmt.Errorf("address is not allowed")
}
return address, false, nil return address, false, nil
} }
@ -696,6 +695,10 @@ func (r *restream) validateOutputAddress(address, basedir string) (string, bool,
} }
if strings.HasPrefix(address, "/dev/") { if strings.HasPrefix(address, "/dev/") {
if !r.ffmpeg.ValidateOutputAddress("file:" + address) {
return address, false, fmt.Errorf("address is not allowed")
}
return "file:" + address, false, nil return "file:" + address, false, nil
} }
@ -703,6 +706,10 @@ func (r *restream) validateOutputAddress(address, basedir string) (string, bool,
return address, false, fmt.Errorf("%s is not inside of %s", address, basedir) return address, false, fmt.Errorf("%s is not inside of %s", address, basedir)
} }
if !r.ffmpeg.ValidateOutputAddress("file:" + address) {
return address, false, fmt.Errorf("address is not allowed")
}
return "file:" + address, true, nil return "file:" + address, true, nil
} }

View file

@ -13,15 +13,17 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func getDummyRestreamer(portrange net.Portranger) (Restreamer, error) { func getDummyRestreamer(portrange net.Portranger, validatorIn, validatorOut ffmpeg.Validator) (Restreamer, error) {
binary, err := testhelper.BuildBinary("ffmpeg", "../internal/testhelper") binary, err := testhelper.BuildBinary("ffmpeg", "../internal/testhelper")
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to build helper program: %w", err) return nil, fmt.Errorf("failed to build helper program: %w", err)
} }
ffmpeg, err := ffmpeg.New(ffmpeg.Config{ ffmpeg, err := ffmpeg.New(ffmpeg.Config{
Binary: binary, Binary: binary,
Portrange: portrange, Portrange: portrange,
ValidatorInput: validatorIn,
ValidatorOutput: validatorOut,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -75,7 +77,7 @@ func getDummyProcess() *app.Config {
} }
func TestAddProcess(t *testing.T) { func TestAddProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -95,7 +97,7 @@ func TestAddProcess(t *testing.T) {
} }
func TestAutostartProcess(t *testing.T) { func TestAutostartProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -110,7 +112,7 @@ func TestAutostartProcess(t *testing.T) {
} }
func TestAddInvalidProcess(t *testing.T) { func TestAddInvalidProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
// Invalid process ID // Invalid process ID
@ -178,7 +180,7 @@ func TestAddInvalidProcess(t *testing.T) {
} }
func TestRemoveProcess(t *testing.T) { func TestRemoveProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -194,7 +196,7 @@ func TestRemoveProcess(t *testing.T) {
} }
func TestGetProcess(t *testing.T) { func TestGetProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -210,7 +212,7 @@ func TestGetProcess(t *testing.T) {
} }
func TestStartProcess(t *testing.T) { func TestStartProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -236,7 +238,7 @@ func TestStartProcess(t *testing.T) {
} }
func TestStopProcess(t *testing.T) { func TestStopProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -261,7 +263,7 @@ func TestStopProcess(t *testing.T) {
} }
func TestRestartProcess(t *testing.T) { func TestRestartProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -286,7 +288,7 @@ func TestRestartProcess(t *testing.T) {
} }
func TestReloadProcess(t *testing.T) { func TestReloadProcess(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -317,7 +319,7 @@ func TestReloadProcess(t *testing.T) {
} }
func TestProcessData(t *testing.T) { func TestProcessData(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -338,7 +340,7 @@ func TestProcessData(t *testing.T) {
} }
func TestLog(t *testing.T) { func TestLog(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -371,7 +373,7 @@ func TestLog(t *testing.T) {
} }
func TestPlayoutNoRange(t *testing.T) { func TestPlayoutNoRange(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -394,7 +396,7 @@ func TestPlayoutRange(t *testing.T) {
portrange, err := net.NewPortrange(3000, 3001) portrange, err := net.NewPortrange(3000, 3001)
require.NoError(t, err) require.NoError(t, err)
rs, err := getDummyRestreamer(portrange) rs, err := getDummyRestreamer(portrange, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process := getDummyProcess() process := getDummyProcess()
@ -415,7 +417,7 @@ func TestPlayoutRange(t *testing.T) {
} }
func TestAddressReference(t *testing.T) { func TestAddressReference(t *testing.T) {
rs, err := getDummyRestreamer(nil) rs, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
process1 := getDummyProcess() process1 := getDummyProcess()
@ -446,8 +448,81 @@ func TestAddressReference(t *testing.T) {
require.Equal(t, nil, err, "should resolve reference") require.Equal(t, nil, err, "should resolve reference")
} }
func TestConfigValidation(t *testing.T) {
rsi, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err)
rs := rsi.(*restream)
config := getDummyProcess()
_, err = rs.validateConfig(config)
require.NoError(t, err)
config.Input = []app.ConfigIO{}
_, err = rs.validateConfig(config)
require.Error(t, err)
config = getDummyProcess()
config.Input[0].ID = ""
_, err = rs.validateConfig(config)
require.Error(t, err)
config = getDummyProcess()
config.Input[0].Address = ""
_, err = rs.validateConfig(config)
require.Error(t, err)
config = getDummyProcess()
config.Output = []app.ConfigIO{}
_, err = rs.validateConfig(config)
require.Error(t, err)
config = getDummyProcess()
config.Output[0].ID = ""
_, err = rs.validateConfig(config)
require.Error(t, err)
config = getDummyProcess()
config.Output[0].Address = ""
_, err = rs.validateConfig(config)
require.Error(t, err)
}
func TestConfigValidationFFmpeg(t *testing.T) {
valIn, err := ffmpeg.NewValidator([]string{"^https?://"}, nil)
require.NoError(t, err)
valOut, err := ffmpeg.NewValidator([]string{"^https?://", "^rtmp://"}, nil)
require.NoError(t, err)
rsi, err := getDummyRestreamer(nil, valIn, valOut)
require.NoError(t, err)
rs := rsi.(*restream)
config := getDummyProcess()
_, err = rs.validateConfig(config)
require.Error(t, err)
config.Input[0].Address = "http://stream.example.com/master.m3u8"
config.Output[0].Address = "http://stream.example.com/master2.m3u8"
_, err = rs.validateConfig(config)
require.NoError(t, err)
config.Output[0].Address = "[f=flv]http://stream.example.com/master2.m3u8"
_, err = rs.validateConfig(config)
require.NoError(t, err)
config.Output[0].Address = "[f=hls]http://stream.example.com/master2.m3u8|[f=flv]rtmp://stream.example.com/stream"
_, err = rs.validateConfig(config)
require.NoError(t, err)
}
func TestOutputAddressValidation(t *testing.T) { func TestOutputAddressValidation(t *testing.T) {
rsi, err := getDummyRestreamer(nil) rsi, err := getDummyRestreamer(nil, nil, nil)
require.NoError(t, err) require.NoError(t, err)
rs := rsi.(*restream) rs := rsi.(*restream)