Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,275 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Narrow native Wi-Fi bridge. Credentials travel over a private Unix socket."""
import argparse
import configparser
import json
import os
from pathlib import Path
import re
import socket
import struct
import subprocess
import sys
import uuid
SOCKET = '/run/tundra-wifi/control.sock'
MAX_REQUEST = 16384
DEVICE = 'wlan0'
PROFILE_DIR = Path('/etc/NetworkManager/system-connections')
class WifiError(Exception):
pass
def fields(line):
"""Decode nmcli's escaped colon-separated output, including SSIDs."""
result, value, escaped = [], '', False
for char in line:
if escaped:
value += char
escaped = False
elif char == '\\':
escaped = True
elif char == ':':
result.append(value)
value = ''
else:
value += char
if escaped:
value += '\\'
return result + [value]
def nm(*args, timeout=45):
try:
return subprocess.run(['/usr/bin/nmcli', '--wait', '30', *args],
capture_output=True, text=True, timeout=timeout,
env={'PATH': '/usr/sbin:/usr/bin:/sbin:/bin', 'LC_ALL': 'C'})
except (OSError, subprocess.TimeoutExpired):
raise WifiError('WIFI_UNAVAILABLE') from None
def networks(rescan=False):
result = nm('-t', '--escape', 'yes', '-f', 'DBUS-PATH,SSID,SIGNAL,SECURITY,IN-USE',
'device', 'wifi', 'list', 'ifname', DEVICE,
'--rescan', 'yes' if rescan else 'no')
if result.returncode:
raise WifiError('WIFI_UNAVAILABLE')
found = []
for line in result.stdout.splitlines():
parts = fields(line)
if len(parts) != 5:
continue
ident, ssid, signal, security, active = parts
if not re.fullmatch(r'/org/freedesktop/NetworkManager/AccessPoint/\d+', ident) or not ssid:
continue
if not signal.isdigit() or not 0 <= int(signal) <= 100:
continue
if not security or security == '--':
mode = 'open'
elif '802.1X' in security or 'EAP' in security:
mode = 'unsupported'
elif 'WPA3' in security and 'WPA2' not in security:
mode = 'sae'
elif 'WPA2' in security or 'WPA1' in security or security == 'WPA':
mode = 'wpa-psk'
else:
mode = 'unsupported'
found.append({'id': ident, 'ssid': ssid, 'signal': int(signal),
'security': mode, 'connected': active == '*'})
return sorted(found, key=lambda row: -row['signal'])[:128]
def saved_profiles(profile_dir):
result = []
for path in profile_dir.glob('vulpes-*.nmconnection'):
try:
if path.is_symlink():
continue
parser = configparser.ConfigParser(interpolation=None)
parser.read(path)
uid = str(uuid.UUID(parser['connection']['uuid']))
if path.name != 'vulpes-' + uid + '.nmconnection':
continue
ssid = bytes(int(b) for b in parser['wifi']['ssid'].split(';') if b).decode()
mode = parser.get('wifi-security', 'key-mgmt', fallback='open')
result.append({'id': uid, 'ssid': ssid, 'security': mode, 'known': True})
except (OSError, ValueError, KeyError, configparser.Error):
continue
return result
def private_write(target, text):
temporary = target.with_suffix('.tmp')
fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_TRUNC | os.O_NOFOLLOW, 0o600)
with os.fdopen(fd, 'w') as stream:
os.fchmod(stream.fileno(), 0o600)
stream.write(text)
stream.flush()
os.fsync(stream.fileno())
temporary.replace(target)
def profile_text(network, password, uid):
ssid = network['ssid']
if not isinstance(ssid, str) or not 1 <= len(ssid.encode()) <= 32:
raise WifiError('WIFI_INVALID_REQUEST')
mode = network['security']
if mode not in ('open', 'wpa-psk', 'sae'):
raise WifiError('WIFI_UNSUPPORTED_SECURITY')
if not isinstance(password, str) or any(ord(c) < 32 for c in password):
raise WifiError('WIFI_INVALID_PASSWORD')
length = len(password.encode())
if mode == 'wpa-psk' and not (8 <= length <= 63 or re.fullmatch(r'[0-9a-fA-F]{64}', password)):
raise WifiError('WIFI_INVALID_PASSWORD')
if mode == 'sae' and not 1 <= length <= 63:
raise WifiError('WIFI_INVALID_PASSWORD')
text = (f'[connection]\nid=Vulpes Wi-Fi\nuuid={uid}\ntype=wifi\n'
'interface-name=wlan0\nautoconnect=true\n[wifi]\nmode=infrastructure\n'
'cloned-mac-address=permanent\nssid=' +
''.join(str(b) + ';' for b in ssid.encode()) +
'\n[ipv4]\nmethod=auto\n[ipv6]\nmethod=auto\n')
if mode != 'open':
escaped = password.replace('\\', '\\\\').replace(' ', '\\s')
text += f'[wifi-security]\nkey-mgmt={mode}\npsk={escaped}\n'
return text
def dispatch(request, profile_dir=PROFILE_DIR):
if not isinstance(request, dict) or set(request) - {'operation', 'id', 'password', 'enabled'}:
raise WifiError('WIFI_INVALID_REQUEST')
operation = request.get('operation')
saved = saved_profiles(profile_dir)
if operation == 'known':
return {'networks': saved}
if operation == 'forget':
network = next((row for row in saved if row['id'] == request.get('id')), None)
if network is None:
raise WifiError('WIFI_NETWORK_GONE')
uid = network['id']
if nm('connection', 'delete', 'uuid', uid).returncode:
raise WifiError('WIFI_FORGET_FAILED')
(profile_dir / ('vulpes-' + uid + '.nmconnection')).unlink(missing_ok=True)
return {'forgotten': True}
if operation in ('status', 'scan', 'setEnabled'):
if operation == 'setEnabled':
enabled = request.get('enabled')
if type(enabled) is not bool:
raise WifiError('WIFI_INVALID_REQUEST')
if nm('radio', 'wifi', 'on' if enabled else 'off').returncode:
raise WifiError('WIFI_UNAVAILABLE')
radio = nm('radio', 'wifi')
if radio.returncode:
raise WifiError('WIFI_UNAVAILABLE')
enabled = radio.stdout.strip() == 'enabled'
found = networks(rescan=True) if enabled and operation == 'scan' else []
for network in found:
stored = next((row for row in saved if row['ssid'] == network['ssid'] and row['security'] == network['security']), None)
network.update(known=stored is not None, savedId=stored['id'] if stored else None)
return {'enabled': enabled, 'networks': found}
if operation == 'disconnect':
if nm('device', 'disconnect', DEVICE).returncode:
raise WifiError('WIFI_DISCONNECT_FAILED')
return {'disconnected': True}
if operation != 'connect':
raise WifiError('WIFI_INVALID_REQUEST')
# Resolve an observed AP; clients cannot supply nmcli arguments or arbitrary SSIDs.
network = next((row for row in networks() if row['id'] == request.get('id')), None)
if network is None:
raise WifiError('WIFI_NETWORK_GONE')
stored = next((row for row in saved if row['ssid'] == network['ssid'] and row['security'] == network['security']), None)
uid = stored['id'] if stored else str(uuid.uuid4())
target = profile_dir / ('vulpes-' + uid + '.nmconnection')
previous = target.read_text() if stored else None
text = previous if stored and not request.get('password') else profile_text(network, request.get('password', ''), uid)
profile_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
target = profile_dir / ('vulpes-' + uid + '.nmconnection')
connected = False
try:
private_write(target, text)
if nm('connection', 'load', str(target)).returncode:
raise WifiError('WIFI_UNAVAILABLE')
if nm('connection', 'up', 'uuid', uid).returncode:
raise WifiError('WIFI_CONNECT_FAILED')
connected = True
return {'connected': True}
finally:
if not connected:
# Never include nmcli stderr: it may contain the SSID or credentials.
if previous is not None:
private_write(target, previous)
nm('connection', 'load', str(target))
else:
nm('connection', 'delete', 'uuid', uid)
target.unlink(missing_ok=True)
def receive(stream, limit):
data = bytearray()
while b'\n' not in data:
part = stream.recv(min(4096, limit + 1 - len(data)))
if not part:
raise WifiError('WIFI_INVALID_REQUEST')
data.extend(part)
if len(data) > limit:
raise WifiError('WIFI_INVALID_REQUEST')
if data.count(b'\n') != 1 or not data.endswith(b'\n'):
raise WifiError('WIFI_INVALID_REQUEST')
return json.loads(data)
def handle(stream):
stream.settimeout(5)
try:
_, uid, _ = struct.unpack('3i', stream.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, 12))
if uid not in (0, 32011):
raise WifiError('PERMISSION_DENIED')
result = {'result': dispatch(receive(stream, MAX_REQUEST))}
except WifiError as error:
result = {'error': str(error)}
except Exception:
result = {'error': 'WIFI_UNAVAILABLE'}
try:
stream.sendall(json.dumps(result).encode() + b'\n')
except OSError:
pass
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--client', action='store_true')
args = parser.parse_args()
if args.client:
try:
data = sys.stdin.buffer.read(MAX_REQUEST + 1)
if len(data) > MAX_REQUEST:
raise WifiError('WIFI_INVALID_REQUEST')
with socket.socket(socket.AF_UNIX) as stream:
stream.settimeout(90)
stream.connect(SOCKET)
stream.sendall(json.dumps(json.loads(data)).encode() + b'\n')
result = receive(stream, 65536)
except Exception:
result = {'error': 'WIFI_UNAVAILABLE'}
print(json.dumps(result))
return
if os.getuid() or 'tundra.rescue=1' not in Path('/proc/cmdline').read_text():
raise SystemExit('Temporary native boot required')
os.umask(0o077)
path = Path(SOCKET)
path.unlink(missing_ok=True)
with socket.socket(socket.AF_UNIX) as server:
server.bind(SOCKET)
os.chown(SOCKET, 0, 32011)
path.chmod(0o660)
server.listen(4)
while True:
stream, _ = server.accept()
with stream:
handle(stream)
if __name__ == '__main__':
main()