package ndr import ( "encoding/binary" "fmt" ) /* Serialization Version 1 https://msdn.microsoft.com/en-us/library/cc243563.aspx Common Header - https://msdn.microsoft.com/en-us/library/cc243890.aspx 8 bytes in total: - First byte - Version: Must equal 1 - Second byte - 1st 4 bits: Endianess (0=Big; 1=Little); 2nd 4 bits: Character Encoding (0=ASCII; 1=EBCDIC) - 3rd - Floating point representation (This does not seem to be the case in examples for Microsoft test sources) - 4th - Common Header Length: Must equal 8 - 5th - 8th - Filler: MUST be set to 0xcccccccc on marshaling, and SHOULD be ignored during unmarshaling. Private Header - https://msdn.microsoft.com/en-us/library/cc243919.aspx 8 bytes in total: - 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. - Second 4 bytes - Filler: MUST be set to 0 (zero) during marshaling, and SHOULD be ignored during unmarshaling. */ const ( protocolVersion uint8 = 1 commonHeaderBytes uint16 = 8 bigEndian = 0 littleEndian = 1 ascii uint8 = 0 ebcdic uint8 = 1 ieee uint8 = 0 vax uint8 = 1 cray uint8 = 2 ibm uint8 = 3 ) // CommonHeader implements the NDR common header: https://msdn.microsoft.com/en-us/library/cc243889.aspx type CommonHeader struct { Version uint8 Endianness binary.ByteOrder CharacterEncoding uint8 FloatRepresentation uint8 HeaderLength uint16 Filler []byte } // PrivateHeader implements the NDR private header: https://msdn.microsoft.com/en-us/library/cc243919.aspx type PrivateHeader struct { ObjectBufferLength uint32 Filler []byte } func (dec *Decoder) readCommonHeader() error { // Version vb, err := dec.r.ReadByte() if err != nil { return Malformed{EText: "could not read first byte of common header for version"} } dec.ch.Version = uint8(vb) if dec.ch.Version != protocolVersion { return Malformed{EText: fmt.Sprintf("byte stream does not indicate a RPC Type serialization of version %v", protocolVersion)} } // Read Endianness & Character Encoding eb, err := dec.r.ReadByte() if err != nil { return Malformed{EText: "could not read second byte of common header for endianness"} } endian := int(eb >> 4 & 0xF) if endian != 0 && endian != 1 { return Malformed{EText: "common header does not indicate a valid endianness"} } dec.ch.CharacterEncoding = uint8(vb & 0xF) if dec.ch.CharacterEncoding != 0 && dec.ch.CharacterEncoding != 1 { return Malformed{EText: "common header does not indicate a valid character encoding"} } switch endian { case littleEndian: dec.ch.Endianness = binary.LittleEndian case bigEndian: dec.ch.Endianness = binary.BigEndian } // Common header length lb, err := dec.readBytes(2) if err != nil { return Malformed{EText: fmt.Sprintf("could not read common header length: %v", err)} } dec.ch.HeaderLength = dec.ch.Endianness.Uint16(lb) if dec.ch.HeaderLength != commonHeaderBytes { return Malformed{EText: "common header does not indicate a valid length"} } // Filler bytes dec.ch.Filler, err = dec.readBytes(4) if err != nil { return Malformed{EText: fmt.Sprintf("could not read common header filler: %v", err)} } return nil } func (dec *Decoder) readPrivateHeader() error { // The next 8 bytes after the common header comprise the RPC type marshalling private header for constructed types. err := binary.Read(dec.r, dec.ch.Endianness, &dec.ph.ObjectBufferLength) if err != nil { return Malformed{EText: "could not read private header object buffer length"} } if dec.ph.ObjectBufferLength%8 != 0 { return Malformed{EText: "object buffer length not a multiple of 8"} } // Filler bytes dec.ph.Filler, err = dec.readBytes(4) if err != nil { return Malformed{EText: fmt.Sprintf("could not read private header filler: %v", err)} } return nil }