/// <summary> /// Calling this method to be notified when a new RPC connection is coming. /// </summary> /// <param name="ifMatchFunc">Matching function.</param> /// <param name="timeout">Timeout of expecting a connection.</param> /// <param name="sessionContext">The sessionContext of binded connection.</param> /// <returns>If bind succeeded, return true; otherwise, false.</returns> private bool InternalExpectBind( RpcIfMatchFunc ifMatchFunc, TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoBindPdu bindPdu = receivedPdu as RpceCoBindPdu; if (bindPdu == null) { throw new InvalidOperationException("Expect bind_pdu, but received others."); } RpcIf rpcIf = new RpcIf(sessionContext.InterfaceId, sessionContext.InterfaceMajorVersion, sessionContext.InterfaceMinorVersion); if (!ifMatchFunc(rpcIf)) { // Interface doesn't match, response BindNak RpceCoBindNakPdu bindNakPdu = rpceServer.CreateCoBindNakPdu(sessionContext, p_reject_reason_t.REASON_NOT_SPECIFIED, null); FragmentAndSendPdu(sessionContext, bindNakPdu); return(false); } RpceCoBindAckPdu bindAckPdu = rpceServer.CreateCoBindAckPdu(sessionContext); FragmentAndSendPdu(sessionContext, bindAckPdu); while (sessionContext.SecurityContext != null && sessionContext.SecurityContextNeedContinueProcessing) { receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoAlterContextPdu alterContextPdu = receivedPdu as RpceCoAlterContextPdu; RpceCoAuth3Pdu auth3Pdu = receivedPdu as RpceCoAuth3Pdu; if (alterContextPdu != null) { RpceCoAlterContextRespPdu alterContextRespPdu = rpceServer.CreateCoAlterContextRespPdu(sessionContext); FragmentAndSendPdu(sessionContext, alterContextRespPdu); } else if (auth3Pdu != null) { //Do nothing } } return(true); }
/// <summary> /// update context on sending RPCE CO BindAck PDU. /// </summary> /// <param name="bindAckPdu">BindAck PDU to send.</param> internal void UpdateContextOnSendingBindAckPdu(RpceCoBindAckPdu bindAckPdu) { this.MaxTransmitFragmentSize = bindAckPdu.max_xmit_frag; this.MaxReceiveFragmentSize = bindAckPdu.max_recv_frag; this.AssociateGroupId = bindAckPdu.assoc_group_id; if (bindAckPdu.sec_addr.port_spec != null) { this.SecondaryAddress = Encoding.ASCII.GetString(bindAckPdu.sec_addr.port_spec); } if (bindAckPdu.p_result_list.p_results != null) { this.NdrVersion = RpceNdrVersion.None; for (int i = 0; i < bindAckPdu.p_result_list.p_results.Length; i++) { p_result_t p_result = bindAckPdu.p_result_list.p_results[i]; if (p_result.result == p_cont_def_result_t.acceptance) { if (p_result.transfer_syntax.if_uuid == RpceUtility.NDR_INTERFACE_UUID && p_result.transfer_syntax.if_vers_major == RpceUtility.NDR_INTERFACE_MAJOR_VERSION && p_result.transfer_syntax.if_vers_minor == RpceUtility.NDR_INTERFACE_MINOR_VERSION) { this.NdrVersion |= RpceNdrVersion.NDR; } else if (p_result.transfer_syntax.if_uuid == RpceUtility.NDR64_INTERFACE_UUID && p_result.transfer_syntax.if_vers_major == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION && p_result.transfer_syntax.if_vers_minor == RpceUtility.NDR64_INTERFACE_MINOR_VERSION) { this.NdrVersion |= RpceNdrVersion.NDR64; } } else if (p_result.result == p_cont_def_result_t.negotiate_ack) { byte[] bitmask = BitConverter.GetBytes((ushort)p_result.reason); this.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)bitmask[0]; if ((this.BindTimeFeatureNegotiationBitmask & RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp) != 0) { this.BindTimeFeatureNegotiationBitmask |= RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported; } } } foreach (KeyValuePair <ushort, RpceNdrVersion> item in this.PresentationContextsTable) { if ((this.NdrVersion & item.Value) == item.Value) { this.ContextIdentifier = item.Key; break; } } } }
/// <summary> /// update context on sending PDU. /// </summary> /// <param name="pdu">PDU to send.</param> internal void UpdateContextOnSendingPdu(RpcePdu pdu) { RpceCoPdu coPdu = pdu as RpceCoPdu; if (coPdu == null) { return; } this.RpcVersionMajor = coPdu.rpc_vers; this.RpcVersionMinor = coPdu.rpc_vers_minor; if (coPdu.PTYPE == RpcePacketType.Bind || coPdu.PTYPE == RpcePacketType.BindAck || coPdu.PTYPE == RpcePacketType.AlterContext || coPdu.PTYPE == RpcePacketType.AlterContextResp) { this.SupportsHeaderSign = (coPdu.pfc_flags & RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN) == RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN; } this.SupportsConcurrentMultiplexing = (coPdu.pfc_flags & RpceCoPfcFlags.PFC_CONC_MPX) == RpceCoPfcFlags.PFC_CONC_MPX; this.PackedDataRepresentationFormat = coPdu.packed_drep.dataRepFormat; if (coPdu.PTYPE != RpcePacketType.Request) { this.outstandingCalls.Remove(coPdu.call_id); } switch (coPdu.PTYPE) { case RpcePacketType.BindAck: RpceCoBindAckPdu bindAckPdu = coPdu as RpceCoBindAckPdu; if (bindAckPdu != null) { UpdateContextOnSendingBindAckPdu(bindAckPdu); } break; case RpcePacketType.Request: RpceCoRequestPdu requestPdu = coPdu as RpceCoRequestPdu; if (requestPdu != null) { this.ContextIdentifier = requestPdu.p_cont_id; } break; case RpcePacketType.Response: RpceCoResponsePdu responsePdu = coPdu as RpceCoResponsePdu; if (responsePdu != null) { this.ContextIdentifier = responsePdu.p_cont_id; } break; case RpcePacketType.BindNak: case RpcePacketType.AlterContextResp: case RpcePacketType.Fault: case RpcePacketType.Shutdown: default: //default situation should do nothing. //This is just update the context, if we cannot recognize the PDU, ignore it. break; } }
public static RpceCoPdu DecodeCoPdu( RpceContext context, byte[] pduBytes) { if (context == null) { throw new ArgumentNullException("context"); } if (pduBytes == null) { throw new ArgumentNullException("pduBytes"); } RpceCoPdu pdu; //#2 byte is PTYPE RpcePacketType packageType = (RpcePacketType)pduBytes[2]; //#3 byte is PFC_*** flags RpceCoPfcFlags pfcFlags = (RpceCoPfcFlags)pduBytes[3]; RpceCoPfcFlags pfcFlagsNoFragment = RpceCoPfcFlags.PFC_FIRST_FRAG | RpceCoPfcFlags.PFC_LAST_FRAG; if (((pfcFlags & pfcFlagsNoFragment) != pfcFlagsNoFragment) && (packageType == RpcePacketType.Bind || packageType == RpcePacketType.BindAck || packageType == RpcePacketType.AlterContext || packageType == RpcePacketType.AlterContextResp || packageType == RpcePacketType.Auth3)) { //If it's a fragment and PTYPE is bind/bind_ack/alter_context/alter_context_resp //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."); } else { switch (packageType) { case RpcePacketType.Bind: pdu = new RpceCoBindPdu(context, pduBytes); break; case RpcePacketType.BindAck: pdu = new RpceCoBindAckPdu(context, pduBytes); break; case RpcePacketType.BindNak: pdu = new RpceCoBindNakPdu(context, pduBytes); break; case RpcePacketType.AlterContext: pdu = new RpceCoAlterContextPdu(context, pduBytes); break; case RpcePacketType.AlterContextResp: pdu = new RpceCoAlterContextRespPdu(context, pduBytes); break; case RpcePacketType.Auth3: pdu = new RpceCoAuth3Pdu(context, pduBytes); break; case RpcePacketType.Request: pdu = new RpceCoRequestPdu(context, pduBytes); break; case RpcePacketType.Response: pdu = new RpceCoResponsePdu(context, pduBytes); break; case RpcePacketType.Fault: pdu = new RpceCoFaultPdu(context, pduBytes); break; case RpcePacketType.CoCancel: pdu = new RpceCoCancelPdu(context, pduBytes); break; case RpcePacketType.Orphaned: pdu = new RpceCoOrphanedPdu(context, pduBytes); break; case RpcePacketType.Shutdown: pdu = new RpceCoShutdownPdu(context, pduBytes); break; default: throw new InvalidOperationException( string.Format("Receive invalid packet - {0}.", packageType)); } } return(pdu); }
public RpceCoBindAckPdu CreateCoBindAckPdu( RpceServerSessionContext sessionContext) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } RpceCoBindAckPdu bindAckPdu = new RpceCoBindAckPdu(sessionContext); float serverRpcVersion = (float)sessionContext.ServerContext.RpcVersionMajor + (float)sessionContext.ServerContext.RpcVersionMinor / 10.0f; float proposedRpcVersion = (float)sessionContext.RpcVersionMajor + (float)sessionContext.RpcVersionMinor / 10.0f; float rpcVersion = Math.Min(serverRpcVersion, proposedRpcVersion); bindAckPdu.rpc_vers = (byte)Math.Truncate(rpcVersion); bindAckPdu.rpc_vers_minor = (byte)((rpcVersion - Math.Truncate(rpcVersion)) * 10.0f); bindAckPdu.PTYPE = RpcePacketType.BindAck; bindAckPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.BindAck); bindAckPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; bindAckPdu.packed_drep.reserved = 0; bindAckPdu.call_id = sessionContext.CurrentCallId; bindAckPdu.max_xmit_frag = sessionContext.MaxTransmitFragmentSize; bindAckPdu.max_recv_frag = sessionContext.MaxReceiveFragmentSize; bindAckPdu.assoc_group_id = sessionContext.AssociateGroupId; if (sessionContext.SecondaryAddress == null) { bindAckPdu.sec_addr.port_spec = new byte[0]; } else { bindAckPdu.sec_addr.port_spec = Encoding.ASCII.GetBytes(sessionContext.SecondaryAddress); } bindAckPdu.sec_addr.length = (ushort)bindAckPdu.sec_addr.port_spec.Length; int sizeOfSecAddr = bindAckPdu.sec_addr.length + Marshal.SizeOf(bindAckPdu.sec_addr.length); bindAckPdu.pad2 = new byte[RpceUtility.Align(sizeOfSecAddr, 4) - sizeOfSecAddr]; RpceNdrVersion ndrVersion = sessionContext.ServerContext.NdrVersion; List<p_result_t> presentationResultList = new List<p_result_t>(); for (int i = 0; i < sessionContext.PresentationContextsTable.Count; i++) { p_result_t pResult = new p_result_t(); RpceNdrVersion proposedNdrVersion = sessionContext.PresentationContextsTable.Values[i]; if ((proposedNdrVersion & ndrVersion) != 0) { pResult.result = p_cont_def_result_t.acceptance; // donot accept any more NDR version. ndrVersion = RpceNdrVersion.None; } else { pResult.result = p_cont_def_result_t.provider_rejection; } pResult.reason = p_provider_reason_t.reason_not_specified; if (proposedNdrVersion == RpceNdrVersion.NDR) { pResult.transfer_syntax.if_uuid = RpceUtility.NDR_INTERFACE_UUID; pResult.transfer_syntax.if_vers_major = RpceUtility.NDR_INTERFACE_MAJOR_VERSION; pResult.transfer_syntax.if_vers_minor = RpceUtility.NDR_INTERFACE_MINOR_VERSION; } else if (proposedNdrVersion == RpceNdrVersion.NDR64) { pResult.transfer_syntax.if_uuid = RpceUtility.NDR64_INTERFACE_UUID; pResult.transfer_syntax.if_vers_major = RpceUtility.NDR64_INTERFACE_MAJOR_VERSION; pResult.transfer_syntax.if_vers_minor = RpceUtility.NDR64_INTERFACE_MINOR_VERSION; } presentationResultList.Add(pResult); } if (sessionContext.BindTimeFeatureNegotiationBitmask != RpceBindTimeFeatureNegotiationBitmask.None) { RpceBindTimeFeatureNegotiationBitmask bindTimeFeatureNegotiationBitmask = sessionContext.BindTimeFeatureNegotiationBitmask; if ((bindTimeFeatureNegotiationBitmask & RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported) != 0) { bindTimeFeatureNegotiationBitmask |= RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp; } bindTimeFeatureNegotiationBitmask &= (sessionContext.ServerContext.SupportsSecurityContextMultiplexing ? RpceBindTimeFeatureNegotiationBitmask.SecurityContextMultiplexingSupported : RpceBindTimeFeatureNegotiationBitmask.None) | (sessionContext.ServerContext.SupportsKeepConnectionOnOrphan ? RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp : RpceBindTimeFeatureNegotiationBitmask.None); p_result_t pResult = new p_result_t(); pResult.result = p_cont_def_result_t.negotiate_ack; pResult.reason = (p_provider_reason_t)bindTimeFeatureNegotiationBitmask; presentationResultList.Add(pResult); } bindAckPdu.p_result_list.n_results = (byte)presentationResultList.Count; bindAckPdu.p_result_list.p_results = presentationResultList.ToArray(); bindAckPdu.AppendAuthenticationVerifier(); bindAckPdu.SetLength(); return bindAckPdu; }
/// <summary> /// update context on receiving RPCE CO BindAck PDU /// </summary> /// <param name="bindAckPdu">BindAck PDU</param> private void UpdateContextOnReceivingBindAckPdu(RpceCoBindAckPdu bindAckPdu) { context.MaxTransmitFragmentSize = bindAckPdu.max_xmit_frag; context.MaxReceiveFragmentSize = bindAckPdu.max_recv_frag; context.AssociateGroupId = bindAckPdu.assoc_group_id; if (bindAckPdu.sec_addr.port_spec != null) { context.SecondaryAddress = Encoding.ASCII.GetString(bindAckPdu.sec_addr.port_spec); } if (bindAckPdu.p_result_list.p_results != null) { context.NdrVersion = RpceNdrVersion.None; for (int i = 0; i < bindAckPdu.p_result_list.p_results.Length; i++) { if (bindAckPdu.p_result_list.p_results[i].result == p_cont_def_result_t.acceptance) { if (bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_uuid == RpceUtility.NDR_INTERFACE_UUID && bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_major == RpceUtility.NDR_INTERFACE_MAJOR_VERSION && bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_minor == RpceUtility.NDR_INTERFACE_MINOR_VERSION) { context.NdrVersion |= RpceNdrVersion.NDR; } else if (bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_uuid == RpceUtility.NDR64_INTERFACE_UUID && bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_major == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION && bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_minor == RpceUtility.NDR64_INTERFACE_MINOR_VERSION) { context.NdrVersion |= RpceNdrVersion.NDR64; } } else if (bindAckPdu.p_result_list.p_results[i].result == p_cont_def_result_t.negotiate_ack) { byte[] bitmask = BitConverter.GetBytes( (ushort)bindAckPdu.p_result_list.p_results[i].reason); context.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)bitmask[0]; } } foreach (KeyValuePair<ushort, RpceNdrVersion> item in context.PresentationContextsTable) { if ((context.NdrVersion & item.Value) == item.Value) { context.ContextIdentifier = item.Key; break; } } } }