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

client

import "github.com/TheManticoreProject/Manticore/network/dcerpc/v4/client"

Package client implements the client side of the connectionless (datagram) DCE/RPC protocol machine ([C706] chapter 10), layered on a datagram transport (network/dcerpc/v4/transport) and the connectionless PDU codec (network/dcerpc/v4/pdu).

Unlike the connection-oriented client, there is no Bind: a call is established implicitly by the first request PDU, which carries the activity UUID, interface identity, and a per-activity sequence number. The client fragments the request stub into request PDUs, transmits them, and then drives a receive loop that handles the server’s flow-control and status PDUs:

  • fack — flow-control acknowledgement; the client may send more fragments.
  • working — the server is processing the call; the client keeps waiting.
  • nocall — the server has not seen the call; the client retransmits.
  • response— output fragments, reassembled until the lastfrag PDU arrives.
  • fault / reject — the call failed; returned as *FaultError / *RejectError.

When no PDU arrives before the transport timeout, the client retransmits the request fragments (while still awaiting any response) or sends a ping (while awaiting further response fragments), giving up after the configured limits.

NOT YET IMPLEMENTED (documented limitations):

  • The conv callback interface (conv_who_are_you) used for at-most-once verification of non-idempotent calls; mark calls idempotent for now.
  • Windowed burst flow control: all request fragments are sent immediately rather than throttled to the server’s advertised fack window. This is correct for the small, typically single-fragment requests connectionless RPC carries, and the server’s nocall/fack still drive retransmission.
  • Broadcast and maybe (no-response) calls, and client-side cancel.

References:

Index

Constants

Default flow-control limits ([C706] chapter 10: MAX_REQUESTS, MAX_PINGS).

const (
    // DefaultMaxRequests is how many times the request burst is retransmitted before
    // the client gives up waiting for the server to acknowledge the call.
    DefaultMaxRequests = 5
    // DefaultMaxPings is how many pings are sent, while a response is outstanding,
    // before the client gives up.
    DefaultMaxPings = 5
    // DefaultFackWindow is the receive window, in fragments, advertised in the facks
    // the client sends for inbound response fragments.
    DefaultFackWindow = 8
    // DefaultMaxReceives bounds the total number of PDUs a single call will process
    // before giving up. It is a backstop against a server that floods non-terminal
    // PDUs (endless working/fack/ping or PDUs for other conversations), which would
    // otherwise spin the receive loop forever since such PDUs do not trip the
    // retransmission or ping limits. It is set far above any plausible fragment count.
    DefaultMaxReceives = 1 << 20
)

Variables

ErrNoResponse is returned when the server never produces a response within the configured retransmission and ping limits.

var ErrNoResponse = errors.New("dcerpc(cl): no response within retransmission limits")

type CallRequest

CallRequest describes one connectionless RPC call.

type CallRequest struct {
    // Object is the optional object UUID; leave zero for none.
    Object guid.GUID
    // Interface is the interface (abstract syntax) UUID.
    Interface guid.GUID
    // InterfaceVersion is the interface major version (the if_vers field).
    InterfaceVersion uint32
    // OpNum is the operation number within the interface.
    OpNum uint16
    // Stub is the NDR-marshalled input parameters.
    Stub []byte
    // Idempotent marks the call idempotent, allowing safe retransmission without
    // at-most-once verification.
    Idempotent bool
}

type Client

Client drives connectionless calls over a single activity (conversation).

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

func New

func New(t transport.Transport, opts ...Option) *Client

New returns a connectionless client bound to the given datagram transport. Unless WithActivityID is supplied, a fresh random activity UUID is generated.

func (*Client) ActivityID

func (c *Client) ActivityID() guid.GUID

ActivityID returns the activity UUID identifying this client’s conversation.

func (*Client) Call

func (c *Client) Call(req CallRequest) ([]byte, error)

Call performs a single connectionless RPC call and returns the reassembled response stub (the NDR-marshalled output parameters). A server fault or reject is returned as *FaultError or *RejectError.

type FaultError

FaultError reports a fault PDU returned by the server, carrying its status code.

type FaultError struct{ Status uint32 }

func (*FaultError) Error

func (e *FaultError) Error() string

type Option

Option configures a Client.

type Option func(*Client)

func WithActivityID

func WithActivityID(id guid.GUID) Option

WithActivityID sets a fixed activity UUID instead of a random one (useful for tests and for resuming a known conversation).

func WithMaxPings

func WithMaxPings(n int) Option

WithMaxPings overrides the ping limit.

func WithMaxReceives

func WithMaxReceives(n int) Option

WithMaxReceives overrides the per-call cap on the total number of PDUs processed before giving up (the flood backstop).

func WithMaxRequests

func WithMaxRequests(n int) Option

WithMaxRequests overrides the request retransmission limit.

type RejectError

RejectError reports a reject PDU returned by the server, carrying its status code.

type RejectError struct{ Status uint32 }

func (*RejectError) Error

func (e *RejectError) Error() string