Documentation
¶
Index ¶
- Constants
- Variables
- func Completions() []display.Options
- func Detail(h *pb.Host, showRoute bool) display.Detail
- func DisplayDetails() []display.Options
- func DisplayHeaders() []display.Options
- func FilterIdenticalPort(raw []host.PortORM, dbHosts []*host.PortORM) (filtered []host.PortORM)
- func GetOperatingSystem(h *pb.Host) (osName, osFamily string)
- func IDsMatching(query *gorm.DB, h *pb.Host) *gorm.DB
- func InfoPanes(h *pb.Host) []display.Pane
- func Insights(h *pb.Host) (lines []string)
- func MergeHost(dst, src *host.Host) (changed bool)
- func SameHost(a, b *host.Host) bool
- func SamePort(a, b *host.Port) bool
- type Group
- type Host
- type Port
- type User
Constants ¶
const ( // StateUp / StateDown are host liveness (Status.State). StateUp = "up" StateDown = "down" // Port states (Port.State.State). Open/Closed/Filtered are the common trio; // the remaining variants are the other values nmap may emit. PortOpen = "open" PortClosed = "closed" PortFiltered = "filtered" PortUnfiltered = "unfiltered" PortOpenFiltered = "open|filtered" PortClosedFiltered = "closed|filtered" )
Host status and port states.
These are NOT an enum: the values are the exact strings nmap writes into its XML `state` attribute (Status.State for a host, Port.State/ExtraPort.State for a port), unmarshalled straight into the `string` fields via their `xml:"…"` tags. They are therefore an external contract whose spelling must not drift — these consts give the codebase one authoritative spelling to switch/compare against instead of the literals that were duplicated across the host, network, scan and cmd packages.
Variables ¶
var DisplayFields = map[string]func(h *pb.Host) string{ "ID": func(h *pb.Host) string { if h.Status != nil && h.Status.State == StateUp { return color.HiGreenString(display.FormatSmallID(h.Id)) } return display.FormatSmallID(h.Id) }, "Hostnames": func(h *pb.Host) string { var hostnames []string for _, hn := range h.Hostnames { hostnames = append(hostnames, hn.Name) } return strings.Join(hostnames, "\n") }, "OS Name": func(h *pb.Host) string { osName, _ := GetOperatingSystem(h) return osName }, "OS Family": func(h *pb.Host) string { _, fam := GetOperatingSystem(h) return fam }, "Addresses": func(h *pb.Host) string { var addresses []string for _, hn := range h.Addresses { addresses = append(addresses, hn.Addr) } return strings.Join(addresses, "\n") }, "Status": func(h *pb.Host) string { if h.Status == nil { return "" } switch h.Status.State { case StateUp: return color.HiGreenString(h.Status.State) case StateDown: return color.HiRedString(h.Status.State) default: return h.Status.State } }, "Hops": func(h *pb.Host) string { if h.Trace == nil { return "" } return fmt.Sprint(len(h.Trace.Hops)) }, "Extra Ports": func(h *pb.Host) string { ports := "" for _, port := range h.ExtraPorts { ports += printExtraPorts(port, 1) } return ports }, "Arch": getProbableCPU, "MAC": func(h *pb.Host) string { return h.MAC }, "Purpose": func(h *pb.Host) string { if h.OS == nil { return "" } if h.Purpose != "" { return h.Purpose } times := map[string]int{} for _, m := range h.OS.Matches { for _, c := range m.Classes { if c.Type != "" { times[c.Type]++ } } } var purposes []string for name, times := range times { typeStr := name + display.Dim + fmt.Sprintf("(%d)", times) purposes = append(purposes, typeStr) } return strings.Join(purposes, " | ") }, "Route": func(h *pb.Host) string { if h.Trace == nil { return "" } routes := "\n" + display.Reset for i := len(h.Trace.Hops) - 1; i >= 0; i-- { hop := h.Trace.Hops[i] line := display.Dim + " |_ " rtt := display.Dim + fmt.Sprintf("%*s", 6, hop.RTT) + display.Reset ipPad := fmt.Sprintf("%*s ", 18, hop.IPAddr) line += rtt + ipPad + display.Bold + display.FgYellow + hop.Host + display.Reset routes += line + "\n" } return strings.TrimSuffix(routes, "\n") }, "Scripts": func(h *pb.Host) string { return "" }, "Sources": func(h *pb.Host) string { return provenance.Tools(h.GetSources()) }, "Virtual Host": func(h *pb.Host) string { return h.VirtualHost }, "Comment": func(h *pb.Host) string { return h.Comment }, }
Fields maps field names to their value generators.
Functions ¶
func Completions ¶
Completions returns some columns to be combined into completion candidates and/or their descriptions.
func Detail ¶
Detail assembles the full `info` view for a single host: the identity banner, the side-by-side info panes, the derived insights, and any trailing sections (open ports, extra ports, comment and — when showRoute is set — the full traceroute). It hands these to the shared display.Detail renderer, so a host's detail view is laid out identically to every other domain's. showRoute mirrors the `hosts show --traceroute` flag: the route can be long, so it prints only on request.
func DisplayDetails ¶
DetailHeaders returns the headers for a detailed host view.
func DisplayHeaders ¶
DisplayHeaders returns all weighted table headers for a table of hosts.
func FilterIdenticalPort ¶
FilterIdenticalPort returns a list of portsfrom which have been removed all ports that are already in the database, with a very high degree of certitude. This avoids redundance when manipulating new ports/services.
func GetOperatingSystem ¶
GetOperatingSystem returns the operating system of the host based on potential OS guess matches, or if none and the information is known without any guessing.
func IDsMatching ¶ added in v0.3.0
IDsMatching resolves a host *filter value* to the subquery selecting the ids of the hosts it denotes. It is the host end of the host/subnet scoping axis: the domain servers pass whatever host a caller sent on the wire (usually a bare `&pb.Host{Id: …}` or `&pb.Host{Addresses: …}`) and get back something db.ScopeByHost can join against, without any domain having to re-spell "how do I turn a host filter into host ids".
Resolution is by identity, most-specific first, and only ONE leg ever runs:
- Id set → that host alone (the id is the identity, nothing else can add to it).
- else Addresses → every host carrying one of those addresses (via the host_addresses m2m, index-backed by addresses.addr). This is the leg a CLI user hits when they scope by IP without knowing the UUID.
- else Hostnames → every host answering to one of those names.
A nil host, or one carrying none of the three, returns nil — the caller's "no host scoping" signal — so a request's Host field can be threaded through unconditionally and an unset one simply widens back to every host. Note this is deliberately *identity* resolution, not the full SameHost fold: it answers "which stored hosts is the caller pointing at", which is a query concern, whereas SameHost answers "are these two records the same host", an ingest one.
TODO(subnet): the second half of this axis — scoping to a CIDR rather than a single host — is NOT implemented. Addresses are stored as free text (addresses.addr), so correct containment needs either an inet-typed column (Postgres-only, a schema change) or loading every address to test it in Go (defeating the point of pushing the scope down to the DB). Byte-aligned-prefix LIKE tricks would only cover /8, /16 and /24 and silently mis-answer everything else, which is exactly the half-implementation this axis must not ship. Revisit alongside a typed address column; until then callers scope one host at a time.
func InfoPanes ¶
InfoPanes groups a host's detail into titled panes (System / Network / Status) for side-by-side layout via display.Columns, mirroring the credential and service info views. Empty panes are dropped, so a host with no OS/network data never prints a bare title.
func Insights ¶
Insights returns cross-cutting observations about a single host for the info view: a down/stale warning, exposed cleartext services, a large-attack-surface note, and a flag when the OS is only an nmap guess.
func MergeHost ¶
MergeHost folds src into dst in place, by field class, without losing data. It assumes the two already match (SameHost); callers do the matching and scoping.
func SameHost ¶
SameHost reports whether two in-memory hosts denote the same machine, using natural keys only (DEDUP.md §2, keyed-first): MAC is definitive, otherwise a shared address is decisive. A shared hostname alone is deliberately NOT enough to merge — virtual hosts share names — so per the no-false-merge asymmetry we would rather split than wrongly collapse two hosts.
Types ¶
type Group ¶
Group - A computer group of users. This type will be closely related to the various aims/credential types.
type Host ¶
Host - A physical or virtual computer host. The type has several categories of fields: general information, and Nmap-compliant fields (ports, status, route, scripts etc).
type Port ¶
Port - A port on a Host. The type has several categories of fields: general information, and Nmap-compliant fields (status, owner, service, scripts etc).