Repository: XKNX/xknx
Pull request #902 (2022-03-30 22:49:24)

Decrypt management password in keyring
<!--
  You are awesome! Thanks for contributing to our project!
  Please, DO NOT DELETE ANY TEXT from this template!.
-->
## Description
<!--
Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context.
List any dependencies that are required for this change.
-->
Add missing decryption of management password to code


Fixes # (issue)

## Type of change
<!--
Please tick the applicable options.
NOTE: Ticking multiple options most likely indicates
that your change is to big and it is suggested to split it into several smaller PRs.
-->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## Checklist:

- [ ] I have performed a self-review of my own code
- [ ] The documentation has been adjusted accordingly
- [ ] The changes generate no new warnings
- [ ] Tests have been added that prove the fix is effective or that the feature works
- [ ] The changes are documented in the changelog
- [ ] The Homeassistant plugin has been adjusted in case of new config options



Patch:
diff --git a/changelog.md b/changelog.md
index 2ebf6fc6..a57a2554 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,10 @@
 
 ## Unreleased changes
 
+### Bug fixes
+
+- Stop SecureSession keepalive_task when session is stopped (and don't restart it from sending STATUS_CLOSE)
+
 ## 0.20.0 IP Secure 2022-03-29
 
 ### Features
diff --git a/xknx/io/secure_session.py b/xknx/io/secure_session.py
index 28846185..13613522 100644
--- a/xknx/io/secure_session.py
+++ b/xknx/io/secure_session.py
@@ -187,7 +187,6 @@ class SecureSession(TCPTransport):
         if self._session_status_handler:
             self.unregister_callback(self._session_status_handler)
             self._session_status_handler = None
-        self.stop_keepalive_task()
         if self.transport and self.initialized:
             self.send(
                 KNXIPFrame.init_from_body(
@@ -197,6 +196,7 @@ class SecureSession(TCPTransport):
                     )
                 )
             )
+        self.stop_keepalive_task()
         self.initialized = False
         super().stop()
 
diff --git a/xknx/secure/keyring.py b/xknx/secure/keyring.py
index 9f1bacb3..171864d2 100644
--- a/xknx/secure/keyring.py
+++ b/xknx/secure/keyring.py
@@ -206,6 +206,15 @@ class XMLDevice(AttributeReader):
                 )
             )
 
+        if self.management_password is not None:
+            self.decrypted_management_password = extract_password(
+                decrypt_aes128cbc(
+                    base64.b64decode(self.management_password),
+                    password_hash,
+                    initialization_vector,
+                )
+            )
+
 
 class Keyring(AttributeReader):
     """Class for loading and decrypting knxkeys XML files."""


Test patch:
diff --git a/test/io_tests/secure_session_test.py b/test/io_tests/secure_session_test.py
index 461cb3f3..c0533d06 100644
--- a/test/io_tests/secure_session_test.py
+++ b/test/io_tests/secure_session_test.py
@@ -177,6 +177,7 @@ class TestSecureSession:
             mock_send.assert_called_once_with(session_status_close_frame)
             mock_super_send.assert_called_once()
             mock_transport.close.assert_called_once()
+            assert self.session._keepalive_task is None
 
     def test_uninitialized(self):
         """Test for raising when an encrypted Frame arrives at an uninitialized Session."""
diff --git a/test/secure_tests/keyring_test.py b/test/secure_tests/keyring_test.py
index 1f7242ba..f8cd8450 100644
--- a/test/secure_tests/keyring_test.py
+++ b/test/secure_tests/keyring_test.py
@@ -34,6 +34,7 @@ class TestKeyRing:
         TestKeyRing.assert_interface(keyring, "user2", "4")
         TestKeyRing.assert_interface(keyring, "user3", "5")
         TestKeyRing.assert_interface(keyring, "user4", "6")
+        assert keyring.devices[0].decrypted_management_password == "commissioning"
 
         interface: XMLInterface = keyring.interfaces[0]
         device: XMLDevice = keyring.get_device_by_interface(interface)