Generated from Manticore v1.1.5 • 201 packages. View on pkg.go.dev

ndr

import "github.com/TheManticoreProject/Manticore/network/dcerpc/ndr"

Package ndr implements the DCE/RPC Network Data Representation (NDR) transfer syntax, version 2.0 (the “NDR20” little-endian encoding used by Windows RPC), with a declarative, reflection-driven API for marshalling RPC call structures.

The low-level codec (Encoder/Decoder) handles NDR’s stream-relative alignment and primitive encoding; the reflection walker in marshal.go drives it from struct tags so callers can declare an RPC call as a Go struct (see Call, Marshal, Unmarshal).

The codec is transfer-syntax aware: an Encoder/Decoder carries a Syntax (NDR20 or NDR64) that governs the width and alignment of NDR counts and referent ids (4 octets 4-aligned for NDR20, 8 octets 8-aligned for NDR64; [MS-RPCE] section 2.2.5). Scalar primitives keep their natural width in both syntaxes. The declarative walker (Marshal/Unmarshal) and the v5 client still default to NDR20; the NDR64 path is being introduced incrementally and is reachable through NewEncoderForSyntax/ NewDecoderForSyntax. Both syntaxes are little-endian (the standard Windows data representation, DREP 0x10); big-endian is out of scope.

References:

Index

func Marshal

func Marshal(v any) ([]byte, error)

Marshal encodes v (a struct or pointer to struct) into an NDR octet stream. Each exported field is marshalled in declaration order according to its `ndr:"…"` tag.

Pointers (Go pointer fields, or value fields tagged “unique”/“ptr”) are encoded as a referent id inline with their referent body deferred to the end of the enclosing construction, per the deferral rule in [C706] section 14.3.10: https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm

func MarshalAs

func MarshalAs(v any, syntax Syntax) ([]byte, error)

MarshalAs is Marshal under an explicit transfer syntax. NDR64 widens counts and referent ids to 8 octets and aligns them to 8 ([MS-RPCE] section 2.2.5). NDR64 unions and pipes are not yet supported and marshalling a value that contains one returns an error rather than emitting an unverified encoding.

func Request

func Request(call Call) ([]byte, error)

Request marshals an RPC call’s [in] parameters into a stub buffer suitable for network/dcerpc/client.Client.Call(call.Opnum(), stub).

func RequestAs

func RequestAs(call Call, syntax Syntax) ([]byte, error)

RequestAs is Request under an explicit transfer syntax, used by a client that has negotiated NDR64 ([MS-RPCE] section 2.2.5).

func Response

func Response(stub []byte, out any) error

Response unmarshals an RPC response stub into out (a pointer to the [out] parameter structure).

func ResponseAs

func ResponseAs(stub []byte, out any, syntax Syntax) error

ResponseAs is Response under an explicit transfer syntax.

func Unmarshal

func Unmarshal(data []byte, v any) error

Unmarshal decodes an NDR octet stream into v, which must be a non-nil pointer to a struct.

func UnmarshalAs

func UnmarshalAs(data []byte, v any, syntax Syntax) error

UnmarshalAs is Unmarshal under an explicit transfer syntax. See MarshalAs for the NDR64 semantics and the union/pipe limitation.

type BOOL

BOOL is the Windows BOOL data type, a 4-octet integer ([MS-DTYP] 2.2.3). It is distinct from the 1-octet NDR boolean: for the latter, use Go bool (or BOOLEAN).

type BOOL = int32

type BOOLEAN

BOOLEAN is the 1-octet NDR boolean ([C706] section 14.2.4).

type BOOLEAN = bool

type BYTE

Windows-style NDR type aliases, mirroring the names used in [MS-DTYP] so declarations read like the IDL. References:

type BYTE = uint8

type Call

Call is implemented by a request structure to provide its operation number. Its exported fields are the [in] parameters, marshalled in declaration order.

type Call interface {
    Opnum() uint16
}

type DWORD

Windows-style NDR type aliases, mirroring the names used in [MS-DTYP] so declarations read like the IDL. References:

type DWORD = uint32

type DWORD64

Windows-style NDR type aliases, mirroring the names used in [MS-DTYP] so declarations read like the IDL. References:

type DWORD64 = uint64

type Decoder

Decoder reads an NDR octet stream produced under the little-endian data representation.

