mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-07-26 13:47:03 +02:00
Support more special chars in camera passwords (#4259)
* Support more special chars in camera passwords * End password test with double @ chars * Escape passwords in paths for go2rtc * Fixes for formatting
This commit is contained in:
parent
95343b6094
commit
40cb5102b0
@ -9,4 +9,4 @@ PLUS_API_HOST = "https://api.frigate.video"
|
|||||||
# Regex Consts
|
# Regex Consts
|
||||||
|
|
||||||
REGEX_CAMERA_NAME = "^[a-zA-Z0-9_-]+$"
|
REGEX_CAMERA_NAME = "^[a-zA-Z0-9_-]+$"
|
||||||
REGEX_CAMERA_USER_PASS = "[a-zA-Z0-9_-]+:[a-zA-Z0-9!*'();:@&=+$,?%#_-]+@"
|
REGEX_CAMERA_USER_PASS = ":\/\/[a-zA-Z0-9_-]+:[\S]+@"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
|
from frigate.util import escape_special_characters
|
||||||
|
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
|
|
||||||
@ -34,10 +35,12 @@ class RestreamApi:
|
|||||||
input.path.startswith("rtsp")
|
input.path.startswith("rtsp")
|
||||||
and not camera.restream.force_audio
|
and not camera.restream.force_audio
|
||||||
):
|
):
|
||||||
self.relays[cam_name] = input.path
|
self.relays[cam_name] = escape_special_characters(input.path)
|
||||||
else:
|
else:
|
||||||
# go2rtc only supports rtsp for direct relay, otherwise ffmpeg is used
|
# go2rtc only supports rtsp for direct relay, otherwise ffmpeg is used
|
||||||
self.relays[cam_name] = get_manual_go2rtc_stream(input.path)
|
self.relays[cam_name] = get_manual_go2rtc_stream(
|
||||||
|
escape_special_characters(input.path)
|
||||||
|
)
|
||||||
|
|
||||||
for name, path in self.relays.items():
|
for name, path in self.relays.items():
|
||||||
params = {"src": path, "name": name}
|
params = {"src": path, "name": name}
|
||||||
|
@ -8,7 +8,9 @@ from frigate.util import clean_camera_user_pass, escape_special_characters
|
|||||||
class TestUserPassCleanup(unittest.TestCase):
|
class TestUserPassCleanup(unittest.TestCase):
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.rtsp_with_pass = "rtsp://user:password@192.168.0.2:554/live"
|
self.rtsp_with_pass = "rtsp://user:password@192.168.0.2:554/live"
|
||||||
self.rtsp_with_special_pass = "rtsp://user:password#$@@192.168.0.2:554/live"
|
self.rtsp_with_special_pass = (
|
||||||
|
"rtsp://user:password`~!@#$%^&*()-_;',.<>:\"\{\}\[\]@@192.168.0.2:554/live"
|
||||||
|
)
|
||||||
self.rtsp_no_pass = "rtsp://192.168.0.3:554/live"
|
self.rtsp_no_pass = "rtsp://192.168.0.3:554/live"
|
||||||
|
|
||||||
def test_cleanup(self):
|
def test_cleanup(self):
|
||||||
@ -25,7 +27,10 @@ class TestUserPassCleanup(unittest.TestCase):
|
|||||||
def test_special_char_password(self):
|
def test_special_char_password(self):
|
||||||
"""Test that special characters in pw are escaped, but not others."""
|
"""Test that special characters in pw are escaped, but not others."""
|
||||||
escaped = escape_special_characters(self.rtsp_with_special_pass)
|
escaped = escape_special_characters(self.rtsp_with_special_pass)
|
||||||
assert escaped == "rtsp://user:password%23%24%40@192.168.0.2:554/live"
|
assert (
|
||||||
|
escaped
|
||||||
|
== "rtsp://user:password%60~%21%40%23%24%25%5E%26%2A%28%29-_%3B%27%2C.%3C%3E%3A%22%5C%7B%5C%7D%5C%5B%5C%5D%40@192.168.0.2:554/live"
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_special_char_password(self):
|
def test_no_special_char_password(self):
|
||||||
"""Test that no change is made to path with no special characters."""
|
"""Test that no change is made to path with no special characters."""
|
||||||
|
@ -635,13 +635,13 @@ def load_labels(path, encoding="utf-8"):
|
|||||||
def clean_camera_user_pass(line: str) -> str:
|
def clean_camera_user_pass(line: str) -> str:
|
||||||
"""Removes user and password from line."""
|
"""Removes user and password from line."""
|
||||||
# todo also remove http password like reolink
|
# todo also remove http password like reolink
|
||||||
return re.sub(REGEX_CAMERA_USER_PASS, "*:*@", line)
|
return re.sub(REGEX_CAMERA_USER_PASS, "://*:*@", line)
|
||||||
|
|
||||||
|
|
||||||
def escape_special_characters(path: str) -> str:
|
def escape_special_characters(path: str) -> str:
|
||||||
"""Cleans reserved characters to encodings for ffmpeg."""
|
"""Cleans reserved characters to encodings for ffmpeg."""
|
||||||
try:
|
try:
|
||||||
found = re.search(REGEX_CAMERA_USER_PASS, path).group(0)[:-1]
|
found = re.search(REGEX_CAMERA_USER_PASS, path).group(0)[3:-1]
|
||||||
pw = found[(found.index(":") + 1) :]
|
pw = found[(found.index(":") + 1) :]
|
||||||
return path.replace(pw, urllib.parse.quote_plus(pw))
|
return path.replace(pw, urllib.parse.quote_plus(pw))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
Loading…
Reference in New Issue
Block a user