VoicePult/lan_access.py
2026-10-03 11:07:47 +02:00

48 lines
1.8 KiB
Python

"""LAN access control and local network address discovery."""
import ipaddress
import json
import os
from pathlib import Path
import secrets
import subprocess
class LanAccess:
def __init__(self, config, enabled, port):
self.enabled, self.port = enabled, port
self.key = ''
self.urls = []
if enabled:
path = Path(config).with_name('lan-key')
path.parent.mkdir(parents=True, exist_ok=True)
try:
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
except FileExistsError:
self.key = path.read_text().strip()
if len(self.key) < 20:
raise ValueError('Ungültiger LAN-Zugangscode in ' + str(path))
else:
self.key = secrets.token_urlsafe(24)
with os.fdopen(fd, 'w') as file:
file.write(self.key)
try:
result = subprocess.run(['ip', '-j', '-4', 'route', 'get', '1.1.1.1'], capture_output=True, text=True, timeout=3)
addresses = {entry['prefsrc'] for entry in json.loads(result.stdout) if entry.get('prefsrc')}
self.urls = [f'http://{address}:{port}' for address in sorted(addresses)]
except (OSError, ValueError, subprocess.TimeoutExpired):
pass
@staticmethod
def local(address):
try:
return ipaddress.ip_address(address).is_loopback
except ValueError:
return False
def allowed(self, address, supplied):
return self.local(address) or (self.enabled and bool(supplied) and secrets.compare_digest(self.key.encode(), supplied.encode()))
def info(self, address):
return {'enabled': self.enabled, 'urls': self.urls,
'key': self.key if self.local(address) else None}