diff options
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py | 55 |
1 files changed, 2 insertions, 53 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py index daaee62..9a6cbd1 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py @@ -17,27 +17,20 @@ from meshbay_common.adminop import ( OP_CHAT_LINK_PREVIEW, OP_DIR_DELETE, OP_FILE_DELETE, - OP_GEK_ROTATE, - OP_GROUP_ATTACH, - OP_GROUP_DETACH, OP_INVITE_CANCEL, OP_INVITE_CREATE, OP_INVITE_LINK_CREATE, OP_MEMBER_REVOKE, - OP_MEMBER_UNPIN, OP_MUSICBRAINZ_ENABLED, - OP_ROOT_ADD, OP_ROOT_EJECT, OP_ROOT_PLUG, OP_ROOT_REMOVE, - OP_ROOT_UPDATE, OP_SEARCH_LISTED, OP_SET_SCAN_SETTINGS, OP_TMDB_CONFIG, OP_TMDB_ENABLED, OP_TMDB_OVERRIDE, OP_TMDB_REMATCH, - OP_TRANSFER_LIMITS, admin_transcript, ) from meshbay_common.crypto import pk_to_b64 @@ -62,28 +55,21 @@ _ADMIN_EXECUTORS = { OP_INVITE_CREATE: "_admin_exec_invite_create", OP_INVITE_LINK_CREATE: "_admin_exec_invite_link_create", OP_INVITE_CANCEL: "_admin_exec_invite_cancel", - OP_GEK_ROTATE: "_admin_exec_gek_rotate", - OP_MEMBER_UNPIN: "_admin_exec_member_unpin", OP_APPS_ENABLED: "_admin_exec_apps_enabled", - OP_TRANSFER_LIMITS: "_admin_exec_transfer_limits", OP_SET_SCAN_SETTINGS: "_admin_exec_set_scan_settings", OP_TMDB_CONFIG: "_admin_exec_tmdb_config", OP_TMDB_ENABLED: "_admin_exec_tmdb_enabled", OP_TMDB_OVERRIDE: "_admin_exec_tmdb_override", OP_TMDB_REMATCH: "_admin_exec_tmdb_rematch", OP_MUSICBRAINZ_ENABLED: "_admin_exec_musicbrainz_enabled", - OP_ROOT_ADD: "_admin_exec_root_add", OP_ROOT_REMOVE: "_admin_exec_root_remove", OP_APP_DIRECTORIES: "_admin_exec_app_directories", OP_CHAT_DIRECTORY: "_admin_exec_chat_directory", OP_CHAT_LINK_PREVIEW: "_admin_exec_chat_link_preview", OP_SEARCH_LISTED: "_admin_exec_search_listed", OP_CHAT_EPOCH: "_admin_exec_chat_epoch", - OP_ROOT_UPDATE: "_admin_exec_root_update", OP_ROOT_EJECT: "_admin_exec_root_eject", OP_ROOT_PLUG: "_admin_exec_root_plug", - OP_GROUP_ATTACH: "_admin_exec_group_attach", - OP_GROUP_DETACH: "_admin_exec_group_detach", } @@ -180,49 +166,12 @@ class AdminMixin: says "the hub says you are the owner", which is the one thing NS4 and M3 rule out: a hub that can name the operator can install itself as node administrator. It rides the handshake ack so a client knows whether - to offer the Node page at all, and every operation is gated on - `_operator_device()` below. + to offer operator controls at all; every operation is gated on a + signature (`_verify_admin_sig`). """ node_user_id = self._ctx.get("node_user_id") return bool(node_user_id and self._user_id == node_user_id) - async def _operator_device(self) -> bool: - """ - Whether this connection may run the node's own controls. - - Two things, and the second is the one that cannot be forged: - - - the account is the one this node belongs to (`_is_node_admin`), which - is what keeps node-wide controls with the machine's owner rather than - with every paired operator of every group on it; and - - **the device on this connection proved a key the node pinned as an - operator**. `device_hello` is signed over a transcript naming this - node, this group and this connection's nonce, and `operator_pks()` is - rebuilt from the roster on each call, so an unpinned browser and a - revoked one are both refused at once. - - The second clause is the fix for the door this used to leave open. - `node_status`, `node_settings_set`, `roster_read`, `denylist_read`, - `denylist_clear` and `node_reload` were gated on the account id alone — - a value the hub chooses. An active hub that can also reach the group key - (which §3.5 concedes it can in an open-join group) could therefore mint - a token for the owner's account and read `node_status`, which lists - every group on the node with the operator's **absolute paths**, or clear - the denylist, which is the persisted revocation H4 exists to keep. - - It holds no user keys and cannot countersign anything, so it cannot - produce a `device_hello` — which is the same property device linking - rests on (§3.3), applied to the node's own surface. - """ - if not self._is_node_admin(): - return False - if not self._device_confirmed or not self._pinned_pk: - return False - roster = self._ctx.get("roster") - if roster is None: - return False - return self._pinned_pk in await roster.operator_pks() - def _has_admin_authority(self) -> bool: """ Cheap synchronous pre-check: is there anyone who could authorize this? |