From 818307ff5490c712f4235ca7a6cd250b5c365aad Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Thu, 31 Dec 2020 21:50:18 +0100 Subject: [PATCH] forbid usage of publishUser, publishPass, publishIps when source is not 'record' --- README.md | 4 +-- internal/conf/pathconf.go | 57 ++++++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 23773d15..d35f3047 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ paths: readPass: userpass ``` -If storing plain credentials in the configuration file is a security problem, username and passwords can be stored as sha256-hashed values; a value must be converted into sha256: +If storing plain credentials in the configuration file is a security problem, username and passwords can be stored as sha256-hashed strings; a string must be hashed with sha256 and encoded with base64: ``` echo -n "userpass" | openssl dgst -binary -sha256 | openssl base64 @@ -211,7 +211,7 @@ paths: readPass: sha256:BdSWkrdV+ZxFBLUQQY7+7uv9RmiSVA8nrPmjGjJtZQQ= ``` -**WARNING**: enable encryption or use a VPN to ensure that no one is intercepting and reading the credentials. +**WARNING**: enable encryption or use a VPN to ensure that no one is intercepting the credentials. ### RTSP proxy mode diff --git a/internal/conf/pathconf.go b/internal/conf/pathconf.go index 8202ce99..c36b7ece 100644 --- a/internal/conf/pathconf.go +++ b/internal/conf/pathconf.go @@ -164,28 +164,47 @@ func (pconf *PathConf) fillAndCheck(name string) error { } } + if (pconf.PublishUser != "" && pconf.PublishPass == "") || (pconf.PublishUser == "" && pconf.PublishPass != "") { + return fmt.Errorf("read username and password must be both filled") + } if pconf.PublishUser != "" { + if pconf.Source != "record" { + return fmt.Errorf("'publishUser' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source") + } + if !strings.HasPrefix(pconf.PublishUser, "sha256:") && !reUserPass.MatchString(pconf.PublishUser) { return fmt.Errorf("publish username contains unsupported characters (supported are %s)", userPassSupportedChars) } } if pconf.PublishPass != "" { + if pconf.Source != "record" { + return fmt.Errorf("'publishPass' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source") + } + if !strings.HasPrefix(pconf.PublishPass, "sha256:") && !reUserPass.MatchString(pconf.PublishPass) { return fmt.Errorf("publish password contains unsupported characters (supported are %s)", userPassSupportedChars) } } - if len(pconf.PublishIps) > 0 { - var err error - pconf.PublishIpsParsed, err = parseIPCidrList(pconf.PublishIps) - if err != nil { - return err - } - } else { - // the configuration file doesn't use nil dicts - avoid test fails by using nil + if len(pconf.PublishIps) == 0 { pconf.PublishIps = nil } + var err error + pconf.PublishIpsParsed, err = func() ([]interface{}, error) { + if len(pconf.PublishIps) == 0 { + return nil, nil + } + + if pconf.Source != "record" { + return nil, fmt.Errorf("'publishIps' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source") + } + + return parseIPCidrList(pconf.PublishIps) + }() + if err != nil { + return err + } - if pconf.ReadUser != "" && pconf.ReadPass == "" || pconf.ReadUser == "" && pconf.ReadPass != "" { + if (pconf.ReadUser != "" && pconf.ReadPass == "") || (pconf.ReadUser == "" && pconf.ReadPass != "") { return fmt.Errorf("read username and password must be both filled") } if pconf.ReadUser != "" { @@ -198,26 +217,22 @@ func (pconf *PathConf) fillAndCheck(name string) error { return fmt.Errorf("read password contains unsupported characters (supported are %s)", userPassSupportedChars) } } - if pconf.ReadUser != "" && pconf.ReadPass == "" || pconf.ReadUser == "" && pconf.ReadPass != "" { - return fmt.Errorf("read username and password must be both filled") - } - if len(pconf.ReadIps) > 0 { - var err error - pconf.ReadIpsParsed, err = parseIPCidrList(pconf.ReadIps) - if err != nil { - return err - } - } else { - // the configuration file doesn't use nil dicts - avoid test fails by using nil + if len(pconf.ReadIps) == 0 { pconf.ReadIps = nil } + pconf.ReadIpsParsed, err = func() ([]interface{}, error) { + return parseIPCidrList(pconf.ReadIps) + }() + if err != nil { + return err + } if pconf.RunOnInit != "" && pconf.Regexp != nil { return fmt.Errorf("a path with a regular expression does not support option 'runOnInit'; use another path") } if pconf.RunOnPublish != "" && pconf.Source != "record" { - return fmt.Errorf("'runOnPublish' is useless when source is not 'record', since the stream is not provided by a publisher, but by another source") + return fmt.Errorf("'runOnPublish' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source") } if pconf.RunOnDemandStartTimeout == 0 {