Initial commit
This commit is contained in:
commit
1b4dacff1f
23 changed files with 1843 additions and 0 deletions
86
checker/rules_usage.go
Normal file
86
checker/rules_usage.go
Normal 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 ""
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue