blob: 1970ddb600ec9f8779c4c93d7cd35edfb1559994 [file] [log] [blame]
Dinesh Belwalkare63f7f92019-11-22 23:11:16 +00001package ndr
2
3import (
4 "encoding/binary"
5 "fmt"
6)
7
8/*
9Serialization Version 1
10https://msdn.microsoft.com/en-us/library/cc243563.aspx
11
12Common Header - https://msdn.microsoft.com/en-us/library/cc243890.aspx
138 bytes in total:
14- First byte - Version: Must equal 1
15- Second byte - 1st 4 bits: Endianess (0=Big; 1=Little); 2nd 4 bits: Character Encoding (0=ASCII; 1=EBCDIC)
16- 3rd - Floating point representation (This does not seem to be the case in examples for Microsoft test sources)
17- 4th - Common Header Length: Must equal 8
18- 5th - 8th - Filler: MUST be set to 0xcccccccc on marshaling, and SHOULD be ignored during unmarshaling.
19
20Private Header - https://msdn.microsoft.com/en-us/library/cc243919.aspx
218 bytes in total:
22- First 4 bytes - Indicates the length of a serialized top-level type in the octet stream. It MUST include the padding length and exclude the header itself.
23- Second 4 bytes - Filler: MUST be set to 0 (zero) during marshaling, and SHOULD be ignored during unmarshaling.
24*/
25
26const (
27 protocolVersion uint8 = 1
28 commonHeaderBytes uint16 = 8
29 bigEndian = 0
30 littleEndian = 1
31 ascii uint8 = 0
32 ebcdic uint8 = 1
33 ieee uint8 = 0
34 vax uint8 = 1
35 cray uint8 = 2
36 ibm uint8 = 3
37)
38
39// CommonHeader implements the NDR common header: https://msdn.microsoft.com/en-us/library/cc243889.aspx
40type CommonHeader struct {
41 Version uint8
42 Endianness binary.ByteOrder
43 CharacterEncoding uint8
44 FloatRepresentation uint8
45 HeaderLength uint16
46 Filler []byte
47}
48
49// PrivateHeader implements the NDR private header: https://msdn.microsoft.com/en-us/library/cc243919.aspx
50type PrivateHeader struct {
51 ObjectBufferLength uint32
52 Filler []byte
53}
54
55func (dec *Decoder) readCommonHeader() error {
56 // Version
57 vb, err := dec.r.ReadByte()
58 if err != nil {
59 return Malformed{EText: "could not read first byte of common header for version"}
60 }
61 dec.ch.Version = uint8(vb)
62 if dec.ch.Version != protocolVersion {
63 return Malformed{EText: fmt.Sprintf("byte stream does not indicate a RPC Type serialization of version %v", protocolVersion)}
64 }
65 // Read Endianness & Character Encoding
66 eb, err := dec.r.ReadByte()
67 if err != nil {
68 return Malformed{EText: "could not read second byte of common header for endianness"}
69 }
70 endian := int(eb >> 4 & 0xF)
71 if endian != 0 && endian != 1 {
72 return Malformed{EText: "common header does not indicate a valid endianness"}
73 }
74 dec.ch.CharacterEncoding = uint8(vb & 0xF)
75 if dec.ch.CharacterEncoding != 0 && dec.ch.CharacterEncoding != 1 {
76 return Malformed{EText: "common header does not indicate a valid character encoding"}
77 }
78 switch endian {
79 case littleEndian:
80 dec.ch.Endianness = binary.LittleEndian
81 case bigEndian:
82 dec.ch.Endianness = binary.BigEndian
83 }
84 // Common header length
85 lb, err := dec.readBytes(2)
86 if err != nil {
87 return Malformed{EText: fmt.Sprintf("could not read common header length: %v", err)}
88 }
89 dec.ch.HeaderLength = dec.ch.Endianness.Uint16(lb)
90 if dec.ch.HeaderLength != commonHeaderBytes {
91 return Malformed{EText: "common header does not indicate a valid length"}
92 }
93 // Filler bytes
94 dec.ch.Filler, err = dec.readBytes(4)
95 if err != nil {
96 return Malformed{EText: fmt.Sprintf("could not read common header filler: %v", err)}
97 }
98 return nil
99}
100
101func (dec *Decoder) readPrivateHeader() error {
102 // The next 8 bytes after the common header comprise the RPC type marshalling private header for constructed types.
103 err := binary.Read(dec.r, dec.ch.Endianness, &dec.ph.ObjectBufferLength)
104 if err != nil {
105 return Malformed{EText: "could not read private header object buffer length"}
106 }
107 if dec.ph.ObjectBufferLength%8 != 0 {
108 return Malformed{EText: "object buffer length not a multiple of 8"}
109 }
110 // Filler bytes
111 dec.ph.Filler, err = dec.readBytes(4)
112 if err != nil {
113 return Malformed{EText: fmt.Sprintf("could not read private header filler: %v", err)}
114 }
115 return nil
116}