2026-03-05 09:14:17 +00:00
|
|
|
import os
|
|
|
|
|
import re
|
2026-03-06 12:26:33 +00:00
|
|
|
import time
|
|
|
|
|
from datetime import datetime
|
2026-03-05 09:14:17 +00:00
|
|
|
from subprocess import run
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
CHANGES_REQUIRING_RESTART = ['wifi_password', 'ssid', 'enable_access_point', 'enable_chat', 'enable_delta_chat', 'butterbox_hostname']
|
|
|
|
|
# 'ssh_access_settings', 'root_account_settings']
|
|
|
|
|
|
|
|
|
|
def lock_root_account():
|
|
|
|
|
result = run(["sudo", "passwd", "-l", "root"])
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def enable_service(service: str):
|
|
|
|
|
is_enabled = run(["sudo", "systemctl", "is-enabled", service], capture_output = True, text = True)
|
2026-03-06 12:26:33 +00:00
|
|
|
if 'not_found' in is_enabled.stdout:
|
|
|
|
|
return False
|
2026-03-05 09:14:17 +00:00
|
|
|
if 'disabled' in is_enabled.stdout:
|
|
|
|
|
enable = run(["sudo", "systemctl", "enable", service], capture_output = True, text = True)
|
|
|
|
|
if enable.returncode != 0:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def disable_service(service: str):
|
|
|
|
|
is_enabled = run(["sudo", "systemctl", "is-enabled", service], capture_output = True, text = True)
|
2026-03-06 12:26:33 +00:00
|
|
|
if 'not_found' in is_enabled.stdout:
|
|
|
|
|
return False
|
2026-03-05 09:14:17 +00:00
|
|
|
if 'enabled' in is_enabled.stdout:
|
|
|
|
|
result = run(["sudo", "systemctl", "disable", service])
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def load_setting(setting):
|
2026-03-06 12:26:33 +00:00
|
|
|
with open("./app/settings.txt", "r") as f:
|
2026-03-05 09:14:17 +00:00
|
|
|
settings = json.load(f)
|
|
|
|
|
return settings[setting]
|
|
|
|
|
|
|
|
|
|
def change_service_status(setting, service):
|
|
|
|
|
if load_setting(setting) == "true":
|
|
|
|
|
enable_service(service)
|
|
|
|
|
else:
|
|
|
|
|
disable_service(service)
|
|
|
|
|
|
|
|
|
|
def change_keanu_weblite_config(new_hostname):
|
|
|
|
|
regex = re.compile('qdt ?= ?"([^"]*)"')
|
|
|
|
|
target_file = "/var/www/html/chat/assets/index-CD0QtET8.js"
|
|
|
|
|
with open(target_file, "r") as f:
|
|
|
|
|
lines = f.readlines()
|
|
|
|
|
for line in enumerate(lines):
|
|
|
|
|
match = regex.search(line)
|
|
|
|
|
if match:
|
|
|
|
|
old_hostname = match.group(1)
|
|
|
|
|
if old_hostname != new_hostname:
|
|
|
|
|
re.sub(old_hostname, new_hostname, lines[line])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def change_line_in_file(target_file: str, regex: str, replacement: str):
|
|
|
|
|
print(f"Changing line in file {target_file}")
|
|
|
|
|
regex = re.compile(regex)
|
|
|
|
|
if not os.path.isfile(target_file):
|
|
|
|
|
raise FileNotFoundError(f"File {target_file} does not exist")
|
|
|
|
|
else:
|
|
|
|
|
with open(target_file, "r") as f:
|
|
|
|
|
lines = f.readlines()
|
|
|
|
|
for i, line in enumerate(lines):
|
|
|
|
|
match = re.fullmatch(replacement, line)
|
|
|
|
|
if match:
|
|
|
|
|
print("Line already exists!")
|
|
|
|
|
return
|
|
|
|
|
for i, line in enumerate(lines):
|
|
|
|
|
match = re.fullmatch(regex, line)
|
|
|
|
|
if match:
|
|
|
|
|
lines.pop(i)
|
|
|
|
|
break
|
|
|
|
|
try:
|
|
|
|
|
lines.append(replacement)
|
|
|
|
|
except NameError:
|
|
|
|
|
raise NameError(f"File {target_file} is empty.")
|
|
|
|
|
new_lines = "".join(lines)
|
|
|
|
|
with open(target_file, "w") as f:
|
|
|
|
|
f.write(new_lines)
|
|
|
|
|
|
|
|
|
|
|
2026-03-06 12:26:33 +00:00
|
|
|
def check_settings(raspap_installed: bool):
|
|
|
|
|
if not os.path.exists("./settings.txt"):
|
|
|
|
|
return
|
|
|
|
|
last_modified = os.path.getmtime('./settings.txt')
|
|
|
|
|
diff_in_minutes = (datetime.now().timestamp() - last_modified)/60
|
|
|
|
|
if diff_in_minutes < 2:
|
2026-03-05 09:14:17 +00:00
|
|
|
for s in CHANGES_REQUIRING_RESTART:
|
2026-03-06 12:26:33 +00:00
|
|
|
if s == "wifi_password" and raspap_installed:
|
2026-03-05 09:14:17 +00:00
|
|
|
regex_wpa_method = "wpa=.*?\n"
|
|
|
|
|
if load_setting("wifi_password") == "":
|
|
|
|
|
change_line_in_file("/etc/hostapd/hostapd.conf", regex_wpa_method, f"wpa=none\n")
|
|
|
|
|
else:
|
|
|
|
|
change_line_in_file("/etc/hostapd/hostapd.conf", regex_wpa_method, f"wpa=3\n")
|
|
|
|
|
regex_pass = "wpa_passphrase=.*?\n"
|
|
|
|
|
change_line_in_file("/etc/hostapd/hostapd.conf", regex_pass,
|
|
|
|
|
f"wpa_passphrase={load_setting("wifi_password")}\n")
|
|
|
|
|
|
2026-03-06 12:26:33 +00:00
|
|
|
if s == "ssid" and raspap_installed:
|
2026-03-05 09:14:17 +00:00
|
|
|
regex_ssid = "ssid=.*?\n"
|
|
|
|
|
change_line_in_file("/etc/hostapd/hostapd.conf", regex_ssid, f"ssid={load_setting("ssid")}\n")
|
|
|
|
|
if s == "enable_chat":
|
|
|
|
|
change_service_status("enable_chat", "dendrite")
|
2026-03-06 12:26:33 +00:00
|
|
|
if s == "enable_access_point" and raspap_installed:
|
2026-03-05 09:14:17 +00:00
|
|
|
change_service_status("enable_access_point", "raspapd")
|
|
|
|
|
if s == "enable_delta_chat":
|
|
|
|
|
change_service_status("enable_delta_chat", "madmail")
|
|
|
|
|
if s == "butterbox_hostname":
|
|
|
|
|
pass
|
|
|
|
|
# change in butterbox-dendrite.conf
|
2026-03-06 12:26:33 +00:00
|
|
|
regex_matrix_server = "server_name:.*?.local\n"
|
2026-03-05 09:14:17 +00:00
|
|
|
change_line_in_file("../dendrite/butterbox-dendrite.conf", regex_matrix_server,
|
2026-03-06 12:26:33 +00:00
|
|
|
f"server_name: {load_setting("butterbox_hostname")}.local\n")
|
2026-03-05 09:14:17 +00:00
|
|
|
# change in butterbox-dnsmasq.conf
|
2026-03-06 12:26:33 +00:00
|
|
|
if raspap_installed:
|
|
|
|
|
regex_dns = "address=/.*?.local/10.3.141.1\n"
|
|
|
|
|
change_line_in_file("/etc/dnsmasq.d/butterbox-dnsmasq.conf", regex_dns,
|
|
|
|
|
f"address=/{load_setting("butterbox_hostname")}.local/10.3.141.1\n")
|
2026-03-05 09:14:17 +00:00
|
|
|
# change in keanu-weblite compiled assets
|
|
|
|
|
change_keanu_weblite_config(load_setting("butterbox_hostname"))
|
|
|
|
|
if s == "ssh_access_settings":
|
|
|
|
|
change_service_status("ssh_enabled", "ssh")
|
|
|
|
|
if load_setting("ssh_access_settings") == "enable_ssh_with_password":
|
|
|
|
|
regex_password_auth = "PasswordAuthentication.*?\n"
|
|
|
|
|
change_line_in_file("test/sshd/sshd.conf", regex_password_auth,
|
|
|
|
|
f"PasswordAuthentication yes\n")
|
|
|
|
|
regex_root_login = "PermitRootLogin.*?\n"
|
|
|
|
|
change_line_in_file("test/sshd/sshd.conf", regex_root_login,
|
|
|
|
|
f"PermitRootLogin yes\n")
|
|
|
|
|
elif load_setting("ssh_access_settings") == "enable_ssh_with_public_key":
|
|
|
|
|
regex_password_auth = "PasswordAuthentication.*?\n"
|
|
|
|
|
change_line_in_file("test/sshd/sshd.conf", regex_password_auth,
|
|
|
|
|
f"PasswordAuthentication no\n")
|
|
|
|
|
regex_root_login = "PermitRootLogin.*?\n"
|
|
|
|
|
change_line_in_file("test/sshd/sshd.conf", regex_root_login,
|
|
|
|
|
f"PermitRootLogin prohibit-password\n")
|
|
|
|
|
# append here new key!!!
|
|
|
|
|
if s == "root_account_settings":
|
|
|
|
|
if load_setting("root_account_settings") == "lock_root_account":
|
|
|
|
|
lock_root_account()
|
|
|
|
|
else:
|
2026-03-06 12:26:33 +00:00
|
|
|
# root password implementation here
|
2026-03-05 09:14:17 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2026-03-06 12:26:33 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
raspap_installed = os.path.exists("/var/www/html/raspapd")
|
|
|
|
|
while True:
|
|
|
|
|
check_settings(raspap_installed)
|
|
|
|
|
time.sleep(30)
|
|
|
|
|
|