Scott Baker | 2c1c482 | 2019-10-16 11:02:41 -0700 | [diff] [blame] | 1 | package ndr |
| 2 | |
| 3 | import ( |
| 4 | "encoding/binary" |
| 5 | "fmt" |
| 6 | ) |
| 7 | |
| 8 | /* |
| 9 | Serialization Version 1 |
| 10 | https://msdn.microsoft.com/en-us/library/cc243563.aspx |
| 11 | |
| 12 | Common Header - https://msdn.microsoft.com/en-us/library/cc243890.aspx |
| 13 | 8 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 | |
| 20 | Private Header - https://msdn.microsoft.com/en-us/library/cc243919.aspx |
| 21 | 8 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 | |
| 26 | const ( |
| 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 |
| 40 | type 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 |
| 50 | type PrivateHeader struct { |
| 51 | ObjectBufferLength uint32 |
| 52 | Filler []byte |
| 53 | } |
| 54 | |
| 55 | func (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 | |
| 101 | func (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 | } |