private static async Task WebSocketToPipeWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken)
        {
            const int blockSize = 0x10000;
            var       buffer    = new MemoryStream(blockSize);

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                int index = (int)buffer.Length;
                buffer.SetLength(index + blockSize);
                buffer.TryGetBuffer(out ArraySegment <byte> bufferSegment);

                var wsrr = await socket.ReceiveAsync(new ArraySegment <byte>(bufferSegment.Array, index, blockSize), cancellationToken);

                buffer.SetLength(index + wsrr.Count);

                if (wsrr.CloseStatus != null)
                {
                    break;
                }

                if (wsrr.EndOfMessage)
                {
                    pipe.Write(buffer.ToArray());
                    buffer.SetLength(0);
                }
            }
        }
Example #2
0
        private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe)
        {
            using (stream) {
                while (true)
                {
                    byte[] message;
                    try {
                        message = await pipe.ReadAsync(CommonStartup.CancellationToken);
                    } catch (PipeDisconnectedException) {
                        break;
                    }

                    var sizeBuf = BitConverter.GetBytes(message.Length);
                    try {
                        await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length);

                        await stream.WriteAsync(message, 0, message.Length);

                        await stream.FlushAsync();
                    } catch (IOException) {
                        break;
                    }
                }
            }
        }
Example #3
0
        private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var message = await pipe.ReadAsync(cancellationToken);

                await socket.SendAsync(new ArraySegment <byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken);
            }
        }
Example #4
0
        private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) {
            while (true) {
                cancellationToken.ThrowIfCancellationRequested();

                byte[] message;
                try {
                    message = await pipe.ReadAsync(cancellationToken);
                } catch (PipeDisconnectedException) {
                    break;
                }

                await socket.SendAsync(new ArraySegment<byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken);
            }
        }
        private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                byte[] message;
                try {
                    message = await pipe.ReadAsync(cancellationToken);
                } catch (PipeDisconnectedException) {
                    break;
                }

                await socket.SendAsync(new ArraySegment <byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken);
            }
        }
Example #6
0
        private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe)
        {
            while (true)
            {
                var message = await pipe.ReadAsync(Program.CancellationToken);

                var sizeBuf = BitConverter.GetBytes(message.Length);
                try {
                    await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length);

                    await stream.WriteAsync(message, 0, message.Length);

                    await stream.FlushAsync();
                } catch (IOException) {
                    break;
                }
            }
        }
Example #7
0
        private async Task HostToClientWorker(Stream stream, IMessagePipeEnd pipe)
        {
            var sizeBuf = new byte[sizeof(int)];

            while (true)
            {
                if (!await FillFromStreamAsync(stream, sizeBuf))
                {
                    break;
                }
                int size = BitConverter.ToInt32(sizeBuf, 0);

                var message = new byte[size];
                if (!await FillFromStreamAsync(stream, message))
                {
                    break;
                }

                pipe.Write(message);
            }
        }
Example #8
0
        private static async Task WebSocketToPipeWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) {
            const int blockSize = 0x10000;
            var buffer = new MemoryStream(blockSize);

            while (true) {
                cancellationToken.ThrowIfCancellationRequested();

                int index = (int)buffer.Length;
                buffer.SetLength(index + blockSize);

                var wsrr = await socket.ReceiveAsync(new ArraySegment<byte>(buffer.GetBuffer(), index, blockSize), cancellationToken);
                buffer.SetLength(index + wsrr.Count);

                if (wsrr.CloseStatus != null) {
                    break;
                } else if (wsrr.EndOfMessage) {
                    pipe.Write(buffer.ToArray());
                    buffer.SetLength(0);
                }
            }
        }
 public WebSocketPipeAction(string id, IMessagePipeEnd pipe, ILogger logger)
 {
     _id     = id;
     _pipe   = pipe;
     _logger = logger;
 }
