Documentation
¶
Overview ¶
Package identity implements RFC 3325 P-Asserted-Identity (PAI) and Privacy header processing for both outbound (UAC) and inbound (UAS) signaling paths.
Why a dedicated package:
- The same parser is needed in pkg/sip/server (extract PAI from inbound INVITE) and pkg/sip/outbound (emit PAI on outbound INVITE), and a future pkg/sip/identity8224 extension (STIR/SHAKEN) wants to chain off the same trust-domain config.
- PAI semantics differ from From/Contact in two non-obvious ways: (1) it carries an *asserted* (carrier-validated) identity, not the UAS-claimed one, and (2) by RFC 3325 §4 it MUST be stripped at trust-domain boundaries unless an explicit relationship exists. Centralising the validation keeps that boundary rule in one place.
Out of scope here: signing the assertion (that's RFC 8224 Identity, batch 3B). PAI is the unsigned, hop-by-hop "trust us, we validated the caller" header — only safe within a trust domain.
Index ¶
Constants ¶
const ( PrivacyNone = "" // no Privacy header PrivacyID = "id" // hide PAI identity (RFC 3325 §7) PrivacyNoChange = "none" // explicit opt-out (RFC 3323) PrivacyHeader = "header" // strip Via/Contact for privacy PrivacyUser = "user" // anonymize From PrivacySession = "session" // anonymize SDP PrivacyCritical = "critical" )
PrivacyToken values defined by RFC 3323 / RFC 3325. We expose the subset we actually emit / consume; "header" / "session" / "user" / "critical" are accepted on input but treated like "id" for the purpose of UI redaction.
Variables ¶
This section is empty.
Functions ¶
func FormatPrivacyHeader ¶
FormatPrivacyHeader renders a Privacy header value from a token list. Empty / nil input returns "" (caller should omit the header entirely).
func ParsePrivacy ¶
ParsePrivacy parses the `Privacy:` header value (RFC 3323 §4.2). The header carries a semicolon-separated token list; we lowercase and return them in declaration order. Empty input → nil slice.
func PeerIsTrusted ¶
PeerIsTrusted reports whether an inbound signaling peer is in the trust domain. Empty allow-list => trust any peer (dev mode).
We match on host alone (port stripped) because operators almost always rotate SBC ports while keeping the host stable. If you need strict host:port matching, configure with explicit ports — we still compare those exactly when the env value carries a port.
func PrivacyRequestsID ¶
PrivacyRequestsID reports whether the parsed Privacy tokens ask us to suppress identity at egress. RFC 3325 §7 says any of {id, header, user} implies "hide PAI"; `none` overrides.
func SetTrustDomainsForTest ¶
func SetTrustDomainsForTest(list []string)
SetTrustDomainsForTest is used by unit tests to override the env without touching process state. Pass nil to revert to env-driven.
Types ¶
type Asserted ¶
type Asserted struct {
// URI is the bare URI without angle brackets ("sip:+8613800138000@trust.example"
// or "tel:+8613800138000"). Empty means the header was absent or
// stripped by the trust-domain filter.
URI string
// DisplayName is the optional unquoted display-name. Empty when the
// header had no display-name part.
DisplayName string
// Scheme is "sip" / "sips" / "tel" for quick predicate checks; lower
// case, never empty when URI != "".
Scheme string
}
Asserted is one parsed P-Asserted-Identity row. RFC 3325 allows two rows max: one sip:/sips: URI and one tel: URI. We keep them in URI / DisplayName form because that's what downstream business code wants to log / display / persist.
func ParsePAI ¶
ParsePAI parses one or more P-Asserted-Identity header values. RFC 3325 §3 allows at most two: one sip:/sips: and one tel:. We tolerate extras gracefully (return what we parsed; ignore the rest) instead of failing loud — better to surface a partial identity than reject the call.
Multi-line input ("\r\n" separator) is the form we get from the stack.Message GetHeader implementation when peers fold PAI.
func (Asserted) FormatHeader ¶
FormatHeader renders one PAI row in wire format. Display-names are wrapped in quotes per RFC 3261 (RFC 3325 does not relax the BNF). Use FormatPAIDisplayName from the outbound package if you need MIME encoded-word support for non-ASCII display names; PAI is *operator to operator* and almost always ASCII, so we keep this minimal.