From 40cb5102b085c1a1e4bec558f62b869f257e956b Mon Sep 17 00:00:00 2001 From: Nate Meyer Date: Sat, 5 Nov 2022 22:42:32 -0400 Subject: [PATCH] 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 --- frigate/const.py | 2 +- frigate/restream.py | 7 +++++-- frigate/test/test_camera_pw.py | 9 +++++++-- frigate/util.py | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/frigate/const.py b/frigate/const.py index 2418d48875..1cc14293eb 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -9,4 +9,4 @@ # Regex Consts 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]+@" diff --git a/frigate/restream.py b/frigate/restream.py index 3168bd9225..b06ae95e2e 100644 --- a/frigate/restream.py +++ b/frigate/restream.py @@ -3,6 +3,7 @@ import logging import requests +from frigate.util import escape_special_characters from frigate.config import FrigateConfig @@ -34,10 +35,12 @@ def add_cameras(self) -> None: input.path.startswith("rtsp") and not camera.restream.force_audio ): - self.relays[cam_name] = input.path + self.relays[cam_name] = escape_special_characters(input.path) else: # 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(): params = {"src": path, "name": name} diff --git a/frigate/test/test_camera_pw.py b/frigate/test/test_camera_pw.py index 37ce2fa869..dd72fcc7d7 100644 --- a/frigate/test/test_camera_pw.py +++ b/frigate/test/test_camera_pw.py @@ -8,7 +8,9 @@ class TestUserPassCleanup(unittest.TestCase): def setUp(self) -> None: 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" def test_cleanup(self): @@ -25,7 +27,10 @@ def test_no_cleanup(self): def test_special_char_password(self): """Test that special characters in pw are escaped, but not others.""" 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): """Test that no change is made to path with no special characters.""" diff --git a/frigate/util.py b/frigate/util.py index a9a30e56e4..7ce973a94f 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -635,13 +635,13 @@ def load_labels(path, encoding="utf-8"): def clean_camera_user_pass(line: str) -> str: """Removes user and password from line.""" # 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: """Cleans reserved characters to encodings for ffmpeg.""" 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) :] return path.replace(pw, urllib.parse.quote_plus(pw)) except AttributeError: