Fix OATH key verifier.

Prevents incorrect "wrong password" messages.
This commit is contained in:
Dain Nilsson 2022-05-30 14:57:49 +02:00
parent fbe20b7049
commit 8b0f6bf8a5
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8

View File

@ -91,6 +91,7 @@ class OathNode(RpcNode):
def __init__(self, connection): def __init__(self, connection):
super().__init__() super().__init__()
self.session = OathSession(connection) self.session = OathSession(connection)
self._key_verifier = None
if self.session.locked: if self.session.locked:
key = self._get_access_key(self.session.device_id) key = self._get_access_key(self.session.device_id)
@ -162,12 +163,15 @@ class OathNode(RpcNode):
return decode_bytes(params.pop("key")) return decode_bytes(params.pop("key"))
raise ValueError("One of 'key' and 'password' must be provided.") raise ValueError("One of 'key' and 'password' must be provided.")
def _do_validate(self, key): def _set_key_verifier(self, key):
self.session.validate(key)
salt = os.urandom(32) salt = os.urandom(32)
digest = hmac.new(salt, key, "sha256").digest() digest = hmac.new(salt, key, "sha256").digest()
self._key_verifier = (salt, digest) self._key_verifier = (salt, digest)
def _do_validate(self, key):
self.session.validate(key)
self._set_key_verifier(key)
@action @action
def validate(self, params, event, signal): def validate(self, params, event, signal):
remember = params.pop("remember", False) remember = params.pop("remember", False)
@ -181,7 +185,7 @@ class OathNode(RpcNode):
valid = False valid = False
else: else:
raise e raise e
elif hasattr(self, "_key_verifier"): elif self._key_verifier:
salt, digest = self._key_verifier salt, digest = self._key_verifier
verify = hmac.new(salt, key, "sha256").digest() verify = hmac.new(salt, key, "sha256").digest()
valid = hmac.compare_digest(digest, verify) valid = hmac.compare_digest(digest, verify)
@ -198,18 +202,21 @@ class OathNode(RpcNode):
remember = params.pop("remember", False) remember = params.pop("remember", False)
key = self._get_key(params) key = self._get_key(params)
self.session.set_key(key) self.session.set_key(key)
self._set_key_verifier(key)
remember &= self._remember_key(key if remember else None) remember &= self._remember_key(key if remember else None)
return dict(remembered=remember) return dict(remembered=remember)
@action(condition=lambda self: self.session.has_key) @action(condition=lambda self: self.session.has_key)
def unset_key(self, params, event, signal): def unset_key(self, params, event, signal):
self.session.unset_key() self.session.unset_key()
self._key_verifier = None
self._remember_key(None) self._remember_key(None)
return dict() return dict()
@action @action
def reset(self, params, event, signal): def reset(self, params, event, signal):
self.session.reset() self.session.reset()
self._key_verifier = None
self._remember_key(None) self._remember_key(None)
return dict() return dict()