From 3ab1788708dc7bb8a9780afb6854ea42ae38d527 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Thu, 26 Oct 2023 05:55:24 +0100 Subject: [PATCH 1/2] permissions --- hivemind_core/database.py | 11 +++++++-- hivemind_core/protocol.py | 49 ++++++++++++++++++++++++++++++++------- hivemind_core/service.py | 3 +++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/hivemind_core/database.py b/hivemind_core/database.py index 571fb7f..368f549 100644 --- a/hivemind_core/database.py +++ b/hivemind_core/database.py @@ -10,7 +10,8 @@ def cast_to_client_obj(): valid_kwargs: Iterable[str] = ("client_id", "api_key", "name", "description", "is_admin", "last_seen", "blacklist", "allowed_types", "crypto_key", - "password") + "password", "can_broadcast", "can_escalate", + "can_propagate") def _handler(func): @@ -49,7 +50,10 @@ def __init__(self, blacklist: Optional[Dict[str, List[str]]] = None, allowed_types: Optional[List[str]] = None, crypto_key: Optional[str] = None, - password: Optional[str] = None): + password: Optional[str] = None, + can_broadcast: bool = True, + can_escalate: bool = True, + can_propagate: bool = True): self.client_id = client_id self.description = description @@ -67,6 +71,9 @@ def __init__(self, self.allowed_types = allowed_types or ["recognizer_loop:utterance"] if "recognizer_loop:utterance" not in self.allowed_types: self.allowed_types.append("recognizer_loop:utterance") + self.can_broadcast = can_broadcast + self.can_escalate = can_escalate + self.can_propagate = can_propagate def __getitem__(self, item: str) -> Any: return self.__dict__.get(item) diff --git a/hivemind_core/protocol.py b/hivemind_core/protocol.py index 6422e48..57cf131 100644 --- a/hivemind_core/protocol.py +++ b/hivemind_core/protocol.py @@ -58,6 +58,9 @@ class HiveMindClientConnection: allowed_types: List[str] = field(default_factory=list) # list of ovos message_type to allow to be sent from this client binarize: bool = False site_id: str = "unknown" + can_broadcast: bool = True + can_escalate: bool = True + can_propagate: bool = True @property def peer(self) -> str: @@ -227,6 +230,7 @@ class HiveMindListenerProtocol: escalate_callback = None # slave asked to escalate payload illegal_callback = None # slave asked to broadcast payload (illegal action) propagate_callback = None # slave asked to propagate payload + broadcast_callback = None # slave asked to broadcast payload mycroft_bus_callback = None # slave asked to inject payload into mycroft bus shared_bus_callback = None # passive sharing of slave device bus (info) @@ -348,6 +352,7 @@ def handle_unknown_message(self, message: HiveMessage, client: HiveMindClientCon def handle_binary_message(self, message: HiveMessage, client: HiveMindClientConnection): assert message.msg_type == HiveMessageType.BINARY + # TODO def handle_handshake_message(self, message: HiveMessage, client: HiveMindClientConnection): @@ -413,12 +418,24 @@ def handle_broadcast_message(self, message: HiveMessage, client: HiveMindClientC """ message (HiveMessage): HiveMind message object """ - # Slaves are not allowed to broadcast, by definition broadcast goes - # downstream only, use propagate instead - LOG.warning("Received broadcast message from downstream, illegal action") - if self.illegal_callback: - self.illegal_callback(message.payload) - # TODO kick client for misbehaviour so it stops doing that? + payload = self._unpack_message(message, client) + + if not client.can_broadcast: + LOG.warning("Received broadcast message from downstream, illegal action") + if self.illegal_callback: + self.illegal_callback(payload) + # TODO kick client for misbehaviour so it stops doing that? + return + + if self.broadcast_callback: + self.broadcast_callback(payload) + + # broadcast message to other peers + payload = self._unpack_message(message, client) + for peer in self.clients: + if peer == client.peer: + continue + self.clients[peer].send(payload) def _unpack_message(self, message: HiveMessage, client: HiveMindClientConnection): # propagate message to other peers @@ -440,13 +457,20 @@ def handle_propagate_message(self, message: HiveMessage, payload = self._unpack_message(message, client) + if not client.can_propagate: + LOG.warning("Received propagate message from downstream, illegal action") + if self.illegal_callback: + self.illegal_callback(payload) + # TODO kick client for misbehaviour so it stops doing that? + return + if self.propagate_callback: self.propagate_callback(payload) # propagate message to other peers - for peer in payload.target_peers: - if peer in self.clients: - self.clients[peer].send(payload) + for peer in self.clients: + if peer == client.peer: + continue # send to other masters message = Message("hive.send.upstream", payload, @@ -469,6 +493,13 @@ def handle_escalate_message(self, message: HiveMessage, # unpack message payload = self._unpack_message(message, client) + if not client.can_escalate: + LOG.warning("Received escalate message from downstream, illegal action") + if self.illegal_callback: + self.illegal_callback(payload) + # TODO kick client for misbehaviour so it stops doing that? + return + if self.escalate_callback: self.escalate_callback(payload) diff --git a/hivemind_core/service.py b/hivemind_core/service.py index cb54f5b..a873889 100644 --- a/hivemind_core/service.py +++ b/hivemind_core/service.py @@ -130,6 +130,9 @@ def open(self): self.client.crypto_key = user.crypto_key self.client.blacklist = user.blacklist.get("messages", []) self.client.allowed_types = user.allowed_types + self.client.can_broadcast = user.can_broadcast + self.client.can_propagate = user.can_propagate + self.client.can_escalate = user.can_escalate if user.password: # pre-shared password to derive aes_key self.client.pswd_handshake = PasswordHandShake(user.password) From ba8b0d548efa0d74133327b39a6bddd65303e4f3 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Thu, 26 Oct 2023 05:56:03 +0100 Subject: [PATCH 2/2] permissions --- hivemind_core/protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hivemind_core/protocol.py b/hivemind_core/protocol.py index 57cf131..db7a7e3 100644 --- a/hivemind_core/protocol.py +++ b/hivemind_core/protocol.py @@ -471,6 +471,7 @@ def handle_propagate_message(self, message: HiveMessage, for peer in self.clients: if peer == client.peer: continue + self.clients[peer].send(payload) # send to other masters message = Message("hive.send.upstream", payload,