/// <summary>
        /// Marshal the PDU struct to a byte array.
        /// </summary>
        /// <param name="binaryWriter">BinaryWriter</param>
        internal override void ToBytes(BinaryWriter binaryWriter)
        {
            base.ToBytes(binaryWriter);

            binaryWriter.Write(max_xmit_frag);
            binaryWriter.Write(max_recv_frag);
            binaryWriter.Write(assoc_group_id);

            binaryWriter.Write(p_context_elem.n_context_elem);
            binaryWriter.Write(p_context_elem.reserved);
            binaryWriter.Write(p_context_elem.reserved2);

            if (p_context_elem.p_cont_elem != null)
            {
                for (int i = 0; i < p_context_elem.p_cont_elem.Length; i++)
                {
                    binaryWriter.Write(p_context_elem.p_cont_elem[i].p_cont_id);
                    binaryWriter.Write(p_context_elem.p_cont_elem[i].n_transfer_syn);
                    binaryWriter.Write(p_context_elem.p_cont_elem[i].reserved);
                    binaryWriter.Write(p_context_elem.p_cont_elem[i].abstract_syntax.if_uuid.ToByteArray());
                    binaryWriter.Write(p_context_elem.p_cont_elem[i].abstract_syntax.if_version);
                    if (p_context_elem.p_cont_elem[i].transfer_syntaxes != null)
                    {
                        for (int j = 0; j < p_context_elem.p_cont_elem[i].transfer_syntaxes.Length; j++)
                        {
                            binaryWriter.Write(
                                p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid.ToByteArray());
                            binaryWriter.Write(p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_version);
                        }
                    }
                }
            }

            RpceUtility.AuthVerifierToBytes(binaryWriter, auth_verifier);
        }
 /// <summary>
 /// Un-marshal a byte array to PDU struct.
 /// </summary>
 /// <param name="binaryReader">BinaryReader</param>
 internal override void FromBytes(BinaryReader binaryReader)
 {
     base.FromBytes(binaryReader);
     auth_verifier = RpceUtility.AuthVerifierFromBytes(
         binaryReader,
         auth_length);
 }
示例#3
0
        /// <summary>
        /// Marshal the PDU struct to a byte array.
        /// </summary>
        /// <returns>A byte array contains PDU data.</returns>
        public override byte[] ToBytes()
        {
            int size = GetSize();

            FieldInfo fieldInfo = GetType().GetField("stub");

            if (fieldInfo != null)
            {
                byte[] stub = (byte[])fieldInfo.GetValue(this);
                if (stub != null)
                {
                    size += stub.Length;
                }
            }

            fieldInfo = GetType().GetField("auth_verifier");
            if (fieldInfo != null)
            {
                auth_verifier_co_t?authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this);
                size += RpceUtility.AuthVerifierGetSize(authVerifier);
            }

            byte[] pduBytes = new byte[size];
            using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(pduBytes)))
            {
                ToBytes(binaryWriter);
            }

            return(pduBytes);
        }
 /// <summary>
 /// Fragment and send PDU.
 /// </summary>
 /// <param name="sessionContext">Context of the RPCE session</param>
 /// <param name="pdu">PDU to Fragment and send.</param>
 private void FragmentAndSendPdu(
     RpceServerSessionContext sessionContext,
     RpceCoPdu pdu)
 {
     if (pdu.PTYPE == RpcePacketType.Bind ||
         pdu.PTYPE == RpcePacketType.BindAck ||
         pdu.PTYPE == RpcePacketType.AlterContext ||
         pdu.PTYPE == RpcePacketType.AlterContextResp ||
         pdu.PTYPE == RpcePacketType.Auth3)
     {
         pdu.InitializeAuthenticationToken();
         pdu.SetLength();
         foreach (RpceCoPdu fragPdu in RpceUtility.FragmentPdu(sessionContext, pdu))
         {
             rpceServer.SendPdu(sessionContext, fragPdu);
         }
     }
     else
     {
         foreach (RpceCoPdu fragPdu in RpceUtility.FragmentPdu(sessionContext, pdu))
         {
             fragPdu.InitializeAuthenticationToken();
             rpceServer.SendPdu(sessionContext, fragPdu);
         }
     }
 }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            provider_reject_reason = (p_reject_reason_t)binaryReader.ReadUInt16();
            versions             = new p_rt_versions_supported_t();
            versions.n_protocols = binaryReader.ReadByte();
            versions.p_protocols = new version_t[versions.n_protocols];
            for (int i = 0; i < versions.n_protocols; i++)
            {
                versions.p_protocols[i].major = binaryReader.ReadByte();
                versions.p_protocols[i].minor = binaryReader.ReadByte();
            }

            //Assume that the client calculates the length of the PDU
            //until the Signature field as L.
            //If the frag_length field is greater than or equal to L
            //plus the size of the Signature field,
            //the client SHOULD assume that the Signature field is present.
            //Otherwise, the client SHOULD assume that the Signature field is not present.
            //TD shows the signature is aligned at 4.
            int L = RpceUtility.Align((int)binaryReader.BaseStream.Position, 4);

            if (frag_length >= (L + RpceUtility.GUID_SIZE))
            {
                pad                 = binaryReader.ReadBytes(L - (int)binaryReader.BaseStream.Position);
                signature           = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                extended_error_info = binaryReader.ReadBytes(frag_length - L - RpceUtility.GUID_SIZE);
            }
        }
