Skip to content

Commit

Permalink
Myrtille Session Shadow/Terminate Options Added.
Browse files Browse the repository at this point in the history
  • Loading branch information
sarathy365 committed Nov 3, 2020
1 parent 3662a5a commit 78d6b2b
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 108 deletions.
178 changes: 84 additions & 94 deletions Myrtille.Web/Default.aspx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ limitations under the License.
using Myrtille.Helpers;
using Myrtille.Services.Contracts;
using Myrtille.Web.Properties;
using Myrtille.Web.src.Utils;
using Newtonsoft.Json.Linq;

namespace Myrtille.Web
Expand Down Expand Up @@ -521,94 +522,6 @@ protected void ConnectButtonClick(
}
}

private static bool TrustCertificate(object sender, X509Certificate x509Certificate, X509Chain x509Chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}

private static JObject SecurdenWebRequest(string serverUrl, string requestUrl, string requestMethod, JObject requestParams)
{
requestUrl = serverUrl + requestUrl;
JObject result = null;
try
{
if (requestMethod == "GET" && requestParams != null)
{
requestUrl += '?';
requestUrl += "LAUNCHER_INPUT=" + requestParams.ToString();
}

ServicePointManager.ServerCertificateValidationCallback = TrustCertificate;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
var uri = new Uri(requestUrl);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = requestMethod;
request.UserAgent = "-SECURDEN-LAUNCHER-";
if (requestMethod == "POST" && requestParams != null)
{
var postData = "LAUNCHER_INPUT=" + requestParams.ToString();
var data = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = string.Empty;
using (var stream = new StreamReader(response.GetResponseStream()))
{
responseString = stream.ReadToEnd();
}
result = JObject.Parse(responseString);
response.Close();
}
catch (Exception)
{ }
return result;
}

private JObject ProcessLaunchRequest(string serverUrl, string authKey)
{
JObject returnObj = null;
JObject paramObj = new JObject(new JProperty("AUTH_KEY", authKey));
JObject response = null;
if (Request["access_url"] != null && Request["access_url"].Trim() != "")
{
string accessUrl = Request["access_url"].Trim();
if (accessUrl.EndsWith("/"))
{
accessUrl = accessUrl.Substring(0, accessUrl.Length - 1);
}
response = SecurdenWebRequest(accessUrl, "/launcher/verify_launch_info", "POST", paramObj);
}
if (response == null)
{
response = SecurdenWebRequest(serverUrl, "/launcher/verify_launch_info", "POST", paramObj);
}
if (response == null)
{
Response.Write("<script>alert('Not able to access Securden web server. Try again.'); window.close();</script>");
}
else if (response.ContainsKey("type"))
{
if ((string)response["type"] == "WEB_RDP")
{
returnObj = response;
}
else
{
Response.Write("<script>alert('Invalid option.'); window.close();</script>");
}
}
else
{
Response.Write("<script>alert('Unable to launch the connection. Try again.'); window.close();</script>");
}
return returnObj;
}

/// <summary>
/// connect the remote server
/// </summary>
Expand All @@ -617,6 +530,8 @@ private JObject ProcessLaunchRequest(string serverUrl, string authKey)
/// </remarks>
private bool ConnectRemoteServer()
{
var connectionId = Guid.NewGuid();

// connection parameters
string loginHostName = null;
var loginHostType = (HostType)Convert.ToInt32(hostType.Value);
Expand All @@ -637,20 +552,96 @@ private bool ConnectRemoteServer()
}
long userProfileId = 0;
long userSessionId = 0;
string accessUrl = null;

if (RemoteSession == null)
{
JObject connectionDetails = ProcessLaunchRequest(Request["referrer"], Request["auth_key"]);
JObject connectionDetails = SecurdenWeb.ProcessLaunchRequest(Request, Response, Request["referrer"], Request["auth_key"], connectionId.ToString());
if (connectionDetails == null)
{
return false;
}
else
{
if (connectionDetails["user_profile_id"] != null && connectionDetails["user_session_id"] != null)
userProfileId = (long)connectionDetails["user_profile_id"];
userSessionId = (long)connectionDetails["user_session_id"];
if ((string)connectionDetails["type"] == "SHADOW_SESSION")
{
connectionDetails = (JObject)connectionDetails["details"];
string guestShareId = "";
try
{
Application.Lock();

// create a new guest for the remote session
var sharedSessions = (IDictionary<Guid, SharingInfo>)Application[HttpApplicationStateVariables.SharedRemoteSessions.ToString()];
Guid OldConnectionId = new Guid((string)connectionDetails["connection_id"]);
var sharingInfo = new SharingInfo
{
RemoteSession = ((IDictionary<Guid, RemoteSession>) Application[HttpApplicationStateVariables.RemoteSessions.ToString()])[OldConnectionId],
GuestInfo = new GuestInfo
{
Id = Guid.NewGuid(),
ConnectionId = OldConnectionId,
Control = false,
}
};

sharedSessions.Add(sharingInfo.GuestInfo.Id, sharingInfo);
guestShareId = sharingInfo.GuestInfo.Id.ToString();
}
catch (ThreadAbortException)
{
// occurs because the response is ended after redirect
}
catch (Exception exc)
{
System.Diagnostics.Trace.TraceError("Failed to generate a session sharing url ({0})", exc);
}
finally
{
Application.UnLock();
}
if (guestShareId != "")
{
Response.Redirect("~/?gid=" + guestShareId, true);
}
else
{
Response.Write("<script>alert('Invalid session.'); window.close();</script>");
}
return false;
}
else if ((string) connectionDetails["type"] == "TERMINATE_SESSION")
{
userProfileId = (long)connectionDetails["user_profile_id"];
userSessionId = (long)connectionDetails["user_session_id"];
connectionDetails = (JObject)connectionDetails["details"];
bool isTerminated = false;
try
{
Guid OldConnectionId = new Guid((string)connectionDetails["connection_id"]);
RemoteSession = ((IDictionary<Guid, RemoteSession>)Application[HttpApplicationStateVariables.RemoteSessions.ToString()])[OldConnectionId];
RemoteSession.Manager.SendCommand(RemoteSessionCommand.CloseClient);
isTerminated = true;
}
catch (ThreadAbortException)
{
// occurs because the response is ended after redirect
}
catch (Exception exc)
{
System.Diagnostics.Trace.TraceError("Failed to terminate the session ({0})", exc);
}
if (isTerminated)
{
Response.Write("<script>alert('Session terminated.'); window.close();</script>");
}
else
{
Response.Write("<script>alert('Invalid session.'); window.close();</script>");
}
return false;
}
accessUrl = (string)connectionDetails["ACCESS_URL"];
connectionDetails = (JObject)connectionDetails["details"];
loginServer = (string)connectionDetails["address"];
loginDomain = "";
Expand All @@ -673,8 +664,6 @@ private bool ConnectRemoteServer()
// sharing parameters
int maxActiveGuests = int.MaxValue;

var connectionId = Guid.NewGuid();

// connect an host from the hosts list or from a one time session url
if (_enterpriseSession != null && (!string.IsNullOrEmpty(Request["SD"])))
{
Expand Down Expand Up @@ -809,6 +798,7 @@ private bool ConnectRemoteServer()

RemoteSession.UserProfileId = userProfileId;
RemoteSession.UserSessionId = userSessionId;
RemoteSession.accessUrl = accessUrl;

// bind the remote session to the current http session
Session[HttpSessionStateVariables.RemoteSession.ToString()] = RemoteSession;
Expand Down
1 change: 1 addition & 0 deletions Myrtille.Web/Myrtille.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
<Compile Include="src\Clients\RemoteSessionProcessClient.cs" />
<Compile Include="src\RemoteSessionAudioSocketHandler.cs" />
<Compile Include="src\RemoteSessionSocketHandler.cs" />
<Compile Include="src\Utils\WebRequest.cs" />
<Compile Include="src\WebInstaller.cs">
<SubType>Component</SubType>
</Compile>
Expand Down
36 changes: 22 additions & 14 deletions Myrtille.Web/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@

<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, Log4net"/>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Myrtille.Web.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Myrtille.Web.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</sectionGroup>
</configSections>

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.5.1.25624" newVersion="1.5.2.14234" />
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.5.1.25624" newVersion="1.5.2.14234"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down Expand Up @@ -98,7 +100,7 @@
<system.webServer>
<defaultDocument>
<files>
<clear />
<clear/>
<add value="Default.aspx"/>
</files>
</defaultDocument>
Expand All @@ -122,25 +124,31 @@
<system.serviceModel>

<client>
<endpoint address="http://localhost:8080/Myrtille/RemoteSessionProcess" binding="wsDualHttpBinding" bindingConfiguration="wsDualHttpBindingCallback" contract="Myrtille.Services.Contracts.IRemoteSessionProcess"/>
<endpoint address="http://localhost:8080/Myrtille/FileStorage" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingFileStream" contract="Myrtille.Services.Contracts.IFileStorage"/>
<endpoint address="http://localhost:8080/Myrtille/PrinterService" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingFileStream" contract="Myrtille.Services.Contracts.IPrinterService"/>
<endpoint address="http://localhost:8080/Myrtille/RemoteSessionProcess" binding="wsDualHttpBinding" bindingConfiguration="wsDualHttpBindingCallback"
contract="Myrtille.Services.Contracts.IRemoteSessionProcess"/>
<endpoint address="http://localhost:8080/Myrtille/FileStorage" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingFileStream"
contract="Myrtille.Services.Contracts.IFileStorage"/>
<endpoint address="http://localhost:8080/Myrtille/PrinterService" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingFileStream"
contract="Myrtille.Services.Contracts.IPrinterService"/>
<endpoint address="http://localhost:8080/Myrtille/MFAAuthentication" binding="basicHttpBinding" contract="Myrtille.Services.Contracts.IMFAAuthentication"/>
<endpoint address="http://localhost:8080/Myrtille/EnterpriseService" binding="basicHttpBinding" contract="Myrtille.Services.Contracts.IEnterpriseService"/>
<endpoint address="http://localhost:8080/Myrtille/ApplicationPoolService" binding="basicHttpBinding" contract="Myrtille.Services.Contracts.IApplicationPoolService"/>
<endpoint address="http://localhost:8080/Myrtille/ApplicationPoolService" binding="basicHttpBinding"
contract="Myrtille.Services.Contracts.IApplicationPoolService"/>
</client>

<bindings>
<wsDualHttpBinding>
<binding name="wsDualHttpBindingCallback" receiveTimeout="infinite" maxReceivedMessageSize="2147483647">
<security mode="None"/>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"/>
<reliableSession inactivityTimeout="infinite"/>
</binding>
</wsDualHttpBinding>
<basicHttpBinding>
<!-- buffer size: 64KB; max file size: 1GB -->
<binding name="basicHttpBindingFileStream" transferMode="Streamed" messageEncoding="Mtom" maxBufferSize="65536" maxReceivedMessageSize="1073741824" closeTimeout="infinite" openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite">
<binding name="basicHttpBindingFileStream" transferMode="Streamed" messageEncoding="Mtom" maxBufferSize="65536" maxReceivedMessageSize="1073741824"
closeTimeout="infinite" openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite">
<security mode="None"/>
</binding>
</basicHttpBinding>
Expand All @@ -167,7 +175,7 @@
<!-- disable Visual Studio SignalR -->
<add key="vs:EnableBrowserLink" value="false"/>
<!-- disable Visual Studio Page Inspector -->
<add key="PageInspector:ServerCodeMappingSupport" value="Disabled" />
<add key="PageInspector:ServerCodeMappingSupport" value="Disabled"/>
<!-- providing access to the remote clipboard could be a security issue, it can be disabled below -->
<add key="AllowRemoteClipboard" value="true"/>
<!-- allow file transfer (requires a domain to be specified on connect) -->
Expand Down
8 changes: 8 additions & 0 deletions Myrtille.Web/src/Clients/RemoteSessionProcessClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,19 @@ limitations under the License.
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Web;
using Myrtille.Helpers;
using Myrtille.Services.Contracts;
using Myrtille.Web.Properties;
using Myrtille.Web.src.Utils;
using Newtonsoft.Json.Linq;

namespace Myrtille.Web
{
Expand Down Expand Up @@ -236,6 +243,7 @@ private void CleanupDisconnectedSession(RemoteSessionExitCode exitCode)
var remoteSessions = (IDictionary<Guid, RemoteSession>)_application[HttpApplicationStateVariables.RemoteSessions.ToString()];
if (remoteSessions.ContainsKey(_remoteSessionManager.RemoteSession.Id))
{
SecurdenWeb.ManageSessionRequest(_remoteSessionManager.RemoteSession.accessUrl, _remoteSessionManager.RemoteSession.Id.ToString(), false);
remoteSessions.Remove(_remoteSessionManager.RemoteSession.Id);
}

Expand Down
1 change: 1 addition & 0 deletions Myrtille.Web/src/RemoteSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class RemoteSession

public long UserProfileId;
public long UserSessionId;
public string accessUrl;

public Guid Id;
public RemoteSessionState State;
Expand Down
2 changes: 2 additions & 0 deletions Myrtille.Web/src/RemoteSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ limitations under the License.
using System.Web.SessionState;
using Myrtille.Helpers;
using Myrtille.Services.Contracts;
using Myrtille.Web.src.Utils;

namespace Myrtille.Web
{
Expand Down Expand Up @@ -161,6 +162,7 @@ public void ProcessUpdatesPipeData(byte[] data)
if (RemoteSession.State == RemoteSessionState.Connecting)
{
RemoteSession.State = RemoteSessionState.Connected;
SecurdenWeb.ManageSessionRequest(RemoteSession.accessUrl, RemoteSession.Id.ToString(), true);
SendMessage(new RemoteSessionMessage { Type = MessageType.Connected, Prefix = "connected" });

// in case the remote session was reconnected, send the capture API config
Expand Down
Loading

0 comments on commit 78d6b2b

Please sign in to comment.