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