diff options
author | Michael Weiss <dev.primeos@gmail.com> | 2021-05-14 21:59:39 +0200 |
---|---|---|
committer | Michael Weiss <dev.primeos@gmail.com> | 2021-05-14 22:54:38 +0200 |
commit | 45bd7b39a444c904986324b5f7c46ba867612575 (patch) | |
tree | 87e8089f2f6236a4e67671a08ca46d52d6325027 /pkgs/applications/networking/instant-messengers/signal-desktop | |
parent | 940dfa99401c04c78bc530c72ecba6f6ccee62e8 (diff) |
signal-desktop: Add a Python wrapper to re-encrypt DBs
This is super hacky... :o But then again it should at least prevent data loss. Note: At least this isn't required for NixOS 21.05.
Diffstat (limited to 'pkgs/applications/networking/instant-messengers/signal-desktop')
-rwxr-xr-x | pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.py | 92 | ||||
-rw-r--r-- | pkgs/applications/networking/instant-messengers/signal-desktop/default.nix | 15 |
2 files changed, 106 insertions, 1 deletions
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.py b/pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.py new file mode 100755 index 0000000000000..8556ee1e4d736 --- /dev/null +++ b/pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.py @@ -0,0 +1,92 @@ +#!@PYTHON@ + +import json +import os +import re +import shlex +import sqlite3 +import subprocess +import sys + + +DB_PATH = os.path.join(os.environ['HOME'], '.config/Signal/sql/db.sqlite') +DB_COPY = os.path.join(os.environ['HOME'], '.config/Signal/sql/db.tmp') +CONFIG_PATH = os.path.join(os.environ['HOME'], '.config/Signal/config.json') + + +def zenity_askyesno(title, text): + args = [ + '@ZENITY@', + '--question', + '--title', + shlex.quote(title), + '--text', + shlex.quote(text) + ] + return subprocess.run(args).returncode == 0 + + +def start_signal(): + os.execvp('@SIGNAL-DESKTOP@', ['@SIGNAL-DESKTOP@'] + sys.argv[1:]) + + +def copy_pragma(name): + result = subprocess.run([ + '@SQLCIPHER@', + DB_PATH, + f"PRAGMA {name};" + ], check=True, capture_output=True).stdout + result = re.search(r'[0-9]+', result.decode()).group(0) + subprocess.run([ + '@SQLCIPHER@', + DB_COPY, + f"PRAGMA key = \"x'{key}'\"; PRAGMA {name} = {result};" + ], check=True, capture_output=True) + + +try: + # Test if DB is encrypted: + con = sqlite3.connect(f'file:{DB_PATH}?mode=ro', uri=True) + cursor = con.cursor() + cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") + con.close() +except: + # DB is encrypted, everything ok: + start_signal() + + +# DB is unencrypted! +answer = zenity_askyesno( + "Error: Signal-Desktop database is not encrypted", + "Should we try to fix this automatically?" + + "You likely want to backup ~/.config/Signal/ first." +) +if not answer: + answer = zenity_askyesno( + "Launch Signal-Desktop", + "DB is unencrypted, should we still launch Signal-Desktop?" + + "Warning: This could result in data loss!" + ) + if not answer: + print('Aborted') + sys.exit(0) + start_signal() + +# Re-encrypt the DB: +with open(CONFIG_PATH) as json_file: + key = json.load(json_file)['key'] +result = subprocess.run([ + '@SQLCIPHER@', + DB_PATH, + f" ATTACH DATABASE '{DB_COPY}' AS signal_db KEY \"x'{key}'\";" + + " SELECT sqlcipher_export('signal_db');" + + " DETACH DATABASE signal_db;" +]).returncode +if result != 0: + print('DB encryption failed') + sys.exit(1) +# Need to copy user_version and schema_version manually: +copy_pragma('user_version') +copy_pragma('schema_version') +os.rename(DB_COPY, DB_PATH) +start_signal() diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix index 38d52b26bff30..e1ba5884de755 100644 --- a/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix +++ b/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix @@ -10,6 +10,9 @@ , hunspellDicts, spellcheckerLanguage ? null # E.g. "de_DE" # For a full list of available languages: # $ cat pkgs/development/libraries/hunspell/dictionaries.nix | grep "dictFileName =" | awk '{ print $3 }' +, python3 +, gnome +, sqlcipher }: let @@ -112,7 +115,7 @@ in stdenv.mkDerivation rec { # Symlink to bin mkdir -p $out/bin - ln -s $out/lib/Signal/signal-desktop $out/bin/signal-desktop + ln -s $out/lib/Signal/signal-desktop $out/bin/signal-desktop-unwrapped runHook postInstall ''; @@ -137,6 +140,16 @@ in stdenv.mkDerivation rec { patchelf --add-needed ${libpulseaudio}/lib/libpulse.so $out/lib/Signal/resources/app.asar.unpacked/node_modules/ringrtc/build/linux/libringrtc.node ''; + postFixup = '' + # This hack is temporarily required to avoid data-loss for users: + cp ${./db-reencryption-wrapper.py} $out/bin/signal-desktop + substituteInPlace $out/bin/signal-desktop \ + --replace '@PYTHON@' '${python3}/bin/python3' \ + --replace '@ZENITY@' '${gnome.zenity}/bin/zenity' \ + --replace '@SQLCIPHER@' '${sqlcipher}/bin/sqlcipher' \ + --replace '@SIGNAL-DESKTOP@' "$out/bin/signal-desktop-unwrapped" + ''; + # Tests if the application launches and waits for "Link your phone to Signal Desktop": passthru.tests.application-launch = nixosTests.signal-desktop; |