summaryrefslogtreecommitdiff
path: root/foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py')
-rw-r--r--foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py68
1 files changed, 68 insertions, 0 deletions
diff --git a/foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py b/foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py
new file mode 100644
index 0000000..6a6eec1
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/memory/libkeepass/__init__.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+import io
+from contextlib import contextmanager
+
+from .common import read_signature
+# from kdb3 import KDB3Reader, KDB3_SIGNATURE
+from .kdb4 import KDB4Reader, KDB4_SIGNATURE
+
+BASE_SIGNATURE = 0x9AA2D903
+
+_kdb_readers = {
+ # KDB3_SIGNATURE[1]: KDB3Reader,
+ #0xB54BFB66: KDB4Reader, # pre2.x may work, untested
+ KDB4_SIGNATURE[1]: KDB4Reader,
+ }
+
+@contextmanager
+def open(filename, **credentials):
+ """
+ A contextmanager to open the KeePass file with `filename`. Use a `password`
+ and/or `keyfile` named argument for decryption.
+
+ Files are identified using their signature and a reader suitable for
+ the file format is intialized and returned.
+
+ Note: `keyfile` is currently not supported for v3 KeePass files.
+ """
+ kdb = None
+ try:
+ with io.open(filename, 'rb') as stream:
+ signature = read_signature(stream)
+ cls = get_kdb_reader(signature)
+ kdb = cls(stream, **credentials)
+ yield kdb
+ kdb.close()
+ except Exception:
+ if kdb: kdb.close()
+ raise
+
+def add_kdb_reader(sub_signature, cls):
+ """
+ Add or overwrite the class used to process a KeePass file.
+
+ KeePass uses two signatures to identify files. The base signature is
+ always `0x9AA2D903`. The second/sub signature varies. For example
+ KeePassX uses the v3 sub signature `0xB54BFB65` and KeePass2 the v4 sub
+ signature `0xB54BFB67`.
+
+ Use this method to add or replace a class by givin a `sub_signature` as
+ integer and a class, which should be a subclass of
+ `keepass.common.KDBFile`.
+ """
+ _kdb_readers[sub_signature] = cls
+
+def get_kdb_reader(signature):
+ """
+ Retrieve the class used to process a KeePass file by `signature`, which
+ is a a tuple or list with two elements. The first being the base signature
+ and the second the sub signature as integers.
+ """
+ if signature[0] != BASE_SIGNATURE:
+ raise IOError('Unknown base signature.')
+
+ if signature[1] not in _kdb_readers:
+ raise IOError('Unknown sub signature.')
+
+ return _kdb_readers[signature[1]]
+