78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package main
|
|
|
|
// askparties.go — who asked to stop what, in the form the audit keeps: the
|
|
// asking account (the kernel's answer), the asking process and the agent it
|
|
// descends from, and the target, each with how it was started (origin.go:
|
|
// interactive, scheduler, service, ...). They are kept on the request itself
|
|
// (Details "asker" and "target"), so every later row about that request —
|
|
// approved, denied, carried out — names both, not only the row that filed it.
|
|
|
|
// askingAgentObs is the observed agent pid descends from, and its pid.
|
|
func askingAgentObs(pid int, observed map[int]agentObs) (agentObs, int, bool) {
|
|
parents := processTree()
|
|
p := pid
|
|
for i := 0; p > 1 && i < 64; i++ {
|
|
if a, ok := observed[p]; ok && a.Kind != kindApp {
|
|
return a, p, true
|
|
}
|
|
p = parents[p]
|
|
}
|
|
return agentObs{}, 0, false
|
|
}
|
|
|
|
// askParties describes the asker and the target of one stop ask. askerPID is
|
|
// the kernel's pid for the asking process, 0 where the platform does not say.
|
|
func askParties(account string, askerPID, targetPID int, observed map[int]agentObs) (asker, target map[string]any) {
|
|
asker = map[string]any{"account": account}
|
|
if askerPID > 1 {
|
|
asker["pid"] = askerPID
|
|
if a, p, ok := askingAgentObs(askerPID, observed); ok {
|
|
asker["agent"] = agentParty(a, p)
|
|
}
|
|
}
|
|
target = agentParty(observed[targetPID], targetPID)
|
|
return asker, target
|
|
}
|
|
|
|
func agentParty(a agentObs, pid int) map[string]any {
|
|
out := map[string]any{"pid": pid, "signature": a.Signature, "name": familyLabel(a.Signature)}
|
|
if a.Origin != "" {
|
|
out["origin"] = a.Origin
|
|
}
|
|
return out
|
|
}
|
|
|
|
// askPartiesOf is what a request carries about its asker and target, for an
|
|
// audit row; nil for a request no local agent asked (a Host's).
|
|
func askPartiesOf(d map[string]any) map[string]any {
|
|
if kind, _ := d["kind"].(string); kind != localStopKind {
|
|
return nil // "target" is a critical_action's own word, not a party
|
|
}
|
|
out := map[string]any{}
|
|
for _, k := range []string{"asker", "target"} {
|
|
if v, ok := d[k]; ok && v != nil {
|
|
out[k] = v
|
|
}
|
|
}
|
|
if by, _ := d["asked_by"].(string); by != "" {
|
|
out["who"] = by
|
|
}
|
|
if len(out) == 0 {
|
|
return nil
|
|
}
|
|
return out
|
|
}
|
|
|
|
// hostAskDetails drops from a Host's request the fields only this machine
|
|
// writes about a local agent's ask. A Host's details are its own words, so
|
|
// without this it could name an account on this computer as the asker in the
|
|
// owner's audit, and have the owner's deny count against that account.
|
|
func hostAskDetails(d map[string]any) {
|
|
delete(d, "asked_by_account")
|
|
delete(d, "asker")
|
|
if kind, _ := d["kind"].(string); kind == localStopKind {
|
|
delete(d, "asked_by")
|
|
delete(d, "target")
|
|
}
|
|
}
|