checker-kerberos/checker/types.go

112 lines
4.5 KiB
Go

// Package checker implements the Kerberos realm checker for happyDomain.
//
// Given a realm / DNS domain, the checker performs a sequence of anonymous
// probes (SRV layout, KDC reachability, AS-REQ exchange, enctype & clock-
// skew discovery) and optionally an authenticated round-trip. Results are
// stored as a single KerberosData observation and rendered as an HTML
// report.
package checker
import (
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
// ObservationKeyKerberos is the observation key for Kerberos realm test data.
const ObservationKeyKerberos sdk.ObservationKey = "kerberos_realm"
// SRVRecord mirrors a *dns.SRV row we want to report on.
type SRVRecord struct {
Target string `json:"target"`
Port uint16 `json:"port"`
Priority uint16 `json:"priority"`
Weight uint16 `json:"weight"`
}
// SRVBucket is the resolution outcome for one SRV prefix.
type SRVBucket struct {
Prefix string `json:"prefix"`
Records []SRVRecord `json:"records,omitempty"`
// Error describes why the lookup failed. NXDOMAIN is reported as an
// empty slice + Error="" so the UI can tell "no records" from
// "lookup failed".
Error string `json:"error,omitempty"`
NXDomain bool `json:"nxdomain,omitempty"`
LookupName string `json:"lookupName"`
}
// HostResolution is the A/AAAA resolution outcome for a single SRV target.
type HostResolution struct {
Target string `json:"target"`
IPv4 []string `json:"ipv4,omitempty"`
IPv6 []string `json:"ipv6,omitempty"`
Error string `json:"error,omitempty"`
}
// KDCProbe captures the outcome of a single L4 probe.
type KDCProbe struct {
Target string `json:"target"`
Port uint16 `json:"port"`
Proto string `json:"proto"` // "tcp" | "udp"
Role string `json:"role"` // "kdc" | "kadmin" | "kpasswd" | "master"
OK bool `json:"ok"`
RTT time.Duration `json:"rtt_ns"`
Error string `json:"error,omitempty"`
KrbSeen bool `json:"krbSeen,omitempty"` // true when a KRB message was actually parsed
}
// EnctypeEntry describes one advertised enctype.
type EnctypeEntry struct {
ID int32 `json:"id"`
Name string `json:"name"`
Weak bool `json:"weak,omitempty"`
Salt string `json:"salt,omitempty"`
Source string `json:"source"` // "etype-info2" | "etype-info" | "pw-salt"
}
// ASProbeResult summarizes what the AS-REQ probe taught us.
type ASProbeResult struct {
Attempted bool `json:"attempted"`
Target string `json:"target,omitempty"`
Proto string `json:"proto,omitempty"`
ErrorCode int32 `json:"errorCode,omitempty"`
ErrorName string `json:"errorName,omitempty"`
ServerRealm string `json:"serverRealm,omitempty"`
ServerTime time.Time `json:"serverTime,omitempty"`
ClockSkew time.Duration `json:"clockSkew_ns,omitempty"`
Enctypes []EnctypeEntry `json:"enctypes,omitempty"`
PreauthReq bool `json:"preauthRequired"`
PKINITOffered bool `json:"pkinitOffered,omitempty"`
PrincipalFound bool `json:"principalFound,omitempty"` // KDC returned an AS-REP without preauth (rare / AS-REP roasting exposure)
Raw string `json:"raw,omitempty"` // informative: e.g. "KRB-ERROR (25) PREAUTH_REQUIRED"
Error string `json:"error,omitempty"`
}
// AuthProbeResult is filled only when credentials were supplied.
type AuthProbeResult struct {
Attempted bool `json:"attempted"`
Principal string `json:"principal,omitempty"`
TGTAcquired bool `json:"tgtAcquired"`
TGSAcquired bool `json:"tgsAcquired"`
TargetService string `json:"targetService,omitempty"`
Latency time.Duration `json:"latency_ns,omitempty"`
ErrorCode int32 `json:"errorCode,omitempty"`
ErrorName string `json:"errorName,omitempty"`
Error string `json:"error,omitempty"`
}
// KerberosData is the full observation payload.
type KerberosData struct {
Realm string `json:"realm"`
CollectedAt time.Time `json:"collectedAt"`
SRV []SRVBucket `json:"srv"`
Resolution map[string]HostResolution `json:"resolution,omitempty"`
Probes []KDCProbe `json:"probes,omitempty"`
AS ASProbeResult `json:"as"`
Auth *AuthProbeResult `json:"auth,omitempty"`
Enctypes []EnctypeEntry `json:"enctypes,omitempty"`
WeakEnctypes []EnctypeEntry `json:"weakEnctypes,omitempty"`
}