Esempio n. 1
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="c">A ComputerAndItsGroups object to copy data from.</param>
            /// <param name="allowedGroupIds">If non-null, this collection of group IDs will be used to filter the computer's group list.  Pass in a collection of the user's group IDs.</param>
            public ResultComputer(Computer c)
            {
                ID             = c.ID;
                Name           = c.Name;
                LastDisconnect = c.LastDisconnect;
                HostConnectHandle handle = HostConnect.GetOnlineComputer(ID);

                if (handle != null)
                {
                    Uptime = (long)(DateTime.UtcNow - handle.ConnectTime).TotalMilliseconds;
                }
            }
Esempio n. 2
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="c">A ComputerAndItsGroups object to copy data from.</param>
            /// <param name="allowedGroupIds">If non-null, this collection of group IDs will be used to filter the computer's group list.  Pass in a collection of the user's group IDs.</param>
            public ResultComputerAndItsGroups(ComputerAndItsGroups c, IEnumerable <int> allowedGroupIds)
            {
                ID     = c.Computer.ID;
                Name   = c.Computer.Name;
                Groups = c.Groups
                         .Where(g => allowedGroupIds == null || allowedGroupIds.Contains(g.ID))
                         .Select(g => new ResultGroupSummary(g))
                         .ToArray();
                LastDisconnect = c.Computer.LastDisconnect;
                HostConnectHandle handle = HostConnect.GetOnlineComputer(ID);

                if (handle != null)
                {
                    Uptime = (long)(DateTime.UtcNow - handle.ConnectTime).TotalMilliseconds;
                }
            }
        public override void handlePOSTRequest(HttpProcessor p, StreamReader inputData)
        {
            string pageLower = p.requestedPage.ToLower();

            p.tcpClient.NoDelay = true;
            if (pageLower == "json")
            {
                JSONAPI.HandleRequest(p, inputData.ReadToEnd());
            }
            else if (pageLower == "hostconnect")
            {
                HostConnectResult result = HostConnect.HandleHostService(p);
                if (result.Error != null)
                {
                    Console.WriteLine(result.Error);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Handles a request from a Web Client who is requesting a proxied web socket connection to a specific Host Service.
        /// </summary>
        /// <param name="p">The HttpProcessor handling the request.</param>
        private static void HandleWebSocketProxyRequest(HttpProcessor p)
        {
            string[] parts = p.request_url.Segments;
            #region Validate Input
            if (parts.Length != 3)
            {
                p.writeFailure("400 Bad Request");
                return;
            }
            if (!int.TryParse(parts[1], out int computerId))
            {
                p.writeFailure("400 Bad Request");
                return;
            }
            #endregion
            #region Verify Permission
            string        sid     = parts[2];
            ServerSession session = SessionManager.GetSession(sid);
            if (session == null || session.Expired)
            {
                p.writeFailure("403 Forbidden");
                return;
            }
            Computer computer = ServiceWrapper.db.GetComputer(computerId);
            if (computer == null)
            {
                p.writeFailure("404 Not Found");
                return;
            }

            User user = session.GetUser();
            if (user == null)
            {
                p.writeFailure("403 Forbidden");
                return;
            }

            // If we get here, we have an active authenticated session.
            if (!user.IsAdmin)
            {
                // Admin users can access all computers.
                // This user is not an adminn, so we must check group membership.
                ComputerGroupMembership[] cgm = computer.GetGroupMemberships();
                if (cgm.Length == 0)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") but computer has no group memberships.");
                    p.writeFailure("403 Forbidden");
                    return;
                }
                UserGroupMembership[] ugm = user.GetGroupMemberships();
                if (ugm.Length == 0)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") but user has no group memberships.");
                    p.writeFailure("403 Forbidden");
                    return;
                }

                // The computer is accessible to this user if the computer and the user share at least one group membership.
                bool accessible = 0 < cgm.Select(m => m.GroupID).Intersect(ugm.Select(m => m.GroupID)).Count();
                if (!accessible)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") without permission.");
                    p.writeFailure("403 Forbidden");
                    return;
                }
            }
            #endregion

            // Now that permission has been verified, find out of the specified computer is online.
            HostConnectHandle host = HostConnect.GetOnlineComputer(computer.ID);
            if (host == null)
            {
                p.writeFailure("504 Gateway Timeout", "Computer " + computer.ID + " is not online.");
                return;
            }

            // The computer is online.  Send a request to have the Host Service connect to this Master Server's web socket proxy service.
            string        proxyKey      = Util.GetRandomAlphaNumericString(64);
            WaitingClient waitingClient = null;
            try
            {
                waitingClient = new WaitingClient(p);
                pendingProxyConnections[proxyKey] = waitingClient;
                host.RequestWebSocketProxy(p.RemoteIPAddress, proxyKey);

                // Wait for the connection from the Host Service.
                if (!waitingClient.clientWaitHandle.WaitOne(10000))
                {
                    p.writeFailure("504 Gateway Timeout", "Computer " + computer.ID + " did not respond in a timely manner.");
                    return;
                }
                Stream hostStream = waitingClient.hostProcessor?.tcpStream;
                if (hostStream == null)
                {
                    p.writeFailure("500 Internal Server Error");
                    Logger.Debug("hostStream was null in WebSocketProxy handler");
                    return;
                }

                // The Host Service has connected.  Remove the pending connection and clean up before starting to proxy data between the sockets.
                pendingProxyConnections.TryRemove(proxyKey, out WaitingClient ignored);
                proxyKey = null;
                waitingClient.Dispose();

                // Copy data from Host Service to Web Client
                p.responseWritten = true;
                CopyStreamUntilClosed(hostStream, p.tcpStream);
            }
            finally
            {
                if (proxyKey != null)
                {
                    pendingProxyConnections.TryRemove(proxyKey, out WaitingClient ignored);
                }

                waitingClient?.Dispose();
            }
        }
        /// <summary>
        /// Handles a request from a Web Client who is requesting a proxied web socket connection to a specific Host Service.
        /// </summary>
        /// <param name="p">The HttpProcessor handling the request.</param>
        public static void HandleWebSocketClientProxyRequest(HttpProcessor p)
        {
            #region Perform Validation
            // Path format: "/WebSocketClientProxy/1/SESSION". More path segments, if given, are ignored (the last path segment is typically used as a display name in browser developer tools).
            string[] parts = p.request_url.LocalPath.Split('/').Skip(1).ToArray();
            int      computerId;        // The computer ID the client wishes to connect to.
            if (parts.Length < 3 || parts[0] != "WebSocketClientProxy" || !int.TryParse(parts[1], out computerId))
            {
                p.writeFailure("400 Bad Request");
                return;
            }
            string sid = parts[2];             // The session ID of the client's session.
            #endregion
            #region Verify Permission
            ServerSession session = SessionManager.GetSession(sid);
            if (session == null || session.Expired)
            {
                p.writeFailure("403 Forbidden");
                return;
            }
            Computer computer = ServiceWrapper.db.GetComputer(computerId);
            if (computer == null)
            {
                p.writeFailure("404 Not Found");
                return;
            }

            User user = session.GetUser();
            if (user == null)
            {
                p.writeFailure("403 Forbidden");
                return;
            }

            // If we get here, we have an active authenticated session.
            if (!user.IsAdmin)
            {
                // Admin users can access all computers.
                // This user is not an adminn, so we must check group membership.
                ComputerGroupMembership[] cgm = computer.GetGroupMemberships();
                if (cgm.Length == 0)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") but computer has no group memberships.");
                    p.writeFailure("403 Forbidden");
                    return;
                }
                UserGroupMembership[] ugm = user.GetGroupMemberships();
                if (ugm.Length == 0)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") but user has no group memberships.");
                    p.writeFailure("403 Forbidden");
                    return;
                }

                // The computer is accessible to this user if the computer and the user share at least one group membership.
                bool accessible = 0 < cgm.Select(m => m.GroupID).Intersect(ugm.Select(m => m.GroupID)).Count();
                if (!accessible)
                {
                    Logger.Info("Non-admin user " + user.ID + " (" + user.Name + ") attempted to access computer " + computer.ID + " (" + computer.Name + ") without permission.");
                    p.writeFailure("403 Forbidden");
                    return;
                }
            }
            #endregion

            // Now that permission has been verified, find out of the specified computer is online.
            HostConnectHandle host = HostConnect.GetOnlineComputer(computer.ID);
            if (host == null)
            {
                p.writeFailure("504 Gateway Timeout", "Computer " + computer.ID + " is not online.");
                return;
            }

            // The computer is online.  Send a request to have the Host Service connect to this Master Server's web socket proxy service.
            string        proxyKey      = StringUtil.GetRandomAlphaNumericString(64);
            WaitingClient waitingClient = null;
            try
            {
                waitingClient = new WaitingClient(p);
                pendingProxyConnections[proxyKey] = waitingClient;
                host.RequestWebSocketProxy(p.RemoteIPAddress, proxyKey);

                // Wait for the connection from the Host Service.
                if (!waitingClient.clientWaitHandle.WaitOne(10000))
                {
                    p.writeFailure("504 Gateway Timeout", "Computer " + computer.ID + " did not respond in a timely manner.");
                    return;
                }
                Stream hostStream = waitingClient.hostProcessor?.tcpStream;
                if (hostStream == null)
                {
                    p.writeFailure("500 Internal Server Error");
                    Logger.Debug("hostStream was null in WebSocketProxy handler");
                    return;
                }

                // The Host Service has connected.  Remove the pending connection and clean up before starting to proxy data between the sockets.
                pendingProxyConnections.TryRemove(proxyKey, out WaitingClient ignored);
                proxyKey = null;
                waitingClient.Dispose();

                // Copy data from Host Service to Web Client
                p.responseWritten   = true;
                p.tcpClient.NoDelay = true;
                Console.WriteLine("Client Proxy Initialized");
                CopyStreamUntilClosed(hostStream, p.tcpStream);
            }
            finally
            {
                // If anything went wrong initializing the proxy connection, we might not have cleaned up yet.
                if (proxyKey != null)
                {
                    pendingProxyConnections.TryRemove(proxyKey, out WaitingClient ignored);
                }

                waitingClient?.Dispose();
            }
        }