dcerpc

package
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2024 License: MIT Imports: 25 Imported by: 1

Documentation

Overview

Package dcerpc implements the DCE/RPC (C706) client with MS-RPCE extensions.

Manual

The package is used by the generated stub/client code, so any examples make sense only within the scope of using generated clients.

One of the key concepts in DCE/RPC is interface. Interface is just set of endopints serving certain logical purpose that are handled by server.

From client perspective, interface is represented by presentation context. Presentation context is simply a Interface ID (Syntax UUID) and Interface Version (Syntax Version) and client-generated unique integer identifier. Syntax UUID and Syntax Version are also called as Abstract Sytnax.

When we call NewXXXClient on the connection, generated stub code provides the abstract syntax as an option, and then performs the Bind request, which creates new Presentation Context (Abstract Syntax + unique identifier) and associates it with particular endpoint to which we are connecting.

Endpoint can be either the named pipe name on the IPC$ share, or the TCP/IP port.

So, Presentation Context and Endpoint make up a client connection.

Let's begin with simpliest program that connects to EPM and lists all the endpoints registered on the server:

import (
	"fmt"

	"github.com/oiweiwei/go-msrpc/dcerpc"

	"github.com/oiweiwei/go-msrpc/epm/epm/v3"
)

func main() {

	// create a new connection to the server my-server.com.
	// note, that no actual connection will be created, since we don't
	// know at this point, to which port and protocol we should connect.
	conn, err := dcerpc.Dial(context.TODO(), "my-server.com")
	if err != nil {
		// exit.
	}

	// close the connection (and all opened transports).
	defer conn.Close(context.TODO())

	// establish connection to the epm client, port 135.
	// internally, all stubs add WithAbstractSyntax option when establishing the connection.
	cli, err := epm.NewClient(ctx, conn, dcerpc.WithInsecure(), dcerpc.WithEndpoint(":135"))
	if err != nil {
		// exit.
	}

	// execute lookup request remote procedure call.
	resp, err := cli.Lookup(context.TODO(), &epm.LookupRequest{MaxEntries: 500})
	if err != nil {
		// exit.
	}

	// print results.
	for i, entries := range resp.Entries {
		fmt.Printf("[%d] %s \n", i, entries.Tower.Binding().StringBinding)
	}
}

Security

The example above doesn't use any security, which is often not true for the real world applications.

DCE/RPC provides multiple ways to configure the security level:

* Insecure: no security.

* Packet (not used).

* Connect: establish context but do not provide integrity/confidentiality services.

* Sign: integrity.

* Seal: confidentiality.

In order to establish the security context, first that we need to do is provision the SSP packages and credentials. This can be done in two ways. First, provision via global settings.

import (
	"github.com/oiweiwei/go-msrpc/ssp"
	"github.com/oiweiwei/go-msrpc/ssp/credential"
	"github.com/oiweiwei/go-msrpc/ssp/gssapi"
)

func init() {
	// This way we add the credentials from the password.
	gssapi.AddCredential(credential.NewFromPassword(os.Getenv("USERNAME"), os.Getenv("PASSWORD")))
	// This way we provision the security package.
	gssapi.AddMechanism(ssp.NTLM)
}

func main() {

	// ...

	// create new security context.
	ctx = gssapi.NewSecurityContext(ctx)

	// We use credentials to establish the NTLM security for Singing the requests/responses.
	cli, err := epm.NewClient(ctx, conn, dcerpc.WithSign(), dcerpc.WithEndpoint(":135"))

	// ...
}

Second, we can provision packages directly when creating the connection.

cli, err := epm.NewClient(ctx, conn,
	dcerpc.WithCredential(creds),
	// only top-level mechanism is used, when this mechanism is SPNEGO, it will
	// combine all the mechanisms and will perform the negotiation with server.
	dcerpc.WithMechanism(ssp.SPNEGO),
	dcerpc.WithMechanism(ssp.KRB5),
	dcerpc.WithMechanism(ssp.NTLM),
	dcerpc.WithSeal(),
	dcerpc.WithEndpoint(":135"))

Or by combination of both approaches (specify mechanisms globally, and credentials locally and so on).

ctx := gssapi.NewSecurityContext(ctx, ssp.NTLM)

cli, err := epm.NewClient(ctx, conn, dcerpc.WithCredential(creds), ...)

Security context can be altered by client:

cli.AlterContext(ctx, dcerpc.WithMechanism(ssp.KRB5), dcerpc.WithSeal())

## Security Context Use-Cases

As you may have noticed, the security can be configured on many levels, so to summarize following is a set of use-cases and proposed approach:

### Global Configuration

Use init function to establish the mechanism / credentials once and for all connections:

func init() {
	gssapi.AddCredential(credential.NewFromPassword(os.Getenv("USERNAME"), os.Getenv("PASSWORD")))
	gssapi.AddMechanism(ssp.NTLM)
}

Note, that you cannot add mechanism to the global configuration more than once, as it is not allowed by GSSAPI package. If you want to have a freedom of choice for the configuration, use dcerpc.WithMechanism per-client options, or NewSecurityContext's gssapi.Option for Reusable Configuration scenario.

### Reusable Configuration

When you're creating multiple clients over the same endpoint (same named pipe, or TCP port) it may be desired to not establish a new security context every time you instantinate the client.

To achieve this, you can define credentials / SSP mechanisms per security context:

ctx := gssapi.NewSecurityContext(ctx, ssp.NTLM, yourCreds)

cli1, err := epm.NewEpmClient(
	ctx, // this context contains NTLM SSP and yourCreds
	dcerpc.WithSign(), // MUST specify for the initial context establishment.
	dcerpc.WithEndpoint(":135"))

cli2, err := iobjectexporter.NewObjectExporterClient(
	ctx, // this contains already established context.
	// dcerpc.WithSign(): DON'T specify it, as you are going to use same TCP connection / and context.
	dcerpc.WithEndpoint(":135"))

As an effect, both cli1 and cli2 will use same security context identifier.

Per-Client Configuration

When you wish for each client to have different security context / credentials / mechanism you should use dcerpc.WithMechanism and dcerpc.WithCredential:

cli, err := epm.NewClient(ctx, conn,
	dcerpc.WithMechanism(ssp.NTLM),
	dcerpc.WithCredential(creds),
	dcerpc.WithSeal(),
	dcerpc.WithEndpoint(":135"))

## Kerberos

Kerberos uses several environment variables, KRB5_CONFIG to specify the path to the kerberos 5 config file, and KRB5_CCACHE for credentials cache path.

The following kerberos configuration should be sufficient to connect to the MSAD KDC:

[realms]
CONTOSO.NET = {
	kdc = win2019-0-1.contoso.net
	admin_server = win2019-0-1.contoso.net
}

[libdefaults]
default_realm = CONTOSO.NET
default_tkt_enctypes = rc4-hmac # or aes128-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96
default_tgs_enctypes = rc4-hmac # or aes128-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96

To acquire the credentials cache you must perform kinit:

$ KRB5_CONFIG=path/to/config.conf kinit <Username> -c /path/to/output.ccache
> Password for <Username>@<Domain>:

The cache can be used via environment variable:

$ export KRB5_CCACHE=/path/to/output.ccache ./your-dcerpc-prog

Note that kerberos requires valid service principal name, like "host/my-server.com".

Verification

MS-RPCE provides a feature to include unprotected header parts into the request payload and hence add integrity check for them when header signing is not supported.

Use WithVerifyBitMask, WithVerifyHeader2, WithVerifyPresentation options in order to include verification trailer to the request.

cli, err := epm.NewClient(ctx, conn,
	// ... other opts ...
	dcerpc.WithVerifyBitMask(true), // required verification
	dcerpc.WithVerifyPresentation(false), // optional verification
	dcerpc.WithEndpoint(":135"))

String Binding

String binding is a special syntax used by DCE/RPC (MS-RPCE) to describe the ways to locate the interface.

The string binding syntax is following:

[ 'ObjectUUID' '@' ] ProtocolSequence ':' NetworkAddress '[' Endpoint ']'

For example:

