blob: 1970ddb600ec9f8779c4c93d7cd35edfb1559994 [file] [log] [blame]
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
}