package checker import ( "fmt" "strings" sdk "git.happydns.org/checker-sdk-go/checker" ) // DNS-level rules: lookup outcome, record presence, service/DNS parity, // DNSSEC authentication, and owner-name hash correctness. These apply // to both OPENPGPKEY and SMIMEA records. func checkDNSQueryFailed(d *EmailKeyData, _ sdk.CheckerOptions) []issue { if d.DNSQueryError == "" { return nil } return []issue{{ Severity: sdk.StatusCrit, Message: d.DNSQueryError, Hint: "Check that the zone is published at an authoritative server reachable from this checker.", }} } func checkDNSNoRecord(d *EmailKeyData, _ sdk.CheckerOptions) []issue { if d.DNSAnswerPresent == nil || *d.DNSAnswerPresent { return nil } kind := "OPENPGPKEY" if d.Kind == KindSMIMEA { kind = "SMIMEA" } return []issue{{ Severity: sdk.StatusCrit, Message: fmt.Sprintf("Authoritative DNS returned no %s record at %s.", kind, d.QueriedOwner), Hint: "Ensure the record is present in the zone and that the zone has been loaded by the authoritative servers.", }} } func checkDNSRecordMismatch(d *EmailKeyData, _ sdk.CheckerOptions) []issue { if d.DNSRecordMatchesService == nil || *d.DNSRecordMatchesService { return nil } return []issue{{ Severity: sdk.StatusWarn, Message: "The record returned by DNS does not match the one declared in the service. The zone may not have been re-published since the last edit.", Hint: "Propagate the zone to the authoritative servers, then wait for TTL/negative-cache expiry.", }} } func checkDNSSECNotValidated(d *EmailKeyData, opts sdk.CheckerOptions) []issue { if d.DNSSECSecure == nil || *d.DNSSECSecure { return nil } sev := sdk.StatusWarn if sdk.GetBoolOption(opts, OptionRequireDNSSEC, true) { sev = sdk.StatusCrit } return []issue{{ Severity: sev, Message: "The validating resolver did not set the AD flag: the record is not DNSSEC-authenticated, which defeats the whole DANE trust model.", Hint: "Sign the zone with DNSSEC and publish the DS record at the parent so RFC 7929/8162 consumers can authenticate the key.", }} } func checkOwnerHashMismatch(d *EmailKeyData, _ sdk.CheckerOptions) []issue { if d.ExpectedOwnerPrefix == "" || d.ObservedOwnerPrefix == "" { return nil } if strings.EqualFold(d.ObservedOwnerPrefix, d.ExpectedOwnerPrefix) { return nil } return []issue{{ Severity: sdk.StatusCrit, Message: fmt.Sprintf("Owner name prefix %q does not match SHA-256(%q)[:28]=%q.", d.ObservedOwnerPrefix, d.Username, d.ExpectedOwnerPrefix), Hint: "Republish the record at the hash-derived name for the intended user, or update the Username field to match the record's owner name.", }} }