mirror of https://github.com/ericonr/sbctl.git
202 lines
4.3 KiB
Go
202 lines
4.3 KiB
Go
package sbctl
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/foxboron/goefi/efi/attributes"
|
|
)
|
|
|
|
// Functions that doesn't fit anywhere else
|
|
|
|
// Veryvery simple check
|
|
func GetESP() string {
|
|
if _, err := os.Stat("/efi"); !os.IsNotExist(err) {
|
|
return "/efi"
|
|
}
|
|
out, err := exec.Command("lsblk", "-o", "PARTTYPE,MOUNTPOINT").Output()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
data := string(out)
|
|
for _, lines := range strings.Split(data, "\n") {
|
|
if len(lines) < 1 {
|
|
continue
|
|
}
|
|
l := strings.Split(lines, " ")
|
|
if len(l) != 2 {
|
|
continue
|
|
}
|
|
if l[0] == "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" {
|
|
return l[1]
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func VerifyESP() {
|
|
espPath := GetESP()
|
|
files := ReadFileDatabase(DBPath)
|
|
msg.Printf("Verifying file database and EFI images in %s...", espPath)
|
|
for _, file := range files {
|
|
if VerifyFile(DBCert, file.OutputFile) {
|
|
msg2.Printf("%s is signed\n", file.OutputFile)
|
|
} else {
|
|
warning2.Printf("%s is not signed\n", file.OutputFile)
|
|
}
|
|
}
|
|
err := filepath.Walk(espPath, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out, err := exec.Command("file", "-b", "--mime-type", path).Output()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
out = bytes.TrimSuffix(out, []byte("\n"))
|
|
if string(out) != "application/x-dosexec" {
|
|
return nil
|
|
}
|
|
if _, ok := files[path]; ok {
|
|
return nil
|
|
}
|
|
if VerifyFile(DBCert, path) {
|
|
msg2.Printf("%s is signed\n", path)
|
|
} else {
|
|
warning2.Printf("%s is not signed\n", path)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
|
|
func Sign(file, output string, enroll bool) {
|
|
file, err := filepath.Abs(file)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if output == "" {
|
|
output = file
|
|
}
|
|
files := ReadFileDatabase(DBPath)
|
|
if entry, ok := files[file]; ok {
|
|
SignFile(DBKey, DBCert, entry.File, entry.OutputFile)
|
|
} else {
|
|
SignFile(DBKey, DBCert, file, output)
|
|
}
|
|
if enroll {
|
|
files[file] = &SigningEntry{File: file, OutputFile: output}
|
|
WriteFileDatabase(DBPath, files)
|
|
}
|
|
}
|
|
|
|
func ListFiles() {
|
|
files := ReadFileDatabase(DBPath)
|
|
for path, s := range files {
|
|
msg.Printf("File: %s", path)
|
|
msg2.Printf("Output: %s", s.OutputFile)
|
|
}
|
|
}
|
|
|
|
func CheckStatus() {
|
|
if _, err := os.Stat("/sys/firmware/efi/efivars"); os.IsNotExist(err) {
|
|
warning.Println("System is not booted with UEFI!")
|
|
os.Exit(1)
|
|
}
|
|
if sm, err := attributes.ReadEfivars("SetupMode"); err == nil {
|
|
if sm.Data[0] == 1 {
|
|
warning.Println("Setup Mode: Enabled")
|
|
} else {
|
|
msg.Println("Setup Mode: Disabled")
|
|
}
|
|
}
|
|
if sb, err := attributes.ReadEfivars("SecureBoot"); err == nil {
|
|
if sb.Data[0] == 1 {
|
|
msg.Println("Secure Boot: Enabled")
|
|
} else {
|
|
warning.Println("Secure Boot: Disabled")
|
|
}
|
|
}
|
|
}
|
|
|
|
func CreateKeys() {
|
|
if !CheckIfKeysInitialized(KeysPath) {
|
|
msg.Printf("Creating secure boot keys...")
|
|
InitializeSecureBootKeys(DatabasePath)
|
|
} else {
|
|
msg.Printf("Secure boot keys has been created")
|
|
}
|
|
}
|
|
|
|
func SyncKeys() {
|
|
synced := SBKeySync(KeysPath)
|
|
if !synced {
|
|
err.Println("Couldn't sync keys")
|
|
os.Exit(1)
|
|
} else {
|
|
msg.Println("Synced keys!")
|
|
}
|
|
}
|
|
|
|
func CombineFiles(microcode, initramfs string) *os.File {
|
|
tmpFile, e := ioutil.TempFile("/var/tmp", "initramfs-")
|
|
if e != nil {
|
|
err.Println("Cannot create temporary file", e)
|
|
}
|
|
|
|
one, _ := os.Open(microcode)
|
|
defer one.Close()
|
|
|
|
two, _ := os.Open(initramfs)
|
|
defer two.Close()
|
|
|
|
_, e = io.Copy(tmpFile, one)
|
|
if e != nil {
|
|
log.Fatalln("failed to append microcode file to output:", err)
|
|
}
|
|
|
|
_, e = io.Copy(tmpFile, two)
|
|
if e != nil {
|
|
log.Fatalln("failed to append initramfs file to output:", err)
|
|
}
|
|
return tmpFile
|
|
}
|
|
|
|
func CreateBundle(bundle Bundle) {
|
|
if bundle.IntelMicrocode != "" {
|
|
tmpFile := CombineFiles(bundle.IntelMicrocode, bundle.Initramfs)
|
|
defer os.Remove(tmpFile.Name())
|
|
bundle.Initramfs = tmpFile.Name()
|
|
}
|
|
|
|
if bundle.AMDMicrocode != "" {
|
|
tmpFile := CombineFiles(bundle.AMDMicrocode, bundle.Initramfs)
|
|
defer os.Remove(tmpFile.Name())
|
|
bundle.Initramfs = tmpFile.Name()
|
|
}
|
|
GenerateBundle(&bundle)
|
|
}
|
|
|
|
func GenerateAllBundles() {
|
|
msg.Println("Generating EFI bundles....")
|
|
bundles := ReadBundleDatabase(BundleDBPath)
|
|
for _, bundle := range bundles {
|
|
CreateBundle(*bundle)
|
|
}
|
|
}
|
|
|
|
func ListBundles() {
|
|
bundles := ReadBundleDatabase(BundleDBPath)
|
|
for key, bundle := range bundles {
|
|
FormatBundle(key, bundle)
|
|
}
|
|
}
|