pdu
import "github.com/TheManticoreProject/Manticore/network/dcerpc/v5/pdu"
Package pdu models connection-oriented DCE/RPC protocol data units (PDUs): the 16-byte common header and the Bind, Bind_Ack, Bind_Nak, Request, Response, and Fault bodies ([C706] section 12, [MS-RPCE] section 2.2).
Each PDU type embeds the common Header and represents a whole PDU. Marshal returns the complete on-the-wire bytes (header included) and sets the header’s frag_length; Unmarshal parses a complete PDU and returns the number of bytes consumed.
Only the little-endian data representation (DREP first byte 0x10) is supported, which is what Windows and Samba always send; a big-endian DREP is rejected on Unmarshal rather than silently mis-parsed.
Index
- Constants
- Variables
- type Auth3
- type Bind
- type BindAck
- type BindNak
- type ContextElement
- type Fault
- type FaultStatus
- type Header
- type PFCFlags
- type PacketType
- type PresentationResult
- type ProtocolVersion
- type Request
- type Response
- type SecTrailer
Constants
Presentation context negotiation result codes (p_cont_def_result_t), as returned in the result field of each p_result_t in a bind_ack PDU.
References:
- [C706] section 12.6.3.1 (“The bind_ack PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.4 Presentation Context and Transfer Syntax Negotiation: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/ca4d3552-4647-4f40-830b-fd2090adec8f
- [MS-RPCE] negotiate_ack member of p_cont_def_result_t: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/8df5c4d4-364d-468c-81fe-ec94c1b40917
const (
ResultAcceptance uint16 = 0
ResultUserRejection uint16 = 1
ResultProviderRejection uint16 = 2
ResultNegotiateAck uint16 = 3 // [MS-RPCE] bind-time feature negotiation
)
Provider reject reasons (p_provider_reason_t / p_reject_reason_t).
Reference: [C706] section 12.6.3.1: https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
const (
ReasonNotSpecified uint16 = 0
ReasonAbstractSyntaxNotSupported uint16 = 1
ReasonProposedTransferSyntaxesNotSupported uint16 = 2
ReasonLocalLimitExceeded uint16 = 3
)
Common connection-oriented RPC fault status codes (nca_* / rpc_s_*). This is a subset; unknown codes are reported numerically by FaultStatus.String.
References:
- [C706] section 12.6.3.1 (“The fault PDU”) and Appendix E (reject status codes): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.5 Fault PDU: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/55c10f44-9037-4d51-aaff-c146bd0f1988
const (
NCASStatusOK uint32 = 0x00000000
NCASOpRngError uint32 = 0x1C010002 // nca_s_op_rng_error: invalid opnum
NCASUnkIf uint32 = 0x1C010003 // nca_s_unk_if: unknown interface
NCASProtoError uint32 = 0x1C01000B // nca_s_proto_error
NCASFaultIntDivByZero uint32 = 0x1C000001 // nca_s_fault_int_div_by_zero
NCASFaultAddrError uint32 = 0x1C000002 // nca_s_fault_addr_error
NCASFaultNDR uint32 = 0x000006F7 // nca_s_fault_ndr: NDR could not decode
NCASFaultAccessDenied uint32 = 0x00000005 // nca_s_fault_access_denied
NCASFaultContextMismatch uint32 = 0x1C00001A // nca_s_fault_context_mismatch
)
Authentication service identifiers (auth_type), as carried in the sec_trailer of an authenticated PDU.
Reference: [MS-RPCE] 2.2.1.1.7 Security Providers: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/d4097450-c62f-484b-872f-ddf59a7a0d36
const (
AuthTypeNone uint8 = 0x00
AuthTypeGSSNegotiate uint8 = 0x09 // SPNEGO
AuthTypeNTLMSSP uint8 = 0x0A // RPC_C_AUTHN_WINNT
AuthTypeGSSSchannel uint8 = 0x0E // RPC_C_AUTHN_GSS_SCHANNEL
AuthTypeGSSKerberos uint8 = 0x10
AuthTypeNetlogon uint8 = 0x44 // RPC_C_AUTHN_NETLOGON
// AuthTypeDefault selects the implementation default provider; it is an SSPI
// selector value, not a value that appears in a sec_trailer on the wire.
AuthTypeDefault uint8 = 0xFF // RPC_C_AUTHN_DEFAULT
)
Authentication levels (auth_level), as carried in the sec_trailer. Higher levels subsume the protection of lower ones.
Reference: [MS-RPCE] 2.2.1.1.8 Authentication Levels: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/425a7c53-c33a-4868-8e5b-2a850d40dc73
const (
AuthLevelDefault uint8 = 0x00
AuthLevelNone uint8 = 0x01
AuthLevelConnect uint8 = 0x02
AuthLevelCall uint8 = 0x03
AuthLevelPkt uint8 = 0x04
AuthLevelPktIntegrity uint8 = 0x05
AuthLevelPktPrivacy uint8 = 0x06
)
HeaderSize is the size, in bytes, of the connection-oriented common header.
const HeaderSize = 16
SecTrailerSize is the size, in bytes, of the sec_trailer (auth_verifier_co_t) header that precedes the auth_value in an authenticated PDU.
const SecTrailerSize = 8
Variables
DataRepresentationLittleEndian is the canonical packed_drep for little-endian integers, ASCII characters, and IEEE floating point.
var DataRepresentationLittleEndian = [4]byte{0x10, 0x00, 0x00, 0x00}
type Auth3
Auth3 is an rpc_auth_3 PDU: the optional third leg of an authenticated bind. After a bind that carried an authentication token and a bind_ack that returned the security provider’s challenge, the client sends an auth3 carrying the final token (for NTLM, the AUTHENTICATE message) to complete the exchange. The server sends no reply.
The PDU is the common header, a 4-byte pad (a vestigial max_xmit_frag/max_recv_frag that the server ignores), then the sec_trailer and the auth_value. The header’s auth_length counts only AuthValue.
References:
- [C706] section 12.6.4.2 (“The rpc_auth_3 PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.10 PDU Types: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/cef9d684-f09f-4533-a54c-9255079d3e1d
type Auth3 struct {
Header Header
SecTrailer SecTrailer
AuthValue []byte
}
func (*Auth3) Marshal
func (a *Auth3) Marshal() ([]byte, error)
Marshal serializes the complete auth3 PDU, filling in the header’s packet type, frag_length, and auth_length.
func (*Auth3) Unmarshal
func (a *Auth3) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete auth3 PDU and returns the bytes consumed.
type Bind
Bind is a bind PDU: it proposes the maximum fragment sizes, an association group, and a list of presentation contexts to negotiate.
References:
- [C706] section 12.6.3.1 (“The bind PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.4 Presentation Context and Transfer Syntax Negotiation: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/ca4d3552-4647-4f40-830b-fd2090adec8f
type Bind struct {
Header Header
MaxXmitFrag uint16
MaxRecvFrag uint16
AssocGroupID uint32
ContextList []ContextElement
// SecTrailer and AuthValue carry an optional authentication verifier. When
// AuthValue is non-empty, Marshal pads the body to a 4-byte boundary, appends the
// sec_trailer and the auth_value (e.g. an NTLM NEGOTIATE token), and sets the
// header's auth_length. They are nil/empty for an unauthenticated bind.
SecTrailer SecTrailer
AuthValue []byte
}
func (*Bind) Marshal
func (b *Bind) Marshal() ([]byte, error)
Marshal serializes the complete bind PDU, filling in the header’s packet type, frag_length, and — when an auth_value is present — auth_length.
func (*Bind) String
func (b *Bind) String() string
String returns a one-line summary.
func (*Bind) Unmarshal
func (b *Bind) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete bind PDU and returns the bytes consumed.
type BindAck
BindAck is a bind_ack PDU: the server’s response to a bind, echoing the negotiated fragment sizes and reporting per-context negotiation results.
References:
- [C706] section 12.6.3.1 (“The bind_ack PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.4 Presentation Context and Transfer Syntax Negotiation: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/ca4d3552-4647-4f40-830b-fd2090adec8f
type BindAck struct {
Header Header
MaxXmitFrag uint16
MaxRecvFrag uint16
AssocGroupID uint32
SecondaryAddress string // port_spec, without the trailing NUL
Results []PresentationResult
}
func (*BindAck) Accepted
func (b *BindAck) Accepted() bool
Accepted reports whether at least one presentation context was accepted.
func (*BindAck) Marshal
func (b *BindAck) Marshal() ([]byte, error)
Marshal serializes the complete bind_ack PDU, including the 4-byte alignment pad after the secondary address.
func (*BindAck) String
func (b *BindAck) String() string
String returns a one-line summary.
func (*BindAck) Unmarshal
func (b *BindAck) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete bind_ack PDU and returns the bytes consumed.
type BindNak
BindNak is a bind_nak PDU: the server’s rejection of a bind, with a reason and the list of RPC protocol versions it supports.
Reference: [C706] section 12.6.3.1 (“The bind_nak PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
type BindNak struct {
Header Header
RejectReason uint16
Versions []ProtocolVersion
}
func (*BindNak) Marshal
func (b *BindNak) Marshal() ([]byte, error)
Marshal serializes the complete bind_nak PDU.
func (*BindNak) String
func (b *BindNak) String() string
String returns a one-line summary.
func (*BindNak) Unmarshal
func (b *BindNak) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete bind_nak PDU and returns the bytes consumed.
type ContextElement
ContextElement is a single presentation context proposed in a bind (or alter_context) PDU: a context id, an abstract syntax (the target interface), and one or more candidate transfer syntaxes (p_cont_elem_t).
References:
- [C706] section 12.6.3.1 (“The bind PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.4 Presentation Context and Transfer Syntax Negotiation: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/ca4d3552-4647-4f40-830b-fd2090adec8f
type ContextElement struct {
ContextID uint16
AbstractSyntax syntax.SyntaxID
TransferSyntaxes []syntax.SyntaxID
}
func (*ContextElement) Marshal
func (c *ContextElement) Marshal() ([]byte, error)
Marshal serializes a presentation context element.
func (*ContextElement) Unmarshal
func (c *ContextElement) Unmarshal(data []byte) (int, error)
Unmarshal parses a presentation context element and returns the bytes consumed.
type Fault
Fault is a fault PDU: it reports that a call failed, carrying a status code and any error stub data.
References:
- [C706] section 12.6.3.1 (“The fault PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.5 Fault PDU: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/55c10f44-9037-4d51-aaff-c146bd0f1988
type Fault struct {
Header Header
AllocHint uint32
ContextID uint16
CancelCount uint8
Status uint32
Stub []byte
}
func (*Fault) Error
func (f *Fault) Error() string
Error implements the error interface so a Fault can be returned directly from a call. The message includes the mnemonic status code.
func (*Fault) Marshal
func (f *Fault) Marshal() ([]byte, error)
Marshal serializes the complete fault PDU.
func (*Fault) String
func (f *Fault) String() string
String returns a one-line summary.
func (*Fault) Unmarshal
func (f *Fault) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete fault PDU and returns the bytes consumed.
type FaultStatus
FaultStatus is a fault PDU status code, with a descriptive String.
type FaultStatus uint32
func (FaultStatus) String
func (s FaultStatus) String() string
String returns a mnemonic for known status codes, otherwise the hex value.
type Header
Header is the connection-oriented common header present at the start of every PDU.
References:
- [C706] section 12.6.3.1 (common fields of the connection-oriented PDU): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.10 PDU Types: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/cef9d684-f09f-4533-a54c-9255079d3e1d
type Header struct {
RPCVersion uint8
RPCVersionMinor uint8
PacketType PacketType
PacketFlags PFCFlags
DataRepresentation [4]byte
FragLength uint16
AuthLength uint16
CallID uint32
}
func NewHeader
func NewHeader(pt PacketType, flags PFCFlags, callID uint32) Header
NewHeader returns a header initialized for protocol version 5.0 with little-endian data representation and the given packet type, flags, and call id.
func PeekHeader
func PeekHeader(data []byte) (*Header, error)
PeekHeader parses just the common header from the front of a complete PDU buffer. It is a convenience for dispatching on PacketType before fully unmarshalling.
func (*Header) Marshal
func (h *Header) Marshal() ([]byte, error)
Marshal serializes the header into its 16-byte wire form.
func (*Header) String
func (h *Header) String() string
String returns a human-readable one-line summary of the header.
func (*Header) Unmarshal
func (h *Header) Unmarshal(data []byte) (int, error)
Unmarshal parses a header from the start of data and returns the bytes consumed (always HeaderSize on success).
type PFCFlags
PFCFlags is the set of PFC_* flags carried in the pfc_flags field of the common header.
References:
- [C706] section 12.6.3.1 (pfc_flags): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.3 PFC_SUPPORT_HEADER_SIGN and related flags: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/4886f349-2a73-4f9e-9262-a8404462c7e9
type PFCFlags uint8
const (
// PFCFirstFrag marks the first fragment of a multi-fragment PDU.
PFCFirstFrag PFCFlags = 0x01
// PFCLastFrag marks the last fragment of a multi-fragment PDU.
PFCLastFrag PFCFlags = 0x02
// PFCPendingCancel signals a pending cancel (request) or a cancel was pending
// (response).
PFCPendingCancel PFCFlags = 0x04
// PFCReserved is reserved.
PFCReserved PFCFlags = 0x08
// PFCConcMpx indicates support for concurrent multiplexing on the connection.
PFCConcMpx PFCFlags = 0x10
// PFCDidNotExecute indicates the server did not execute the call (response/fault).
PFCDidNotExecute PFCFlags = 0x20
// PFCMaybe indicates a "maybe" call with no response expected.
PFCMaybe PFCFlags = 0x40
// PFCObjectUuid indicates an object UUID is present in the PDU body.
PFCObjectUuid PFCFlags = 0x80
)
func (PFCFlags) Has
func (f PFCFlags) Has(flag PFCFlags) bool
Has reports whether all bits in flag are set.
func (PFCFlags) String
func (f PFCFlags) String() string
String returns a “|”-joined list of set flag names.
type PacketType
PacketType identifies the kind of a connection-oriented DCE/RPC PDU, as carried in the ptype field of the common header.
References:
- [C706] section 12.6.4 (PDU types): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
- [MS-RPCE] 2.2.2.10 PDU Types: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/cef9d684-f09f-4533-a54c-9255079d3e1d
type PacketType uint8
const (
PacketTypeRequest PacketType = 0
PacketTypePing PacketType = 1
PacketTypeResponse PacketType = 2
PacketTypeFault PacketType = 3
PacketTypeWorking PacketType = 4
PacketTypeNoCall PacketType = 5
PacketTypeReject PacketType = 6
PacketTypeAck PacketType = 7
PacketTypeClCancel PacketType = 8
PacketTypeFack PacketType = 9
PacketTypeCancelAck PacketType = 10
PacketTypeBind PacketType = 11
PacketTypeBindAck PacketType = 12
PacketTypeBindNak PacketType = 13
PacketTypeAlterContext PacketType = 14
PacketTypeAlterContextResp PacketType = 15
PacketTypeAuth3 PacketType = 16
PacketTypeShutdown PacketType = 17
PacketTypeCoCancel PacketType = 18
PacketTypeOrphaned PacketType = 19
)
func (PacketType) String
func (t PacketType) String() string
String returns the mnemonic name of the packet type.
type PresentationResult
PresentationResult is one server response in a bind_ack p_result_list (p_result_t): the negotiation result, an optional reason, and the accepted transfer syntax.
Reference: [C706] section 12.6.3.1 (“The bind_ack PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
type PresentationResult struct {
Result uint16
Reason uint16
TransferSyntax syntax.SyntaxID
}
func (*PresentationResult) Marshal
func (r *PresentationResult) Marshal() ([]byte, error)
Marshal serializes a single presentation result (24 bytes).
func (*PresentationResult) Unmarshal
func (r *PresentationResult) Unmarshal(data []byte) (int, error)
Unmarshal parses a single presentation result and returns the bytes consumed.
type ProtocolVersion
ProtocolVersion is one supported RPC protocol version (p_rt_version_t).
type ProtocolVersion struct {
Major uint8
Minor uint8
}
type Request
Request is a request PDU: it carries a method call (opnum) and its marshalled arguments (stub data) to the server.
When the PFC_OBJECT_UUID flag is set, a 16-byte object UUID precedes the stub data; otherwise it is absent. Stub data is 8-octet aligned, which the fixed 8-byte body (plus an optional 16-byte object UUID) already satisfies.
Reference: [C706] section 12.6.3.1 (“The request PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
type Request struct {
Header Header
AllocHint uint32
ContextID uint16
Opnum uint16
ObjectUUID *guid.GUID // present iff PFC_OBJECT_UUID is set
Stub []byte
}
func (*Request) Marshal
func (r *Request) Marshal() ([]byte, error)
Marshal serializes the complete request PDU. If ObjectUUID is non-nil the PFC_OBJECT_UUID flag is set automatically. AllocHint defaults to len(Stub) when left zero.
func (*Request) String
func (r *Request) String() string
String returns a one-line summary.
func (*Request) Unmarshal
func (r *Request) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete request PDU and returns the bytes consumed.
type Response
Response is a response PDU: it carries the marshalled return values (stub data) of a successful call back to the client.
Reference: [C706] section 12.6.3.1 (“The response PDU”): https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm
type Response struct {
Header Header
AllocHint uint32
ContextID uint16
CancelCount uint8
Stub []byte
}
func (*Response) Marshal
func (r *Response) Marshal() ([]byte, error)
Marshal serializes the complete response PDU.
func (*Response) String
func (r *Response) String() string
String returns a one-line summary.
func (*Response) Unmarshal
func (r *Response) Unmarshal(data []byte) (int, error)
Unmarshal parses a complete response PDU and returns the bytes consumed.
type SecTrailer
SecTrailer is the fixed 8-byte security trailer (auth_verifier_co_t) that sits between a PDU’s body and its authentication token (auth_value). The header’s auth_length counts only the auth_value that follows this trailer, not the trailer itself.
References:
- [C706] section 13.2.6.1 (the connection-oriented authentication verifier): https://pubs.opengroup.org/onlinepubs/9629399/chap13.htm
- [MS-RPCE] 2.2.2.11 auth_verifier_co (sec_trailer): https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/c0fe71f3-0fd1-4a0d-aa3f-b6a36e3fbe81
type SecTrailer struct {
AuthType uint8 // security provider (auth_type)
AuthLevel uint8 // protection level (auth_level)
AuthPadLength uint8 // bytes of padding inserted before the trailer to 4-byte-align it
AuthReserved uint8 // must be zero
AuthContextID uint32 // identifies the security context within the connection
}
func ExtractAuthVerifier
func ExtractAuthVerifier(raw []byte) (*SecTrailer, []byte, error)
ExtractAuthVerifier returns the sec_trailer and auth_value from the tail of a complete PDU, located using the common header’s auth_length: the last auth_length bytes are the auth_value, preceded by the 8-byte sec_trailer. It returns nil, nil when the PDU carries no authentication verifier (auth_length == 0).
func (*SecTrailer) Marshal
func (s *SecTrailer) Marshal() []byte
Marshal serializes the 8-byte sec_trailer.
func (*SecTrailer) Unmarshal
func (s *SecTrailer) Unmarshal(data []byte) error
Unmarshal parses an 8-byte sec_trailer from the front of data.