/// <summary> /// Display a messagebox with the certificate details, ask user to approve/decline it. /// </summary> public static void CheckCertificate(object sender, ValidateCertificateEventArgs n) { var msg = string.Empty; // Add certificate info if (Program.Account.Account.Protocol == FtpProtocol.SFTP) msg += string.Format("{0,-8}\t {1}\n{2,-8}\t {3}\n", "Key:", n.Key, "Key Size:", n.KeySize); else msg += string.Format("{0,-25}\t {1}\n{2,-25}\t {3}\n{4,-25}\t {5}\n{6,-25}\t {7}\n\n", "Valid from:", n.ValidFrom, "Valid to:", n.ValidTo, "Serial number:", n.SerialNumber, "Algorithm:", n.Algorithm); msg += string.Format("Fingerprint: {0}\n\n", n.Fingerprint); msg += "Trust this certificate and continue?"; // Do we trust the server's certificate? bool certificate_trusted = MessageBox.Show(msg, "Do you trust this certificate?", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes; n.IsTrusted = certificate_trusted; if (certificate_trusted) { Settings.TrustedCertificates.Add(n.Fingerprint); Settings.SaveCertificates(); } }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); if (FTP) { _ftpc = new FtpClient { Host = controller.Account.Host, Port = controller.Account.Port }; // Add accepted certificates _ftpc.ClientCertificates.AddRange(Certificates); if (controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.ValidateCertificate += (sender, x) => { var fingerPrint = new X509Certificate2(x.Certificate).Thumbprint; if (_ftpc.ClientCertificates.Count <= 0 && x.PolicyErrors != SslPolicyErrors.None) { Certificates.Add(x.Certificate); x.Accept = false; return; } // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.Accept = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, SerialNumber = x.Certificate.GetSerialNumberString(), Algorithm = x.Certificate.GetKeyAlgorithmParametersString(), ValidFrom = x.Certificate.GetEffectiveDateString(), ValidTo = x.Certificate.GetExpirationDateString(), Issuer = x.Certificate.Issuer }; // Prompt user to validate ValidateCertificate(null, e); x.Accept = e.IsTrusted; }; // Change Security Protocol if (controller.Account.FtpsMethod == FtpsMethod.Explicit) { _ftpc.EncryptionMode = FtpEncryptionMode.Explicit; } else if (controller.Account.FtpsMethod == FtpsMethod.Implicit) { _ftpc.EncryptionMode = FtpEncryptionMode.Implicit; } } _ftpc.Credentials = new NetworkCredential(controller.Account.Username, controller.Account.Password); try { _ftpc.Connect(); } catch (Exception exc) { // Since the ClientCertificates are added when accepted in ValidateCertificate, the first // attempt to connect will fail with an AuthenticationException. If this is the case, a // re-connect is attempted, this time with the certificates properly set. // This is a workaround to avoid storing Certificate files locally... if (exc is System.Security.Authentication.AuthenticationException && _ftpc.ClientCertificates.Count <= 0) { Connect(); } else { throw; } } } else // SFTP { ConnectionInfo connectionInfo; if (controller.isPrivateKeyValid) { connectionInfo = new PrivateKeyConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, new PrivateKeyFile(controller.Account.PrivateKeyFile, controller.Account.Password)); } else { connectionInfo = new PasswordConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, controller.Account.Password); } _sftpc = new SftpClient(connectionInfo); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; // Prompt user to validate ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) { Notifications.ChangeTrayText(MessageType.Nothing); } if (ConnectionClosed != null) { ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); } if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException) { Log.Write(l.Warning, "Permission denied error occured"); } if (e.Exception is Renci.SshNet.Common.SshConnectionException) { Reconnect(); } }; } controller.HomePath = WorkingDirectory; if (isConnected) { if (!string.IsNullOrWhiteSpace(controller.Paths.Remote) && !controller.Paths.Remote.Equals("/")) { WorkingDirectory = controller.Paths.Remote; } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); if (FTP) { _ftpc = new FtpClient { Host = controller.Account.Host, Port = controller.Account.Port }; // Add accepted certificates _ftpc.ClientCertificates.AddRange(Certificates); if (controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.ValidateCertificate += (sender, x) => { var fingerPrint = new X509Certificate2(x.Certificate).Thumbprint; if (_ftpc.ClientCertificates.Count <= 0 && x.PolicyErrors != SslPolicyErrors.None) { Certificates.Add(x.Certificate); x.Accept = false; return; } // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.Accept = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, SerialNumber = x.Certificate.GetSerialNumberString(), Algorithm = x.Certificate.GetKeyAlgorithmParametersString(), ValidFrom = x.Certificate.GetEffectiveDateString(), ValidTo = x.Certificate.GetExpirationDateString(), Issuer = x.Certificate.Issuer }; // Prompt user to validate ValidateCertificate(null, e); x.Accept = e.IsTrusted; }; // Change Security Protocol if (controller.Account.FtpsMethod == FtpsMethod.Explicit) _ftpc.EncryptionMode = FtpEncryptionMode.Explicit; else if (controller.Account.FtpsMethod == FtpsMethod.Implicit) _ftpc.EncryptionMode = FtpEncryptionMode.Implicit; } _ftpc.Credentials = new NetworkCredential(controller.Account.Username, controller.Account.Password); try { _ftpc.Connect(); } catch (Exception exc) { // Since the ClientCertificates are added when accepted in ValidateCertificate, the first // attempt to connect will fail with an AuthenticationException. If this is the case, a // re-connect is attempted, this time with the certificates properly set. // This is a workaround to avoid storing Certificate files locally... if (exc is System.Security.Authentication.AuthenticationException && _ftpc.ClientCertificates.Count <= 0) Connect(); else throw; } } else // SFTP { ConnectionInfo connectionInfo; if (controller.isPrivateKeyValid) connectionInfo = new PrivateKeyConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, new PrivateKeyFile(controller.Account.PrivateKeyFile, controller.Account.Password)); else connectionInfo = new PasswordConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, controller.Account.Password); _sftpc = new SftpClient(connectionInfo); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; // Prompt user to validate ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) Notifications.ChangeTrayText(MessageType.Nothing); if (ConnectionClosed != null) ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException) Log.Write(l.Warning, "Permission denied error occured"); if (e.Exception is Renci.SshNet.Common.SshConnectionException) Reconnect(); }; } controller.HomePath = WorkingDirectory; if (isConnected) if (!string.IsNullOrWhiteSpace(controller.Paths.Remote) && !controller.Paths.Remote.Equals("/")) WorkingDirectory = controller.Paths.Remote; Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) LogServerInfo(); // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public static void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); if (FTP) { _ftpc = new FtpClient(Profile.Host, Profile.Port); _ftpc.ConnectionClosed += (o, e) => { Notifications.ChangeTrayText(MessageType.Nothing); ConnectionClosed(null, new ConnectionClosedEventArgs { Text = _ftpc.LastResponse.Text }); Reconnect(); }; _ftpc.TransferProgress += (o, e) => { // if (e.KilobytesPerSecond > 0) Console.Write("\r Transferring at {0,6} kb/s Transferred: {1}\n", e.KilobytesPerSecond, e.BytesTransferred); }; if (Profile.Protocol == FtpProtocol.FTPS) { _ftpc.ValidateServerCertificate += (sender, x) => { // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(x.Certificate.Thumbprint)) { Log.Write(l.Client, "Trusted: {0}", x.Certificate.Thumbprint); x.IsCertificateValid = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = x.Certificate.Thumbprint, SerialNumber = x.Certificate.SerialNumber, Algorithm = x.Certificate.SignatureAlgorithm.FriendlyName, ValidFrom = x.Certificate.NotBefore.ToString("MM/dd/yy"), ValidTo = x.Certificate.NotAfter.ToString("MM/dd/yy"), Issuer = x.Certificate.IssuerName.Name }; ValidateCertificate(null, e); x.IsCertificateValid = e.IsTrusted; }; // Change Security Protocol if (Profile.FtpsInvokeMethod == FtpsMethod.Explicit) _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Explicit; else if (Profile.FtpsInvokeMethod == FtpsMethod.Implicit) _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Implicit; } try { _ftpc.Open(Profile.Username, Profile.Password); _ftpc.CharacterEncoding = Encoding.Default; } catch (Exception) { if (Profile.FtpsInvokeMethod == FtpsMethod.None) throw; bool connected = false; // Try connecting with the other available Security Protocols foreach (FtpSecurityProtocol p in Enum.GetValues(typeof(FtpSecurityProtocol))) { if ((Profile.FtpsInvokeMethod == FtpsMethod.Explicit && p.ToString().Contains("Explicit")) || (Profile.FtpsInvokeMethod == FtpsMethod.Implicit && p.ToString().Contains("Implicit"))) { Log.Write(l.Debug, "Testing with {0}", p.ToString()); try { _ftpc.Close(); _ftpc.SecurityProtocol = p; _ftpc.Open(Profile.Username, Profile.Password); } catch (Exception exe){ Log.Write(l.Warning, "Unable to connect: {0}", exe.GetType().ToString()); continue; } connected = true; Profile.SecurityProtocol = p; _ftpc.CharacterEncoding = Encoding.Default; break; } } if (!connected) { Notifications.ChangeTrayText(MessageType.Nothing); throw; } } } else // SFTP { _sftpc = new SftpClient(Profile.Host, Profile.Port, Profile.Username, Profile.Password); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) Notifications.ChangeTrayText(MessageType.Nothing); ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException) Log.Write(l.Warning, "Permission denied error occured"); if (e.Exception is Renci.SshNet.Common.SshConnectionException) Reconnect(); }; } Profile.HomePath = WorkingDirectory; // Profile.HomePath = (Profile.HomePath.StartsWith("/")) ? Profile.HomePath.Substring(1) : Profile.HomePath; if (isConnected) if (!string.IsNullOrWhiteSpace(Profile.RemotePath) && !Profile.RemotePath.Equals("/")) WorkingDirectory = Profile.RemotePath; Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Profile.IsDebugMode) LogServerInfo(); }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public override void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); lock (ftpcLock) { ConnectionInfo connectionInfo; if (_controller.IsPrivateKeyValid) { connectionInfo = new PrivateKeyConnectionInfo(_controller.Account.Host, _controller.Account.Port, _controller.Account.Username, new PrivateKeyFile(_controller.Account.PrivateKeyFile, _controller.Account.Password)); } else { connectionInfo = new PasswordConnectionInfo(_controller.Account.Host, _controller.Account.Port, _controller.Account.Username, _controller.Account.Password); } _sftpc = new SftpClient(connectionInfo); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; // Prompt user to validate ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) { Notifications.ChangeTrayText(MessageType.Nothing); } if (ConnectionClosed != null) { ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); } if (e.Exception is SftpPermissionDeniedException) { Log.Write(l.Warning, "Permission denied error occured"); } if (e.Exception is SshConnectionException) { Reconnect(); } }; } _controller.HomePath = WorkingDirectory; if (isConnected) { if (!string.IsNullOrWhiteSpace(_controller.Paths.Remote) && !_controller.Paths.Remote.Equals("/")) { WorkingDirectory = _controller.Paths.Remote; } if (connectionState == null) { connectionState = new BackgroundWorker(); connectionState.DoWork += new DoWorkEventHandler((o, e) => { while (true) { if (!isConnected) { // RECONNECT //_controller.Client.Reconnect(); } Thread.Sleep(5000); } }); connectionState.RunWorkerAsync(); } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); if (FTP) { _ftpc = new FtpClient(controller.Account.Host, controller.Account.Port); _ftpc.ConnectionClosed += (o, e) => { Notifications.ChangeTrayText(MessageType.Nothing); if (ConnectionClosed != null) { ConnectionClosed(null, new ConnectionClosedEventArgs { Text = _ftpc.LastResponse.Text }); } Reconnect(); }; if (controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.ValidateServerCertificate += (sender, x) => { // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(x.Certificate.Thumbprint)) { Log.Write(l.Client, "Trusted: {0}", x.Certificate.Thumbprint); x.IsCertificateValid = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = x.Certificate.Thumbprint, SerialNumber = x.Certificate.SerialNumber, Algorithm = x.Certificate.SignatureAlgorithm.FriendlyName, ValidFrom = x.Certificate.NotBefore.ToString("MM/dd/yy"), ValidTo = x.Certificate.NotAfter.ToString("MM/dd/yy"), Issuer = x.Certificate.IssuerName.Name }; ValidateCertificate(null, e); x.IsCertificateValid = e.IsTrusted; }; // Change Security Protocol if (controller.Account.FtpsMethod == FtpsMethod.Explicit) { _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Explicit; } else if (controller.Account.FtpsMethod == FtpsMethod.Implicit) { _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Implicit; } } try { _ftpc.Open(controller.Account.Username, controller.Account.Password); } catch (Exception) { if (controller.Account.FtpsMethod == FtpsMethod.None) { throw; } bool connected = false; // Try connecting with the other available Security Protocols foreach (FtpSecurityProtocol p in Enum.GetValues(typeof(FtpSecurityProtocol))) { if ((controller.Account.FtpsMethod == FtpsMethod.Explicit && p.ToString().Contains("Explicit")) || (controller.Account.FtpsMethod == FtpsMethod.Implicit && p.ToString().Contains("Implicit"))) { Log.Write(l.Debug, "Testing with {0}", p.ToString()); try { _ftpc.Close(); _ftpc.SecurityProtocol = p; _ftpc.Open(controller.Account.Username, controller.Account.Password); } catch (Exception exe) { Log.Write(l.Warning, "Unable to connect: {0}", exe.GetType().ToString()); continue; } connected = true; controller.Account.FtpSecurityProtocol = p; break; } } if (!connected) { Notifications.ChangeTrayText(MessageType.Nothing); throw; } } } else // SFTP { ConnectionInfo connectionInfo; if (controller.isPrivateKeyValid) { connectionInfo = new PrivateKeyConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, new PrivateKeyFile(controller.Account.PrivateKeyFile, controller.Account.Password)); } else { connectionInfo = new PasswordConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, controller.Account.Password); } _sftpc = new SftpClient(connectionInfo); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) { Notifications.ChangeTrayText(MessageType.Nothing); } if (ConnectionClosed != null) { ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); } if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException) { Log.Write(l.Warning, "Permission denied error occured"); } if (e.Exception is Renci.SshNet.Common.SshConnectionException) { Reconnect(); } }; } controller.HomePath = WorkingDirectory; if (isConnected) { if (!string.IsNullOrWhiteSpace(controller.Paths.Remote) && !controller.Paths.Remote.Equals("/")) { WorkingDirectory = controller.Paths.Remote; } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } }
public override async Task Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); _ftpc = new System.Net.FtpClient.FtpClient { Host = Controller.Account.Host, Port = Controller.Account.Port }; // Add accepted certificates _ftpc.ClientCertificates.AddRange(_certificates); if (Controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.SslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12; _ftpc.ValidateCertificate += (sender, x) => { var certificate = new X509Certificate2(x.Certificate); Log.Write(l.Warning, $"Policy errors: {x.PolicyErrors}"); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(certificate.Thumbprint)) { Log.Write(l.Client, "Trusted: {0}", certificate.Thumbprint); x.Accept = true; return; } var e = new ValidateCertificateEventArgs { cert = certificate, Fingerprint = certificate.Thumbprint }; // Prompt user to validate ValidateCertificate?.Invoke(null, e); if (e.IsTrusted) { _certificates.Add(x.Certificate); } x.Accept = e.IsTrusted; }; } // Change Security Protocol _ftpc.EncryptionMode = (FtpEncryptionMode)Controller.Account.FtpsMethod; _ftpc.Credentials = new NetworkCredential(Controller.Account.Username, Controller.Account.Password); try { await _ftpc.ConnectAsync(); } catch (AuthenticationException ex) when(ex.Message.StartsWith("The remote certificate is invalid")) { throw new CertificateDeclinedException(ex.Message, ex); } catch (FtpCommandException ex) { ex.LogException(); throw new AuthenticationException(ex.Message, ex.InnerException); } catch (Exception ex) { ex.LogException(); throw; } _ftpc.Encoding = this.Charset; Controller.HomePath = WorkingDirectory; if (IsConnected) { if (!string.IsNullOrWhiteSpace(Controller.Paths.Remote) && !Controller.Paths.Remote.Equals("/")) { WorkingDirectory = Controller.Paths.Remote; } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); if (FTP) { _ftpc = new FtpClient(controller.Account.Host, controller.Account.Port); _ftpc.ConnectionClosed += (o, e) => { Notifications.ChangeTrayText(MessageType.Nothing); if (ConnectionClosed != null) ConnectionClosed(null, new ConnectionClosedEventArgs { Text = _ftpc.LastResponse.Text }); Reconnect(); }; if (controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.ValidateServerCertificate += (sender, x) => { // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(x.Certificate.Thumbprint)) { Log.Write(l.Client, "Trusted: {0}", x.Certificate.Thumbprint); x.IsCertificateValid = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = x.Certificate.Thumbprint, SerialNumber = x.Certificate.SerialNumber, Algorithm = x.Certificate.SignatureAlgorithm.FriendlyName, ValidFrom = x.Certificate.NotBefore.ToString("MM/dd/yy"), ValidTo = x.Certificate.NotAfter.ToString("MM/dd/yy"), Issuer = x.Certificate.IssuerName.Name }; ValidateCertificate(null, e); x.IsCertificateValid = e.IsTrusted; }; // Change Security Protocol if (controller.Account.FtpsMethod == FtpsMethod.Explicit) _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Explicit; else if (controller.Account.FtpsMethod == FtpsMethod.Implicit) _ftpc.SecurityProtocol = FtpSecurityProtocol.Tls1OrSsl3Implicit; } try { _ftpc.Open(controller.Account.Username, controller.Account.Password); } catch (Exception) { if (controller.Account.FtpsMethod == FtpsMethod.None) throw; bool connected = false; // Try connecting with the other available Security Protocols foreach (FtpSecurityProtocol p in Enum.GetValues(typeof(FtpSecurityProtocol))) { if ((controller.Account.FtpsMethod == FtpsMethod.Explicit && p.ToString().Contains("Explicit")) || (controller.Account.FtpsMethod == FtpsMethod.Implicit && p.ToString().Contains("Implicit"))) { Log.Write(l.Debug, "Testing with {0}", p.ToString()); try { _ftpc.Close(); _ftpc.SecurityProtocol = p; _ftpc.Open(controller.Account.Username, controller.Account.Password); } catch (Exception exe){ Log.Write(l.Warning, "Unable to connect: {0}", exe.GetType().ToString()); continue; } connected = true; controller.Account.FtpSecurityProtocol = p; break; } } if (!connected) { Notifications.ChangeTrayText(MessageType.Nothing); throw; } } } else // SFTP { ConnectionInfo connectionInfo; if (controller.isPrivateKeyValid) connectionInfo = new PrivateKeyConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, new PrivateKeyFile(controller.Account.PrivateKeyFile, controller.Account.Password)); else connectionInfo = new PasswordConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, controller.Account.Password); _sftpc = new SftpClient(connectionInfo); _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; ValidateCertificate(null, e); x.CanTrust = e.IsTrusted; }; _sftpc.Connect(); _sftpc.ErrorOccurred += (o, e) => { if (!isConnected) Notifications.ChangeTrayText(MessageType.Nothing); if (ConnectionClosed != null) ConnectionClosed(null, new ConnectionClosedEventArgs { Text = e.Exception.Message }); if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException) Log.Write(l.Warning, "Permission denied error occured"); if (e.Exception is Renci.SshNet.Common.SshConnectionException) Reconnect(); }; } controller.HomePath = WorkingDirectory; if (isConnected) if (!string.IsNullOrWhiteSpace(controller.Paths.Remote) && !controller.Paths.Remote.Equals("/")) WorkingDirectory = controller.Paths.Remote; Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) LogServerInfo(); // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }
public override async Task Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); ConnectionInfo connectionInfo; if (Controller.IsPrivateKeyValid) { connectionInfo = new PrivateKeyConnectionInfo(Controller.Account.Host, Controller.Account.Port, Controller.Account.Username, new PrivateKeyFile(Controller.Account.PrivateKeyFile, Controller.Account.Password)); } else { connectionInfo = new PasswordConnectionInfo(Controller.Account.Host, Controller.Account.Port, Controller.Account.Username, Controller.Account.Password); } connectionInfo.Encoding = this.Charset; connectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage); _sftpc = new Renci.SshNet.SftpClient(connectionInfo); _sftpc.HostKeyReceived += (o, x) => { var fingerPrint = x.FingerPrint.GetCertificateData(); // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.CanTrust = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, Key = x.HostKeyName, KeySize = x.KeyLength.ToString() }; // Prompt user to validate ValidateCertificate?.Invoke(null, e); x.CanTrust = e.IsTrusted; }; var caughtException = default(Exception); await Task.Run(() => { try { _sftpc.Connect(); } catch (SshAuthenticationException ex) { ex.LogException(); caughtException = new AuthenticationException(ex.Message, ex.InnerException); } catch (SshConnectionException ex) { ex.LogException(); caughtException = new CertificateDeclinedException(ex.Message, ex.InnerException); } catch (Exception ex) { ex.LogException(); caughtException = ex; } }); if (caughtException != default(Exception)) { throw caughtException; } _sftpc.ErrorOccurred += async(o, e) => { if (!IsConnected) { Notifications.ChangeTrayText(MessageType.Nothing); } OnConnectionClosed(new ConnectionClosedEventArgs { Text = e.Exception.Message }); if (e.Exception is SftpPermissionDeniedException) { Log.Write(l.Warning, "Permission denied error occured"); } if (e.Exception is SshConnectionException) { await Reconnect(); } }; Controller.HomePath = WorkingDirectory; if (IsConnected) { if (!string.IsNullOrWhiteSpace(Controller.Paths.Remote) && !Controller.Paths.Remote.Equals("/")) { WorkingDirectory = Controller.Paths.Remote; } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } }
/// <summary> /// Connect to the remote servers, with the details from Profile /// </summary> /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param> public override void Connect(bool reconnecting = false) { Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting); Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting"); lock (ftpcLock) { _ftpc = new FtpClient { Host = _controller.Account.Host, Port = _controller.Account.Port }; // Add accepted certificates _ftpc.ClientCertificates.AddRange(_certificates); if (_controller.Account.Protocol == FtpProtocol.FTPS) { _ftpc.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; _ftpc.ValidateCertificate += (sender, x) => { var fingerPrint = new X509Certificate2(x.Certificate).Thumbprint; if (_ftpc.ClientCertificates.Count <= 0 && x.PolicyErrors != SslPolicyErrors.None) { _certificates.Add(x.Certificate); x.Accept = false; return; } // if ValidateCertificate handler isn't set, accept the certificate and move on if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint)) { Log.Write(l.Client, "Trusted: {0}", fingerPrint); x.Accept = true; return; } var e = new ValidateCertificateEventArgs { Fingerprint = fingerPrint, SerialNumber = x.Certificate.GetSerialNumberString(), Algorithm = x.Certificate.GetKeyAlgorithmParametersString(), ValidFrom = x.Certificate.GetEffectiveDateString(), ValidTo = x.Certificate.GetExpirationDateString(), Issuer = x.Certificate.Issuer }; // Prompt user to validate ValidateCertificate(null, e); x.Accept = e.IsTrusted; }; // Change Security Protocol if (_controller.Account.FtpsMethod == FtpsMethod.Explicit) { _ftpc.EncryptionMode = FtpEncryptionMode.Explicit; } else if (_controller.Account.FtpsMethod == FtpsMethod.Implicit) { _ftpc.EncryptionMode = FtpEncryptionMode.Implicit; } } _ftpc.Credentials = new NetworkCredential(_controller.Account.Username, _controller.Account.Password); } try { lock (ftpcLock) { _ftpc.Connect(); } } catch (Exception exc) { // Since the ClientCertificates are added when accepted in ValidateCertificate, the first // attempt to connect will fail with an AuthenticationException. If this is the case, a // re-connect is attempted, this time with the certificates properly set. // This is a workaround to avoid storing Certificate files locally... if (exc is AuthenticationException && _ftpc.ClientCertificates.Count <= 0) { Connect(); } else { throw; } } _controller.HomePath = WorkingDirectory; if (isConnected) { if (!string.IsNullOrWhiteSpace(_controller.Paths.Remote) && !_controller.Paths.Remote.Equals("/")) { WorkingDirectory = _controller.Paths.Remote; } } Log.Write(l.Debug, "Client connected sucessfully"); Notifications.ChangeTrayText(MessageType.Ready); if (Settings.IsDebugMode) { LogServerInfo(); } // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set SetKeepAlive(); }