backup: fix handling already encoded passphrase
When passphrase is retrieved from VM, it is already encoded. Do not try to encode it again. QubesOS/qubes-issues#2931
This commit is contained in:
parent
cdbe1d14b3
commit
1556814f59
@ -1146,7 +1146,6 @@ class QubesAdminAPI(qubes.api.AbstractQubesAPI):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise qubes.exc.QubesException(
|
raise qubes.exc.QubesException(
|
||||||
'Invalid backup profile - invalid passphrase_vm')
|
'Invalid backup profile - invalid passphrase_vm')
|
||||||
# TODO .decode()?
|
|
||||||
passphrase, _ = yield from passphrase_vm.run_service_for_stdio(
|
passphrase, _ = yield from passphrase_vm.run_service_for_stdio(
|
||||||
'qubes.BackupPassphrase+' + self.arg)
|
'qubes.BackupPassphrase+' + self.arg)
|
||||||
else:
|
else:
|
||||||
|
@ -200,6 +200,7 @@ def launch_scrypt(action, input_name, output_name, passphrase):
|
|||||||
:param input_name: input path or '-' for stdin
|
:param input_name: input path or '-' for stdin
|
||||||
:param output_name: output path or '-' for stdout
|
:param output_name: output path or '-' for stdout
|
||||||
:param passphrase: passphrase
|
:param passphrase: passphrase
|
||||||
|
:type passphrase: bytes
|
||||||
:return: subprocess.Popen object
|
:return: subprocess.Popen object
|
||||||
'''
|
'''
|
||||||
command_line = ['scrypt', action, input_name, output_name]
|
command_line = ['scrypt', action, input_name, output_name]
|
||||||
@ -217,7 +218,7 @@ def launch_scrypt(action, input_name, output_name, passphrase):
|
|||||||
if actual_prompt != prompt:
|
if actual_prompt != prompt:
|
||||||
raise qubes.exc.QubesException(
|
raise qubes.exc.QubesException(
|
||||||
'Unexpected prompt from scrypt: {}'.format(actual_prompt))
|
'Unexpected prompt from scrypt: {}'.format(actual_prompt))
|
||||||
pty.write(passphrase.encode('utf-8') + b'\n')
|
pty.write(passphrase + b'\n')
|
||||||
pty.flush()
|
pty.flush()
|
||||||
# save it here, so garbage collector would not close it (which would kill
|
# save it here, so garbage collector would not close it (which would kill
|
||||||
# the child)
|
# the child)
|
||||||
@ -492,8 +493,8 @@ class Backup(object):
|
|||||||
backup_header.save(header_file_path)
|
backup_header.save(header_file_path)
|
||||||
# Start encrypt, scrypt will also handle integrity
|
# Start encrypt, scrypt will also handle integrity
|
||||||
# protection
|
# protection
|
||||||
scrypt_passphrase = u'{filename}!{passphrase}'.format(
|
scrypt_passphrase = '{filename}!'.format(
|
||||||
filename=HEADER_FILENAME, passphrase=self.passphrase)
|
filename=HEADER_FILENAME).encode() + self.passphrase
|
||||||
scrypt = yield from launch_scrypt(
|
scrypt = yield from launch_scrypt(
|
||||||
'enc', header_file_path, header_file_path + '.hmac',
|
'enc', header_file_path, header_file_path + '.hmac',
|
||||||
scrypt_passphrase)
|
scrypt_passphrase)
|
||||||
@ -545,11 +546,10 @@ class Backup(object):
|
|||||||
# Start encrypt, scrypt will also handle integrity
|
# Start encrypt, scrypt will also handle integrity
|
||||||
# protection
|
# protection
|
||||||
scrypt_passphrase = \
|
scrypt_passphrase = \
|
||||||
u'{backup_id}!{filename}!{passphrase}'.format(
|
'{backup_id}!{filename}!'.format(
|
||||||
backup_id=self.backup_id,
|
backup_id=self.backup_id,
|
||||||
filename=os.path.relpath(chunkfile[:-4],
|
filename=os.path.relpath(chunkfile[:-4],
|
||||||
self.tmpdir),
|
self.tmpdir)).encode() + self.passphrase
|
||||||
passphrase=self.passphrase)
|
|
||||||
try:
|
try:
|
||||||
scrypt = yield from launch_scrypt(
|
scrypt = yield from launch_scrypt(
|
||||||
"enc", "-", chunkfile, scrypt_passphrase)
|
"enc", "-", chunkfile, scrypt_passphrase)
|
||||||
@ -691,6 +691,8 @@ class Backup(object):
|
|||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
if self.passphrase is None:
|
if self.passphrase is None:
|
||||||
raise qubes.exc.QubesException("No passphrase set")
|
raise qubes.exc.QubesException("No passphrase set")
|
||||||
|
if not isinstance(self.passphrase, bytes):
|
||||||
|
self.passphrase = self.passphrase.encode('utf-8')
|
||||||
qubes_xml = self.app.store
|
qubes_xml = self.app.store
|
||||||
self.tmpdir = tempfile.mkdtemp()
|
self.tmpdir = tempfile.mkdtemp()
|
||||||
shutil.copy(qubes_xml, os.path.join(self.tmpdir, 'qubes.xml'))
|
shutil.copy(qubes_xml, os.path.join(self.tmpdir, 'qubes.xml'))
|
||||||
|
@ -1930,7 +1930,7 @@ class TC_00_VMs(AdminAPITestCase):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def service_passphrase(*args, **kwargs):
|
def service_passphrase(*args, **kwargs):
|
||||||
return ('pass-from-vm', None)
|
return (b'pass-from-vm', None)
|
||||||
|
|
||||||
mock_backup.return_value.backup_do.side_effect = self.dummy_coro
|
mock_backup.return_value.backup_do.side_effect = self.dummy_coro
|
||||||
self.vm.run_service_for_stdio = unittest.mock.Mock(
|
self.vm.run_service_for_stdio = unittest.mock.Mock(
|
||||||
@ -1950,7 +1950,7 @@ class TC_00_VMs(AdminAPITestCase):
|
|||||||
target_vm=self.vm,
|
target_vm=self.vm,
|
||||||
target_dir='/home/user',
|
target_dir='/home/user',
|
||||||
compressed=True,
|
compressed=True,
|
||||||
passphrase='pass-from-vm')
|
passphrase=b'pass-from-vm')
|
||||||
mock_backup.return_value.backup_do.assert_called_once_with()
|
mock_backup.return_value.backup_do.assert_called_once_with()
|
||||||
self.vm.run_service_for_stdio.assert_called_with(
|
self.vm.run_service_for_stdio.assert_called_with(
|
||||||
'qubes.BackupPassphrase+testprofile')
|
'qubes.BackupPassphrase+testprofile')
|
||||||
|
Loading…
Reference in New Issue
Block a user