示例#6
0
        /// <summary>
        /// Receive and reassemble PDU.
        /// </summary>
        /// <param name="timeout">timeout</param>
        /// <returns>PDU</returns>
        private RpcePdu ReceiveAndReassemblePdu(TimeSpan timeout)
        {
            RpcePdu   receivedPdu   = rpceClient.ExpectPdu(timeout);
            RpceCoPdu receivedCoPdu = receivedPdu as RpceCoPdu;

            if (receivedCoPdu == null)
            {
                return(receivedPdu);
            }

            List <RpceCoPdu> pduList = new List <RpceCoPdu>();

            pduList.Add(receivedCoPdu);

            while ((receivedCoPdu.pfc_flags & RpceCoPfcFlags.PFC_LAST_FRAG) == 0)
            {
                receivedPdu   = rpceClient.ExpectPdu(timeout);
                receivedCoPdu = receivedPdu as RpceCoPdu;
                if (receivedCoPdu == null)
                {
                    throw new InvalidOperationException("CL PDU received inside a connection.");
                }

                pduList.Add(receivedCoPdu);
            }

            return(RpceUtility.ReassemblePdu(rpceClient.Context, pduList.ToArray()));
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            alloc_hint = binaryReader.ReadUInt32();
            p_cont_id  = binaryReader.ReadUInt16();
            opnum      = binaryReader.ReadUInt16();

            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                alloc_hint = EndianUtility.ReverseByteOrder(alloc_hint);
                p_cont_id  = EndianUtility.ReverseByteOrder(p_cont_id);
                opnum      = EndianUtility.ReverseByteOrder(opnum);
            }

            if ((pfc_flags & RpceCoPfcFlags.PFC_OBJECT_UUID) != 0)
            {
                @object = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
            }

            int stubLength = frag_length;

            stubLength -= GetSize();
            if (auth_verifier != null)
            {
                stubLength -= auth_verifier.Value.auth_pad_length;
                stubLength -= RpceUtility.AUTH_VERIFIER_SIZE;
                stubLength -= auth_length;
            }
            stub = binaryReader.ReadBytes(stubLength);
        }
        /// <summary>
        /// Marshal the PDU struct to a byte array.
        /// </summary>
        /// <param name="binaryWriter">BinaryWriter</param>
        internal override void ToBytes(BinaryWriter binaryWriter)
        {
            base.ToBytes(binaryWriter);

            binaryWriter.Write(max_xmit_frag);
            binaryWriter.Write(max_recv_frag);
            binaryWriter.Write(assoc_group_id);

            binaryWriter.Write(sec_addr.length);
            binaryWriter.Write(sec_addr.port_spec);

            if (pad2 != null)
            {
                binaryWriter.Write(pad2);
            }

            binaryWriter.Write(p_result_list.n_results);
            binaryWriter.Write(p_result_list.reserved);
            binaryWriter.Write(p_result_list.reserved2);

            if (p_result_list.p_results != null)
            {
                for (int i = 0; i < p_result_list.p_results.Length; i++)
                {
                    binaryWriter.Write((ushort)p_result_list.p_results[i].result);
                    binaryWriter.Write((ushort)p_result_list.p_results[i].reason);

                    binaryWriter.Write(p_result_list.p_results[i].transfer_syntax.if_uuid.ToByteArray());
                    binaryWriter.Write(p_result_list.p_results[i].transfer_syntax.if_version);
                }
            }

            RpceUtility.AuthVerifierToBytes(binaryWriter, auth_verifier);
        }
        /// <summary>
        /// Append verification_trailer to stub.
        /// </summary>
        /// <param name="verificationTrailer">verification_trailer</param>
        /// <exception cref="ArgumentNullException">Thrown when verificationTrailer is null.</exception>
        public void AppendVerificationTrailerToStub(verification_trailer_t verificationTrailer)
        {
            if (verificationTrailer == null)
            {
                throw new ArgumentNullException("verificationTrailer");
            }

            if (stub == null)
            {
                stub = new byte[0];
            }

            stub = RpceUtility.AppendVerificationTrailerToStub(stub, verificationTrailer);

            if (auth_verifier != null)
            {
                auth_verifier_co_t authVerifier = auth_verifier.Value;
                authVerifier.auth_pad_length = (byte)(
                    RpceUtility.Align(stub.Length, RpceUtility.STUB_PAD_LENGTH) - stub.Length);
                authVerifier.auth_pad = new byte[authVerifier.auth_pad_length];
                auth_verifier         = authVerifier;
            }

            SetLength();
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            alloc_hint   = binaryReader.ReadUInt32();
            p_cont_id    = binaryReader.ReadUInt16();
            cancel_count = binaryReader.ReadByte();
            reserved     = binaryReader.ReadByte();
            status       = binaryReader.ReadUInt32();
            reserved2    = binaryReader.ReadUInt32();

            // read stub
            int stubLength = frag_length;

            stubLength -= GetSize();
            if (auth_verifier != null)
            {
                stubLength -= auth_verifier.Value.auth_pad_length;
                stubLength -= RpceUtility.AUTH_VERIFIER_SIZE;
                stubLength -= auth_length;
            }
            stub = binaryReader.ReadBytes(stubLength);
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            alloc_hint   = binaryReader.ReadUInt32();
            p_cont_id    = binaryReader.ReadUInt16();
            cancel_count = binaryReader.ReadByte();
            reserved     = binaryReader.ReadByte();

            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                alloc_hint = EndianUtility.ReverseByteOrder(alloc_hint);
                p_cont_id  = EndianUtility.ReverseByteOrder(p_cont_id);
            }

            // read stub.
            int stubLength = frag_length;

            stubLength -= GetSize();
            if (auth_verifier != null)
            {
                stubLength -= auth_verifier.Value.auth_pad_length;
                stubLength -= RpceUtility.AUTH_VERIFIER_SIZE;
                stubLength -= auth_length;
            }
            stub = binaryReader.ReadBytes(stubLength);
        }
