/// <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); }
/// <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); } }
/// <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); }
/// <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)); }
/// <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); } }
/// <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(); } } }
/// <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)); }
/// <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); }
/// <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(); } }
/// <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()); }
/// <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); } } } }
/// <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]); } }
/// <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())); }