import shutil import subprocess from PyQt6.QtWidgets import QHBoxLayout, QMessageBox, QPlainTextEdit, QVBoxLayout, QWidget from raveos_center import muveletek from raveos_center.elemek import Kartya, Racs, cimke, gomb from raveos_center.hatter import ervenytelenit, gyorsitott, tarolt AZON = "secureboot" CIM = "Secure Boot" SZKRIPT = "raveos-secureboot-setup" UJRAINDITAS_KELL = 10 LEPESEK_SZOVEG = [ "telepíti a szükséges eszközöket (sbsigntools, efitools),", "létrehoz egy saját, csak ehhez a géphez tartozó aláíró kulcsot,", "aláírja a rendszerbetöltőt, a kernelt és a külső kernelmodulokat (pl. NVIDIA),", "beírja a firmware-be a RaveOS, a Microsoft és a saját géped kulcsát, így a Windows is tovább indul,", "beállít egy automatikus aláírást, ami minden kernelfrissítés után újra aláír.", ] def allapot_lekerdez(): if not shutil.which(SZKRIPT): return None kimenet = subprocess.run([SZKRIPT, "--status"], capture_output=True, text=True, timeout=30) adat = {} for sor in kimenet.stdout.splitlines(): if "=" in sor and not sor.startswith("["): k, _, v = sor.partition("=") adat[k.strip()] = v.strip() if not adat and "Nem UEFI" in kimenet.stdout: adat["uefi"] = "0" return adat class SecureBoot(QWidget): def __init__(self, kozpont): super().__init__() self.kozpont = kozpont doboz = QVBoxLayout(self) doboz.setContentsMargins(0, 20, 0, 0) doboz.setSpacing(16) doboz.addWidget( cimke( "A Secure Boot csak aláírt rendszerbetöltőt és kernelt enged elindulni. Akkor hasznos, ha a gépen " "Windows is van, és ott olyan játék vagy program fut, ami bekapcsolt Secure Bootot kér (például egyes " "csalásvédelmek vagy a Windows 11). A beállítás után a RaveOS és a Windows is elindul.", "masodlagos", True, ) ) oszlopok = QHBoxLayout() oszlopok.setSpacing(24) bal = QVBoxLayout() bal.setSpacing(12) oszlopok.addLayout(bal, 3) doboz.addLayout(oszlopok, 1) self.racs = Racs(110, 10) self.ertekek = {} for kulcs, nev in ( ("secureboot", "Secure Boot"), ("setupmode", "Setup Mode"), ("keys", "Gépkulcs"), ("signed", "Aláírások"), ): k = Kartya(nev, terkoz=6, margo=14) ertek = cimke("...", "nagyszam") k.elrendezes.addWidget(ertek) self.ertekek[kulcs] = ertek self.racs.hozzaad(k) bal.addWidget(self.racs) self.figyelem = cimke("", "figyelem", True) self.figyelem.hide() bal.addWidget(self.figyelem) bal.addWidget( cimke( "FIGYELEM, BITLOCKER: ha a gépen Windows is van BitLockerrel, a beállítás előtt a Windowsban függeszd " "fel a BitLockert (manage-bde -protectors -disable C: -rebootcount 2), vagy legyen kéznél a 48 jegyű " "helyreállítási kulcs. Enélkül a Windows a következő indításkor ezt a kulcsot fogja kérni.", "figyelem", True, ) ) leiras = Kartya("A beállítás lépései", terkoz=6) leiras.elrendezes.addWidget(cimke("A Beállítás gomb egymás után:", "masodlagos")) for i, szoveg in enumerate(LEPESEK_SZOVEG, 1): sor = QHBoxLayout() sor.setSpacing(10) jel = cimke(f"{i}.", "monozold") jel.setFixedWidth(22) sor.addWidget(jel) sor.addWidget(cimke(szoveg, "masodlagos", True), 1) leiras.elrendezes.addLayout(sor) leiras.elrendezes.addSpacing(6) leiras.elrendezes.addWidget( cimke( "Ehhez a firmware-nek Setup Mode-ban kell lennie: a BIOS/UEFI beállításokban töröld a Secure Boot " "kulcsokat (Clear Secure Boot keys / Reset to Setup Mode). Ha nincs Setup Mode-ban, a Center szól, " "és újraindítás után a beállítás magától folytatódik.", "halvany", True, ) ) leiras.setMinimumWidth(300) leiras.setMaximumWidth(420) jobb = QVBoxLayout() jobb.addWidget(leiras) jobb.addStretch(1) oszlopok.addLayout(jobb, 2) gombok = QHBoxLayout() gombok.setSpacing(8) self.frissit_gomb = gomb("Állapot frissítése") self.frissit_gomb.clicked.connect(self.frissit) self.ujra_gomb = gomb("Újra aláírás") self.ujra_gomb.setToolTip("Ha a gépkulcs már megvan, csak újra aláírja a rendszerbetöltőt, a kernelt és a modulokat.") self.ujra_gomb.clicked.connect(lambda: self._futtat("resign", "Újra aláírás")) self.beallit_gomb = gomb("Beállítás", fo=True) self.beallit_gomb.clicked.connect(self._beallit) gombok.addWidget(self.frissit_gomb) gombok.addStretch(1) gombok.addWidget(self.ujra_gomb) gombok.addWidget(self.beallit_gomb) bal.addLayout(gombok) bal.addWidget(cimke("NAPLÓ", "h2")) self.naplo = QPlainTextEdit() self.naplo.setObjectName("naplo") self.naplo.setReadOnly(True) self.naplo.setMinimumHeight(80) bal.addWidget(self.naplo, 1) self.futtato = muveletek.Futtato(self) self.futtato.sor.connect(self.naplo.appendPlainText) self.futtato.kesz.connect(self._kesz) self.adat = {} def megjelenik(self, *_): self._betolt() def frissit(self): ervenytelenit("secureboot") self._betolt() def _betolt(self): if tarolt("secureboot") is None: for e in self.ertekek.values(): e.setText("...") gyorsitott( "secureboot", allapot_lekerdez, kesz=self._allapot, hiba=lambda u: self._hiba(f"Az állapot nem olvasható: {u}"), kor=60, ) def _hiba(self, szoveg): self.figyelem.setText(szoveg) self.figyelem.show() def _allapot(self, adat): self.adat = adat or {} self.figyelem.hide() if adat is None: for e in self.ertekek.values(): e.setText("-") self._hiba("A Secure Boot beállító (raveos-secureboot-setup) nincs telepítve.") self._gombok(False) return if adat.get("uefi") == "0": for e in self.ertekek.values(): e.setText("-") self._hiba("Ez a gép nem UEFI módban indult, ezért a Secure Boot nem érhető el.") self._gombok(False) return def ki(ertek, igen, nem): return igen if ertek == "1" else nem if ertek == "0" else "?" self._beir("secureboot", ki(adat.get("secureboot"), "BE", "KI"), adat.get("secureboot") == "1") self._beir("setupmode", ki(adat.get("setupmode"), "IGEN", "NEM"), adat.get("setupmode") == "1") self._beir("keys", ki(adat.get("keys"), "MEGVAN", "NINCS"), adat.get("keys") == "1") self._beir("signed", ki(adat.get("signed"), "RENDBEN", "HIÁNYZIK"), adat.get("signed") == "1") if adat.get("pending") == "1": self._hiba("A beállítás félbemaradt, és a következő újraindításkor magától folytatódik.") self._gombok(True) def _beir(self, kulcs, szoveg, zold): e = self.ertekek[kulcs] e.setText(szoveg) e.setProperty("zold", zold) e.style().unpolish(e) e.style().polish(e) def _gombok(self, elerheto): fut = self.futtato.fut() helper = muveletek.helper_elerheto() self.beallit_gomb.setEnabled(elerheto and helper and not fut) self.ujra_gomb.setEnabled(elerheto and helper and not fut and self.adat.get("keys") == "1") self.frissit_gomb.setEnabled(not fut) def _beallit(self): valasz = QMessageBox.question( self, "Secure Boot beállítása", "A beállítás kulcsokat ír a firmware-be, és aláírja a rendszerbetöltőt és a kernelt. " "Ha Windows is van a gépen BitLockerrel, előtte függeszd fel a BitLockert.\n\nFolytatod?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No, ) if valasz == QMessageBox.StandardButton.Yes: self._futtat("setup", "Secure Boot beállítása") def _futtat(self, mod, cimke_szoveg): self.naplo.clear() self._gombok(False) self.futtato.indit([muveletek.Lepes(cimke_szoveg, muveletek.root("secureboot", mod))]) def _bios_ujrainditas(self, cim, szoveg): doboz = QMessageBox(self) doboz.setWindowTitle(cim) doboz.setText(szoveg) most = doboz.addButton("Újraindítás a BIOS-ba", QMessageBox.ButtonRole.AcceptRole) doboz.addButton("Később", QMessageBox.ButtonRole.RejectRole) doboz.exec() if doboz.clickedButton() is most: muveletek.Futtato(self).indit( [ muveletek.Lepes( "Újraindítás a firmware beállításaiba", ["bash", "-c", "systemctl reboot --firmware-setup || systemctl reboot"], ) ] ) def _kesz(self, rendben, _hibasak): kod = self.futtato.utolso_kod if rendben: self._bios_ujrainditas( "Secure Boot", "Az aláírások és a kulcsok készen vannak.\n\nA BIOS-ban állítsd a Secure Bootot Enabled-re, " "majd mentsd el a beállítást és indítsd újra a gépet.", ) elif kod == UJRAINDITAS_KELL: self._bios_ujrainditas( "Újraindítás szükséges", "A firmware nincs Setup Mode-ban.\n\nA BIOS-ban a Secure Boot menüben töröld a kulcsokat " "(Key Management, Clear Secure Boot keys), így a gép Setup Mode-ba kerül. Mentés után indítsd újra " "a gépet: a beállítás indítás után magától befejeződik.", ) else: QMessageBox.warning(self, "Secure Boot", "A művelet nem sikerült. A részleteket a napló mutatja.") self.frissit() FUL = SecureBoot