"ncacn_ip_tcp:[135]" // TCP/IP on Port 135.
"ncacn_np:WIN2019[winreg]" // Named Pipe "winreg" over SMB IPC$ share, WIN2019 is a NetBIOS name.

Endpont Mapping

Endpoint mapper is not only the service of its own, but also a core component in DCE/RPC architecture. The endpoint mapper interface (EPM) is used to determine the endpoints (port or named pipes) that are used by interfaces.

Some endpoints are so-called well-known endpoint, that is, they are always the same for any system, for example, EPM itself has a well-known endpoint ncacn_ip_tcp:[135], and ncacn_np:[epmapper].

You can use the well_known endpoint mapper like following:

import "github.com/oiweiwei/go-msrpc/well_known"

// most of the well-known endpoints are SMB endpoints.
// (note that SMB will perform significantly slower).
conn, err := dcerpc.Dial(ctx, "my-server.com", well_known.EndpointMapper())

But most of the endpoints are dynamic, like DNSServer, DHCPServer, Eventlog TCP/IP endpoints. To locate them Endpoint mapper must be used:

import "github.com/oiweiwei/go-msrpc/epm/epm/v3"

// specify EPMv3 endpoint mapper, it will use well_known.EndpointMapper()
// internally to determine it's own address, by you can also force
// it to use SMB by replacing "my-server.com" with "ncacn_np:my-server.com[epmapper]"
// or passing dcerpc.WithEndpoint("ncacn_np:[epmapper]") as an option.
conn, err := dcerpc.Dial(ctx, "my-server.com", epm.EndpointMapper(ctx, "my-server.com", dcerpc.WithSeal()))

Error Handling

The "github.com/oiweiwei/go-msrpc/msrpc/erref" package contains the error handlers for the list of known errors. If you will import any of the packages inside it, any error in `Return` will be automatically matched and converted to human-readable strings.

// importing win32 errors will convert the error codes into human-readable errors.
// go run examples/rrp.go # with erorr
// key enumerate: query_info: dcerpc: invoke: /winreg/v1/BaseRegQueryInfoKey: response: decode packet: win32: RPC_X_BAD_STUB_DATA (0x000006f7): The stub received bad data.
// go run examples/rrp.go # without error
// key enumerate: query_info: dcerpc: invoke: /winreg/v1/BaseRegQueryInfoKey: response: decode packet: error: code: 0x000006f7
import _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"

SMB Performance

Note that using SMB may slow-down the performance, since every request write and response read are dedicated SMB Write and SMB Read calls. To improve the performance, SMB transaction support must be implemented.

Also note, that the only working security scenario for SMB is WithInsecure and WithSeal, where second will also slow-down the performace.

Examples

See github.com/oiweiwei/go-msrpc/examples for more examples.

Index

Constants

View Source
const (
	RequestSize    = HeaderSize + 8
	ObjectUUIDSize = 16
)
View Source
const (
	// Even number of legs.
	LegsEven = 2
	// Odd number of legs.
	LegsOdd = 3
	// Unknown.
	LegsUnknown = 0
)
View Source
const (

	// The client is anonymous to the server. The server process
	// can impersonate the client, but the impersonation token does
	// not contain any information about the client. This level is
	// only supported over the local interprocess communication transport.
	// All other transports silently promote this level to identify.
	ImpersonationLevelAnonymous = 1

	// The system default level. The server can obtain the client's
	// identity, and the server can impersonate the client to do ACL
	// checks.
	ImpersonationLevelIdentify = 2

	// The server can impersonate the client's security context while
	// acting on behalf of the client. The server can access local
	// resources as the client. If the server is local, it can access
	// network resources as the client. If the server is remote, it can
	// access only resources that are on the same computer as the server.
	ImpersonationLevelImpersonate = 3

	// The most powerful impersonation level. When this level is selected,
	// the server (whether local or remote) can impersonate the client's
	// security context while acting on behalf of the client. During
	// impersonation, the client's credentials (both local and network) can
	// be passed to any number of computers.
	ImpersonationLevelDelegate = 4
)
View Source
const DefaultXmitSize = 4096

The default transmit/receive size.

View Source
const HeaderSize = 16

The common header size.

View Source
const MaxPad = 16

MaxPad specifies the maximum possible padding.

View Source
const MinimumXmitSize = 4096

The MinimumXmitSize.

View Source
const SecurityTrailerSize = 8

SecurityTrailerSize is the size of the security trailer.

View Source
const VerificationTrailerMaxPad = 4

Variables

View Source
var (
	ErrConnClosed   = errors.New("connection is closed")
	ErrConnNotExist = errors.New("presentation connection does not exist")
)
View Source
var (
	// Transfer Syntax NDR UUID.
	TransferNDR = uuid.New(0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, [6]byte{0x08, 0x00, 0x2B, 0x10, 0x48, 0x60})
	// Transfer Syntax NDR v2.0.
	TransferNDRSyntaxV2_0 = &SyntaxID{TransferNDR, 2, 0}

	// Transfer Syntax NDR64 UUID.
	TransferNDR64 = uuid.New(0x71710533, 0xBEBA, 0x4937, 0x83, 0x19, [6]uint8{0xB5, 0xDB, 0xEF, 0x9C, 0xCC, 0x36})
	// Transfer Syntax NDR64 v1.0.
	TransferNDR64SyntaxV1_0 = &SyntaxID{TransferNDR, 1, 0}

	// Bind-time feature negotiation flags.
	BindFlags = KeepConnOpenOnOrphaned | SecurityContextMultiplexing
	// Bind-time feature negotiation UUID.
	BindFeature = uuid.New(0x6CB71C2C, 0x9812, 0x4540, uint8(BindFlags), 0, [6]byte{})
	// Bind-time feature negotiation Syntax.
	BindFeatureSyntaxV1_0 = &SyntaxID{BindFeature, 1, 0}
)
View Source
var (
	// Server terminated the connection.
	ErrShutdown = errors.New("server terminated")
	// UUID mismatch.
	ErrObjectUUIDMismatch = errors.New("object uuid mismatch")
	// Security Context is empty.
	ErrNoSecurityContext = errors.New("security context is empty")
	// Presentation Context is empty.
	ErrNoPresentationContext = errors.New("presentation context is empty")
)
View Source
var (
	// The transport was not binded.
	ErrNotBinded = errors.New("not binded")
	// The transport is closed.
	ErrClosed = errors.New("transport is closed")
)
View Source
var (
	// Too long packet error.
	ErrPacketTooLong = errors.New("packet is too long")
	// Too small buffer error.
	ErrBufferTooSmall = errors.New("buffer is too small")
)
View Source
var DefaultConvertUUID = ConvertUUID(func(u *uuid.UUID) string { return u.String() })

The default UUID covert function.

View Source
var VerificationTrailerSignature = [...]byte{0x8A, 0xE3, 0x13, 0x71, 0x02, 0xF4, 0x36, 0x71}

Functions

func HasObjectUUID

func HasObjectUUID(opts any) (*uuid.UUID, bool)

HasObjectUUID function returns `true` if set of options contains the ObjectUUID option.

func NewPresentationContextID

func NewPresentationContextID() uint16

func ParseOptions

func ParseOptions(ctx context.Context, opts ...Option) (*option, error)

func ParseSecurityOptions added in v1.0.3

func ParseSecurityOptions(ctx context.Context, opts ...Option) *option

func SecurityContextID

func SecurityContextID() uint32

SecurityContextID function returns the unique identifier for the next security context.

Types

type AlterContext

type AlterContext struct {
	MaxXmitFrag  uint16
	MaxRecvFrag  uint16
	AssocGroupID uint32
	ContextList  []*Context
}

The AlterContextPDU is used to request additional presentation negotiation for another interface and/or version, or to negotiate a new security context, or both. The format is identical to the BindPDU, except that the value of the COHeader.PacketType field is set to PacketTypeAlterContext. The MaxXmitFrag, MaxRecvFrag, AssocGroupID and SecAddressLength/PortSpec fields are ignored.

func (*AlterContext) MarshalZerologObject

func (pdu *AlterContext) MarshalZerologObject(e *zerolog.Event)

