package msrpc
import (
"encoding/binary"
"encoding/hex"
"github.com/hirochachacha/go-smb2/internal/utf16le"
)
var le = binary .LittleEndian
func roundup(x , align int ) int {
return (x + (align - 1 )) &^ (align - 1 )
}
const (
RPC_VERSION = 5
RPC_VERSION_MINOR = 0
RPC_TYPE_REQUEST = 0
RPC_TYPE_RESPONSE = 2
RPC_TYPE_BIND = 11
RPC_TYPE_BIND_ACK = 12
RPC_PACKET_FLAG_FIRST = 0x01
RPC_PACKET_FLAG_LAST = 0x02
SRVSVC_VERSION = 3
SRVSVC_VERSION_MINOR = 0
NDR_VERSION = 2
OP_NET_SHARE_ENUM = 15
)
var (
SRVSVC_UUID = []byte ("c84f324b7016d30112785a47bf6ee188" )
NDR_UUID = []byte ("045d888aeb1cc9119fe808002b104860" )
)
type Bind struct {
CallId uint32
}
func (r *Bind ) Size () int {
return 72
}
func (r *Bind ) Encode (b []byte ) {
b [0 ] = RPC_VERSION
b [1 ] = RPC_VERSION_MINOR
b [2 ] = RPC_TYPE_BIND
b [3 ] = RPC_PACKET_FLAG_FIRST | RPC_PACKET_FLAG_LAST
b [4 ] = 0x10
b [5 ] = 0
b [6 ] = 0
b [7 ] = 0
le .PutUint16 (b [8 :10 ], 72 )
le .PutUint16 (b [10 :12 ], 0 )
le .PutUint32 (b [12 :16 ], r .CallId )
le .PutUint16 (b [16 :18 ], 4280 )
le .PutUint16 (b [18 :20 ], 4280 )
le .PutUint32 (b [20 :24 ], 0 )
le .PutUint32 (b [24 :28 ], 1 )
le .PutUint16 (b [28 :30 ], 0 )
le .PutUint16 (b [30 :32 ], 1 )
hex .Decode (b [32 :48 ], SRVSVC_UUID )
le .PutUint16 (b [48 :50 ], SRVSVC_VERSION )
le .PutUint16 (b [50 :52 ], SRVSVC_VERSION_MINOR )
hex .Decode (b [52 :68 ], NDR_UUID )
le .PutUint32 (b [68 :72 ], NDR_VERSION )
}
type BindAckDecoder []byte
func (c BindAckDecoder ) IsInvalid () bool {
if len (c ) < 24 {
return true
}
if c .Version () != RPC_VERSION {
return true
}
if c .VersionMinor () != RPC_VERSION_MINOR {
return true
}
if c .PacketType () != RPC_TYPE_BIND_ACK {
return true
}
return false
}
func (c BindAckDecoder ) Version () uint8 {
return c [0 ]
}
func (c BindAckDecoder ) VersionMinor () uint8 {
return c [1 ]
}
func (c BindAckDecoder ) PacketType () uint8 {
return c [2 ]
}
func (c BindAckDecoder ) PacketFlags () uint8 {
return c [3 ]
}
func (c BindAckDecoder ) DataRepresentation () []byte {
return c [4 :8 ]
}
func (c BindAckDecoder ) FragLength () uint16 {
return le .Uint16 (c [8 :10 ])
}
func (c BindAckDecoder ) AuthLength () uint16 {
return le .Uint16 (c [10 :12 ])
}
func (c BindAckDecoder ) CallId () uint32 {
return le .Uint32 (c [12 :16 ])
}
func (c BindAckDecoder ) MaxXmitFrag () uint16 {
return le .Uint16 (c [16 :18 ])
}
func (c BindAckDecoder ) MaxRecvFrag () uint16 {
return le .Uint16 (c [18 :20 ])
}
func (c BindAckDecoder ) AssocGroupId () uint32 {
return le .Uint32 (c [20 :24 ])
}
type NetShareEnumAllRequest struct {
CallId uint32
ServerName string
Level uint32
}
func (r *NetShareEnumAllRequest ) Size () int {
off := 40 + utf16le .EncodedStringLen (r .ServerName ) + 2
off = roundup (off , 4 )
off += 24
off += 4
return off
}
func (r *NetShareEnumAllRequest ) Encode (b []byte ) {
b [0 ] = RPC_VERSION
b [1 ] = RPC_VERSION_MINOR
b [2 ] = RPC_TYPE_REQUEST
b [3 ] = RPC_PACKET_FLAG_FIRST | RPC_PACKET_FLAG_LAST
b [4 ] = 0x10
b [5 ] = 0
b [6 ] = 0
b [7 ] = 0
le .PutUint16 (b [10 :12 ], 0 )
le .PutUint32 (b [12 :16 ], r .CallId )
le .PutUint16 (b [20 :22 ], 0 )
le .PutUint16 (b [22 :24 ], OP_NET_SHARE_ENUM )
le .PutUint32 (b [24 :28 ], 0x20000 )
count := utf16le .EncodedStringLen (r .ServerName )/2 + 1
le .PutUint32 (b [28 :32 ], uint32 (count ))
le .PutUint32 (b [32 :36 ], 0 )
le .PutUint32 (b [36 :40 ], uint32 (count ))
utf16le .EncodeString (b [40 :], r .ServerName )
off := 40 + count *2
off = roundup (off , 4 )
le .PutUint32 (b [off :off +4 ], r .Level )
le .PutUint32 (b [off +4 :off +8 ], 1 )
le .PutUint32 (b [off +8 :off +12 ], 0x20004 )
le .PutUint32 (b [off +12 :off +16 ], 0 )
le .PutUint32 (b [off +16 :off +20 ], 0 )
le .PutUint32 (b [off +20 :off +24 ], 0xffffffff )
off += 24
le .PutUint32 (b [off :off +4 ], 0 )
off += 4
le .PutUint16 (b [8 :10 ], uint16 (off ))
le .PutUint32 (b [16 :20 ], uint32 (off -24 ))
}
type NetShareEnumAllResponseDecoder []byte
func (c NetShareEnumAllResponseDecoder ) IsInvalid () bool {
if len (c ) < 24 {
return true
}
if c .Version () != RPC_VERSION {
return true
}
if c .VersionMinor () != RPC_VERSION_MINOR {
return true
}
if c .PacketType () != RPC_TYPE_RESPONSE {
return true
}
return false
}
func (c NetShareEnumAllResponseDecoder ) Version () uint8 {
return c [0 ]
}
func (c NetShareEnumAllResponseDecoder ) VersionMinor () uint8 {
return c [1 ]
}
func (c NetShareEnumAllResponseDecoder ) PacketType () uint8 {
return c [2 ]
}
func (c NetShareEnumAllResponseDecoder ) PacketFlags () uint8 {
return c [3 ]
}
func (c NetShareEnumAllResponseDecoder ) DataRepresentation () []byte {
return c [4 :8 ]
}
func (c NetShareEnumAllResponseDecoder ) FragLength () uint16 {
return le .Uint16 (c [8 :10 ])
}
func (c NetShareEnumAllResponseDecoder ) AuthLength () uint16 {
return le .Uint16 (c [10 :12 ])
}
func (c NetShareEnumAllResponseDecoder ) CallId () uint32 {
return le .Uint32 (c [12 :16 ])
}
func (c NetShareEnumAllResponseDecoder ) AllocHint () uint32 {
return le .Uint32 (c [16 :20 ])
}
func (c NetShareEnumAllResponseDecoder ) ContextId () uint16 {
return le .Uint16 (c [20 :22 ])
}
func (c NetShareEnumAllResponseDecoder ) CancelCount () uint8 {
return c [22 ]
}
func (c NetShareEnumAllResponseDecoder ) IsIncomplete () bool {
if len (c ) < 48 {
return true
}
level := le .Uint32 (c [24 :28 ])
count := int (le .Uint32 (c [36 :40 ]))
switch level {
case 0 :
offset := 48 + count *4
if len (c ) < offset {
return true
}
for i := 0 ; i < count ; i ++ {
if len (c ) < offset +12 {
return true
}
noff := int (le .Uint32 (c [offset +4 : offset +8 ]))
nlen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
offset = roundup (offset +12 +noff +nlen , 4 )
if len (c ) < offset {
return true
}
}
case 1 :
offset := 48 + count *12
if len (c ) < offset {
return true
}
for i := 0 ; i < count ; i ++ {
{
if len (c ) < offset +12 {
return true
}
noff := int (le .Uint32 (c [offset +4 : offset +8 ]))
nlen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
offset = roundup (offset +12 +noff +nlen , 4 )
if len (c ) < offset {
return true
}
}
{
if len (c ) < offset +12 {
return true
}
coff := int (le .Uint32 (c [offset +4 : offset +8 ]))
clen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
offset = roundup (offset +12 +coff +clen , 4 )
if len (c ) < offset {
return true
}
}
}
default :
return true
}
return false
}
func (c NetShareEnumAllResponseDecoder ) Buffer () []byte {
return c [24 :]
}
func (c NetShareEnumAllResponseDecoder ) ShareNameList () []string {
level := le .Uint32 (c [24 :28 ])
count := int (le .Uint32 (c [36 :40 ]))
ss := make ([]string , count )
switch level {
case 0 :
offset := 48 + count *4
for i := 0 ; i < count ; i ++ {
noff := int (le .Uint32 (c [offset +4 : offset +8 ]))
nlen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
ss [i ] = utf16le .DecodeToString (c [offset +12 +noff : offset +12 +noff +nlen ])
offset = roundup (offset +12 +noff +nlen , 4 )
}
case 1 :
offset := 48 + count *12
for i := 0 ; i < count ; i ++ {
{
noff := int (le .Uint32 (c [offset +4 : offset +8 ]))
nlen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
ss [i ] = utf16le .DecodeToString (c [offset +12 +noff : offset +12 +noff +nlen ])
offset = roundup (offset +12 +noff +nlen , 4 )
}
{
coff := int (le .Uint32 (c [offset +4 : offset +8 ]))
clen := int (le .Uint32 (c [offset +8 :offset +12 ])) * 2
offset = roundup (offset +12 +coff +clen , 4 )
}
}
default :
return nil
}
return ss
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .