#!/usr/bin/python3
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2026 Ondrej Holba
"""Holbox NAS – příjem záloh ze spárovaného Holboxu (vynucený příkaz SSH).

Spárovaný Holbox se přihlásí klíčem, který má v /root/.ssh/authorized_keys volby
`restrict,command="/usr/lib/archa-nas/archa-prijem <složka>"` – sshd pak místo jejího příkazu
spustí tenhle skript a ten povolí jen příkazy, které potřebuje záloha typu „jiný NAS se ZFS“
(backup.py), a jen uvnitř přidělené složky <složka> (např. POOL1/archa-zalohy/archanas).
Všechno ostatní odmítne – spárovaný Holbox nemůže číst ani měnit nic jiného na tomto NASu.
"""
import os
import re
import shlex
import subprocess
import sys

DS = r"[A-Za-z0-9][A-Za-z0-9_.:-]*(?:/[A-Za-z0-9][A-Za-z0-9_.:-]*)*"
DS_RE = re.compile(rf"^{DS}\Z")
SNAP_RE = re.compile(rf"^({DS})@([A-Za-z0-9][A-Za-z0-9_.:-]*)\Z")
JOB_RE = re.compile(r"^archa-nas:job=[A-Za-z0-9_-]{1,40}\Z")
TEST = "zfs version 2>/dev/null | head -1 || true; command -v rsync >/dev/null && echo RSYNC-OK; echo SPOJENI-OK"


def deny(msg):
    print(f"Holbox NAS: {msg}", file=sys.stderr)
    sys.exit(1)


def main():
    if len(sys.argv) != 2 or not DS_RE.match(sys.argv[1]) or "/" not in sys.argv[1]:
        deny("chybné nastavení párování")
    root = sys.argv[1]
    cmd = os.environ.get("SSH_ORIGINAL_COMMAND", "")

    def inside(ds, allow_root=True):
        return bool(DS_RE.match(ds)) and (ds == root and allow_root or ds.startswith(root + "/"))

    if cmd == TEST:                                    # „Otestovat spojení“ v nastavení zálohy
        p = subprocess.run(["zfs", "version"], capture_output=True, text=True)
        print((p.stdout.splitlines() or ["zfs-?"])[0])
        print("SPOJENI-OK")
        return 0
    try:
        a = shlex.split(cmd)
    except ValueError:
        deny("neplatný příkaz")
    ok = False
    if a[:1] == ["zfs"]:
        r = a[1:]
        if r[:-1] in (["list", "-H", "-o", "name", "-t", "snapshot", "-d", "1", "-s", "creation"], ["list", "-H", "-o", "name"],
                      ["list", "-H", "-o", "name,archa-nas:job", "-r", "-t", "filesystem,volume,snapshot"]) and len(r) > 1:
            ok = inside(r[-1])
        elif r[:2] == ["create", "-p"] and len(r) == 3:
            ok = inside(r[2])
        elif r[:2] == ["destroy", "-r"] and len(r) == 3:
            ok = inside(r[2], allow_root=False)       # celou přidělenou složku smazat nejde, jen zálohy v ní
        elif r[:1] == ["destroy"] and len(r) == 2:
            m = SNAP_RE.match(r[1])
            ok = bool(m) and inside(m.group(1))
        elif r[:3] == ["recv", "-u", "-F"]:
            rest = r[3:]
            if len(rest) == 5 and rest[0] == "-o" and rest[1] == "readonly=on" and rest[2] == "-o" and JOB_RE.match(rest[3]):
                ok = inside(rest[4], allow_root=False)
            elif len(rest) == 1:
                ok = inside(rest[0], allow_root=False)
    if not ok:
        deny("tento příkaz spárovaný Holbox nesmí – povolené jsou jen zálohy do složky " + root)
    if a[1] == "recv":
        # Přijatá data se nikdy nepřipojí: přípojné místo a sdílení z proudu se ignorují (jinak by podstrčená
        # složka s mountpoint=/etc překryla po restartu systém) a canmount=off platí i pro vnořené složky.
        a = a[:4] + ["-x", "mountpoint", "-x", "sharenfs", "-x", "sharesmb", "-o", "canmount=off"] + a[4:]
    os.execvp("zfs", a)


if __name__ == "__main__":
    sys.exit(main())