func (*AlterContext) ReadFrom

func (pdu *AlterContext) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*AlterContext) WriteTo

func (pdu *AlterContext) WriteTo(ctx context.Context, w ndr.Writer) error

type AlterContextResponse

type AlterContextResponse struct {
	MaxXmitFrag  uint16
	MaxRecvFrag  uint16
	AssocGroupID uint32
	PortSpec     string
	ResultList   []*Result
}

The AlterContextResponsePDU is used to indicate the server's response to an AlterContext request. The PDU format is identical to BindAckPDU, except that the value of the COHeader.PacketType field is set to PacketTypeAlterContextResponse. The MaxXmitFrag, MaxRecvFrag, AssocGroupID and SecAddressLength/PortSpec fields are ignored.

func (*AlterContextResponse) MarshalZerologObject

func (pdu *AlterContextResponse) MarshalZerologObject(e *zerolog.Event)

func (*AlterContextResponse) ReadFrom

func (pdu *AlterContextResponse) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*AlterContextResponse) WriteTo

func (pdu *AlterContextResponse) WriteTo(ctx context.Context, w ndr.Writer) error

type Auth3

type Auth3 struct {
	Pad [4]byte
}

func (*Auth3) MarshalZerologObject

func (pdu *Auth3) MarshalZerologObject(e *zerolog.Event)

func (*Auth3) ReadFrom

func (pdu *Auth3) ReadFrom(ctx context.Context, r ndr.Reader) error

ReadFrom function ...

func (*Auth3) WriteTo

func (pdu *Auth3) WriteTo(ctx context.Context, w ndr.Writer) error

marshal function ...

type AuthLevel

type AuthLevel uint8

The authentication-level constants represent authentication levels passed to various run-time functions. These levels are listed in order of increasing authentication. Each new level adds to the authentication provided by the previous level.

const (
	// Uses the default authentication level for the specified
	// authentication service.
	AuthLevelDefault AuthLevel = 0x00
	// Performs no authentication.
	AuthLevelNone AuthLevel = 0x01
	// Authenticates only when the client establishes a relationship
	// with a server.
	AuthLevelConnect AuthLevel = 0x02
	// Authenticates only at the beginning of each remote procedure call
	// when the server receives the request. Does not apply to remote
	// procedure calls made using the connection-based protocol sequences.
	AuthLevelCall AuthLevel = 0x03
	// Authenticates only that all data received is from the expected client.
	// Does not validate the data itself.
	AuthLevelPkt AuthLevel = 0x04
	// Authenticates and verifies that none of the data transferred between
	// client and server has been modified.
	AuthLevelPktIntegrity AuthLevel = 0x05
	// Includes all previous levels, and ensures clear text data can only
	// be seen by the sender and the receiver. This involves encrypting
	// the argument value of each remote procedure call.
	AuthLevelPktPrivacy AuthLevel = 0x06
)

type AuthType

type AuthType uint8
const (
	// No authentication.
	AuthTypeNone AuthType = 0x00 // 0
	// Use the Microsoft Negotiate SSP. This SSP negotiates
	// between the use of the NTLM and Kerberos protocol Security
	// Support Providers (SSP).
	AuthTypeGSSNegotiate AuthType = 0x09 // 9
	// Use the Microsoft NT LAN Manager (NTLM) SSP.
	AuthTypeWinNT AuthType = 0x0A // 10
	// Use the Schannel SSP. This SSP supports Secure Socket Layer
	// (SSL), private communication technology (PCT), and transport
	// level security (TLS).
	AuthTypeGSSChannel AuthType = 0x0E // 14
	// Use the Microsoft Kerberos SSP.
	AuthTypeKerberos AuthType = 0x10 // 16
	// The Netlogon Secure Channel.
	AuthTypeNetLogon AuthType = 0x44 // 68
	// Use the default authentication service.
	AuthTypeDefault AuthType = 0xFF // 255
)

func MechanismToAuthType

func MechanismToAuthType(mech gssapi.OID) AuthType

MechanismToAuthType function converts the mechanism OID to the DCE/RPC authentication type.

func (AuthType) Legs

func (v AuthType) Legs() int

type Bind

type Bind struct {
	MaxXmitFrag  uint16
	MaxRecvFrag  uint16
	AssocGroupID uint32
	ContextList  []*Context
}

The BindPDU is used to initiate the presentation negotiation for the body data, and optionally, authentication. The presentation negotiation follows the model of the OSI presentation layer.

The PDU contains a priority-ordered list of supported presentation syntaxes, both abstract and transfer, and context identifiers (local handles). (This differs from OSI, which does not specify any order for the list.) The abstract and transfer syntaxes are represented as a record of interface UUID and interface version. (These may map one-to-one into OSI object identifiers by providing suitable prefixes and changing the encoding.) Each supported data representation, such as NDR, will be assigned an interface UUID, and will use that UUID as part of its transfer syntax value. Each stub computes its abstract syntax value given its interface UUID and interface version.

If COHeader.PFCFlags does not have PFCFlagCOLastFrag set and RPCVersMinor is 1, then the PDU has fragmented AuthVerifier data. The server will assemble the data concatenating sequentially each AuthVerifier field until a PDU is sent with PFCFlagCOLastFrag flag set. This completed buffer is then used as AuthVerifier data.

The fields MaxXmitFrag and MaxRecvFrag are used for fragment size negotiation.

The AssocGroupID field contains either an association group identifier that was created during a previous bind negotiation or 0 (zero) to indicate a request for a new group.

This PDU shall not exceed the MustRecvFragSize, since no size negotiation has yet occurred. If the ContextList is too long, the leading subset should be transmitted, and additional presentation context negotiation can occur in subsequent AlterContext PDUs, as needed, after a successful BindAck.

func (*Bind) MarshalZerologObject

func (pdu *Bind) MarshalZerologObject(e *zerolog.Event)

func (*Bind) ReadFrom

func (pdu *Bind) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Bind) WriteTo

func (pdu *Bind) WriteTo(ctx context.Context, w ndr.Writer) error

type BindAck

type BindAck struct {
	MaxXmitFrag  uint16
	MaxRecvFrag  uint16
	AssocGroupID uint32
	PortSpec     string
	ResultList   []*Result
}

The BindAckPDU is returned by the server when it accepts a bind request initiated by the client's bindPDU. It contains the results of presentation context and fragment size negotiations.

It may also contain a new association group identifier if one was requested by the client.

The MaxXmitFrag and MaxRecvFrag fields contain the maximum transmit and receive fragment sizes as determined by the server in response to the client's desired sizes.

The ResultList contains the results of the presentation context negotiation initiated by the client. It is possible for a BindAckPDU not to contain any mutually supported syntaxes.

If the client requested a new association group, AssocGroupID contains the identifier of the new association group created by the server. Otherwise, it contains the identifier of the previously created association group requested by the client.

func (*BindAck) MarshalZerologObject

func (pdu *BindAck) MarshalZerologObject(e *zerolog.Event)

func (*BindAck) ReadFrom

func (pdu *BindAck) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*BindAck) WriteTo

func (pdu *BindAck) WriteTo(ctx context.Context, w ndr.Writer) error

type BindNak

type BindNak struct {
	ProviderRejectReason ProviderReason
	// VersionList represents the list of supported protocols returned when the
	// protocol negotiation fails.
	VersionList []*Version
}

The BindNakPDU is returned by the server when it rejects an association request initiated by the client's BindPDU. The ProviderRejectReason field holds the rejection reason code. When the reject reason is ProtocolVersionNotSupported, the versions field contains a list of runtime protocol versions supported by the server.

The BindNakPDU never contains an authentication verifier.

func (*BindNak) Error

func (pdu *BindNak) Error() string

func (*BindNak) MarshalZerologObject

func (pdu *BindNak) MarshalZerologObject(e *zerolog.Event)

func (*BindNak) ReadFrom

func (pdu *BindNak) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*BindNak) WriteTo

func (pdu *BindNak) WriteTo(ctx context.Context, w ndr.Writer) error

type BindOption

type BindOption func(*option)

