/// <summary> /// Removes the link between the rpce session context with its corresponding /// nrpc session context. /// </summary> /// <param name="rpceSessionContext">The rpce layer session context</param> internal void RemoveSessionContext(RpceServerSessionContext rpceSessionContext) { lock (lockObj) { sessionContextMap.Remove(rpceSessionContext); } }
/// <summary> /// Lookup the RPCE session context. /// </summary> /// <param name="remoteEndpoint">remote Endpoint. (IPEndPoint or SmbFile)</param> /// <returns>The sessionContext with the specific key.</returns> internal RpceServerSessionContext LookupSessionContext(object remoteEndpoint) { string key = BuildSessionContextKey(remoteEndpoint); RpceServerSessionContext sessionContext; lock (this.sessions) { if (!this.sessions.TryGetValue(key, out sessionContext)) { sessionContext = null; } if (sessionContext == null) { // Create / retrieve temp session when it is not created by user. if (!this.tempSessions.TryGetValue(key, out sessionContext)) { sessionContext = new RpceServerSessionContext(this, remoteEndpoint); this.tempSessions.Add(key, sessionContext); } } } return(sessionContext); }
/// <summary> /// Create and add a session context to the session collection. /// </summary> /// <param name="remoteEndpoint">remote Endpoint. (IPEndPoint or SmbFile)</param> /// <returns>The sessionContext with the specific key.</returns> internal RpceServerSessionContext CreateAndAddSessionContext(object remoteEndpoint) { string key = BuildSessionContextKey(remoteEndpoint); RpceServerSessionContext sessionContext; lock (this.sessions) { if (this.tempSessions.TryGetValue(key, out sessionContext)) { this.tempSessions.Remove(key); } else { sessionContext = new RpceServerSessionContext(this, remoteEndpoint); } if (!this.sessions.ContainsKey(key)) { this.sessions.Add(key, sessionContext); } } return(sessionContext); }
/// <summary> /// Calling this method to be notified when a new RPC connection is coming. /// Users, who don't care about the coming of a new connection, just call ExpectCall directly. /// </summary> /// <param name="ifId"> /// If_id to accept the bind. Null to accept all interface regardless the if_id. /// </param> /// <param name="ifMajorVer"> /// If_major_ver to accept the bind. Null to accept all interface regardless the if_major_ver. /// </param> /// <param name="ifMinorVer"> /// If_minor_ver to accept the bind. Null to accept all interface regardless the if_minor_ver. /// </param> /// <param name="timeout">Timeout of expecting a connection.</param> /// <param name="sessionContext">The sessionContext of binded connection.</param> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when securityProvider is null and auth_level is not NONE /// </exception> /// <exception cref="SspiException"> /// Thrown when accept client token failed /// </exception> public virtual void ExpectBind( Guid?ifId, ushort?ifMajorVer, ushort?ifMinorVer, TimeSpan timeout, out RpceServerSessionContext sessionContext) { if (this.registeredInterfaceList.Count > 0) { throw new InvalidOperationException("Auto accept bind was turned on, ExpectBind is not allowed."); } DateTime t0 = DateTime.Now; sessionContext = rpceServer.ExpectConnect(timeout); RpcIfMatchFunc matchFunc = delegate(RpcIf rpcIf) { return(!((ifId != null && rpcIf.id != ifId.Value) || (ifMajorVer != null && rpcIf.majorVer != ifMajorVer.Value) || (ifMinorVer != null && rpcIf.minorVer != ifMinorVer.Value))); }; while (!InternalExpectBind(matchFunc, timeout - (DateTime.Now - t0), ref sessionContext)) { if ((DateTime.Now - t0) >= timeout) { throw new TimeoutException(); } } }
/// <summary> /// Expect to receive a call. /// </summary> /// <param name="timeout">Timeout of expecting a call.</param> /// <param name="sessionContext">Session Context of the received call.</param> /// <param name="opnum">Operation number of the method invoked.</param> /// <returns>Received a byte array of the request stub from a client.</returns> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> public virtual byte[] ExpectCall( TimeSpan timeout, out RpceServerSessionContext sessionContext, out ushort opnum) { sessionContext = null; RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoRequestPdu requestPdu = receivedPdu as RpceCoRequestPdu; if (requestPdu == null) { throw new InvalidOperationException("Expect request_pdu, but received others."); } opnum = requestPdu.opnum; byte[] stub = requestPdu.stub; if (stub == null) { stub = new byte[0]; } return(stub); }
/// <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> /// Expect to disconnect from the specific client. /// </summary> /// <param name="timeout">Timeout of expecting to disconnect with client.</param> /// <param name="sessionContext">The sessionContext of expecting to disconnect.</param> public virtual void ExpectDisconnect( TimeSpan timeout, out RpceServerSessionContext sessionContext) { if (this.registeredInterfaceList.Count > 0) { throw new InvalidOperationException("Auto accept bind was turned on, ExpectBind is not allowed."); } sessionContext = null; this.rpceServer.ExpectDisconnect(timeout, ref sessionContext); }
/// <summary> /// Initialize a RpceTransportEvent. /// </summary> /// <param name="type">the type of the occurred event.</param> /// <param name="remoteEndpoint">the remote endpoint from which the event occurred.</param> /// <param name="localEndpoint">the local endpoint from which the event occurred.</param> /// <param name="serverContext">The server context.</param> /// <param name="sessionContext">The session context.</param> /// <param name="pdu">A received PDU.</param> internal RpceTransportEvent( EventType type, object remoteEndpoint, object localEndpoint, RpceServerContext serverContext, RpceServerSessionContext sessionContext, RpcePdu pdu) : base(type, remoteEndpoint, localEndpoint, pdu) { //because sessionContext might be null when accept a connection, we must pass it in. this.serverContext = serverContext; this.sessionContext = sessionContext; this.pdu = pdu; }
/// <summary> /// Send a Response to client. /// </summary> /// <param name="sessionContext">Context of the RPCE session.</param> /// <param name="responseStub">A byte array of the response stub send to client.</param> /// <exception cref="ArgumentNullException">Thrown when responseStub is null.</exception> public virtual void SendResponse( RpceServerSessionContext sessionContext, byte[] responseStub) { if (responseStub == null) { throw new ArgumentNullException("responseStub"); } RpceCoResponsePdu responsePdu = this.rpceServer.CreateCoResponsePdu(sessionContext, responseStub); FragmentAndSendPdu(sessionContext, responsePdu); }
/// <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> /// Lookup the RPCE session context. /// </summary> /// <param name="remoteEndpoint">remote Endpoint. (IPEndPoint or SmbFile)</param> /// <returns>The sessionContext with the specific key.</returns> internal RpceServerSessionContext LookupSessionContext(object remoteEndpoint) { lock (this.serverContexts) { foreach (KeyValuePair <string, RpceServerContext> item in this.serverContexts) { RpceServerSessionContext sessionContext = item.Value.LookupSessionContext(remoteEndpoint); if (sessionContext != null) { return(sessionContext); } } } return(null); }
/// <summary> /// Remove a session context from the session collection. /// </summary> ///<param name="sessionContext">The session to remove.</param> internal void RemoveSessionContext(RpceServerSessionContext sessionContext) { string key = BuildSessionContextKey(sessionContext.RemoteEndpoint); lock (this.sessions) { if (this.sessions.ContainsKey(key)) { this.sessions.Remove(key); } if (this.tempSessions.ContainsKey(key)) { this.tempSessions.Remove(key); } } }
/// <summary> /// Look up the NRPC session context using the session context of RPCE /// </summary> /// <param name="rpceSessionContext">The RPCE layer session context</param> /// <param name="sessionContext">The corresponding NRPC session context</param> /// <returns>Whether the rpce session is a new session</returns> internal bool LookupSessionContext(RpceServerSessionContext rpceSessionContext, out NrpcServerSessionContext sessionContext) { lock (lockObj) { if (sessionContextMap.ContainsKey(rpceSessionContext)) { sessionContext = sessionContextMap[rpceSessionContext]; return false; } else { sessionContext = new NrpcServerSessionContext(); sessionContextMap[rpceSessionContext] = sessionContext; return true; } } }
/// <summary> /// Generate PFC_*** based on context and package type. /// </summary> /// <param name="context">Context of the session.</param> /// <param name="packageType">package type.</param> /// <returns>RFC_*** flag.</returns> internal static RpceCoPfcFlags GeneratePfcFlags(RpceContext context, RpcePacketType packageType) { RpceServerSessionContext sessionContext = context as RpceServerSessionContext; RpceCoPfcFlags flags = RpceCoPfcFlags.PFC_FIRST_FRAG | RpceCoPfcFlags.PFC_LAST_FRAG; if (sessionContext == null) //client-side { if (context.SupportsConcurrentMultiplexing) { flags |= RpceCoPfcFlags.PFC_CONC_MPX; } } else if ( //server-side (packageType == RpcePacketType.BindAck && sessionContext.ServerContext.SupportsConcurrentMultiplexing) || // first response, read server context sessionContext.SupportsConcurrentMultiplexing) // if it's not first response, we can read session context { flags |= RpceCoPfcFlags.PFC_CONC_MPX; } if ((packageType == RpcePacketType.Bind || packageType == RpcePacketType.BindAck || packageType == RpcePacketType.AlterContext || packageType == RpcePacketType.AlterContextResp) && context.SupportsHeaderSign) { if (sessionContext == null || //client-side sessionContext.ServerContext.SupportsHeaderSign) //server-side { flags |= RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN; } } return(flags); }
/// <summary> /// Send a PDU to a specific connected client. /// </summary> /// <param name="pdu">Rpce PDU to send.</param> /// <param name="sessionContext">Context of the RPCE session.</param> /// <exception cref="ArgumentNullException"> /// Thrown when sessionContext or pdu is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when underlayer transport was not established. /// Thrown when protocol sequence is unknown. /// </exception> public virtual void SendPdu( RpceServerSessionContext sessionContext, RpcePdu pdu) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } if (pdu == null) { throw new ArgumentNullException("pdu"); } EnsureTransportIsValid(); sessionContext.UpdateContextOnSendingPdu(pdu); if (sessionContext.ProtocolSequence.Equals( RpceUtility.RPC_OVER_TCPIP_PROTOCOL_SEQUENCE, StringComparison.OrdinalIgnoreCase)) { this.tcpTransport.SendPacket(sessionContext.RemoteEndpoint, pdu); } else if (sessionContext.ProtocolSequence.Equals( RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, StringComparison.OrdinalIgnoreCase)) { lock (sessionContext.smbSendingLocker) { sessionContext.smbBufferSending = ArrayUtility.ConcatenateArrays( sessionContext.smbBufferSending, pdu.ToBytes()); if (sessionContext.smbSendingFunc != null) { sessionContext.smbSendingFunc(); } } } else { throw new InvalidOperationException("Unknown protocol sequence."); } }
private void ProcessReceivedData( RpceServerSessionContext sessionContext, byte[] buf) { RpceServerContext serverContext = sessionContext.ServerContext; string namedPipeName = serverContext.Endpoint; object fid = sessionContext.fsOpen.FileId; buf = ArrayUtility.ConcatenateArrays(sessionContext.smbBufferReceiving, buf); int consumedLength; int expectedLength; RpceCoPdu[] pduList = (RpceCoPdu[])this.RpceDecodePduCallback( fid, buf, out consumedLength, out expectedLength); for (int i = 0; i < pduList.Length; i++) { this.receivedTransportEvents.Enqueue( new RpceTransportEvent( EventType.ReceivedPacket, fid, namedPipeName, serverContext, sessionContext, pduList[i])); } sessionContext.smbBufferReceiving = ArrayUtility.SubArray(buf, consumedLength); }
/// <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())); }
/// <summary> /// Disconnect with a client. /// </summary> /// <param name="sessionContext">Context of the RPCE session</param> public virtual void Disconnect(RpceServerSessionContext sessionContext) { this.rpceServer.Disconnect(sessionContext); }
/// <summary> /// Send a Fault to client. /// </summary> /// <param name="sessionContext">Context of the RPCE session.</param> /// <param name="statusCode">Status code.</param> public virtual void SendFault(RpceServerSessionContext sessionContext, uint statusCode) { RpceCoFaultPdu faultPdu = this.rpceServer.CreateCoFaultPdu(sessionContext, null, statusCode); FragmentAndSendPdu(sessionContext, faultPdu); }
/// <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> /// Lookup the RPCE session context. /// </summary> /// <param name="remoteEndpoint">remote Endpoint. (IPEndPoint or SmbFile)</param> /// <returns>The sessionContext with the specific key.</returns> internal RpceServerSessionContext LookupSessionContext(object remoteEndpoint) { string key = BuildSessionContextKey(remoteEndpoint); RpceServerSessionContext sessionContext; lock (this.sessions) { if (!this.sessions.TryGetValue(key, out sessionContext)) { sessionContext = null; } if (sessionContext == null) { // Create / retrieve temp session when it is not created by user. if (!this.tempSessions.TryGetValue(key, out sessionContext)) { sessionContext = new RpceServerSessionContext(this, remoteEndpoint); this.tempSessions.Add(key, sessionContext); } } } return sessionContext; }
private static byte[] PrepareSendingBuffer(RpceServerSessionContext sessionContext) { byte[] buf = sessionContext.smbBufferSending; sessionContext.smbBufferSending = new byte[0]; if (sessionContext.smbMaxSendingLength < buf.Length) { sessionContext.smbBufferSending = ArrayUtility.SubArray( buf, sessionContext.smbMaxSendingLength); buf = ArrayUtility.SubArray( buf, 0, sessionContext.smbMaxSendingLength); } return buf; }
/// <summary> /// Create a RpceCoRequestPdu. /// </summary> /// <param name="sessionContext">Context of the RPCE session.</param> /// <param name="opnum">Operation number (opnum) to /// inform a callback server of the operation it should invoke.</param> /// <param name="stub">Request stub.</param> /// <returns>Created RpceCoRequestPdu.</returns> /// <exception cref="ArgumentNullException">Thrown when sessionContext is null.</exception> public RpceCoRequestPdu CreateCoRequestPdu( RpceServerSessionContext sessionContext, ushort opnum, byte[] stub) { return CreateCoRequestPdu(sessionContext, opnum, sessionContext.CurrentCallId, stub); }
public RpceCoFaultPdu CreateCoFaultPdu( RpceServerSessionContext sessionContext, byte[] stub, uint statusCode) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } RpceCoFaultPdu faultPdu = new RpceCoFaultPdu(sessionContext); faultPdu.rpc_vers = sessionContext.RpcVersionMajor; faultPdu.rpc_vers_minor = sessionContext.RpcVersionMinor; faultPdu.PTYPE = RpcePacketType.Fault; faultPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.Fault); faultPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; faultPdu.packed_drep.reserved = 0; faultPdu.call_id = sessionContext.CurrentCallId; faultPdu.alloc_hint = (uint)(stub == null ? 0 : stub.Length); faultPdu.p_cont_id = sessionContext.ContextIdentifier; faultPdu.cancel_count = 0; faultPdu.reserved = 0; faultPdu.status = statusCode; faultPdu.reserved2 = 0; faultPdu.stub = stub; faultPdu.AppendAuthenticationVerifier(); faultPdu.SetLength(); return faultPdu; }
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; }
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> /// 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()); }
/// <summary> /// Disconnect from the specific client /// </summary> /// <param name="sessionContext">Context of session</param> /// <exception cref="ArgumentNullException"> /// Thrown when sessionContext is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when server was not started. /// </exception> public virtual void Disconnect(RpceServerSessionContext sessionContext) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } EnsureTransportIsValid(); if (sessionContext.ProtocolSequence.Equals( RpceUtility.RPC_OVER_TCPIP_PROTOCOL_SEQUENCE, StringComparison.OrdinalIgnoreCase)) { this.tcpTransport.Disconnect(sessionContext.RemoteEndpoint); } else if (sessionContext.ProtocolSequence.Equals( RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, StringComparison.OrdinalIgnoreCase)) { if (sessionContext.fsConnection != null) { Smb.SmbServerConnection connection = sessionContext.fsConnection as Smb.SmbServerConnection; if (connection.OpenList.Count == 0 || (connection.OpenList.Count == 1 && connection.OpenList[0].Equals(sessionContext.fsOpen))) { this.smbTransport.Disconnect(connection); } } } sessionContext.ServerContext.RemoveSessionContext(sessionContext); }
/// <summary> /// Expect to disconnect from the client. /// </summary> /// <param name="timeout">Timeout of expecting a disconnect.</param> /// <param name="sessionContext">The sessionContext of expecting to disconnect.</param> /// <exception cref="InvalidOperationException"> /// Thrown when unknown object was received from transport. /// Thrown when server was not started. /// </exception> public virtual void ExpectDisconnect( TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu pdu; EventType eventType = ExpectEvent( timeout, ref sessionContext, out pdu); if (eventType != EventType.Disconnected) { throw new InvalidOperationException( string.Format("{0} (unexpected) event received.", eventType)); } }
/// <summary> /// Expect an event (connect, disconnect, pdu received) with the specific sessionContext. /// </summary> /// <param name="timeout">Timeout of expecting a PDU.</param> /// <param name="sessionContext"> /// Session context to receive the event. /// Null means expect event on all sessions. /// </param> /// <param name="pdu">The PDU if receiving a packet; otherwise, null.</param> /// <returns>The expected PDU. It is null when event is connect or disconnect.</returns> /// <returns>The event type.</returns> /// <exception cref="InvalidOperationException"> /// Thrown when server was not started. /// </exception> public virtual EventType ExpectEvent( TimeSpan timeout, ref RpceServerSessionContext sessionContext, out RpcePdu pdu) { EnsureTransportIsValid(); RpceEventFilter filter; if (sessionContext == null) { filter = new RpceEventFilter( EventType.Connected | EventType.ReceivedPacket | EventType.Disconnected); } else { filter = new RpceEventFilter( EventType.Connected | EventType.ReceivedPacket | EventType.Disconnected, sessionContext.RemoteEndpoint); } RpceTransportEvent transportEvent = this.receivedTransportEvents.Dequeue(timeout, filter.EventFilter); ValidateTransportEvent( transportEvent, EventType.Connected | EventType.ReceivedPacket | EventType.Disconnected); if (transportEvent.EventType == EventType.Connected) { pdu = null; RpceServerContext serverContext = transportEvent.ServerContext; sessionContext = serverContext.CreateAndAddSessionContext( transportEvent.RemoteEndPoint); return EventType.Connected; } sessionContext = transportEvent.SessionContext; if (sessionContext == null) { throw new InvalidOperationException( "Session context was not found for this disconnect event."); } if (transportEvent.EventType == EventType.ReceivedPacket) { pdu = transportEvent.Pdu; if (pdu == null) { throw new InvalidOperationException("Unknown object received from transport."); } sessionContext.UpdateContextOnReceivingPdu(pdu); return EventType.ReceivedPacket; } if (transportEvent.EventType == EventType.Disconnected) { pdu = null; transportEvent.ServerContext.RemoveSessionContext(sessionContext); return EventType.Disconnected; } throw new InvalidOperationException("unknown event type"); }
/// <summary> /// Expect a Pdu with the specific sessionContext. /// </summary> /// <param name="timeout">Timeout of expecting a PDU.</param> /// <param name="sessionContext"> /// Session Context to receive PDU. /// Null means expect PDU on all sessions. /// </param> /// <returns>The expected PDU.</returns> /// <exception cref="InvalidOperationException"> /// Thrown when server was not started. /// </exception> public virtual RpcePdu ExpectPdu( TimeSpan timeout, ref RpceServerSessionContext sessionContext) { RpcePdu pdu; EventType eventType = ExpectEvent( timeout, ref sessionContext, out pdu); if (eventType != EventType.ReceivedPacket) { throw new InvalidOperationException( string.Format("{0} (unexpected) event received.", eventType)); } return pdu; }
/// <summary> /// Expect to receive a call. /// </summary> /// <param name="timeout">Timeout of expecting a call.</param> /// <param name="sessionContext">Session Context of the received call.</param> /// <param name="opnum">Operation number of the method invoked.</param> /// <returns>Received a byte array of the request stub from a client.</returns> /// <exception cref="InvalidOperationException"> /// Thrown when receive error from server. /// </exception> public virtual byte[] ExpectCall( TimeSpan timeout, out RpceServerSessionContext sessionContext, out ushort opnum) { sessionContext = null; RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext); RpceCoRequestPdu requestPdu = receivedPdu as RpceCoRequestPdu; if (requestPdu == null) { throw new InvalidOperationException("Expect request_pdu, but received others."); } opnum = requestPdu.opnum; byte[] stub = requestPdu.stub; if (stub == null) { stub = new byte[0]; } return stub; }
/// <summary> /// Remove a session from the server context. /// </summary> /// <param name="sessionContext">Context of the RPCE session.</param> /// <exception cref="ArgumentNullException">Thrown when sessionContext is null.</exception> public virtual void RemoveSessionContext(RpceServerSessionContext sessionContext) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } for (int i = 0; i < this.ServerContexts.Count; i++) { this.ServerContexts[i].RemoveSessionContext(sessionContext); } }
public RpceCoResponsePdu CreateCoResponsePdu( RpceServerSessionContext sessionContext, uint callId, byte[] stub) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } if (stub == null) { stub = new byte[0]; } RpceCoResponsePdu responsePdu = new RpceCoResponsePdu(sessionContext); responsePdu.rpc_vers = sessionContext.RpcVersionMajor; responsePdu.rpc_vers_minor = sessionContext.RpcVersionMinor; responsePdu.PTYPE = RpcePacketType.Response; responsePdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.Response); responsePdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; responsePdu.packed_drep.reserved = 0; responsePdu.call_id = callId; responsePdu.alloc_hint = (uint)stub.Length; responsePdu.p_cont_id = sessionContext.ContextIdentifier; responsePdu.stub = stub; responsePdu.cancel_count = 0; responsePdu.reserved = 0; responsePdu.AppendAuthenticationVerifier(); responsePdu.SetLength(); return responsePdu; }
public RpceCoAlterContextRespPdu CreateCoAlterContextRespPdu( RpceServerSessionContext sessionContext) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } RpceCoAlterContextRespPdu alterContextRespPdu = new RpceCoAlterContextRespPdu(sessionContext); alterContextRespPdu.rpc_vers = sessionContext.RpcVersionMajor; alterContextRespPdu.rpc_vers_minor = sessionContext.RpcVersionMinor; alterContextRespPdu.PTYPE = RpcePacketType.AlterContextResp; alterContextRespPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.AlterContextResp); alterContextRespPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; alterContextRespPdu.packed_drep.reserved = 0; alterContextRespPdu.call_id = sessionContext.CurrentCallId; alterContextRespPdu.max_xmit_frag = 0; alterContextRespPdu.max_recv_frag = 0; alterContextRespPdu.assoc_group_id = 0; alterContextRespPdu.sec_addr.length = 0; alterContextRespPdu.sec_addr.port_spec = new byte[0]; int sizeOfSecAddr = alterContextRespPdu.sec_addr.length + Marshal.SizeOf(alterContextRespPdu.sec_addr.length); alterContextRespPdu.pad2 = new byte[RpceUtility.Align(sizeOfSecAddr, 4) - sizeOfSecAddr]; //there's only one presentation result in alter_context_resp alterContextRespPdu.p_result_list.n_results = 1; alterContextRespPdu.p_result_list.p_results = new p_result_t[1]; alterContextRespPdu.p_result_list.p_results[0].result = p_cont_def_result_t.acceptance; alterContextRespPdu.p_result_list.p_results[0].reason = p_provider_reason_t.reason_not_specified; if (sessionContext.NdrVersion == RpceNdrVersion.NDR) { alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_uuid = RpceUtility.NDR_INTERFACE_UUID; alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_vers_major = RpceUtility.NDR_INTERFACE_MAJOR_VERSION; alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_vers_minor = RpceUtility.NDR_INTERFACE_MINOR_VERSION; } else if (sessionContext.NdrVersion == RpceNdrVersion.NDR64) { alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_uuid = RpceUtility.NDR64_INTERFACE_UUID; alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_vers_major = RpceUtility.NDR64_INTERFACE_MAJOR_VERSION; alterContextRespPdu.p_result_list.p_results[0].transfer_syntax.if_vers_minor = RpceUtility.NDR64_INTERFACE_MINOR_VERSION; } alterContextRespPdu.AppendAuthenticationVerifier(); alterContextRespPdu.SetLength(); return alterContextRespPdu; }
/// <summary> /// Create and add a session context to the session collection. /// </summary> /// <param name="remoteEndpoint">remote Endpoint. (IPEndPoint or SmbFile)</param> /// <returns>The sessionContext with the specific key.</returns> internal RpceServerSessionContext CreateAndAddSessionContext(object remoteEndpoint) { string key = BuildSessionContextKey(remoteEndpoint); RpceServerSessionContext sessionContext; lock (this.sessions) { if (this.tempSessions.TryGetValue(key, out sessionContext)) { this.tempSessions.Remove(key); } else { sessionContext = new RpceServerSessionContext(this, remoteEndpoint); } if (!this.sessions.ContainsKey(key)) { this.sessions.Add(key, sessionContext); } } return sessionContext; }
/// <summary> /// Create a RpceCoResponsePdu, the call_id is set to current call_id. /// The server maintains a current call_id for each connection. /// The current call_id is the highest call_id that the server has processed on this connection. /// </summary> /// <param name="sessionContext">Context of the RPCE session.</param> /// <param name="stub">Response stub.</param> /// <returns>Created RpceCoResponsePdu.</returns> public RpceCoResponsePdu CreateCoResponsePdu( RpceServerSessionContext sessionContext, byte[] stub) { return this.CreateCoResponsePdu(sessionContext, sessionContext.CurrentCallId, stub); }
public RpceCoShutdownPdu CreateCoShutdownPdu(RpceServerSessionContext sessionContext) { if (sessionContext == null) { throw new ArgumentNullException("sessionContext"); } RpceCoShutdownPdu shutdownPdu = new RpceCoShutdownPdu(sessionContext); shutdownPdu.rpc_vers = sessionContext.RpcVersionMajor; shutdownPdu.rpc_vers_minor = sessionContext.RpcVersionMinor; shutdownPdu.PTYPE = RpcePacketType.Shutdown; shutdownPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.Shutdown); shutdownPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat; shutdownPdu.packed_drep.reserved = 0; shutdownPdu.call_id = sessionContext.CurrentCallId; shutdownPdu.AppendAuthenticationVerifier(); shutdownPdu.SetLength(); return shutdownPdu; }