public RemoteSessionSocketHandler(HttpContext context, bool binary, string clientId, WebSocketDirection direction) : base() { _session = context.Session; Binary = binary; Direction = direction; try { if (context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; if (!_remoteSession.Manager.Clients.ContainsKey(clientId)) { lock (_remoteSession.Manager.ClientsLock) { _remoteSession.Manager.Clients.Add(clientId, new RemoteSessionClient(clientId)); } } _client = _remoteSession.Manager.Clients[clientId]; } catch (Exception exc) { Trace.TraceError("Failed to initialize socket handler ({0})", exc); } }
public RemoteSessionManager(RemoteSession remoteSession) { try { RemoteSession = remoteSession; // remote session process client and callback var callback = new RemoteSessionProcessClientCallback(this); var callbackContext = new InstanceContext(callback); Client = new RemoteSessionProcessClient(this, callbackContext); // pipes Pipes = new RemoteSessionPipes(RemoteSession); Pipes.ProcessUpdatesPipeMessage = ProcessUpdatesPipeMessage; // sockets WebSockets = new List <RemoteSessionSocketHandler>(); // messages _messageEventLock = new object(); // images _imageEventLock = new object(); // cache _imageCache = (Cache)HttpContext.Current.Application[HttpApplicationStateVariables.Cache.ToString()]; } catch (Exception exc) { Trace.TraceError("Failed to initialize remote session manager, remote session {0} ({1})", RemoteSession.Id, exc); } }
public RemoteSessionSocketHandler(HttpSessionState session, bool binaryMode) : base() { _session = session; BinaryMode = binaryMode; try { if (session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)session[HttpSessionStateVariables.RemoteSession.ToString()]; bool websocketBuffering; if (!bool.TryParse(ConfigurationManager.AppSettings["WebsocketBuffering"], out websocketBuffering)) { websocketBuffering = true; } // RDP: display updates are buffered to fit the client latency; buffer data is also invalidated past the image cache duration (default 1 sec) to avoid lag // SSH: terminal messages are unbuffered if (websocketBuffering && _remoteSession.HostType == HostTypeEnum.RDP) { Buffer = new DataBuffer <int>(_bufferSize, _bufferDelay); Buffer.SendBufferData = SendBufferData; } } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", session.SessionID, exc); } }
public RemoteSessionEventSourceHandler(HttpContext context, string clientId) { _context = context; try { if (context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; if (!_remoteSession.Manager.Clients.ContainsKey(clientId)) { lock (_remoteSession.Manager.ClientsLock) { _remoteSession.Manager.Clients.Add(clientId, new RemoteSessionClient(clientId)); } } _client = _remoteSession.Manager.Clients[clientId]; } catch (Exception exc) { Trace.TraceError("Failed to initialize event source handler ({0})", exc); } }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // retrieve the active enterprise session, if any if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] != null) { try { _remoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; if (_remoteSession.DisableSessionSharing(HttpContext.Current.Session.SessionID)) { Response.Redirect("~/", true); } _remoteSession.SessionKey = Guid.NewGuid().ToString(); HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] = _remoteSession; sessionUrl.Value = Request.Url.Scheme + "://" + Request.Url.Host + (Request.Url.Port != 80 && Request.Url.Port != 443 ? ":" + Request.Url.Port : "") + Request.ApplicationPath + "/?SSE=" + RDPCryptoHelper.GetSessionKey(_remoteSession.Id, HttpContext.Current.Session.SessionID, _remoteSession.SessionKey); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); } } else { Response.Redirect("~/", true); } }
/// <summary> /// retrieve a shared remote session /// </summary> /// <param name="guestGuid">guest guid</param> /// <returns></returns> private RemoteSession GetSharedRemoteSession( string guestGuid) { RemoteSession remoteSession = null; try { Application.Lock(); var sharedSessions = (IDictionary <string, RemoteSession>)Application[HttpApplicationStateVariables.SharedRemoteSessions.ToString()]; if (sharedSessions.ContainsKey(guestGuid)) { remoteSession = sharedSessions[guestGuid]; sharedSessions.Remove(guestGuid); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the shared remote session ({0})", exc); } finally { Application.UnLock(); } return(remoteSession); }
/// <summary> /// initialization /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Init( object sender, EventArgs e) { try { // retrieve the active remote session, if any if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] != null) { try { if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } _remoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session ({0})", exc); } } // ensure there is an active remote session // if a domain is specified, the roaming user profile is loaded from the Active Directory // file storage is synchronized with the user "My documents" folder (will use folder redirection if defined) // user credentials will be checked prior to any file operation // if possible, use SSL to communicate with the service if (_remoteSession != null && (_remoteSession.State == RemoteSessionState.Connecting || _remoteSession.State == RemoteSessionState.Connected) && (_remoteSession.ServerAddress.ToLower() == "localhost" || _remoteSession.ServerAddress == "127.0.0.1" || _remoteSession.ServerAddress == HttpContext.Current.Request.Url.Host || !string.IsNullOrEmpty(_remoteSession.UserDomain)) && !string.IsNullOrEmpty(_remoteSession.UserName) && !string.IsNullOrEmpty(_remoteSession.UserPassword)) { _fileStorageClient = new FileStorageClient(); var files = _fileStorageClient.GetUserDocumentsFolderFiles( _remoteSession.Id, _remoteSession.UserDomain, _remoteSession.UserName, _remoteSession.UserPassword); if (files.Count > 0) { fileToDownloadSelect.DataSource = files; fileToDownloadSelect.DataBind(); downloadFileButton.Disabled = false; } } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to init file storage ({0})", exc); } }
public RemoteSessionAudioSocketHandler(HttpContext context, bool binary) : base() { _context = context; Binary = binary; try { if (context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", context.Session.SessionID, exc); return; } var clientId = context.Session.SessionID; if (context.Request.Cookies[HttpRequestCookies.ClientKey.ToString()] != null) { clientId = context.Request.Cookies[HttpRequestCookies.ClientKey.ToString()].Value; } if (!_remoteSession.Manager.Clients.ContainsKey(clientId)) { lock (_remoteSession.Manager.ClientsLock) { _remoteSession.Manager.Clients.Add(clientId, new RemoteSessionClient(clientId)); } } _client = _remoteSession.Manager.Clients[clientId]; bool audioBuffering; if (!bool.TryParse(ConfigurationManager.AppSettings["AudioBuffering"], out audioBuffering)) { audioBuffering = true; } // RDP: audio blocks are buffered for a seamless playback; buffer data is also invalidated past the audio cache duration (default 1,5 sec) in case of lag // SSH: no audio if (audioBuffering && _remoteSession.HostType == HostType.RDP) { Buffer = new DataBuffer <int>(_bufferCount, _bufferDelay); Buffer.SendBufferData = SendBufferData; } }
public RemoteSessionManager(RemoteSession remoteSession) { try { RemoteSession = remoteSession; // remote session process client and callback var callback = new RemoteSessionProcessClientCallback(this); var callbackContext = new InstanceContext(callback); HostClient = new RemoteSessionProcessClient(this, callbackContext); // pipes Pipes = new RemoteSessionPipes(RemoteSession); Pipes.ProcessUpdatesPipeMessage = ProcessUpdatesPipeMessage; // audio (RDP only) if (RemoteSession.HostType == HostType.RDP) { Pipes.ProcessAudioPipeMessage = ProcessAudioPipeMessage; } // sockets WebSockets = new List <RemoteSessionSocketHandler>(); AudioWebSockets = new List <RemoteSessionAudioSocketHandler>(); // messages MessageQueues = new Hashtable(); // images event _imageEventLock = new object(); // cache _cache = (Cache)HttpContext.Current.Application[HttpApplicationStateVariables.Cache.ToString()]; // owner idle timeout if (!int.TryParse(ConfigurationManager.AppSettings["ClientIdleTimeout"], out _clientIdleTimeoutDelay)) { _clientIdleTimeoutDelay = 0; } if (_clientIdleTimeoutDelay > 0) { ClientIdleTimeout = new CancellationTokenSource(); } // guests idle timeout _guestsIdleTimeout = new Dictionary <string, CancellationTokenSource>(); _guestsIdleTimeoutLock = new object(); } catch (Exception exc) { Trace.TraceError("Failed to initialize remote session manager, remote session {0} ({1})", RemoteSession.Id, exc); } }
public RemoteSessionManager(RemoteSession remoteSession) { try { RemoteSession = remoteSession; // remote session process client and callback var callback = new RemoteSessionProcessClientCallback(this); var callbackContext = new InstanceContext(callback); HostClient = new RemoteSessionProcessClient(this, callbackContext); // pipes Pipes = new RemoteSessionPipes(RemoteSession); Pipes.ProcessUpdatesPipeMessage = ProcessUpdatesPipeMessage; // sockets WebSockets = new List <RemoteSessionSocketHandler>(); // messages MessageQueues = new Hashtable(); // images event _imageEventLock = new object(); // images cache _imageCache = (Cache)HttpContext.Current.Application[HttpApplicationStateVariables.Cache.ToString()]; // browser resize if (!bool.TryParse(ConfigurationManager.AppSettings["ScaleOnResize"], out _scaleOnResize)) { _scaleOnResize = true; } if (!_scaleOnResize) { _reconnectTimeout = new CancellationTokenSource(); } // browser timeout if (!int.TryParse(ConfigurationManager.AppSettings["ClientIdleTimeout"], out _clientIdleTimeoutDelay)) { _clientIdleTimeoutDelay = 0; } if (_clientIdleTimeoutDelay > 0) { ClientIdleTimeout = new CancellationTokenSource(); } } catch (Exception exc) { Trace.TraceError("Failed to initialize remote session manager, remote session {0} ({1})", RemoteSession.Id, exc); } }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { try { if (Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } _remoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()]; // retrieve the pdf file if (!string.IsNullOrEmpty(Request["name"])) { try { var fileStream = _printerServiceClient.GetPdfFile(_remoteSession.Id, Request["name"]); // CAUTION! IE/Edge appears to have issues with inline documents // for instance, it loads twice "application/pdf" documents (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6734131/), // which is a problem because the document is deleted on retrieval to enforce security (the second request will thus fail) // the idea behind inline content was to open the pdf in a new tab; it works on every browser but IE/Edge :/ // using attachment instead //FileHelper.DownloadFile(Response, fileStream, Request["name"], true, "application/pdf", "inline"); FileHelper.DownloadFile(Response, fileStream, Request["name"], true, "application/pdf"); } catch (ThreadAbortException) { // occurs because the response is ended after sending the pdf } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to download pdf file ({0})", exc); } finally { // remove the pdf file _printerServiceClient.DeletePdfFile(_remoteSession.Id, Request["name"]); } } } catch (ThreadAbortException) { // occurs because the response is ended after deleting the pdf } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } }
/// <summary> /// retrieve an image update (region or fullscreen) from the rdp session and send it to the browser /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url // in both cases, the given http session is automatically bound to the current http context RemoteSession remoteSession = null; try { if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the current http session remoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); return; } try { // retrieve params var imgIdx = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]); // retrieve image data var img = remoteSession.Manager.GetCachedUpdate(imgIdx); // if the image isn't available (removed from cache?), request a fullscreen update (resync display) if (img == null) { remoteSession.Manager.SendCommand(RemoteSessionCommand.RequestFullscreenUpdate); } var imgData = img != null ? img.Data : null; if (imgData != null && imgData.Length > 0) { // write the output HttpContext.Current.Response.OutputStream.Write(imgData, 0, imgData.Length); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to get display update, remote session {0} ({1})", remoteSession.Id, exc); } }
public RemoteSessionEventSourceHandler(HttpContext context) { _context = context; Session = context.Session; try { if (_context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)_context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; // register the handler against the remote session manager lock (((ICollection)_remoteSession.Manager.EventSources).SyncRoot) { // search for a previously registered handler RemoteSessionEventSourceHandler oldEventSource = null; foreach (var eventSource in _remoteSession.Manager.EventSources) { if (eventSource.Session.SessionID == _context.Session.SessionID) { oldEventSource = eventSource; break; } } // unregister the previous handler, if any if (oldEventSource != null) { _remoteSession.Manager.EventSources.Remove(oldEventSource); } // register this handler _remoteSession.Manager.EventSources.Add(this); } // mime type for event source _context.Response.ContentType = "text/event-stream"; _context.Response.Headers.Add("Content-Type", "text/event-stream\n\n"); } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", _context.Session.SessionID, exc); } }
public RemoteSessionLongPollingHandler(HttpContext context) { _context = context; Session = context.Session; try { if (_context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)_context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; // register the handler against the remote session manager lock (((ICollection)_remoteSession.Manager.LongPollings).SyncRoot) { // search for a previously registered handler RemoteSessionLongPollingHandler oldLongPolling = null; foreach (var longPolling in _remoteSession.Manager.LongPollings) { if (longPolling.Session.SessionID == _context.Session.SessionID) { oldLongPolling = longPolling; break; } } // unregister the previous handler, if any if (oldLongPolling != null) { _remoteSession.Manager.LongPollings.Remove(oldLongPolling); } // register this handler _remoteSession.Manager.LongPollings.Add(this); } // the handler is ready to push data Send("<script>parent.lpInitConnection();</script>"); } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", _context.Session.SessionID, exc); } }
public RemoteSessionManager(RemoteSession remoteSession) { try { RemoteSession = remoteSession; // remote session process client and callback var callback = new RemoteSessionProcessClientCallback(this, HttpContext.Current.Application); var callbackContext = new InstanceContext(callback); HostClient = new RemoteSessionProcessClient(this, callbackContext); // clients Clients = new Dictionary <string, RemoteSessionClient>(); ClientsLock = new object(); // pipes Pipes = new RemoteSessionPipes(RemoteSession); // images event _imageEventLock = new object(); // cache _cache = (Cache)HttpContext.Current.Application[HttpApplicationStateVariables.Cache.ToString()]; // owner idle timeout if (!int.TryParse(ConfigurationManager.AppSettings["OwnerIdleTimeout"], out _ownerIdleTimeoutDelay)) { _ownerIdleTimeoutDelay = 0; } if (_ownerIdleTimeoutDelay > 0) { OwnerIdleTimeout = new CancellationTokenSource(); } // guests idle timeout _guestsIdleTimeout = new Dictionary <string, CancellationTokenSource>(); _guestsIdleTimeoutLock = new object(); // clients idle timeout _clientsIdleTimeout = new Dictionary <string, CancellationTokenSource>(); _clientsIdleTimeoutLock = new object(); } catch (Exception exc) { Trace.TraceError("Failed to initialize remote session manager, remote session {0} ({1})", RemoteSession?.Id, exc); } }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { try { if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } _remoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; try { Application.Lock(); // if remote session sharing is enabled, only the remote session owner can share it if (!_remoteSession.AllowSessionSharing || !HttpContext.Current.Session.SessionID.Equals(_remoteSession.OwnerSessionID)) { Response.Redirect("~/", true); } // create a new guest for the remote session var sharedSessions = (IDictionary <string, RemoteSession>)Application[HttpApplicationStateVariables.SharedRemoteSessions.ToString()]; var guestGuid = Guid.NewGuid().ToString(); sharedSessions.Add(guestGuid, _remoteSession); sessionUrl.Value = Request.Url.Scheme + "://" + Request.Url.Host + (Request.Url.Port != 80 && Request.Url.Port != 443 ? ":" + Request.Url.Port : "") + Request.ApplicationPath + "/?SSE=" + guestGuid; } 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(); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } }
/// <summary> /// disconnect the remote server /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void DisconnectButtonClick( object sender, EventArgs e) { if (!_authorizedRequest) { return; } // disconnect the active remote session, if any and connecting/connected if (RemoteSession != null && (RemoteSession.State == RemoteSessionState.Connecting || RemoteSession.State == RemoteSessionState.Connected)) { try { // prevent the remote session from being disconnected by a guest if (Session.SessionID.Equals(RemoteSession.OwnerSessionID)) { RemoteSession.State = RemoteSessionState.Disconnecting; RemoteSession.Manager.SendCommand(RemoteSessionCommand.CloseClient); } else { Session[HttpSessionStateVariables.RemoteSession.ToString()] = null; RemoteSession = null; } // logout the enterprise session if single use only if (_enterpriseSession != null && _enterpriseSession.SingleUseConnection) { LogoutButtonClick(this, EventArgs.Empty); } // enterprise mode: redirect to the hosts list // standard mode: redirect to the login screen Response.Redirect("~/", true); } catch (ThreadAbortException) { // occurs because the response is ended after redirect } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to disconnect the remote session {0} ({1})", RemoteSession.Id, exc); } } }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { try { if (Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } _remoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()]; // retrieve the pdf file if (!string.IsNullOrEmpty(Request["name"])) { try { var fileStream = _printerClient.GetPdfFile(_remoteSession.Id, Request["name"]); FileHelper.DownloadFile(Response, fileStream, Request["name"], true, "application/pdf", Request["disposition"]); } catch (ThreadAbortException) { // occurs because the response is ended after sending the pdf } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to download pdf file ({0})", exc); } finally { // remove the pdf file _printerClient.DeletePdfFile(_remoteSession.Id, Request["name"]); } } } catch (ThreadAbortException) { // occurs because the response is ended after deleting the pdf } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } }
/// <summary> /// retrieve an image update (region or fullscreen) from the remote session and send it to the browser /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url // in both cases, the given http session is automatically bound to the current http context RemoteSession remoteSession = null; try { if (Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the current http session remoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()]; try { // retrieve params var imgIdx = int.Parse(Request.QueryString["imgIdx"]); // retrieve image data var img = remoteSession.Manager.GetCachedUpdate(imgIdx); var imgData = img != null ? img.Data : null; if (imgData != null && imgData.Length > 0) { // write the output Response.OutputStream.Write(imgData, 0, imgData.Length); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve display update, remote session {0} ({1})", remoteSession.Id, exc); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } }
/// <summary> /// retrieve the mouse cursor from the rdp session and send it to the browser /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // if cookies are enabled, the http session id is added to the http request headers; otherwise, it's added to the http request url // in both cases, the given http session is automatically bound to the current http context RemoteSession remoteSession = null; try { if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the current http session remoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); return; } try { // retrieve params var imgIdx = int.Parse(HttpContext.Current.Request.QueryString["imgIdx"]); // retrieve image data var img = remoteSession.Manager.GetCachedUpdate(imgIdx); var imgData = img != null ? img.Data : null; if (imgData != null && imgData.Length > 0) { CreateCursorFromImage(img.Width, img.Height, img.PosX, img.PosY, imgData, Response.OutputStream); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to get mouse cursor, remote session {0} ({1})", remoteSession.Id, exc); } }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // prevent session fixation or stealing SessionFixationHandler(); // retrieve the active enterprise session, if any if (HttpContext.Current.Session[HttpSessionStateVariables.EnterpriseSession.ToString()] != null) { try { _enterpriseSession = (EnterpriseSession)HttpContext.Current.Session[HttpSessionStateVariables.EnterpriseSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the enterprise session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); } } // retrieve the active remote session, if any if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] != null) { try { RemoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); } } // postback events may redirect after execution; UI is updated from there if (!IsPostBack) { UpdateControls(); } // disable the browser cache; in addition to a "noCache" dummy param, with current time, on long-polling and xhr requests Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); }
public RemoteSessionSocketHandler(HttpSessionState session, bool binaryMode) : base() { BinaryMode = binaryMode; try { if (session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", session.SessionID, exc); } }
public RemoteSessionAudioSocketHandler(HttpSessionState session, bool binaryMode) : base() { _session = session; BinaryMode = binaryMode; try { if (session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } if (!BinaryMode) { throw new Exception("Audio requires a binary websocket (HTML5 standard)"); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)session[HttpSessionStateVariables.RemoteSession.ToString()]; bool audioBuffering; if (!bool.TryParse(ConfigurationManager.AppSettings["AudioBuffering"], out audioBuffering)) { audioBuffering = true; } // RDP: audio blocks are buffered for a seamless playback; buffer data is also invalidated past the audio cache duration (default 1,5 sec) in case of lag // SSH: no audio if (audioBuffering && _remoteSession.HostType == HostType.RDP) { Buffer = new DataBuffer <int>(_bufferCount, _bufferDelay); Buffer.SendBufferData = SendBufferData; } } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", session.SessionID, exc); } }
public RemoteSessionSocketHandler(HttpContext context, bool binary, WebSocketDirection direction) : base() { _session = context.Session; Binary = binary; Direction = direction; try { if (context.Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } // retrieve the remote session for the given http session _remoteSession = (RemoteSession)context.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", context.Session.SessionID, exc); return; } var clientId = context.Session.SessionID; if (context.Request.Cookies[HttpRequestCookies.ClientKey.ToString()] != null) { clientId = context.Request.Cookies[HttpRequestCookies.ClientKey.ToString()].Value; } if (!_remoteSession.Manager.Clients.ContainsKey(clientId)) { lock (_remoteSession.Manager.ClientsLock) { _remoteSession.Manager.Clients.Add(clientId, new RemoteSessionClient(clientId)); } } _client = _remoteSession.Manager.Clients[clientId]; }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { try { if (Session[HttpSessionStateVariables.RemoteSession.ToString()] == null) { throw new NullReferenceException(); } _remoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()]; // if remote session sharing is enabled, only the remote session owner can share it if (!_remoteSession.AllowSessionSharing || !Session.SessionID.Equals(_remoteSession.OwnerSessionID)) { Response.Redirect("~/", true); } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } }
/// <summary> /// initialization /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { #region session fixation attack // prevent session fixation attack by generating a new session ID upon login // https://www.owasp.org/index.php/Session_Fixation if (!string.IsNullOrEmpty(HttpContext.Current.Request["oldSID"])) { try { HttpContext.Current.Application.Lock(); // retrieve the given (old) http session var httpSessions = (IDictionary <string, HttpSessionState>)HttpContext.Current.Application[HttpApplicationStateVariables.HttpSessions.ToString()]; var httpSession = httpSessions[HttpContext.Current.Request["oldSID"]]; // retrieve the remote session bound to it var remoteSession = httpSession[HttpSessionStateVariables.RemoteSession.ToString()]; // unbind it from the old http session httpSession[HttpSessionStateVariables.RemoteSession.ToString()] = null; // bind it to the new http session HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] = remoteSession; // cancel the old http session httpSession.Abandon(); // unregister it at application level httpSessions.Remove(httpSession.SessionID); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to generate a new http session upon login ({0})", exc); } finally { HttpContext.Current.Application.UnLock(); } } #endregion try { // retrieve the active remote session, if any if (HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] != null) { try { RemoteSession = (RemoteSession)HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the remote session for the http session {0}, ({1})", HttpContext.Current.Session.SessionID, exc); } } // update controls UpdateControls(); // disable the browser cache; in addition to a "noCache" dummy param, with current time, on long-polling and xhr requests Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to load myrtille ({0})", exc); } }
/// <summary> /// start the rdp session /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ConnectButtonClick( object sender, EventArgs e) { // remove the active remote session, if any (disconnected?) if (RemoteSession != null) { try { // unset the remote session for the current http session HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] = null; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to remove remote session ({0})", exc); } finally { RemoteSession = null; } } // create a new remote session try { HttpContext.Current.Application.Lock(); // auto-increment the remote sessions counter // note that it doesn't really count the active remote sessions... it's just an auto-increment for the remote session id, ensuring it's unique... var remoteSessionsCounter = (int)HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsCounter.ToString()]; remoteSessionsCounter++; // create the remote session RemoteSession = new RemoteSession { Id = remoteSessionsCounter, State = RemoteSessionState.NotConnected, ServerAddress = string.IsNullOrEmpty(server.Value) ? "localhost" : server.Value, UserDomain = domain.Value, UserName = user.Value, UserPassword = string.IsNullOrEmpty(passwordHash.Value) ? password.Value : RDPCryptoHelper.DecryptPassword(passwordHash.Value), ClientWidth = int.Parse(width.Value), ClientHeight = int.Parse(height.Value), Program = program.Value }; // set the remote session for the current http session HttpContext.Current.Session[HttpSessionStateVariables.RemoteSession.ToString()] = RemoteSession; // register the http session at application level var httpSessions = (IDictionary <string, HttpSessionState>)HttpContext.Current.Application[HttpApplicationStateVariables.HttpSessions.ToString()]; httpSessions[HttpContext.Current.Session.SessionID] = HttpContext.Current.Session; // update the remote sessions auto-increment counter HttpContext.Current.Application[HttpApplicationStateVariables.RemoteSessionsCounter.ToString()] = remoteSessionsCounter; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to create remote session ({0})", exc); RemoteSession = null; } finally { HttpContext.Current.Application.UnLock(); } // connect it if (RemoteSession != null) { try { // update the remote session state RemoteSession.State = RemoteSessionState.Connecting; // create pipes for the web gateway and the rdp client to talk RemoteSession.Manager.Pipes.CreatePipes(); // the rdp client does connect the pipes when it starts; when it stops (either because it was closed, crashed or because the rdp session had ended), pipes are released // as the process command line can be displayed into the task manager / process explorer, the connection settings (including user credentials) are now passed to the rdp client through the inputs pipe // use http://technet.microsoft.com/en-us/sysinternals/dd581625 to track the existing pipes RemoteSession.Manager.Client.StartProcess( RemoteSession.Id, RemoteSession.ClientWidth, RemoteSession.ClientHeight); // update controls UpdateControls(); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to connect the remote session {0} ({1})", RemoteSession.Id, exc); } } }
/// <summary> /// connect the remote server /// </summary> /// <remarks> /// authentication is delegated to the remote server or connection broker (if applicable) /// </remarks> private bool ConnectRemoteServer() { // connection parameters string loginHostName = null; var loginHostType = (HostType)Convert.ToInt32(hostType.Value); var loginProtocol = (SecurityProtocol)securityProtocol.SelectedIndex; var loginServer = string.IsNullOrEmpty(server.Value) ? "localhost" : server.Value; var loginVMGuid = vmGuid.Value; var loginVMAddress = string.Empty; var loginVMEnhancedMode = vmEnhancedMode.Checked; var loginDomain = domain.Value; var loginUser = user.Value; var loginPassword = string.IsNullOrEmpty(passwordHash.Value) ? password.Value : CryptoHelper.RDP_Decrypt(passwordHash.Value); var startProgram = program.Value; // allowed features var allowRemoteClipboard = _allowRemoteClipboard; var allowFileTransfer = _allowFileTransfer; var allowPrintDownload = _allowPrintDownload; var allowSessionSharing = _allowSessionSharing; var allowAudioPlayback = _allowAudioPlayback; // 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"]))) { long hostId; if (!long.TryParse(Request["SD"], out hostId)) { hostId = 0; } try { // retrieve the host connection details var connection = _enterpriseClient.GetSessionConnectionDetails(_enterpriseSession.SessionID, hostId, _enterpriseSession.SessionKey); if (connection == null) { System.Diagnostics.Trace.TraceInformation("Unable to retrieve host {0} connection details (invalid host or one time session url already used?)", hostId); return(false); } loginHostName = connection.HostName; loginHostType = connection.HostType; loginProtocol = connection.Protocol; loginServer = !string.IsNullOrEmpty(connection.HostAddress) ? connection.HostAddress : connection.HostName; loginVMGuid = connection.VMGuid; loginVMEnhancedMode = connection.VMEnhancedMode; loginDomain = connection.Domain; loginUser = connection.Username; loginPassword = CryptoHelper.RDP_Decrypt(connection.Password); startProgram = connection.StartRemoteProgram; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve host {0} connection details ({1})", hostId, exc); return(false); } } // by using a connection service on a backend (connection API), the connection details can be hidden from querystring and mapped to a connection identifier else if (!string.IsNullOrEmpty(Request["cid"])) { if (!Guid.TryParse(Request["cid"], out connectionId)) { System.Diagnostics.Trace.TraceInformation("Invalid connection id {0}", Request["cid"]); return(false); } try { // retrieve the connection details var connection = _connectionClient.GetConnectionInfo(connectionId); if (connection == null) { System.Diagnostics.Trace.TraceInformation("Unable to retrieve connection info {0}", connectionId); return(false); } // ensure the user is allowed to connect the host if (!_connectionClient.IsUserAllowedToConnectHost(connection.User.Domain, connection.User.UserName, connection.Host.IPAddress, connection.VM != null ? connection.VM.Guid : Guid.Empty)) { System.Diagnostics.Trace.TraceInformation("User: domain={0}, name={1} is not allowed to connect host {2}", connection.User.Domain, connection.User.UserName, connection.Host.IPAddress); return(false); } loginHostType = connection.Host.HostType; loginProtocol = connection.Host.SecurityProtocol; loginServer = connection.Host.IPAddress; loginVMGuid = connection.VM != null?connection.VM.Guid.ToString() : string.Empty; loginVMAddress = connection.VM != null ? connection.VM.IPAddress : string.Empty; loginVMEnhancedMode = connection.VM != null ? connection.VM.EnhancedMode : false; loginDomain = connection.User.Domain; loginUser = connection.User.UserName; loginPassword = connection.User.Password; startProgram = connection.StartProgram; allowRemoteClipboard = allowRemoteClipboard && connection.AllowRemoteClipboard; allowFileTransfer = allowFileTransfer && connection.AllowFileTransfer; allowPrintDownload = allowPrintDownload && connection.AllowPrintDownload; allowSessionSharing = allowSessionSharing && connection.MaxActiveGuests > 0; allowAudioPlayback = allowAudioPlayback && connection.AllowAudioPlayback; maxActiveGuests = connection.MaxActiveGuests; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve connection info {0} ({1})", connectionId, exc); return(false); } } // if the connection from login screen or url is disabled, the connection must be done either by using a connection API or from the enterprise mode else if (!_loginEnabled) { return(false); } // remove any active remote session (disconnected?) if (RemoteSession != null) { // unset the remote session for the current http session Session[HttpSessionStateVariables.RemoteSession.ToString()] = null; RemoteSession = null; } // create a new remote session try { Application.Lock(); // create the remote session RemoteSession = new RemoteSession( connectionId, loginHostName, loginHostType, loginProtocol, loginServer, loginVMGuid, loginVMAddress, loginVMEnhancedMode, !string.IsNullOrEmpty(loginDomain) ? loginDomain : AccountHelper.GetDomain(loginUser, loginPassword), AccountHelper.GetUserName(loginUser), loginPassword, int.Parse(width.Value), int.Parse(height.Value), startProgram, allowRemoteClipboard, allowFileTransfer, allowPrintDownload, allowSessionSharing, allowAudioPlayback, maxActiveGuests, Session.SessionID, (string)Session[HttpSessionStateVariables.ClientKey.ToString()], Request["cid"] != null ); // bind the remote session to the current http session Session[HttpSessionStateVariables.RemoteSession.ToString()] = RemoteSession; // register the remote session at the application level var remoteSessions = (IDictionary <Guid, RemoteSession>)Application[HttpApplicationStateVariables.RemoteSessions.ToString()]; remoteSessions.Add(RemoteSession.Id, RemoteSession); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to create remote session ({0})", exc); RemoteSession = null; } finally { Application.UnLock(); } // connect it if (RemoteSession != null) { RemoteSession.State = RemoteSessionState.Connecting; } else { connectError.InnerText = "Failed to create remote session!"; return(false); } return(true); }
/// <summary> /// page load (postback data is now available) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { // client ip protection if (_clientIPTracking) { var clientIP = ClientIPHelper.ClientIPFromRequest(new HttpContextWrapper(HttpContext.Current).Request, true, new string[] { }); if (Session[HttpSessionStateVariables.ClientIP.ToString()] == null) { Session[HttpSessionStateVariables.ClientIP.ToString()] = clientIP; } else if (!((string)Session[HttpSessionStateVariables.ClientIP.ToString()]).Equals(clientIP)) { System.Diagnostics.Trace.TraceWarning("Failed to validate the client ip"); _authorizedRequest = false; UpdateControls(); return; } } // session spoofing protection if (_cookielessSession) { if (Request.Cookies["clientKey"] == null) { if (Session[HttpSessionStateVariables.ClientKey.ToString()] == null) { var cookie = new HttpCookie("clientKey"); cookie.Value = Guid.NewGuid().ToString(); cookie.Path = "/"; Response.Cookies.Add(cookie); } else { System.Diagnostics.Trace.TraceWarning("Failed to validate the client key: missing key"); _authorizedRequest = false; UpdateControls(); return; } } else { var clientKey = Request.Cookies["clientKey"].Value; if (Session[HttpSessionStateVariables.ClientKey.ToString()] == null) { Session[HttpSessionStateVariables.ClientKey.ToString()] = clientKey; } else if (!((string)Session[HttpSessionStateVariables.ClientKey.ToString()]).Equals(clientKey)) { System.Diagnostics.Trace.TraceWarning("Failed to validate the client key: key mismatch"); _authorizedRequest = false; UpdateControls(); return; } } } // retrieve the active enterprise session, if any if (Session[HttpSessionStateVariables.EnterpriseSession.ToString()] != null) { try { _enterpriseSession = (EnterpriseSession)Session[HttpSessionStateVariables.EnterpriseSession.ToString()]; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active enterprise session ({0})", exc); } } // retrieve the active remote session, if any if (Session[HttpSessionStateVariables.RemoteSession.ToString()] != null) { try { RemoteSession = (RemoteSession)Session[HttpSessionStateVariables.RemoteSession.ToString()]; if (RemoteSession.State == RemoteSessionState.Disconnected) { // handle connection failure ClientScript.RegisterClientScriptBlock(GetType(), Guid.NewGuid().ToString(), string.Format("handleRemoteSessionExit({0});", RemoteSession.ExitCode), true); // cleanup Session[HttpSessionStateVariables.RemoteSession.ToString()] = null; RemoteSession = null; } } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve the active remote session ({0})", exc); } } // retrieve a shared remote session from url, if any else if (Request["SSE"] != null) { Session[HttpSessionStateVariables.RemoteSession.ToString()] = GetSharedRemoteSession(Request["SSE"]); try { // remove the shared session guid from url Response.Redirect("~/", true); } catch (ThreadAbortException) { // occurs because the response is ended after redirect } } // postback events may redirect after execution; UI is updated from there if (!IsPostBack) { UpdateControls(); } // disable the browser cache; in addition to a "noCache" dummy param, with current time, on long-polling and xhr requests Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); }
/// <summary> /// connect the remote server /// </summary> /// <remarks> /// authentication is delegated to the remote server or connection broker (if applicable) /// </remarks> private bool ConnectRemoteServer() { // connection parameters string loginHostName = null; var loginHostType = (HostTypeEnum)Convert.ToInt32(hostType.Value); var loginProtocol = (SecurityProtocolEnum)securityProtocol.SelectedIndex; var loginServer = string.IsNullOrEmpty(server.Value) ? "localhost" : server.Value; var loginVMGuid = vmGuid.Value; var loginVMEnhancedMode = vmEnhancedMode.Checked; var loginDomain = domain.Value; var loginUser = user.Value; var loginPassword = string.IsNullOrEmpty(passwordHash.Value) ? password.Value : RDPCryptoHelper.DecryptPassword(passwordHash.Value); var startProgram = program.Value; // connect an host from the hosts list or from a one time session url if (_enterpriseSession != null && Request["SD"] != null) { long hostId; if (!long.TryParse(Request["SD"], out hostId)) { hostId = 0; } try { // retrieve the host connection details var connection = _enterpriseClient.GetSessionConnectionDetails(_enterpriseSession.SessionID, hostId, _enterpriseSession.SessionKey); if (connection == null) { System.Diagnostics.Trace.TraceInformation("Unable to retrieve host {0} connection details (invalid host or one time session url already used?)", hostId); return(false); } loginHostName = connection.HostName; loginHostType = connection.HostType; loginProtocol = connection.Protocol; loginServer = !string.IsNullOrEmpty(connection.HostAddress) ? connection.HostAddress : connection.HostName; loginVMGuid = connection.VMGuid; loginVMEnhancedMode = connection.VMEnhancedMode; loginDomain = connection.Domain; loginUser = connection.Username; loginPassword = RDPCryptoHelper.DecryptPassword(connection.Password); startProgram = connection.StartRemoteProgram; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to retrieve host {0} connection details ({1})", hostId, exc); return(false); } } // remove any active remote session (disconnected?) if (RemoteSession != null) { // unset the remote session for the current http session Session[HttpSessionStateVariables.RemoteSession.ToString()] = null; RemoteSession = null; } // create a new remote session try { // create the remote session RemoteSession = new RemoteSession( Guid.NewGuid(), RemoteSessionState.NotConnected, loginHostName, loginHostType, loginProtocol, loginServer, loginVMGuid, loginVMEnhancedMode, loginDomain, loginUser, loginPassword, int.Parse(width.Value), int.Parse(height.Value), startProgram, _allowRemoteClipboard, _allowFileTransfer, _allowPrintDownload, _allowSessionSharing, Session.SessionID ); // bind the remote session to the current http session Session[HttpSessionStateVariables.RemoteSession.ToString()] = RemoteSession; } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to create remote session ({0})", exc); RemoteSession = null; } // connect it if (RemoteSession != null) { try { // update the remote session state RemoteSession.State = RemoteSessionState.Connecting; // create pipes for the web gateway and the host client to talk RemoteSession.Manager.Pipes.CreatePipes(); // the host client does connect the pipes when it starts; when it stops (either because it was closed, crashed or because the remote session had ended), pipes are released // as the process command line can be displayed into the task manager / process explorer, the connection settings (including user credentials) are now passed to the host client through the inputs pipe // use http://technet.microsoft.com/en-us/sysinternals/dd581625 to track the existing pipes RemoteSession.Manager.HostClient.StartProcess( RemoteSession.Id, RemoteSession.HostType, RemoteSession.SecurityProtocol, RemoteSession.ServerAddress, RemoteSession.VMGuid, RemoteSession.UserDomain, RemoteSession.UserName, RemoteSession.StartProgram, RemoteSession.ClientWidth, RemoteSession.ClientHeight, RemoteSession.AllowRemoteClipboard, RemoteSession.AllowPrintDownload); } catch (Exception exc) { System.Diagnostics.Trace.TraceError("Failed to connect the remote session {0} ({1})", RemoteSession.Id, exc); connectError.InnerText = "Failed to connect! ensure myrtille services are running"; return(false); } } else { connectError.InnerText = "Failed to create remote session!"; return(false); } return(true); }