BindOption represents the DCE/RPC binding option.

func WithAbstractSyntax

func WithAbstractSyntax(abstractSyntax *SyntaxID) BindOption

WithAbstractSyntax option specifies the abstract syntax for the DCE/RPC connection.

func WithEndpoint

func WithEndpoint(s string) BindOption

WithEndpoint option specifies the string binding for the connection.

You can specify exact binding string that should be used to establish the connection to the server, for example:

conn, err := dcerpc.Dial(ctx, "contoso.net", dcerpc.WithEndpoint("ncacn_ip_tcp:[48621]")

This code should create a server connection, that will bind any transport to the TCP/IP port 48621.

Alternatively, you can specify this option during NewXClient call, for example:

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSeal(), dcerpc.WithEndpoint("ncacn_np:[winreg]"))

This code should establish a new transport over a named pipe to the windows registry server.

func WithGroup

func WithGroup(g *Group) BindOption

WithGroup option specifies the association group for the connection or is used to initialize the association group id.

func WithLogger

func WithLogger(logger zerolog.Logger) BindOption

WithLogger option sets the debug logger.

Specify this option to turn on the debug logging for the DCE/RPC connection:

conn, err := dcerpc.Dial(ctx, "contoso.net", dcerpc.WithLogger(zerolog.New(os.Stderr)))

func WithNDR20

func WithNDR20() BindOption

WithNDR20 option specifies the (default) NDR encoding.

func WithNDR64

func WithNDR64() BindOption

WithNDR64 option specifies the NDR64 encoding. (NYI)

func WithVerifyBitMask

func WithVerifyBitMask(must bool) BindOption

WithVerifyBitMask option includes the bit-mask verification to the request verification trailer.

func WithVerifyHeader2

func WithVerifyHeader2(must bool) BindOption

WithVerifyHeader2 option includes the header2 verification to the request verification trailer.

func WithVerifyPresenetation

func WithVerifyPresenetation(must bool) BindOption

WithVerifyPresentation option includes the presentation verification to the request verification trailer.

type Binding

type Binding struct {
	// The syntax identifier for the binding.
	SyntaxID SyntaxID
	// The transfer syntax.
	TransferSyntaxID SyntaxID
	// The string binding.
	StringBinding StringBinding
}

func ParseBindingURL

func ParseBindingURL(s string) (*Binding, error)

func (Binding) URL

func (s Binding) URL(uConvs ...ConvertUUID) *url.URL

URL function returns the URL for the Binding. Use UUID converter to change the UUID to human-readable string.

type Body

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

Body structure represents the read-writer for the chunked marshalling/unmarshalling operations.

func NewBody

func NewBody(ctx context.Context, op Operation, p *Presentation, marshal bool) *Body

NewBody function returns the new stub reader (when marshal is `false`), or writer, (when marshal is `true`).

func (*Body) Close

func (body *Body) Close()

Close function terminates the marshaling/unmarshaling routines that haven't yet completed.

func (*Body) DecodeFrom

func (body *Body) DecodeFrom(b []byte, frmt ndr.DataRepresentation, maxLen int) (int, error)

DecodeFrom function performs the blocking read from the buffer `b` to unmarshaller.

func (*Body) EncodeTo

func (body *Body) EncodeTo(b []byte, frmt ndr.DataRepresentation, maxLen int) (int, error)

WriteTo function performs the blocking write from the marshaler to buffer `b`.

func (*Body) IsDone

func (body *Body) IsDone() bool

func (*Body) SetDone

func (body *Body) SetDone()

type BufferedConn

type BufferedConn struct {
	// The wrapped raw connection.
	RawConn
	// contains filtered or unexported fields
}

BufferedConn is a raw connection wrapper to optimize the short read header operations.

func (*BufferedConn) Read

func (conn *BufferedConn) Read(b []byte) (int, error)

Read function reads the data into buffer `b` and optionally fetches the next data block.

func (*BufferedConn) Resized

func (conn *BufferedConn) Resized(sz int) *BufferedConn

type Call

type Call interface {
	// The call identifier.
	ID() uint32
	// The function must be called to indicate that transport
	// buffer can be released.
	Ready(context.Context)
	// ReadBuffer function copies the data into the buffer.
	ReadBuffer(context.Context, []byte) (Header, error)
	// WriteBuffer function writes the data from the buffer.
	WriteBuffer(context.Context, Header, []byte) error
}

Call interface provides the exclusive access to the transport.

type CallOption

type CallOption interface {
	// contains filtered or unexported methods
}

CallOption represents the DCE/RPC Call option.

type Cancel

type Cancel struct{}

The CoCancelPDU is used to forward a cancel.

func (*Cancel) MarshalZerologObject

func (pdu *Cancel) MarshalZerologObject(e *zerolog.Event)

func (*Cancel) ReadFrom

func (pdu *Cancel) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Cancel) WriteTo

func (pdu *Cancel) WriteTo(ctx context.Context, w ndr.Writer) error

type CommandType

type CommandType uint16
var (
	// SEC_VT_COMMAND_BITMASK_1: This is an rpc_sec_vt_bitmask command.
	CommandTypeBitMask CommandType = 0x0001
	// SEC_VT_COMMAND_PCONTEXT: This is an rpc_sec_vt_pcontext command.
	CommandTypePresentation CommandType = 0x0002
	// SEC_VT_COMMAND_HEADER2: This is an rpc_sec_vt_header2 command.
	CommandTypeHeader2 CommandType = 0x0003
	// SEC_VT_COMMAND_END: This flag MUST be present in the last command
	// in the verification trailer body.
	CommandTypeEnd CommandType = 0x4000
	// SEC_VT_MUST_PROCESS_COMMAND: Indicates that the server MUST process
	// this command. If the server does not support the command, it MUST
	// reject the request.
	CommandTypeRequired CommandType = 0x8000
	// Mask.
	CommandMask CommandType = 0x3FFF
)

func (CommandType) Is

func (o CommandType) Is(is CommandType) bool

func (CommandType) IsEnd

func (o CommandType) IsEnd() bool

func (CommandType) IsRequired

func (o CommandType) IsRequired() bool

type Conn

type Conn interface {
	Bind(context.Context, ...Option) (Conn, error)
	// Alter Context.
	AlterContext(context.Context, ...Option) error
	// Invoke.
	Invoke(context.Context, Operation, ...CallOption) error
	// Invoke Object.
	InvokeObject(context.Context, *uuid.UUID, Operation, ...CallOption) error
	// Close.
	Close(context.Context) error
	// RegisterServer.
	RegisterServer(ServerHandle, ...Option)
}

The DCE/RPC Connection.

func Dial

func Dial(ctx context.Context, addr string, opts ...Option) (Conn, error)

Dial function creates a new transport set that should be used for the binding procedures performed by clients.

func HasNoBind

func HasNoBind(opts any) (Conn, bool)

HasNoBind function returns `true` if set of options contains the NoBind option.

type ConnectOption

type ConnectOption func(*Transport)

The transport connection option.

func WithEndpointMapper

func WithEndpointMapper(m EndpointMapper) ConnectOption

WithEndpointMapper option sets the endpoint mapper to find the endpoint (port or named pipe) for the selected abstract syntax.

There are two interface implementation, first is EPM service:

import "github.com/oiweiwei/go-msrpc/msrpc/epm/epm/v3"

conn, err := dcerpc.Dial(ctx, "contoso.net", epm.EndpointMapper(ctx, "contoso.net", dcerpc.WithSign()))

Second is well-known endpoints:

import "github.com/oiweiwei/go-msrpc/msrpc/well_known"

conn, err := dcerpc.Dial(ctx, "contoso.net", well_known.EndpointMapper())

func WithFragmentSize

func WithFragmentSize(sz int) ConnectOption

WithBufferSize options sets the buffer input/output size.

func WithGroupID

func WithGroupID(id int) ConnectOption

WithGroupID option sets the association group identifier.

func WithNewTransport

func WithNewTransport() ConnectOption

func WithSMBDialer

func WithSMBDialer(dialer *smb2.Dialer) ConnectOption

