/// <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> /// Connect and bind to a RPCE remote host. /// </summary> /// <param name="protocolSequence"> /// A protocol sequence.<para/> /// Support ncacn_ip_tcp and ncacn_np only. /// </param> /// <param name="networkAddress"> /// A network address of RPCE remote host. /// </param> /// <param name="endpoint"> /// An endpoint that its format and content /// are associated with the protocol sequence. /// </param> /// <param name="transportCredential"> /// If connect by SMB/SMB2, it's the security credential /// used by underlayer transport (SMB/SMB2). /// If connect by TCP, this parameter is ignored. /// </param> /// <param name="interfaceId"> /// A Guid of interface_id that is binding to. /// </param> /// <param name="interfaceMajorVersion"> /// interface_major_ver that is binding to. /// </param> /// <param name="interfaceMinorVersion"> /// interface_minor_ver that is binding to. /// </param> /// <param name="securityContext"> /// A security provider. If setting to null, indicate the default authentication type NTLM is selected. /// </param> /// <param name="connectSecurityContext"> /// A security provider for connect authentication. If setting to null, indicate the default authentication type NTLM is selected. /// </param> /// <param name="authenticationLevel"> /// An authentication level. /// </param> /// <param name="supportsHeaderSign"> /// Indicates whether client supports header sign or not. /// </param> /// <param name="timeout"> /// Timeout period. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when protSeq, networkAddr or endpoint is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> public virtual void Bind( string protocolSequence, string networkAddress, string endpoint, AccountCredential transportCredential, Guid interfaceId, ushort interfaceMajorVersion, ushort interfaceMinorVersion, ClientSecurityContext securityContext, ClientSecurityContext connectSecurityContext, RpceAuthenticationLevel authenticationLevel, bool supportsHeaderSign, TimeSpan timeout) { if (protocolSequence == null) { throw new ArgumentNullException("protocolSequence"); } if (networkAddress == null) { throw new ArgumentNullException("networkAddress"); } if (endpoint == null) { throw new ArgumentNullException("endpoint"); } // RPC over named-pipe does not support asynchronous call in this library. // http://msdn.microsoft.com/en-us/library/windows/desktop/aa373551(v=vs.85).aspx rpceClient.Context.IsAsynchronous = (string.Compare(protocolSequence, RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, true) != 0); rpceClient.Connect(protocolSequence, networkAddress, endpoint, transportCredential, timeout, connectSecurityContext == null ? SecurityPackageType.Ntlm : connectSecurityContext.PackageType); rpceClient.SetAuthInfo(securityContext, authenticationLevel, rpceClient.Context.AuthenticationContextId); RpceCoBindPdu bindPdu = rpceClient.CreateCoBindPdu( //read from context, donot hardcode. rpceClient.Context.RpcVersionMinor, // default is rpc vers 5.0 supportsHeaderSign ? RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN : RpceCoPfcFlags.None, rpceClient.ComputeNextCallId(), // call id, default is 1 rpceClient.Context.MaxTransmitFragmentSize, // max xmit frag rpceClient.Context.MaxReceiveFragmentSize, // max recv frag rpceClient.Context.AssociateGroupId, // assoc group id, default 0 interfaceId, interfaceMajorVersion, interfaceMinorVersion, rpceClient.Context.NdrVersion, // default is NDR (rpceClient.Context.BindTimeFeatureNegotiationBitmask != RpceBindTimeFeatureNegotiationBitmask.None) // default is None ? (RpceBindTimeFeatureNegotiationBitmask?)rpceClient.Context.BindTimeFeatureNegotiationBitmask : null); FragmentAndSendPdu(bindPdu); RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout); if (receivedPdu is RpceCoBindAckPdu) { if (rpceClient.Context.NdrVersion == RpceNdrVersion.None) { throw new InvalidOperationException("Neither NDR nor NDR64 is supported."); } } else { RpceCoBindNakPdu bindNakPdu = receivedPdu as RpceCoBindNakPdu; if (bindNakPdu != null) { throw new InvalidOperationException(bindNakPdu.provider_reject_reason.ToString()); } else { throw new InvalidOperationException( string.Format("Unexpected packet type received - {0}.", receivedPdu.GetType().Name)); } } while (rpceClient.Context.SecurityContext != null && rpceClient.Context.SecurityContext.NeedContinueProcessing) { RpceCoAlterContextPdu alterContextPdu = rpceClient.CreateCoAlterContextPdu(); FragmentAndSendPdu(alterContextPdu); receivedPdu = ReceiveAndReassemblePdu(timeout); RpceCoFaultPdu faultPdu = receivedPdu as RpceCoFaultPdu; if (faultPdu != null) { throw new InvalidOperationException(faultPdu.status.ToString()); } if (!(receivedPdu is RpceCoAlterContextRespPdu)) { throw new InvalidOperationException("Expect alter_context_pdu, but received others."); } } if (rpceClient.Context.SecurityContext != null && rpceClient.Context.SecurityContext.Token != null && rpceClient.Context.SecurityContext.Token.Length != 0) { RpceCoAuth3Pdu auth3Pdu = rpceClient.CreateCoAuth3Pdu(); FragmentAndSendPdu(auth3Pdu); // no expected response from server rpceClient.Context.OutstandingCalls.Remove(auth3Pdu.call_id); } if (rpceClient.Context.IsAsynchronous) { // Start the receiving thread to receive the response from server. cancellationToken = new CancellationTokenSource(); receiveTask = new Task(EventLoop, cancellationToken.Token); //new Thread(new ThreadStart(EventLoop)); //receiveThread.IsBackground = true; receiveTask.Start(); } }
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 RpceCoBindNakPdu CreateCoBindNakPdu( RpceServerSessionContext sessionContext, p_reject_reason_t rejectReason, byte[] extendedErrorInfo) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } RpceCoBindNakPdu bindNakPdu = new RpceCoBindNakPdu(sessionContext); bindNakPdu.rpc_vers = sessionContext.RpcVersionMajor; bindNakPdu.rpc_vers_minor = sessionContext.RpcVersionMinor; bindNakPdu.PTYPE = RpcePacketType.BindNak; bindNakPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.BindNak); bindNakPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; bindNakPdu.packed_drep.reserved = 0; bindNakPdu.call_id = sessionContext.CurrentCallId; bindNakPdu.provider_reject_reason = rejectReason; bindNakPdu.versions.n_protocols = 1; // only one rpc version in server context. bindNakPdu.versions.p_protocols = new version_t[bindNakPdu.versions.n_protocols]; // It's the supported rpc versions, so we response version number in server context. bindNakPdu.versions.p_protocols[0].major = sessionContext.ServerContext.RpcVersionMajor; bindNakPdu.versions.p_protocols[0].major = sessionContext.ServerContext.RpcVersionMinor; int sizeOfReasonAndVersions = Marshal.SizeOf(typeof(ushort)); // bindNakPdu.provider_reject_reason sizeOfReasonAndVersions += Marshal.SizeOf(bindNakPdu.versions.n_protocols); sizeOfReasonAndVersions += Marshal.SizeOf(typeof(version_t)) * bindNakPdu.versions.n_protocols; bindNakPdu.pad = new byte[RpceUtility.Align(sizeOfReasonAndVersions, 4) - sizeOfReasonAndVersions]; if (extendedErrorInfo != null) { bindNakPdu.signature = RpceUtility.BINDNAK_SIGNATURE; bindNakPdu.extended_error_info = extendedErrorInfo; } bindNakPdu.SetLength(); return bindNakPdu; }