Package cert

Leaf X.509 certificate fetching and CA/Browser Forum validation-level classification from policy OIDs. Source: internal/cert/cert.go.

Reserved policy OIDs: 2.23.140.1.1 (EV), 2.23.140.1.2.1 (DV), 2.23.140.1.2.2 (OV), 2.23.140.1.2.3 (IV). Priority order is EV > OV > IV > DV.


Details

type Details struct {
    Issuer      string    // Organization, or fallback issuer string
    Class       string    // EV, OV, IV, DV, or Unknown
    SANs        []string  // DNS SANs (CN fallback), empty when unavailable
    OIDs        []string  // raw policy OIDs found
    Subject     string
    IssuerStr   string
    Fingerprint string    // SHA-256 of the raw leaf, hex-encoded
    NotBefore   time.Time
    NotAfter    time.Time
    HasCert     bool
}

Extracted leaf-certificate fields. Issuer prefers the Organization attribute and falls back to Common Name, then the full issuer string. SANs falls back to the subject Common Name.


Classify

func Classify(oids []string) string

Maps a set of policy OID strings to a validation class using the ordered priority table (EV first). Returns "Unknown" when none match.

cert.Classify([]string{"2.23.140.1.2.1"}) // => "DV"

InspectDomain

func InspectDomain(ctx context.Context, domain string, perCall time.Duration) (*Details, error)

Dials domain:443 with tls.Dialer (InsecureSkipVerify, since the peer is untrusted by definition) and returns the parsed leaf via FromLeaf. Transient failures are retried up to 3 times with a 1 second delay.

ParameterDescription
ctxParent context; the global 15 second budget.
domainAlready-normalized domain to dial.
perCallPer-attempt deadline (5 seconds in the CLI).

InspectAddr

func InspectAddr(ctx context.Context, ip net.IP, domain string, perCall time.Duration) (*Details, error)

Dials ip:443 directly (bypassing the system resolver) while presenting domain as SNI, capturing the TLS identity served at one resolution-path endpoint. The CLI fetches one Details per path (system-resolved IP vs public-resolved IP) so ComparePaths can diff them. Same 3-attempt retry posture as InspectDomain.


ComparePaths

func ComparePaths(sys, pub *Details) (match, complete bool, detail string)

Pure comparison of the TLS identities served at the system-resolved and public-resolved endpoints: issuer organization, validation class, SAN set (order/case-insensitive), and leaf SHA-256 fingerprint. Reports whether both endpoints were interrogated (complete), whether the identities agree (match), and a human-readable mismatch description. Missing certificates fail open — incomplete, never a mismatch. Safe to unit test.


FromLeaf

func FromLeaf(leaf *x509.Certificate) *Details

Pure constructor: builds Details from an already-parsed leaf certificate. Preferred entry point for tests.


SANsString

func (d *Details) SANsString() string

Joins SANs with ", " for display, or returns "Unknown" when empty. Nil-receiver safe.


Licensed under the GNU General Public License v3 - Mark Robillard Jr (MARKMENTAL)