Files
ShotRDP/grdp/protocol/pdu/data.go
2025-02-20 12:31:02 +08:00

1055 lines
29 KiB
Go

package pdu
import (
"bytes"
"errors"
"fmt"
"io"
"ShotRDP/grdp/core"
"ShotRDP/grdp/glog"
"github.com/lunixbochs/struc"
)
const (
PDUTYPE_DEMANDACTIVEPDU = 0x11
PDUTYPE_CONFIRMACTIVEPDU = 0x13
PDUTYPE_DEACTIVATEALLPDU = 0x16
PDUTYPE_DATAPDU = 0x17
PDUTYPE_SERVER_REDIR_PKT = 0x1A
)
type PduType2 uint8
const (
PDUTYPE2_UPDATE = 0x02
PDUTYPE2_CONTROL = 0x14
PDUTYPE2_POINTER = 0x1B
PDUTYPE2_INPUT = 0x1C
PDUTYPE2_SYNCHRONIZE = 0x1F
PDUTYPE2_REFRESH_RECT = 0x21
PDUTYPE2_PLAY_SOUND = 0x22
PDUTYPE2_SUPPRESS_OUTPUT = 0x23
PDUTYPE2_SHUTDOWN_REQUEST = 0x24
PDUTYPE2_SHUTDOWN_DENIED = 0x25
PDUTYPE2_SAVE_SESSION_INFO = 0x26
PDUTYPE2_FONTLIST = 0x27
PDUTYPE2_FONTMAP = 0x28
PDUTYPE2_SET_KEYBOARD_INDICATORS = 0x29
PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST = 0x2B
PDUTYPE2_BITMAPCACHE_ERROR_PDU = 0x2C
PDUTYPE2_SET_KEYBOARD_IME_STATUS = 0x2D
PDUTYPE2_OFFSCRCACHE_ERROR_PDU = 0x2E
PDUTYPE2_SET_ERROR_INFO_PDU = 0x2F
PDUTYPE2_DRAWNINEGRID_ERROR_PDU = 0x30
PDUTYPE2_DRAWGDIPLUS_ERROR_PDU = 0x31
PDUTYPE2_ARC_STATUS_PDU = 0x32
PDUTYPE2_STATUS_INFO_PDU = 0x36
PDUTYPE2_MONITOR_LAYOUT_PDU = 0x37
)
func (p PduType2) String() string {
switch p {
case PDUTYPE2_UPDATE:
return "PDUTYPE2_UPDATE"
case PDUTYPE2_CONTROL:
return "PDUTYPE2_CONTROL"
case PDUTYPE2_POINTER:
return "PDUTYPE2_POINTER"
case PDUTYPE2_INPUT:
return "PDUTYPE2_INPUT"
case PDUTYPE2_SYNCHRONIZE:
return "PDUTYPE2_SYNCHRONIZE"
case PDUTYPE2_REFRESH_RECT:
return "PDUTYPE2_REFRESH_RECT"
case PDUTYPE2_PLAY_SOUND:
return "PDUTYPE2_PLAY_SOUND"
case PDUTYPE2_SUPPRESS_OUTPUT:
return "PDUTYPE2_SUPPRESS_OUTPUT"
case PDUTYPE2_SHUTDOWN_REQUEST:
return "PDUTYPE2_SHUTDOWN_REQUEST"
case PDUTYPE2_SHUTDOWN_DENIED:
return "PDUTYPE2_SHUTDOWN_DENIED"
case PDUTYPE2_SAVE_SESSION_INFO:
return "PDUTYPE2_SAVE_SESSION_INFO"
case PDUTYPE2_FONTLIST:
return "PDUTYPE2_FONTLIST"
case PDUTYPE2_FONTMAP:
return "PDUTYPE2_FONTMAP"
case PDUTYPE2_SET_KEYBOARD_INDICATORS:
return "PDUTYPE2_SET_KEYBOARD_INDICATORS"
case PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST:
return "PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST"
case PDUTYPE2_BITMAPCACHE_ERROR_PDU:
return "PDUTYPE2_BITMAPCACHE_ERROR_PDU"
case PDUTYPE2_SET_KEYBOARD_IME_STATUS:
return "PDUTYPE2_SET_KEYBOARD_IME_STATUS"
case PDUTYPE2_OFFSCRCACHE_ERROR_PDU:
return "PDUTYPE2_OFFSCRCACHE_ERROR_PDU"
case PDUTYPE2_SET_ERROR_INFO_PDU:
return "PDUTYPE2_SET_ERROR_INFO_PDU"
case PDUTYPE2_DRAWNINEGRID_ERROR_PDU:
return "PDUTYPE2_DRAWNINEGRID_ERROR_PDU"
case PDUTYPE2_DRAWGDIPLUS_ERROR_PDU:
return "PDUTYPE2_DRAWGDIPLUS_ERROR_PDU"
case PDUTYPE2_ARC_STATUS_PDU:
return "PDUTYPE2_ARC_STATUS_PDU"
case PDUTYPE2_STATUS_INFO_PDU:
return "PDUTYPE2_STATUS_INFO_PDU"
case PDUTYPE2_MONITOR_LAYOUT_PDU:
return "PDUTYPE2_MONITOR_LAYOUT_PDU"
}
return "Unknown"
}
const (
CTRLACTION_REQUEST_CONTROL = 0x0001
CTRLACTION_GRANTED_CONTROL = 0x0002
CTRLACTION_DETACH = 0x0003
CTRLACTION_COOPERATE = 0x0004
)
const (
STREAM_UNDEFINED = 0x00
STREAM_LOW = 0x01
STREAM_MED = 0x02
STREAM_HI = 0x04
)
type FastPathUpdateType uint8
const (
FASTPATH_UPDATETYPE_ORDERS = 0x0
FASTPATH_UPDATETYPE_BITMAP = 0x1
FASTPATH_UPDATETYPE_PALETTE = 0x2
FASTPATH_UPDATETYPE_SYNCHRONIZE = 0x3
FASTPATH_UPDATETYPE_SURFCMDS = 0x4
FASTPATH_UPDATETYPE_PTR_NULL = 0x5
FASTPATH_UPDATETYPE_PTR_DEFAULT = 0x6
FASTPATH_UPDATETYPE_PTR_POSITION = 0x8
FASTPATH_UPDATETYPE_COLOR = 0x9
FASTPATH_UPDATETYPE_CACHED = 0xA
FASTPATH_UPDATETYPE_POINTER = 0xB
FASTPATH_UPDATETYPE_LARGE_POINTER = 0xC
)
func (t FastPathUpdateType) String() string {
switch t {
case FASTPATH_UPDATETYPE_ORDERS:
return "FASTPATH_UPDATETYPE_ORDERS"
case FASTPATH_UPDATETYPE_BITMAP:
return "FASTPATH_UPDATETYPE_BITMAP"
case FASTPATH_UPDATETYPE_PALETTE:
return "FASTPATH_UPDATETYPE_PALETTE"
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
return "FASTPATH_UPDATETYPE_SYNCHRONIZE"
case FASTPATH_UPDATETYPE_SURFCMDS:
return "FASTPATH_UPDATETYPE_SURFCMDS"
case FASTPATH_UPDATETYPE_PTR_NULL:
return "FASTPATH_UPDATETYPE_PTR_NULL"
case FASTPATH_UPDATETYPE_PTR_DEFAULT:
return "FASTPATH_UPDATETYPE_PTR_DEFAULT"
case FASTPATH_UPDATETYPE_PTR_POSITION:
return "FASTPATH_UPDATETYPE_PTR_POSITION"
case FASTPATH_UPDATETYPE_COLOR:
return "FASTPATH_UPDATETYPE_COLOR"
case FASTPATH_UPDATETYPE_CACHED:
return "FASTPATH_UPDATETYPE_CACHED"
case FASTPATH_UPDATETYPE_POINTER:
return "FASTPATH_UPDATETYPE_POINTER"
case FASTPATH_UPDATETYPE_LARGE_POINTER:
return "FASTPATH_UPDATETYPE_LARGE_POINTER"
}
return "Unknown"
}
const (
BITMAP_COMPRESSION = 0x0001
//NO_BITMAP_COMPRESSION_HDR = 0x0400
)
/* compression types */
const (
RDP_MPPC_BIG = 0x01
RDP_MPPC_COMPRESSED = 0x20
RDP_MPPC_RESET = 0x40
RDP_MPPC_FLUSH = 0x80
RDP_MPPC_DICT_SIZE = 65536
)
type ShareDataHeader struct {
SharedId uint32 `struc:"little"`
Padding1 uint8 `struc:"little"`
StreamId uint8 `struc:"little"`
UncompressedLength uint16 `struc:"little"`
PDUType2 uint8 `struc:"little"`
CompressedType uint8 `struc:"little"`
CompressedLength uint16 `struc:"little"`
}
func NewShareDataHeader(size int, type2 uint8, shareId uint32) *ShareDataHeader {
return &ShareDataHeader{
SharedId: shareId,
PDUType2: type2,
StreamId: STREAM_LOW,
UncompressedLength: uint16(size + 4),
}
}
type PDUMessage interface {
Type() uint16
Serialize() []byte
}
type DemandActivePDU struct {
SharedId uint32 `struc:"little"`
LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
LengthCombinedCapabilities uint16 `struc:"little"`
SourceDescriptor []byte `struc:"sizefrom=LengthSourceDescriptor"`
NumberCapabilities uint16 `struc:"little,sizeof=CapabilitySets"`
Pad2Octets uint16 `struc:"little"`
CapabilitySets []Capability `struc:"sizefrom=NumberCapabilities"`
SessionId uint32 `struc:"little"`
}
func (d *DemandActivePDU) Type() uint16 {
return PDUTYPE_DEMANDACTIVEPDU
}
func (d *DemandActivePDU) Serialize() []byte {
buff := &bytes.Buffer{}
core.WriteUInt32LE(d.SharedId, buff)
core.WriteUInt16LE(d.LengthSourceDescriptor, buff)
core.WriteUInt16LE(d.LengthCombinedCapabilities, buff)
core.WriteBytes([]byte(d.SourceDescriptor), buff)
core.WriteUInt16LE(uint16(len(d.CapabilitySets)), buff)
core.WriteUInt16LE(d.Pad2Octets, buff)
for _, cap := range d.CapabilitySets {
core.WriteUInt16LE(uint16(cap.Type()), buff)
capBuff := &bytes.Buffer{}
struc.Pack(capBuff, cap)
capBytes := capBuff.Bytes()
core.WriteUInt16LE(uint16(len(capBytes)+4), buff)
core.WriteBytes(capBytes, buff)
}
core.WriteUInt32LE(d.SessionId, buff)
return buff.Bytes()
}
func readDemandActivePDU(r io.Reader) (*DemandActivePDU, error) {
d := &DemandActivePDU{}
var err error
d.SharedId, err = core.ReadUInt32LE(r)
if err != nil {
return nil, err
}
d.LengthSourceDescriptor, err = core.ReadUint16LE(r)
d.LengthCombinedCapabilities, err = core.ReadUint16LE(r)
sourceDescriptorBytes, err := core.ReadBytes(int(d.LengthSourceDescriptor), r)
if err != nil {
return nil, err
}
d.SourceDescriptor = sourceDescriptorBytes
d.NumberCapabilities, err = core.ReadUint16LE(r)
d.Pad2Octets, err = core.ReadUint16LE(r)
d.CapabilitySets = make([]Capability, 0, d.NumberCapabilities)
glog.Debug("NumberCapabilities is", d.NumberCapabilities)
for i := 0; i < int(d.NumberCapabilities); i++ {
c, err := readCapability(r)
if err != nil {
//return nil, err
continue
}
d.CapabilitySets = append(d.CapabilitySets, c)
}
d.NumberCapabilities = uint16(len(d.CapabilitySets))
d.SessionId, err = core.ReadUInt32LE(r)
if err != nil {
return nil, err
}
return d, nil
}
type ConfirmActivePDU struct {
SharedId uint32 `struc:"little"`
OriginatorId uint16 `struc:"little"`
LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
LengthCombinedCapabilities uint16 `struc:"little"`
SourceDescriptor []byte `struc:"sizefrom=LengthSourceDescriptor"`
NumberCapabilities uint16 `struc:"little,sizeof=CapabilitySets"`
Pad2Octets uint16 `struc:"little"`
CapabilitySets []Capability `struc:"sizefrom=NumberCapabilities"`
}
func (*ConfirmActivePDU) Type() uint16 {
return PDUTYPE_CONFIRMACTIVEPDU
}
func (c *ConfirmActivePDU) Serialize() []byte {
buff := &bytes.Buffer{}
core.WriteUInt32LE(c.SharedId, buff)
core.WriteUInt16LE(c.OriginatorId, buff)
core.WriteUInt16LE(uint16(len(c.SourceDescriptor)), buff)
capsBuff := &bytes.Buffer{}
for _, capa := range c.CapabilitySets {
core.WriteUInt16LE(uint16(capa.Type()), capsBuff)
capBuff := &bytes.Buffer{}
struc.Pack(capBuff, capa)
capBytes := capBuff.Bytes()
core.WriteUInt16LE(uint16(len(capBytes)+4), capsBuff)
core.WriteBytes(capBytes, capsBuff)
}
capsBytes := capsBuff.Bytes()
core.WriteUInt16LE(uint16(2+2+len(capsBytes)), buff)
core.WriteBytes(c.SourceDescriptor, buff)
core.WriteUInt16LE(c.NumberCapabilities, buff)
core.WriteUInt16LE(c.Pad2Octets, buff)
core.WriteBytes(capsBytes, buff)
return buff.Bytes()
}
// 9401 => share control header
// 1300 => share control header
// ec03 => share control header
// ea030100 => shareId 66538
// ea03 => OriginatorId
// 0400
// 8001 => LengthCombinedCapabilities
// 72647079
// 0c00 => NumberCapabilities 12
// 0000
// caps below
// 010018000100030000020000000015040000000000000000
// 02001c00180001000100010000052003000000000100000001000000
// 030058000000000000000000000000000000000000000000010014000000010000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000008403000000000000000000
// 04002800000000000000000000000000000000000000000000000000000000000000000000000000
// 0800080000001400
// 0c00080000000000
// 0d005c001500000009040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000
// 0f00080000000000
// 10003400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
// 11000c000000000000000000
// 14000c000000000000000000
// 1a00080000000000
func NewConfirmActivePDU() *ConfirmActivePDU {
return &ConfirmActivePDU{
OriginatorId: 0x03EA,
CapabilitySets: make([]Capability, 0),
SourceDescriptor: []byte("rdpy"),
}
}
func readConfirmActivePDU(r io.Reader) (*ConfirmActivePDU, error) {
p := &ConfirmActivePDU{}
var err error
p.SharedId, err = core.ReadUInt32LE(r)
if err != nil {
return nil, err
}
p.OriginatorId, err = core.ReadUint16LE(r)
p.LengthSourceDescriptor, err = core.ReadUint16LE(r)
p.LengthCombinedCapabilities, err = core.ReadUint16LE(r)
sourceDescriptorBytes, err := core.ReadBytes(int(p.LengthSourceDescriptor), r)
if err != nil {
return nil, err
}
p.SourceDescriptor = sourceDescriptorBytes
p.NumberCapabilities, err = core.ReadUint16LE(r)
p.Pad2Octets, err = core.ReadUint16LE(r)
p.CapabilitySets = make([]Capability, 0)
for i := 0; i < int(p.NumberCapabilities); i++ {
c, err := readCapability(r)
if err != nil {
return nil, err
}
p.CapabilitySets = append(p.CapabilitySets, c)
}
s, _ := core.ReadUInt32LE(r)
glog.Info("sessionid:", s)
return p, nil
}
type DeactiveAllPDU struct {
ShareId uint32 `struc:"little"`
LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
SourceDescriptor []byte
}
func (*DeactiveAllPDU) Type() uint16 {
return PDUTYPE_DEACTIVATEALLPDU
}
func (d *DeactiveAllPDU) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, d)
return buff.Bytes()
}
func readDeactiveAllPDU(r io.Reader) (*DeactiveAllPDU, error) {
p := &DeactiveAllPDU{}
err := struc.Unpack(r, p)
return p, err
}
type DataPDU struct {
Header *ShareDataHeader
Data DataPDUData
}
func (*DataPDU) Type() uint16 {
return PDUTYPE_DATAPDU
}
func (d *DataPDU) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, d.Header)
struc.Pack(buff, d.Data)
return buff.Bytes()
}
func NewDataPDU(data DataPDUData, shareId uint32) *DataPDU {
dataBuff := &bytes.Buffer{}
struc.Pack(dataBuff, data)
return &DataPDU{
Header: NewShareDataHeader(len(dataBuff.Bytes()), data.Type2(), shareId),
Data: data,
}
}
func readDataPDU(r io.Reader) (*DataPDU, error) {
header := &ShareDataHeader{}
err := struc.Unpack(r, header)
if err != nil {
glog.Error("read data pdu header error", err)
return nil, err
}
var d DataPDUData
glog.Debugf("PDUType2 0x%02x", header.PDUType2)
switch header.PDUType2 {
case PDUTYPE2_UPDATE:
d = &UpdateDataPDU{}
case PDUTYPE2_SYNCHRONIZE:
d = &SynchronizeDataPDU{}
case PDUTYPE2_CONTROL:
d = &ControlDataPDU{}
case PDUTYPE2_FONTLIST:
d = &FontListDataPDU{}
case PDUTYPE2_SET_ERROR_INFO_PDU:
d = &ErrorInfoDataPDU{}
case PDUTYPE2_FONTMAP:
d = &FontMapDataPDU{}
case PDUTYPE2_SAVE_SESSION_INFO:
d = &SaveSessionInfo{}
default:
err = errors.New(fmt.Sprintf("Unknown data pdu type2 0x%02x", header.PDUType2))
glog.Error(err)
return nil, err
}
err = d.Unpack(r)
if err != nil {
glog.Error("Read data pdu:", err)
return nil, err
}
p := &DataPDU{
Header: header,
Data: d,
}
return p, nil
}
type DataPDUData interface {
Type2() uint8
Unpack(io.Reader) error
}
type UpdateDataPDU struct {
UpdateType uint16
Udata UpdateData
}
func (*UpdateDataPDU) Type2() uint8 {
return PDUTYPE2_UPDATE
}
func (d *UpdateDataPDU) Unpack(r io.Reader) (err error) {
//slow path update
d.UpdateType, err = core.ReadUint16LE(r)
glog.Debugf("UpdateType 0x%02x", d.UpdateType)
var p UpdateData
switch d.UpdateType {
case FASTPATH_UPDATETYPE_ORDERS:
case FASTPATH_UPDATETYPE_BITMAP:
p = &BitmapUpdateDataPDU{}
case FASTPATH_UPDATETYPE_PALETTE:
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
}
if p != nil {
err = p.Unpack(r)
if err != nil {
//glog.Error("Unpack:", err)
return err
}
} else {
return errors.New(fmt.Sprintf("Unsupport slow update type 0x%x", d.UpdateType))
}
d.Udata = p
return nil
}
type BitmapUpdateDataPDU struct {
NumberRectangles uint16 `struc:"little,sizeof=Rectangles"`
Rectangles []BitmapData
}
func (*BitmapUpdateDataPDU) FastPathUpdateType() uint8 {
return FASTPATH_UPDATETYPE_BITMAP
}
func (f *BitmapUpdateDataPDU) Unpack(r io.Reader) error {
var err error
f.NumberRectangles, err = core.ReadUint16LE(r)
f.Rectangles = make([]BitmapData, 0, f.NumberRectangles)
for i := 0; i < int(f.NumberRectangles); i++ {
rect := BitmapData{}
rect.DestLeft, err = core.ReadUint16LE(r)
rect.DestTop, err = core.ReadUint16LE(r)
rect.DestRight, err = core.ReadUint16LE(r)
rect.DestBottom, err = core.ReadUint16LE(r)
rect.Width, err = core.ReadUint16LE(r)
rect.Height, err = core.ReadUint16LE(r)
rect.BitsPerPixel, err = core.ReadUint16LE(r)
rect.Flags, err = core.ReadUint16LE(r)
rect.BitmapLength, err = core.ReadUint16LE(r)
ln := rect.BitmapLength
if rect.Flags&BITMAP_COMPRESSION != 0 && (rect.Flags&NO_BITMAP_COMPRESSION_HDR == 0) {
rect.BitmapComprHdr = new(BitmapCompressedDataHeader)
rect.BitmapComprHdr.CbCompFirstRowSize, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbCompMainBodySize, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbScanWidth, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbUncompressedSize, err = core.ReadUint16LE(r)
ln = rect.BitmapComprHdr.CbCompMainBodySize
}
rect.BitmapDataStream, err = core.ReadBytes(int(ln), r)
f.Rectangles = append(f.Rectangles, rect)
}
return err
}
type SynchronizeDataPDU struct {
MessageType uint16 `struc:"little"`
TargetUser uint16 `struc:"little"`
}
func (*SynchronizeDataPDU) Type2() uint8 {
return PDUTYPE2_SYNCHRONIZE
}
func NewSynchronizeDataPDU(targetUser uint16) *SynchronizeDataPDU {
return &SynchronizeDataPDU{
MessageType: 1,
TargetUser: targetUser,
}
}
func (d *SynchronizeDataPDU) Unpack(r io.Reader) error {
return struc.Unpack(r, d)
}
type ControlDataPDU struct {
Action uint16 `struc:"little"`
GrantId uint16 `struc:"little"`
ControlId uint32 `struc:"little"`
}
func (*ControlDataPDU) Type2() uint8 {
return PDUTYPE2_CONTROL
}
func (d *ControlDataPDU) Unpack(r io.Reader) error {
return struc.Unpack(r, d)
}
type FontListDataPDU struct {
NumberFonts uint16 `struc:"little"`
TotalNumFonts uint16 `struc:"little"`
ListFlags uint16 `struc:"little"`
EntrySize uint16 `struc:"little"`
}
func (*FontListDataPDU) Type2() uint8 {
return PDUTYPE2_FONTLIST
}
func (d *FontListDataPDU) Unpack(r io.Reader) error {
return struc.Unpack(r, d)
}
type ErrorInfoDataPDU struct {
ErrorInfo uint32 `struc:"little"`
}
func (*ErrorInfoDataPDU) Type2() uint8 {
return PDUTYPE2_SET_ERROR_INFO_PDU
}
func (d *ErrorInfoDataPDU) Unpack(r io.Reader) error {
return struc.Unpack(r, d)
}
type FontMapDataPDU struct {
NumberEntries uint16 `struc:"little"`
TotalNumEntries uint16 `struc:"little"`
MapFlags uint16 `struc:"little"`
EntrySize uint16 `struc:"little"`
}
func (*FontMapDataPDU) Type2() uint8 {
return PDUTYPE2_FONTMAP
}
func (d *FontMapDataPDU) Unpack(r io.Reader) error {
return struc.Unpack(r, d)
}
type InfoType uint32
const (
INFOTYPE_LOGON = 0x00000000
INFOTYPE_LOGON_LONG = 0x00000001
INFOTYPE_LOGON_PLAINNOTIFY = 0x00000002
INFOTYPE_LOGON_EXTENDED_INFO = 0x00000003
)
const (
LOGON_EX_AUTORECONNECTCOOKIE = 0x00000001
LOGON_EX_LOGONERRORS = 0x00000002
)
type LogonFields struct {
CbFileData uint32 `struc:"little"`
Len uint32 //28 `struc:"little"`
Version uint32 // 1 `struc:"little"`
LogonId uint32 `struc:"little"`
random [16]byte //16 `struc:"little"`
}
type SaveSessionInfo struct {
InfoType uint32
Length uint16
FieldsPresent uint32
LogonId uint32
Random []byte
}
func (s *SaveSessionInfo) logonInfoV1(r io.Reader) (err error) {
core.ReadUInt32LE(r) // cbDomain
b, _ := core.ReadBytes(52, r)
domain := core.UnicodeDecode(b)
core.ReadUInt32LE(r) // cbUserName
b, _ = core.ReadBytes(512, r)
userName := core.UnicodeDecode(b)
sessionId, _ := core.ReadUInt32LE(r)
s.LogonId = sessionId
glog.Infof("SessionId:[%d] UserName:[%s] Domain:[%s]", s.LogonId, userName, domain)
return err
}
func (s *SaveSessionInfo) logonInfoV2(r io.Reader) (err error) {
core.ReadUint16LE(r)
core.ReadUInt32LE(r)
sessionId, _ := core.ReadUInt32LE(r)
s.LogonId = sessionId
cbDomain, _ := core.ReadUInt32LE(r)
cbUserName, _ := core.ReadUInt32LE(r)
core.ReadBytes(558, r)
b, _ := core.ReadBytes(int(cbDomain), r)
domain := core.UnicodeDecode(b)
b, _ = core.ReadBytes(int(cbUserName), r)
userName := core.UnicodeDecode(b)
glog.Infof("SessionId:[%d] UserName:[ %s] Domain:[ %s]", s.LogonId, userName, domain)
return err
}
func (s *SaveSessionInfo) logonPlainNotify(r io.Reader) (err error) {
core.ReadBytes(576, r) /* pad (576 bytes) */
return err
}
func (s *SaveSessionInfo) logonInfoExtended(r io.Reader) (err error) {
s.Length, err = core.ReadUint16LE(r)
s.FieldsPresent, err = core.ReadUInt32LE(r)
//glog.Info("FieldsPresent:", s.FieldsPresent)
// auto reconnect cookie
if s.FieldsPresent&LOGON_EX_AUTORECONNECTCOOKIE != 0 {
core.ReadUInt32LE(r)
b, _ := core.ReadUInt32LE(r)
if b != 28 {
return errors.New(fmt.Sprintf("invalid length in Auto-Reconnect packet"))
}
b, _ = core.ReadUInt32LE(r)
if b != 1 {
return errors.New(fmt.Sprintf("unsupported version of Auto-Reconnect packet"))
}
b, _ = core.ReadUInt32LE(r)
s.LogonId = b
s.Random, _ = core.ReadBytes(16, r)
} else { // logon error info
core.ReadUInt32LE(r)
b, _ := core.ReadUInt32LE(r)
b, _ = core.ReadUInt32LE(r)
s.LogonId = b
}
core.ReadBytes(570, r)
return err
}
func (s *SaveSessionInfo) Unpack(r io.Reader) (err error) {
s.InfoType, err = core.ReadUInt32LE(r)
switch s.InfoType {
case INFOTYPE_LOGON:
err = s.logonInfoV1(r)
case INFOTYPE_LOGON_LONG:
err = s.logonInfoV2(r)
case INFOTYPE_LOGON_PLAINNOTIFY:
err = s.logonPlainNotify(r)
case INFOTYPE_LOGON_EXTENDED_INFO:
err = s.logonInfoExtended(r)
default:
glog.Errorf("Unhandled saveSessionInfo type 0x%x", s.InfoType)
return fmt.Errorf("Unhandled saveSessionInfo type 0x%x", s.InfoType)
}
return err
}
func (*SaveSessionInfo) Type2() uint8 {
return PDUTYPE2_SAVE_SESSION_INFO
}
type PersistKeyPDU struct {
NumEntriesCache0 uint16 `struc:"little"`
NumEntriesCache1 uint16 `struc:"little"`
NumEntriesCache2 uint16 `struc:"little"`
NumEntriesCache3 uint16 `struc:"little"`
NumEntriesCache4 uint16 `struc:"little"`
TotalEntriesCache0 uint16 `struc:"little"`
TotalEntriesCache1 uint16 `struc:"little"`
TotalEntriesCache2 uint16 `struc:"little"`
TotalEntriesCache3 uint16 `struc:"little"`
TotalEntriesCache4 uint16 `struc:"little"`
BBitMask uint8 `struc:"little"`
Pad1 uint8 `struc:"little"`
Ppad3 uint16 `struc:"little"`
}
func (*PersistKeyPDU) Type2() uint8 {
return PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST
}
type UpdateData interface {
FastPathUpdateType() uint8
Unpack(io.Reader) error
}
type BitmapCompressedDataHeader struct {
CbCompFirstRowSize uint16 `struc:"little"`
CbCompMainBodySize uint16 `struc:"little"`
CbScanWidth uint16 `struc:"little"`
CbUncompressedSize uint16 `struc:"little"`
}
type BitmapData struct {
DestLeft uint16 `struc:"little"`
DestTop uint16 `struc:"little"`
DestRight uint16 `struc:"little"`
DestBottom uint16 `struc:"little"`
Width uint16 `struc:"little"`
Height uint16 `struc:"little"`
BitsPerPixel uint16 `struc:"little"`
Flags uint16 `struc:"little"`
BitmapLength uint16 `struc:"little,sizeof=BitmapDataStream"`
BitmapComprHdr *BitmapCompressedDataHeader
BitmapDataStream []byte
}
func (b *BitmapData) IsCompress() bool {
return b.Flags&BITMAP_COMPRESSION != 0
}
type FastPathBitmapUpdateDataPDU struct {
Header uint16 `struc:"little"`
NumberRectangles uint16 `struc:"little,sizeof=Rectangles"`
Rectangles []BitmapData
}
func (f *FastPathBitmapUpdateDataPDU) Unpack(r io.Reader) error {
var err error
f.Header, err = core.ReadUint16LE(r)
f.NumberRectangles, err = core.ReadUint16LE(r)
f.Rectangles = make([]BitmapData, 0, f.NumberRectangles)
for i := 0; i < int(f.NumberRectangles); i++ {
rect := BitmapData{}
rect.DestLeft, err = core.ReadUint16LE(r)
rect.DestTop, err = core.ReadUint16LE(r)
rect.DestRight, err = core.ReadUint16LE(r)
rect.DestBottom, err = core.ReadUint16LE(r)
rect.Width, err = core.ReadUint16LE(r)
rect.Height, err = core.ReadUint16LE(r)
rect.BitsPerPixel, err = core.ReadUint16LE(r)
rect.Flags, err = core.ReadUint16LE(r)
rect.BitmapLength, err = core.ReadUint16LE(r)
ln := rect.BitmapLength
if rect.Flags&BITMAP_COMPRESSION != 0 && (rect.Flags&NO_BITMAP_COMPRESSION_HDR == 0) {
rect.BitmapComprHdr = new(BitmapCompressedDataHeader)
rect.BitmapComprHdr.CbCompFirstRowSize, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbCompMainBodySize, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbScanWidth, err = core.ReadUint16LE(r)
rect.BitmapComprHdr.CbUncompressedSize, err = core.ReadUint16LE(r)
ln = rect.BitmapComprHdr.CbCompMainBodySize
}
rect.BitmapDataStream, err = core.ReadBytes(int(ln), r)
f.Rectangles = append(f.Rectangles, rect)
}
return err
}
func (*FastPathBitmapUpdateDataPDU) FastPathUpdateType() uint8 {
return FASTPATH_UPDATETYPE_BITMAP
}
type FastPathColorPdu struct {
CacheIdx uint16
X uint16
Y uint16
Width uint16
Height uint16
MaskLen uint16 `struc:"little,sizeof=Mask"`
DataLen uint16 `struc:"little,sizeof=Data"`
Mask []byte
Data []byte
}
func (*FastPathColorPdu) FastPathUpdateType() uint8 {
return FASTPATH_UPDATETYPE_COLOR
}
func (f *FastPathColorPdu) Unpack(r io.Reader) error {
return struc.Unpack(r, f)
}
type FastPathSurfaceCmds struct {
}
func (*FastPathSurfaceCmds) FastPathUpdateType() uint8 {
return FASTPATH_UPDATETYPE_SURFCMDS
}
func (f *FastPathSurfaceCmds) Unpack(r io.Reader) error {
cmdType, _ := core.ReadUint16LE(r)
switch cmdType {
}
return nil
}
type FastPathUpdatePDU struct {
UpdateHeader uint8
Fragmentation uint8
CompressionFlags uint8
Size uint16
Data UpdateData
}
const (
FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
)
const (
FASTPATH_FRAGMENT_SINGLE = (0x0 << 4)
FASTPATH_FRAGMENT_LAST = (0x1 << 4)
FASTPATH_FRAGMENT_FIRST = (0x2 << 4)
FASTPATH_FRAGMENT_NEXT = (0x3 << 4)
)
func readFastPathUpdatePDU(r io.Reader, code uint8) (*FastPathUpdatePDU, error) {
f := &FastPathUpdatePDU{}
var err error
var d UpdateData
//glog.Debugf("FastPathPDU type %s(0x%x)", FastPathUpdateType(code), code)
switch code {
case FASTPATH_UPDATETYPE_ORDERS:
d = &FastPathOrdersPDU{}
case FASTPATH_UPDATETYPE_BITMAP:
d = &FastPathBitmapUpdateDataPDU{}
case FASTPATH_UPDATETYPE_PALETTE:
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
case FASTPATH_UPDATETYPE_SURFCMDS:
//d = &FastPathSurfaceCmds{}
case FASTPATH_UPDATETYPE_PTR_NULL:
case FASTPATH_UPDATETYPE_PTR_DEFAULT:
case FASTPATH_UPDATETYPE_PTR_POSITION:
case FASTPATH_UPDATETYPE_COLOR:
//d = &FastPathColorPdu{}
case FASTPATH_UPDATETYPE_CACHED:
case FASTPATH_UPDATETYPE_POINTER:
case FASTPATH_UPDATETYPE_LARGE_POINTER:
default:
glog.Debugf("Unknown FastPathPDU type 0x%x", code)
return f, errors.New(fmt.Sprintf("Unknown FastPathPDU type 0x%x", code))
}
if d != nil {
err = d.Unpack(r)
if err != nil {
//glog.Error("Unpack:", err)
return nil, err
}
} else {
return nil, errors.New(fmt.Sprintf("Unsupport FastPathPDU type 0x%x", code))
}
f.Data = d
return f, nil
}
type ShareControlHeader struct {
TotalLength uint16 `struc:"little"`
PDUType uint16 `struc:"little"`
PDUSource uint16 `struc:"little"`
}
type PDU struct {
ShareCtrlHeader *ShareControlHeader
Message PDUMessage
}
func NewPDU(userId uint16, message PDUMessage) *PDU {
pdu := &PDU{}
pdu.ShareCtrlHeader = &ShareControlHeader{
TotalLength: uint16(len(message.Serialize()) + 6),
PDUType: message.Type(),
PDUSource: userId,
}
pdu.Message = message
return pdu
}
func readPDU(r io.Reader) (*PDU, error) {
pdu := &PDU{}
var err error
header := &ShareControlHeader{}
err = struc.Unpack(r, header)
if err != nil {
return nil, err
}
pdu.ShareCtrlHeader = header
var d PDUMessage
switch pdu.ShareCtrlHeader.PDUType {
case PDUTYPE_DEMANDACTIVEPDU:
glog.Debug("PDUTYPE_DEMANDACTIVEPDU")
d, err = readDemandActivePDU(r)
case PDUTYPE_DATAPDU:
glog.Debug("PDUTYPE_DATAPDU")
d, err = readDataPDU(r)
case PDUTYPE_CONFIRMACTIVEPDU:
glog.Debug("PDUTYPE_CONFIRMACTIVEPDU")
d, err = readConfirmActivePDU(r)
case PDUTYPE_DEACTIVATEALLPDU:
glog.Debug("PDUTYPE_DEACTIVATEALLPDU")
d, err = readDeactiveAllPDU(r)
default:
glog.Errorf("PDU invalid pdu type: 0x%02x", pdu.ShareCtrlHeader.PDUType)
}
if err != nil {
return nil, err
}
pdu.Message = d
return pdu, err
}
func (p *PDU) serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, p.ShareCtrlHeader)
core.WriteBytes(p.Message.Serialize(), buff)
return buff.Bytes()
}
type SlowPathInputEvent struct {
EventTime uint32 `struc:"little"`
MessageType uint16 `struc:"little"`
Size int `struc:"skip"`
SlowPathInputData []byte `struc:"sizefrom=Size"`
}
type PointerEvent struct {
PointerFlags uint16 `struc:"little"`
XPos uint16 `struc:"little"`
YPos uint16 `struc:"little"`
}
func (p *PointerEvent) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, p)
return buff.Bytes()
}
type SynchronizeEvent struct {
Pad2Octets uint16 `struc:"little"`
ToggleFlags uint32 `struc:"little"`
}
func (p *SynchronizeEvent) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, p)
return buff.Bytes()
}
type ScancodeKeyEvent struct {
KeyboardFlags uint16 `struc:"little"`
KeyCode uint16 `struc:"little"`
Pad2Octets uint16 `struc:"little"`
}
func (p *ScancodeKeyEvent) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, p)
return buff.Bytes()
}
type UnicodeKeyEvent struct {
KeyboardFlags uint16 `struc:"little"`
Unicode uint16 `struc:"little"`
Pad2Octets uint16 `struc:"little"`
}
func (p *UnicodeKeyEvent) Serialize() []byte {
buff := &bytes.Buffer{}
struc.Pack(buff, p)
return buff.Bytes()
}
type ClientInputEventPDU struct {
NumEvents uint16 `struc:"little,sizeof=SlowPathInputEvents"`
Pad2Octets uint16 `struc:"little"`
SlowPathInputEvents []SlowPathInputEvent `struc:"little"`
}
func (*ClientInputEventPDU) Type2() uint8 {
return PDUTYPE2_INPUT
}
func (*ClientInputEventPDU) Unpack(io.Reader) error {
return nil
}