示例#12
0
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            alloc_hint = binaryReader.ReadUInt32();
            p_cont_id  = binaryReader.ReadUInt16();
            opnum      = binaryReader.ReadUInt16();

            if ((pfc_flags & RpceCoPfcFlags.PFC_OBJECT_UUID) != 0)
            {
                @object = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
            }

            int stubLength = frag_length;

            stubLength -= GetSize();
            if (auth_verifier != null)
            {
                stubLength -= auth_verifier.Value.auth_pad_length;
                stubLength -= RpceUtility.AUTH_VERIFIER_SIZE;
                stubLength -= auth_length;
            }
            stub = binaryReader.ReadBytes(stubLength);
        }
        /// <summary>
        /// Extract verification_trailer from stub.
        /// </summary>
        /// <param name="startIndex">
        /// Input: The position of the end of stub (the beginning position to search for verification_trailer).
        /// Output: The start position of verification_trailer.
        /// </param>
        /// <returns>Returns verification_trailer if found; otherwise, returns null.</returns>
        public verification_trailer_t ExtractVerificationTrailerFromStub(ref int startIndex)
        {
            if (stub == null)
            {
                //No stub, no verification_trailer.
                return(null);
            }

            return(RpceUtility.ExtractVerificationTrailerFromStub(stub, ref startIndex));
        }
示例#14
0
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);
            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);
            pad = binaryReader.ReadUInt32();

            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                pad = EndianUtility.ReverseByteOrder(pad);
            }
        }
示例#15
0
        /// <summary>
        /// Decode CO PDU.
        /// </summary>
        /// <param name="context">The context that received data.</param>
        /// <param name="messageBytes">bytes received</param>
        /// <param name="consumedLength">num of bytes consumed in processing</param>
        /// <param name="expectedLength">num of bytes expected if the bytes is not enough</param>
        /// <returns>pdus</returns>
        internal static RpceCoPdu[] DecodeCoPdu(
            RpceContext context,
            byte[] messageBytes,
            out int consumedLength,
            out int expectedLength)
        {
            List <RpceCoPdu> pduList = new List <RpceCoPdu>();

            consumedLength = 0;
            expectedLength = 0;

            while (consumedLength < messageBytes.Length)
            {
                if ((messageBytes.Length - consumedLength) < RpceUtility.CO_PDU_HEADER_SIZE)
                {
                    expectedLength = RpceUtility.CO_PDU_HEADER_SIZE;
                    break;
                }

                //#4 byte is drep
                uint dataRepresentation = BitConverter.ToUInt32(
                    messageBytes,
                    consumedLength + RpceUtility.DREP_FIELD_OFFSET);
                //#8 byte is frag_length
                ushort fragmentLength = BitConverter.ToUInt16(
                    messageBytes,
                    consumedLength + RpceUtility.FRAG_LENGTH_FIELD_OFFSET);
                if ((dataRepresentation & 0x0000FFFFU) != NativeMethods.NDR_LOCAL_DATA_REPRESENTATION)
                {
                    fragmentLength = EndianUtility.ReverseByteOrder(fragmentLength);
                }

                if ((messageBytes.Length - consumedLength) < fragmentLength)
                {
                    expectedLength = fragmentLength;
                    break;
                }

                byte[] pduBytes = new byte[fragmentLength];
                Buffer.BlockCopy(messageBytes, consumedLength, pduBytes, 0, fragmentLength);

                RpceCoPdu pdu = RpceUtility.DecodeCoPdu(context, pduBytes);

                pduList.Add(pdu);
                consumedLength += fragmentLength;
            }

            return(pduList.ToArray());
        }
        /// <summary>
        /// Marshal the PDU struct to a byte array.
        /// </summary>
        /// <param name="binaryWriter">BinaryWriter</param>
        internal override void ToBytes(BinaryWriter binaryWriter)
        {
            base.ToBytes(binaryWriter);

            binaryWriter.Write(alloc_hint);
            binaryWriter.Write(p_cont_id);
            binaryWriter.Write(cancel_count);
            binaryWriter.Write(reserved);

            if (stub != null)
            {
                binaryWriter.Write(stub);
            }

            RpceUtility.AuthVerifierToBytes(binaryWriter, auth_verifier);
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            max_xmit_frag  = binaryReader.ReadUInt16();
            max_recv_frag  = binaryReader.ReadUInt16();
            assoc_group_id = binaryReader.ReadUInt32();

            p_context_elem = new p_cont_list_t();

            p_context_elem.n_context_elem = binaryReader.ReadByte();
            p_context_elem.reserved       = binaryReader.ReadByte();
            p_context_elem.reserved2      = binaryReader.ReadUInt16();

            p_context_elem.p_cont_elem = new p_cont_elem_t[p_context_elem.n_context_elem];
            for (int i = 0; i < p_context_elem.n_context_elem; i++)
            {
                p_context_elem.p_cont_elem[i].p_cont_id      = binaryReader.ReadUInt16();
                p_context_elem.p_cont_elem[i].n_transfer_syn = binaryReader.ReadByte();
                p_context_elem.p_cont_elem[i].reserved       = binaryReader.ReadByte();

                p_context_elem.p_cont_elem[i].abstract_syntax = new p_syntax_id_t();
                p_context_elem.p_cont_elem[i].abstract_syntax.if_uuid
                    = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                p_context_elem.p_cont_elem[i].abstract_syntax.if_vers_major
                    = binaryReader.ReadUInt16();
                p_context_elem.p_cont_elem[i].abstract_syntax.if_vers_minor
                    = binaryReader.ReadUInt16();

                p_context_elem.p_cont_elem[i].transfer_syntaxes
                    = new p_syntax_id_t[p_context_elem.p_cont_elem[i].n_transfer_syn];
                for (int j = 0; j < p_context_elem.p_cont_elem[i].transfer_syntaxes.Length; j++)
                {
                    p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid
                        = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                    p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_major
                        = binaryReader.ReadUInt16();
                    p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_minor
                        = binaryReader.ReadUInt16();
                }
            }
        }
