Wireshark-dev: Re: [Wireshark-dev] [openchange][devel] Parsing array and its size in EcDoRpcExt

From: Julien Kerihuel <j.kerihuel@xxxxxxxxxxxxxx>
Date: Tue, 28 Apr 2009 11:16:33 +0200
On Mon, 2009-04-27 at 15:38 -0700, Harsha wrote:
> Hi all,
> 
> I am writing a dissector for Wireshark for MAPI protocol and was
> trying to parse a DCERPC message. The code comments in Wireshark
> mentioned that the Samba folks maintain the DCERPC part, so I figured
> that this would be the best place to post my question.
> 
> I was trying to parse this MSRPC function in Wireshark-
> 
> long __stdcall EcDoRpcExt2(
> [in, out, ref] CXH * pcxh, [in, out] unsigned long *pulFlags,
> [in, size_is(cbIn)] unsigned char rgbIn[],
> [in] unsigned long cbIn, <br/>
> [out, length_is(*pcbOut), size_is(*pcbOut)] unsigned char rgbOut[],
> [in, out] BIG_RANGE_ULONG *pcbOut, <br/>
> [in, size_is(cbAuxIn)] unsigned char rgbAuxIn[],
> [in] unsigned long cbAuxIn, [out, length_is(*pcbAuxOut),
> size_is(*pcbAuxOut)] unsigned char rgbAuxOut[],
> [in, out] SMALL_RANGE_ULONG *pcbAuxOut,
> [out] unsigned long *pulTransTime
> );
> 
> I'm stuck trying to parse
> 
> [in, size_is(cbIn)] unsigned char rgbIn[],
> [in] unsigned long cbIn,

Hi Harsha,

You'll find below a *very* preliminary IDL and remarks:

	typedef [public, bitmap16bit] bitmap {
		RHEF_Compressed		= 0x0001,
		RHEF_XorMagic		= 0x0002,
		RHEF_Last		= 0x0004
	} RPC_HEADER_EXT_Flags;

	typedef [public] struct {
		uint16			Version;
		RPC_HEADER_EXT_Flags	Flags;
		uint16			Size;
		uint16			SizeActual;
	} RPC_HEADER_EXT;

	typedef [public, bitmap32bit] bitmap {
		pulFlags_NoCompression	= 0x00000001,
		pulFlags_NoXorMagic	= 0x00000002,
		pulFlags_Chain		= 0x00000004
	} pulFlags;

	typedef [public] struct {
		RPC_HEADER_EXT					header;
		[flag(NDR_NOALIGN|NDR_REMAINING)] DATA_BLOB	data;
	} mapi2k3_rgbIn;

	MAPISTATUS EcDoRpcExt2(
		[in,out]						policy_handle	*handle,
		[in,out]						pulFlags	*pulFlags,
		[in, subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)]	mapi2k3_rgbIn	*rgbIn,
		[in]							uint32		cbIn,
		[out]							uint32		size,
		[out]							uint32		offset,
		[out,subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)]	DATA_BLOB	rgbOut,
		[in,out][range(0,262144)]				uint32		*pcbOut,
		[in, subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)]	DATA_BLOB	rgbAuxIn,
		[in]							uint32		cbAuxIn,
		[out,subcontext(4),flag(NDR_REMAINING|NDR_NOALIGN)]	DATA_BLOB	rgbAuxOut,
		[in,out][range(0,4104)]					uint32		*pcbAuxOut,
		[out]							uint32		*pulTransTime
		);

        -  I replaced the SMALL_RANGE_ULONG and BIG_RANGE_ULONG typedefs
        with their associated values
        
        - rgbAuxIn and rgbAuxOut while having their size defined after
        in the IDL (cbAuxIn, pcbAuxOut) also have their array size
        prefixing the blob when you look at the NDR blob.
        
        - rgbOut is prefixed with
        [size=4bytes][offset=4bytes][length=4bytes], so I turned it into
        a subcontext(4) handling length and explicitly added size and
        offset field for padding purposes.
        
        - In this IDL I have only started to hack rgbIn which I changed
        from DATA_BLOB to mapi2k3_rgbIn (not definitive names).