Example #10
0
        public void StartHost(string profilePath, string logFolder, ILogger outputLogger, LogVerbosity verbosity)
        {
            if (_hostEnd != null)
            {
                throw new InvalidOperationException("Host process is already running");
            }

            var useridentity = User as WindowsIdentity;
            // In remote broker User Identity type is always WindowsIdentity
            string suppressUI     = (useridentity == null) ? string.Empty : "--rhost-suppress-ui ";
            string isRepl         = _isInteractive ? "--rhost-interactive " : string.Empty;
            string brokerPath     = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath());
            string rhostExePath   = Path.Combine(brokerPath, RHostExe);
            string logFolderParam = string.IsNullOrEmpty(logFolder) ? string.Empty : Invariant($"--rhost-log-dir \"{logFolder}\"");
            string commandLine    = Invariant($"\"{rhostExePath}\" {suppressUI}{isRepl}--rhost-name \"{Id}\" {logFolderParam} --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}");
            var    usernameBldr   = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1);
            var    domainBldr     = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1);

            // Get R_HOME value
            var shortHome = new StringBuilder(NativeMethods.MAX_PATH);

            NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity);

            Stream stdout, stdin, stderror;
            bool   loggedOnUser = useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User;

            // build user environment block
            Win32EnvironmentBlock eb;

            if (loggedOnUser)
            {
                uint error = NativeMethods.CredUIParseUserName(User.Name, usernameBldr, usernameBldr.Capacity, domainBldr, domainBldr.Capacity);
                if (error != 0)
                {
                    _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error);
                    throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error));
                }

                string username = usernameBldr.ToString();
                string domain   = domainBldr.ToString();

                eb = CreateEnvironmentBlockForUser(useridentity, username, profilePath);
            }
            else
            {
                eb = Win32EnvironmentBlock.Create((useridentity ?? WindowsIdentity.GetCurrent()).Token);
            }

            // add additional variables to the environment block
            eb["R_HOME"] = shortHome.ToString();
            _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "R_HOME", eb["R_HOME"]);
            eb["PATH"] = Invariant($"{Interpreter.Info.BinPath};{Environment.GetEnvironmentVariable("PATH")}");
            _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "PATH", eb["PATH"]);


            _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, commandLine);
            using (Win32NativeEnvironmentBlock nativeEnv = eb.GetNativeEnvironmentBlock()) {
                if (loggedOnUser)
                {
                    _process = Win32Process.StartProcessAsUser(useridentity, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror);
                }
                else
                {
                    _process = Win32Process.StartProcessAsUser(null, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror);
                }
            }

            _process.Exited += delegate(object o, Win32ProcessExitEventArgs exitState){
                _hostEnd?.Dispose();
                _hostEnd = null;
                State    = SessionState.Terminated;
                if (exitState.HasError())
                {
                    _sessionLogger.LogInformation(Resources.Error_ExitRHost, exitState.ExitCode);
                }
            };

            _process.WaitForExit(250);
            if (_process.HasExited && _process.ExitCode < 0)
            {
                var message = ErrorCodeConverter.MessageFromErrorCode(_process.ExitCode);
                if (!string.IsNullOrEmpty(message))
                {
                    throw new Win32Exception(message);
                }
                throw new Win32Exception(_process.ExitCode);
            }

            _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name);

            var hostEnd = _pipe.ConnectHost(_process.ProcessId);

            _hostEnd = hostEnd;

            ClientToHostWorker(stdin, hostEnd).DoNotWait();
            HostToClientWorker(stdout, hostEnd).DoNotWait();

            HostToClientErrorWorker(stderror, _process.ProcessId, (int processid, string errdata) => {
                outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, processid, errdata);
            }).DoNotWait();
        }
Example #11
0
        private async Task HostToClientWorker(Stream stream, IMessagePipeEnd pipe) {
            var sizeBuf = new byte[sizeof(int)];
            while (true) {
                if (!await FillFromStreamAsync(stream, sizeBuf)) {
                    break;
                }
                int size = BitConverter.ToInt32(sizeBuf, 0);

                var message = new byte[size];
                if (!await FillFromStreamAsync(stream, message)) {
                    break;
                }

                pipe.Write(message);
            }
        }
Example #12
0
 public WebSocketPipeAction(IMessagePipeEnd pipe, ILogger logger)
 {
     _pipe   = pipe;
     _logger = logger;
 }
Example #13
0
 public WebSocketPipeAction(string id, IMessagePipeEnd pipe)
 {
     _id   = id;
     _pipe = pipe;
 }
Example #14
0
 public WebSocketPipeAction(string id, IMessagePipeEnd pipe) {
     _id = id;
     _pipe = pipe;
 }