示例#18
0
        /// <summary>
        /// Set length field of PDU.
        /// </summary>
        public override void SetLength()
        {
            auth_verifier_co_t?authVerifier = null;
            FieldInfo          fieldInfo    = this.GetType().GetField("auth_verifier");

            if (fieldInfo != null)
            {
                authVerifier = (auth_verifier_co_t?)fieldInfo.GetValue(this);
            }

            byte[] stub       = GetStub();
            int    stubLength = (stub == null) ? 0 : stub.Length;

            // stub was already padded in AppendAuthenticationVerifier()
            auth_length = (authVerifier == null || authVerifier.Value.auth_value == null)
                            ? (ushort)0
                            : (ushort)authVerifier.Value.auth_value.Length;
            frag_length = (ushort)(GetSize() + stubLength + RpceUtility.AuthVerifierGetSize(authVerifier));
        }
示例#19
0
        /// <summary>
        /// Append verification_trailer to stub.
        /// </summary>
        /// <param name="stub">The stub.</param>
        /// <param name="verificationTrailer">verification_trailer</param>
        /// <returns>The stub with verification_trailer.</returns>
        /// <exception cref="ArgumentNullException">Thrown when stub or verificationTrailer is null.</exception>
        public static byte[] AppendVerificationTrailerToStub(byte[] stub, verification_trailer_t verificationTrailer)
        {
            if (stub == null)
            {
                throw new ArgumentNullException("stub");
            }

            if (verificationTrailer == null)
            {
                throw new ArgumentNullException("verificationTrailer");
            }

            //The beginning of the header MUST be 4-byte aligned with respect to the beginning of the PDU.
            int padLength = RpceUtility.Align(stub.Length, 4) - stub.Length;

            verificationTrailer.pad = new byte[padLength];
            byte[] verificationTrailerBytes = verificationTrailer.ToBytes();
            return(ArrayUtility.ConcatenateArrays(stub, verificationTrailerBytes));
        }
        /// <summary>
        /// Marshal the PDU struct to a byte array.
        /// </summary>
        /// <param name="binaryWriter">BinaryWriter</param>
        internal override void ToBytes(BinaryWriter binaryWriter)
        {
            base.ToBytes(binaryWriter);

            binaryWriter.Write(alloc_hint);
            binaryWriter.Write(p_cont_id);
            binaryWriter.Write(opnum);

            if (@object != null)
            {
                binaryWriter.Write(@object.Value.ToByteArray());
            }

            if (stub != null)
            {
                binaryWriter.Write(stub);
            }

            RpceUtility.AuthVerifierToBytes(binaryWriter, auth_verifier);
        }
示例#21
0
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            max_xmit_frag  = binaryReader.ReadUInt16();
            max_recv_frag  = binaryReader.ReadUInt16();
            assoc_group_id = binaryReader.ReadUInt32();

            sec_addr           = new port_any_t();
            sec_addr.length    = binaryReader.ReadUInt16();
            sec_addr.port_spec = binaryReader.ReadBytes(sec_addr.length);

            // restore 4-octet alignment
            int pad2length = RpceUtility.Align((int)binaryReader.BaseStream.Position, 4)
                             - (int)binaryReader.BaseStream.Position;

            pad2 = binaryReader.ReadBytes(pad2length);

            p_result_list           = new p_result_list_t();
            p_result_list.n_results = binaryReader.ReadByte();
            p_result_list.reserved  = binaryReader.ReadByte();
            p_result_list.reserved2 = binaryReader.ReadUInt16();

            p_result_list.p_results = new p_result_t[p_result_list.n_results];
            for (int i = 0; i < p_result_list.n_results; i++)
            {
                p_result_list.p_results[i].result          = (p_cont_def_result_t)binaryReader.ReadUInt16();
                p_result_list.p_results[i].reason          = (p_provider_reason_t)binaryReader.ReadUInt16();
                p_result_list.p_results[i].transfer_syntax = new p_syntax_id_t();
                p_result_list.p_results[i].transfer_syntax.if_uuid
                    = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                p_result_list.p_results[i].transfer_syntax.if_vers_major
                    = binaryReader.ReadUInt16();
                p_result_list.p_results[i].transfer_syntax.if_vers_minor
                    = binaryReader.ReadUInt16();
            }
        }