type Decoder struct {
    // contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(data []byte) *Decoder

NewDecoder returns a decoder over data for the NDR20 transfer syntax.

func NewDecoderForSyntax

func NewDecoderForSyntax(data []byte, s Syntax) *Decoder

NewDecoderForSyntax returns a decoder over data for the given transfer syntax.

func (*Decoder) Align

func (d *Decoder) Align(n int)

Align advances the read position to the next multiple of n.

func (*Decoder) Pos

func (d *Decoder) Pos() int

Pos returns the current read offset.

func (*Decoder) ReadBytes

func (d *Decoder) ReadBytes(n int) ([]byte, error)

ReadBytes returns the next n octets.

func (*Decoder) ReadUint16

func (d *Decoder) ReadUint16() (uint16, error)

ReadUint16 reads a 2-octet little-endian value, 2-aligned.

func (*Decoder) ReadUint32

func (d *Decoder) ReadUint32() (uint32, error)

ReadUint32 reads a 4-octet little-endian value, 4-aligned.

func (*Decoder) ReadUint64

func (d *Decoder) ReadUint64() (uint64, error)

ReadUint64 reads an 8-octet little-endian value, 8-aligned.

func (*Decoder) ReadUint8

func (d *Decoder) ReadUint8() (uint8, error)

ReadUint8 reads a 1-octet value.

func (*Decoder) Remaining

func (d *Decoder) Remaining() int

Remaining returns the number of unread octets.

func (*Decoder) Syntax

func (d *Decoder) Syntax() Syntax

Syntax reports the transfer syntax the decoder operates under.

type Encoder

Encoder builds an NDR octet stream. Alignment is computed relative to the start of the stream, as required by [C706] section 14.2.2.

type Encoder struct {
    // contains filtered or unexported fields
}

func NewEncoder

func NewEncoder() *Encoder

NewEncoder returns an empty encoder for the NDR20 transfer syntax.

func NewEncoderForSyntax

func NewEncoderForSyntax(s Syntax) *Encoder

NewEncoderForSyntax returns an empty encoder for the given transfer syntax.

func (*Encoder) Align

func (e *Encoder) Align(n int)

Align pads the stream with zero octets so the next write begins on a multiple of n.

func (*Encoder) Bytes

func (e *Encoder) Bytes() []byte

Bytes returns the accumulated octet stream.

func (*Encoder) Len

func (e *Encoder) Len() int

Len returns the current stream length, which is the offset alignment is measured against.

func (*Encoder) Syntax

func (e *Encoder) Syntax() Syntax

Syntax reports the transfer syntax the encoder operates under.

func (*Encoder) WriteBytes

func (e *Encoder) WriteBytes(b []byte)

WriteBytes appends raw octets with no alignment.

func (*Encoder) WriteUint16

func (e *Encoder) WriteUint16(v uint16)

WriteUint16 appends a 2-octet little-endian value, 2-aligned.

func (*Encoder) WriteUint32

func (e *Encoder) WriteUint32(v uint32)

WriteUint32 appends a 4-octet little-endian value, 4-aligned.

func (*Encoder) WriteUint64

func (e *Encoder) WriteUint64(v uint64)

WriteUint64 appends an 8-octet little-endian value, 8-aligned.

func (*Encoder) WriteUint8

func (e *Encoder) WriteUint8(v uint8)

WriteUint8 appends a 1-octet value.

type Invoker

Invoker executes an RPC call: it marshals in (an ndr.Call) to a request stub, transmits it on opnum in.Opnum(), and unmarshals the response stub into out. It is the transport-version-neutral surface that interface method stubs depend on, so the stubs stay independent of any concrete client or wire-protocol version. Both the connection-oriented (network/dcerpc/v5/client) and, in future, connectionless (network/dcerpc/v4) DCE/RPC clients satisfy it.

type Invoker interface {
    Invoke(in Call, out any) error
}

type LONG

Windows-style NDR type aliases, mirroring the names used in [MS-DTYP] so declarations read like the IDL. References:

type LONG = int32

type Marshaler

Marshaler is implemented by types that encode themselves as NDR, bypassing the reflection walker. It is the escape hatch for unions and any layout the declarative tags do not cover.

type Marshaler interface {
    // AlignmentNDR reports the type's NDR alignment (1, 2, 4, or 8).
    AlignmentNDR() int
    // MarshalNDR appends the type's NDR representation to the encoder.
    MarshalNDR(*Encoder) error
    // UnmarshalNDR reads the type's NDR representation from the decoder.
    UnmarshalNDR(*Decoder) error
}

type STR

STR is a char string ([string]). A field of this type marshals as a conformant+varying ASCII array. See WSTR for pointer semantics.

type STR string

type Syntax

Syntax selects the NDR transfer syntax an Encoder/Decoder operates under. It governs the on-the-wire width and alignment of NDR counts (maximum_count, offset, actual_count) and referent ids, which differ between the two syntaxes ([MS-RPCE] section 2.2.5). NDR20 is the zero value, so an Encoder/Decoder built without an explicit syntax behaves as the classic NDR 2.0 codec.

type Syntax int
const (
    // NDR20 is NDR transfer syntax version 2.0: 4-octet counts and referent ids.
    NDR20 Syntax = iota
    // NDR64 is the NDR64 transfer syntax: 8-octet counts and referent ids.
    NDR64
)

func (Syntax) String

func (s Syntax) String() string

String returns the syntax name for diagnostics.

type WORD

Windows-style NDR type aliases, mirroring the names used in [MS-DTYP] so declarations read like the IDL. References:

type WORD = uint16

type WSTR

WSTR is a wchar_t string ([string] wide). A field of this type marshals as a conformant+varying UTF-16LE array without needing an explicit “wstr” tag.

Pointer semantics are explicit and controlled by the tag: a bare WSTR/STR/string field is encoded inline with no referent id (matching a top-level [ref] string parameter), while one tagged “unique” or “ptr” is encoded as a referent id with its body deferred (matching an embedded [unique,string] wchar_t*). Embedded strings in MS-RPC structures are almost always unique; tag them accordingly.

type WSTR string