WithSMBDialer function sets the SMB dialer.

func WithSMBPort

func WithSMBPort(port int) ConnectOption

WithSMBPort function sets the SMB communication port.

func WithTimeout

func WithTimeout(timeout time.Duration) ConnectOption

WithTimeout option sets the networking timeout.

type Context

type Context struct {
	ContextID uint16

	AbstractSyntax   *SyntaxID
	TransferSyntaxes []*SyntaxID
	// contains filtered or unexported fields
}

The ContextElement struct represents one element in a presentation context list.

func (*Context) ReadFrom

func (c *Context) ReadFrom(ctx context.Context, r ndr.Reader) error

ReadFrom function ...

func (*Context) WriteTo

func (c *Context) WriteTo(ctx context.Context, w ndr.Writer) error

marshal function ...

type ContextList

type ContextList struct {
	NContextElem uint8

	ContextElem []*Context
	// contains filtered or unexported fields
}

func (*ContextList) ReadFrom

func (c *ContextList) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*ContextList) WriteTo

func (c *ContextList) WriteTo(ctx context.Context, w ndr.Writer) error

type ConvertUUID

type ConvertUUID func(*uuid.UUID) string

The UUID convert to string function type.

type DefResult

type DefResult uint16

DefResults represents the results of a presentation context negotiation.

const (
	Acceptance        DefResult = 0x0000
	UserRejection     DefResult = 0x0001
	ProviderRejection DefResult = 0x0002
	NegotiateAck      DefResult = 0x0003
)

type EndpointMapper

type EndpointMapper interface {
	Map(context.Context, *Binding) ([]StringBinding, error)
}

The Endpoint Mapper interface maps the given syntax identifier and returns the list of bindings of following format:

type Fault

type Fault struct {
	AllocHint   uint32
	ContextID   uint16
	CancelCount uint8
	Flags       uint8
	Status      uint32
	Pad         [4]byte
}

The FaultPDU is used to indicate either an RPC run-time, RPC stub, or RPC-specific exception to the client. The ContextID field holds a context identifier that identifies the data representation.

The AllocHint field is optionally used by the client to provide a hint to the receiver of the amount of buffer space to allocate contiguously for fragmented requests. This is only a potential optimisation. The server must work correctly regardless of the value passed. The value 0 (zero) is reserved to indicate that the transmitter is not supplying any information.

The Status field indicates run-time status. The value may either be an architected non-zero value, indicating a run-time error, such as an interface version mismatch, or 0 (zero), indicating a stub defined exception that is specified with the stub data. If a non-zero value is present, no stub data is allowed.

Certain status values imply that the call did not execute. To keep such status values consistent with the flag, an implementation should model all fault messages as being initialised with the COHeader.PFCFlagCODidNotExecute flag set, then cleared when the run-time system (or stub, if the implementation allows) passes control to the server stub routine.

func (*Fault) MarshalZerologObject

func (pdu *Fault) MarshalZerologObject(e *zerolog.Event)

func (*Fault) ReadFrom

func (pdu *Fault) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Fault) WriteTo

func (pdu *Fault) WriteTo(ctx context.Context, w ndr.Writer) error

type Feature

type Feature Result

func (*Feature) KeepConnOpenOnOrphaned

func (f *Feature) KeepConnOpenOnOrphaned() bool

func (*Feature) SecurityContextMultiplexing

func (f *Feature) SecurityContextMultiplexing() bool

type Group

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

Group is used to hold the association group identifier. The association can be passed through the options using multiple connections, thus sharing the same group id between them.

func (*Group) GroupID

func (a *Group) GroupID() int

GroupID function returns the association group (or 0 if association is null).

func (*Group) SetID

func (a *Group) SetID(id int) int

SetID function sets the association group id (when present) and returns that identifier.

type Header struct {
	RPCVersion      uint8
	RPCVersionMinor uint8
	PacketType      PacketType
	PacketFlags     PacketFlag
	PacketDRep      ndr.DataRepresentation
	FragLength      uint16
	AuthLength      uint16
	CallID          uint32
}

func (Header) MarshalZerologObject

func (h Header) MarshalZerologObject(e *zerolog.Event)

func (*Header) ReadFrom

func (h *Header) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Header) WriteTo

func (h *Header) WriteTo(ctx context.Context, w ndr.Writer) error

type ImpersonationLevel

type ImpersonationLevel int

type Legs

type Legs int

The security provider underlying protocol and implementation defines the number of legs and whether the number of legs is odd or even that are used in the token exchange process that builds a security context.

type NoBindOption

type NoBindOption struct{ Conn Conn }

NoBindOption option indicates that no bind must be performed for this connection.

func WithNoBind

func WithNoBind(cc Conn) NoBindOption

WithNoBind option is used to indicate, that no bind must be performed to the connection.

type ObjectUUIDOption

type ObjectUUIDOption func() *uuid.UUID

The ObjectUUID option.

func WithObjectUUID

func WithObjectUUID(u *uuid.UUID) ObjectUUIDOption

WithObjectUUID option specifies the object UUID for the RPC call. For more explicit scenarios, use InvokeObject RPC.

type Operation

type Operation = ndr.Operation

The DCE/RPC Operation.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option represents the common interface for DCE/RPC options.

type Orphaned

type Orphaned struct{}

The OrphanedPDU is used by a client to notify a server that it is aborting a request in progress that has not been entirely transmitted yet, or that it is aborting a (possibly lengthy) response in progress.

func (*Orphaned) MarshalZerologObject

func (pdu *Orphaned) MarshalZerologObject(e *zerolog.Event)

func (*Orphaned) ReadFrom

func (pdu *Orphaned) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Orphaned) WriteTo

func (pdu *Orphaned) WriteTo(ctx context.Context, w ndr.Writer) error

type PDU

type PDU interface {
	WriteTo(context.Context, ndr.Writer) error
	ReadFrom(context.Context, ndr.Reader) error
	MarshalZerologObject(*zerolog.Event)
}

type Packet

type Packet struct {
	// The packet header.
	Header Header
	// The PDU header.
	PDU PDU
	// Verification trailer.
	VerificationTrailer VerificationTrailer
	// Security trailer.
	SecurityTrailer SecurityTrailer
	// Body.
	Body *Body
	// Auth token.
	AuthData []byte
	// contains filtered or unexported fields
}

Packet represents the raw DCE/RPC packet structure.

func (*Packet) AuthDataBytes

func (p *Packet) AuthDataBytes() []byte

AuthDataBytes function returns the slice pointing to the auth_data encoded value.

func (*Packet) Bytes

func (p *Packet) Bytes() []byte

Bytes function returns the PDU bytes.

func (*Packet) HeaderBytes

func (p *Packet) HeaderBytes() []byte

HeaderBytes function returns the header bytes.

func (*Packet) IsLastFrag

func (p *Packet) IsLastFrag() bool

func (*Packet) Len

func (p *Packet) Len() int

func (*Packet) SecurityTrailerBytes

func (p *Packet) SecurityTrailerBytes() []byte

SecurityTrailerBytes function returns the slice pointing to the security trailer bytes.

func (*Packet) StubDataBytes

func (p *Packet) StubDataBytes() []byte

StubDataBytes function returns the stub data bytes. (will include padding only when request/response is not a case)

type PacketFlag

type PacketFlag uint8
const (
	// PFC_FIRST_FRAG: First fragment.
	PacketFlagFirstFrag PacketFlag = 1 << 0
	// PFC_LAST_FRAG: Last fragment.
	PacketFlagLastFrag PacketFlag = 1 << 1
	// PFC_PENDING_CANCEL: Cancel was pending at sender.
	PacketFlagPendingCancel PacketFlag = 1 << 2
	// PFC_SUPPORT_HEADER_SIGN: Supports the header/trailer protection.
	// (same as PFC_PENDING_CANCEL, only during Bind/BindAck).
	PacketFlagSupportHeaderSign PacketFlag = 1 << 2
	// PFC_RESERVED_1: Reserved1.
	PacketFlagReserved1 PacketFlag = 1 << 3
	// PFC_CONC_MPX: Supports concurrent multiplexing of a single connection.
	PacketFlagConcMPX PacketFlag = 1 << 4
	// PFC_DID_NOT_EXECUTE: Only meaningful on 'fault' packet; If true,
	// guaranteed call did not execute.
	PacketFlagDidNotExecute PacketFlag = 1 << 5
	// PFC_MAYBE: 'maybe' call semantics requested
	PacketFlagMaybe PacketFlag = 1 << 6
	// PFC_OBJECT_UUID: if true, a non-nil object UUID was specified in the
	// handle, and is present in the optional object field. If false, the
	// object field is omitted.
	PacketFlagObjectUUID PacketFlag = 1 << 7
)