示例#22
0
        /// <summary>
        /// Append auth_verifier to the end of PDU.
        /// </summary>
        public override void AppendAuthenticationVerifier()
        {
            FieldInfo fieldInfo = this.GetType().GetField("auth_verifier");

            if (fieldInfo == null)
            {
                return;
            }

            byte[] stub = GetStub();

            auth_verifier_co_t?authVerifier = RpceUtility.AuthVerifierCreateInstance(
                PTYPE,
                stub != null ? stub.Length : 0,
                context.SecurityContext,
                context.AuthenticationType,
                context.AuthenticationLevel,
                context.AuthenticationContextId);

            fieldInfo.SetValue(this, authVerifier);
        }
        /// <summary>
        /// Decode CO PDU.
        /// </summary>
        /// <param name="context">The context that received data.</param>
        /// <param name="messageBytes">bytes received</param>
        /// <param name="consumedLength">num of bytes consumed in processing</param>
        /// <param name="expectedLength">num of bytes expected if the bytes is not enough</param>
        /// <returns>pdus</returns>
        internal static RpceCoPdu[] DecodeCoPdu(
            RpceContext context,
            byte[] messageBytes,
            out int consumedLength,
            out int expectedLength)
        {
            List <RpceCoPdu> pduList = new List <RpceCoPdu>();

            consumedLength = 0;
            expectedLength = 0;

            while (consumedLength < messageBytes.Length)
            {
                if ((messageBytes.Length - consumedLength) < RpceUtility.CO_PDU_HEADER_SIZE)
                {
                    expectedLength = RpceUtility.CO_PDU_HEADER_SIZE;
                    break;
                }

                //#8 byte is frag_length
                ushort fragmentLength = BitConverter.ToUInt16(
                    messageBytes,
                    consumedLength + RpceUtility.FRAG_LENGTH_FIELD_OFFSET);
                if ((messageBytes.Length - consumedLength) < fragmentLength)
                {
                    expectedLength = fragmentLength;
                    break;
                }

                byte[] pduBytes = new byte[fragmentLength];
                Buffer.BlockCopy(messageBytes, consumedLength, pduBytes, 0, fragmentLength);

                RpceCoPdu pdu = RpceUtility.DecodeCoPdu(context, pduBytes);

                pduList.Add(pdu);
                consumedLength += fragmentLength;
            }

            return(pduList.ToArray());
        }
示例#24
0
        /// <summary>
        /// Extract verification_trailer from stub.
        /// </summary>
        /// <param name="stub">The stub.</param>
        /// <param name="startIndex">
        /// Input: The position of the end of stub (the beginning position to search for verification_trailer).
        /// Output: The start position of verification_trailer.
        /// </param>
        /// <returns>Returns verification_trailer if found; otherwise, returns null.</returns>
        /// <exception cref="ArgumentNullException">Thrown when stub is null.</exception>
        public static verification_trailer_t ExtractVerificationTrailerFromStub(byte[] stub, ref int startIndex)
        {
            if (stub == null)
            {
                throw new ArgumentNullException("stub");
            }

            //The beginning of the header MUST be 4-byte aligned with respect to the beginning of the PDU.
            for (int i = RpceUtility.Align(startIndex, 4); i < stub.Length; i += 4)
            {
                if ((stub.Length - i) >= Marshal.SizeOf(verification_trailer_t.SIGNATURE) &&
                    BitConverter.ToUInt64(stub, i) == verification_trailer_t.SIGNATURE)
                {
                    //found verification_trailer
                    byte[] verificationTrailerBuffer           = ArrayUtility.SubArray(stub, i);
                    verification_trailer_t verificationTrailer = new verification_trailer_t();
                    verificationTrailer.FromBytes(verificationTrailerBuffer);
                    startIndex = i;
                    return(verificationTrailer);
                }
            }

            return(null);
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            max_xmit_frag  = binaryReader.ReadUInt16();
            max_recv_frag  = binaryReader.ReadUInt16();
            assoc_group_id = binaryReader.ReadUInt32();

            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                max_xmit_frag  = EndianUtility.ReverseByteOrder(max_xmit_frag);
                max_recv_frag  = EndianUtility.ReverseByteOrder(max_recv_frag);
                assoc_group_id = EndianUtility.ReverseByteOrder(assoc_group_id);
            }

            p_context_elem = new p_cont_list_t();

            p_context_elem.n_context_elem = binaryReader.ReadByte();
            p_context_elem.reserved       = binaryReader.ReadByte();
            p_context_elem.reserved2      = binaryReader.ReadUInt16();

            p_context_elem.p_cont_elem = new p_cont_elem_t[p_context_elem.n_context_elem];
            for (int i = 0; i < p_context_elem.n_context_elem; i++)
            {
                p_context_elem.p_cont_elem[i].p_cont_id      = binaryReader.ReadUInt16();
                p_context_elem.p_cont_elem[i].n_transfer_syn = binaryReader.ReadByte();
                p_context_elem.p_cont_elem[i].reserved       = binaryReader.ReadByte();

                p_context_elem.p_cont_elem[i].abstract_syntax = new p_syntax_id_t();
                p_context_elem.p_cont_elem[i].abstract_syntax.if_uuid
                    = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                p_context_elem.p_cont_elem[i].abstract_syntax.if_version
                    = binaryReader.ReadUInt32();

                if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
                {
                    p_context_elem.p_cont_elem[i].p_cont_id = EndianUtility.ReverseByteOrder(p_context_elem.p_cont_elem[i].p_cont_id);
                    p_context_elem.p_cont_elem[i].abstract_syntax.if_uuid    = EndianUtility.ReverseByteOrder(p_context_elem.p_cont_elem[i].abstract_syntax.if_uuid);
                    p_context_elem.p_cont_elem[i].abstract_syntax.if_version = EndianUtility.ReverseByteOrder(p_context_elem.p_cont_elem[i].abstract_syntax.if_version);
                }

                p_context_elem.p_cont_elem[i].transfer_syntaxes
                    = new p_syntax_id_t[p_context_elem.p_cont_elem[i].n_transfer_syn];
                for (int j = 0; j < p_context_elem.p_cont_elem[i].transfer_syntaxes.Length; j++)
                {
                    p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid
                        = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                    p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_version
                        = binaryReader.ReadUInt32();

                    if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
                    {
                        p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid    = EndianUtility.ReverseByteOrder(p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid);
                        p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_version = EndianUtility.ReverseByteOrder(p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_version);
                    }
                }
            }
        }
