private void RemotingServer_ReceiveClientDataComplete(object sender, EventArgs<Guid, byte[], int> e)
{
ClientInfo client = FindConnectedClient(e.Argument1);
if ((object)client == null)
{
// First message from a remote client should be its info.
Serialization.TryDeserialize(e.Argument2.BlockCopy(0, e.Argument3), m_serializationFormat, out client);
try
{
if ((object)client != null)
{
client.ClientID = e.Argument1;
client.ConnectedAt = DateTime.UtcNow;
if (TrySetCurrentThreadPrincipal(client))
{
// Engage security for the remote client connection if configured.
if (!m_secureRemoteInteractions || VerifySecurity(client))
{
lock (m_remoteClients)
{
m_remoteClients.Add(client);
}
SendAuthenticationSuccessResponse(client.ClientID);
UpdateStatus(UpdateType.Information, "Remote client connected - {0} from {1}.\r\n\r\n", client.ClientUser.Identity.Name, client.MachineName);
}
else
{
throw new SecurityException($"Failed to authenticate '{client.ClientName}' - thread principal identity was '{Thread.CurrentPrincipal.Identity.Name}'");
}
}
else
{
throw new SecurityException($"Failed to retrieve client principal from the socket connection: remote client '{client.ClientID}' not found");
}
}
else
{
// Required client information is missing.
throw new SecurityException("Remote client failed to transmit the required information");
}
}
catch (Exception ex)
{
LogException(ex);
try
{
SendResponse(e.Argument1, new ServiceResponse("AuthenticationFailure"), false);
if ((object)m_remotingServer != null)
m_remotingServer.DisconnectOne(e.Argument1);
if ((object)client != null)
UpdateStatus(UpdateType.Warning, "Remote client connection rejected - {0} [{1}] from {2}\r\n\r\n", client.ClientName, client.ClientUser.Identity.Name, client.MachineName);
}
catch (Exception ex2)
{
LogException(ex2);
}
}
}
else
{
// All subsequent messages from a remote client would be requests.
ClientRequest request;
ClientRequestInfo requestInfo = null;
Serialization.TryDeserialize(e.Argument2.BlockCopy(0, e.Argument3), m_serializationFormat, out request);
if ((object)request != null)
{
try
{
requestInfo = new ClientRequestInfo(client, request);
string resource = requestInfo.Request.Command;
if (m_remoteCommandClientID == Guid.Empty)
{
// Process incoming requests when remote command session is not in progress.
lock (m_clientRequestHistory)
{
m_clientRequestHistory.Add(requestInfo);
if (m_clientRequestHistory.Count > m_requestHistoryLimit)
m_clientRequestHistory.RemoveRange(0, (m_clientRequestHistory.Count - m_requestHistoryLimit));
}
// Check if remote client has permission to invoke the requested command.
if (m_secureRemoteInteractions)
{
// Validate current client principal
if (TrySetCurrentThreadPrincipal(client))
{
if (VerifySecurity(requestInfo.Sender))
{
if (SecurityProviderUtility.IsResourceSecurable(resource) && !SecurityProviderUtility.IsResourceAccessible(resource))
throw new SecurityException($"Access to '{requestInfo.Request.Command}' is denied");
}
else
{
throw new SecurityException($"Failed to authenticate '{Thread.CurrentPrincipal.Identity.Name}'");
}
}
else
{
throw new SecurityException($"Failed to retrieve client principal from the socket connection: remote client '{client.ClientID}' not found");
}
}
// Notify the consumer about the incoming request from client.
OnReceivedClientRequest(request, client);
ClientRequestHandler requestHandler = FindClientRequestHandler(request.Command);
if ((object)requestHandler != null)
{
// Request handler exists.
requestHandler.HandlerMethod(requestInfo);
}
else
{
// No request handler exists.
throw new InvalidOperationException("Request is not supported");
}
}
else if (client.ClientID == m_remoteCommandClientID)
{
// Redirect requests to remote command session if requests are from its originator.
RemoteTelnetSession(requestInfo);
}
else
{
// Reject all request from other clients since remote command session is in progress.
throw new InvalidOperationException("Remote telnet session is in progress");
}
}
catch (Exception ex)
{
LogException(ex);
if ((object)requestInfo != null)
SendActionableResponse(requestInfo, false, null, "Failed to process request \"{0}\" - {1}\r\n\r\n", request.Command, ex.Message);
else
UpdateStatus(client.ClientID, UpdateType.Alarm, "Failed to process request \"{0}\" - {1}\r\n\r\n", request.Command, ex.Message);
}
}
else
{
UpdateStatus(client.ClientID, UpdateType.Alarm, "Failed to process request - Request could not be deserialized.\r\n\r\n");
}
}
}