func FlagObjectUUID

func FlagObjectUUID(obj *uuid.UUID) PacketFlag

FlagObjectUUID function computes the PFC_OBJECT_UUID flag based on the value `obj`.

func (PacketFlag) IsSet

func (f PacketFlag) IsSet(ff PacketFlag) bool

func (PacketFlag) String

func (f PacketFlag) String() string

type PacketType

type PacketType uint8
const (
	PacketTypeRequest              PacketType = 0
	PacketTypeResponse             PacketType = 2
	PacketTypeFault                PacketType = 3
	PacketTypeBind                 PacketType = 11
	PacketTypeBindAck              PacketType = 12
	PacketTypeBindNak              PacketType = 13
	PacketTypeAlterContext         PacketType = 14
	PacketTypeAlterContextResponse PacketType = 15
	PacketTypeAuth3                PacketType = 16
	PacketTypeShutdown             PacketType = 17
	PacketTypeCancel               PacketType = 18
	PacketTypeOrphaned             PacketType = 19
)

func PDUToPacketType

func PDUToPacketType(pdu PDU) PacketType

func (PacketType) String

func (f PacketType) String() string

type PortAny

type PortAny struct {
	PortSpec string
}

func (*PortAny) ReadFrom

func (pa *PortAny) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*PortAny) WriteTo

func (pa *PortAny) WriteTo(ctx context.Context, w ndr.Writer) error

type Presentation

type Presentation struct {

	// The list of abstract syntaxes. (only one supported).
	AbstractSyntax *SyntaxID
	// Selected transfer syntax.
	TransferSyntax *SyntaxID
	// Error.
	Error error
	// contains filtered or unexported fields
}

The Presentation represents the data presentation context.

func NewPresentation

func NewPresentation(abstractSyntax *SyntaxID) *Presentation

func (*Presentation) ID

func (p *Presentation) ID() uint16

func (*Presentation) TransferEncoding

func (c *Presentation) TransferEncoding() func([]byte, ...any) ndr.NDR

TransferEncoding function returns the transfer encoding for the presentation context. The only supported encoding is NDR v2.0.

type ProtocolSequence

type ProtocolSequence int

The protocol sequence.

var (
	// The ncacn_ip_tcp identifies TCP/IP as the protocol
	// family for the endpoint.
	// Example: object@ncacn_ip_tcp:server-name[port-name]
	// URL: tcp://username:password@server-name:port/object/interface/version
	// Example URL: tcp://guest:guest@127.0.0.1:54212/00000000-0000-0000-0000000000000000/12345678-1234-abcd-ef0001234567cffb/v1.0
	ProtocolSequenceIPTCP ProtocolSequence = 1
	// The ncadg_ip_udp identifies UDP as the protocol
	// family for the endpoint.
	// Example: object@ncadg_ip_udp:server-name[port-name]
	// URL (?): udp://username:password@server-name:port/object/interface/version
	ProtocolSequenceIPUDP ProtocolSequence = 2
	// The ncacn_np identifies named pipes as the protocol family
	// for the endpoint.
	// Example: object@ncacn_np:server-name[\\pipe\\pipe-name]
	// URL (?): smb://username:password@server-name:smb_port/@computer/pipe/object/interface/version
	// Example URL: smb://guest:guest@127.0.0.1:445/@WIN_PC/winreg/00000000-0000-0000-0000000000000000/338cd001-2244-31f1-aaaa900038001003/v1.0
	ProtocolSequenceNamedPipe ProtocolSequence = 3
	// The ncalrpc identifies local interprocess communication
	// as the protocol family for the endpoint.
	// Example: object@ncalrpc:[port-name]
	// URL (?): alpc://port-name/object/interface/version
	ProtocolSequenceLRPC ProtocolSequence = 4
	// The ncacn_http identifies the Microsoft Internet Information
	// Server (IIS) as the protocol family for the endpoint.
	// Example: object@ncacn_http:rpc_server[endpoint]
	// URL (?): http://username:password@server-name:port/object/interface/version
	ProtocolSequenceHTTP ProtocolSequence = 5
)

func ProtocolSequenceFromString

func ProtocolSequenceFromString(s string) ProtocolSequence

func (ProtocolSequence) String

func (p ProtocolSequence) String() string

type ProviderReason

type ProviderReason uint16

ProviderReason represents the reasons for rejection of a context element.

const (
	ReasonNotSpecified                   ProviderReason = 0x0000
	AbstractSyntaxNotSupported           ProviderReason = 0x0001
	ProposedTransferSyntaxesNotSupported ProviderReason = 0x0002
	LocalLimitExceeded                   ProviderReason = 0x0003
	AuthTypeNotRecognized                ProviderReason = 0x0008
	InvalidChecksum                      ProviderReason = 0x0009

	// bind time feature negotiation flags.
	SecurityContextMultiplexing ProviderReason = 0x0001
	KeepConnOpenOnOrphaned      ProviderReason = 0x0002
)

type RawConn

type RawConn interface {
	io.ReadWriteCloser
}

The Raw connection.

func NewBufferedConn

func NewBufferedConn(cc RawConn, sz int) RawConn

NewBufferedConn function returns the new buffered connection.

type Request

type Request struct {
	AllocHint  uint32
	ContextID  uint16
	OpNum      uint16
	ObjectUUID *uuid.UUID
}

The RequestPDU is used for an initial call request. The ContextID field holds a presentation context identifier that identifies the data representation. The OpNum field identifies the operation being invoked within the interface.

The PDU may also contain an Object UUID. In this case the PFCFlagCOObjectUUID flag is set in COHeader.PFCFlags, and the PDU includes the object field. If the PFCFlagCOObjectUUID flag is not set, the PDU does not include the object field.

The AllocHint field is optionally used by the client to provide a hint to the receiver of the amount of buffer space to allocate contiguously for fragmented requests. This is only a potential optimisation. The server must work correctly regardless of the value passed. The value 0 (zero) is reserved to indicate that the transmitter is not supplying any information.

func (*Request) MarshalZerologObject

func (pdu *Request) MarshalZerologObject(e *zerolog.Event)

func (*Request) ReadFrom

func (pdu *Request) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Request) WriteTo

func (pdu *Request) WriteTo(ctx context.Context, w ndr.Writer) error

type Response

type Response struct {
	AllocHint   uint32
	ContextID   uint16
	CancelCount uint8
	// contains filtered or unexported fields
}

The ResponsePDU is used to respond to an active call. The ContextID field holds a context identifier that identifies the data representation. The CancelCount field holds a count of cancels received.

The AllocHint field is optionally used by the client to provide a hint to the receiver of the amount of buffer space to allocate contiguously for fragmented requests. This is only a potential optimisation. The server must work correctly regardless of the value passed. The value 0 (zero) is reserved to indicate that the transmitter is not supplying any information.

func (*Response) MarshalZerologObject

func (pdu *Response) MarshalZerologObject(e *zerolog.Event)

func (*Response) ReadFrom

func (pdu *Response) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Response) WriteTo

func (pdu *Response) WriteTo(ctx context.Context, w ndr.Writer) error

type Result

type Result struct {
	DefResult      DefResult
	ProviderReason ProviderReason
	TransferSyntax *SyntaxID
}

The Result struct represents one element in the results of the context negotiation.

func (*Result) Error

func (result *Result) Error() string

func (*Result) HasError

func (result *Result) HasError() bool

func (*Result) ReadFrom

func (result *Result) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Result) WriteTo