示例#26
0
        /// <summary>
        /// Encrypt and sign to get auth_token.
        /// </summary>
        /// <param name="authVerifier">auth_verifier, not null.</param>
        private void EncryptAndSign(ref auth_verifier_co_t authVerifier)
        {
            //Request, Response, Fault
            //Get stub, pad the length to a multiple of 4 bytes.
            byte[] stub = GetStub();
            if (stub == null)
            {
                stub = new byte[0];
                SetStub(stub);
            }

            //Get SecurityBuffers.
            int stubSecBufIndex;
            int tokenSecBufIndex;
            SecurityBufferType    readonlyFlag;
            List <SecurityBuffer> securityBufferList = new List <SecurityBuffer>();

            if (context.SupportsHeaderSign)
            {
                readonlyFlag = SecurityBufferType.ReadOnlyWithChecksum;
            }
            else
            {
                readonlyFlag = SecurityBufferType.ReadOnly;
            }
            int headerSize = GetSize();

            byte[] buf = new byte[
                headerSize
                + stub.Length
                + RpceUtility.AuthVerifierGetSize(authVerifier)];
            using (BinaryWriter binaryWriter = new BinaryWriter(new MemoryStream(buf)))
            {
                ToBytes(binaryWriter);
            }

            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(buf, 0, headerSize)));
            stubSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data,
                    ArrayUtility.ConcatenateArrays(stub, authVerifier.auth_pad)));
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Data | readonlyFlag,
                    ArrayUtility.SubArray(
                        buf,
                        headerSize + stub.Length + authVerifier.auth_pad_length,
                        RpceUtility.AUTH_VERIFIER_SIZE))); //8 == length of auth_verifier
            tokenSecBufIndex = securityBufferList.Count;
            securityBufferList.Add(
                new SecurityBuffer(
                    SecurityBufferType.Token,
                    authVerifier.auth_value));
            SecurityBuffer[] securityBuffers = securityBufferList.ToArray();

            //encrypt and sign
            switch (context.AuthenticationLevel)
            {
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_CALL:     //Same as RPC_C_AUTHN_LEVEL_PKT
            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                context.SecurityContext.Sign(securityBuffers);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
                //the field "checksum" is the checksum value returned
                //by the underlying security service in response to
                //an integrity protection call
                context.SecurityContext.Sign(securityBuffers);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                break;

            case RpceAuthenticationLevel.RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
                //This level of service provides strong integrity protection for the
                //entire PDU, plus privacy protection for the body data only.
                //Therefore, only the bodies of the request, response and fault PDUs
                //are encrypted.
                context.SecurityContext.Encrypt(securityBuffers);
                authVerifier.auth_pad   = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, stub.Length);
                authVerifier.auth_value = securityBuffers[tokenSecBufIndex].Buffer;
                stub = ArrayUtility.SubArray(securityBuffers[stubSecBufIndex].Buffer, 0, stub.Length);
                SetStub(stub);
                break;

                //default do nothing.
            }

            //A client or a server that (during composing of a PDU) has allocated more space for
            //the authentication token than the security provider fills in SHOULD<36> fill in
            //the rest of the allocated space with zero octets. These zero octets are still
            //considered to belong to the authentication token part of the PDU.
            int padLength = (int)auth_length - authVerifier.auth_value.Length;

            if (padLength < 0)
            {
                throw new InvalidOperationException("Length of calculated auth_value is incorrect.");
            }
            else if (padLength > 0)
            {
                authVerifier.auth_value = ArrayUtility.ConcatenateArrays(authVerifier.auth_value, new byte[padLength]);
            }
        }
