package main import ( "crypto/sha256" "encoding/hex" "os" "strings" ) // deniedCallHashes lists station callsigns not permitted to run this build, // stored as SHA-256 hex of the base call so the calls themselves appear nowhere // in the source or the compiled binary. Enforcement is best-effort by design — // the call is entered by the operator and can be changed — so this only turns // away straightforward use, not a determined one. var deniedCallHashes = map[string]struct{}{ "2282a88b3e5e4eebc6b8174d005bb46d32025758b7741bdcf34f2b3621c02205": {}, "0ee09fe60817a2a4982f5e5b14a60b8dbb11cff55b3d36661213c4cbdd0933ea": {}, "46fb61e71afb40627cb6493a6a59c9d4d0231ee3cad1a2bf3fcc4cdfce36fabc": {}, } // callDenied reports whether a callsign is on deniedCallHashes. The call is // reduced to its base form (upper-cased, portable prefix/suffix dropped) the // same way extsvc does, so F4XYZ/P matches F4XYZ. func callDenied(call string) bool { base := denyBaseCall(call) if base == "" { return false } sum := sha256.Sum256([]byte(base)) _, bad := deniedCallHashes[hex.EncodeToString(sum[:])] return bad } // denyBaseCall mirrors extsvc.baseCall: for a slashed form it returns the // longest token (the real call), otherwise the call itself, upper-cased. func denyBaseCall(s string) string { s = strings.ToUpper(strings.TrimSpace(s)) if !strings.Contains(s, "/") { return s } best := "" for _, part := range strings.Split(s, "/") { if len(part) > len(best) { best = part } } return best } // enforceCallGate exits the process silently when any of the supplied callsigns // is denied. Called once at startup, after the profiles are loaded: the first // launch is where the operator enters and saves the call, so a denied build // simply does not come back up on the next launch. No window, no message. func enforceCallGate(calls ...string) { for _, c := range calls { if callDenied(c) { os.Exit(0) } } }