public static string PuttyArguments(HostInfo host, PuttyProfile profile, AuthenticationType authType) { // example: -ssh -load _stm_preset_ username@domainName -P 22 -pw password -D 5000 -L 44333:username.dyndns.org:44333 string profileArg = ""; if (profile != null) { profileArg = @" -load " + profile.Name; } var startShellOption = ""; if (string.IsNullOrWhiteSpace(host.RemoteCommand)) { startShellOption = " -N"; } string args; switch (authType) { case AuthenticationType.None: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -v{4}", profileArg, host.Username, host.Hostname, host.Port, startShellOption); Logger.Log.DebugFormat(@"plink.exe {0}", args); break; case AuthenticationType.Password: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -pw {4} -v{5}", profileArg, host.Username, host.Hostname, host.Port, host.Password, startShellOption); Logger.Log.DebugFormat(@"plink.exe -ssh{0} {1}@{2} -P {3} -pw ******** -v -N", profileArg, host.Username, host.Hostname, host.Port); break; case AuthenticationType.PrivateKey: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -i {4} -v{5}", profileArg, host.Username, host.Hostname, host.Port, PrivateKeysStorage.CreatePrivateKey(host).Filename, startShellOption); Logger.Log.DebugFormat(@"plink.exe {0}", args); break; default: throw new ArgumentOutOfRangeException("authType"); } var sb = new StringBuilder(args); foreach (var tunnelArg in host.Tunnels.Select(tunnelArguments)) { sb.Append(tunnelArg); } args = sb.ToString(); return(args); }
private static string psftpArguments(HostInfo host) { string args; switch (host.AuthType) { case AuthenticationType.Password: args = String.Format(@"{0}@{1} -P {2} -pw {3} -batch", host.Username, host.Hostname, host.Port, host.Password); break; case AuthenticationType.PrivateKey: args = String.Format(@"{0}@{1} -P {2} -i {3} -batch", host.Username, host.Hostname, host.Port, PrivateKeysStorage.CreatePrivateKey(host).Filename); break; default: throw new ArgumentOutOfRangeException("authType"); } return(args); }
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() { // 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); }
/// <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); }
public static string PuttyArguments(HostInfo host, PuttyProfile profile, AuthenticationType authType, bool addTunnels) { // example: -ssh -load _stm_preset_ username@domainName -P 22 -pw password -D 5000 -L 44333:username.dyndns.org:44333 string profileArg = ""; if (profile != null) { profileArg = @" -load " + profile.Name; } var startShellOption = ""; if (string.IsNullOrWhiteSpace(host.RemoteCommand) && addTunnels) { startShellOption = " -N"; } string args; switch (authType) { case AuthenticationType.None: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -v{4}", profileArg, host.Username, host.CurrentHostAndPort.Hostname, host.CurrentHostAndPort.Port, startShellOption); //Logger.Log.DebugFormat(@"plink.exe {0}", args); break; case AuthenticationType.Password: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -pw {4} -v{5}", profileArg, host.Username, host.CurrentHostAndPort.Hostname, host.CurrentHostAndPort.Port, host.Password, startShellOption); //Logger.Log.DebugFormat(@"plink.exe -ssh{0} {1}@{2} -P {3} -pw ******** -v -N", profileArg, host.Username,host.Hostname, host.Port); break; case AuthenticationType.PrivateKey: args = String.Format(@"-ssh{0} {1}@{2} -P {3} -i ""{4}"" -v{5}", profileArg, host.Username, host.CurrentHostAndPort.Hostname, host.CurrentHostAndPort.Port, PrivateKeysStorage.CreatePrivateKey(host).Filename, startShellOption); //Logger.Log.DebugFormat(@"plink.exe {0}", args); break; default: throw new ArgumentOutOfRangeException("authType"); } if (addTunnels) { var sb = new StringBuilder(args); foreach (var tunnelArg in host.Tunnels.Select(tunnelArguments)) { sb.Append(tunnelArg); } args = sb.ToString(); } Logger.Log.DebugFormat(@"plink.exe {0}", args.Replace("-pw " + host.Password + " ", "-pw ********* ")); if (addTunnels && host.Tunnels.Any()) { var ports = host.Tunnels.Select(x => x.LocalPort).ToList(); var ipGP = IPGlobalProperties.GetIPGlobalProperties(); var endpoints = ipGP.GetActiveTcpListeners(); var portUsed = endpoints.Select(x => x.Port.ToString()).Distinct().Where(x => ports.Contains(x)).ToList(); if (portUsed.Any()) { var portsDetail = NetStatPortsAndProcessNames.GetNetStatPorts().ToLookup(x => x.port_number); if (portUsed.Count == 1) { throw new Exception("La porta " + portUsed[0] + " è già in uso da '" + portsDetail[portUsed[0]].Select(p => p.process_name).FirstOrDefault() + "'."); } portUsed = portUsed.Select(x => x + " (" + portsDetail[x].Select(p => p.process_name).FirstOrDefault() + ")").ToList(); throw new Exception("Le seguenti porto sono già in uso: " + string.Join(", ", portUsed)); } } return(args); }