Example #15
0
        public void StartHost(SecureString password, string profilePath, ILogger outputLogger, LogVerbosity verbosity) {
            if (_hostEnd != null) {
                throw new InvalidOperationException("Host process is already running");
            }

            var useridentity = User as WindowsIdentity;
            // In remote broker User Identity type is always WindowsIdentity
            string suppressUI = (useridentity == null) ? string.Empty : " --suppress-ui ";
            string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath());
            string rhostExePath = Path.Combine(brokerPath, RHostExe);
            string arguments = Invariant($"{suppressUI}--rhost-name \"{Id}\" --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}");
            var username = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1);
            var domain = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1);

            ProcessStartInfo psi = new ProcessStartInfo(rhostExePath) {
                UseShellExecute = false,
                CreateNoWindow = false,
                Arguments = arguments,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                LoadUserProfile = true
            };
            
            if (useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User && password != null) {
                uint error = NativeMethods.CredUIParseUserName(User.Name, username, username.Capacity, domain, domain.Capacity);
                if (error != 0) {
                    _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error);
                    throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error));
                }

                psi.Domain = domain.ToString();
                psi.UserName = username.ToString();
                psi.Password = password;

                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariableCreationBegin, User.Name, profilePath);
                // if broker and rhost are run as different users recreate user environment variables.
                psi.EnvironmentVariables["USERNAME"] = username.ToString();
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERNAME", psi.EnvironmentVariables["USERNAME"]);

                psi.EnvironmentVariables["HOMEDRIVE"] = profilePath.Substring(0, 2);
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEDRIVE", psi.EnvironmentVariables["HOMEDRIVE"]);

                psi.EnvironmentVariables["HOMEPATH"] = profilePath.Substring(2);
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEPATH", psi.EnvironmentVariables["HOMEPATH"]);

                psi.EnvironmentVariables["USERPROFILE"] = Invariant($"{psi.EnvironmentVariables["HOMEDRIVE"]}{psi.EnvironmentVariables["HOMEPATH"]}");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERPROFILE", psi.EnvironmentVariables["USERPROFILE"]);

                psi.EnvironmentVariables["APPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Roaming");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "APPDATA", psi.EnvironmentVariables["APPDATA"]);

                psi.EnvironmentVariables["LOCALAPPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Local");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "LOCALAPPDATA", psi.EnvironmentVariables["LOCALAPPDATA"]);

                psi.EnvironmentVariables["TEMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TEMP", psi.EnvironmentVariables["TEMP"]);

                psi.EnvironmentVariables["TMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TMP", psi.EnvironmentVariables["TMP"]);
            }

            var shortHome = new StringBuilder(NativeMethods.MAX_PATH);
            NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity);
            psi.EnvironmentVariables["R_HOME"] = shortHome.ToString();
            psi.EnvironmentVariables["PATH"] = Interpreter.Info.BinPath + ";" + Environment.GetEnvironmentVariable("PATH");

            psi.WorkingDirectory = Path.GetDirectoryName(rhostExePath);
            
            _process = new Process {
                StartInfo = psi,
                EnableRaisingEvents = true,
            };

            _process.ErrorDataReceived += (sender, e) => {
                var process = (Process)sender;
                outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, process.Id, e.Data);
            };

            _process.Exited += delegate {
                _hostEnd?.Dispose();
                _hostEnd = null;
                State = SessionState.Terminated;
            };

            _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, rhostExePath, arguments);
            try {
                StartSession();
            } catch(Exception ex) {
                _sessionLogger.LogError(Resources.Error_RHostFailedToStart, ex.Message);
                throw;
            }
            _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name);

            _process.BeginErrorReadLine();

            var hostEnd = _pipe.ConnectHost(_process.Id);
            _hostEnd = hostEnd;

            ClientToHostWorker(_process.StandardInput.BaseStream, hostEnd).DoNotWait();
            HostToClientWorker(_process.StandardOutput.BaseStream, hostEnd).DoNotWait();
        }
