Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pykeepass for
openSUSE:Factory checked in at 2021-06-01 10:37:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pykeepass (Old)
and /work/SRC/openSUSE:Factory/.python-pykeepass.new.1898 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pykeepass"
Tue Jun 1 10:37:05 2021 rev:6 rq:895543 version:4.0.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pykeepass/python-pykeepass.changes
2021-02-18 20:53:10.735482651 +0100
+++
/work/SRC/openSUSE:Factory/.python-pykeepass.new.1898/python-pykeepass.changes
2021-06-01 10:38:08.108881835 +0200
@@ -1,0 +2,8 @@
+Sun May 23 00:32:17 UTC 2021 - Atri Bhattacharya <[email protected]>
+
+- Update to version 4.0.1:
+ * No release notes.
+- Drop python-pykeepass-fix-version.patch: incorporated upstream.
+- Update dependency versions in keeping with upstream.
+
+-------------------------------------------------------------------
Old:
----
pykeepass-4.0.0.tar.gz
python-pykeepass-fix-version.patch
New:
----
pykeepass-4.0.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pykeepass.spec ++++++
--- /var/tmp/diff_new_pack.SbX2lh/_old 2021-06-01 10:38:08.716882870 +0200
+++ /var/tmp/diff_new_pack.SbX2lh/_new 2021-06-01 10:38:08.720882876 +0200
@@ -18,32 +18,30 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pykeepass
-Version: 4.0.0
+Version: 4.0.1
Release: 0
Summary: Low-level library to interact with keepass databases
License: GPL-3.0-only
Group: Development/Languages/Python
URL: https://github.com/libkeepass/pykeepass
Source:
https://github.com/libkeepass/pykeepass/archive/%{version}.tar.gz#/pykeepass-%{version}.tar.gz
-# PATCH-FIX-UPSTREAM python-pykeepass-fix-version.patch [email protected]
-- Fix version so that egg-infos don't end up with the wrong version; patch
taken from upstream commit
-Patch0: python-pykeepass-fix-version.patch
BuildRequires: %{python_module devel}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-argon2-cffi
+Requires: python-argon2-cffi >= 20.1.0
Requires: python-construct >= 2.10.54
Requires: python-future
-Requires: python-lxml
-Requires: python-pycryptodomex >= 3.6.2
+Requires: python-lxml >= 4.6.1
+Requires: python-pycryptodomex >= 3.10.1
Requires: python-python-dateutil
BuildArch: noarch
# SECTION test requirements
-BuildRequires: %{python_module argon2-cffi}
+BuildRequires: %{python_module argon2-cffi >= 20.1.0}
BuildRequires: %{python_module construct >= 2.10.54}
BuildRequires: %{python_module future}
-BuildRequires: %{python_module lxml}
-BuildRequires: %{python_module pycryptodomex >= 3.6.2}
+BuildRequires: %{python_module lxml >= 4.6.1}
+BuildRequires: %{python_module pycryptodomex >= 3.10.1}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module python-dateutil}
# /SECTION
++++++ pykeepass-4.0.0.tar.gz -> pykeepass-4.0.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/.github/dependabot.yml
new/pykeepass-4.0.1/.github/dependabot.yml
--- old/pykeepass-4.0.0/.github/dependabot.yml 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/.github/dependabot.yml 2021-05-22 09:07:02.000000000
+0200
@@ -3,4 +3,4 @@
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
- interval: "daily"
+ interval: "monthly"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/index.rst
new/pykeepass-4.0.1/doc/source/index.rst
--- old/pykeepass-4.0.0/doc/source/index.rst 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/doc/source/index.rst 2021-05-22 09:07:02.000000000
+0200
@@ -13,7 +13,6 @@
icons
exceptions
baseelement
- kdbx_parsing/*
.. image:: https://travis-ci.org/libkeepass/pykeepass.svg?branch=master
:target: https://travis-ci.org/libkeepass/pykeepass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/kdbx_parsing/common.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/common.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/common.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/common.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.common
-===================
-
-.. automodule:: pykeepass.kdbx_parsing.common
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.kdbx
-=================
-
-.. automodule:: pykeepass.kdbx_parsing.kdbx
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx3.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx3.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx3.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx3.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.kdbx3
-==================
-
-.. automodule:: pykeepass.kdbx_parsing.kdbx3
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx4.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx4.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/kdbx4.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/kdbx4.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.kdbx4
-==================
-
-.. automodule:: pykeepass.kdbx_parsing.kdbx4
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pykeepass-4.0.0/doc/source/kdbx_parsing/pytwofish.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/pytwofish.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/pytwofish.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/pytwofish.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.pytwofish
-======================
-
-.. automodule:: pykeepass.kdbx_parsing.pytwofish
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/doc/source/kdbx_parsing/twofish.rst
new/pykeepass-4.0.1/doc/source/kdbx_parsing/twofish.rst
--- old/pykeepass-4.0.0/doc/source/kdbx_parsing/twofish.rst 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/doc/source/kdbx_parsing/twofish.rst 1970-01-01
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-kdbx_parsing.twofish
-====================
-
-.. automodule:: pykeepass.kdbx_parsing.twofish
- :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/baseelement.py
new/pykeepass-4.0.1/pykeepass/baseelement.py
--- old/pykeepass-4.0.0/pykeepass/baseelement.py 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/pykeepass/baseelement.py 2021-05-22
09:07:02.000000000 +0200
@@ -14,7 +14,7 @@
class BaseElement(object):
"""Entry and Group inherit from this class"""
- def __init__(self, element=None, kp=None, icon=None, expires=False,
+ def __init__(self, element, kp=None, icon=None, expires=False,
expiry_time=None):
self._element = element
@@ -221,3 +221,15 @@
return self.uuid == other.uuid
else:
return False
+
+ def touch(self, modify=False):
+ """
+ Update last access time of an entry/group
+
+ Args:
+ modify (bool): update access time as well a modification time
+ """
+ now = datetime.now()
+ self.atime = now
+ if modify:
+ self.mtime = now
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/entry.py
new/pykeepass-4.0.1/pykeepass/entry.py
--- old/pykeepass-4.0.0/pykeepass/entry.py 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/pykeepass/entry.py 2021-05-22 09:07:02.000000000
+0200
@@ -49,7 +49,7 @@
self._element.append(E.String(E.Key('Title'), E.Value(title)))
self._element.append(E.String(E.Key('UserName'),
E.Value(username)))
self._element.append(
- E.String(E.Key('Password'), E.Value(password,
protected="False"))
+ E.String(E.Key('Password'), E.Value(password,
Protected="True"))
)
if url:
self._element.append(E.String(E.Key('URL'), E.Value(url)))
@@ -220,6 +220,9 @@
@property
def path(self):
+ """Path to element as list. List contains all parent group names
+ ending with entry title. List may contain strings or NoneTypes."""
+
# The root group is an orphan
if self.parentgroup is None:
return None
@@ -267,15 +270,6 @@
}
return '{{REF:{}@I:{}}}'.format(attribute_to_field[attribute],
self.uuid.hex.upper())
- def touch(self, modify=False):
- '''
- Update last access time of an entry
- '''
- now = datetime.now()
- self.atime = now
- if modify:
- self.mtime = now
-
def save_history(self):
'''
Save the entry in its history
@@ -291,7 +285,8 @@
self._element.append(history)
def __str__(self):
- pathstr = '/'.join(self.path)
+ # filter out NoneTypes and join into string
+ pathstr = '/'.join('' if p==None else p for p in self.path)
if self.is_a_history_entry:
return '[History of: {}]'.format(pathstr)
return 'Entry: "{} ({})"'.format(pathstr, self.username)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/group.py
new/pykeepass-4.0.1/pykeepass/group.py
--- old/pykeepass-4.0.0/pykeepass/group.py 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/pykeepass/group.py 2021-05-22 09:07:02.000000000
+0200
@@ -94,5 +94,6 @@
self._element.append(entries._element)
def __str__(self):
- pathstr = '/'.join(self.path)
+ # filter out NoneTypes and join into string
+ pathstr = '/'.join('' if p==None else p for p in self.path)
return 'Group: "{}"'.format(pathstr)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/kdbx_parsing/common.py
new/pykeepass-4.0.1/pykeepass/kdbx_parsing/common.py
--- old/pykeepass-4.0.0/pykeepass/kdbx_parsing/common.py 2021-02-03
05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/pykeepass/kdbx_parsing/common.py 2021-05-22
09:07:02.000000000 +0200
@@ -8,12 +8,16 @@
from lxml import etree
from copy import deepcopy
import base64
+from binascii import Error as BinasciiError
import unicodedata
import zlib
import re
import codecs
from io import BytesIO
from collections import OrderedDict
+import logging
+
+log = logging.getLogger(__name__)
class HeaderChecksumError(Exception):
@@ -116,7 +120,17 @@
try:
with open(keyfile, 'r') as f:
tree = etree.parse(f).getroot()
- keyfile_composite =
base64.b64decode(tree.find('Key/Data').text)
+ version = tree.find('Meta/Version').text
+ data_element = tree.find('Key/Data')
+ if version.startswith('1.0'):
+ keyfile_composite = base64.b64decode(data_element.text)
+ elif version.startswith('2.0'):
+ # read keyfile data and convert to bytes
+ keyfile_composite =
bytes.fromhex(data_element.text.strip())
+ # validate bytes against hash
+ hash = bytes.fromhex(data_element.attrib['Hash'])
+ hash_computed =
hashlib.sha256(keyfile_composite).digest()[:4]
+ assert hash == hash_computed, "Keyfile has invalid hash"
# otherwise, try to read plain keyfile
except (etree.XMLSyntaxError, UnicodeDecodeError):
try:
@@ -178,7 +192,6 @@
provided by get_cipher"""
protected_xpath = '//Value[@Protected=\'True\']'
- unprotected_xpath = '//Value[@Protected=\'False\']'
def __init__(self, protected_stream_key, subcon):
super(UnprotectedStream, self).__init__(subcon)
@@ -188,29 +201,33 @@
cipher = self.get_cipher(self.protected_stream_key(con))
for elem in tree.xpath(self.protected_xpath):
if elem.text is not None:
- result =
cipher.decrypt(base64.b64decode(elem.text)).decode('utf-8')
- # strip invalid XML characters -
https://stackoverflow.com/questions/8733233
- result = re.sub(
-
u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+',
- '',
- result
- )
- elem.text = result
- elem.attrib['Protected'] = 'False'
+ try:
+ result =
cipher.decrypt(base64.b64decode(elem.text)).decode('utf-8')
+ # strip invalid XML characters -
https://stackoverflow.com/questions/8733233
+ result = re.sub(
+
u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+',
+ '',
+ result
+ )
+ elem.text = result
+ except (UnicodeDecodeError, BinasciiError, ValueError):
+ # FIXME: this should be a warning eventually, need to fix
all databases in tests/ first
+ log.error(
+ "Element at {} marked as protected, but could not
unprotect".format(tree.getpath(elem))
+ )
return tree
def _encode(self, tree, con, path):
tree_copy = deepcopy(tree)
cipher = self.get_cipher(self.protected_stream_key(con))
- for elem in tree_copy.xpath(self.unprotected_xpath):
+ for elem in tree_copy.xpath(self.protected_xpath):
if elem.text is not None:
elem.text = base64.b64encode(
cipher.encrypt(
elem.text.encode('utf-8')
)
)
- elem.attrib['Protected'] = 'True'
- return tree
+ return tree_copy
class ARCFourVariantStream(UnprotectedStream):
@@ -282,7 +299,16 @@
con._.header.value.dynamic_header.encryption_iv.data
)
payload_data = cipher.decrypt(payload_data)
- payload_data = self.unpad(payload_data)
+ # FIXME: Construct ugliness. Fixes #244. First 32 bytes of decrypted
kdbx3 payload
+ # should be checked against stream_start_bytes for a CredentialsError.
Due to construct
+ # limitations, we have to decrypt the whole payload in order to check
the first 32 bytes.
+ # However, when the credentials are wrong the invalid decrypted
payload cannot
+ # be unpadded correctly. Instead, catch the unpad ValueError
exception raised by unpad()
+ # and allow kdbx3.py to raise a ChecksumError
+ try:
+ payload_data = self.unpad(payload_data)
+ except ValueError:
+ log.debug("Decryption unpadding failed")
return payload_data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/pykeepass.py
new/pykeepass-4.0.1/pykeepass/pykeepass.py
--- old/pykeepass-4.0.0/pykeepass/pykeepass.py 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/pykeepass/pykeepass.py 2021-05-22 09:07:02.000000000
+0200
@@ -123,6 +123,11 @@
else:
raise
+ def reload(self):
+ """Reload current database using previous credentials """
+
+ self.read(self.filename, self.password, self.keyfile)
+
def save(self, filename=None, transformed_key=None):
"""Save current database object to disk.
@@ -272,7 +277,7 @@
if tree is None:
tree = self.tree
- logger.debug(xpath_str)
+ logger.debug('xpath query: ' + xpath_str)
elements = tree.xpath(
xpath_str, namespaces={'re':
'http://exslt.org/regular-expressions'}
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/pykeepass/version.py
new/pykeepass-4.0.1/pykeepass/version.py
--- old/pykeepass-4.0.0/pykeepass/version.py 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/pykeepass/version.py 2021-05-22 09:07:02.000000000
+0200
@@ -1,3 +1,3 @@
-__version__ = "3.2.1"
+__version__ = "4.0.1"
__all__= ["__version__"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/requirements-rtd.txt
new/pykeepass-4.0.1/requirements-rtd.txt
--- old/pykeepass-4.0.0/requirements-rtd.txt 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/requirements-rtd.txt 2021-05-22 09:07:02.000000000
+0200
@@ -1,7 +1,7 @@
-lxml==4.3.5
-pycryptodomex==3.9.9
+lxml==4.6.2
+pycryptodomex==3.10.1
construct==2.10.54
-argon2-cffi==19.2.0
+argon2-cffi==20.1.0
python-dateutil==2.8.1
future==0.18.2
Sphinx>=3.2.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/requirements.txt
new/pykeepass-4.0.1/requirements.txt
--- old/pykeepass-4.0.0/requirements.txt 2021-02-03 05:02:22.000000000
+0100
+++ new/pykeepass-4.0.1/requirements.txt 2021-05-22 09:07:02.000000000
+0200
@@ -1,6 +1,6 @@
-lxml==4.3.5
-pycryptodomex==3.9.9
+lxml==4.6.2
+pycryptodomex==3.10.1
construct==2.10.54
-argon2-cffi==19.2.0
+argon2-cffi==20.1.0
python-dateutil==2.8.1
future==0.18.2
Binary files old/pykeepass-4.0.0/tests/test3.kdbx and
new/pykeepass-4.0.1/tests/test3.kdbx differ
Binary files old/pykeepass-4.0.0/tests/test3_transformed.kdbx and
new/pykeepass-4.0.1/tests/test3_transformed.kdbx differ
Binary files old/pykeepass-4.0.0/tests/test4.kdbx and
new/pykeepass-4.0.1/tests/test4.kdbx differ
Binary files old/pykeepass-4.0.0/tests/test4_keyx.kdbx and
new/pykeepass-4.0.1/tests/test4_keyx.kdbx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/tests/test4_keyx.keyx
new/pykeepass-4.0.1/tests/test4_keyx.keyx
--- old/pykeepass-4.0.0/tests/test4_keyx.keyx 1970-01-01 01:00:00.000000000
+0100
+++ new/pykeepass-4.0.1/tests/test4_keyx.keyx 2021-05-22 09:07:02.000000000
+0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<KeyFile>
+ <Meta>
+ <Version>2.0</Version>
+ </Meta>
+ <Key>
+ <Data Hash="F79BE54D">
+ 30D73184 FBE1C7C4 B07EE4D6 BC4F118B
+ 87577CAB 5CB8846F 5FD286FF F98BF9A9
+ </Data>
+ </Key>
+</KeyFile>
\ No newline at end of file
Binary files old/pykeepass-4.0.0/tests/test4_transformed.kdbx and
new/pykeepass-4.0.1/tests/test4_transformed.kdbx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-4.0.0/tests/tests.py
new/pykeepass-4.0.1/tests/tests.py
--- old/pykeepass-4.0.0/tests/tests.py 2021-02-03 05:02:22.000000000 +0100
+++ new/pykeepass-4.0.1/tests/tests.py 2021-05-22 09:07:02.000000000 +0200
@@ -277,6 +277,11 @@
self.assertIsInstance(e.__repr__(), str)
self.assertIsInstance(e.history.__repr__(), str)
+ # issue 250
+ e = self.kp.find_entries(username='blank_title', first=True)
+ self.assertIsNot(e, None)
+ self.assertIsInstance(e.__repr__(), str)
+
class GroupFindTests3(KDBX3Tests):
@@ -317,7 +322,7 @@
def test_groups(self):
results = self.kp.groups
- self.assertEqual(len(results), 6)
+ self.assertEqual(len(results), 7)
# ---------- Adding/Deleting Groups -----------
@@ -349,6 +354,10 @@
def test_print_groups(self):
self.assertIsInstance(self.kp.groups.__repr__(), str)
+ g = self.kp.find_groups(notes='blank_name')
+ self.assertIsNot(g, None)
+ self.assertIsInstance(g.__repr__(), str)
+
class RecycleBinTests3(KDBX3Tests):
def test_recyclebincreation(self):
@@ -541,6 +550,15 @@
self.assertTrue(mtime < entry.mtime)
self.assertEqual(ctime, entry.ctime)
+ group = self.kp.find_groups(name='foobar_group', first=True)
+ atime = group.atime
+ mtime = group.mtime
+ ctime = group.ctime
+ group.touch(modify=True)
+ self.assertTrue(atime < group.atime)
+ self.assertTrue(mtime < group.mtime)
+ self.assertEqual(ctime, group.ctime)
+
def test_add_remove_attachment(self):
entry = self.kp.add_entry(
@@ -824,6 +842,15 @@
self.assertTrue(g.name is None)
self.assertTrue(g in self.kp.groups)
+ def test_issue194(self):
+ # entries with Protected=True aren't being protected properly
+
+ self.kp_tmp.add_entry(self.kp_tmp.root_group, 'protect_test', 'user',
'pass')
+ self.kp_tmp.save()
+ self.kp_tmp.reload()
+ e = self.kp_tmp.find_entries(title='protect_test', first=True)
+ self.assertEqual(e.password, 'pass')
+
class EntryFindTests4(KDBX4Tests, EntryFindTests3):
@@ -867,17 +894,17 @@
stream = BytesIO(file.read())
filenames_in = [
- os.path.join(base_dir, 'test3.kdbx'), # KDBX v3 test
- os.path.join(base_dir, 'test4.kdbx'), # KDBX v4 test
- os.path.join(base_dir, 'test4_aes.kdbx'), # KDBX v4 AES test
- os.path.join(base_dir, 'test4_aeskdf.kdbx'), # KDBX v3 AESKDF
test
- os.path.join(base_dir, 'test4_chacha20.kdbx'), # KDBX v4 ChaCha
test
- os.path.join(base_dir, 'test4_twofish.kdbx'), # KDBX v4 Twofish
test
- os.path.join(base_dir, 'test4_hex.kdbx'), # legacy 64 byte
hexadecimal keyfile test
- os.path.join(base_dir, 'test3.kdbx'), # KDBX v3
transformed_key open test
- os.path.join(base_dir, 'test4_hex.kdbx'), # KDBX v4
transformed_key open test
+ os.path.join(base_dir, 'test3.kdbx'), # KDBX v3
+ os.path.join(base_dir, 'test4.kdbx'), # KDBX v4
+ os.path.join(base_dir, 'test4_aes.kdbx'), # KDBX v4 AES
+ os.path.join(base_dir, 'test4_aeskdf.kdbx'), # KDBX v3
AESKDF
+ os.path.join(base_dir, 'test4_chacha20.kdbx'), # KDBX v4
ChaCha
+ os.path.join(base_dir, 'test4_twofish.kdbx'), # KDBX v4
Twofish
+ os.path.join(base_dir, 'test4_hex.kdbx'), # legacy 64
byte hexadecimal keyfile
+ os.path.join(base_dir, 'test3_transformed.kdbx'), # KDBX v3
transformed_key open
+ os.path.join(base_dir, 'test4_transformed.kdbx'), # KDBX v4
transformed_key open
stream,
- os.path.join(base_dir, 'test4_aes_uncompressed.kdbx') # KDBX v4
AES uncompressed test
+ os.path.join(base_dir, 'test4_aes_uncompressed.kdbx') # KDBX v4
AES uncompressed
]
filenames_out = [
os.path.join(base_dir, 'test3.kdbx.out'),
@@ -887,8 +914,8 @@
os.path.join(base_dir, 'test4_chacha20.kdbx.out'),
os.path.join(base_dir, 'test4_twofish.kdbx.out'),
os.path.join(base_dir, 'test4_hex.kdbx.out'),
- os.path.join(base_dir, 'test3.kdbx.out'),
- os.path.join(base_dir, 'test4_hex.kdbx.out'),
+ os.path.join(base_dir, 'test3_transformed.kdbx.out'),
+ os.path.join(base_dir, 'test4_transformed.kdbx.out'),
BytesIO(),
os.path.join(base_dir, 'test4_aes_uncompressed.kdbx.out'),
os.path.join(base_dir, 'test4_twofish_uncompressed.kdbx.out'),
@@ -918,7 +945,7 @@
None,
None,
b'\xfb\xb1!\x0e0\x94\xd4\x868\xa5\x04\xe6T\x9b<\xf9+\xb8\x82EN\xbc\xbe\xbc\xc8\xd3\xbbf\xfb\xde\xff.',
-
b'M\xb7\x08\xf6\xa7\xd1v\xb1{&\x06\x8f\xae\xe9\r\xeb\x9a\x1b\x02b\xce\xf2\x8aR\xaea)7\x1fs\xe9\xc0',
+
b'\x95\x0be\x9ca\x9e<\xe0\x07\x02\x7f\xc3\xd8\xa1\xa6&\x985\x8f!\xa6\x18k\x13\xa2\xd2\r=\xf3\xebd\xc5',
None,
None,
None,
@@ -1021,25 +1048,33 @@
os.remove(os.path.join(base_dir, filename))
- def test_open_error(self):
- with self.assertRaises(CredentialsError):
- database = 'test4.kdbx'
- invalid_password = 'foobar'
- keyfile = os.path.join(base_dir, 'test4.key')
- PyKeePass(
- os.path.join(base_dir, database),
- password=invalid_password,
- keyfile=keyfile
- )
- with self.assertRaises(CredentialsError):
- database = 'test4.kdbx'
- password = 'password'
- invalid_keyfile = os.path.join(base_dir, 'test3.key')
- PyKeePass(
- os.path.join(base_dir, database),
- password=password,
- keyfile=invalid_keyfile
- )
+ def test_credentials_error(self):
+
+ databases = [
+ 'test3.kdbx',
+ 'test3.kdbx',
+ 'test4.kdbx',
+ 'test4.kdbx'
+ ]
+ passwords = [
+ 'invalid',
+ 'password',
+ 'invalid',
+ 'password',
+ ]
+ keyfiles = [
+ 'test3.key',
+ 'test4.key',
+ 'test4.key',
+ 'test3.key',
+ ]
+ for database, password, keyfile in zip(databases, passwords, keyfiles):
+ with self.assertRaises(CredentialsError):
+ PyKeePass(
+ os.path.join(base_dir, database),
+ password,
+ os.path.join(base_dir, keyfile)
+ )
if __name__ == '__main__':
unittest.main()