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