dtyp
import "github.com/TheManticoreProject/Manticore/network/dcerpc/dtyp"
Package dtyp provides the [MS-DTYP] common data types that recur across DCE/RPC interfaces (lsarpc, samr, srvsvc, …) as NDR-marshallable Go types, so each interface reuses one definition instead of redeclaring the same NDR-tagged structs.
The types are driven by the declarative reflection walker in network/dcerpc/ndr (struct tags, the Marshaler escape hatch where needed), so they compose into request/response structs exactly like an interface’s own structures. The package sits beside ndr and syntax rather than inside ndr: these are data types defined by a separate specification ([MS-DTYP], not the NDR transfer syntax), and they are version-neutral, used by both the connectionless (v4) and connection- oriented (v5) interfaces.
References:
- [MS-DTYP] Windows Data Types: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/cca27429-5689-4a16-b2b4-9325d93e4ba2
- [MS-DTYP] Appendix A: Full IDL: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/24637f2d-238b-4d22-b44d-fe54b024280c
- [C706] DCE 1.1: RPC, Chapter 14 “Transfer Syntax NDR”: https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm
Index
- type FILETIME
- type GUID
- type LARGE_INTEGER
- type LUID
- type RPC_SID
- type RPC_UNICODE_STRING
- type ULARGE_INTEGER
type FILETIME
FILETIME is the [MS-DTYP] 2.3.3 64-bit timestamp (100-nanosecond intervals since 1601-01-01 UTC) transmitted as two 32-bit halves, low then high. Unlike a bare uint64 it carries 4-octet NDR alignment because both members are 32-bit ([C706] section 14.2.2), matching how Windows lays it out on the wire.
type FILETIME struct {
DwLowDateTime uint32
DwHighDateTime uint32
}
func (FILETIME) Uint64
func (f FILETIME) Uint64() uint64
Uint64 returns the FILETIME as a single 64-bit value (high half in the upper 32 bits).
type GUID
GUID is the [MS-DTYP] 2.3.4.2 GUID in its NDR-marshallable form: Data1 (4 octets), Data2 (2), Data3 (2), and Data4 (8 opaque octets), for 16 octets total with 4-octet alignment. Data1/2/3 are little-endian integers; Data4 is transmitted verbatim.
The reflection walker cannot use windows/guid.GUID directly: its Go layout ends in a uint64, which over-aligns the struct to 8 and inserts interior padding, so it would marshal as 24 octets instead of 16. This type mirrors the wire layout exactly. Use NewGUID / GUID to convert to and from windows/guid.GUID.
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
func NewGUID
func NewGUID(g guid.GUID) GUID
NewGUID converts a windows/guid.GUID to its NDR GUID form.
func (GUID) GUID
func (g GUID) GUID() guid.GUID
GUID converts back to a windows/guid.GUID.
func (GUID) String
func (g GUID) String() string
String renders the GUID in the standard “D” format.
type LARGE\_INTEGER
LARGE_INTEGER is the [MS-DTYP] 2.3.5 signed 64-bit integer. It is a named type rather than a bare int64 so declarations read like the IDL and it carries 8-octet NDR alignment ([C706] section 14.2.2).
type LARGE_INTEGER int64
type LUID
LUID is the [MS-DTYP] 2.3.7 locally unique identifier: a 64-bit value split into a low (unsigned) and high (signed) 32-bit part, transmitted in that order. It is used pervasively for privilege identifiers (for example by LsarLookupPrivilegeValue).
type LUID struct {
LowPart uint32
HighPart int32
}
func LUIDFromUint64
func LUIDFromUint64(v uint64) LUID
LUIDFromUint64 splits a 64-bit value into a LUID.
func (LUID) Uint64
func (l LUID) Uint64() uint64
Uint64 returns the LUID as a single 64-bit value (HighPart in the upper 32 bits).
type RPC\_SID
RPC_SID is the [MS-DTYP] 2.4.2.3 marshallable security identifier. The SubAuthority member is a conformant array whose element count is given by SubAuthorityCount, so NDR hoists its maximum_count to the front of the structure ([C706] section 14.3.3.1); the walker derives both the hoisted count and SubAuthorityCount from the slice length, so callers set only SubAuthority (or use ParseSID).
IdentifierAuthority is a 6-octet big-endian value transmitted verbatim ([MS-DTYP] 2.4.1 RPC_SID_IDENTIFIER_AUTHORITY). SubAuthorityCount is capped at 15 by the spec.
type RPC_SID struct {
Revision uint8
SubAuthorityCount uint8
IdentifierAuthority [6]byte
SubAuthority []uint32 `ndr:"conformant,size_is=SubAuthorityCount"`
}
func ParseSID
func ParseSID(s string) (RPC_SID, error)
ParseSID parses a textual SID (“S-1-5-21-…”) into an RPC_SID, setting Revision, IdentifierAuthority, and the SubAuthority array (SubAuthorityCount is derived on marshal). The identifier authority may be decimal or 0x-prefixed hexadecimal.
func (RPC_SID) String
func (s RPC_SID) String() string
String renders the SID in the standard “S-R-I-S1-S2-…” textual form ([MS-DTYP] 2.4.2.1 SID String Format): authorities below 2^32 are decimal, larger ones hex.
type RPC\_UNICODE\_STRING
RPC_UNICODE_STRING is the [MS-DTYP] 2.3.10 counted Unicode string. It is the single most common string carrier in the LSA/SAMR interfaces and, unlike a bare NDR wide string, cannot be modeled by ndr.WSTR because of a byte-vs-char gotcha:
- Length and MaximumLength are counts in BYTES (each must be even), whereas
- Buffer is a unique pointer to a conformant-varying array of wchar whose maximum_count is MaximumLength/2 and actual_count is Length/2 — counts in CHARS.
The buffer carries no NUL terminator (it is a size\_is/length\_is array, not an NDR [string]). Modeling Buffer as a []uint16 tagged “unique,varying” lets the walker emit the referent id inline and the char-counted conformant-varying body deferred, so the buffers of an array of RPC_UNICODE_STRING are correctly emitted after the whole array (see issue #419).
The size_is/length_is divisor tags resolve the wchar array’s maximum_count to MaximumLength/2 and actual_count to Length/2, which differ from len(Buffer) whenever the buffer is over-allocated (MaximumLength > Length, as a server may advertise). Use NewUnicodeString to set the byte counts and buffer together.
type RPC_UNICODE_STRING struct {
Length uint16 // length of the string in bytes, excluding any terminator
MaximumLength uint16 // size of Buffer in bytes
Buffer []uint16 `ndr:"unique,varying,size_is=MaximumLength/2,length_is=Length/2"`
}
func NewUnicodeString
func NewUnicodeString(s string) RPC_UNICODE_STRING
NewUnicodeString builds an RPC_UNICODE_STRING from a Go string, encoding it to UTF-16 and setting Length and MaximumLength to the byte count (2 per code unit). An empty string yields a zero-length value with a NULL Buffer, matching the Windows representation of an empty counted string.
func (RPC_UNICODE_STRING) String
func (u RPC_UNICODE_STRING) String() string
String decodes the Buffer (truncated to Length/2 code units, as Length governs the valid portion) back to a Go string.
type ULARGE\_INTEGER
ULARGE_INTEGER is the [MS-DTYP] 2.3.13 unsigned 64-bit integer.
type ULARGE_INTEGER uint64