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.forditas import tr from raveos_center.hatter import ervenytelenit, gyorsitott, tarolt AZON = "secureboot" CIM = "Secure Boot" SZKRIPT = "raveos-secureboot-setup" UJRAINDITAS_KELL = 10 LEPESEK_SZOVEG = [ tr("telepíti a szükséges eszközöket (sbsigntools, efitools),"), tr("létrehoz egy saját, csak ehhez a géphez tartozó aláíró kulcsot,"), tr("aláírja a rendszerbetöltőt, a kernelt és a külső kernelmodulokat (pl. NVIDIA),"), tr("beírja a firmware-be a RaveOS, a Microsoft és a saját géped kulcsát, így a Windows is tovább indul,"), tr("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( tr("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", tr("Gépkulcs")), ("signed", tr("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( tr("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(tr("A beállítás lépései"), terkoz=6) leiras.elrendezes.addWidget(cimke(tr("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( tr("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(tr("Állapot frissítése")) self.frissit_gomb.clicked.connect(self.frissit) self.ujra_gomb = gomb(tr("Újra aláírás")) self.ujra_gomb.setToolTip(tr("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", tr("Újra aláírás"))) self.beallit_gomb = gomb(tr("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(tr("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(tr("Az állapot nem olvasható: {0}", 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(tr("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(tr("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"), tr("BE"), tr("KI")), adat.get("secureboot") == "1") self._beir("setupmode", ki(adat.get("setupmode"), tr("IGEN"), tr("NEM")), adat.get("setupmode") == "1") self._beir("keys", ki(adat.get("keys"), tr("MEGVAN"), tr("NINCS")), adat.get("keys") == "1") self._beir("signed", ki(adat.get("signed"), tr("RENDBEN"), tr("HIÁNYZIK")), adat.get("signed") == "1") if adat.get("pending") == "1": self._hiba(tr("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, tr("Secure Boot beállítása"), tr("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", tr("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(tr("Újraindítás a BIOS-ba"), QMessageBox.ButtonRole.AcceptRole) doboz.addButton(tr("Később"), QMessageBox.ButtonRole.RejectRole) doboz.exec() if doboz.clickedButton() is most: muveletek.Futtato(self).indit( [ muveletek.Lepes( tr("Ú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", tr("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( tr("Újraindítás szükséges"), tr("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", tr("A művelet nem sikerült. A részleteket a napló mutatja.")) self.frissit() FUL = SecureBoot