The reason why I turned the initial uint8 array into subcontexts is that
the blob processing - using samba4 NDR layer - needs to be done manually
(see ndr_mapi.c in openchange trunk) - and dealing with DATA_BLOB is
easier IMHO than uint8 array when it comes to use this blob as a ndr
context - for boundaries etc.

About the decoding routines internals (will focus on rgbIn as it
shouldn't be different for other blobs):

        - the mapi2k3_rgbIn can be either a single request or multiple
        requests (depending if the Last flag is enabled). Note that
        using NDR_REMAINING for the mapi2k3_rgbIn.data is incorrect
        since it doesn't consider the Last flag at all.
        
        - secondly it can either be Xor'ed (already used for EcDoRpc) or
        Compressed (see samba4/librpc/idl/drsuapi.idl and
        compression(NDR_COMPRESSION_XPRESS)).
        
        The point is that as far I as know, we won't be able to process
        this using a pidl union. While we can easily use
        switch_is(Header.Flags) in mapi2k3_rgbIn, we also need to supply
        the length and actual length so the lxpress decompression can be
        done properly.
        
Conclusion:
        1. I plan to implement this similarly to what was done for
        EcDoRpc:
                - Try to write as much EcDoRpcExt2 related structures as
                possible, tag them as public and use NDR_NOALIGN
        2. Only write manually the mapi2k3_rgbIn pull/push/print
        functions and rely as much as possible on generated/existing
        IDL.
        
PS: TDR is probably the best way to implement this, but that would cost
a lot of extra work and this would probably take quite some time before
we get back to the same level of features/stability.

Note: I have preliminary tried to use the following IDL which turns to
decode the EcDoRpcExt2 blob properly, but which has limitations - mostly
because rgbOut, rgbAuxIn and pcbAuxOut are not NDR encoded (see the
NDR_NOALIGN hack) and I try to avoid as much as possible non-pidl
generated code:

	MAPISTATUS EcDoRpcExt2(
		[in,out]			policy_handle		*handle,
		[in,out]			pulFlags		*pulFlags,
		[in,size_is(cbIn)]		uint8			rgbIn[],
		[in]				uint32			cbIn,
		[out, length_is(*pcbOut), size_is(*pcbOut)] uint8	rgbOut[],
		[in,out][range(0,262144)]	uint32			*pcbOut,
		[in,size_is(cbAuxIn)]		uint8			rgbAuxIn[],
		[in]				uint32			cbAuxIn,
		[out, length_is(*pcbAuxOut), size_is(*pcbAuxOut)] uint8	rgbAuxOut[],
		[in,out][range(0,4104)]		uint32			*pcbAuxOut,
		[out]				uint32			*pulTransTime
		);


> The problem I see is that we first have the array and then it length.
> 
> I did a quick read of the relevant part of DCE RPC specs, but in all
> the cases I saw it always had the size and then the array. In those
> cases it is trivial to first extract the size and use the size to
> extract the array contents.
> 
> I'm sure it is not a typo in the spec, so clearly I'm missing
> something. Can someone please clarify how to parse the array field ?
> 
> Any pointers/ suggestions/ hints welcome.
> 
> Many thanks,
> Harsha
> _______________________________________________
> devel mailing list
> devel@xxxxxxxxxxxxxxxxxxxx
> http://mailman.openchange.org/listinfo/devel
Julien Kerihuel
j.kerihuel@xxxxxxxxxxxxxx
OpenChange Project Manager

GPG Fingerprint: 0B55 783D A781 6329 108A  B609 7EF6 FE11 A35F 1F79


Attachment: signature.asc
Description: This is a digitally signed message part