예제 #1
0
        /// <summary>
        /// Start attemt to establish link once.
        /// </summary>
        /// <returns>Link was successfully started.</returns>
        private bool startOnce()
        {
            // fill results dic
            lock (_forwardingResultsLock)
            {
                _forwardingResults = Host.Tunnels.ToDictionary(t => t, t => ForwardingResult.CreateSuccess());
            }

            // Процесс
            _process = new Process
            {
                StartInfo =
                {
                    FileName               = ConsoleTools.PLinkLocation,
                    CreateNoWindow         = true,
                    UseShellExecute        = false,
                    RedirectStandardError  = true,
                    RedirectStandardOutput = true,
                    RedirectStandardInput  = true,
                    Arguments              = ConsoleTools.PuttyArguments(Host, _profile, Host.AuthType)
                }
            };

            _process.ErrorDataReceived += errorDataHandler;
            _process.Start();
            _process.BeginErrorReadLine();

            _process.StandardInput.AutoFlush = true;

            var  buffer                   = new StringBuilder();
            bool passwordProvided         = false;
            bool passphraseForKeyProvided = false;

            while (!_process.HasExited)
            {
                while (_process.StandardOutput.Peek() >= 0)
                {
                    char c = (char)_process.StandardOutput.Read();
                    buffer.Append(c);
                }

                _process.StandardOutput.DiscardBufferedData();
                string data = buffer.ToString().ToLower();

                buffer.Clear();

                if (data.Contains(@"login as:"))
                {
                    // invalid username provided
                    stop();
                    // _process.StandardInput.WriteLine(username);
                    LastStartError = Resources.PuttyLink_Error_InvalidUsername;
                }
                else if (data.Contains(@"password:"******"passphrase for key") && !passphraseForKeyProvided)
                {
                    writeLineStdIn(Host.Password);
                    passphraseForKeyProvided = true;
                }
                else
                {
                    foreach (var line in data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        Logger.Log.Debug(line);
                    }
                }
            }

            PrivateKeysStorage.RemovePrivateKey(Host);
            return(Status == ELinkStatus.Started || Status == ELinkStatus.StartedWithWarnings);
        }
예제 #2
0
        private void errorDataHandler(object o, DataReceivedEventArgs args)
        {
            if (args.Data == null)
            {
                return;
            }
            ThreadContext.Properties[@"Host"] = Host; // Set up context for working thread
            Logger.Log.Debug(args.Data);
            // LOCAL tunnels error
            var m = Regex.Match(args.Data, @"Local port (?<srcPort>\d+) forwarding to (?<dstHost>[^:]+):(?<dstPort>\d+) failed: (?<errorString>.*)", RegexOptions.IgnoreCase);

            if (m.Success)
            {
                var srcPort     = m.Groups["srcPort"].Value;
                var dstHost     = m.Groups["dstHost"].Value;
                var dstPort     = m.Groups["dstPort"].Value;
                var errorString = m.Groups["errorString"].Value;
                var tunnel      = Host.Tunnels.FirstOrDefault(
                    t => t.LocalPort == srcPort && t.RemoteHostname == dstHost && t.RemotePort == dstPort && t.Type == TunnelType.Local);
                if (tunnel != null)
                {
                    lock (_forwardingResultsLock)
                    {
                        _forwardingResults[tunnel] = ForwardingResult.CreateFailed(errorString);
                    }

                    Logger.Log.WarnFormat("[{0}] [{1}] {2}", Host.Name, tunnel.SimpleString, errorString);
                }
            }
            // DYNAMIC tunnels error
            m = Regex.Match(args.Data, @"Local port (?<srcPort>\d+) SOCKS dynamic forwarding failed: (?<errorString>.*)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                var srcPort     = m.Groups["srcPort"].Value;
                var errorString = m.Groups["errorString"].Value;
                var tunnel      = Host.Tunnels.FirstOrDefault(
                    t => t.LocalPort == srcPort && t.Type == TunnelType.Dynamic);
                if (tunnel != null)
                {
                    lock (_forwardingResultsLock)
                    {
                        _forwardingResults[tunnel] = ForwardingResult.CreateFailed(errorString);
                    }
                    Logger.Log.WarnFormat("[{0}] [{1}] {2}", Host.Name, tunnel.SimpleString, errorString);
                }
            }
            // Accept certificate
            if (args.Data.Contains(@"The server's host key is not cached in the registry."))
            {
                writeStdIn(@"y");
            }
            // Unable to open connection:
            if (args.Data.Contains(@"Unable to open connection:"))
            {
                _multilineError.Append(@"Unable to open connection: ");
                return;
            }
            // Access denied error
            if (args.Data.Contains(@"Access denied"))
            {
                // Неверный пароль (Доступ запрещен)
                LastStartError = @"Access Denied";
                stop();
            }
            // Access granted
            if (args.Data.Contains(@"Access granted"))
            {
                // Доступ открыт, можно удалить ключ
                PrivateKeysStorage.RemovePrivateKey(Host);
                Logger.Log.Debug(string.Format("Access granted called: {0}", Host));

                // Make delay for a couple of seconds and set status to 'Started' if a shell is not supposed to be started
                if (string.IsNullOrWhiteSpace(Host.RemoteCommand))
                {
                    _deferredCallTimer = new Timer(
                        delegate
                    {
                        bool forwardingFailed;
                        lock (_forwardingResultsLock)
                        {
                            forwardingFailed = _forwardingResults.Any(p => !p.Value.Success);
                        }

                        ThreadContext.Properties[@"Host"] = Host;
                        Logger.Log.Debug(string.Format("Delegate called: {0}", Host));
                        Status = forwardingFailed
                                         ? ELinkStatus.StartedWithWarnings
                                         : ELinkStatus.Started;
                        ThreadContext.Properties[@"Host"] = null;
                    },
                        null,
                        1500,
                        Timeout.Infinite);
                }
            }

            // Fatal errors
            m = Regex.Match(args.Data, @"^FATAL ERROR:\s*(?<msg>.*)$");
            if (m.Success)
            {
                LastStartError = m.Groups["msg"].Value;
            }

            // connection establishing
            if (args.Data.Contains(ShellStartedMessage))
            {
                bool forwardingFails;
                lock (_forwardingResultsLock)
                {
                    forwardingFails = _forwardingResults.Any(p => !p.Value.Success);
                }

                Status = forwardingFails ? ELinkStatus.StartedWithWarnings : ELinkStatus.Started;

                // Start a command to be executed after connection establishment
                if (!string.IsNullOrWhiteSpace(Host.RemoteCommand))
                {
                    _deferredCallTimer = new Timer(
                        delegate
                    {
                        ThreadContext.Properties[@"Host"] = Host;
                        writeLineStdIn(Host.RemoteCommand);
                        ThreadContext.Properties[@"Host"] = null;
                    },
                        null,
                        1000,
                        Timeout.Infinite);
                }
            }

            // multiline error?
            if (_multilineError.Length > 0)
            {
                _multilineError.Append(args.Data);
                LastStartError = _multilineError.ToString();
                _multilineError.Clear();
                stop();
            }

            ThreadContext.Properties[@"Host"] = null;
        }
예제 #3
0
        /// <summary>
        /// Start attemt to establish link once.
        /// </summary>
        /// <returns>Link was successfully started.</returns>
        private bool startOnce(TimeSpan?connectionTimeout)
        {
            // fill results dic
            lock (_forwardingResultsLock)
            {
                _forwardingResults = Host.Tunnels.ToDictionary(t => t, t => ForwardingResult.CreateSuccess());
            }

            // Процесс
            _process = new Process
            {
                StartInfo =
                {
                    FileName               = ConsoleTools.PLinkLocation,
                    CreateNoWindow         = true,
                    UseShellExecute        = false,
                    RedirectStandardError  = true,
                    RedirectStandardOutput = true,
                    RedirectStandardInput  = true,
                    Arguments              = ConsoleTools.PuttyArguments(Host, _profile, Host.AuthType, true)
                }
            };

            _process.ErrorDataReceived += errorDataHandler;
            _process.Start();
            _process.BeginErrorReadLine();

            _process.StandardInput.AutoFlush = true;
            var p = _process;
            var processAutoKillTimer = connectionTimeout == null
                                ? null
                                : new Timer(delegate
            {
                ThreadContext.Properties[@"Host"] = Host;
                var connectionStarted             = Status == ELinkStatus.Started || Status == ELinkStatus.StartedWithWarnings;
                if (!connectionStarted && p == _process)
                {
                    try { p.Kill(); }
                    catch { /**/ }
                    Logger.Log.WarnFormat("[{0}] {1}", Host.Name, $"Connection timeout ({connectionTimeout})...");
                }

                ThreadContext.Properties[@"Host"] = null;
            }, null, (long)connectionTimeout.Value.TotalMilliseconds, Timeout.Infinite);

            var  buffer                   = new StringBuilder();
            bool passwordProvided         = false;
            bool passphraseForKeyProvided = false;

            while (!_process.HasExited)
            {
                while (_process.StandardOutput.Peek() >= 0)
                {
                    char c = (char)_process.StandardOutput.Read();
                    buffer.Append(c);
                }

                _process.StandardOutput.DiscardBufferedData();
                string data = buffer.ToString().ToLower();

                buffer.Clear();

                if (data.Contains(@"login as:"))
                {
                    // invalid username provided
                    stop();
                    // _process.StandardInput.WriteLine(username);
                    LastStartError = Resources.PuttyLink_Error_InvalidUsername;
                }
                else if (data.Contains(@"password:"******"passphrase for key") && !passphraseForKeyProvided)
                {
                    writeLineStdIn(Host.Password);
                    passphraseForKeyProvided = true;
                }
                else
                {
                    foreach (var line in data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        Logger.Log.Debug(line);
                    }
                }
            }

            processAutoKillTimer?.Dispose();
            PrivateKeysStorage.RemovePrivateKey(Host);
            return(Status == ELinkStatus.Started || Status == ELinkStatus.StartedWithWarnings);
        }