Example #16
0
        public void StartHost(SecureString password, string profilePath, ILogger outputLogger, LogVerbosity verbosity)
        {
            if (_hostEnd != null)
            {
                throw new InvalidOperationException("Host process is already running");
            }

            string brokerPath   = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath());
            string rhostExePath = Path.Combine(brokerPath, RHostExe);
            string arguments    = Invariant($"--rhost-name \"{Id}\" --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}");
            var    username     = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1);
            var    domain       = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1);

            ProcessStartInfo psi = new ProcessStartInfo(rhostExePath)
            {
                UseShellExecute        = false,
                CreateNoWindow         = false,
                Arguments              = arguments,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
                LoadUserProfile        = true
            };

            var useridentity = User as WindowsIdentity;

            if (useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User && password != null)
            {
                uint error = NativeMethods.CredUIParseUserName(User.Name, username, username.Capacity, domain, domain.Capacity);
                if (error != 0)
                {
                    _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error);
                    throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error));
                }

                psi.Domain   = domain.ToString();
                psi.UserName = username.ToString();
                psi.Password = password;

                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariableCreationBegin, User.Name, profilePath);
                // if broker and rhost are run as different users recreate user environment variables.
                psi.EnvironmentVariables["USERNAME"] = username.ToString();
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERNAME", psi.EnvironmentVariables["USERNAME"]);

                psi.EnvironmentVariables["HOMEDRIVE"] = profilePath.Substring(0, 2);
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEDRIVE", psi.EnvironmentVariables["HOMEDRIVE"]);

                psi.EnvironmentVariables["HOMEPATH"] = profilePath.Substring(2);
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEPATH", psi.EnvironmentVariables["HOMEPATH"]);

                psi.EnvironmentVariables["USERPROFILE"] = Invariant($"{psi.EnvironmentVariables["HOMEDRIVE"]}{psi.EnvironmentVariables["HOMEPATH"]}");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERPROFILE", psi.EnvironmentVariables["USERPROFILE"]);

                psi.EnvironmentVariables["APPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Roaming");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "APPDATA", psi.EnvironmentVariables["APPDATA"]);

                psi.EnvironmentVariables["LOCALAPPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Local");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "LOCALAPPDATA", psi.EnvironmentVariables["LOCALAPPDATA"]);

                psi.EnvironmentVariables["TEMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TEMP", psi.EnvironmentVariables["TEMP"]);

                psi.EnvironmentVariables["TMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp");
                _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TMP", psi.EnvironmentVariables["TMP"]);
            }

            var shortHome = new StringBuilder(NativeMethods.MAX_PATH);

            NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity);
            psi.EnvironmentVariables["R_HOME"] = shortHome.ToString();
            psi.EnvironmentVariables["PATH"]   = Interpreter.Info.BinPath + ";" + Environment.GetEnvironmentVariable("PATH");

            psi.WorkingDirectory = Path.GetDirectoryName(rhostExePath);

            _process = new Process {
                StartInfo           = psi,
                EnableRaisingEvents = true,
            };

            _process.ErrorDataReceived += (sender, e) => {
                var process = (Process)sender;
                outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, process.Id, e.Data);
            };

            _process.Exited += delegate {
                _hostEnd?.Dispose();
                _hostEnd = null;
                State    = SessionState.Terminated;
            };

            _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, rhostExePath, arguments);
            try {
                StartSession();
            } catch (Exception ex) {
                _sessionLogger.LogError(Resources.Error_RHostFailedToStart, ex.Message);
                throw;
            }
            _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name);

            _process.BeginErrorReadLine();

            var hostEnd = _pipe.ConnectHost(_process.Id);

            _hostEnd = hostEnd;

            ClientToHostWorker(_process.StandardInput.BaseStream, hostEnd).DoNotWait();
            HostToClientWorker(_process.StandardOutput.BaseStream, hostEnd).DoNotWait();
        }
Example #17
0
        private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe) {
            using (stream) {
                while (true) {
                    byte[] message;
                    try {
                        message = await pipe.ReadAsync(Program.CancellationToken);
                    } catch (PipeDisconnectedException) {
                        break;
                    }

                    var sizeBuf = BitConverter.GetBytes(message.Length);
                    try {
                        await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length);
                        await stream.WriteAsync(message, 0, message.Length);
                        await stream.FlushAsync();
                    } catch (IOException) {
                        break;
                    }
                }
            }
        }