func (result *Result) WriteTo(ctx context.Context, w ndr.Writer) error

type ResultList

type ResultList struct {
	NResults uint8

	Results []*Result
	// contains filtered or unexported fields
}

func (*ResultList) ReadFrom

func (rl *ResultList) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*ResultList) WriteTo

func (rl *ResultList) WriteTo(ctx context.Context, w ndr.Writer) error

type Security

type Security struct {

	// The impersonation level.
	Impersonation ImpersonationLevel
	// SupportHeaderSign.
	RequestHeaderSign PacketFlag
	// The security context authentication type.
	Type AuthType
	// The security context authentication level.
	Level AuthLevel
	// The flag that indicates whether the header signing is
	// supported.
	SignHeader bool
	// The flag that indicates whether the security context
	// multiplexing is supported.
	Multiplexing bool
	// The target name.
	TargetName string
	// contains filtered or unexported fields
}

The DCE/RPC Security Context.

func NewSecurity

func NewSecurity(ctx context.Context, opts ...gssapi.ContextOption) *Security

NewSecurity function returns the new security context and saves the GSSAPI context storied in `ctx` variable.

func (*Security) AuthLength

func (cc *Security) AuthLength(ctx context.Context, pkt *Packet) int

AuthLength function returns the expected length for the authentication trailer.

func (*Security) CanWrap

func (cc *Security) CanWrap(ctx context.Context, pkt *Packet) bool

CanWrap function returns true if security context can be applied to the packet (context is established and packet is request or response).

func (*Security) Established

func (cc *Security) Established() bool

Established function returns `true` if the security context was established and can be used for Wrap/Unwrap functions.

func (*Security) ID

func (o *Security) ID() uint32

ID returns the security context identifier.

func (*Security) Init

func (cc *Security) Init(ctx context.Context, b []byte) ([]byte, error)

Init function inits the security context.

func (*Security) SecurityTrailer

func (cc *Security) SecurityTrailer() SecurityTrailer

SecurityTrailer function returns the DCE/RPC security trailer.

func (*Security) Unwrap

func (cc *Security) Unwrap(ctx context.Context, pkt *Packet, afterLock func(context.Context)) error

Unwrap function unwraps the packet and verifies the signature. The `afterLock` parameter is to ensure that any lock that must be released, will be released once the Security lock will be acquired.

func (*Security) Wrap

func (cc *Security) Wrap(ctx context.Context, pkt *Packet) error

Wrap function depending on the security level encrypts and computes the checksum for the packet.

type SecurityContextOption

type SecurityContextOption func(o *option)

SecurityContextOption defines the security options before establishing the security context.

func WithCredentials

func WithCredentials(creds any) SecurityContextOption

WithCredentials option specifies the credentials set for the security context.

Use this method to trigger the new security context establishement for the client with credentials provided.

import "github.com/oiweiwei/go-msrpc/ssp/credential"

creds := credential.NewFromPassword(os.Getenv("USERNAME"), os.Getenv("PASSWORD"))

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSeal(), dcerpc.WithCredentials(creds))

Alternatively, you can use gssapi.Credential wrapping for more granular configuration:

// creds := gssapi.NewCredential("spn/my-spn", []gssapi.OID{ssp.NTLM}, gssapi.Initiate, credential.NewFromPassword(...))

func WithMechanism

WithMechanism option specifies the allowed mechanism for the security context.

Use this method to trigger the new security context establishment for the client with mechanism provided.

import "github.com/oiweiwei/go-msrpc/ssp"

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSeal(), dcerpc.WithMechanism(ssp.NTLM))

type SecurityMask

type SecurityMask uint8
var (
	// SkipSealOpt option skips the Confidentiality option as it must
	// be defined on individual buffer level.
	SkipSealOpt SecurityMask = 0x01
	// SkipSignOpt option skips the Integrity option as it must be
	// defined on individual buffer level.
	SkipSignOpt SecurityMask = 0x02
)

type SecurityOption

type SecurityOption func(*Security)

SecurityOption represents the function on security context.

func Anonymize

func Anonymize() SecurityOption

The client is anonymous to the server. The server process can impersonate the client, but the impersonation token does not contain any information about the client. This level is only supported over the local interprocess communication transport. All other transports silently promote this level to identify.

func Delegate

func Delegate() SecurityOption

The most powerful impersonation level. When this level is selected, the server (whether local or remote) can impersonate the client's security context while acting on behalf of the client. During impersonation, the client's credentials (both local and network) can be passed to any number of computers.

func Identify

func Identify() SecurityOption

The server can obtain the client's identity, and the server can impersonate the client to do ACL checks.

func Impersonate

func Impersonate() SecurityOption

The server can impersonate the client's security context while acting on behalf of the client. The server can access local resources as the client. If the server is local, it can access network resources as the client. If the server is remote, it can access only resources that are on the same computer as the server.

func NoHeaderSign

func NoHeaderSign() SecurityOption

NoHeaderSign option disables the header signing.

func WithConnect

func WithConnect() SecurityOption

WithConnect option sepcifies the connect authentication level.

func WithInsecure

func WithInsecure() SecurityOption

WithInsecure option specifies the plain-text connection over RPC.

func WithSeal

func WithSeal() SecurityOption

WithSeal option specifies the connection with packet stub encryption.

func WithSecurityConfig

func WithSecurityConfig(cfg gssapi.MechanismConfig) SecurityOption

WithSecurityConfig option specifies the mechanism configuration.

Example:

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSecurityConfig(&krb5.Config{
	KRB5ConfPath:       "/tmp/my-krb.conf",
	CCachePath: 	    "/tmp/ccache",
	RequireHostAddress: true,
}))

func WithSecurityLevel

func WithSecurityLevel(lvl AuthLevel) SecurityOption

WithSecurityLevel option specifies the authenticate security level.

Use this option to specify the security level for the connection.

func WithSecurtyProvider

func WithSecurtyProvider(typ AuthType) SecurityOption

WithSecurityProvider option specifies the exact security provider.

Use this option to specify the security provider. Note, that security provider must be provisioned either globally, or using the GSSAPI security context option `WithMechanism`.

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSecurityProvider(dcerpc.AuthTypeKerberos), dcerpc.WithSeal())

func WithSign

func WithSign() SecurityOption

WithSign option specifies the connection with packet integrity check.

func WithTargetName

func WithTargetName(n string) SecurityOption

WithTargetName option specifies the target name.

Use this option to set the SSP target name:

cli, err := winreg.NewWinregClient(ctx, conn, dcerpc.WithSeal(), dcerpc.WithTargetName("host/contoso.svc.net"))

type SecurityTrailer

type SecurityTrailer struct {
	AuthType      AuthType
	AuthLevel     AuthLevel
	AuthPadLength uint8

	AuthContextID uint32
	// contains filtered or unexported fields
}

func (*SecurityTrailer) ReadFrom

func (st *SecurityTrailer) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*SecurityTrailer) WriteTo

func (st *SecurityTrailer) WriteTo(ctx context.Context, w ndr.Writer) error

type ServerHandle

type ServerHandle func(context.Context, int, ndr.Reader) (Operation, error)

ServerHandle is a function that must accept the incoming reader and operation number and return the operation response.

type Shutdown

type Shutdown struct{}

The ShutdownPDU is sent by the server to request that a client terminate the connection, freeing the related resources.

The ShutdownPDU never contains an authentication verifier even if authentication services are in use.

func (*Shutdown) MarshalZerologObject

func (pdu *Shutdown) MarshalZerologObject(e *zerolog.Event)

func (*Shutdown) ReadFrom

func (pdu *Shutdown) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Shutdown) WriteTo

func (pdu *Shutdown) WriteTo(ctx context.Context, w ndr.Writer) error

type StringBinding

type StringBinding struct {
	// The object UUID.
	ObjectUUID *uuid.UUID
	// The protocol sequence.
	ProtocolSequence ProtocolSequence
	// The IP/FQDN for the binding.
	NetworkAddress string
	// The NetBIOS computer name for named pipes.
	ComputerName string
	// The endpoint: port number for TCP/IP or HTTP,
	// named pipe name for SMB, or local IPC port for ALPC.
	Endpoint string
}

