Initial commit

This commit is contained in:
nemunaire 2026-04-24 10:33:26 +07:00
commit a6dbcef0f9
26 changed files with 2993 additions and 0 deletions

86
checker/rules_usage.go Normal file
View file

@ -0,0 +1,86 @@
package checker
import (
"context"
"strings"
sdk "git.happydns.org/checker-sdk-go/checker"
tls "git.happydns.org/checker-tls/checker"
)
// usageCoherentRule flags TLSA records whose declared usage contradicts the
// chain slot their hash actually matches, typically a record published as
// usage 1 or 3 (end-entity) whose hash in fact matches an intermediate.
// That is almost always a publisher error: the intended usage was 0 or 2.
type usageCoherentRule struct{}
func (r *usageCoherentRule) Name() string { return "dane.usage_coherent" }
func (r *usageCoherentRule) Description() string {
return "Flags TLSA records whose declared usage does not match the chain slot they actually hash (e.g. usage 3 matching an intermediate)."
}
func (r *usageCoherentRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
rc := loadRuleContext(ctx, obs)
if rc.err != nil {
return []sdk.CheckState{observationErrorState(rc.err)}
}
var out []sdk.CheckState
tested := 0
for _, t := range rc.data.Targets {
probe := rc.probes[t.Ref]
if !probeUsable(probe) || len(probe.Chain) < 2 {
continue
}
tested++
warn := suspiciousUsage(t, probe)
if warn != "" {
out = append(out, sdk.CheckState{
Status: sdk.StatusWarn,
Code: "dane_usage_incoherent",
Subject: targetSubject(t),
Message: warn,
Meta: targetMeta(t),
})
}
}
if len(out) == 0 {
if tested == 0 {
return []sdk.CheckState{{
Status: sdk.StatusUnknown,
Code: "dane_usage_coherent_skipped",
Message: "No multi-cert chain probed yet; cannot assess usage coherence.",
}}
}
return []sdk.CheckState{{
Status: sdk.StatusOK,
Code: "dane_usage_coherent_ok",
Message: "End-entity TLSA records match end-entity certificates on every probed chain.",
}}
}
return out
}
// suspiciousUsage returns a human-readable hint when a record hash matches a
// chain slot that contradicts its declared usage (e.g. usage 3 whose hash
// actually matches the intermediate), almost always a publisher error. Used
// by both usageCoherentRule and the HTML report.
func suspiciousUsage(t TargetResult, p *tls.TLSProbe) string {
if p == nil || len(p.Chain) < 2 {
return ""
}
for _, r := range t.Records {
if r.Usage != UsageDANEEE && r.Usage != UsagePKIXEE {
continue
}
for _, c := range p.Chain[1:] {
cand, err := recordCandidate(r, c)
if err != nil {
continue
}
if strings.EqualFold(cand, r.Certificate) {
return "A record declared with usage 1/3 (end-entity) actually matches an intermediate certificate. It should probably use usage 0 or 2 (trust-anchor) instead."
}
}
}
return ""
}