From 1ba7cd85d7d03cd544590c8f15684cacfb75e5d2 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 24 Sep 2025 21:05:47 -0700 Subject: [PATCH] tethering password --- system/ui/lib/wifi_manager.py | 63 +++++++++++++++++++++++++++++++++++ system/ui/widgets/keyboard.py | 3 ++ system/ui/widgets/network.py | 20 ++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 0716deeba6..dc7cc23e0b 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -134,6 +134,7 @@ class WifiManager: # State self._connecting_to_ssid: str = "" self._ipv4_address: str = "" + self._tethering_password: str = "" self._last_network_update: float = 0.0 self._callback_queue: list[Callable] = [] @@ -179,6 +180,10 @@ class WifiManager: def ipv4_address(self) -> str: return self._ipv4_address + @property + def tethering_password(self) -> str: + return self._tethering_password + def _enqueue_callback(self, cb: Callable, *args): self._callback_queue.append(lambda: cb(*args)) @@ -196,10 +201,13 @@ class WifiManager: self._last_network_update = 0.0 def _monitor_state(self): + # TODO: make an initialize function to only wait in one place device_path = self._wait_for_wifi_device() if device_path is None: return + self._tethering_password = self._get_tethering_password() + rule = MatchRule( type="signal", interface=NM_DEVICE_IFACE, @@ -305,6 +313,14 @@ class WifiManager: def _get_active_connections(self): return self._router_main.send_and_get_reply(Properties(self._nm).get('ActiveConnections')).body[0][1] + def _get_connection_settings(self, conn_path: str) -> dict: + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'GetSettings')) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to get connection settings: {reply}') + return {} + return dict(reply.body[0]) + def connect_to_network(self, ssid: str, password: str): def worker(): # Clear all connections that may already exist to the network we are connecting to @@ -398,6 +414,53 @@ class WifiManager: return bool(network.ssid == self._tethering_ssid) return False + def set_tethering_password(self, password: str): + def worker(): + conn_path = self._get_connections().get(self._tethering_ssid, None) + if conn_path is None: + cloudlog.warning('No tethering connection found') + return + + settings = self._get_connection_settings(conn_path) + if len(settings) == 0: + cloudlog.warning(f'Failed to get tethering settings for {conn_path}') + return + + settings['802-11-wireless-security']['psk'] = ('s', password) + + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Update', 'a{sa{sv}}', (settings,))) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to update tethering settings: {reply}') + return + + self._tethering_password = password + if self.is_tethering_active(): + self.activate_connection(self._tethering_ssid, block=True) + + threading.Thread(target=worker, daemon=True).start() + + def _get_tethering_password(self) -> str: + conn_path = self._get_connections().get(self._tethering_ssid, None) + if conn_path is None: + cloudlog.warning('No tethering connection found') + return '' + + reply = self._router_main.send_and_get_reply(new_method_call( + DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE), + 'GetSecrets', 's', ('802-11-wireless-security',) + )) + + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to get tethering password: {reply}') + return '' + + secrets = reply.body[0] + if '802-11-wireless-security' not in secrets: + return '' + + return str(secrets['802-11-wireless-security'].get('psk', ('s', ''))[1]) + def set_tethering_active(self, active: bool): def worker(): if active: diff --git a/system/ui/widgets/keyboard.py b/system/ui/widgets/keyboard.py index 25843d1ce8..6b346db0d9 100644 --- a/system/ui/widgets/keyboard.py +++ b/system/ui/widgets/keyboard.py @@ -104,6 +104,9 @@ class Keyboard(Widget): self._all_keys[CAPS_LOCK_KEY] = Button("", partial(self._key_callback, CAPS_LOCK_KEY), icon=self._key_icons[CAPS_LOCK_KEY], button_style=ButtonStyle.KEYBOARD, multi_touch=True) + def set_text(self, text: str): + self._input_box.text = text + @property def text(self): return self._input_box.text diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index b7a958f5cd..04088abb89 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -105,6 +105,9 @@ class AdvancedNetworkSettings(Widget): def __init__(self, wifi_manager: WifiManager): super().__init__() self._wifi_manager = wifi_manager + + self._keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True) + self._keyboard.set_title("Enter new tethering password") # # self._params = Params() # self._select_language_dialog: MultiOptionDialog | None = None @@ -116,7 +119,7 @@ class AdvancedNetworkSettings(Widget): # action = - # enable tethering, tethering password, ~ip address~, wifi network metered, hidden network + # ~enable tethering~, tethering password, ~ip address~, wifi network metered, hidden network # # tethering = toggle_item("Enable Tethering", initial_state=wifi_manager # tethering = toggle_item("Enable Tethering", callback=self._wifi_manager)#, initial_state=wifi_manager @@ -124,8 +127,11 @@ class AdvancedNetworkSettings(Widget): self._tethering_action = ToggleAction(initial_state=False, enabled=True) self._tethering_btn = ListItem(title="Enable Tethering", action_item=self._tethering_action, callback=self._tethering_toggled) + self._tethering_password = button_item("Tethering Password", "EDIT", callback=self._edit_tethering_password) + items = [ self._tethering_btn, + self._tethering_password, text_item("IP Address", lambda: self._wifi_manager.ipv4_address) ] @@ -146,6 +152,18 @@ class AdvancedNetworkSettings(Widget): self._tethering_action.set_enabled(False) self._wifi_manager.set_tethering_active(checked) + def _edit_tethering_password(self): + def update_password(result): + if result != 1: + return + + password = self._keyboard.text + self._wifi_manager.set_tethering_password(password) + + self._keyboard.reset() + self._keyboard.set_text(self._wifi_manager.tethering_password) + gui_app.set_modal_overlay(self._keyboard, update_password) + def _initialize_items(self): items = [