The string binding is an unsigned character string composed of strings that represent the binding object UUID, the RPC protocol sequence, the network address, and the endpoint and endpoint options.

func ParseStringBinding

func ParseStringBinding(s string) (*StringBinding, error)

ParseBinding function parses the string binding of format: [ 'ObjectUUID' '@' ] ProtocolSequence ':' NetworkAddress '[' Endpoint ']' [ NetworkAddress ] ':' Port

func (StringBinding) Complete

func (s StringBinding) Complete() bool

func (StringBinding) MarshalJSON

func (s StringBinding) MarshalJSON() ([]byte, error)

func (StringBinding) MatchTarget added in v1.0.1

func (s StringBinding) MatchTarget(n string) bool

MatchTarget function returns true if the target name of the string binding matches the provided target name n.

func (StringBinding) NamedPipe

func (s StringBinding) NamedPipe() string

func (StringBinding) ShareName

func (s StringBinding) ShareName() string

func (StringBinding) String

func (s StringBinding) String() string

func (StringBinding) TargetName added in v1.0.1

func (s StringBinding) TargetName() string

func (StringBinding) URL

func (s StringBinding) URL() *url.URL

func (StringBinding) URLWithSyntax

func (s StringBinding) URLWithSyntax(syntax SyntaxID, uConvs ...ConvertUUID) *url.URL

URLWithSyntax function returns the URL with syntax interface identifier and version.

type SyntaxID

type SyntaxID struct {
	IfUUID         *uuid.UUID
	IfVersionMajor uint16
	IfVersionMinor uint16
}

SyntaxID ...

func NewBindFeatureSyntaxV1_0

func NewBindFeatureSyntaxV1_0(flags ProviderReason) *SyntaxID

NewBindFeatureSyntaxV1_0 function returns the bind-feature negotiation flags.

func ParseSyntaxID added in v1.0.3

func ParseSyntaxID(s string) (*SyntaxID, error)

func (*SyntaxID) ReadFrom

func (v *SyntaxID) ReadFrom(ctx context.Context, r ndr.Reader) error

ReadFrom function ...

func (*SyntaxID) WriteTo

func (v *SyntaxID) WriteTo(ctx context.Context, w ndr.Writer) error

marshal function ...

type Transport

type Transport struct {
	// The receive buffer size.
	MaxRecvFrag int
	// The transmit buffer size.
	MaxXmitFrag int
	// The association group identifier.
	GroupID int
	// The hostname.
	HostName string
	// Clients that implement MS-RPCE extensions SHOULD ignore the
	// secondary endpoint address.
	SecondaryAddr string
	// The data representation for the connection.
	DataRepresentation ndr.DataRepresentation
	// Once concurrent multiplexing on a connection is negotiated,
	// a client is allowed to send another request on a connection
	// before it receives a response on a previous request
	Multiplexing bool
	// The server supports keeping the connection open after an
	// orphaned PDU is received.
	KeepConnOpenOnOrphaned bool
	// If this flag is set to `true` it is allowed for a client
	// to use more than one security context per connection.
	SecurityContextMultiplexing bool
	// The number of security contexts established for this
	// connection.
	SecurityContextCount int
	// The number of allowed outstanding calls.
	MultiplexingOutstandingCalls int
	// The network interaction timeout.
	Timeout time.Duration
	// The programmable operation deadline for deecoding and
	// encryption/decryption.
	Deadline time.Duration
	// SMB port.
	SMBPort int
	// SMB dialer.
	SMBDialer *smb2.Dialer
	// Endpoint Mapper.
	EndpointMapper EndpointMapper
	// Preferred protocol sequence.
	StringBinding StringBinding
	// If set to `true`, new connection will be established
	// for every new client with matching binding.
	NoReuseTransport bool
}

The transport settings.

func NewTransport

func NewTransport() Transport

NewTransport function returns the default transport configuration.

func (Transport) FragmentSize

func (s Transport) FragmentSize() int

BufferSize function returns the biggest number between max_recv_frag and max_xmit_frag.

func (Transport) IsSecurityMultiplexed

func (s Transport) IsSecurityMultiplexed() bool

IsSecurityMultiplexed function returns `true` if security multiplexing is enabled and there are more than one security context captured.

func (Transport) MarshalZerologObject

func (s Transport) MarshalZerologObject(e *zerolog.Event)

type VerificationCommand

type VerificationCommand struct {
	CommandType CommandType
	Required    bool
	Command     any
}

func (VerificationCommand) Type

type VerificationTrailer

type VerificationTrailer struct {
	Commands []*VerificationCommand
}

func (*VerificationTrailer) ReadFrom

func (o *VerificationTrailer) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*VerificationTrailer) Size

func (o *VerificationTrailer) Size() int

func (*VerificationTrailer) VerificationTrailer

func (o *VerificationTrailer) VerificationTrailer() VerificationTrailer

func (*VerificationTrailer) WriteTo

func (o *VerificationTrailer) WriteTo(ctx context.Context, w ndr.Writer) error

type VerifyBitMask

type VerifyBitMask uint32

The bits field is a bitmask. A server MUST ignore bits it does not understand. Currently, there is only one bit defined: CLIENT_SUPPORT_HEADER_SIGNING (bitmask of 0x00000001). If this bit is set, the PFC_SUPPORT_HEADER_SIGN bit, MUST be present in the PDU header for the bind PDU on this connection.

var (
	// If this bit is set, the PFC_SUPPORT_HEADER_SIGN bit, MUST be present
	// in the PDU header for the bind PDU on this connection.
	VerifyBitMaskSupportHeaderSign VerifyBitMask = 0x00000001
)

func (*VerifyBitMask) ReadFrom

func (o *VerifyBitMask) ReadFrom(ctx context.Context, r ndr.Reader) error

func (VerifyBitMask) WriteTo

func (o VerifyBitMask) WriteTo(ctx context.Context, w ndr.Writer) error

type VerifyHeader2

type VerifyHeader2 struct {
	// MUST be the same as the PTYPE field in the request PDU header.
	PacketType PacketType

	// MUST be the same as the drep field in the request PDU header.
	PacketDRep ndr.DataRepresentation
	// MUST be the same as the call_id field in the request PDU header.
	CallID uint32
	// MUST be the same as the p_cont_id field in the request PDU header.
	ContextID uint16
	// MUST be the same as the opnum field in the request PDU header.
	OpNum uint16
	// contains filtered or unexported fields
}

func (*VerifyHeader2) ReadFrom

func (o *VerifyHeader2) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*VerifyHeader2) WriteTo

func (o *VerifyHeader2) WriteTo(ctx context.Context, w ndr.Writer) error

type VerifyPresentation

type VerifyPresentation struct {
	// The interface identifier for the presentation context of the
	// request PDU in which this verification trailer appears. This value
	// MUST match the chosen abstract_syntax field from the bind or
	// alter_context PDU where the presentation context was negotiated.
	InterfaceID *SyntaxID
	// The transfer syntax identifier for the presentation context of
	// the request PDU in which this verification trailer appears. This
	// value MUST match the chosen transfer_syntax from the bind or
	// alter_context PDU where the presentation context was negotiated.
	TransferSyntax *SyntaxID
}

func (*VerifyPresentation) ReadFrom

func (o *VerifyPresentation) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*VerifyPresentation) WriteTo

func (o *VerifyPresentation) WriteTo(ctx context.Context, w ndr.Writer) error

type Version

type Version struct {
	Major uint8
	Minor uint8
}

Version structure specifies the protocol version.

func (*Version) ReadFrom

func (version *Version) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*Version) WriteTo

func (version *Version) WriteTo(ctx context.Context, w ndr.Writer) error

type VersionList

type VersionList struct {
	NProtocols uint8
	Versions   []*Version
}

func (*VersionList) ReadFrom

func (vl *VersionList) ReadFrom(ctx context.Context, r ndr.Reader) error

func (*VersionList) WriteTo

func (vl *VersionList) WriteTo(ctx context.Context, w ndr.Writer) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL