48 lines
1.8 KiB
Python
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}
|