示例#27
0
        /// <summary>
        /// Fragment a PDU into several PDUs by max_xmit_frag field.<para/>
        /// Only bind, bind_ack, alter_context, alter_context_response,
        /// request and response PDUs will be fragmented.<para/>
        /// Must call before sign/encrypt.
        /// </summary>
        /// <param name="context">RpceContext to fragment PDU</param>
        /// <param name="pdu">
        /// A PDU to be fragmented.
        /// Only bind, bind_ack, alter_context, alter_context_response,
        /// request and response PDUs will be fragmented.
        /// </param>
        /// <returns>Fragmented PDUs.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when pdu or context is null.
        /// </exception>
        /// <exception cref="NotSupportedException">Thrown when PDU PacketType isn't supported.</exception>
        public static RpceCoPdu[] FragmentPdu(RpceContext context, RpceCoPdu pdu)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (pdu == null)
            {
                throw new ArgumentNullException("pdu");
            }

            if (pdu.frag_length > context.MaxTransmitFragmentSize)
            {
                int    headerAndTrailerSize;
                byte[] stub;

                switch (pdu.PTYPE)
                {
                case RpcePacketType.Request:

                    //Get stub of request PDU
                    RpceCoRequestPdu requestPdu = pdu as RpceCoRequestPdu;

                    if (requestPdu == null)
                    {
                        throw new ArgumentException("The pdu is not a valid RpceCoRequestPdu.");
                    }

                    headerAndTrailerSize = requestPdu.GetSize();

                    if (requestPdu.auth_verifier != null)
                    {
                        //length of auth_verifier
                        headerAndTrailerSize += RpceUtility.AUTH_VERIFIER_SIZE;
                        headerAndTrailerSize += requestPdu.auth_verifier.Value.auth_value.Length;

                        //To keep stub always be padded to 16 bytes, and pdu doesnot exceed max transmit frag size.
                        int stubLength = context.MaxTransmitFragmentSize - headerAndTrailerSize;
                        headerAndTrailerSize +=
                            RpceUtility.Align(stubLength, RpceUtility.AUTH_PAD_LENGTH) - stubLength;

                        //The beginning of the verification_trailer header MUST be 4-byte aligned
                        //with respect to the beginning of the PDU.
                        headerAndTrailerSize = RpceUtility.Align(headerAndTrailerSize, RpceUtility.STUB_PAD_LENGTH);
                    }

                    stub = requestPdu.stub ?? new byte[0];

                    //Fragment
                    RpceCoRequestPdu[] requestFragmentPduList = FragmentPdu <RpceCoRequestPdu>(
                        context,
                        pdu,
                        stub.Length,
                        headerAndTrailerSize);

                    for (int i = 0; i < requestFragmentPduList.Length; i++)
                    {
                        //SHOULD set the alloc_hint field in every PDU to
                        //be the combined stub data length of all remaining fragment PDUs.
                        requestFragmentPduList[i].alloc_hint = (uint)stub.Length;
                        requestFragmentPduList[i].p_cont_id  = requestPdu.p_cont_id;
                        requestFragmentPduList[i].opnum      = requestPdu.opnum;
                        requestFragmentPduList[i].@object    = requestPdu.@object;
                        requestFragmentPduList[i].stub       = ArrayUtility.SubArray(
                            stub,
                            0,
                            Math.Min(stub.Length, context.MaxTransmitFragmentSize - headerAndTrailerSize));

                        //For request and response PDUs, where the request and response PDUs are
                        //part of a fragmented request or response and authentication is requested,
                        //the sec_trailer structure MUST be present in every fragment of the request
                        //or response.
                        requestFragmentPduList[i].AppendAuthenticationVerifier();
                        requestFragmentPduList[i].SetLength();
                        stub = ArrayUtility.SubArray(stub, requestFragmentPduList[i].stub.Length);
                    }

                    return(requestFragmentPduList);

                case RpcePacketType.Response:

                    //Get stub of response PDU
                    RpceCoResponsePdu responsePdu = pdu as RpceCoResponsePdu;

                    if (responsePdu == null)
                    {
                        throw new ArgumentException("The PDU is not a valid RpceCoResponsePdu");
                    }

                    headerAndTrailerSize = responsePdu.GetSize();

                    if (responsePdu.auth_verifier != null)
                    {
                        //length of auth_verifier
                        headerAndTrailerSize += RpceUtility.AUTH_VERIFIER_SIZE;
                        headerAndTrailerSize += responsePdu.auth_verifier.Value.auth_value.Length;

                        //To keep stub always be padded to 16 bytes, and pdu doesnot exceed max transmit frag size.
                        int stubLength = context.MaxTransmitFragmentSize - headerAndTrailerSize;
                        headerAndTrailerSize +=
                            RpceUtility.Align(stubLength, RpceUtility.AUTH_PAD_LENGTH) - stubLength;

                        //The beginning of the verification_trailer header MUST be 4-byte aligned
                        //with respect to the beginning of the PDU.
                        headerAndTrailerSize = RpceUtility.Align(headerAndTrailerSize, RpceUtility.STUB_PAD_LENGTH);
                    }

                    stub = responsePdu.stub ?? new byte[0];

                    //Fragment
                    RpceCoResponsePdu[] responseFragmentPduList = FragmentPdu <RpceCoResponsePdu>(
                        context,
                        pdu,
                        stub.Length,
                        headerAndTrailerSize);

                    for (int i = 0; i < responseFragmentPduList.Length; i++)
                    {
                        //SHOULD set the alloc_hint field in every PDU to
                        //be the combined stub data length of all remaining fragment PDUs.
                        responseFragmentPduList[i].alloc_hint   = (uint)stub.Length;
                        responseFragmentPduList[i].p_cont_id    = responsePdu.p_cont_id;
                        responseFragmentPduList[i].cancel_count = responsePdu.cancel_count;
                        responseFragmentPduList[i].reserved     = responsePdu.reserved;
                        responseFragmentPduList[i].stub         = ArrayUtility.SubArray(
                            stub,
                            0,
                            Math.Min(stub.Length, context.MaxTransmitFragmentSize - headerAndTrailerSize));

                        //For request and response PDUs, where the request and response PDUs are
                        //part of a fragmented request or response and authentication is requested,
                        //the sec_trailer structure MUST be present in every fragment of the request
                        //or response.
                        responseFragmentPduList[i].AppendAuthenticationVerifier();
                        responseFragmentPduList[i].SetLength();
                        stub = ArrayUtility.SubArray(stub, responseFragmentPduList[i].stub.Length);
                    }

                    return(responseFragmentPduList);

                case RpcePacketType.Bind:
                case RpcePacketType.BindAck:
                case RpcePacketType.AlterContext:
                case RpcePacketType.AlterContextResp:
                case RpcePacketType.Auth3:
                    //Windows RPC support version 5.0 only.
                    //Bind fragment requires RPC ver 5.1.
                    //We don't support it.
                    throw new NotSupportedException("bind/bind_ack/alt_context/alt_context_resp/auth3 PDU fragment are not supported.");

                default:
                    throw new InvalidOperationException("PDU PacketType isn't supported.");
                }
            }

            //If we cannot fragment the PDU
            return(new RpceCoPdu[] { pdu });
        }
        /// <summary>
        /// Un-marshal a byte array to PDU struct.
        /// </summary>
        /// <param name="binaryReader">BinaryReader</param>
        internal override void FromBytes(BinaryReader binaryReader)
        {
            base.FromBytes(binaryReader);

            auth_verifier = RpceUtility.AuthVerifierFromBytes(
                binaryReader,
                auth_length);

            max_xmit_frag  = binaryReader.ReadUInt16();
            max_recv_frag  = binaryReader.ReadUInt16();
            assoc_group_id = binaryReader.ReadUInt32();

            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                max_xmit_frag  = EndianUtility.ReverseByteOrder(max_xmit_frag);
                max_recv_frag  = EndianUtility.ReverseByteOrder(max_recv_frag);
                assoc_group_id = EndianUtility.ReverseByteOrder(assoc_group_id);
            }

            sec_addr        = new port_any_t();
            sec_addr.length = binaryReader.ReadUInt16();
            if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
            {
                sec_addr.length = EndianUtility.ReverseByteOrder(sec_addr.length);
            }
            sec_addr.port_spec = binaryReader.ReadBytes(sec_addr.length);

            // restore 4-octet alignment
            int pad2Length = RpceUtility.Align((int)binaryReader.BaseStream.Position, 4)
                             - (int)binaryReader.BaseStream.Position;

            pad2 = binaryReader.ReadBytes(pad2Length);

            p_result_list           = new p_result_list_t();
            p_result_list.n_results = binaryReader.ReadByte();
            p_result_list.reserved  = binaryReader.ReadByte();
            p_result_list.reserved2 = binaryReader.ReadUInt16();

            p_result_list.p_results = new p_result_t[p_result_list.n_results];
            for (int i = 0; i < p_result_list.n_results; i++)
            {
                if (packed_drep.dataRepFormat == RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
                {
                    p_result_list.p_results[i].result = (p_cont_def_result_t)binaryReader.ReadUInt16();
                    p_result_list.p_results[i].reason = (p_provider_reason_t)binaryReader.ReadUInt16();
                }
                else
                {
                    p_result_list.p_results[i].result = (p_cont_def_result_t)EndianUtility.ReverseByteOrder(binaryReader.ReadUInt16());
                    p_result_list.p_results[i].reason = (p_provider_reason_t)EndianUtility.ReverseByteOrder(binaryReader.ReadUInt16());
                }

                p_result_list.p_results[i].transfer_syntax = new p_syntax_id_t();
                p_result_list.p_results[i].transfer_syntax.if_uuid
                    = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE));
                p_result_list.p_results[i].transfer_syntax.if_version
                    = binaryReader.ReadUInt32();

                if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII)
                {
                    p_result_list.p_results[i].transfer_syntax.if_uuid    = EndianUtility.ReverseByteOrder(p_result_list.p_results[i].transfer_syntax.if_uuid);
                    p_result_list.p_results[i].transfer_syntax.if_version = EndianUtility.ReverseByteOrder(p_result_list.p_results[i].transfer_syntax.if_version);
                }
            }
        }
 /// <summary>
 /// Marshal the PDU struct to a byte array.
 /// </summary>
 /// <param name="binaryWriter">BinaryWriter</param>
 internal override void ToBytes(BinaryWriter binaryWriter)
 {
     base.ToBytes(binaryWriter);
     binaryWriter.Write(pad);
     RpceUtility.AuthVerifierToBytes(binaryWriter, auth_verifier);
 }
        /// <summary>
        /// Receive and reassemble PDU.
        /// </summary>
        /// <param name="timeout">Timeout of receiving PDU</param>
        /// <param name="sessionContext">Context of the RPCE session</param>
        /// <returns>Received PDU</returns>
        private RpcePdu ReceiveAndReassemblePdu(
            TimeSpan timeout,
            ref RpceServerSessionContext sessionContext)
        {
            RpcePdu receivedPdu;
            bool    expectAny = sessionContext == null;

WaitForEvent:

            if (expectAny)
            {
                sessionContext = null;
            }
            EventType eventType = rpceServer.ExpectEvent(timeout, ref sessionContext, out receivedPdu);

            if (this.registeredInterfaceList.Count > 0)
            {
                // auto accept connect/bind/disconnect
                if (eventType == EventType.Connected)
                {
                    RpcIfMatchFunc matchFunc = delegate(RpcIf rpcIf)
                    {
                        for (int i = 0; i < this.registeredInterfaceList.Count; i++)
                        {
                            if (this.registeredInterfaceList[i].Equals(rpcIf))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    };
                    InternalExpectBind(matchFunc, timeout, ref sessionContext);
                    goto WaitForEvent;
                }
                else if (eventType == EventType.Disconnected)
                {
                    goto WaitForEvent;
                }
                else
                {
                    // it is a PDU.
                }
            }
            else if (eventType != EventType.ReceivedPacket)
            {
                throw new InvalidOperationException(
                          string.Format("Unexpected event ({0}) received.", eventType));
            }


            RpceCoPdu receivedCoPdu = receivedPdu as RpceCoPdu;

            if (receivedCoPdu == null)
            {
                return(receivedPdu);
            }

            List <RpceCoPdu> pduList = new List <RpceCoPdu>();

            pduList.Add(receivedCoPdu);

            while ((receivedCoPdu.pfc_flags & RpceCoPfcFlags.PFC_LAST_FRAG) == 0)
            {
                receivedPdu = rpceServer.ExpectPdu(timeout, ref sessionContext);

                receivedCoPdu = receivedPdu as RpceCoPdu;
                if (receivedCoPdu == null)
                {
                    throw new InvalidOperationException("CL PDU received inside a connection.");
                }

                pduList.Add(receivedCoPdu);
            }

            return(RpceUtility.ReassemblePdu(sessionContext, pduList.ToArray()));
        }