Files
Bridge-and-Join-s/internal/hwid/hwid.go
T

79 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package hwid — отпечаток сервера для сервера лицензий: хэши (sha256) трёх признаков, сами
// значения никуда не передаются. По ним сервер лицензий узнаёт один и тот же сервер у разных
// организаций (защита от «отключил лицензию у одной компании — включил у другой»).
// - machine: /etc/machine-id — меняется при переустановке ОС;
// - board: UUID платформы (BIOS / гипервизор, /sys/class/dmi/id/product_uuid) — у виртуальной
// машины сохраняется при переустановке ОС; читается только root, поэтому установщик кладёт
// его хэш в /etc/bj/hw-id, а bj читает оттуда;
// - mac: MAC-адреса сетевых карт (физических и virtio), отсортированные.
package hwid
import (
"crypto/sha256"
"encoding/hex"
"os"
"path/filepath"
"sort"
"strings"
)
// CacheFile — хэш UUID платформы, записанный установщиком (root) для bj.
const CacheFile = "/etc/bj/hw-id"
func sum(s string) string {
s = strings.TrimSpace(s)
if s == "" {
return ""
}
h := sha256.Sum256([]byte(s))
return hex.EncodeToString(h[:])
}
// Machine — хэш /etc/machine-id.
func Machine() string {
b, _ := os.ReadFile("/etc/machine-id")
return sum(string(b))
}
// Board — хэш UUID платформы: из DMI (под root) или из файла, записанного установщиком.
func Board() string {
if b, err := os.ReadFile("/sys/class/dmi/id/product_uuid"); err == nil {
if v := strings.ToLower(strings.TrimSpace(string(b))); v != "" && v != "00000000-0000-0000-0000-000000000000" {
return sum(v)
}
}
b, _ := os.ReadFile(CacheFile)
return strings.TrimSpace(string(b))
}
// MAC — хэш отсортированных MAC-адресов сетевых карт, у которых есть устройство (не lo, не мосты).
func MAC() string {
ents, _ := os.ReadDir("/sys/class/net")
var macs []string
for _, e := range ents {
dir := filepath.Join("/sys/class/net", e.Name())
if _, err := os.Stat(filepath.Join(dir, "device")); err != nil {
continue
}
b, err := os.ReadFile(filepath.Join(dir, "address"))
if a := strings.ToLower(strings.TrimSpace(string(b))); err == nil && a != "" && a != "00:00:00:00:00:00" {
macs = append(macs, a)
}
}
sort.Strings(macs)
return sum(strings.Join(macs, ","))
}
// WriteCache — записать хэш UUID платформы для bj (вызывает установщик под root).
func WriteCache(root string) error {
b := Board()
if b == "" {
return nil
}
p := filepath.Join(root, CacheFile)
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
return err
}
return os.WriteFile(p, []byte(b+"\n"), 0o644)
}