Initial commit
This commit is contained in:
commit
40a4cf285e
18 changed files with 1933 additions and 0 deletions
120
checker/types.go
Normal file
120
checker/types.go
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// 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"`
|
||||
LocalTime time.Time `json:"localTime"`
|
||||
|
||||
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"`
|
||||
|
||||
// OverallOK is the rule's summary verdict; set by the rule, not the
|
||||
// collector. Stored here for the HTML report which is rendered from
|
||||
// the observation alone.
|
||||
OverallOK bool `json:"overallOK"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue