/// <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); }
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; }
/// <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); }