Fix a regression in which some MariaDB/MySQL passwords were not escaped correctly (#1017).

This commit is contained in:
Dan Helfman
2025-03-06 10:32:38 -08:00
parent 5a8f27d75c
commit 1d486d024b
3 changed files with 23 additions and 4 deletions
+1
View File
@@ -3,6 +3,7 @@
incident UI. See the documentation for more information:
https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#pagerduty-hook
* #936: Clarify Zabbix monitoring hook documentation about creating items.
* #1017: Fix a regression in which some MariaDB/MySQL passwords were not escaped correctly.
1.9.13
* #975: Add a "compression" option to the PostgreSQL database hook.
+3 -1
View File
@@ -65,10 +65,12 @@ def make_defaults_file_options(username=None, password=None, defaults_extra_file
Do not use the returned value for multiple different command invocations. That will not work
because each pipe is "used up" once read.
'''
escaped_password = None if password is None else password.replace('\\', '\\\\')
values = '\n'.join(
(
(f'user={username}' if username is not None else ''),
(f"password='{password}'" if password is not None else ''),
(f'password="{escaped_password}"' if escaped_password is not None else ''),
)
).strip()
+19 -3
View File
@@ -36,7 +36,7 @@ def test_make_defaults_file_option_with_username_and_password_writes_them_to_fil
flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
flexmock(module.os).should_receive('write').with_args(
write_descriptor, b"[client]\nuser=root\npassword='trustsome1'"
write_descriptor, b'[client]\nuser=root\npassword="trustsome1"'
).once()
flexmock(module.os).should_receive('close')
flexmock(module.os).should_receive('set_inheritable')
@@ -46,6 +46,22 @@ def test_make_defaults_file_option_with_username_and_password_writes_them_to_fil
)
def test_make_defaults_file_option_escapes_password_containing_backslash():
read_descriptor = 99
write_descriptor = flexmock()
flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
flexmock(module.os).should_receive('write').with_args(
write_descriptor, b'[client]\nuser=root\n' + br'password="trust\\nsome1"'
).once()
flexmock(module.os).should_receive('close')
flexmock(module.os).should_receive('set_inheritable')
assert module.make_defaults_file_options(username='root', password=r'trust\nsome1') == (
'--defaults-extra-file=/dev/fd/99',
)
def test_make_defaults_file_pipe_with_only_username_writes_it_to_file_descriptor():
read_descriptor = 99
write_descriptor = flexmock()
@@ -68,7 +84,7 @@ def test_make_defaults_file_pipe_with_only_password_writes_it_to_file_descriptor
flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
flexmock(module.os).should_receive('write').with_args(
write_descriptor, b"[client]\npassword='trustsome1'"
write_descriptor, b'[client]\npassword="trustsome1"'
).once()
flexmock(module.os).should_receive('close')
flexmock(module.os).should_receive('set_inheritable')
@@ -84,7 +100,7 @@ def test_make_defaults_file_option_with_defaults_extra_filename_includes_it_in_f
flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
flexmock(module.os).should_receive('write').with_args(
write_descriptor, b"!include extra.cnf\n[client]\nuser=root\npassword='trustsome1'"
write_descriptor, b'!include extra.cnf\n[client]\nuser=root\npassword="trustsome1"'
).once()
flexmock(module.os).should_receive('close')
flexmock(module.os).should_receive('set_inheritable')